Merge branch 'features/application-settings' of github.com:strapi/strapi into front/application-settings

This commit is contained in:
soupette 2020-10-14 15:56:40 +02:00
commit 069f1d9700
76 changed files with 984 additions and 175 deletions

View File

@ -118,4 +118,4 @@
"git add"
]
}
}
}

View File

@ -33,6 +33,7 @@ import { merge } from 'lodash';
import Fonts from './components/Fonts';
import { freezeApp, pluginLoaded, unfreezeApp, updatePlugin } from './containers/App/actions';
import { showNotification } from './containers/NotificationProvider/actions';
import { showNotification as showNewNotification } from './containers/NewNotification/actions';
import basename from './utils/basename';
import getInjectors from './utils/reducerInjectors';
@ -121,8 +122,15 @@ const remoteURL = (() => {
})();
const displayNotification = (message, status) => {
console.warn(
// Validate the text
'Deprecated: Will be deleted.\nPlease use strapi.notification.toggle(config).\nDocs : https://strapi.io/documentation/v3.x/plugin-development/frontend-development.html#strapi-notification'
);
dispatch(showNotification(message, status));
};
const displayNewNotification = config => {
dispatch(showNewNotification(config));
};
const lockApp = data => {
dispatch(freezeApp(data));
};
@ -145,6 +153,10 @@ window.strapi = Object.assign(window.strapi || {}, {
remoteURL,
backendURL: BACKEND_URL === '/' ? window.location.origin : BACKEND_URL,
notification: {
// New notification api
toggle: config => {
displayNewNotification(config);
},
success: message => {
displayNotification(message, 'success');
},

View File

@ -113,8 +113,8 @@ const GlobalStyle = createGlobalStyle`
*/
.notification-enter {
opacity: 0.01;
top: -60px;
opacity: 0;
top: -70px;
}
.notification-enter.notification-enter-active {
@ -128,7 +128,7 @@ const GlobalStyle = createGlobalStyle`
}
.notification-exit.notification-exit-active {
opacity: 0.01;
opacity: 0;
transition: all 400ms ease-in;
}

View File

@ -14,7 +14,7 @@ import Wrapper from './Wrapper';
const MagicLink = ({ registrationToken }) => {
const { formatMessage } = useIntl();
const handleCopy = () => {
strapi.notification.info('notification.link-copied');
strapi.notification.toggle({ type: 'info', message: { id: 'notification.link-copied' } });
};
const link = `${window.location.origin}${basename}auth/register?registrationToken=${registrationToken}`;

View File

@ -61,7 +61,7 @@ const ModalCreateBody = forwardRef(
} catch (err) {
const message = get(err, ['response', 'payload', 'message'], 'An error occured');
strapi.notification.error(message);
strapi.notification.toggle({ type: 'warning', message });
} finally {
strapi.unlockApp();
setIsSubmiting(false);

View File

@ -10,3 +10,4 @@
export const LOGIN_LOGO = null;
export const SHOW_TUTORIALS = true;
export const SETTINGS_BASE_URL = '/settings';
export const STRAPI_UPDATE_NOTIF = true;

View File

@ -27,6 +27,7 @@ import PrivateRoute from '../PrivateRoute';
import Theme from '../Theme';
import { Content, Wrapper } from './components';
import { getDataSucceeded } from './actions';
import NewNotification from '../NewNotification';
function App(props) {
const getDataRef = useRef();
@ -84,7 +85,10 @@ function App(props) {
getDataRef.current(data);
setState({ isLoading: false, hasAdmin: data.hasAdmin });
} catch (err) {
strapi.notification.error('app.containers.App.notification.error.init');
strapi.notification.toggle({
type: 'warning',
message: { id: 'app.containers.App.notification.error.init' },
});
}
};
@ -100,6 +104,7 @@ function App(props) {
<Wrapper>
<GlobalStyle />
<NotificationProvider />
<NewNotification />
<Content>
<Switch>
<Route

View File

@ -60,14 +60,19 @@ const AuthPage = ({ hasAdmin }) => {
`${strapi.backendURL}/admin/registration-info?registrationToken=${registrationToken}`
);
dispatch({
type: 'SET_DATA',
data: { registrationToken, userInfo: data },
});
if (data) {
dispatch({
type: 'SET_DATA',
data: { registrationToken, userInfo: data },
});
}
} catch (err) {
const errorMessage = get(err, ['response', 'data', 'message'], 'An error occured');
strapi.notification.error(errorMessage);
strapi.notification.toggle({
type: 'warning',
message: errorMessage,
});
// Redirect to the oops page in case of an invalid token
// @alexandrebodin @JAB I am not sure it is the wanted behavior
@ -138,7 +143,10 @@ const AuthPage = ({ hasAdmin }) => {
} catch (err) {
console.error(err);
strapi.notification.error('notification.error');
strapi.notification.toggle({
type: 'warning',
message: { id: 'notification.error' },
});
}
};

View File

@ -4,12 +4,16 @@
*
*/
/* eslint-disable */
import React, { memo, useMemo } from 'react';
import React, { memo, useMemo, useEffect } from 'react';
import { FormattedMessage } from 'react-intl';
import { get, upperFirst } from 'lodash';
import { get, isNil, upperFirst } from 'lodash';
import { auth, LoadingIndicatorPage } from 'strapi-helper-plugin';
import axios from 'axios';
import { useSelector } from 'react-redux';
import PageTitle from '../../components/PageTitle';
import { useModels } from '../../hooks';
import { STRAPI_UPDATE_NOTIF } from '../../config';
import useFetch from './hooks';
import { ALink, Block, Container, LinkWrapper, P, Wave, Separator } from './components';
@ -61,7 +65,54 @@ const SOCIAL_LINKS = [
},
];
const HomePage = ({ global: { plugins }, history: { push } }) => {
const HomePage = ({ global: { strapiVersion }, history: { push } }) => {
const notifications = useSelector(state => state.get('newNotification').notifications);
useEffect(() => {
const getStrapiLatestRelease = async () => {
try {
const notificationAlreadyExist =
notifications.findIndex(notification => notification.uid === 'STRAPI_UPDATE_NOTIF') != -1;
const showUpdateNotif =
STRAPI_UPDATE_NOTIF &&
!JSON.parse(localStorage.getItem('STRAPI_UPDATE_NOTIF')) &&
!notificationAlreadyExist;
if (showUpdateNotif) {
const res = await fetch('https://api.github.com/repos/strapi/strapi/releases/latest');
const data = await res.json();
if (strapiVersion !== data.name.split('v').join('')) {
strapi.notification.toggle({
type: 'info',
message: { id: 'notification.version.update.message' },
link: {
url: `https://github.com/strapi/strapi/releases/tag/${data.name}`,
label: {
id: 'notification.version.update.link',
},
},
blockTransition: true,
// Used to check if the notification is already displayed
// to avoid multiple notifications each time the user goes back to the home page.
uid: 'STRAPI_UPDATE_NOTIF',
onClose: () => localStorage.setItem('STRAPI_UPDATE_NOTIF', true),
});
}
}
} catch (e) {
strapi.notification.toggle({
type: 'warning',
message: { id: 'notification.error' },
});
}
};
getStrapiLatestRelease();
}, []);
const { error, isLoading, posts } = useFetch();
// Temporary until we develop the menu API
const { collectionTypes, singleTypes, isLoading: isLoadingForModels } = useModels();

View File

@ -28,7 +28,10 @@ const InstalledPluginsPage = () => {
}
} catch (err) {
strapi.unlockApp();
strapi.notification.error('app.components.listPluginsPage.deletePlugin.error');
strapi.notification.toggle({
type: 'warning',
message: { id: 'app.components.listPluginsPage.deletePlugin.error' },
});
}
};

View File

@ -106,7 +106,10 @@ const LeftMenu = forwardRef(({ version, plugins }, ref) => {
});
} catch (err) {
console.error(err);
strapi.notification.error('notification.error');
strapi.notification.toggle({
type: 'warning',
message: { id: 'notification.error' },
});
}
};

View File

@ -43,7 +43,10 @@ const MarketPlacePage = () => {
}
} catch (err) {
strapi.unlockApp();
strapi.notification.error('notification.error');
strapi.notification.toggle({
type: 'warning',
message: { id: 'notification.error' },
});
}
};

