feat: change head title depending on page (#582)
This commit is contained in:
@@ -9,6 +9,7 @@ import { FormattedMessage, injectIntl, intlShape } from '@edx/frontend-platform/
|
||||
import Placeholder from '@edx/frontend-lib-content-components';
|
||||
|
||||
import AlertProctoringError from '../generic/AlertProctoringError';
|
||||
import { useModel } from '../generic/model-store';
|
||||
import InternetConnectionAlert from '../generic/internet-connection-alert';
|
||||
import { parseArrayOrObjectValues } from '../utils';
|
||||
import { RequestStatus } from '../data/constants';
|
||||
@@ -23,6 +24,7 @@ import SettingsSidebar from './settings-sidebar/SettingsSidebar';
|
||||
import validateAdvancedSettingsData from './utils';
|
||||
import messages from './messages';
|
||||
import ModalError from './modal-error/ModalError';
|
||||
import getPageHeadTitle from '../generic/utils';
|
||||
|
||||
const AdvancedSettings = ({ intl, courseId }) => {
|
||||
const dispatch = useDispatch();
|
||||
@@ -36,6 +38,9 @@ const AdvancedSettings = ({ intl, courseId }) => {
|
||||
const [isEditableState, setIsEditableState] = useState(false);
|
||||
const [hasInternetConnectionError, setInternetConnectionError] = useState(false);
|
||||
|
||||
const courseDetails = useModel('courseDetails', courseId);
|
||||
document.title = getPageHeadTitle(courseDetails?.name, intl.formatMessage(messages.headingTitle));
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(fetchCourseAppSettings(courseId));
|
||||
dispatch(fetchProctoringExamErrors(courseId));
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
import { Add as IconAdd } from '@edx/paragon/icons';
|
||||
|
||||
import InternetConnectionAlert from '../generic/internet-connection-alert';
|
||||
import { useModel } from '../generic/model-store';
|
||||
import SubHeader from '../generic/sub-header/SubHeader';
|
||||
import { USER_ROLES } from '../constants';
|
||||
import messages from './messages';
|
||||
@@ -18,10 +19,14 @@ import AddTeamMember from './add-team-member/AddTeamMember';
|
||||
import CourseTeamMember from './course-team-member/CourseTeamMember';
|
||||
import InfoModal from './info-modal/InfoModal';
|
||||
import { useCourseTeam } from './hooks';
|
||||
import getPageHeadTitle from '../generic/utils';
|
||||
|
||||
const CourseTeam = ({ courseId }) => {
|
||||
const intl = useIntl();
|
||||
|
||||
const courseDetails = useModel('courseDetails', courseId);
|
||||
document.title = getPageHeadTitle(courseDetails?.name, intl.formatMessage(messages.headingTitle));
|
||||
|
||||
const {
|
||||
modalType,
|
||||
errorMessage,
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
import { Add as AddIcon } from '@edx/paragon/icons';
|
||||
import { useSelector } from 'react-redux';
|
||||
|
||||
import { useModel } from '../generic/model-store';
|
||||
import { getProcessingNotification } from '../generic/processing-notification/data/selectors';
|
||||
import ProcessingNotification from '../generic/processing-notification';
|
||||
import SubHeader from '../generic/sub-header/SubHeader';
|
||||
@@ -23,10 +24,14 @@ import messages from './messages';
|
||||
import { useCourseUpdates } from './hooks';
|
||||
import { getLoadingStatuses, getSavingStatuses } from './data/selectors';
|
||||
import { matchesAnyStatus } from './utils';
|
||||
import getPageHeadTitle from '../generic/utils';
|
||||
|
||||
const CourseUpdates = ({ courseId }) => {
|
||||
const intl = useIntl();
|
||||
|
||||
const courseDetails = useModel('courseDetails', courseId);
|
||||
document.title = getPageHeadTitle(courseDetails?.name, intl.formatMessage(messages.headingTitle));
|
||||
|
||||
const {
|
||||
requestType,
|
||||
courseUpdates,
|
||||
|
||||
@@ -26,7 +26,7 @@ import Placeholder, {
|
||||
} from '@edx/frontend-lib-content-components';
|
||||
|
||||
import { RequestStatus } from '../data/constants';
|
||||
import { useModels } from '../generic/model-store';
|
||||
import { useModels, useModel } from '../generic/model-store';
|
||||
import { getLoadingStatus, getSavingStatus } from './data/selectors';
|
||||
import {
|
||||
addSingleCustomPage,
|
||||
@@ -40,6 +40,7 @@ import CustomPageCard from './CustomPageCard';
|
||||
import messages from './messages';
|
||||
import CustomPagesProvider from './CustomPagesProvider';
|
||||
import EditModal from './EditModal';
|
||||
import getPageHeadTitle from '../generic/utils';
|
||||
|
||||
const CustomPages = ({
|
||||
courseId,
|
||||
@@ -52,6 +53,9 @@ const CustomPages = ({
|
||||
const [isOpen, open, close] = useToggle(false);
|
||||
const [isEditModalOpen, openEditModal, closeEditModal] = useToggle(false);
|
||||
|
||||
const courseDetails = useModel('courseDetails', courseId);
|
||||
document.title = getPageHeadTitle(courseDetails?.name, intl.formatMessage(messages.heading));
|
||||
|
||||
const { config } = useContext(AppContext);
|
||||
const { path, url } = useRouteMatch();
|
||||
const learningCourseURL = `${config.LEARNING_BASE_URL}/course/${courseId}`;
|
||||
|
||||
@@ -17,7 +17,7 @@ import {
|
||||
import Placeholder, { ErrorAlert } from '@edx/frontend-lib-content-components';
|
||||
|
||||
import { RequestStatus } from '../data/constants';
|
||||
import { useModels } from '../generic/model-store';
|
||||
import { useModels, useModel } from '../generic/model-store';
|
||||
import {
|
||||
addAssetFile,
|
||||
deleteAssetFile,
|
||||
@@ -41,6 +41,7 @@ import {
|
||||
} from './table-components';
|
||||
import ApiStatusToast from './ApiStatusToast';
|
||||
import { clearErrors } from './data/slice';
|
||||
import getPageHeadTitle from '../generic/utils';
|
||||
|
||||
const FilesAndUploads = ({
|
||||
courseId,
|
||||
@@ -62,6 +63,9 @@ const FilesAndUploads = ({
|
||||
const [selectedRows, setSelectedRows] = useState([]);
|
||||
const [isDeleteConfirmationOpen, openDeleteConfirmation, closeDeleteConfirmation] = useToggle(false);
|
||||
|
||||
const courseDetails = useModel('courseDetails', courseId);
|
||||
document.title = getPageHeadTitle(courseDetails?.name, intl.formatMessage(messages.heading));
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(fetchAssets(courseId));
|
||||
}, [courseId]);
|
||||
|
||||
10
src/generic/utils.js
Normal file
10
src/generic/utils.js
Normal file
@@ -0,0 +1,10 @@
|
||||
import { isEmpty } from 'lodash';
|
||||
|
||||
const getPageHeadTitle = (courseName, pageName) => {
|
||||
if (isEmpty(courseName)) {
|
||||
return `${pageName} | ${process.env.SITE_NAME}`;
|
||||
}
|
||||
return `${pageName} | ${courseName} | ${process.env.SITE_NAME}`;
|
||||
};
|
||||
|
||||
export default getPageHeadTitle;
|
||||
16
src/generic/utils.test.js
Normal file
16
src/generic/utils.test.js
Normal file
@@ -0,0 +1,16 @@
|
||||
import getPageHeadTitle from './utils';
|
||||
|
||||
describe('utils', () => {
|
||||
describe('getPageHeader', () => {
|
||||
it('should return with page name and site name', () => {
|
||||
const expected = 'pageName | edX';
|
||||
const actual = getPageHeadTitle(null, 'pageName');
|
||||
expect(expected).toEqual(actual);
|
||||
});
|
||||
it('should return with page name, course name, and site name', () => {
|
||||
const expected = 'pageName | courseName | edX';
|
||||
const actual = getPageHeadTitle('courseName', 'pageName');
|
||||
expect(expected).toEqual(actual);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
} from '@edx/paragon';
|
||||
import { CheckCircle, Warning, Add as IconAdd } from '@edx/paragon/icons';
|
||||
|
||||
import { useModel } from '../generic/model-store';
|
||||
import AlertMessage from '../generic/alert-message';
|
||||
import { RequestStatus } from '../data/constants';
|
||||
import InternetConnectionAlert from '../generic/internet-connection-alert';
|
||||
@@ -28,6 +29,7 @@ import AssignmentSection from './assignment-section';
|
||||
import CreditSection from './credit-section';
|
||||
import DeadlineSection from './deadline-section';
|
||||
import { useConvertGradeCutoffs, useUpdateGradingData } from './hooks';
|
||||
import getPageHeadTitle from '../generic/utils';
|
||||
|
||||
const GradingSettings = ({ intl, courseId }) => {
|
||||
const gradingSettingsData = useSelector(getGradingSettings);
|
||||
@@ -42,6 +44,9 @@ const GradingSettings = ({ intl, courseId }) => {
|
||||
const [showOverrideInternetConnectionAlert, setOverrideInternetConnectionAlert] = useState(false);
|
||||
const [eligibleGrade, setEligibleGrade] = useState(null);
|
||||
|
||||
const courseDetails = useModel('courseDetails', courseId);
|
||||
document.title = getPageHeadTitle(courseDetails?.name, intl.formatMessage(messages.headingTitle));
|
||||
|
||||
const {
|
||||
graders,
|
||||
resetDataRef,
|
||||
|
||||
@@ -23,10 +23,14 @@ import { getCourseAppsApiStatus, getLoadingStatus } from './data/selectors';
|
||||
import PagesAndResourcesProvider from './PagesAndResourcesProvider';
|
||||
import { RequestStatus } from '../data/constants';
|
||||
import PermissionDeniedAlert from '../generic/PermissionDeniedAlert';
|
||||
import getPageHeadTitle from '../generic/utils';
|
||||
|
||||
const PagesAndResources = ({ courseId, intl }) => {
|
||||
const { path, url } = useRouteMatch();
|
||||
|
||||
const courseDetails = useModel('courseDetails', courseId);
|
||||
document.title = getPageHeadTitle(courseDetails?.name, intl.formatMessage(messages.heading));
|
||||
|
||||
const dispatch = useDispatch();
|
||||
useEffect(() => {
|
||||
dispatch(fetchCourseApps(courseId));
|
||||
|
||||
@@ -12,8 +12,9 @@ import {
|
||||
intlShape,
|
||||
FormattedMessage,
|
||||
} from '@edx/frontend-platform/i18n';
|
||||
|
||||
import { getConfig } from '@edx/frontend-platform';
|
||||
|
||||
import { useModel } from '../generic/model-store';
|
||||
import messages from './ProctoredExamSettings.messages';
|
||||
import ExamsApiService from '../data/services/ExamsApiService';
|
||||
import StudioApiService from '../data/services/StudioApiService';
|
||||
@@ -25,6 +26,7 @@ import {
|
||||
fetchExamSettingsPending,
|
||||
fetchExamSettingsSuccess,
|
||||
} from './data/thunks';
|
||||
import getPageHeadTitle from '../generic/utils';
|
||||
|
||||
const ProctoredExamSettings = ({ courseId, intl }) => {
|
||||
const dispatch = useDispatch();
|
||||
@@ -51,6 +53,9 @@ const ProctoredExamSettings = ({ courseId, intl }) => {
|
||||
errors: {},
|
||||
});
|
||||
|
||||
const courseDetails = useModel('courseDetails', courseId);
|
||||
document.title = getPageHeadTitle(courseDetails?.name, 'Proctored Exam Settings');
|
||||
|
||||
const alertRef = React.createRef();
|
||||
const saveStatusAlertRef = React.createRef();
|
||||
const proctoringEscalationEmailInputRef = useRef(null);
|
||||
|
||||
@@ -12,6 +12,7 @@ import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
|
||||
import Placeholder from '@edx/frontend-lib-content-components';
|
||||
|
||||
import { RequestStatus } from '../data/constants';
|
||||
import { useModel } from '../generic/model-store';
|
||||
import AlertMessage from '../generic/alert-message';
|
||||
import InternetConnectionAlert from '../generic/internet-connection-alert';
|
||||
import { STATEFUL_BUTTON_STATES } from '../constants';
|
||||
@@ -39,6 +40,7 @@ import LicenseSection from './license-section';
|
||||
import ScheduleSidebar from './schedule-sidebar';
|
||||
import messages from './messages';
|
||||
import { useSaveValuesPrompt } from './hooks';
|
||||
import getPageHeadTitle from '../generic/utils';
|
||||
|
||||
const ScheduleAndDetails = ({ intl, courseId }) => {
|
||||
const courseSettings = useSelector(getCourseSettings);
|
||||
@@ -48,6 +50,9 @@ const ScheduleAndDetails = ({ intl, courseId }) => {
|
||||
const isLoading = loadingDetailsStatus === RequestStatus.IN_PROGRESS
|
||||
|| loadingSettingsStatus === RequestStatus.IN_PROGRESS;
|
||||
|
||||
const course = useModel('courseDetails', courseId);
|
||||
document.title = getPageHeadTitle(course?.name, intl.formatMessage(messages.headingTitle));
|
||||
|
||||
const {
|
||||
errorFields,
|
||||
savingStatus,
|
||||
|
||||
Reference in New Issue
Block a user