fix: a11y issues (#47)
This commit is contained in:
40
package-lock.json
generated
40
package-lock.json
generated
@@ -40,6 +40,7 @@
|
||||
"query-string": "7.0.1",
|
||||
"react": "^16.14.0",
|
||||
"react-dom": "^16.14.0",
|
||||
"react-helmet": "^6.1.0",
|
||||
"react-intl": "^5.20.9",
|
||||
"react-pdf": "^5.5.0",
|
||||
"react-redux": "^7.2.4",
|
||||
@@ -24531,6 +24532,20 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/react-helmet": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/react-helmet/-/react-helmet-6.1.0.tgz",
|
||||
"integrity": "sha512-4uMzEY9nlDlgxr61NL3XbKRy1hEkXmKNXhjbAIOVw5vcFrsdYbH2FEwcNyWvWinl103nXgzYNlns9ca+8kFiWw==",
|
||||
"dependencies": {
|
||||
"object-assign": "^4.1.1",
|
||||
"prop-types": "^15.7.2",
|
||||
"react-fast-compare": "^3.1.1",
|
||||
"react-side-effect": "^2.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=16.3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-intl": {
|
||||
"version": "5.25.1",
|
||||
"resolved": "https://registry.npmjs.org/react-intl/-/react-intl-5.25.1.tgz",
|
||||
@@ -24870,6 +24885,14 @@
|
||||
"isarray": "0.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/react-side-effect": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/react-side-effect/-/react-side-effect-2.1.2.tgz",
|
||||
"integrity": "sha512-PVjOcvVOyIILrYoyGEpDN3vmYNLdy1CajSFNt4TDsVQC5KpTijDvWVoR+/7Rz2xT978D8/ZtFceXxzsPwZEDvw==",
|
||||
"peerDependencies": {
|
||||
"react": "^16.3.0 || ^17.0.0 || ^18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-style-singleton": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.1.tgz",
|
||||
@@ -48625,6 +48648,17 @@
|
||||
"use-sidecar": "^1.1.2"
|
||||
}
|
||||
},
|
||||
"react-helmet": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/react-helmet/-/react-helmet-6.1.0.tgz",
|
||||
"integrity": "sha512-4uMzEY9nlDlgxr61NL3XbKRy1hEkXmKNXhjbAIOVw5vcFrsdYbH2FEwcNyWvWinl103nXgzYNlns9ca+8kFiWw==",
|
||||
"requires": {
|
||||
"object-assign": "^4.1.1",
|
||||
"prop-types": "^15.7.2",
|
||||
"react-fast-compare": "^3.1.1",
|
||||
"react-side-effect": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"react-intl": {
|
||||
"version": "5.25.1",
|
||||
"resolved": "https://registry.npmjs.org/react-intl/-/react-intl-5.25.1.tgz",
|
||||
@@ -48888,6 +48922,12 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"react-side-effect": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/react-side-effect/-/react-side-effect-2.1.2.tgz",
|
||||
"integrity": "sha512-PVjOcvVOyIILrYoyGEpDN3vmYNLdy1CajSFNt4TDsVQC5KpTijDvWVoR+/7Rz2xT978D8/ZtFceXxzsPwZEDvw==",
|
||||
"requires": {}
|
||||
},
|
||||
"react-style-singleton": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.1.tgz",
|
||||
|
||||
@@ -58,6 +58,7 @@
|
||||
"query-string": "7.0.1",
|
||||
"react": "^16.14.0",
|
||||
"react-dom": "^16.14.0",
|
||||
"react-helmet": "^6.1.0",
|
||||
"react-intl": "^5.20.9",
|
||||
"react-pdf": "^5.5.0",
|
||||
"react-redux": "^7.2.4",
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import React from 'react';
|
||||
import { BrowserRouter as Router } from 'react-router-dom';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { Helmet } from 'react-helmet';
|
||||
|
||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||
import { AppContext } from '@edx/frontend-platform/react';
|
||||
import Footer from '@edx/frontend-component-footer';
|
||||
|
||||
@@ -9,6 +11,7 @@ import { thunkActions } from 'data/redux';
|
||||
import fakeData from 'data/services/lms/fakeData/courses';
|
||||
import LearnerDashboardHeader from 'containers/LearnerDashboardHeader';
|
||||
import Dashboard from 'containers/Dashboard';
|
||||
import messages from './messages';
|
||||
|
||||
import './App.scss';
|
||||
|
||||
@@ -16,6 +19,7 @@ export const App = () => {
|
||||
const dispatch = useDispatch();
|
||||
// TODO: made development-only
|
||||
const { authenticatedUser } = React.useContext(AppContext);
|
||||
const { formatMessage } = useIntl();
|
||||
React.useEffect(() => {
|
||||
if (authenticatedUser?.administrator || process.env.NODE_ENV === 'development') {
|
||||
window.loadEmptyData = () => {
|
||||
@@ -34,6 +38,9 @@ export const App = () => {
|
||||
});
|
||||
return (
|
||||
<Router>
|
||||
<Helmet>
|
||||
<title>{formatMessage(messages.pageTitle)}</title>
|
||||
</Helmet>
|
||||
<div>
|
||||
<LearnerDashboardHeader />
|
||||
<main>
|
||||
|
||||
@@ -2,6 +2,14 @@
|
||||
|
||||
exports[`App router component snapshot: enabled 1`] = `
|
||||
<BrowserRouter>
|
||||
<HelmetWrapper
|
||||
defer={true}
|
||||
encodeSpecialCharacters={true}
|
||||
>
|
||||
<title>
|
||||
Learner Home
|
||||
</title>
|
||||
</HelmetWrapper>
|
||||
<div>
|
||||
<LearnerDashboardHeader />
|
||||
<main>
|
||||
|
||||
@@ -30,9 +30,11 @@ export const CourseCardContent = ({ cardId, orientation }) => {
|
||||
<Card.Body>
|
||||
<Card.Header
|
||||
title={(
|
||||
<a href={homeUrl} data-testid="CourseCardTitle">
|
||||
{courseName}
|
||||
</a>
|
||||
<h3>
|
||||
<a href={homeUrl} data-testid="CourseCardTitle">
|
||||
{courseName}
|
||||
</a>
|
||||
</h3>
|
||||
)}
|
||||
actions={<CourseCardMenu cardId={cardId} />}
|
||||
/>
|
||||
|
||||
@@ -7,7 +7,7 @@ exports[`CourseCardMenu snapshot 1`] = `
|
||||
alt="Actions dropdown"
|
||||
as="IconButton"
|
||||
iconAs="Icon"
|
||||
id="dropdown-toggle-with-iconbutton"
|
||||
id="course-actions-dropdown-test-card-id"
|
||||
src={[MockFunction icons.MoreVert]}
|
||||
variant="primary"
|
||||
/>
|
||||
|
||||
@@ -19,7 +19,7 @@ export const CourseCardMenu = ({ cardId }) => {
|
||||
<>
|
||||
<Dropdown>
|
||||
<Dropdown.Toggle
|
||||
id="dropdown-toggle-with-iconbutton"
|
||||
id={`course-actions-dropdown-${cardId}`}
|
||||
as={IconButton}
|
||||
src={MoreVert}
|
||||
iconAs={Icon}
|
||||
|
||||
@@ -20,12 +20,14 @@ exports[`CourseCardContent snapshot orientation horizontal 1`] = `
|
||||
/>
|
||||
}
|
||||
title={
|
||||
<a
|
||||
data-testid="CourseCardTitle"
|
||||
href="test-home-url"
|
||||
>
|
||||
test-course-name
|
||||
</a>
|
||||
<h3>
|
||||
<a
|
||||
data-testid="CourseCardTitle"
|
||||
href="test-home-url"
|
||||
>
|
||||
test-course-name
|
||||
</a>
|
||||
</h3>
|
||||
}
|
||||
/>
|
||||
<Card.Section
|
||||
@@ -71,12 +73,14 @@ exports[`CourseCardContent snapshot orientation vertical 1`] = `
|
||||
/>
|
||||
}
|
||||
title={
|
||||
<a
|
||||
data-testid="CourseCardTitle"
|
||||
href="test-home-url"
|
||||
>
|
||||
test-course-name
|
||||
</a>
|
||||
<h3>
|
||||
<a
|
||||
data-testid="CourseCardTitle"
|
||||
href="test-home-url"
|
||||
>
|
||||
test-course-name
|
||||
</a>
|
||||
</h3>
|
||||
}
|
||||
/>
|
||||
<Card.Section
|
||||
|
||||
@@ -1,17 +1,5 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`CourseList snapshots renders loading 1`] = `
|
||||
<div
|
||||
className="course-list-loading"
|
||||
>
|
||||
<Spinner
|
||||
animation="border"
|
||||
className="mie-3"
|
||||
screenReaderText="loading"
|
||||
/>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`CourseList snapshots with filters 1`] = `
|
||||
<div
|
||||
className="course-list-container"
|
||||
|
||||
@@ -6,7 +6,6 @@ import { useCheckboxSetValues } from '@edx/paragon';
|
||||
import { StrictDict } from 'utils';
|
||||
import { actions, hooks as appHooks } from 'data/redux';
|
||||
import { ListPageSize, SortKeys } from 'data/constants/app';
|
||||
import { RequestKeys } from 'data/constants/requests';
|
||||
|
||||
import * as module from './hooks';
|
||||
|
||||
@@ -27,7 +26,6 @@ export const useCourseListData = () => {
|
||||
});
|
||||
const handleRemoveFilter = (filter) => () => setFilters.remove(filter);
|
||||
const setPageNumber = (value) => dispatch(actions.app.setPageNumber(value));
|
||||
const initIsPending = appHooks.useIsPendingRequest(RequestKeys.initialize);
|
||||
|
||||
return {
|
||||
pageNumber,
|
||||
@@ -42,7 +40,6 @@ export const useCourseListData = () => {
|
||||
handleRemoveFilter,
|
||||
},
|
||||
showFilters: filters.length > 0,
|
||||
initIsPending,
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -80,12 +80,6 @@ describe('CourseList hooks', () => {
|
||||
// don't show filter when list is empty.
|
||||
expect(out.showFilters).toEqual(false);
|
||||
});
|
||||
test('initIsPending loads from useIsPendingRequest', () => {
|
||||
expect(out.initIsPending).toEqual(false);
|
||||
appHooks.useIsPendingRequest.mockReturnValueOnce(true);
|
||||
out = hooks.useCourseListData();
|
||||
expect(out.initIsPending).toEqual(true);
|
||||
});
|
||||
describe('filterOptions', () => {
|
||||
test('sortBy and setSortBy are connected to the state value', () => {
|
||||
expect(out.filterOptions.sortBy).toEqual(testSortBy);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
|
||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||
import { Pagination, Spinner } from '@edx/paragon';
|
||||
import { Pagination } from '@edx/paragon';
|
||||
|
||||
import {
|
||||
ActiveCourseFilters,
|
||||
@@ -23,13 +23,8 @@ export const CourseList = () => {
|
||||
numPages,
|
||||
showFilters,
|
||||
visibleList,
|
||||
initIsPending,
|
||||
} = useCourseListData();
|
||||
return initIsPending ? (
|
||||
<div className="course-list-loading">
|
||||
<Spinner animation="border" className="mie-3" screenReaderText="loading" />
|
||||
</div>
|
||||
) : (
|
||||
return (
|
||||
<div className="course-list-container">
|
||||
<div id="course-list-heading-container">
|
||||
<h2 className="my-3">{formatMessage(messages.myCourses)}</h2>
|
||||
|
||||
@@ -20,7 +20,6 @@ describe('CourseList', () => {
|
||||
setPageNumber: jest.fn().mockName('setPageNumber'),
|
||||
showFilters: false,
|
||||
visibleList: [],
|
||||
initIsPending: false,
|
||||
};
|
||||
const createWrapper = (courseListData) => {
|
||||
useCourseListData.mockReturnValueOnce({
|
||||
@@ -31,10 +30,6 @@ describe('CourseList', () => {
|
||||
};
|
||||
|
||||
describe('snapshots', () => {
|
||||
it('renders loading', () => {
|
||||
const wrapper = createWrapper({ initIsPending: true });
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
test('with no filters', () => {
|
||||
const wrapper = createWrapper();
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
|
||||
@@ -1,20 +1,15 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Dashboard snapshots there are available dashboards 1`] = `
|
||||
<div
|
||||
className="d-flex flex-column p-2"
|
||||
id="dashboard-container"
|
||||
>
|
||||
<EnterpriseDashboardModal />
|
||||
<EmptyCourse />
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`Dashboard snapshots there are courses, or they are still loading 1`] = `
|
||||
exports[`Dashboard snapshots courses loaded 1`] = `
|
||||
<div
|
||||
className="d-flex flex-column p-2"
|
||||
id="dashboard-container"
|
||||
>
|
||||
<h1
|
||||
className="sr-only"
|
||||
>
|
||||
Learner Home
|
||||
</h1>
|
||||
<Container
|
||||
fluid={true}
|
||||
size="xl"
|
||||
@@ -67,11 +62,53 @@ exports[`Dashboard snapshots there are courses, or they are still loading 1`] =
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`Dashboard snapshots courses still loading 1`] = `
|
||||
<div
|
||||
className="d-flex flex-column p-2"
|
||||
id="dashboard-container"
|
||||
>
|
||||
<h1
|
||||
className="sr-only"
|
||||
>
|
||||
Learner Home
|
||||
</h1>
|
||||
<div
|
||||
className="course-list-loading"
|
||||
>
|
||||
<Spinner
|
||||
animation="border"
|
||||
className="mie-3"
|
||||
screenReaderText="Loading..."
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`Dashboard snapshots there are available dashboards 1`] = `
|
||||
<div
|
||||
className="d-flex flex-column p-2"
|
||||
id="dashboard-container"
|
||||
>
|
||||
<h1
|
||||
className="sr-only"
|
||||
>
|
||||
Learner Home
|
||||
</h1>
|
||||
<EnterpriseDashboardModal />
|
||||
<EmptyCourse />
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`Dashboard snapshots there are no courses 1`] = `
|
||||
<div
|
||||
className="d-flex flex-column p-2"
|
||||
id="dashboard-container"
|
||||
>
|
||||
<h1
|
||||
className="sr-only"
|
||||
>
|
||||
Learner Home
|
||||
</h1>
|
||||
<EmptyCourse />
|
||||
</div>
|
||||
`;
|
||||
@@ -81,6 +118,11 @@ exports[`Dashboard snapshots there is a select session modal 1`] = `
|
||||
className="d-flex flex-column p-2"
|
||||
id="dashboard-container"
|
||||
>
|
||||
<h1
|
||||
className="sr-only"
|
||||
>
|
||||
Learner Home
|
||||
</h1>
|
||||
<EmptyCourse />
|
||||
</div>
|
||||
`;
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
import React from 'react';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { Container, Col, Row } from '@edx/paragon';
|
||||
import {
|
||||
Container,
|
||||
Col,
|
||||
Row,
|
||||
Spinner,
|
||||
} from '@edx/paragon';
|
||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||
|
||||
import {
|
||||
thunkActions,
|
||||
@@ -14,6 +20,8 @@ import EmptyCourse from 'containers/EmptyCourse';
|
||||
import SelectSessionModal from 'containers/SelectSessionModal';
|
||||
import EnterpriseDashboardModal from 'containers/EnterpriseDashboardModal';
|
||||
|
||||
import appMessages from 'messages';
|
||||
|
||||
import './index.scss';
|
||||
|
||||
export const Dashboard = () => {
|
||||
@@ -22,6 +30,7 @@ export const Dashboard = () => {
|
||||
() => { dispatch(thunkActions.app.initialize()); },
|
||||
[dispatch],
|
||||
);
|
||||
const { formatMessage } = useIntl();
|
||||
|
||||
const hasCourses = appHooks.useHasCourses();
|
||||
const hasAvailableDashboards = appHooks.useHasAvailableDashboards();
|
||||
@@ -30,8 +39,18 @@ export const Dashboard = () => {
|
||||
|
||||
return (
|
||||
<div id="dashboard-container" className="d-flex flex-column p-2">
|
||||
<h1 className="sr-only">{formatMessage(appMessages.pageTitle)}</h1>
|
||||
{hasAvailableDashboards && <EnterpriseDashboardModal />}
|
||||
{initIsPending || (!initIsPending && hasCourses) ? (
|
||||
{initIsPending && (
|
||||
<div className="course-list-loading">
|
||||
<Spinner
|
||||
animation="border"
|
||||
className="mie-3"
|
||||
screenReaderText={formatMessage(appMessages.loadingSR)}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{(!initIsPending && hasCourses) && (
|
||||
<Container fluid size="xl">
|
||||
<Row>
|
||||
<Col
|
||||
@@ -50,7 +69,8 @@ export const Dashboard = () => {
|
||||
</Col>
|
||||
</Row>
|
||||
</Container>
|
||||
) : (<EmptyCourse />)}
|
||||
)}
|
||||
{(!initIsPending && !hasCourses) && (<EmptyCourse />)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -45,22 +45,23 @@ describe('Dashboard', () => {
|
||||
};
|
||||
|
||||
describe('snapshots', () => {
|
||||
test('there are courses, or they are still loading', () => {
|
||||
const pendingNoCoursesWrapper = createWrapper({
|
||||
test('courses still loading', () => {
|
||||
const wrapper = createWrapper({
|
||||
hasCourses: false,
|
||||
hasAvailableDashboards: false,
|
||||
showSelectSessionModal: false,
|
||||
initIsPending: true,
|
||||
});
|
||||
expect(pendingNoCoursesWrapper).toMatchSnapshot();
|
||||
|
||||
const doneLoadingWithCoursesWrapper = createWrapper({
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
test('courses loaded', () => {
|
||||
const wrapper = createWrapper({
|
||||
hasCourses: true,
|
||||
hasAvailableDashboards: false,
|
||||
showSelectSessionModal: false,
|
||||
initIsPending: false,
|
||||
});
|
||||
expect(doneLoadingWithCoursesWrapper).toEqual(pendingNoCoursesWrapper);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('there are no courses', () => {
|
||||
|
||||
@@ -31,20 +31,22 @@ export const GreetingBanner = ({ size }) => {
|
||||
{ 'p-5': !isSmall, 'p-3.5': isSmall },
|
||||
)}
|
||||
>
|
||||
<Image
|
||||
style={{ width: isSmall ? '46px' : '148px' }}
|
||||
className="d-block"
|
||||
src={getConfig().LOGO_WHITE_URL}
|
||||
alt={getConfig().SITE_NAME}
|
||||
/>
|
||||
<a href={`${getConfig().LMS_BASE_URL}/dashboard`}>
|
||||
<Image
|
||||
style={{ width: isSmall ? '46px' : '148px' }}
|
||||
className="d-block"
|
||||
src={getConfig().LOGO_WHITE_URL}
|
||||
alt={getConfig().SITE_NAME}
|
||||
/>
|
||||
</a>
|
||||
<div className={`greetings-slash-container-${size} bg-brand-500`} />
|
||||
{isSmall
|
||||
? (
|
||||
<h5 className="text-center text-accent-b">
|
||||
<h5 role="presentation" className="text-center text-accent-b">
|
||||
{formatMessage(greetMessage)}
|
||||
</h5>
|
||||
) : (
|
||||
<h1 className="text-center text-accent-b">
|
||||
<h1 role="presentation" className="text-center text-accent-b">
|
||||
{formatMessage(greetMessage)}
|
||||
</h1>
|
||||
)}
|
||||
|
||||
@@ -4,21 +4,26 @@ exports[`GreetingBanner snapshots with size large and afternoon 1`] = `
|
||||
<div
|
||||
className="d-flex align-items-center justify-content-center p-5"
|
||||
>
|
||||
<Image
|
||||
alt="localhost"
|
||||
className="d-block"
|
||||
src="https://edx-cdn.org/v3/default/logo-white.svg"
|
||||
style={
|
||||
Object {
|
||||
"width": "148px",
|
||||
<a
|
||||
href="http://localhost:18000/dashboard"
|
||||
>
|
||||
<Image
|
||||
alt="localhost"
|
||||
className="d-block"
|
||||
src="https://edx-cdn.org/v3/default/logo-white.svg"
|
||||
style={
|
||||
Object {
|
||||
"width": "148px",
|
||||
}
|
||||
}
|
||||
}
|
||||
/>
|
||||
/>
|
||||
</a>
|
||||
<div
|
||||
className="greetings-slash-container-large bg-brand-500"
|
||||
/>
|
||||
<h1
|
||||
className="text-center text-accent-b"
|
||||
role="presentation"
|
||||
>
|
||||
Good Afternoon!
|
||||
</h1>
|
||||
@@ -29,21 +34,26 @@ exports[`GreetingBanner snapshots with size large and evening 1`] = `
|
||||
<div
|
||||
className="d-flex align-items-center justify-content-center p-5"
|
||||
>
|
||||
<Image
|
||||
alt="localhost"
|
||||
className="d-block"
|
||||
src="https://edx-cdn.org/v3/default/logo-white.svg"
|
||||
style={
|
||||
Object {
|
||||
"width": "148px",
|
||||
<a
|
||||
href="http://localhost:18000/dashboard"
|
||||
>
|
||||
<Image
|
||||
alt="localhost"
|
||||
className="d-block"
|
||||
src="https://edx-cdn.org/v3/default/logo-white.svg"
|
||||
style={
|
||||
Object {
|
||||
"width": "148px",
|
||||
}
|
||||
}
|
||||
}
|
||||
/>
|
||||
/>
|
||||
</a>
|
||||
<div
|
||||
className="greetings-slash-container-large bg-brand-500"
|
||||
/>
|
||||
<h1
|
||||
className="text-center text-accent-b"
|
||||
role="presentation"
|
||||
>
|
||||
Good Evening!
|
||||
</h1>
|
||||
@@ -54,21 +64,26 @@ exports[`GreetingBanner snapshots with size large and morning 1`] = `
|
||||
<div
|
||||
className="d-flex align-items-center justify-content-center p-5"
|
||||
>
|
||||
<Image
|
||||
alt="localhost"
|
||||
className="d-block"
|
||||
src="https://edx-cdn.org/v3/default/logo-white.svg"
|
||||
style={
|
||||
Object {
|
||||
"width": "148px",
|
||||
<a
|
||||
href="http://localhost:18000/dashboard"
|
||||
>
|
||||
<Image
|
||||
alt="localhost"
|
||||
className="d-block"
|
||||
src="https://edx-cdn.org/v3/default/logo-white.svg"
|
||||
style={
|
||||
Object {
|
||||
"width": "148px",
|
||||
}
|
||||
}
|
||||
}
|
||||
/>
|
||||
/>
|
||||
</a>
|
||||
<div
|
||||
className="greetings-slash-container-large bg-brand-500"
|
||||
/>
|
||||
<h1
|
||||
className="text-center text-accent-b"
|
||||
role="presentation"
|
||||
>
|
||||
Good Morning!
|
||||
</h1>
|
||||
@@ -79,21 +94,26 @@ exports[`GreetingBanner snapshots with size small and afternoon 1`] = `
|
||||
<div
|
||||
className="d-flex align-items-center justify-content-center p-3.5"
|
||||
>
|
||||
<Image
|
||||
alt="localhost"
|
||||
className="d-block"
|
||||
src="https://edx-cdn.org/v3/default/logo-white.svg"
|
||||
style={
|
||||
Object {
|
||||
"width": "46px",
|
||||
<a
|
||||
href="http://localhost:18000/dashboard"
|
||||
>
|
||||
<Image
|
||||
alt="localhost"
|
||||
className="d-block"
|
||||
src="https://edx-cdn.org/v3/default/logo-white.svg"
|
||||
style={
|
||||
Object {
|
||||
"width": "46px",
|
||||
}
|
||||
}
|
||||
}
|
||||
/>
|
||||
/>
|
||||
</a>
|
||||
<div
|
||||
className="greetings-slash-container-small bg-brand-500"
|
||||
/>
|
||||
<h5
|
||||
className="text-center text-accent-b"
|
||||
role="presentation"
|
||||
>
|
||||
Good Afternoon!
|
||||
</h5>
|
||||
@@ -104,21 +124,26 @@ exports[`GreetingBanner snapshots with size small and evening 1`] = `
|
||||
<div
|
||||
className="d-flex align-items-center justify-content-center p-3.5"
|
||||
>
|
||||
<Image
|
||||
alt="localhost"
|
||||
className="d-block"
|
||||
src="https://edx-cdn.org/v3/default/logo-white.svg"
|
||||
style={
|
||||
Object {
|
||||
"width": "46px",
|
||||
<a
|
||||
href="http://localhost:18000/dashboard"
|
||||
>
|
||||
<Image
|
||||
alt="localhost"
|
||||
className="d-block"
|
||||
src="https://edx-cdn.org/v3/default/logo-white.svg"
|
||||
style={
|
||||
Object {
|
||||
"width": "46px",
|
||||
}
|
||||
}
|
||||
}
|
||||
/>
|
||||
/>
|
||||
</a>
|
||||
<div
|
||||
className="greetings-slash-container-small bg-brand-500"
|
||||
/>
|
||||
<h5
|
||||
className="text-center text-accent-b"
|
||||
role="presentation"
|
||||
>
|
||||
Good Evening!
|
||||
</h5>
|
||||
@@ -129,21 +154,26 @@ exports[`GreetingBanner snapshots with size small and morning 1`] = `
|
||||
<div
|
||||
className="d-flex align-items-center justify-content-center p-3.5"
|
||||
>
|
||||
<Image
|
||||
alt="localhost"
|
||||
className="d-block"
|
||||
src="https://edx-cdn.org/v3/default/logo-white.svg"
|
||||
style={
|
||||
Object {
|
||||
"width": "46px",
|
||||
<a
|
||||
href="http://localhost:18000/dashboard"
|
||||
>
|
||||
<Image
|
||||
alt="localhost"
|
||||
className="d-block"
|
||||
src="https://edx-cdn.org/v3/default/logo-white.svg"
|
||||
style={
|
||||
Object {
|
||||
"width": "46px",
|
||||
}
|
||||
}
|
||||
}
|
||||
/>
|
||||
/>
|
||||
</a>
|
||||
<div
|
||||
className="greetings-slash-container-small bg-brand-500"
|
||||
/>
|
||||
<h5
|
||||
className="text-center text-accent-b"
|
||||
role="presentation"
|
||||
>
|
||||
Good Morning!
|
||||
</h5>
|
||||
|
||||
@@ -12,6 +12,7 @@ exports[`RelatedProgramsModal snapshot: closed 1`] = `
|
||||
title="Related Programs"
|
||||
>
|
||||
<ModalDialog.Header
|
||||
aria-level={2}
|
||||
as="h3"
|
||||
className="programs-title m-0 p-0"
|
||||
>
|
||||
@@ -95,6 +96,7 @@ exports[`RelatedProgramsModal snapshot: open 1`] = `
|
||||
title="Related Programs"
|
||||
>
|
||||
<ModalDialog.Header
|
||||
aria-level={2}
|
||||
as="h3"
|
||||
className="programs-title m-0 p-0"
|
||||
>
|
||||
|
||||
@@ -27,13 +27,14 @@ export const ProgramCard = ({ data }) => {
|
||||
style={{ width: '18rem', color: 'white' }}
|
||||
as="a"
|
||||
href={data.programUrl}
|
||||
isClickable
|
||||
>
|
||||
<Card.ImageCap
|
||||
className="program-card-banner"
|
||||
src={data.bannerImgSrc}
|
||||
srcAlt={formatMessage(messages.bannerAlt)}
|
||||
logoSrc={data.logoImgSrc}
|
||||
logoAlt={formatMessage(messages.logoAlt)}
|
||||
logoAlt={formatMessage(messages.logoAlt, { provider: data.provider })}
|
||||
/>
|
||||
<Card.Header
|
||||
title={whiteFontWrapper(data.title)}
|
||||
|
||||
@@ -5,6 +5,7 @@ exports[`RelatedProgramsModal ProgramCard snapshot 1`] = `
|
||||
as="a"
|
||||
className="program-card mx-auto bg-primary-500 text-white mb-3.5 pb-3.5"
|
||||
href="props.data.programUrl"
|
||||
isClickable={true}
|
||||
style={
|
||||
Object {
|
||||
"color": "white",
|
||||
@@ -14,10 +15,10 @@ exports[`RelatedProgramsModal ProgramCard snapshot 1`] = `
|
||||
>
|
||||
<Card.ImageCap
|
||||
className="program-card-banner"
|
||||
logoAlt="Provider logo"
|
||||
logoAlt="props.data.provider logo"
|
||||
logoSrc="props.data.logoImgSrc"
|
||||
src="props.data.bannerImgSrc"
|
||||
srcAlt="Program banner"
|
||||
srcAlt=""
|
||||
/>
|
||||
<Card.Header
|
||||
subtitle={
|
||||
|
||||
@@ -11,12 +11,12 @@ export const messages = {
|
||||
},
|
||||
logoAlt: {
|
||||
id: 'learnerDashboard.programCard.logoAlt',
|
||||
defaultMessage: 'Provider logo',
|
||||
defaultMessage: '{provider} logo',
|
||||
description: 'Program provider logo alt-text',
|
||||
},
|
||||
bannerAlt: {
|
||||
id: 'learnerDashboard.programCard.bannerAlt',
|
||||
defaultMessage: 'Program banner',
|
||||
defaultMessage: '',
|
||||
description: 'Program banner logo alt-text',
|
||||
},
|
||||
};
|
||||
|
||||
@@ -31,7 +31,7 @@ export const RelatedProgramsModal = ({
|
||||
className="related-programs-modal p-4"
|
||||
data-testid="RelatedProgramsModal"
|
||||
>
|
||||
<ModalDialog.Header className="programs-title m-0 p-0" as="h3">
|
||||
<ModalDialog.Header className="programs-title m-0 p-0" as="h3" aria-level={2}>
|
||||
{formatMessage(messages.header)}
|
||||
</ModalDialog.Header>
|
||||
<ModalDialog.Header as="h4" className="programs-header p-0">
|
||||
|
||||
16
src/messages.js
Normal file
16
src/messages.js
Normal file
@@ -0,0 +1,16 @@
|
||||
import { StrictDict } from 'utils';
|
||||
|
||||
export const messages = StrictDict({
|
||||
loadingSR: {
|
||||
id: 'learner-dash.loadingSR',
|
||||
description: 'Page loading screen-reader text',
|
||||
defaultMessage: 'Loading...',
|
||||
},
|
||||
pageTitle: {
|
||||
id: 'learner-dash.title',
|
||||
description: 'Page title: Learner Home',
|
||||
defaultMessage: 'Learner Home',
|
||||
},
|
||||
});
|
||||
|
||||
export default messages;
|
||||
Reference in New Issue
Block a user