View File

@ -0,0 +1,163 @@
import React, { useEffect, useCallback } from 'react';
import PropTypes from 'prop-types';
import { Padded, Text, Flex } from '@buffetjs/core';
import { useIntl } from 'react-intl';
import { useDispatch } from 'react-redux';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Remove } from '@buffetjs/icons';
import { HIDE_NEW_NOTIFICATION } from '../constants';
import { NotificationWrapper, IconWrapper, LinkArrow, RemoveWrapper } from './styledComponents';
const types = {
success: {
icon: 'check',
color: 'green',
},
warning: {
icon: 'exclamation',
color: 'orange',
},
info: {
icon: 'info',
color: 'blue',
},
};
const Notification = ({ notification }) => {
const { formatMessage } = useIntl();
const dispatch = useDispatch();
const { title, message, link, type, id, onClose, timeout, blockTransition } = notification;
const formattedMessage = msg => (typeof msg === 'string' ? msg : formatMessage(msg, msg.values));
const handleClose = useCallback(() => {
if (onClose) {
onClose();
}
dispatch({
type: HIDE_NEW_NOTIFICATION,
id,
});
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [id]);
useEffect(() => {
let timeoutToClear;
if (!blockTransition) {
timeoutToClear = setTimeout(() => {
handleClose();
}, timeout || 2500);
}
return () => clearTimeout(timeoutToClear);
}, [blockTransition, handleClose, timeout]);
return (
<NotificationWrapper color={types[type].color}>
<Padded top left right bottom size="smd">
<Flex alignItems="center" justifyContent="space-between">
<IconWrapper>
<FontAwesomeIcon icon={types[type].icon} />
</IconWrapper>
<Padded left size="sm" style={{ width: '80%', flex: 1 }}>
{title && (
<Text
fontSize="xs"
textTransform="uppercase"
color="grey"
title={formattedMessage(title)}
>
{formattedMessage(title)}
</Text>
)}
<Flex>
{message && (
<Text title={formattedMessage(message)} ellipsis>
{formattedMessage(message)}
</Text>
)}
{link && (
<a href={link.url} target="_blank" rel="noopener noreferrer">
<Padded left size="xs">
<Flex alignItems="center">
<Text
style={{ maxWidth: '120px' }}
ellipsis
fontWeight="bold"
color="blue"
title={formattedMessage(link.label)}
>
{formattedMessage(link.label)}
</Text>
<Padded left size="xs" />
<LinkArrow />
</Flex>
</Padded>
</a>
)}
</Flex>
</Padded>
<RemoveWrapper>
<Remove onClick={handleClose} />
</RemoveWrapper>
</Flex>
</Padded>
</NotificationWrapper>
);
};
Notification.defaultProps = {
notification: {
id: 1,
type: 'success',
message: {
id: 'notification.success.saved',
defaultMessage: 'Saved',
},
onClose: () => null,
timeout: 2500,
blockTransition: false,
},
};
Notification.propTypes = {
notification: PropTypes.shape({
id: PropTypes.number,
message: PropTypes.oneOfType([
PropTypes.string,
PropTypes.shape({
id: PropTypes.string.isRequired,
defaultMessage: PropTypes.string,
values: PropTypes.object,
}),
]),
title: PropTypes.oneOfType([
PropTypes.string,
PropTypes.shape({
id: PropTypes.string.isRequired,
defaultMessage: PropTypes.string,
values: PropTypes.object,
}),
]),
link: PropTypes.shape({
url: PropTypes.string.isRequired,
label: PropTypes.oneOfType([
PropTypes.string,
PropTypes.shape({
id: PropTypes.string.isRequired,
defaultMessage: PropTypes.string,
values: PropTypes.object,
}),
]).isRequired,
}),
type: PropTypes.string,
onClose: PropTypes.func,
timeout: PropTypes.number,
blockTransition: PropTypes.bool,
}),
};
export default Notification;

View File

@ -0,0 +1,64 @@
import styled from 'styled-components';
import { Arrow } from '@buffetjs/icons';
const NotificationWrapper = styled.div`
position: relative;
border-top-right-radius: ${({ theme }) => theme.main.sizes.borderRadius};
border-bottom-right-radius: ${({ theme }) => theme.main.sizes.borderRadius};
margin-bottom: ${({ theme }) => theme.main.sizes.paddings.sm};
box-shadow: 0 2px 4px 0 ${({ theme }) => theme.main.colors.darkGrey};
background-color: ${props => props.theme.main.colors.white};
border-left: 2px solid ${({ theme, color }) => theme.main.colors[color]};
overflow: hidden;
z-index: 10;
color: ${({ color, theme }) => theme.main.colors[color]};
transition: all 0.15s ease;
width: 400px;
min-height: 60px;
&:hover {
box-shadow: 0 1px 5px 0 rgba(0, 0, 0, 0.2);
}
`;
const IconWrapper = styled.div`
border: 1px solid;
padding: 5px;
border-radius: 50%;
width: 20px;
height: 20px;
display: flex;
align-items: center;
justify-content: center;
font-size: 10px;
`;
const LinkArrow = styled(Arrow)`
transform: rotate(45deg);
margin-top: 4px;
color: ${({ theme }) => theme.main.colors.blue};
`;
const RemoveWrapper = styled.div`
position: relative;
display: flex;
width: 20px;
cursor: pointer;
opacity: 0.6;
font-size: 1.4rem;
color: #bbc2bf;
transition: opacity 0.1s ease;
-webkit-font-smoothing: antialiased;
&:hover {
opacity: 1;
}
svg {
margin: auto;
font-size: 1.3rem;
font-weight: 100 !important;
}
`;
export { NotificationWrapper, IconWrapper, LinkArrow, RemoveWrapper };

View File

@ -0,0 +1,16 @@
import styled from 'styled-components';
import { TransitionGroup } from 'react-transition-group';
const Wrapper = styled(TransitionGroup)`
position: fixed;
top: 72px;
left: 240px;
right: 0;
z-index: 1100;
list-style: none;
width: 400px;
margin: 0 auto;
overflow-y: hidden;
`;
export default Wrapper;

View File

@ -0,0 +1,9 @@
/* eslint-disable import/prefer-default-export */
import { SHOW_NEW_NOTIFICATION } from './constants';
export function showNotification(config) {
return {
type: SHOW_NEW_NOTIFICATION,
config,
};
}

View File

@ -0,0 +1,2 @@
export const SHOW_NEW_NOTIFICATION = 'SHOW_NEW_NOTIFICATION';
export const HIDE_NEW_NOTIFICATION = 'HIDE_NEW_NOTIFICATION';

View File

@ -0,0 +1,35 @@
/**
*
* NotificationsContainer
*
*/
import React, { memo } from 'react';
import { useSelector } from 'react-redux';
import { CSSTransition } from 'react-transition-group';
import Notification from './Notification';
import NotificationsWrapper from './Wrapper';
const NotificationsContainer = () => {
const notifications = useSelector(state => state.get('newNotification').notifications);
return (
<NotificationsWrapper>
{notifications.map(notification => (
<CSSTransition
key={notification.id}
classNames="notification"
timeout={{
enter: 500,
exit: 300,
}}
>
<Notification notification={notification} />
</CSSTransition>
))}
</NotificationsWrapper>
);
};
export default memo(NotificationsContainer);

View File

@ -0,0 +1,48 @@
import produce from 'immer';
import { get } from 'lodash';
import { SHOW_NEW_NOTIFICATION, HIDE_NEW_NOTIFICATION } from './constants';
const initialState = {
notifId: 0,
notifications: [],
};
const notificationReducer = (state = initialState, action) =>
// eslint-disable-next-line consistent-return
produce(state, draftState => {
switch (action.type) {
case SHOW_NEW_NOTIFICATION: {
draftState.notifications.push({
// No action.config spread to limit the notification API and avoid customization
id: state.notifId,
type: get(action, ['config', 'type'], 'success'),
message: get(action, ['config', 'message'], {
id: 'notification.success.saved',
defaultMessage: 'Saved',
}),
title: get(action, ['config', 'title'], null),
link: get(action, ['config', 'link'], null),
timeout: get(action, ['config', 'timeout'], 2500),
blockTransition: get(action, ['config', 'blockTransition'], false),
uid: get(action, ['config', 'uid'], null),
onClose: get(action, ['config', 'onClose'], null),
});
draftState.notifId = state.notifId + 1;
break;
}
case HIDE_NEW_NOTIFICATION: {
const indexToRemove = state.notifications.findIndex(notif => notif.id === action.id);
if (indexToRemove !== -1) {
draftState.notifications.splice(indexToRemove, 1);
}
break;
}
default: {
return draftState;
}
}
});
export default notificationReducer;

View File

@ -0,0 +1,82 @@
import reducer from '../reducer';
import { SHOW_NEW_NOTIFICATION, HIDE_NEW_NOTIFICATION } from '../constants';
describe('AMDIN | CONTAINERS | NEWNOTIFICATION | reducer', () => {
describe('DEFAULT_ACTION', () => {
it('should return the initialState', () => {
const state = {
test: true,
};
expect(reducer(state, {})).toEqual(state);
});
});
describe('SHOW_NEW_NOTIFICATION', () => {
it('should add a notification', () => {
const action = {
type: SHOW_NEW_NOTIFICATION,
config: {
type: 'success',
message: {
id: 'notification.message',
},
},
};
const initialState = {
notifications: [],
notifId: 0,
};
const expected = {
notifications: [
{
id: 0,
type: 'success',
message: { id: 'notification.message' },
title: null,
link: null,
timeout: 2500,
blockTransition: false,
uid: null,
onClose: null,
},
],
notifId: 1,
};
expect(reducer(initialState, action)).toEqual(expected);
});
});
describe('HIDE_NEW_NOTIFICATION', () => {
it('should remove a notification if the notification exist', () => {
const action = {
type: HIDE_NEW_NOTIFICATION,
id: 1,
};
const initialState = {
notifications: [{ id: 1, message: { id: 'notification.message' }, type: 'success' }],
};
const expected = {
notifications: [],
};
expect(reducer(initialState, action)).toEqual(expected);
});
it('should not remove the notification if the notification does not exist', () => {
const action = {
type: HIDE_NEW_NOTIFICATION,
id: 3,
};
const initialState = {
notifications: [{ id: 1, message: { id: 'notification.message' }, type: 'success' }],
};
const expected = {
notifications: [{ id: 1, message: { id: 'notification.message' }, type: 'success' }],
};
expect(reducer(initialState, action)).toEqual(expected);
});
});
});

View File

@ -5,10 +5,7 @@
*/
import { fromJS } from 'immutable';
import {
SHOW_NOTIFICATION,
HIDE_NOTIFICATION,
} from './constants';
import { SHOW_NOTIFICATION, HIDE_NOTIFICATION } from './constants';
const initialState = fromJS({
notifications: [],
@ -20,11 +17,14 @@ function notificationProviderReducer(state = initialState, action) {
switch (action.type) {
case SHOW_NOTIFICATION:
return state.set('notifications', state.get('notifications').push({
message: action.message || 'app.utils.defaultMessage',
status: action.status || 'success',
id: action.id,
}));
return state.set(
'notifications',
state.get('notifications').push({
message: action.message || 'app.utils.defaultMessage',
status: action.status || 'success',
id: action.id,
})
);
case HIDE_NOTIFICATION:
// Check that the index exists
state.get('notifications').forEach((notification, i) => {

View File

@ -106,12 +106,18 @@ const EditPage = () => {
permissionsRef.current.setFormAfterSubmit();
onSubmitSucceeded({ name: data.name, description: data.description });
strapi.notification.success('notification.success.saved');
strapi.notification.toggle({
type: 'success',
message: { id: 'notification.success.saved' },
});
} catch (err) {
console.error(err.response);
const message = get(err, 'response.payload.message', 'An error occured');
strapi.notification.error(message);
strapi.notification.toggle({
type: 'warning',
message,
});
} finally {
setIsSubmiting(false);
strapi.unlockApp();

View File

@ -78,7 +78,10 @@ const ListPage = () => {
});
} catch (err) {
console.error(err.response);
strapi.notification.error('notification.error');
strapi.notification.toggle({
type: 'warning',
message: { id: 'notification.error' },
});
}
};
@ -182,7 +185,10 @@ const ListPage = () => {
} catch (err) {
const errorMessage = get(err, 'response.payload.data', 'An error occured');
strapi.notification.error(errorMessage);
strapi.notification.toggle({
type: 'warning',
message: errorMessage,
});
}
// Only dispatch the action once

View File

@ -23,7 +23,10 @@ const ProtectedEditPage = () => {
useEffect(() => {
if (!isLoading) {
if (!canRead && !canUpdate) {
strapi.notification.info('notification.permission.not-allowed-read');
strapi.notification.toggle({
type: 'info',
message: { id: 'notification.permission.not-allowed-read' },
});
}
}
}, [isLoading, canRead, canUpdate]);

View File

@ -69,7 +69,10 @@ function EditView() {
dispatch({ type: 'UNSET_LOADER' });
if (err.code !== 20) {
strapi.notification.error('notification.error');
strapi.notification.toggle({
type: 'warning',
message: { id: 'notification.error' },
});
}
}
}
@ -176,7 +179,10 @@ function EditView() {
setErrors(getYupInnerErrors(err));
if (submit) {
strapi.notification.error('notification.form.error.fields');
strapi.notification.toggle({
type: 'warning',
message: { id: 'notification.form.error.fields' },
});
}
}
}
@ -194,11 +200,17 @@ function EditView() {
dispatch({
type: 'SUBMIT_SUCCEEDED',
});
strapi.notification.success('Settings.webhooks.created');
strapi.notification.toggle({
type: 'success',
message: { id: 'Settings.webhooks.created' },
});
replace(`/settings/webhooks/${data.id}`);
} catch (err) {
setIsSubmitting(false);
strapi.notification.error('notification.error');
strapi.notification.toggle({
type: 'warning',
message: { id: 'notification.error' },
});
} finally {
strapi.unlockApp();
}
@ -260,7 +272,10 @@ function EditView() {
} catch (err) {
if (isMounted.current) {
if (err.code !== 20) {
strapi.notification.error('notification.error');
strapi.notification.toggle({
type: 'warning',
message: { id: 'notification.error' },
});
}
dispatch({
type: 'SET_IS_TRIGGERING',
@ -353,10 +368,16 @@ function EditView() {
dispatch({
type: 'SUBMIT_SUCCEEDED',
});
strapi.notification.success('notification.form.success.fields');
strapi.notification.toggle({
type: 'success',
message: { id: 'notification.form.success.fields' },
});
} catch (err) {
setIsSubmitting(false);
strapi.notification.error('notification.error');
strapi.notification.toggle({
type: 'warning',
message: { id: 'notification.error' },
});
} finally {
strapi.unlockApp();
}

View File

@ -137,7 +137,10 @@ function ListView() {
} catch (err) {
if (isMounted.current) {
if (err.code !== 20) {
strapi.notification.error('notification.error');
strapi.notification.toggle({
type: 'warning',
message: { id: 'notification.error' },
});
}
}
}
@ -171,7 +174,10 @@ function ListView() {
});
} catch (err) {
if (err.code !== 20) {
strapi.notification.error('notification.error');
strapi.notification.toggle({
type: 'warning',
message: { id: 'notification.error' },
});
}
}
setShowModal(false);
@ -196,7 +202,10 @@ function ListView() {
} catch (err) {
if (isMounted.current) {
if (err.code !== 20) {
strapi.notification.error('notification.error');
strapi.notification.toggle({
type: 'warning',
message: { id: 'notification.error' },
});
}
}
}
@ -245,7 +254,10 @@ function ListView() {
});
if (err.code !== 20) {
strapi.notification.error('notification.error');
strapi.notification.toggle({
type: 'warning',
message: { id: 'notification.error' },
});
}
}
}

View File

@ -40,7 +40,10 @@ const useFetchRole = id => {
dispatch({
type: 'GET_DATA_ERROR',
});
strapi.notification.error('notification.error');
strapi.notification.toggle({
type: 'warning',
message: { id: 'notification.error' },
});
}
};

View File

@ -31,7 +31,10 @@ const useModels = () => {
dispatch({
type: 'GET_MODELS_ERROR',
});
strapi.notification.error('notification.error');
strapi.notification.toggle({
type: 'warning',
message: { id: 'notification.error' },
});
}
};

View File

@ -35,7 +35,10 @@ const useRolesList = (shouldFetchData = true) => {
});
if (message !== 'Forbidden') {
strapi.notification.error(message);
strapi.notification.toggle({
type: 'warning',
message,
});
}
}
};

