diff --git a/package-lock.json b/package-lock.json
index 9d60fba67..5f567586a 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -31,6 +31,7 @@
"mapbox-gl": "^2.15.0",
"notistack": "^3.0.1",
"path-browserify": "^1.0.1",
+ "query-string": "^7.1.3",
"react": "^18.2.0",
"react-avatar-editor": "^13.0.0",
"react-beautiful-dnd": "^13.1.1",
@@ -48,7 +49,7 @@
"slate-history": "^0.93.0",
"slate-hyperscript": "^0.77.0",
"slate-react": "^0.99.0",
- "terraso-client-shared": "github:techmatters/terraso-client-shared#a0e3a5e",
+ "terraso-client-shared": "github:techmatters/terraso-client-shared#5e56086",
"use-debounce": "^9.0.4",
"uuid": "^9.0.0",
"web-vitals": "^3.5.0",
@@ -6758,9 +6759,9 @@
}
},
"node_modules/@reduxjs/toolkit": {
- "version": "1.9.5",
- "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-1.9.5.tgz",
- "integrity": "sha512-Rt97jHmfTeaxL4swLRNPD/zV4OxTes4la07Xc4hetpUW/vc75t5m1ANyxG6ymnEQ2FsLQsoMlYB2vV1sO3m8tQ==",
+ "version": "1.9.7",
+ "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-1.9.7.tgz",
+ "integrity": "sha512-t7v8ZPxhhKgOKtU+uyJT13lu4vL7az5aFi4IdoDs/eS548edn2M8Ik9h8fxgvMjGoAUVFSt6ZC1P5cWmQ014QQ==",
"dependencies": {
"immer": "^9.0.21",
"redux": "^4.2.1",
@@ -11623,6 +11624,14 @@
"integrity": "sha512-F29o+vci4DodHYT9UrR5IEbfBw9pE5eSapIJdTqXK5+6hq+t8VRxwQyKlW2i+KDKFkkJQRvFyI/QXD83h8LyQw==",
"dev": true
},
+ "node_modules/decode-uri-component": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz",
+ "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==",
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
"node_modules/decompress-response": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz",
@@ -14062,6 +14071,14 @@
"node": ">=8"
}
},
+ "node_modules/filter-obj": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-1.1.0.tgz",
+ "integrity": "sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/finalhandler": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz",
@@ -24017,6 +24034,23 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/query-string": {
+ "version": "7.1.3",
+ "resolved": "https://registry.npmjs.org/query-string/-/query-string-7.1.3.tgz",
+ "integrity": "sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg==",
+ "dependencies": {
+ "decode-uri-component": "^0.2.2",
+ "filter-obj": "^1.1.0",
+ "split-on-first": "^1.0.0",
+ "strict-uri-encode": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/querystringify": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz",
@@ -26344,6 +26378,14 @@
"node": ">= 6"
}
},
+ "node_modules/split-on-first": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz",
+ "integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/sponge-case": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/sponge-case/-/sponge-case-1.0.1.tgz",
@@ -26418,6 +26460,14 @@
"node": ">=10.0.0"
}
},
+ "node_modules/strict-uri-encode": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz",
+ "integrity": "sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
"node_modules/string_decoder": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
@@ -27310,20 +27360,19 @@
},
"node_modules/terraso-backend": {
"version": "0.1.0",
- "resolved": "git+ssh://git@github.com/techmatters/terraso-backend.git#8813449c8b2f4eb4b70b4add87007d2a93d25baa",
- "integrity": "sha512-WXumMW1dnbEFfZjmNkRuibIuO7TDeRUQ8vr5K2nyhUs8bDZXUS67zM6TtLx92czO+PvdzI36ncH5abGHg3rpOQ=="
+ "resolved": "git+ssh://git@github.com/techmatters/terraso-backend.git#4929e5f4599cebc2f107873dd0075885c4df5e46"
},
"node_modules/terraso-client-shared": {
"version": "0.1.0",
- "resolved": "git+ssh://git@github.com/techmatters/terraso-client-shared.git#691d4f0928a4b24d1a2a6506a1780a91ce26cc19",
- "integrity": "sha512-lv7XZ0LZ1xx2DsVyj2EdrTKVIFSBOSy8BQdaJVng+5D5FV8IwoBGcxcEVqEOIxvnd8GLwOClUHyhO1ow72792g==",
+ "resolved": "git+ssh://git@github.com/techmatters/terraso-client-shared.git#b86117e3735b2d8b2f85ffdb68547eb9738b9f77",
+ "integrity": "sha512-33236wvHVdvHmd6R0icNzt1PWtVhqZq8nkRguDfhq5bYrH8H3MCKf1umcsJQHJ+Y4csYw6VlFSHKrIzbayIrZw==",
"dependencies": {
- "@reduxjs/toolkit": "^1.9.5",
+ "@reduxjs/toolkit": "^1.9.6",
"jwt-decode": "^3.1.2",
"lodash": "^4.17.21",
"react": "^18.2.0",
"react-redux": "^8.1.2",
- "terraso-backend": "github:techmatters/terraso-backend#8813449c8b2f4eb4b70b4add87007d2a93d25baa",
+ "terraso-backend": "github:techmatters/terraso-backend#4929e5f",
"uuid": "^9.0.0"
}
},
diff --git a/package.json b/package.json
index 13dd64570..6e11bd30e 100644
--- a/package.json
+++ b/package.json
@@ -29,6 +29,7 @@
"mapbox-gl": "^2.15.0",
"notistack": "^3.0.1",
"path-browserify": "^1.0.1",
+ "query-string": "^7.1.3",
"react": "^18.2.0",
"react-avatar-editor": "^13.0.0",
"react-beautiful-dnd": "^13.1.1",
@@ -46,7 +47,7 @@
"slate-history": "^0.93.0",
"slate-hyperscript": "^0.77.0",
"slate-react": "^0.99.0",
- "terraso-client-shared": "github:techmatters/terraso-client-shared#a0e3a5e",
+ "terraso-client-shared": "github:techmatters/terraso-client-shared#5e56086",
"use-debounce": "^9.0.4",
"uuid": "^9.0.0",
"web-vitals": "^3.5.0",
diff --git a/src/account/components/AccountLogin.js b/src/account/components/AccountLogin.js
index e753b601b..55d84f8ae 100644
--- a/src/account/components/AccountLogin.js
+++ b/src/account/components/AccountLogin.js
@@ -14,10 +14,11 @@
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
-import React from 'react';
+import React, { useEffect } from 'react';
+import queryString from 'query-string';
import { Trans, useTranslation } from 'react-i18next';
import { useSelector } from 'react-redux';
-import { useSearchParams } from 'react-router-dom';
+import { useNavigate, useSearchParams } from 'react-router-dom';
import { fetchAuthURLs } from 'terraso-client-shared/account/accountSlice';
import { useFetchData } from 'terraso-client-shared/store/utils';
import AppleIcon from '@mui/icons-material/Apple';
@@ -40,25 +41,59 @@ const MicrosoftIcon = props => {
return ;
};
-const appendReferrer = (url, referrer) =>
- referrer ? `${url}&state=${referrer}` : url;
+const appendReferrer = (url, referrer) => {
+ if (!referrer) {
+ return url;
+ }
+ const parsedUrl = queryString.parseUrl(url);
+ const redirectUrl = queryString.stringifyUrl({
+ url: 'account',
+ query: {
+ referrerBase64: btoa(referrer),
+ },
+ });
+ return queryString.stringifyUrl({
+ ...parsedUrl,
+ query: {
+ ...parsedUrl.query,
+ state: redirectUrl,
+ },
+ });
+};
const AccountForm = () => {
const { t } = useTranslation();
const { trackEvent } = useAnalytics();
+ const navigate = useNavigate();
const [searchParams] = useSearchParams();
const { fetching, urls } = useSelector(state => state.account.login);
+ const hasToken = useSelector(state => state.account.hasToken);
const referrer = searchParams.get('referrer');
+ const referrerBase64 = searchParams.get('referrerBase64');
useDocumentTitle(t('account.login_document_title'));
useDocumentDescription(t('account.login_document_description'));
useFetchData(fetchAuthURLs);
+ useEffect(() => {
+ if (!hasToken) {
+ return;
+ }
+ const url = referrerBase64 ? atob(referrerBase64) : referrer;
+ navigate(url ? decodeURIComponent(url) : '/', {
+ replace: true,
+ });
+ }, [hasToken, navigate, referrer, referrerBase64]);
+
if (fetching) {
return ;
}
+ if (hasToken) {
+ return null;
+ }
+
return (
({
...jest.requireActual('react-router-dom'),
useSearchParams: jest.fn(),
+ useNavigate: jest.fn(),
}));
beforeEach(() => {
useSearchParams.mockReturnValue([new URLSearchParams(), () => {}]);
+ useNavigate.mockReturnValue(jest.fn());
});
test('AccountLogin: Display error', async () => {
@@ -50,36 +52,100 @@ test('AccountLogin: Display loader', async () => {
test('AccountLogin: Display buttons', async () => {
accountService.getAuthURLs.mockReturnValue(
Promise.resolve({
- google: 'google.url',
- apple: 'apple.url',
+ google: 'google.url?param=value',
+ apple: 'apple.url?param=value',
})
);
await render();
expect(screen.getByText('Continue with Google')).toBeInTheDocument();
+ expect(screen.getByText('Continue with Google')).toHaveAttribute(
+ 'href',
+ `google.url?param=value`
+ );
expect(screen.getByText('Continue with Apple')).toBeInTheDocument();
});
test('AccountLogin: Add referrer', async () => {
const searchParams = new URLSearchParams();
- searchParams.set('referrer', 'groups?sort=-name');
+ const referrer = encodeURIComponent('groups?sort=-name&other=1');
+ searchParams.set('referrer', referrer);
useSearchParams.mockReturnValue([searchParams]);
accountService.getAuthURLs.mockReturnValue(
Promise.resolve({
- google: 'google.url',
- apple: 'apple.url',
+ google: 'google.url?param=value',
+ apple: 'apple.url?param=value',
})
);
await render();
expect(screen.getByText('Continue with Google')).toBeInTheDocument();
+ const state = `account%3FreferrerBase64%3D${btoa(referrer)}`;
expect(screen.getByText('Continue with Google')).toHaveAttribute(
'href',
- 'google.url&state=groups?sort=-name'
+ `google.url?param=value&state=${state}`
);
expect(screen.getByText('Continue with Apple')).toBeInTheDocument();
expect(screen.getByText('Continue with Apple')).toHaveAttribute(
'href',
- 'apple.url&state=groups?sort=-name'
+ `apple.url?param=value&state=${state}`
+ );
+});
+
+test('AccountLogin: Navigate to referrer if logged in', async () => {
+ accountService.getAuthURLs.mockReturnValue(
+ Promise.resolve({
+ google: 'google.url',
+ apple: 'apple.url',
+ })
);
+ const navigate = jest.fn();
+ useNavigate.mockReturnValue(navigate);
+ const searchParams = new URLSearchParams();
+ const referrer = encodeURIComponent('groups?sort=-name&other=1');
+ searchParams.set('referrer', referrer);
+ useSearchParams.mockReturnValue([searchParams]);
+ await render(, {
+ account: {
+ hasToken: true,
+ login: {},
+ currentUser: {
+ data: {
+ email: 'test@test.com',
+ },
+ },
+ },
+ });
+ expect(navigate).toHaveBeenCalledWith('groups?sort=-name&other=1', {
+ replace: true,
+ });
+});
+
+test('AccountLogin: Navigate to referrer base 64 if logged in', async () => {
+ accountService.getAuthURLs.mockReturnValue(
+ Promise.resolve({
+ google: 'google.url',
+ apple: 'apple.url',
+ })
+ );
+ const navigate = jest.fn();
+ useNavigate.mockReturnValue(navigate);
+ const searchParams = new URLSearchParams();
+ const referrer = encodeURIComponent('groups?sort=-name&other=1');
+ searchParams.set('referrerBase64', btoa(referrer));
+ useSearchParams.mockReturnValue([searchParams]);
+ await render(, {
+ account: {
+ hasToken: true,
+ login: {},
+ currentUser: {
+ data: {
+ email: 'test@test.com',
+ },
+ },
+ },
+ });
+ expect(navigate).toHaveBeenCalledWith('groups?sort=-name&other=1', {
+ replace: true,
+ });
});
test('AccountLogin: Display locale picker', async () => {
diff --git a/src/account/components/RequireAuth.js b/src/account/components/RequireAuth.js
index 22400a743..d9b2d2faf 100644
--- a/src/account/components/RequireAuth.js
+++ b/src/account/components/RequireAuth.js
@@ -15,6 +15,7 @@
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
import React, { useCallback } from 'react';
+import queryString from 'query-string';
import { useSelector } from 'react-redux';
import { Navigate, useLocation } from 'react-router-dom';
import { fetchUser } from 'terraso-client-shared/account/accountSlice';
@@ -48,7 +49,15 @@ const RequireAuth = ({ children }) => {
const referrer = generateReferrerPath(location);
- const to = referrer ? `/account?referrer=${referrer}` : '/account';
+ const to = referrer
+ ? queryString.stringifyUrl({
+ url: '/account',
+ query: {
+ referrer,
+ },
+ })
+ : '/account';
+
return ;
};
diff --git a/src/account/components/RequireAuth.test.js b/src/account/components/RequireAuth.test.js
index 1593bb07f..0feae1e54 100644
--- a/src/account/components/RequireAuth.test.js
+++ b/src/account/components/RequireAuth.test.js
@@ -85,10 +85,24 @@ test('Auth: test redirect', async () => {
expect(terrasoApi.requestGraphQL).toHaveBeenCalledTimes(2);
expect(screen.getByText('To: /account')).toBeInTheDocument();
});
-test('Auth: test redirect referrer', async () => {
+
+const REDIRECT_PATHNAME = '/groups';
+const REDIRECT_SEARCH = '?sort=-name&other=1';
+const REFERRER_PATH = `/account?referrer=${encodeURIComponent(
+ `${REDIRECT_PATHNAME}${REDIRECT_SEARCH}`
+)}`;
+const REFERRER_URL = new URL(`http://127.0.0.1${REFERRER_PATH}`);
+
+test('Auth: Test url parsing for referrer', async () => {
+ expect(REFERRER_URL.searchParams.get('referrer')).toBe(
+ '/groups?sort=-name&other=1'
+ );
+});
+
+test('Auth: Test redirect referrer', async () => {
useLocation.mockReturnValue({
- pathname: '/groups',
- search: '?sort=-name',
+ pathname: REDIRECT_PATHNAME,
+ search: REDIRECT_SEARCH,
});
await render(
@@ -97,9 +111,12 @@ test('Auth: test redirect referrer', async () => {
);
expect(
- screen.getByText('To: /account?referrer=groups?sort=-name')
+ screen.getByText(
+ 'To: /account?referrer=%2Fgroups%3Fsort%3D-name%26other%3D1'
+ )
).toBeInTheDocument();
});
+
test('Auth: test refresh tokens', async () => {
useParams.mockReturnValue({
slug: 'slug-1',
diff --git a/src/localization/locales/en-US.json b/src/localization/locales/en-US.json
index 0a1aa9547..6ec75b2c7 100644
--- a/src/localization/locales/en-US.json
+++ b/src/localization/locales/en-US.json
@@ -1014,7 +1014,8 @@
"addMemberships.unique": "One or more users are already collaborators of this story map.",
"approved_membership": "You have been added to “{{storyMapTitle}}”",
"approve_invite_success": "You have been added to “{{storyMapTitle}}”",
- "approve_invite_error": "Failed to accept Story Map invite",
+ "approveMembership.update_not_allowed": "Unable to accept Story Map invitation",
+ "approveMembership.update_not_allowed_permissions_validation": "You can't accept the invitation to edit “{{storyMapTitle}}.” You must log in using the email address shown in the invitation.",
"invite_document_title": "Story Map Invite"
},
"site": {
diff --git a/src/localization/locales/es-ES.json b/src/localization/locales/es-ES.json
index a95cf040a..11315d17d 100644
--- a/src/localization/locales/es-ES.json
+++ b/src/localization/locales/es-ES.json
@@ -1021,7 +1021,8 @@
"addMemberships.unique": "Uno o más usuarios ya son colaboradores de este story map.",
"approved_membership": "Te han agregado a “{{storyMapTitle}}”",
"approve_invite_success": "Te han agregado a “{{storyMapTitle}}”",
- "approve_invite_error": "No se pudo aceptar la invitación al Story Map",
+ "approveMembership.update_not_allowed": "No se puede aceptar la invitación de Story Map",
+ "approveMembership.update_not_allowed_permissions_validation": "No puedes aceptar la invitación para editar “{{storyMapTitle}}”. Debes iniciar sesión utilizando la dirección de correo electrónico que se muestra en la invitación.",
"invite_document_title": "Invitación a Story Map"
},
"site": {
diff --git a/src/navigation/components/Routes.js b/src/navigation/components/Routes.js
index 9fa9f11d6..c3c159b6b 100644
--- a/src/navigation/components/Routes.js
+++ b/src/navigation/components/Routes.js
@@ -193,11 +193,7 @@ const paths = [
isEmbedded: true,
},
}),
- path('/tools/story-maps/accept', StoryMapInvite, {
- optionalAuth: {
- enabled: true,
- },
- }),
+ path('/tools/story-maps/accept', StoryMapInvite),
path('*', NotFound),
];
diff --git a/src/navigation/navigationUtils.js b/src/navigation/navigationUtils.js
index 10d9e6d32..034f31ccb 100644
--- a/src/navigation/navigationUtils.js
+++ b/src/navigation/navigationUtils.js
@@ -22,5 +22,5 @@ export const generateReferrerPath = location => {
const referrer = [path.substring(1), queryParams]
.filter(part => part)
.join('');
- return referrer;
+ return referrer ? `/${referrer}` : null;
};
diff --git a/src/storyMap/components/StoryMapInvite.js b/src/storyMap/components/StoryMapInvite.js
index 7caa23c22..a28a606d5 100644
--- a/src/storyMap/components/StoryMapInvite.js
+++ b/src/storyMap/components/StoryMapInvite.js
@@ -52,44 +52,26 @@ const StoryMapInvite = () => {
}, [token, decodedToken, membershipId])
);
- useEffect(() => {
- if (!success && !error) {
- return;
- }
-
- if (success) {
- dispatch(
- addMessage({
- severity: 'success',
- content: 'storyMap.approve_invite_success',
- params: {
- storyMapTitle: storyMap.title,
- },
- })
- );
- }
-
- if (error) {
- dispatch(
- addMessage({
- severity: 'error',
- content: 'storyMap.approve_invite_error',
- })
- );
- }
- }, [success, error, storyMap, dispatch, navigate]);
-
useEffect(() => {
if (!success) {
return;
}
navigate(`/tools/story-maps/${storyMap.storyMapId}/${storyMap.slug}/edit`);
trackEvent('storymap.share.accept');
- }, [success, navigate, trackEvent, storyMap]);
+ dispatch(
+ addMessage({
+ severity: 'success',
+ content: 'storyMap.approve_invite_success',
+ params: {
+ storyMapTitle: storyMap.title,
+ },
+ })
+ );
+ }, [success, navigate, trackEvent, dispatch, storyMap]);
useDocumentTitle(t('storyMap.invite_document_title'));
- if (processing || !storyMap) {
+ if (processing) {
return ;
}
@@ -99,7 +81,14 @@ const StoryMapInvite = () => {
return (
- {t('storyMap.approve_invite_error')}
+ {error?.parsedErrors.map((error, index) => (
+
+ {t(error.content, {
+ ...error.params,
+ storyMapTitle: error.params?.response?.storyMap?.title,
+ })}
+
+ ))}
);
};
diff --git a/src/storyMap/components/StoryMapInvite.test.js b/src/storyMap/components/StoryMapInvite.test.js
index eee7b65dc..23fff0fd4 100644
--- a/src/storyMap/components/StoryMapInvite.test.js
+++ b/src/storyMap/components/StoryMapInvite.test.js
@@ -110,7 +110,9 @@ test('StoryMapInvite: Invalid token', async () => {
useSearchParams.mockReturnValue([searchParams]);
mockTerrasoAPIrequestGraphQL({
- 'mutation approveMembershipToken': Promise.reject('Error'),
+ 'mutation approveMembershipToken': Promise.reject({
+ content: 'update_not_allowed',
+ }),
});
await setup();
@@ -118,8 +120,40 @@ test('StoryMapInvite: Invalid token', async () => {
await waitFor(() =>
expect(
within(screen.getByRole('alert')).getByText(
- /Failed to accept Story Map invite/i
+ /Unable to accept Story Map invitation/i
)
).toBeInTheDocument()
);
});
+
+test('StoryMapInvite: Different user token', async () => {
+ const navigate = jest.fn();
+ useNavigate.mockReturnValue(navigate);
+
+ const searchParams = new URLSearchParams();
+ searchParams.set('token', TOKEN);
+ useSearchParams.mockReturnValue([searchParams]);
+
+ mockTerrasoAPIrequestGraphQL({
+ 'mutation approveMembershipToken': Promise.reject({
+ content: 'update_not_allowed_permissions_validation',
+ params: {
+ response: {
+ storyMap: {
+ title: 'Story Map title',
+ },
+ },
+ },
+ }),
+ });
+
+ await setup();
+
+ expect(
+ within(screen.getByRole('alert')).getByText(
+ /You can't accept the invitation to edit “Story Map title.” You must log in using the email address shown in the invitation./i
+ )
+ ).toBeInTheDocument();
+
+ expect(navigate).not.toHaveBeenCalled();
+});
diff --git a/src/storyMap/storyMapSlice.js b/src/storyMap/storyMapSlice.js
index 120c19670..c5fa46eec 100644
--- a/src/storyMap/storyMapSlice.js
+++ b/src/storyMap/storyMapSlice.js
@@ -363,7 +363,7 @@ const storyMapSlice = createSlice({
...state.memberships.approve,
[action.meta.arg.membership.membershipId]: {
processing: false,
- error: true,
+ error: action.payload,
},
},
},