From ccfd6ceaad51b18ec5d15065426bee2c18280ebd Mon Sep 17 00:00:00 2001 From: Martin Krulis Date: Tue, 5 Oct 2021 01:35:32 +0200 Subject: [PATCH] Making the information about not-verified email address more persistent and visible on multiple places. --- .../NotVerifiedEmailCallout.js | 42 +++++++++++++++++ .../Users/NotVerifiedEmailCallout/index.js | 2 + src/components/Users/UsersName/NotVerified.js | 1 + .../EditUserSettingsForm.js | 9 ++++ .../widgets/Sidebar/UserPanel/UserPanel.js | 2 +- src/locales/cs.json | 45 ++++++++++--------- src/locales/en.json | 1 + src/pages/Dashboard/Dashboard.js | 10 ++++- src/pages/EditUser/EditUser.js | 42 +++-------------- src/pages/Instance/Instance.js | 17 ++++++- src/pages/SisIntegration/SisIntegration.js | 21 ++++++++- 11 files changed, 128 insertions(+), 64 deletions(-) create mode 100644 src/components/Users/NotVerifiedEmailCallout/NotVerifiedEmailCallout.js create mode 100644 src/components/Users/NotVerifiedEmailCallout/index.js diff --git a/src/components/Users/NotVerifiedEmailCallout/NotVerifiedEmailCallout.js b/src/components/Users/NotVerifiedEmailCallout/NotVerifiedEmailCallout.js new file mode 100644 index 000000000..6ad6a03f2 --- /dev/null +++ b/src/components/Users/NotVerifiedEmailCallout/NotVerifiedEmailCallout.js @@ -0,0 +1,42 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { FormattedMessage } from 'react-intl'; + +import ResendVerificationEmail from '../../../containers/ResendVerificationEmailContainer'; +import Callout from '../../widgets/Callout'; +import Button, { TheButtonGroup } from '../../widgets/TheButton'; +import { RefreshIcon } from '../../icons'; + +const NotVerifiedEmailCallout = ({ userId, refreshUser }) => ( + +

+ +

+

+ +

+

+ +

+ + + + +
+); + +NotVerifiedEmailCallout.propTypes = { + userId: PropTypes.string.isRequired, + refreshUser: PropTypes.func.isRequired, +}; + +export default NotVerifiedEmailCallout; diff --git a/src/components/Users/NotVerifiedEmailCallout/index.js b/src/components/Users/NotVerifiedEmailCallout/index.js new file mode 100644 index 000000000..8d0b22ec5 --- /dev/null +++ b/src/components/Users/NotVerifiedEmailCallout/index.js @@ -0,0 +1,2 @@ +import NotVerifiedEmailCallout from './NotVerifiedEmailCallout'; +export default NotVerifiedEmailCallout; diff --git a/src/components/Users/UsersName/NotVerified.js b/src/components/Users/UsersName/NotVerified.js index 18977430d..6cf443deb 100644 --- a/src/components/Users/UsersName/NotVerified.js +++ b/src/components/Users/UsersName/NotVerified.js @@ -10,6 +10,7 @@ const NotVerified = ({ userId, currentUserId }) => { diff --git a/src/components/forms/EditUserSettingsForm/EditUserSettingsForm.js b/src/components/forms/EditUserSettingsForm/EditUserSettingsForm.js index 3770fb789..91d25e777 100644 --- a/src/components/forms/EditUserSettingsForm/EditUserSettingsForm.js +++ b/src/components/forms/EditUserSettingsForm/EditUserSettingsForm.js @@ -133,6 +133,15 @@ const EditUserSettingsForm = ({ : + {!user.isVerified && ( + + + + )} + {isStudentRole(user.privateData.role) && ( <> ) : ( - + )} diff --git a/src/locales/cs.json b/src/locales/cs.json index 1fcc74f2e..93893119b 100644 --- a/src/locales/cs.json +++ b/src/locales/cs.json @@ -180,7 +180,7 @@ "app.changePassword.tokenExpired": "Vaše heslo nemůže být změněno - Váš token pravděpodobně vypršel nebo máte nesprávný formát URL.", "app.changePassword.tokenExpiresIn": "Token vyprší za:", "app.changePasswordForm.changePassword": "Změnit heslo", - "app.changePasswordForm.email": "Email:", + "app.changePasswordForm.email": "E-mail:", "app.changePasswordForm.failed": "Změna hesla selhala.", "app.changePasswordForm.oldPassword": "Staré heslo:", "app.changePasswordForm.password": "Nové heslo:", @@ -217,7 +217,7 @@ "app.createGroup.makeMeAdmin": "Chci být administrátorem skupiny", "app.createGroup.publicStats": "Studenti mohou vidět dosažené body ostatních", "app.createGroup.threshold": "Minimální procentuální hranice potřebná ke splnění tohoto kurzu:", - "app.createUserForm.validation.emailTaken": "Tato emailová adresa již patří jinému uživateli.", + "app.createUserForm.validation.emailTaken": "Tato e-mailová adresa již patří jinému uživateli.", "app.createUserForm.validation.emptyPassword": "Heslo nemůže zůstat prázdné.", "app.dashboard.memberOf": "Skupiny, ve kterých jste členem", "app.dashboard.sisGroupsStudent": "Přihlásit se do skupin asociovaných s kurzy ze SISu UK", @@ -548,8 +548,8 @@ "app.editTestsTest.pointsPercentage": "Body v procentech:", "app.editTestsTest.testUsedInExpression": "použit ve výrazu", "app.editTestsTest.weight": "Váha testu:", - "app.editUser.emailStillNotVerified": "Vaše emailová adresa dosud nebyla ověřena. ReCodEx se potřebuje spolehnout na platnost adres, protože řada notifikací je zasílána emailem. Pomocí tlačítka níže si můžete nechat opětovně zaslat ověřovací email. Ten obsahuje odkaz, který potvrzuje platnost adresy. Prosíme, ověřte vaši adresu co nejdříve.", - "app.editUser.emailStillNotVerifiedTitle": "Emailová adresa není ověřena", + "app.editUser.emailStillNotVerified": "Vaše e-mailová adresa dosud nebyla ověřena. ReCodEx se potřebuje spolehnout na platnost adres, protože řada notifikací je zasílána e-mailem. Pomocí tlačítka níže si můžete nechat opětovně zaslat ověřovací e-mail. Ten obsahuje odkaz, který potvrzuje platnost adresy. Prosíme, ověřte vaši adresu co nejdříve.", + "app.editUser.emailStillNotVerifiedTitle": "E-mailová adresa není ověřena", "app.editUser.isEmailAlreadyVefiried": "Pokud jste právě ověřili vaši adresu a stále vidíte tuto hlášku, prosím občerstvěte stránku.", "app.editUser.makeLocal": "Vytvořit lokální účet", "app.editUser.title": "Upravit uživatelský profil", @@ -562,9 +562,9 @@ "app.editUserProfile.passwordTitle": "Změna hesla", "app.editUserProfile.titlesAfterName": "Tituly za jménem:", "app.editUserProfile.titlesBeforeName": "Tituly před jménem:", - "app.editUserProfile.validation.emailNotValid": "Emailová adresa není platná.", - "app.editUserProfile.validation.emailTaken": "Tento email je již zabrán jiným uživatelem nebo je shodný s vaší starou adresou.", - "app.editUserProfile.validation.emptyEmail": "Emailová adresa nemůže být prázdná.", + "app.editUserProfile.validation.emailNotValid": "E-mailová adresa není platná.", + "app.editUserProfile.validation.emailTaken": "Tento e-mail je již zabrán jiným uživatelem nebo je shodný s vaší starou adresou.", + "app.editUserProfile.validation.emptyEmail": "E-mailová adresa nemůže být prázdná.", "app.editUserProfile.validation.emptyFirstName": "Jméno nemůže být prázdné.", "app.editUserProfile.validation.emptyLastName": "Příjmení nemůže být prázdné.", "app.editUserProfile.validation.emptyNewPassword": "Nové heslo nemůže být prázdné pokud si měníte heslo.", @@ -585,7 +585,8 @@ "app.editUserSettings.defaultPage.dashboard": "Přehled", "app.editUserSettings.defaultPage.home": "Domovská stránka (o ReCodExu)", "app.editUserSettings.defaultPage.instance": "Detail instance", - "app.editUserSettings.emailsTitle": "Oznámení emailem", + "app.editUserSettings.emailStillNotVerifiedTitle": "Vaše e-mailová adresa nebyla verifikována, takže žádné notifikační maily nebudou zasílány bez ohledu na vaše osobní nastavení.", + "app.editUserSettings.emailsTitle": "Oznámení e-mailem", "app.editUserSettings.failed": "Uložení uživatelského profilu se nezdařilo.", "app.editUserSettings.newAssignmentEmails": "Nově zadaná úloha", "app.editUserSettings.openedSidebar": "Postraní panel je ve výchozím stavu rozbalený.", @@ -595,13 +596,13 @@ "app.editUserSettings.title": "Změnit nastavení", "app.editUserSettings.useGravatar": "Používat službu Gravatar pro zobrazování avatarů ostatních uživatelů.", "app.editUserSettings.vimMode": "Použít rozložení kláves editoru VIM pro editor zdrojového kódu.", - "app.emailVerification.failed": "Tato emailová adresa nemůže být ověřena.", - "app.emailVerification.progress": "Postup ověřování emailu", + "app.emailVerification.failed": "Tato e-mailová adresa nemůže být ověřena.", + "app.emailVerification.progress": "Postup ověřování e-mailu", "app.emailVerification.requestAnotherLink": "Prosíme požádejte o (další) odkaz s unikátním tokenem.", - "app.emailVerification.title": "Ověření emailu", - "app.emailVerification.tokenExpired": "Emailová adresa nyní nemůže být ověřena - váš token vypršel nebo používáte špatnou URL.", - "app.emailVerification.verified": "Emailová adresa byla ověřena.", - "app.emailVerification.waiting": "Emailová adresa je právě ověřována.", + "app.emailVerification.title": "Ověření e-mailu", + "app.emailVerification.tokenExpired": "E-mailová adresa nyní nemůže být ověřena - váš token vypršel nebo používáte špatnou URL.", + "app.emailVerification.verified": "E-mailová adresa byla ověřena.", + "app.emailVerification.waiting": "E-mailová adresa je právě ověřována.", "app.environmentsList.noEnvironments": "žádná běhová prostředí", "app.evaluationDetail.buildSucceeded": "Kompilace:", "app.evaluationDetail.evaluatedAt": "Vyhodnoceno:", @@ -1205,7 +1206,7 @@ "app.registrationForm.processing": "Probíhá vytváření účtu...", "app.registrationForm.success": "Váš účet byl vytvořen.", "app.registrationForm.title": "Vytvořte si účet v ReCodExu", - "app.registrationForm.validation.emailAlreadyTaken": "Tato emailová adresa je již zabraná jiným uživatelem.", + "app.registrationForm.validation.emailAlreadyTaken": "Tato e-mailová adresa je již zabraná jiným uživatelem.", "app.registrationForm.validation.emailIsNotAnEmail": "E-mailová adresa není zadána správně.", "app.registrationForm.validation.emptyEmail": "E-mailová adresa nemůže být prázdná.", "app.registrationForm.validation.emptyFirstName": "Jméno nemůže být prázdné.", @@ -1220,9 +1221,9 @@ "app.relocateGroupForm.success": "Skupina přemístěna", "app.removeFromGroup.confirm": "Opravdu chcete odstranit uživatele z této skupiny?", "app.resendEmailVerification.failed": "Opětovné odeslání selhalo. Prosíme opakujte akci později", - "app.resendEmailVerification.resend": "Znovu odeslat ověřovací email", - "app.resendEmailVerification.resending": "Odesílání emailu...", - "app.resendEmailVerification.resent": "Email byl úspěšně odeslán", + "app.resendEmailVerification.resend": "Znovu odeslat ověřovací e-mail", + "app.resendEmailVerification.resending": "Odesílání e-mailu...", + "app.resendEmailVerification.resent": "E-mail byl úspěšně odeslán", "app.resetPassword.email": "E-mailová adresa:", "app.resetPassword.failed": "Reset hesla se nezdařil. Prosíme, zkontrolujte Vaší mailovou adresu.", "app.resetPassword.processing": "Resetování hesla...", @@ -1499,7 +1500,7 @@ "app.submissionFailures.resolveMaxLengthExceeded": "Délka poznámky byla překročena.", "app.submissionFailures.resolveNote": "Poznámka k řešení problému:", "app.submissionFailures.resolveTitle": "Vyřešit chybu", - "app.submissionFailures.sendEmail": "Poslat email", + "app.submissionFailures.sendEmail": "Poslat e-mail", "app.submissionFailures.title": "Neúspěšná odevzdání", "app.submissionStatus.accepted": "Toto řešení bylo označeno jako akceptované vedoucím skupiny.", "app.submissions.testResultsTable.correctness": "Správnost odevzdaného řešení (rozhodnutí sudího)", @@ -1603,9 +1604,9 @@ "app.users.takeOver": "Přihlásit jako", "app.users.title": "Seznam všech uživatelů", "app.users.userCreatedAt": "Uživatel vytvořen", - "app.usersName.notVerified.title": "Tento účet nemá ověřenou emailovou adresu.", + "app.usersName.notVerified.title": "Tento účet nemá ověřenou e-mailovou adresu.", "app.usersStats.description": "Body získané ve skupině {name}.", - "app.usersname.notVerified.description": "Tento uživatel si neověřil svou emailovou adresu přes aktivační odkaz, který mu byl na tuto adresu zaslán.", + "app.usersname.notVerified.description": "Tento uživatel si neověřil svou e-mailovou adresu přes aktivační odkaz, který mu byl na tuto adresu zaslán.", "diff": "Sudí binárních dat", "generic.accessDenied": "Nemáte oprávnění vidět tuto stránku. Pokud došlo k přesměrování na tuto stránku po kliknutí na zdánlivě legitimní odkaz nebo tlačítko, prosíme nahlaste chybu.", "generic.acknowledge": "Beru na vědomí", @@ -1629,7 +1630,7 @@ "generic.discussion": "Diskuse", "generic.edit": "Editovat", "generic.effectiveRole": "Efektivní role", - "generic.email": "Email", + "generic.email": "E-mail", "generic.enable": "Povolit", "generic.errorMessage": "Chybová hláška", "generic.explain": "vysvětlit", diff --git a/src/locales/en.json b/src/locales/en.json index d2c7674b3..6ef8c5dba 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -585,6 +585,7 @@ "app.editUserSettings.defaultPage.dashboard": "Dashboard", "app.editUserSettings.defaultPage.home": "Home page (about)", "app.editUserSettings.defaultPage.instance": "Instance overview", + "app.editUserSettings.emailStillNotVerifiedTitle": "Your email address is not verified, so no notifications will be sent regardless your personal settings.", "app.editUserSettings.emailsTitle": "Email Notifications", "app.editUserSettings.failed": "Cannot save profile settings.", "app.editUserSettings.newAssignmentEmails": "New exercise assigned", diff --git a/src/pages/Dashboard/Dashboard.js b/src/pages/Dashboard/Dashboard.js index 6578f881a..70b9da636 100644 --- a/src/pages/Dashboard/Dashboard.js +++ b/src/pages/Dashboard/Dashboard.js @@ -9,6 +9,7 @@ import { Link } from 'react-router-dom'; import Button, { TheButtonGroup } from '../../components/widgets/TheButton'; import Page from '../../components/layout/Page'; import { UserNavigation } from '../../components/layout/Navigation'; +import NotVerifiedEmailCallout from '../../components/Users/NotVerifiedEmailCallout'; import Box from '../../components/widgets/Box'; import Callout from '../../components/widgets/Callout'; import StudentsListContainer from '../../containers/StudentsListContainer'; @@ -17,7 +18,7 @@ import GroupsNameContainer from '../../containers/GroupsNameContainer'; import AssignmentsTableContainer from '../../containers/AssignmentsTableContainer'; import ShadowAssignmentsTableContainer from '../../containers/ShadowAssignmentsTableContainer'; -import { fetchUserIfNeeded } from '../../redux/modules/users'; +import { fetchUserIfNeeded, fetchUser } from '../../redux/modules/users'; import { fetchAllGroups } from '../../redux/modules/groups'; import { fetchRuntimeEnvironments } from '../../redux/modules/runtimeEnvironments'; @@ -61,6 +62,7 @@ class Dashboard extends Component { supervisor, memberGroups, fetchManyGroupsStatus, + refreshUser, links: { GROUP_INFO_URI_FACTORY, GROUP_DETAIL_URI_FACTORY }, } = this.props; @@ -78,6 +80,10 @@ class Dashboard extends Component {
+ {user && !user.isVerified && ( + refreshUser(user.id)} /> + )} + {() => ( <> @@ -228,6 +234,7 @@ Dashboard.propTypes = { supervisor: PropTypes.bool, superadmin: PropTypes.bool, loadAsync: PropTypes.func.isRequired, + refreshUser: PropTypes.func.isRequired, userId: PropTypes.string, memberGroups: PropTypes.object.isRequired, fetchManyGroupsStatus: PropTypes.string, @@ -251,6 +258,7 @@ export default withLinks( }, (dispatch, { match: { params } }) => ({ loadAsync: userId => Dashboard.loadAsync(params, dispatch, { userId }), + refreshUser: userId => dispatch(fetchUser(userId)), }) )(injectIntl(Dashboard)) ); diff --git a/src/pages/EditUser/EditUser.js b/src/pages/EditUser/EditUser.js index 3cef8b1fd..36fe723a0 100644 --- a/src/pages/EditUser/EditUser.js +++ b/src/pages/EditUser/EditUser.js @@ -2,7 +2,7 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import ImmutablePropTypes from 'react-immutable-proptypes'; import { connect } from 'react-redux'; -import { FormattedMessage, injectIntl } from 'react-intl'; +import { FormattedMessage } from 'react-intl'; import { Row, Col } from 'react-bootstrap'; import { defaultMemoize } from 'reselect'; @@ -17,12 +17,11 @@ import { import { getUser, isLoggedAsSuperAdmin } from '../../redux/selectors/users'; import Page from '../../components/layout/Page'; import { UserNavigation } from '../../components/layout/Navigation'; +import NotVerifiedEmailCallout from '../../components/Users/NotVerifiedEmailCallout'; import Button, { TheButtonGroup } from '../../components/widgets/TheButton'; -import Callout from '../../components/widgets/Callout'; -import { LocalIcon, TransferIcon, EditUserIcon, RefreshIcon } from '../../components/icons'; +import { LocalIcon, TransferIcon, EditUserIcon } from '../../components/icons'; import { isStudentRole } from '../../components/helpers/usersRoles'; import AllowUserButtonContainer from '../../containers/AllowUserButtonContainer'; -import ResendVerificationEmail from '../../containers/ResendVerificationEmailContainer'; import EditUserProfileForm from '../../components/forms/EditUserProfileForm'; import EditUserSettingsForm from '../../components/forms/EditUserSettingsForm'; @@ -72,7 +71,6 @@ class EditUser extends Component { lastToken, takeOver, refreshUser, - intl: { locale }, } = this.props; return ( -

- -

-

- -

-

- -

-

- - -

- + )} @@ -225,7 +194,6 @@ EditUser.propTypes = { generateToken: PropTypes.func.isRequired, setRole: PropTypes.func.isRequired, takeOver: PropTypes.func.isRequired, - intl: PropTypes.object, }; export default connect( @@ -265,4 +233,4 @@ export default connect( setRole: role => dispatch(setRole(userId, role)), takeOver: userId => dispatch(takeOver(userId)), }) -)(injectIntl(EditUser)); +)(EditUser); diff --git a/src/pages/Instance/Instance.js b/src/pages/Instance/Instance.js index d335e3ea7..6c59fd616 100644 --- a/src/pages/Instance/Instance.js +++ b/src/pages/Instance/Instance.js @@ -17,6 +17,8 @@ import AddLicenceFormContainer from '../../containers/AddLicenceFormContainer'; import EditGroupForm, { EDIT_GROUP_FORM_EMPTY_INITIAL_VALUES } from '../../components/forms/EditGroupForm'; import { EditIcon, InstanceIcon } from '../../components/icons'; import FetchManyResourceRenderer from '../../components/helpers/FetchManyResourceRenderer'; +import ResourceRenderer from '../../components/helpers/ResourceRenderer'; +import NotVerifiedEmailCallout from '../../components/Users/NotVerifiedEmailCallout'; import { fetchUser } from '../../redux/modules/users'; import { fetchInstanceIfNeeded } from '../../redux/modules/instances'; @@ -24,7 +26,7 @@ import { instanceSelector, isAdminOfInstance } from '../../redux/selectors/insta import { createGroup, fetchAllGroups } from '../../redux/modules/groups'; import { notArchivedGroupsSelector, fetchManyGroupsStatus } from '../../redux/selectors/groups'; import { loggedInUserIdSelector } from '../../redux/selectors/auth'; -import { isLoggedAsSuperAdmin } from '../../redux/selectors/users'; +import { isLoggedAsSuperAdmin, getUser } from '../../redux/selectors/users'; import { transformLocalizedTextsFormData, getLocalizedName } from '../../helpers/localizedData'; import { resourceStatus } from '../../redux/helpers/resourceManager'; @@ -58,6 +60,8 @@ class Instance extends Component { params: { instanceId }, }, userId, + user, + refreshUser, instance, groups, fetchGroupsStatus, @@ -83,6 +87,13 @@ class Instance extends Component { windowTitle={instance => getLocalizedName(instance.rootGroup, locale)}> {data => (
+ + {user => + user && + !user.isVerified && refreshUser(userId)} /> + } + + {isSuperAdmin && ( @@ -163,12 +174,14 @@ class Instance extends Component { Instance.propTypes = { loadAsync: PropTypes.func.isRequired, + refreshUser: PropTypes.func.isRequired, match: PropTypes.shape({ params: PropTypes.shape({ instanceId: PropTypes.string.isRequired, }), }).isRequired, userId: PropTypes.string.isRequired, + user: ImmutablePropTypes.map, instance: ImmutablePropTypes.map, groups: ImmutablePropTypes.map, fetchGroupsStatus: PropTypes.string, @@ -195,6 +208,7 @@ export default withLinks( const userId = loggedInUserIdSelector(state); return { userId, + user: getUser(userId)(state), instance: instanceSelector(state, instanceId), groups: notArchivedGroupsSelector(state), fetchGroupsStatus: fetchManyGroupsStatus(state), @@ -225,6 +239,7 @@ export default withLinks( }) ).then(() => Promise.all([dispatch(fetchAllGroups()), dispatch(fetchUser(userId))])), loadAsync: fetchGroupsStatus => Instance.loadAsync({ instanceId, fetchGroupsStatus }, dispatch), + refreshUser: userId => dispatch(fetchUser(userId)), }) )(injectIntl(Instance)) ); diff --git a/src/pages/SisIntegration/SisIntegration.js b/src/pages/SisIntegration/SisIntegration.js index 9231cecf5..2c7ec18b5 100644 --- a/src/pages/SisIntegration/SisIntegration.js +++ b/src/pages/SisIntegration/SisIntegration.js @@ -21,9 +21,11 @@ import Box from '../../components/widgets/Box/Box'; import ResourceRenderer from '../../components/helpers/ResourceRenderer'; import Button, { TheButtonGroup } from '../../components/widgets/TheButton'; import Callout from '../../components/widgets/Callout'; +import NotVerifiedEmailCallout from '../../components/Users/NotVerifiedEmailCallout'; import { fetchAllTerms, create, deleteTerm, editTerm } from '../../redux/modules/sisTerms'; import { createGroup, fetchAllGroups, setArchived } from '../../redux/modules/groups'; +import { fetchUser } from '../../redux/modules/users'; import { loggedInUserSelector, getLoggedInUserEffectiveRole } from '../../redux/selectors/users'; import { fetchManyStatus, readySisTermsSelector } from '../../redux/selectors/sisTerms'; import { notArchivedGroupsSelector } from '../../redux/selectors/groups'; @@ -188,8 +190,17 @@ class SisIntegration extends Component { } render() { - const { loggedInUser, effectiveRole, fetchStatus, adminOfGroups, allGroups, createNewTerm, deleteTerm, sisTerms } = - this.props; + const { + loggedInUser, + effectiveRole, + fetchStatus, + adminOfGroups, + allGroups, + createNewTerm, + deleteTerm, + sisTerms, + refreshUser, + } = this.props; return ( + {user && !user.isVerified && ( + refreshUser(user.id)} /> + )} + }> ({ ).then(), setArchived: groupId => dispatch(setArchived(groupId, true)), refreshGroups: () => dispatch(fetchAllGroups()), + refreshUser: userId => dispatch(fetchUser(userId)), }); export default connect(mapStateToProps, mapDispatchToProps)(injectIntl(SisIntegration));