View File

@ -23,7 +23,10 @@ const useUsersForm = (endPoint, schema, cbSuccess, fieldsToPick) => {
});
} catch (err) {
console.error(err.response);
strapi.notification.error('notification.error');
strapi.notification.toggle({
type: 'warning',
message: { id: 'notification.error' },
});
}
};
@ -83,14 +86,23 @@ const useUsersForm = (endPoint, schema, cbSuccess, fieldsToPick) => {
data,
});
strapi.notification.success('notification.success.saved');
strapi.notification.toggle({
type: 'success',
message: { id: 'notification.success.saved' },
});
} catch (err) {
const data = get(err, 'response.payload', { data: {} });
if (has(data, 'data') && typeof data.data === 'string') {
strapi.notification.error(data.data);
strapi.notification.toggle({
type: 'warning',
message: data.data,
});
} else {
strapi.notification.error(data.message);
strapi.notification.toggle({
type: 'warning',
message: data.message,
});
}
const apiErrors = formatAPIErrors(data);

View File

@ -8,6 +8,7 @@ import globalReducer from './containers/App/reducer';
import adminReducer from './containers/Admin/reducer';
import languageProviderReducer from './containers/LanguageProvider/reducer';
import notificationProviderReducer from './containers/NotificationProvider/reducer';
import newNotificationReducer from './containers/NewNotification/reducer';
/**
* Creates the main reducer with the dynamically injected ones
@ -18,6 +19,7 @@ export default function createReducer(injectedReducers) {
admin: adminReducer,
language: languageProviderReducer,
notification: notificationProviderReducer,
newNotification: newNotificationReducer,
...injectedReducers,
});
}

View File

@ -337,5 +337,7 @@
"notification.permission.not-allowed-read": "You are not allowed to see this document",
"notification.success.delete": "The item has been deleted",
"notification.success.saved": "Saved",
"notification.version.update.message": "A new version of Strapi is available!",
"notification.version.update.link": "See more",
"request.error.model.unknown": "This model doesn't exist"
}

View File

@ -88,13 +88,19 @@ const CreatePage = () => {
})
.then(res => {
setIsSubmiting(false);
strapi.notification.success('Settings.roles.created');
strapi.notification.toggle({
type: 'success',
message: { id: 'Settings.roles.created' },
});
replace(`${settingsBaseURL}/roles/${res.data.id}`);
})
.catch(err => {
console.error(err);
setIsSubmiting(false);
strapi.notification.error('notification.error');
strapi.notification.toggle({
type: 'warning',
message: { id: 'notification.error' },
});
})
.finally(() => {
strapi.unlockApp();

View File

@ -31,7 +31,10 @@ const RoleRow = ({
e.stopPropagation();
if (role.usersCount) {
strapi.notification.info('Roles.ListPage.notification.delete-not-allowed');
strapi.notification.toggle({
type: 'info',
message: { id: 'Roles.ListPage.notification.delete-not-allowed' },
});
} else {
onRoleRemove(role.id);
}

View File

@ -86,7 +86,10 @@ const RoleListPage = () => {
});
if (selectedRoles.length !== filteredRoles.length) {
strapi.notification.info('Roles.ListPage.notification.delete-all-not-allowed');
strapi.notification.toggle({
type: 'info',
message: { id: 'Roles.ListPage.notification.delete-all-not-allowed' },
});
}
if (filteredRoles.length) {
@ -106,7 +109,10 @@ const RoleListPage = () => {
} catch (err) {
console.error(err);
strapi.notification.error('notification.error');
strapi.notification.toggle({
type: 'warning',
message: { id: 'notification.error' },
});
} finally {
handleToggleModal();
}

View File

@ -84,7 +84,7 @@
"react-router": "^5.0.0",
"react-router-dom": "^5.0.0",
"react-select": "^3.0.8",
"react-transition-group": "^4.3.0",
"react-transition-group": "4.4.1",
"react-virtualized": "^9.21.2",
"reactstrap": "8.4.1",
"redux": "^4.0.1",

View File

@ -26,7 +26,10 @@ const CheckPagePermissions = ({ permissions, children }) => {
if (isMounted.current) {
console.error(err);
strapi.notification.error('notification.error');
strapi.notification.toggle({
type: 'warning',
message: { id: 'notification.error' },
});
setState({ isLoading: false });
}

View File

@ -27,7 +27,10 @@ const CheckPermissions = ({ permissions, children }) => {
} catch (err) {
if (isMounted.current) {
console.error(err);
strapi.notification.error('notification.error');
strapi.notification.toggle({
type: 'warning',
message: { id: 'notification.error' },
});
setState({ isLoading: false });
}

View File

@ -23,10 +23,12 @@ const auth = {
if (localStorage) {
const videos = auth.get('videos');
const onboarding = auth.get('onboarding');
const strapiUpdateNotification = auth.get('STRAPI_UPDATE_NOTIF');
localStorage.clear();
localStorage.setItem('videos', JSON.stringify(videos));
localStorage.setItem('onboarding', onboarding);
localStorage.setItem('STRAPI_UPDATE_NOTIF', strapiUpdateNotification);
}
if (sessionStorage) {

View File

@ -169,9 +169,10 @@ const DynamicZone = ({
if (dynamicDisplayedComponentsLength < max) {
setIsOpen(prev => !prev);
} else {
strapi.notification.info(
`${pluginId}.components.notification.info.maximum-requirement`
);
strapi.notification.toggle({
type: 'info',
message: { id: `${pluginId}.components.notification.info.maximum-requirement` },
});
}
}}
/>

View File

@ -136,9 +136,10 @@ const RepeatableComponent = ({
type: 'ADD_NEW_FIELD',
});
} else if (componentValueLength >= max) {
strapi.notification.info(
`${pluginId}.components.notification.info.maximum-requirement`
);
strapi.notification.toggle({
type: 'info',
message: { id: `${pluginId}.components.notification.info.maximum-requirement` },
});
}
}
}}

View File

@ -1,4 +1,5 @@
import { fromJS } from 'immutable';
import getTrad from '../../utils/getTrad';
const initialState = fromJS({ collapses: [] });
@ -7,7 +8,10 @@ const getMax = arr => {
return -1;
}
return Math.max.apply(Math, arr.toJS().map(o => o._temp__id));
return Math.max.apply(
Math,
arr.toJS().map(o => o._temp__id)
);
};
const reducer = (state, action) => {
@ -23,18 +27,16 @@ const reducer = (state, action) => {
const oldList = list;
const newList = list
.delete(action.dragIndex)
.insert(
action.hoverIndex,
state.getIn(['collapses', action.dragIndex])
);
.insert(action.hoverIndex, state.getIn(['collapses', action.dragIndex]));
// Fix for
// https://github.com/react-dnd/react-dnd/issues/1368
// https://github.com/frontend-collective/react-sortable-tree/issues/490
if (oldList.size !== newList.size) {
strapi.notification.error(
"An error occured while reordering your component's field, please try again"
);
strapi.notification.toggle({
type: 'warning',
message: getTrad('components.repeatable.reorder.error'),
});
return oldList;
}

View File

@ -126,7 +126,10 @@ function SelectWrapper({
setIsLoading(false);
} catch (err) {
if (err.code !== 20) {
strapi.notification.error('notification.error');
strapi.notification.toggle({
type: 'warning',
message: { id: 'notification.error' },
});
}
}
}

View File

@ -128,7 +128,10 @@ const EditSettingsView = ({
});
} catch (err) {
if (err.code !== 20) {
strapi.notification.error('notification.error');
strapi.notification.toggle({
type: 'warning',
message: { id: 'notification.error' },
});
}
}
};
@ -190,7 +193,10 @@ const EditSettingsView = ({
emitEvent('didEditEditSettings');
} catch (err) {
strapi.notification.error('notification.error');
strapi.notification.toggle({
type: 'warning',
message: { id: 'notification.error' },
});
}
};

View File

@ -47,7 +47,10 @@ const DeleteLink = ({
method: 'DELETE',
});
strapi.notification.success(`${pluginId}.success.record.delete`);
strapi.notification.toggle({
type: 'success',
message: { id: `${pluginId}.success.record.delete` },
});
emitEvent('didDeleteEntry', trackerProperty);
@ -62,7 +65,10 @@ const DeleteLink = ({
'response.payload.message',
formatMessage({ id: `${pluginId}.error.record.delete` })
);
strapi.notification.error(errorMessage);
strapi.notification.toggle({
type: 'warning',
message: errorMessage,
});
} finally {
setIsModalConfirmButtonLoading(false);
toggleWarningDelete();

View File

@ -147,13 +147,19 @@ const EditViewDataManagerProvider = ({
useEffect(() => {
if (shouldRedirectToHomepageWhenEditingEntry) {
strapi.notification.info(getTrad('permissions.not-allowed.update'));
strapi.notification.toggle({
type: 'info',
message: { id: getTrad('permissions.not-allowed.update') },
});
}
}, [shouldRedirectToHomepageWhenEditingEntry]);
useEffect(() => {
if (shouldRedirectToHomepageWhenCreatingEntry) {
strapi.notification.info(getTrad('permissions.not-allowed.create'));
strapi.notification.toggle({
type: 'info',
message: { id: getTrad('permissions.not-allowed.create') },
});
}
}, [shouldRedirectToHomepageWhenCreatingEntry]);
@ -186,7 +192,10 @@ const EditViewDataManagerProvider = ({
}
if (id && resStatus === 403) {
strapi.notification.info(getTrad('permissions.not-allowed.update'));
strapi.notification.toggle({
type: 'info',
message: { id: getTrad('permissions.not-allowed.update') },
});
push(from);
@ -194,7 +203,10 @@ const EditViewDataManagerProvider = ({
}
if (id && err.code !== 20) {
strapi.notification.error(`${pluginId}.error.record.fetch`);
strapi.notification.toggle({
type: 'warning',
message: { id: `${pluginId}.error.record.fetch` },
});
}
// Create a single type
@ -206,7 +218,10 @@ const EditViewDataManagerProvider = ({
// Not allowed to update or read a ST
if (!id && resStatus === 403) {
strapi.notification.info(getTrad('permissions.not-allowed.update'));
strapi.notification.toggle({
type: 'info',
message: { id: getTrad('permissions.not-allowed.update') },
});
push(from);
}
@ -453,7 +468,10 @@ const EditViewDataManagerProvider = ({
dispatch({
type: 'SUBMIT_SUCCESS',
});
strapi.notification.success(`${pluginId}.success.record.save`);
strapi.notification.toggle({
type: 'success',
message: { id: `${pluginId}.success.record.save` },
});
setIsCreatingEntry(false);
@ -490,7 +508,10 @@ const EditViewDataManagerProvider = ({
});
}
strapi.notification.error(error);
strapi.notification.toggle({
type: 'warning',
message: { id: `${pluginId}.error.record.fetch` },
});
}
} catch (err) {
console.error({ err });
@ -542,7 +563,10 @@ const EditViewDataManagerProvider = ({
type: 'PUBLISH_SUCCESS',
data,
});
strapi.notification.success(`${pluginId}.success.record.publish`);
strapi.notification.toggle({
type: 'success',
message: { id: `${pluginId}.success.record.publish` },
});
} catch (err) {
// ---------- @Soupette Is this error handling still mandatory? ----------
// The api error send response.payload.message: 'The error message'.
@ -571,7 +595,10 @@ const EditViewDataManagerProvider = ({
}
const errorMessage = get(err, ['response', 'payload', 'message'], 'SERVER ERROR');
strapi.notification.error(errorMessage);
strapi.notification.toggle({
type: 'warning',
message: errorMessage,
});
}
} catch (err) {
console.error({ err });
@ -608,13 +635,19 @@ const EditViewDataManagerProvider = ({
type: 'UNPUBLISH_SUCCESS',
data,
});
strapi.notification.success(`${pluginId}.success.record.unpublish`);
strapi.notification.toggle({
type: 'success',
message: { id: `${pluginId}.success.record.unpublish` },
});
} catch (err) {
console.error({ err });
setStatus('resolved');
const errorMessage = get(err, ['response', 'payload', 'message'], 'SERVER ERROR');
strapi.notification.error(errorMessage);
strapi.notification.toggle({
type: 'warning',
message: errorMessage,
});
}
}, [id, modifiedData, slug]);

View File

@ -58,7 +58,10 @@ const ListSettingsView = ({ deleteLayout, slug }) => {
});
} catch (err) {
if (err.code !== 20) {
strapi.notification.error('notification.error');
strapi.notification.toggle({
type: 'warning',
message: { id: 'notification.error' },
});
}
}
};
@ -143,7 +146,10 @@ const ListSettingsView = ({ deleteLayout, slug }) => {
deleteLayout(slug);
emitEvent('didEditListSettings');
} catch (err) {
strapi.notification.error('notification.error');
strapi.notification.toggle({
type: 'warning',
message: { id: 'notification.error' },
});
}
};
@ -243,7 +249,10 @@ const ListSettingsView = ({ deleteLayout, slug }) => {
e.stopPropagation();
if (displayedFields.length === 1) {
strapi.notification.info(`${pluginId}.notification.info.minimumFields`);
strapi.notification.toggle({
type: 'info',
message: { id: `${pluginId}.notification.info.minimumFields` },
});
} else {
dispatch({
type: 'REMOVE_FIELD',

View File

@ -180,7 +180,10 @@ function ListView({
getDataSucceededRef.current(count, data);
} catch (err) {
strapi.notification.error(`${pluginId}.error.model.fetch`);
strapi.notification.toggle({
type: 'warning',
message: { id: `${pluginId}.error.model.fetch` },
});
}
};
@ -309,7 +312,10 @@ function ListView({
method: 'DELETE',
});
strapi.notification.success(`${pluginId}.success.record.delete`);
strapi.notification.toggle({
type: 'success',
message: { id: `${pluginId}.success.record.delete` },
});
// Close the modal and refetch data
onDeleteDataSucceeded();
@ -321,7 +327,10 @@ function ListView({
formatMessage({ id: `${pluginId}.error.record.delete` })
);
strapi.notification.error(errorMessage);
strapi.notification.toggle({
type: 'warning',
message: errorMessage,
});
// Close the modal
onDeleteDataError();
}
@ -341,7 +350,10 @@ function ListView({
onDeleteSeveralDataSucceeded();
} catch (err) {
strapi.notification.error(`${pluginId}.error.record.delete`);
strapi.notification.toggle({
type: 'warning',
message: { id: `${pluginId}.error.record.delete` },
});
}
}, [entriesToDelete, onDeleteSeveralDataSucceeded, slug, setModalLoadingState]);
@ -350,7 +362,10 @@ function ListView({
// Display a notification if trying to remove the last displayed field
if (value && listLayout.length === 1) {
strapi.notification.error('content-manager.notification.error.displayedFields');
strapi.notification.toggle({
type: 'warning',
message: { id: 'content-manager.notification.error.displayedFields' },
});
return;
}

View File

@ -64,7 +64,10 @@ function Main({
...createPossibleMainFieldsForModelsAndComponents(models),
});
} catch (err) {
strapi.notification.error('notification.error');
strapi.notification.toggle({
type: 'warning',
message: { id: 'notification.error' },
});
}
};
@ -76,7 +79,10 @@ function Main({
getLayoutSucceeded(layout, uid);
} catch (err) {
strapi.notification.error('notification.error');
strapi.notification.toggle({
type: 'warning',
message: { id: 'notification.error' },
});
}
};
resetPropsRef.current = resetProps;

View File

@ -34,6 +34,7 @@
"components.TableEmpty.withSearch": "There is no {contentType} corresponding to the search ({search})...",
"components.TableEmpty.withoutFilter": "There is no {contentType}...",
"components.empty-repeatable": "No entry yet. Click on the button below to add one.",
"components.repeatable.reorder.error": "An error occurred while reordering your component's field, please try again",
"components.notification.info.maximum-requirement": "You have already reached the maximum number of fields",
"components.notification.info.minimum-requirement": "A field has been added to match the minimum requirement",
"components.reset-entry": "Reset entry",

View File

@ -103,7 +103,10 @@ const DataManagerProvider = ({ allIcons, children }) => {
});
} catch (err) {
console.error({ err });
strapi.notification.error('notification.error');
strapi.notification.toggle({
type: 'warning',
message: { id: 'notification.error' },
});
}
};
@ -122,11 +125,10 @@ const DataManagerProvider = ({ allIcons, children }) => {
useEffect(() => {
if (currentEnvironment === 'development' && !autoReload) {
strapi.notification.info(
formatMessageRef.current({
id: getTrad('notification.info.autoreaload-disable'),
})
);
strapi.notification.toggle({
type: 'info',
message: { id: getTrad('notification.info.autoreaload-disable') },
});
}
}, [autoReload, currentEnvironment]);
@ -235,7 +237,10 @@ const DataManagerProvider = ({ allIcons, children }) => {
}
} catch (err) {
console.error({ err });
strapi.notification.error('notification.error');
strapi.notification.toggle({
type: 'warning',
message: { id: 'notification.error' },
});
} finally {
strapi.unlockApp();
}
@ -285,7 +290,10 @@ const DataManagerProvider = ({ allIcons, children }) => {
}
} catch (err) {
console.error({ err });
strapi.notification.error('notification.error');
strapi.notification.toggle({
type: 'warning',
message: { id: 'notification.error' },
});
} finally {
strapi.unlockApp();
}
@ -312,7 +320,10 @@ const DataManagerProvider = ({ allIcons, children }) => {
getDataRef.current();
} catch (err) {
console.error({ err });
strapi.notification.error('notification.error');
strapi.notification.toggle({
type: 'warning',
message: { id: 'notification.error' },
});
} finally {
strapi.unlockApp();
}
@ -464,7 +475,10 @@ const DataManagerProvider = ({ allIcons, children }) => {
}
console.error({ err: err.response });
strapi.notification.error('notification.error');
strapi.notification.toggle({
type: 'warning',
message: { id: 'notification.error' },
});
} finally {
strapi.unlockApp();
}

View File

@ -661,7 +661,10 @@ const FormModal = () => {
push({ search: '' });
submitData(modifiedData);
} else {
strapi.notification.error('notification.contentType.relations.conflict');
strapi.notification.toggle({
type: 'warning',
message: { id: 'notification.contentType.relations.conflict' },
});
}
return;

View File

@ -869,7 +869,10 @@ const forms = {
type: 'booleanBox',
size: 12,
onChangeCallback: () =>
strapi.notification.info(getTrad('contentType.kind.change.warning')),
strapi.notification.toggle({
type: 'info',
message: { id: getTrad('contentType.kind.change.warning') },
}),
options: [
{
headerId: getTrad('menu.section.models.name.singular'),

View File

@ -20,7 +20,10 @@ import Wrapper from './Wrapper';
/* eslint-disable indent */
const displayNotificationCTNotSaved = () => {
strapi.notification.info(`${pluginId}.notification.info.creating.notSaved`);
strapi.notification.toggle({
type: 'info',
message: { id: `${pluginId}.notification.info.creating.notSaved` },
});
};
function LeftMenu({ wait }) {

View File

@ -93,7 +93,10 @@ export class HomePage extends React.Component {
};
handleCopy = () => {
strapi.notification.info(getTrad('containers.HomePage.copied'));
strapi.notification.toggle({
type: 'info',
message: { id: getTrad('containers.HomePage.copied') },
});
};
openCurrentDocumentation = () => {

View File

@ -1,18 +1,10 @@
import { cloneDeep, isArray } from 'lodash';
import { all, takeLatest, put, fork, call, select } from 'redux-saga/effects';
import { request } from 'strapi-helper-plugin';
import {
GET_DOC_INFOS,
ON_CONFIRM_DELETE_DOC,
ON_UPDATE_DOC,
ON_SUBMIT,
} from './constants';
import { GET_DOC_INFOS, ON_CONFIRM_DELETE_DOC, ON_UPDATE_DOC, ON_SUBMIT } from './constants';
import { getDocInfosSucceeded, setFormErrors } from './actions';
import {
makeSelectVersionToDelete,
makeSelectPrefix,
makeSelectForm,
} from './selectors';
import { makeSelectVersionToDelete, makeSelectPrefix, makeSelectForm } from './selectors';
import getTrad from '../../utils/getTrad';
/* eslint-disable consistent-return */
@ -23,7 +15,10 @@ function* getData() {
});
yield put(getDocInfosSucceeded(response));
} catch (err) {
strapi.notification.error('An error occurred');
strapi.notification.toggle({
type: 'warning',
message: { id: 'notification.error' },
});
}
}
@ -36,10 +31,16 @@ function* deleteDoc() {
if (response.ok) {
yield call(getData);
strapi.notification.info('Doc deleted');
strapi.notification.toggle({
type: 'info',
message: { id: getTrad('notification.delete.success') },
});
}
} catch (err) {
strapi.notification.error(err.response.payload.message);
strapi.notification.toggle({
type: 'warning',
message: err.response.payload.message,
});
}
}
@ -71,9 +72,15 @@ function* submit() {
yield call(request, `${prefix}/updateSettings`, { method: 'PUT', body });
yield put(setFormErrors({}));
strapi.notification.success('documentation.notification.update.success');
strapi.notification.toggle({
type: 'success',
message: { id: getTrad('notification.update.success') },
});
} catch (err) {
strapi.notification.error(err.response.payload.message);
strapi.notification.toggle({
type: 'warning',
message: err.response.payload.message,
});
}
}
@ -88,10 +95,16 @@ function* updateDoc(action) {
if (response.ok) {
yield call(getData);
strapi.notification.info('Doc generated');
strapi.notification.toggle({
type: 'info',
message: { id: getTrad('notification.generate.success') },
});
}
} catch (err) {
strapi.notification.error(err.response.payload.message);
strapi.notification.toggle({
type: 'warning',
message: err.response.payload.message,
});
}
}

