refactor: replacing injectIntl with useIntl part 1 (#2296)

This commit is contained in:
Jacobo Dominguez
2025-07-18 15:21:26 -06:00
committed by GitHub
parent 654daa58ee
commit cbec6505f5
14 changed files with 109 additions and 123 deletions

View File

@@ -1,6 +1,6 @@
import React from 'react';
import PropTypes from 'prop-types';
import { injectIntl, FormattedMessage } from '@edx/frontend-platform/i18n';
import { FormattedMessage } from '@edx/frontend-platform/i18n';
import messages from './messages';
@@ -33,4 +33,4 @@ AriaLiveRegion.propTypes = {
enableQuality: PropTypes.bool.isRequired,
};
export default injectIntl(AriaLiveRegion);
export default AriaLiveRegion;

View File

@@ -1,8 +1,6 @@
import React from 'react';
import PropTypes from 'prop-types';
import { injectIntl } from '@edx/frontend-platform/i18n';
import { Container, Stack } from '@openedx/paragon';
import { LoadingSpinner } from '../../generic/Loading';
import { getCompletionCount, useChecklistState } from './hooks';
import ChecklistItemBody from './ChecklistItemBody';
@@ -129,4 +127,4 @@ ChecklistSection.propTypes = {
isLoading: PropTypes.bool.isRequired,
};
export default injectIntl(ChecklistSection);
export default ChecklistSection;

View File

@@ -1,7 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { injectIntl, FormattedMessage, intlShape } from '@edx/frontend-platform/i18n';
import { FormattedMessage, useIntl } from '@edx/frontend-platform/i18n';
import { Form, Hyperlink } from '@openedx/paragon';
import SettingsOption from '../SettingsOption';
import { ShowAnswerTypes, ShowAnswerTypesKeys } from '../../../../../../data/constants/problem';
@@ -13,13 +13,12 @@ const ShowAnswerCard = ({
showAnswer,
updateSettings,
defaultValue,
// inject
intl,
// redux
studioEndpointUrl,
learningContextId,
isLibrary,
}) => {
const intl = useIntl();
const {
handleShowAnswerChange,
handleAttemptsChange,
@@ -90,7 +89,6 @@ const ShowAnswerCard = ({
};
ShowAnswerCard.propTypes = {
intl: intlShape.isRequired,
// eslint-disable-next-line
showAnswer: PropTypes.any.isRequired,
solutionExplanation: PropTypes.string,
@@ -115,4 +113,4 @@ export const mapStateToProps = (state) => ({
export const mapDispatchToProps = {};
export const ShowAnswerCardInternal = ShowAnswerCard; // For testing only
export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(ShowAnswerCard));
export default connect(mapStateToProps, mapDispatchToProps)(ShowAnswerCard);

View File

@@ -2,7 +2,6 @@ import React from 'react';
import {
render, screen, initializeMocks,
} from '@src/testUtils';
import { formatMessage } from '@src/editors/testUtils';
import { selectors } from '../../../../../../data/redux';
import { ShowAnswerCardInternal as ShowAnswerCard, mapStateToProps, mapDispatchToProps } from './ShowAnswerCard';
import * as hooks from '../hooks';
@@ -25,15 +24,12 @@ describe('ShowAnswerCard', () => {
on: 'after_attempts',
afterAttempts: 5,
updateSettings: jest.fn().mockName('args.updateSettings'),
intl: { formatMessage },
};
const props = {
showAnswer,
defaultValue: 'finished',
updateSettings: jest.fn(),
// injected
intl: { formatMessage },
// redux
studioEndpointUrl: 'SoMEeNDpOinT',
learningContextId: 'sOMEcouRseId',

View File

@@ -2,7 +2,7 @@ import React from 'react';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import { FormattedMessage, injectIntl } from '@edx/frontend-platform/i18n';
import { FormattedMessage } from '@edx/frontend-platform/i18n';
import {
ActionRow,
Button,
@@ -58,4 +58,4 @@ export const mapDispatchToProps = {
};
export const ImportTranscriptCardInternal = ImportTranscriptCard; // For testing only
export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(ImportTranscriptCard));
export default connect(mapStateToProps, mapDispatchToProps)(ImportTranscriptCard);

View File

@@ -15,7 +15,7 @@ import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import { Spinner } from '@openedx/paragon';
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import { useIntl } from '@edx/frontend-platform/i18n';
import EditorContainer from '../EditorContainer';
// This 'module' self-import hack enables mocking during tests.
@@ -32,48 +32,51 @@ export const hooks = {
}),
};
export const thumbEditor = ({
onClose,
// redux
blockValue,
lmsEndpointUrl,
blockFailed,
blockFinished,
initializeEditor,
// inject
intl,
}) => (
<EditorContainer
getContent={module.hooks.getContent}
onClose={onClose}
>
<div className="editor-body h-75 overflow-auto">
{!blockFinished
? (
<div className="text-center p-6">
<Spinner
animation="border"
className="m-3"
// Use a messages.js file for intl messages.
screenreadertext={intl.formatMessage('Loading Spinner')}
/>
</div>
)
: (
<p>
Your Editor Goes here.
You can get at the xblock data with the blockValue field.
here is what is in your xblock: {JSON.stringify(blockValue)}
</p>
)}
</div>
</EditorContainer>
);
thumbEditor.defaultProps = {
export const ThumbEditor = (
{
onClose,
// redux
blockValue,
lmsEndpointUrl,
blockFailed,
blockFinished,
initializeEditor,
},
) => {
const intl = useIntl();
return (
<EditorContainer
getContent={module.hooks.getContent}
onClose={onClose}
>
<div className="editor-body h-75 overflow-auto">
{!blockFinished
? (
<div className="text-center p-6">
<Spinner
animation="border"
className="m-3"
// Use a messages.js file for intl messages.
screenreadertext={intl.formatMessage('Loading Spinner')}
/>
</div>
)
: (
<p>
Your Editor Goes here.
You can get at the xblock data with the blockValue field.
here is what is in your xblock: {JSON.stringify(blockValue)}
</p>
)}
</div>
</EditorContainer>
);
};
ThumbEditor.defaultProps = {
blockValue: null,
lmsEndpointUrl: null,
};
thumbEditor.propTypes = {
ThumbEditor.propTypes = {
onClose: PropTypes.func.isRequired,
// redux
blockValue: PropTypes.shape({
@@ -83,8 +86,6 @@ thumbEditor.propTypes = {
blockFailed: PropTypes.bool.isRequired,
blockFinished: PropTypes.bool.isRequired,
initializeEditor: PropTypes.func.isRequired,
// inject
intl: intlShape.isRequired,
};
export const mapStateToProps = (state) => ({
@@ -98,4 +99,4 @@ export const mapDispatchToProps = {
initializeEditor: actions.app.initializeEditor,
};
export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(thumbEditor));
export default connect(mapStateToProps, mapDispatchToProps)(ThumbEditor);

View File

@@ -3,8 +3,7 @@ import PropTypes from 'prop-types';
import {
Button, Container, Row, Col,
} from '@openedx/paragon';
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import { useIntl } from '@edx/frontend-platform/i18n';
import messages from './messages';
import { isLibraryV1Key } from '../../../generic/key-utils';
import { navigateTo } from '../../hooks';
@@ -20,9 +19,8 @@ const ErrorPage = ({
learningContextId,
// redux
unitData,
// injected
intl,
}) => {
const intl = useIntl();
const outlineType = isLibraryV1Key(learningContextId) ? 'library' : 'course';
const outlineUrl = `${studioEndpointUrl}/${outlineType}/${learningContextId}`;
const unitUrl = unitData?.data ? `${studioEndpointUrl}/container/${unitData?.data.ancestors[0].id}` : null;
@@ -73,8 +71,6 @@ ErrorPage.propTypes = {
),
}),
}),
// injected
intl: intlShape.isRequired,
};
ErrorPage.defaultProps = {
@@ -87,4 +83,4 @@ export const mapStateToProps = (state) => ({
});
export const ErrorPageInternal = ErrorPage; // For testing only
export default injectIntl(connect(mapStateToProps)(ErrorPage));
export default connect(mapStateToProps)(ErrorPage);

View File

@@ -1,6 +1,5 @@
import React from 'react';
import { render, screen, initializeMocks } from '@src/testUtils';
import { formatMessage } from '../../testUtils';
import { ErrorPageInternal as ErrorPage } from './ErrorPage';
jest.mock('../../data/redux', () => ({
@@ -15,13 +14,11 @@ describe('Editor Page', () => {
const emptyProps = {
learningContextId: 'course-v1:edX+DemoX+Demo_Course',
studioEndpointUrl: 'fakeurl.com',
intl: { formatMessage },
};
const passedProps = {
learningContextId: 'course-v1:edX+DemoX+Demo_Course',
studioEndpointUrl: 'fakeurl.com',
message: 'cUStomMEssagE',
intl: { formatMessage },
};
const unitData = {
data: {

View File

@@ -2,14 +2,11 @@ import React from 'react';
import { PropTypes } from 'prop-types';
import { Icon, OverlayTrigger, Tooltip } from '@openedx/paragon';
import { Locked, LockOpen } from '@openedx/paragon/icons';
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import { useIntl } from '@edx/frontend-platform/i18n';
import messages from '../../messages';
const AccessColumn = ({
row,
// injected
intl,
}) => {
const AccessColumn = ({ row }) => {
const intl = useIntl();
const { locked } = row.original;
return (
<OverlayTrigger
@@ -35,8 +32,6 @@ AccessColumn.propTypes = {
locked: PropTypes.bool.isRequired,
}.isRequired,
}.isRequired,
// injected
intl: intlShape.isRequired,
};
export default injectIntl(AccessColumn);
export default AccessColumn;

View File

@@ -1,6 +1,6 @@
import React, { useState } from 'react';
import PropTypes from 'prop-types';
import { FormattedMessage, injectIntl } from '@edx/frontend-platform/i18n';
import { FormattedMessage } from '@edx/frontend-platform/i18n';
import {
Button,
Icon,
@@ -82,4 +82,4 @@ TranscriptActionMenu.propTypes = {
}).isRequired,
};
export default injectIntl(TranscriptActionMenu);
export default TranscriptActionMenu;

View File

@@ -2,13 +2,18 @@ import React, { useState } from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import { Form } from '@openedx/paragon';
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import { useIntl } from '@edx/frontend-platform/i18n';
import messages from './messages';
const CreditSection = ({
intl, eligibleGrade, setShowSavePrompt, minimumGradeCredit, setGradingData, setShowSuccessAlert,
eligibleGrade,
setShowSavePrompt,
minimumGradeCredit,
setGradingData,
setShowSuccessAlert,
}) => {
const intl = useIntl();
const [errorEffort, setErrorEffort] = useState(false);
const handleCreditChange = (e) => {
@@ -60,7 +65,6 @@ const CreditSection = ({
};
CreditSection.propTypes = {
intl: intlShape.isRequired,
eligibleGrade: PropTypes.number.isRequired,
setShowSavePrompt: PropTypes.func.isRequired,
setGradingData: PropTypes.func.isRequired,
@@ -68,4 +72,4 @@ CreditSection.propTypes = {
minimumGradeCredit: PropTypes.number.isRequired,
};
export default injectIntl(CreditSection);
export default CreditSection;

View File

@@ -1,21 +1,20 @@
import React from 'react';
import { Helmet } from 'react-helmet';
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import { useIntl } from '@edx/frontend-platform/i18n';
import { getConfig } from '@edx/frontend-platform';
import messages from './messages';
const Head = ({ intl }) => (
<Helmet>
<title>
{intl.formatMessage(messages['course-authoring.page.title'], { siteName: getConfig().SITE_NAME })}
</title>
<link rel="shortcut icon" href={getConfig().FAVICON_URL} type="image/x-icon" />
</Helmet>
);
Head.propTypes = {
intl: intlShape.isRequired,
const Head = () => {
const intl = useIntl();
return (
<Helmet>
<title>
{intl.formatMessage(messages['course-authoring.page.title'], { siteName: getConfig().SITE_NAME })}
</title>
<link rel="shortcut icon" href={getConfig().FAVICON_URL} type="image/x-icon" />
</Helmet>
);
};
export default injectIntl(Head);
export default Head;

View File

@@ -1,40 +1,42 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Collapsible } from '@openedx/paragon';
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import { useIntl } from '@edx/frontend-platform/i18n';
import SupportedFeature from './SupportedFeature';
import messages from './messages';
const FeaturesList = ({ app, intl }) => (
<Collapsible
onClick={(event) => event.stopPropagation()}
title={(
<>
<Collapsible.Visible whenClosed>
{intl.formatMessage(messages['supportedFeatureList-mobile-show'])}
</Collapsible.Visible>
<Collapsible.Visible whenOpen>
{intl.formatMessage(messages['supportedFeatureList-mobile-hide'])}
</Collapsible.Visible>
</>
)}
styling="basic"
>
{app.featureIds.map((id) => (
<div key={`collapsible-${app.id}&${id}`} className="d-flex mb-1">
<SupportedFeature name={intl.formatMessage(messages[`featureName-${id}`])} />
</div>
))}
</Collapsible>
);
const FeaturesList = ({ app }) => {
const intl = useIntl();
return (
<Collapsible
onClick={(event) => event.stopPropagation()}
title={(
<>
<Collapsible.Visible whenClosed>
{intl.formatMessage(messages['supportedFeatureList-mobile-show'])}
</Collapsible.Visible>
<Collapsible.Visible whenOpen>
{intl.formatMessage(messages['supportedFeatureList-mobile-hide'])}
</Collapsible.Visible>
</>
)}
styling="basic"
>
{app.featureIds.map((id) => (
<div key={`collapsible-${app.id}&${id}`} className="d-flex mb-1">
<SupportedFeature name={intl.formatMessage(messages[`featureName-${id}`])} />
</div>
))}
</Collapsible>
);
};
export default injectIntl(FeaturesList);
export default FeaturesList;
FeaturesList.propTypes = {
app: PropTypes.shape({
id: PropTypes.string.isRequired,
featureIds: PropTypes.shape([]).isRequired,
}).isRequired,
intl: intlShape.isRequired,
};

View File

@@ -84,7 +84,7 @@ export const generateProvidersApiResponse = (piazzaAdminOnlyConfig = false, acti
'discussion-page',
'embedded-course-sections',
'wcag-2.1',
'lti',
'lti-advanced-sharing-mode',
],
external_links: {
learn_more: '',