feat: change head title depending on page (#582)

This commit is contained in:
Kristin Aoki
2023-09-06 11:02:16 -04:00
committed by GitHub
parent a1793efcc0
commit 2bd8037d7b
11 changed files with 71 additions and 3 deletions

View File

@@ -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));

View File

@@ -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,

View File

@@ -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,

View File

@@ -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}`;

View File

@@ -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
View 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
View 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);
});
});
});

View File

@@ -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,

View File

@@ -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));

View File

@@ -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);

View File

@@ -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,