View File

@ -23,5 +23,7 @@
"error.regenerateDoc": "An error occurred while regenerating the doc",
"error.regenerateDoc.versionMissing": "The version you are trying to generate doesn't exist",
"notification.update.success": "Settings updated successfully",
"notification.delete.success": "Doc deleted",
"notification.generate.success": "Doc generated",
"plugin.name": "Documentation"
}

View File

@ -193,7 +193,10 @@ const EditForm = forwardRef(
};
const handleCopy = () => {
strapi.notification.info('notification.link-copied');
strapi.notification.toggle({
type: 'info',
message: { id: 'notification.link-copied' },
});
};
const handleClickDownload = () => {

View File

@ -94,7 +94,10 @@ const InputMedia = ({ disabled, label, onChange, name, attribute, value, type, i
};
const handleCopy = () => {
strapi.notification.info('notification.link-copied');
strapi.notification.toggle({
type: 'info',
message: { id: 'notification.link-copied' },
});
};
const handleAllowDrop = e => e.preventDefault();

View File

@ -92,7 +92,10 @@ const HomePage = () => {
} catch (err) {
if (isMounted.current) {
dispatch({ type: 'GET_DATA_ERROR' });
strapi.notification.error('notification.error');
strapi.notification.toggle({
type: 'warning',
message: { id: 'notification.error' },
});
}
}
@ -112,7 +115,10 @@ const HomePage = () => {
} catch (err) {
if (isMounted.current) {
dispatch({ type: 'GET_DATA_ERROR' });
strapi.notification.error('notification.error');
strapi.notification.toggle({
type: 'warning',
message: { id: 'notification.error' },
});
}
}
@ -227,7 +233,10 @@ const HomePage = () => {
type: 'ON_DELETE_MEDIAS_SUCCEEDED',
});
} catch (err) {
strapi.notification.error(err);
strapi.notification.toggle({
type: 'warning',
message: err,
});
dispatch({
type: 'ON_DELETE_MEDIAS_ERROR',

View File

@ -24,7 +24,10 @@ const Initializer = ({ updatePlugin }) => {
ref.current(pluginId, 'fileModel', fileModel);
ref.current(pluginId, 'isReady', true);
} catch (err) {
strapi.notification.error('content-manager.error.model.fetch');
strapi.notification.toggle({
type: 'warning',
message: { id: 'content-manager.error.model.fetch' },
});
}
};

View File

@ -210,7 +210,10 @@ const InputModalStepper = ({
['response', 'payload', 'message', '0', 'messages', '0', 'message'],
get(err, ['response', 'payload', 'message'], statusText)
);
strapi.notification.error(errorMessage);
strapi.notification.toggle({
type: 'warning',
message: errorMessage,
});
if (status) {
handleSetFileToEditError(errorMessage);

View File

@ -339,7 +339,10 @@ const InputModalStepperProvider = ({
});
} catch (err) {
console.error(err);
strapi.notification.error('notification.error');
strapi.notification.toggle({
type: 'warning',
message: { id: 'notification.error' },
});
return 0;
}
@ -366,7 +369,10 @@ const InputModalStepperProvider = ({
});
} catch (err) {
console.error(err);
strapi.notification.error('notification.error');
strapi.notification.toggle({
type: 'warning',
message: { id: 'notification.error' },
});
return [];
}

View File

@ -199,7 +199,10 @@ const ModalStepper = ({
} catch (err) {
const errorMessage = get(err, 'response.payload.message', 'An error occured');
strapi.notification.error(errorMessage);
strapi.notification.toggle({
type: 'warning',
message: errorMessage,
});
} finally {
setShowModalConfirmButtonLoading(true);
toggleModalWarning();

View File

@ -58,7 +58,10 @@ const SettingsPage = () => {
});
}
strapi.notification.success('notification.form.success.fields');
strapi.notification.toggle({
type: 'success',
message: { id: 'notification.form.success.fields' },
});
} catch (err) {
console.error(err);
}

View File

@ -54,7 +54,10 @@ const AdvancedSettingsPage = () => {
type: 'GET_DATA_ERROR',
});
console.error(err);
strapi.notification.error('notification.error');
strapi.notification.toggle({
type: 'warning',
message: { id: 'notification.error' },
});
}
}
};
@ -95,13 +98,19 @@ const AdvancedSettingsPage = () => {
type: 'ON_SUBMIT_SUCCEEDED',
});
strapi.notification.success(getTrad('notification.success.submit'));
strapi.notification.toggle({
type: 'success',
message: { id: getTrad('notification.success.submit') },
});
} catch (err) {
dispatch({
type: 'ON_SUBMIT_ERROR',
});
console.error(err);
strapi.notification.error('notification.error');
strapi.notification.toggle({
type: 'warning',
message: { id: 'notification.error' },
});
}
strapi.unlockApp();

