diff --git a/client/app/bundles/course/enrol-requests/components/buttons/PendingEnrolRequestsButtons.tsx b/client/app/bundles/course/enrol-requests/components/buttons/PendingEnrolRequestsButtons.tsx index 9154e9cd815..0175d95b0e3 100644 --- a/client/app/bundles/course/enrol-requests/components/buttons/PendingEnrolRequestsButtons.tsx +++ b/client/app/bundles/course/enrol-requests/components/buttons/PendingEnrolRequestsButtons.tsx @@ -1,5 +1,5 @@ import { FC, memo, useState } from 'react'; -import { defineMessages, injectIntl, WrappedComponentProps } from 'react-intl'; +import { defineMessages } from 'react-intl'; import equal from 'fast-deep-equal'; import { EnrolRequestRowData } from 'types/course/enrolRequests'; @@ -8,10 +8,11 @@ import DeleteButton from 'lib/components/core/buttons/DeleteButton'; import { COURSE_USER_ROLES } from 'lib/constants/sharedConstants'; import { useAppDispatch } from 'lib/hooks/store'; import toast from 'lib/hooks/toast'; +import useTranslation from 'lib/hooks/useTranslation'; import { approveEnrolRequest, rejectEnrolRequest } from '../../operations'; -interface Props extends WrappedComponentProps { +interface Props { enrolRequest: EnrolRequestRowData; } const styles = { @@ -53,7 +54,8 @@ const translations = defineMessages({ }); const PendingEnrolRequestsButtons: FC = (props) => { - const { intl, enrolRequest } = props; + const { enrolRequest } = props; + const { t } = useTranslation(); const dispatch = useAppDispatch(); const [isApproving, setIsApproving] = useState(false); const [isDeleting, setIsDeleting] = useState(false); @@ -63,7 +65,7 @@ const PendingEnrolRequestsButtons: FC = (props) => { return dispatch(approveEnrolRequest(enrolRequest)) .then(() => { toast.success( - intl.formatMessage(translations.approveSuccess, { + t(translations.approveSuccess, { name: enrolRequest.name, }), ); @@ -73,7 +75,7 @@ const PendingEnrolRequestsButtons: FC = (props) => { ? error.response.data.errors : ''; toast.error( - intl.formatMessage(translations.approveFailure, { + t(translations.approveFailure, { error: errorMessage, }), ); @@ -86,7 +88,7 @@ const PendingEnrolRequestsButtons: FC = (props) => { return dispatch(rejectEnrolRequest(enrolRequest.id)) .then(() => { toast.success( - intl.formatMessage(translations.rejectSuccess, { + t(translations.rejectSuccess, { name: enrolRequest.name, }), ); @@ -96,7 +98,7 @@ const PendingEnrolRequestsButtons: FC = (props) => { ? error.response.data.errors : ''; toast.error( - intl.formatMessage(translations.rejectFailure, { + t(translations.rejectFailure, { error: errorMessage, }), ); @@ -111,11 +113,11 @@ const PendingEnrolRequestsButtons: FC = (props) => { disabled={isApproving || isDeleting} onClick={onApprove} sx={styles.buttonStyle} - tooltip={intl.formatMessage(translations.approveTooltip)} + tooltip={t(translations.approveTooltip)} /> = (props) => { loading={isDeleting} onClick={onDelete} sx={styles.buttonStyle} - tooltip={intl.formatMessage(translations.rejectTooltip)} + tooltip={t(translations.rejectTooltip)} /> ); }; export default memo( - injectIntl(PendingEnrolRequestsButtons), + PendingEnrolRequestsButtons, (prevProps, nextProps) => { return equal(prevProps.enrolRequest, nextProps.enrolRequest); }, diff --git a/client/app/bundles/course/user-invitations/components/forms/IndividualInvitation.tsx b/client/app/bundles/course/user-invitations/components/forms/IndividualInvitation.tsx index 5dbf8aa1e42..a37a36ebc78 100644 --- a/client/app/bundles/course/user-invitations/components/forms/IndividualInvitation.tsx +++ b/client/app/bundles/course/user-invitations/components/forms/IndividualInvitation.tsx @@ -5,7 +5,7 @@ import { UseFieldArrayAppend, UseFieldArrayRemove, } from 'react-hook-form'; -import { defineMessages, injectIntl, WrappedComponentProps } from 'react-intl'; +import { defineMessages } from 'react-intl'; import { Close } from '@mui/icons-material'; import { Box, Grid, IconButton, Tooltip } from '@mui/material'; import { ManageCourseUsersPermissions } from 'types/course/courseUsers'; @@ -21,9 +21,10 @@ import { COURSE_USER_ROLES, TIMELINE_ALGORITHMS, } from 'lib/constants/sharedConstants'; +import useTranslation from 'lib/hooks/useTranslation'; import tableTranslations from 'lib/translations/table'; -interface Props extends WrappedComponentProps { +interface Props { permissions: ManageCourseUsersPermissions; fieldsConfig: { control: Control; @@ -70,7 +71,8 @@ const userRoleOptions = Object.keys(COURSE_USER_ROLES).map((roleValue) => ({ })); const IndividualInvitation: FC = (props) => { - const { permissions, fieldsConfig, index, intl } = props; + const { permissions, fieldsConfig, index } = props; + const { t } = useTranslation(); const renderInvitationBody = ( @@ -82,8 +84,8 @@ const IndividualInvitation: FC = (props) => { field={field} fieldState={fieldState} id={`name-${index}`} - label={intl.formatMessage(tableTranslations.name)} - placeholder={intl.formatMessage(translations.namePlaceholder)} + label={t(tableTranslations.name)} + placeholder={t(translations.namePlaceholder)} sx={styles.textInput} variant="standard" /> @@ -97,8 +99,8 @@ const IndividualInvitation: FC = (props) => { field={field} fieldState={fieldState} id={`email-${index}`} - label={intl.formatMessage(tableTranslations.email)} - placeholder={intl.formatMessage(translations.emailPlaceholder)} + label={t(tableTranslations.email)} + placeholder={t(translations.emailPlaceholder)} sx={styles.textInput} variant="standard" /> @@ -111,7 +113,7 @@ const IndividualInvitation: FC = (props) => { @@ -125,7 +127,7 @@ const IndividualInvitation: FC = (props) => { )} @@ -138,7 +140,7 @@ const IndividualInvitation: FC = (props) => { )} /> @@ -148,7 +150,7 @@ const IndividualInvitation: FC = (props) => { return ( {renderInvitationBody} - + fieldsConfig.remove(index)}> @@ -157,4 +159,4 @@ const IndividualInvitation: FC = (props) => { ); }; -export default injectIntl(IndividualInvitation); +export default IndividualInvitation; diff --git a/client/app/bundles/course/user-invitations/components/tables/InvitationResultInvitationsTable.tsx b/client/app/bundles/course/user-invitations/components/tables/InvitationResultInvitationsTable.tsx index df8e554eec2..d89be6766b8 100644 --- a/client/app/bundles/course/user-invitations/components/tables/InvitationResultInvitationsTable.tsx +++ b/client/app/bundles/course/user-invitations/components/tables/InvitationResultInvitationsTable.tsx @@ -1,5 +1,4 @@ import { FC, memo } from 'react'; -import { injectIntl, WrappedComponentProps } from 'react-intl'; import { Typography } from '@mui/material'; import equal from 'fast-deep-equal'; import { TableColumns, TableOptions } from 'types/components/DataTable'; @@ -10,15 +9,17 @@ import { COURSE_USER_ROLES, DEFAULT_TABLE_ROWS_PER_PAGE, } from 'lib/constants/sharedConstants'; +import useTranslation from 'lib/hooks/useTranslation'; import tableTranslations from 'lib/translations/table'; -interface Props extends WrappedComponentProps { +interface Props { title: JSX.Element; invitations: InvitationListData[]; } const InvitationResultInvitationsTable: FC = (props) => { - const { title, invitations, intl } = props; + const { title, invitations } = props; + const { t } = useTranslation(); if (invitations && invitations.length === 0) return null; @@ -47,7 +48,7 @@ const InvitationResultInvitationsTable: FC = (props) => { const columns: TableColumns[] = [ { name: 'id', - label: intl.formatMessage(tableTranslations.id), + label: t(tableTranslations.id), options: { display: false, filter: false, @@ -56,7 +57,7 @@ const InvitationResultInvitationsTable: FC = (props) => { }, { name: 'name', - label: intl.formatMessage(tableTranslations.name), + label: t(tableTranslations.name), options: { alignCenter: false, sort: false, @@ -64,7 +65,7 @@ const InvitationResultInvitationsTable: FC = (props) => { }, { name: 'email', - label: intl.formatMessage(tableTranslations.email), + label: t(tableTranslations.email), options: { alignCenter: false, sort: false, @@ -72,7 +73,7 @@ const InvitationResultInvitationsTable: FC = (props) => { }, { name: 'phantom', - label: intl.formatMessage(tableTranslations.phantom), + label: t(tableTranslations.phantom), options: { sort: false, customBodyRenderLite: (dataIndex): JSX.Element => { @@ -91,7 +92,7 @@ const InvitationResultInvitationsTable: FC = (props) => { }, { name: 'role', - label: intl.formatMessage(tableTranslations.role), + label: t(tableTranslations.role), options: { alignCenter: false, sort: false, @@ -111,7 +112,7 @@ const InvitationResultInvitationsTable: FC = (props) => { }, { name: 'sentAt', - label: intl.formatMessage(tableTranslations.invitationSentAt), + label: t(tableTranslations.invitationSentAt), options: { alignCenter: false, sort: false, @@ -132,7 +133,7 @@ const InvitationResultInvitationsTable: FC = (props) => { }; export default memo( - injectIntl(InvitationResultInvitationsTable), + InvitationResultInvitationsTable, (prevProps, nextProps) => { return equal(prevProps.invitations, nextProps.invitations); }, diff --git a/client/app/bundles/course/user-invitations/components/tables/InvitationResultUsersTable.tsx b/client/app/bundles/course/user-invitations/components/tables/InvitationResultUsersTable.tsx index 1f0ff894d04..bf36b7a0694 100644 --- a/client/app/bundles/course/user-invitations/components/tables/InvitationResultUsersTable.tsx +++ b/client/app/bundles/course/user-invitations/components/tables/InvitationResultUsersTable.tsx @@ -1,5 +1,4 @@ import { FC, memo } from 'react'; -import { injectIntl, WrappedComponentProps } from 'react-intl'; import { Typography } from '@mui/material'; import equal from 'fast-deep-equal'; import { TableColumns, TableOptions } from 'types/components/DataTable'; @@ -7,15 +6,17 @@ import { CourseUserData } from 'types/course/courseUsers'; import DataTable from 'lib/components/core/layouts/DataTable'; import { COURSE_USER_ROLES } from 'lib/constants/sharedConstants'; +import useTranslation from 'lib/hooks/useTranslation'; import tableTranslations from 'lib/translations/table'; -interface Props extends WrappedComponentProps { +interface Props { title: JSX.Element; users: CourseUserData[]; } const InvitationResultUsersTable: FC = (props) => { - const { title, users, intl } = props; + const { title, users } = props; + const { t } = useTranslation(); if (users && users.length === 0) return null; @@ -42,7 +43,7 @@ const InvitationResultUsersTable: FC = (props) => { const columns: TableColumns[] = [ { name: 'id', - label: intl.formatMessage(tableTranslations.id), + label: t(tableTranslations.id), options: { display: false, filter: false, @@ -51,7 +52,7 @@ const InvitationResultUsersTable: FC = (props) => { }, { name: 'name', - label: intl.formatMessage(tableTranslations.name), + label: t(tableTranslations.name), options: { alignCenter: false, sort: false, @@ -59,7 +60,7 @@ const InvitationResultUsersTable: FC = (props) => { }, { name: 'email', - label: intl.formatMessage(tableTranslations.email), + label: t(tableTranslations.email), options: { alignCenter: false, sort: false, @@ -67,7 +68,7 @@ const InvitationResultUsersTable: FC = (props) => { }, { name: 'phantom', - label: intl.formatMessage(tableTranslations.phantom), + label: t(tableTranslations.phantom), options: { sort: false, customBodyRenderLite: (dataIndex): JSX.Element => { @@ -86,7 +87,7 @@ const InvitationResultUsersTable: FC = (props) => { }, { name: 'role', - label: intl.formatMessage(tableTranslations.role), + label: t(tableTranslations.role), options: { alignCenter: false, sort: false, @@ -119,7 +120,7 @@ const InvitationResultUsersTable: FC = (props) => { }; export default memo( - injectIntl(InvitationResultUsersTable), + InvitationResultUsersTable, (prevProps, nextProps) => { return equal(prevProps.users, nextProps.users); }, diff --git a/client/app/bundles/course/user-invitations/components/tables/UserInvitationsTable.tsx b/client/app/bundles/course/user-invitations/components/tables/UserInvitationsTable.tsx index d46b0e0d8ee..ff24448ed25 100644 --- a/client/app/bundles/course/user-invitations/components/tables/UserInvitationsTable.tsx +++ b/client/app/bundles/course/user-invitations/components/tables/UserInvitationsTable.tsx @@ -2,8 +2,6 @@ import { FC, memo, ReactElement } from 'react'; import { defineMessages, FormattedMessage, - injectIntl, - WrappedComponentProps, } from 'react-intl'; import { Typography } from '@mui/material'; import equal from 'fast-deep-equal'; @@ -21,13 +19,14 @@ import { } from 'lib/constants/sharedConstants'; import rebuildObjectFromRow from 'lib/helpers/mui-datatables-helpers'; import { useAppSelector } from 'lib/hooks/store'; +import useTranslation from 'lib/hooks/useTranslation'; import { formatLongDateTime } from 'lib/moment'; import tableTranslations from 'lib/translations/table'; import { getManageCourseUserPermissions } from '../../selectors'; import ResendInvitationsButton from '../buttons/ResendAllInvitationsButton'; -interface Props extends WrappedComponentProps { +interface Props { title: string; invitations: InvitationMiniEntity[]; pendingInvitations?: boolean; @@ -57,8 +56,8 @@ const UserInvitationsTable: FC = (props) => { pendingInvitations = false, acceptedInvitations = false, renderRowActionComponent = null, - intl, } = props; + const { t } = useTranslation(); const permissions = useAppSelector(getManageCourseUserPermissions); if (invitations && invitations.length === 0) { @@ -75,8 +74,8 @@ const UserInvitationsTable: FC = (props) => { } const invitationTypePrefix: string = pendingInvitations - ? intl.formatMessage(translations.pending) - : intl.formatMessage(translations.accepted); + ? t(translations.pending) + : t(translations.accepted); const options: TableOptions = { download: false, @@ -104,7 +103,7 @@ const UserInvitationsTable: FC = (props) => { const columns: TableColumns[] = [ { name: 'id', - label: intl.formatMessage(tableTranslations.id), + label: t(tableTranslations.id), options: { display: false, filter: false, @@ -113,7 +112,7 @@ const UserInvitationsTable: FC = (props) => { }, { name: 'name', - label: intl.formatMessage(tableTranslations.name), + label: t(tableTranslations.name), options: { alignCenter: false, customBodyRenderLite: (dataIndex): JSX.Element => { @@ -128,7 +127,7 @@ const UserInvitationsTable: FC = (props) => { }, { name: 'email', - label: intl.formatMessage(tableTranslations.email), + label: t(tableTranslations.email), options: { alignCenter: false, customBodyRenderLite: (dataIndex): JSX.Element => { @@ -143,7 +142,7 @@ const UserInvitationsTable: FC = (props) => { }, { name: 'role', - label: intl.formatMessage(tableTranslations.role), + label: t(tableTranslations.role), options: { alignCenter: false, customBodyRenderLite: (dataIndex): JSX.Element => { @@ -158,7 +157,7 @@ const UserInvitationsTable: FC = (props) => { }, { name: 'phantom', - label: intl.formatMessage(tableTranslations.phantom), + label: t(tableTranslations.phantom), options: { alignCenter: false, customBodyRenderLite: (dataIndex): JSX.Element => { @@ -173,7 +172,7 @@ const UserInvitationsTable: FC = (props) => { }, { name: 'invitationKey', - label: intl.formatMessage(tableTranslations.invitationCode), + label: t(tableTranslations.invitationCode), options: { alignCenter: false, customBodyRenderLite: (dataIndex): JSX.Element => { @@ -191,7 +190,7 @@ const UserInvitationsTable: FC = (props) => { if (pendingInvitations) { columns.push({ name: 'sentAt', - label: intl.formatMessage(tableTranslations.invitationSentAt), + label: t(tableTranslations.invitationSentAt), options: { alignCenter: false, customBodyRenderLite: (dataIndex): JSX.Element => { @@ -209,7 +208,7 @@ const UserInvitationsTable: FC = (props) => { if (permissions.canManagePersonalTimes) { columns.push({ name: 'timelineAlgorithm', - label: intl.formatMessage(tableTranslations.personalizedTimeline), + label: t(tableTranslations.personalizedTimeline), options: { alignCenter: false, customBodyRenderLite: (dataIndex): JSX.Element => { @@ -229,7 +228,7 @@ const UserInvitationsTable: FC = (props) => { if (acceptedInvitations) { columns.push({ name: 'confirmedAt', - label: intl.formatMessage(tableTranslations.invitationAcceptedAt), + label: t(tableTranslations.invitationAcceptedAt), options: { alignCenter: false, customBodyRenderLite: (dataIndex): JSX.Element => { @@ -247,7 +246,7 @@ const UserInvitationsTable: FC = (props) => { if (renderRowActionComponent) { columns.push({ name: 'actions', - label: intl.formatMessage(tableTranslations.actions), + label: t(tableTranslations.actions), options: { empty: true, sort: false, @@ -274,7 +273,7 @@ const UserInvitationsTable: FC = (props) => { }; export default memo( - injectIntl(UserInvitationsTable), + UserInvitationsTable, (prevProps, nextProps) => { return equal(prevProps.invitations, nextProps.invitations); }, diff --git a/client/app/bundles/course/users/components/buttons/UserManagementButtons.tsx b/client/app/bundles/course/users/components/buttons/UserManagementButtons.tsx index 1c367ffd674..501d754d871 100644 --- a/client/app/bundles/course/users/components/buttons/UserManagementButtons.tsx +++ b/client/app/bundles/course/users/components/buttons/UserManagementButtons.tsx @@ -1,5 +1,5 @@ import { FC, memo, useState } from 'react'; -import { defineMessages, injectIntl, WrappedComponentProps } from 'react-intl'; +import { defineMessages } from 'react-intl'; import equal from 'fast-deep-equal'; import { CourseUserMiniEntity } from 'types/course/courseUsers'; @@ -7,10 +7,11 @@ import DeleteButton from 'lib/components/core/buttons/DeleteButton'; import { COURSE_USER_ROLES } from 'lib/constants/sharedConstants'; import { useAppDispatch } from 'lib/hooks/store'; import toast from 'lib/hooks/toast'; +import useTranslation from 'lib/hooks/useTranslation'; import { deleteUser } from '../../operations'; -interface Props extends WrappedComponentProps { +interface Props { user: CourseUserMiniEntity; disabled?: boolean; } @@ -37,7 +38,8 @@ const translations = defineMessages({ }); const UserManagementButtons: FC = (props) => { - const { intl, user } = props; + const { user } = props; + const { t } = useTranslation(); const dispatch = useAppDispatch(); const [isDeleting, setIsDeleting] = useState(false); @@ -52,7 +54,7 @@ const UserManagementButtons: FC = (props) => { return dispatch(deleteUser(user.id)) .then(() => { toast.success( - intl.formatMessage( + t( translations.deletionScheduled, userTranslationDict, ), @@ -63,7 +65,7 @@ const UserManagementButtons: FC = (props) => { }) .catch((error) => { toast.error( - intl.formatMessage(translations.deletionFailure, userTranslationDict), + t(translations.deletionFailure, userTranslationDict), ); throw error; }) @@ -74,7 +76,7 @@ const UserManagementButtons: FC = (props) => {
= (props) => { ); }; -export default memo(injectIntl(UserManagementButtons), equal); +export default memo(UserManagementButtons, equal); diff --git a/client/app/bundles/course/users/components/misc/UserProfileCard.tsx b/client/app/bundles/course/users/components/misc/UserProfileCard.tsx index 874cc8709b2..4be0e5b74bd 100644 --- a/client/app/bundles/course/users/components/misc/UserProfileCard.tsx +++ b/client/app/bundles/course/users/components/misc/UserProfileCard.tsx @@ -1,16 +1,17 @@ import { FC, MouseEvent } from 'react'; -import { defineMessages, injectIntl, WrappedComponentProps } from 'react-intl'; +import { defineMessages } from 'react-intl'; import { scroller } from 'react-scroll'; import { Avatar, Card, CardContent, Grid, Typography } from '@mui/material'; import { CourseUserEntity } from 'types/course/courseUsers'; import Link from 'lib/components/core/Link'; import { COURSE_USER_ROLES } from 'lib/constants/sharedConstants'; +import useTranslation from 'lib/hooks/useTranslation'; import UserProfileCardStats from './UserProfileCardStats'; import styles from './UserProfileCard.scss'; -interface Props extends WrappedComponentProps { +interface Props { user: CourseUserEntity; } @@ -29,7 +30,8 @@ const translations = defineMessages({ }, }); -const UserProfileCard: FC = ({ user, intl }) => { +const UserProfileCard: FC = ({ user }) => { + const { t } = useTranslation(); const handleScrollToAchievements = (e: MouseEvent): void => { e.preventDefault(); scroller.scrollTo('user-profile-achievements', { @@ -51,7 +53,7 @@ const UserProfileCard: FC = ({ user, intl }) => { {user.level >= 0 && ( )} @@ -59,7 +61,7 @@ const UserProfileCard: FC = ({ user, intl }) => { @@ -71,7 +73,7 @@ const UserProfileCard: FC = ({ user, intl }) => { > @@ -122,4 +124,4 @@ const UserProfileCard: FC = ({ user, intl }) => { ); }; -export default injectIntl(UserProfileCard); +export default UserProfileCard; diff --git a/client/app/bundles/users/components/tables/CoursesTable.tsx b/client/app/bundles/users/components/tables/CoursesTable.tsx index f4c3e24ca9e..535b9bdd03d 100644 --- a/client/app/bundles/users/components/tables/CoursesTable.tsx +++ b/client/app/bundles/users/components/tables/CoursesTable.tsx @@ -1,5 +1,4 @@ import { FC } from 'react'; -import { injectIntl, WrappedComponentProps } from 'react-intl'; import { Box, Table, @@ -13,15 +12,17 @@ import { UserCourseMiniEntity } from 'types/users'; import Link from 'lib/components/core/Link'; import { COURSE_USER_ROLES } from 'lib/constants/sharedConstants'; +import useTranslation from 'lib/hooks/useTranslation'; import { formatLongDateTime } from 'lib/moment'; import tableTranslations from 'lib/translations/table'; -interface Props extends WrappedComponentProps { +interface Props { title: string; courses: UserCourseMiniEntity[]; } -const CoursesTable: FC = ({ title, courses, intl }: Props) => { +const CoursesTable: FC = ({ title, courses }: Props) => { + const { t } = useTranslation(); return ( {title} @@ -29,18 +30,18 @@ const CoursesTable: FC = ({ title, courses, intl }: Props) => { - {intl.formatMessage(tableTranslations.enrolledAt)} + {t(tableTranslations.enrolledAt)} - {intl.formatMessage(tableTranslations.course)} + {t(tableTranslations.course)} - {intl.formatMessage(tableTranslations.name)} - {intl.formatMessage(tableTranslations.role)} + {t(tableTranslations.name)} + {t(tableTranslations.role)} - {intl.formatMessage(tableTranslations.level)} + {t(tableTranslations.level)} - {intl.formatMessage(tableTranslations.achievements)} + {t(tableTranslations.achievements)} @@ -87,4 +88,4 @@ const CoursesTable: FC = ({ title, courses, intl }: Props) => { ); }; -export default injectIntl(CoursesTable); +export default CoursesTable;