refactor: Replace of injectIntl with useIntl() part 8 #2288 (#2357)

Co-authored-by: Ahtesham Quraish <ahtesham.quraish@192.168.1.4>
This commit is contained in:
Ahtesham Quraish
2025-08-20 23:07:24 +05:00
committed by GitHub
parent 33c445ebc2
commit 87af7e8973
14 changed files with 143 additions and 170 deletions

View File

@@ -1,7 +1,7 @@
import React, { useEffect } from 'react';
import PropTypes from 'prop-types';
import { getConfig } from '@edx/frontend-platform';
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import { useIntl } from '@edx/frontend-platform/i18n';
import { Helmet } from 'react-helmet';
import { useDispatch, useSelector } from 'react-redux';
import { Container, Stack } from '@openedx/paragon';
@@ -17,9 +17,8 @@ import ConnectionErrorAlert from '../generic/ConnectionErrorAlert';
const CourseChecklist = ({
courseId,
// injected,
intl,
}) => {
const intl = useIntl();
const dispatch = useDispatch();
const courseDetails = useModel('courseDetails', courseId);
const enableQuality = getConfig().ENABLE_CHECKLIST_QUALITY === 'true';
@@ -97,8 +96,6 @@ const CourseChecklist = ({
CourseChecklist.propTypes = {
courseId: PropTypes.string.isRequired,
// injected
intl: intlShape.isRequired,
};
export default injectIntl(CourseChecklist);
export default CourseChecklist;

View File

@@ -1,5 +1,5 @@
import React from 'react';
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import { useIntl } from '@edx/frontend-platform/i18n';
import { Form } from '@openedx/paragon';
import PropTypes from 'prop-types';
import SettingsOption from '../../SettingsOption';
@@ -11,9 +11,8 @@ export const RandomizationCard = ({
randomization,
defaultValue,
updateSettings,
// inject
intl,
}) => {
const intl = useIntl();
const curretRandomization = randomization || defaultValue;
const { summary, handleChange } = useRandomizationSettingStatus({
randomization: curretRandomization,
@@ -56,7 +55,6 @@ RandomizationCard.propTypes = {
defaultValue: PropTypes.string.isRequired,
randomization: PropTypes.string.isRequired,
updateSettings: PropTypes.func.isRequired,
intl: intlShape.isRequired,
};
export default injectIntl(RandomizationCard);
export default RandomizationCard;

View File

@@ -2,7 +2,6 @@ import React from 'react';
import {
render, screen, initializeMocks, fireEvent,
} from '@src/testUtils';
import { formatMessage } from '@src/editors/testUtils';
import { RandomizationCard } from './index';
import * as hooks from './hooks';
@@ -11,11 +10,10 @@ describe('RandomizationCard', () => {
randomization: 'per_student',
defaultValue: 'always',
updateSettings: jest.fn().mockName('args.updateSettings'),
intl: { formatMessage },
};
const randomizationCardHooksProps = {
summary: { message: { defaultMessage: 'sUmmary' } },
summary: { message: { id: 'defaultMessage', defaultMessage: 'sUmmary' } },
handleChange: jest.fn().mockName('randomizationCardHooks.handleChange'),
};

View File

@@ -3,7 +3,7 @@ import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import { Col, Form } from '@openedx/paragon';
import { injectIntl, intlShape, FormattedMessage } from '@edx/frontend-platform/i18n';
import { FormattedMessage, useIntl } from '@edx/frontend-platform/i18n';
import { actions, selectors } from '../../../../../../data/redux';
import { keyStore } from '../../../../../../utils';
@@ -21,9 +21,8 @@ const DurationWidget = ({
// redux
duration,
updateField,
// injected
intl,
}) => {
const intl = useIntl();
const {
unsavedDuration,
onBlur,
@@ -88,8 +87,6 @@ DurationWidget.propTypes = {
// redux
duration: PropTypes.objectOf(PropTypes.number).isRequired,
updateField: PropTypes.func.isRequired,
// injected
intl: intlShape.isRequired,
};
export const mapStateToProps = (state) => ({
@@ -101,4 +98,4 @@ export const mapDispatchToProps = {
};
export const DurationWidgetInternal = DurationWidget; // For testing only
export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(DurationWidget));
export default connect(mapStateToProps, mapDispatchToProps)(DurationWidget);

View File

@@ -3,8 +3,7 @@ import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import {
FormattedMessage,
injectIntl,
intlShape,
useIntl,
} from '@edx/frontend-platform/i18n';
import {
Hyperlink,
@@ -20,8 +19,6 @@ import * as hooks from './hooks';
* Collapsible Form widget controlling video thumbnail
*/
const SocialShareWidget = ({
// injected
intl,
// redux
allowVideoSharing,
isLibrary,
@@ -30,6 +27,7 @@ const SocialShareWidget = ({
videoSharingLearnMoreLink,
updateField,
}) => {
const intl = useIntl();
const isSetByCourse = allowVideoSharing.level === 'course';
const videoSharingEnabled = isLibrary ? videoSharingEnabledForAll : videoSharingEnabledForCourse;
const learnMoreLink = videoSharingLearnMoreLink || 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html';
@@ -90,8 +88,6 @@ SocialShareWidget.defaultProps = {
};
SocialShareWidget.propTypes = {
// injected
intl: intlShape.isRequired,
// redux
allowVideoSharing: PropTypes.shape({
level: PropTypes.string.isRequired,
@@ -117,4 +113,4 @@ export const mapDispatchToProps = (dispatch) => ({
});
export const SocialShareWidgetInternal = SocialShareWidget; // For testing only
export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(SocialShareWidget));
export default connect(mapStateToProps, mapDispatchToProps)(SocialShareWidget);

View File

@@ -5,7 +5,7 @@ import {
Button,
} from '@openedx/paragon';
import { FormattedMessage, injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import { FormattedMessage, useIntl } from '@edx/frontend-platform/i18n';
import messages from './messages';
import './index.scss';
@@ -15,9 +15,8 @@ const CodeEditor = ({
innerRef,
value,
lang,
// injected
intl,
}) => {
const intl = useIntl();
const DOMref = useRef();
const btnRef = useRef();
hooks.createCodeMirrorDomNode({
@@ -49,9 +48,8 @@ CodeEditor.propTypes = {
PropTypes.shape({ current: PropTypes.any }),
]).isRequired,
value: PropTypes.string.isRequired,
intl: intlShape.isRequired,
lang: PropTypes.string.isRequired,
};
export const CodeEditorInternal = CodeEditor; // For testing only
export default injectIntl(CodeEditor);
export default CodeEditor;

View File

@@ -1,49 +1,45 @@
import React from 'react';
import {
injectIntl,
intlShape,
} from '@edx/frontend-platform/i18n';
import { useIntl } from '@edx/frontend-platform/i18n';
import { Layout } from '@openedx/paragon';
import messages from './messages';
const ExportFooter = ({ intl }) => (
<footer className="mt-4 small">
<Layout
lg={[{ span: 5 }, { span: 2 }, { span: 5 }]}
md={[{ span: 5 }, { span: 2 }, { span: 5 }]}
sm={[{ span: 5 }, { span: 2 }, { span: 5 }]}
xs={[{ span: 5 }, { span: 2 }, { span: 5 }]}
xl={[{ span: 5 }, { span: 2 }, { span: 5 }]}
>
<Layout.Element>
<h4>{intl.formatMessage(messages.exportedDataTitle)}</h4>
<ul className="export-footer-list">
<li>{intl.formatMessage(messages.exportedDataItem1)}</li>
<li>{intl.formatMessage(messages.exportedDataItem2)}</li>
<li>{intl.formatMessage(messages.exportedDataItem3)}</li>
<li>{intl.formatMessage(messages.exportedDataItem4)}</li>
<li>{intl.formatMessage(messages.exportedDataItem5)}</li>
<li>{intl.formatMessage(messages.exportedDataItem6)}</li>
<li>{intl.formatMessage(messages.exportedDataItem7)}</li>
</ul>
</Layout.Element>
<Layout.Element />
<Layout.Element>
<h4>{intl.formatMessage(messages.notExportedDataTitle)}</h4>
<ul className="export-footer-list">
<li>{intl.formatMessage(messages.notExportedDataItem1)}</li>
<li>{intl.formatMessage(messages.notExportedDataItem2)}</li>
<li>{intl.formatMessage(messages.notExportedDataItem3)}</li>
<li>{intl.formatMessage(messages.notExportedDataItem4)}</li>
</ul>
</Layout.Element>
</Layout>
</footer>
);
ExportFooter.propTypes = {
intl: intlShape.isRequired,
const ExportFooter = () => {
const intl = useIntl();
return (
<footer className="mt-4 small">
<Layout
lg={[{ span: 5 }, { span: 2 }, { span: 5 }]}
md={[{ span: 5 }, { span: 2 }, { span: 5 }]}
sm={[{ span: 5 }, { span: 2 }, { span: 5 }]}
xs={[{ span: 5 }, { span: 2 }, { span: 5 }]}
xl={[{ span: 5 }, { span: 2 }, { span: 5 }]}
>
<Layout.Element>
<h4>{intl.formatMessage(messages.exportedDataTitle)}</h4>
<ul className="export-footer-list">
<li>{intl.formatMessage(messages.exportedDataItem1)}</li>
<li>{intl.formatMessage(messages.exportedDataItem2)}</li>
<li>{intl.formatMessage(messages.exportedDataItem3)}</li>
<li>{intl.formatMessage(messages.exportedDataItem4)}</li>
<li>{intl.formatMessage(messages.exportedDataItem5)}</li>
<li>{intl.formatMessage(messages.exportedDataItem6)}</li>
<li>{intl.formatMessage(messages.exportedDataItem7)}</li>
</ul>
</Layout.Element>
<Layout.Element />
<Layout.Element>
<h4>{intl.formatMessage(messages.notExportedDataTitle)}</h4>
<ul className="export-footer-list">
<li>{intl.formatMessage(messages.notExportedDataItem1)}</li>
<li>{intl.formatMessage(messages.notExportedDataItem2)}</li>
<li>{intl.formatMessage(messages.notExportedDataItem3)}</li>
<li>{intl.formatMessage(messages.notExportedDataItem4)}</li>
</ul>
</Layout.Element>
</Layout>
</footer>
);
};
export default injectIntl(ExportFooter);
export default ExportFooter;

View File

@@ -1,6 +1,6 @@
import React from 'react';
import PropTypes from 'prop-types';
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import { useIntl } from '@edx/frontend-platform/i18n';
import {
Dropdown,
IconButton,
@@ -19,58 +19,59 @@ const FileMenu = ({
portableUrl,
id,
fileType,
// injected
intl,
}) => (
<Dropdown data-testid={`file-menu-dropdown-${id}`}>
<Dropdown.Toggle
id={`file-menu-dropdown-${id}`}
as={IconButton}
src={MoreHoriz}
iconAs={Icon}
variant="primary"
alt="file-menu-toggle"
/>
<Dropdown.Menu>
{fileType === 'video' ? (
<Dropdown.Item
onClick={() => navigator.clipboard.writeText(id)}
>
{intl.formatMessage(messages.copyVideoIdTitle)}
}) => {
const intl = useIntl();
return (
<Dropdown data-testid={`file-menu-dropdown-${id}`}>
<Dropdown.Toggle
id={`file-menu-dropdown-${id}`}
as={IconButton}
src={MoreHoriz}
iconAs={Icon}
variant="primary"
alt="file-menu-toggle"
/>
<Dropdown.Menu>
{fileType === 'video' ? (
<Dropdown.Item
onClick={() => navigator.clipboard.writeText(id)}
>
{intl.formatMessage(messages.copyVideoIdTitle)}
</Dropdown.Item>
) : (
<>
<Dropdown.Item
onClick={/* istanbul ignore next */() => navigator.clipboard.writeText(portableUrl)}
>
{intl.formatMessage(messages.copyStudioUrlTitle)}
</Dropdown.Item>
<Dropdown.Item
onClick={/* istanbul ignore next */ () => navigator.clipboard.writeText(externalUrl)}
>
{intl.formatMessage(messages.copyWebUrlTitle)}
</Dropdown.Item>
<Dropdown.Item onClick={handleLock}>
{locked ? intl.formatMessage(messages.unlockMenuTitle) : intl.formatMessage(messages.lockMenuTitle)}
</Dropdown.Item>
</>
)}
<Dropdown.Item onClick={onDownload}>
{intl.formatMessage(messages.downloadTitle)}
</Dropdown.Item>
) : (
<>
<Dropdown.Item
onClick={() => navigator.clipboard.writeText(portableUrl)}
>
{intl.formatMessage(messages.copyStudioUrlTitle)}
</Dropdown.Item>
<Dropdown.Item
onClick={() => navigator.clipboard.writeText(externalUrl)}
>
{intl.formatMessage(messages.copyWebUrlTitle)}
</Dropdown.Item>
<Dropdown.Item onClick={handleLock}>
{locked ? intl.formatMessage(messages.unlockMenuTitle) : intl.formatMessage(messages.lockMenuTitle)}
</Dropdown.Item>
</>
)}
<Dropdown.Item onClick={onDownload}>
{intl.formatMessage(messages.downloadTitle)}
</Dropdown.Item>
<Dropdown.Item onClick={openAssetInfo}>
{intl.formatMessage(messages.infoTitle)}
</Dropdown.Item>
<Dropdown.Divider />
<Dropdown.Item
data-testid="open-delete-confirmation-button"
onClick={openDeleteConfirmation}
>
{intl.formatMessage(messages.deleteTitle)}
</Dropdown.Item>
</Dropdown.Menu>
</Dropdown>
);
<Dropdown.Item onClick={openAssetInfo}>
{intl.formatMessage(messages.infoTitle)}
</Dropdown.Item>
<Dropdown.Divider />
<Dropdown.Item
data-testid="open-delete-confirmation-button"
onClick={openDeleteConfirmation}
>
{intl.formatMessage(messages.deleteTitle)}
</Dropdown.Item>
</Dropdown.Menu>
</Dropdown>
);
};
FileMenu.propTypes = {
externalUrl: PropTypes.string,
@@ -82,8 +83,6 @@ FileMenu.propTypes = {
portableUrl: PropTypes.string,
id: PropTypes.string.isRequired,
fileType: PropTypes.string.isRequired,
// injected
intl: intlShape.isRequired,
};
FileMenu.defaultProps = {
@@ -93,4 +92,4 @@ FileMenu.defaultProps = {
portableUrl: null,
};
export default injectIntl(FileMenu);
export default FileMenu;

View File

@@ -1,4 +1,4 @@
import { injectIntl, intlShape, FormattedMessage } from '@edx/frontend-platform/i18n';
import { FormattedMessage, useIntl } from '@edx/frontend-platform/i18n';
import { getConfig } from '@edx/frontend-platform';
import PropTypes from 'prop-types';
import {
@@ -16,9 +16,8 @@ const UsageMetricsMessage = ({
usagePathStatus,
usageLocations,
error,
// injected
intl,
}) => {
const intl = useIntl();
let usageMessage;
if (usagePathStatus === RequestStatus.SUCCESSFUL) {
usageMessage = isEmpty(usageLocations) ? (
@@ -65,8 +64,6 @@ UsageMetricsMessage.propTypes = {
usagePathStatus: PropTypes.string.isRequired,
usageLocations: PropTypes.arrayOf(PropTypes.string).isRequired,
error: PropTypes.arrayOf(PropTypes.string).isRequired,
// injected
intl: intlShape.isRequired,
};
export default injectIntl(UsageMetricsMessage);
export default UsageMetricsMessage;

View File

@@ -1,28 +1,27 @@
import React from 'react';
import { injectIntl, intlShape, FormattedMessage } from '@edx/frontend-platform/i18n';
import { FormattedMessage, useIntl } from '@edx/frontend-platform/i18n';
import { Alert } from '@openedx/paragon';
import { getConfig } from '@edx/frontend-platform';
import messages from '../messages';
const SaveFormConnectionErrorAlert = ({ intl }) => (
<Alert variant="danger" data-testid="connectionErrorAlert">
<FormattedMessage
id="authoring.alert.save.error.connection"
defaultMessage="We encountered a technical error when applying changes. This might be a temporary issue, so please try again in a few minutes. If the problem persists, please go to the {supportLink} for help."
values={{
supportLink: (
<Alert.Link href={getConfig().SUPPORT_URL}>
{intl.formatMessage(messages.supportText)}
</Alert.Link>
),
}}
/>
</Alert>
);
SaveFormConnectionErrorAlert.propTypes = {
intl: intlShape.isRequired,
const SaveFormConnectionErrorAlert = () => {
const intl = useIntl();
return (
<Alert variant="danger" data-testid="connectionErrorAlert">
<FormattedMessage
id="authoring.alert.save.error.connection"
defaultMessage="We encountered a technical error when applying changes. This might be a temporary issue, so please try again in a few minutes. If the problem persists, please go to the {supportLink} for help."
values={{
supportLink: (
<Alert.Link href={getConfig().SUPPORT_URL}>
{intl.formatMessage(messages.supportText)}
</Alert.Link>
),
}}
/>
</Alert>
);
};
export default injectIntl(SaveFormConnectionErrorAlert);
export default SaveFormConnectionErrorAlert;

View File

@@ -1,7 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Alert, Form } from '@openedx/paragon';
import { FormattedMessage, injectIntl, useIntl } from '@edx/frontend-platform/i18n';
import { FormattedMessage, useIntl } from '@edx/frontend-platform/i18n';
import messages from './messages';
import { COURSE_BLOCK_NAMES } from '../../constants';
@@ -146,4 +146,4 @@ VisibilityTab.defaultProps = {
isSelfPaced: false,
};
export default injectIntl(VisibilityTab);
export default VisibilityTab;

View File

@@ -2,7 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import { useSelector } from 'react-redux';
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import { useIntl } from '@edx/frontend-platform/i18n';
import Responsive from 'react-responsive';
import {
Card, CheckboxControl, breakpoints,
@@ -12,8 +12,9 @@ import appMessages from '../app-config-form/messages';
import FeaturesList from './FeaturesList';
const AppCard = ({
app, onClick, intl, selected, features,
app, onClick, selected, features,
}) => {
const intl = useIntl();
const { canChangeProviders } = useSelector(state => state.courseDetail);
const supportText = app.hasFullSupport
? intl.formatMessage(messages.appFullSupport)
@@ -72,8 +73,7 @@ AppCard.propTypes = {
}).isRequired,
onClick: PropTypes.func.isRequired,
selected: PropTypes.bool.isRequired,
intl: intlShape.isRequired,
features: PropTypes.arrayOf(PropTypes.shape({})).isRequired,
};
export default injectIntl(AppCard);
export default AppCard;

View File

@@ -1,8 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import {
injectIntl,
intlShape,
useIntl,
FormattedMessage,
} from '@edx/frontend-platform/i18n';
import { Form, Hyperlink } from '@openedx/paragon';
@@ -15,7 +14,6 @@ import ExtendedCourseDetails from './extended-course-details';
import messages from './messages';
const IntroducingSection = ({
intl,
title,
subtitle,
duration,
@@ -34,6 +32,7 @@ const IntroducingSection = ({
videoThumbnailImageAssetPath,
onChange,
}) => {
const intl = useIntl();
const overviewHelpText = (
<FormattedMessage
id="course-authoring.schedule-section.introducing.course-overview.help-text"
@@ -182,7 +181,6 @@ IntroducingSection.defaultProps = {
};
IntroducingSection.propTypes = {
intl: intlShape.isRequired,
title: PropTypes.string,
subtitle: PropTypes.string,
duration: PropTypes.string,
@@ -202,4 +200,4 @@ IntroducingSection.propTypes = {
onChange: PropTypes.func.isRequired,
};
export default injectIntl(IntroducingSection);
export default IntroducingSection;

View File

@@ -3,14 +3,15 @@ import { useSelector } from 'react-redux';
import PropTypes from 'prop-types';
import { Button, Card } from '@openedx/paragon';
import { Add as AddIcon } from '@openedx/paragon/icons/es5';
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import { useIntl } from '@edx/frontend-platform/i18n';
import { getStudioHomeData } from '../../../data/selectors';
import messages from '../../../messages';
const ContactAdministrator = ({
intl, hasAbilityToCreateCourse, showNewCourseContainer, onClickNewCourse,
hasAbilityToCreateCourse, showNewCourseContainer, onClickNewCourse,
}) => {
const intl = useIntl();
const { studioShortName } = useSelector(getStudioHomeData);
return (
@@ -52,10 +53,9 @@ ContactAdministrator.defaultProps = {
};
ContactAdministrator.propTypes = {
intl: intlShape.isRequired,
hasAbilityToCreateCourse: PropTypes.bool,
showNewCourseContainer: PropTypes.bool.isRequired,
onClickNewCourse: PropTypes.func.isRequired,
};
export default injectIntl(ContactAdministrator);
export default ContactAdministrator;