View File

@ -111,7 +111,10 @@ const EmailTemplatesPage = () => {
emitEventRef.current('didEditEmailTemplates');
strapi.notification.success(getTrad('notification.success.submit'));
strapi.notification.toggle({
type: 'success',
message: { id: getTrad('notification.success.submit') },
});
dispatchSubmitSucceeded();
@ -119,7 +122,10 @@ const EmailTemplatesPage = () => {
} catch (err) {
console.error(err);
strapi.notification.error('notification.error');
strapi.notification.toggle({
type: 'warning',
message: { id: 'notification.error' },
});
}
} catch (err) {
errors = getYupInnerErrors(err);

View File

@ -150,14 +150,20 @@ const ProvidersPage = () => {
emitEventRef.current('didEditAuthenticationProvider');
strapi.notification.success(getTrad('notification.success.submit'));
strapi.notification.toggle({
type: 'success',
message: { id: getTrad('notification.success.submit') },
});
dispatchSubmitSucceeded();
handleToggle();
} catch (err) {
console.error(err);
strapi.notification.error('notification.error');
strapi.notification.toggle({
type: 'warning',
message: { id: 'notification.error' },
});
}
} catch (err) {
console.error(err);
@ -176,7 +182,7 @@ const ProvidersPage = () => {
formToRender,
handleToggle,
modifiedData,
providerToEditName
providerToEditName,
]
);
@ -235,13 +241,13 @@ const ProvidersPage = () => {
<Row>
{formToRender.form.map(input => {
const label = input.label.params
? { ...input.label, params: { provider: upperFirst(providerToEditName) } }
: input.label;
? { ...input.label, params: { provider: upperFirst(providerToEditName) } }
: input.label;
const value =
input.name === 'noName'
? `${strapi.backendURL}/connect/${providerToEditName}/callback`
: get(modifiedData, [providerToEditName, ...input.name.split('.')], '');
input.name === 'noName'
? `${strapi.backendURL}/connect/${providerToEditName}/callback`
: get(modifiedData, [providerToEditName, ...input.name.split('.')], '');
return (
<SizedInput

View File

@ -68,14 +68,20 @@ const CreatePage = () => {
)
.then(() => {
emitEvent('didCreateRole');
strapi.notification.success('Settings.roles.created');
strapi.notification.toggle({
type: 'success',
message: { id: 'Settings.roles.created' },
});
// Forcing redirecting since we don't have the id in the response
// TODO
goBack();
})
.catch(err => {
console.error(err);
strapi.notification.error('notification.error');
strapi.notification.toggle({
type: 'warning',
message: { id: 'notification.error' },
});
})
.finally(() => {
setIsSubmiting(false);

View File

@ -74,11 +74,17 @@ const EditPage = () => {
.then(() => {
onSubmitSucceeded({ name: data.name, description: data.description });
permissionsRef.current.setFormAfterSubmit();
strapi.notification.success(getTrad('Settings.roles.edited'));
strapi.notification.toggle({
type: 'success',
message: { id: getTrad('Settings.roles.edited') },
});
})
.catch(err => {
console.error(err);
strapi.notification.error('notification.error');
strapi.notification.toggle({
type: 'warning',
message: { id: 'notification.error' },
});
})
.finally(() => {
setIsSubmiting(false);

View File

@ -55,11 +55,17 @@ const RoleListPage = () => {
)
.then(() => {
setShouldRefetchData(true);
strapi.notification.success(getTrad('Settings.roles.deleted'));
strapi.notification.toggle({
type: 'success',
message: { id: getTrad('Settings.roles.deleted') },
});
})
.catch(err => {
console.error(err);
strapi.notification.error('notification.error');
strapi.notification.toggle({
type: 'warning',
message: { id: 'notification.error' },
});
})
.finally(() => {
setModalDelete(null);

View File

@ -35,7 +35,10 @@ const useFetchRole = id => {
dispatch({
type: 'GET_DATA_ERROR',
});
strapi.notification.error('notification.error');
strapi.notification.toggle({
type: 'warning',
message: { id: 'notification.error' },
});
}
};

View File

@ -35,7 +35,10 @@ const useUserForm = (endPoint, permissions) => {
type: 'GET_DATA_ERROR',
});
console.error(err);
strapi.notification.error('notification.error');
strapi.notification.toggle({
type: 'warning',
message: { id: 'notification.error' },
});
}
}
};

View File

@ -47,7 +47,10 @@ const usePlugins = (shouldFetchData = true) => {
});
if (message !== 'Forbidden') {
strapi.notification.error(message);
strapi.notification.toggle({
type: 'warning',
message,
});
}
}
}, [formatMessage]);

View File

@ -47,7 +47,10 @@ const useRolesList = (shouldFetchData = true) => {
});
if (message !== 'Forbidden') {
strapi.notification.error(message);
strapi.notification.toggle({
type: 'warning',
message,
});
}
}
}

View File

@ -15648,6 +15648,16 @@ react-test-renderer@^16.0.0-0, react-test-renderer@^16.9.0:
react-is "^16.8.6"
scheduler "^0.19.1"
react-transition-group@4.4.1, react-transition-group@^4.3.0:
version "4.4.1"
resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.4.1.tgz#63868f9325a38ea5ee9535d828327f85773345c9"
integrity sha512-Djqr7OQ2aPUiYurhPalTrVy9ddmFCCzwhqQmtN+J3+3DzLO209Fdr70QrN8Z3DsglWql6iY1lDWAfpFiBtuKGw==
dependencies:
"@babel/runtime" "^7.5.5"
dom-helpers "^5.0.1"
loose-envify "^1.4.0"
prop-types "^15.6.2"
react-transition-group@^2.3.1:
version "2.9.0"
resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-2.9.0.tgz#df9cdb025796211151a436c69a8f3b97b5b07c8d"
@ -15658,16 +15668,6 @@ react-transition-group@^2.3.1:
prop-types "^15.6.2"
react-lifecycles-compat "^3.0.4"
react-transition-group@^4.3.0:
version "4.4.1"
resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.4.1.tgz#63868f9325a38ea5ee9535d828327f85773345c9"
integrity sha512-Djqr7OQ2aPUiYurhPalTrVy9ddmFCCzwhqQmtN+J3+3DzLO209Fdr70QrN8Z3DsglWql6iY1lDWAfpFiBtuKGw==
dependencies:
"@babel/runtime" "^7.5.5"
dom-helpers "^5.0.1"
loose-envify "^1.4.0"
prop-types "^15.6.2"
react-virtualized@^9.21.2:
version "9.22.2"
resolved "https://registry.yarnpkg.com/react-virtualized/-/react-virtualized-9.22.2.tgz#217a870bad91e5438f46f01a009e1d8ce1060a5a"