Skip to content
This repository has been archived by the owner on Sep 3, 2024. It is now read-only.

Commit

Permalink
feat: react based studio footer (#359)
Browse files Browse the repository at this point in the history
  • Loading branch information
KristinAoki committed Jul 11, 2023
1 parent f942ef9 commit 3586307
Show file tree
Hide file tree
Showing 7 changed files with 362 additions and 5 deletions.
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
"@edx/browserslist-config": "^1.1.1",
"@edx/frontend-build": "12.8.27",
"@edx/frontend-platform": "4.2.0",
"@edx/paragon": "^20.32.0",
"@edx/paragon": "^20.45.0",
"@edx/reactifex": "^2.1.1",
"@testing-library/dom": "^8.13.0",
"@testing-library/jest-dom": "^5.16.5",
Expand Down
166 changes: 166 additions & 0 deletions src/footer/Footer.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
import React, { useState } from 'react';
import PropTypes from 'prop-types';
import _ from 'lodash-es';
import { intlShape, injectIntl, FormattedMessage } from '@edx/frontend-platform/i18n';
import {
ActionRow,
Button,
Hyperlink,
Image,
TransitionReplace,
} from '@edx/paragon';
import { ExpandLess, ExpandMore, Help } from '@edx/paragon/icons';
import messages from './messages';

const Footer = ({
marketingBaseUrl,
termsOfServiceUrl,
privacyPolicyUrl,
supportEmail,
platformName,
lmsBaseUrl,
studioBaseUrl,
showAccessibilityPage,
// injected
intl,
}) => {
const [isOpen, setIsOpen] = useState(false);

return (
<>
<div className="m-0 row align-items-center justify-content-center">
<div className="col border-top mr-2" />
<Button
data-testid="helpToggleButton"
variant="outline-primary"
onClick={() => setIsOpen(!isOpen)}
iconBefore={Help}
iconAfter={isOpen ? ExpandLess : ExpandMore}
size="sm"
>
{isOpen ? intl.formatMessage(messages.closeHelpButtonLabel)
: intl.formatMessage(messages.openHelpButtonLabel)}
</Button>
<div className="col border-top ml-2" />
</div>
<TransitionReplace>
{isOpen ? (
<ActionRow key="help-link-button-row" className="py-4" data-testid="helpButtonRow">
<ActionRow.Spacer />
<Button as="a" href="https://docs.edx.org/" size="sm">
<FormattedMessage {...messages.edxDocumentationButtonLabel} />
</Button>
{platformName === 'edX' ? (
<Button
as="a"
href="https://partner.edx.org/"
size="sm"
data-testid="edXPortalButton"
>
<FormattedMessage {...messages.parnterPortalButtonLabel} />
</Button>
) : (
<Button
as="a"
href="https://open.edx.org/"
size="sm"
data-testid="openEdXPortalButton"
>
<FormattedMessage {...messages.openEdxPortalButtonLabel} />
</Button>
)}
<Button
as="a"
href="https://www.edx.org/course/edx101-overview-of-creating-an-edx-course#.VO4eaLPF-n1"
size="sm"
>
<FormattedMessage {...messages.edx101ButtonLabel} />
</Button>
<Button
as="a"
href="https://www.edx.org/course/studiox-creating-a-course-with-edx-studio"
size="sm"
>
<FormattedMessage {...messages.studioXButtonLabel} />
</Button>
{!_.isEmpty(supportEmail) && (
<Button
as="a"
href={`mailto:${supportEmail}`}
size="sm"
data-testid="contactUsButton"
>
<FormattedMessage {...messages.contactUsButtonLabel} />
</Button>
)}
<ActionRow.Spacer />
</ActionRow>
) : null}
</TransitionReplace>
<ActionRow className="pt-3 px-4 m-0 x-small">
© {new Date().getFullYear()} <Hyperlink destination={marketingBaseUrl} target="_blank" className="ml-2">{platformName}</Hyperlink>
<ActionRow.Spacer />
{!_.isEmpty(termsOfServiceUrl) && (
<Hyperlink destination={termsOfServiceUrl} data-testid="termsOfService">
{intl.formatMessage(messages.termsOfServiceLinkLabel)}
</Hyperlink>
)}{!_.isEmpty(privacyPolicyUrl) && (
<Hyperlink destination={privacyPolicyUrl} data-testid="privacyPolicy">
{intl.formatMessage(messages.privacyPolicyLinkLabel)}
</Hyperlink>
)}
{showAccessibilityPage && (
<Hyperlink
destination={`${studioBaseUrl}/accessibility`}
data-testid="accessibilityRequest"
>
{intl.formatMessage(messages.accessibilityRequestLinkLabel)}
</Hyperlink>
)}
<Hyperlink destination={lmsBaseUrl}>LMS</Hyperlink>
</ActionRow>
<ActionRow className="mt-3 mx-4 pb-4 x-small">
{/*
Site operators: Please do not remove this paragraph! this attributes back to edX and
makes your acknowledgement of edX's trademarks clear.
Translators: 'edX' and 'Open edX' are trademarks of 'edX Inc.'. Please do not translate
any of these trademarks and company names.
*/}
<FormattedMessage {...messages.trademarkMessage} />
<Hyperlink className="ml-1" destination="https://www.edx.org">edX Inc</Hyperlink>.
<ActionRow.Spacer />
<Hyperlink destination="https://open.edx.org" className="float-right">
<Image
width="120px"
alt="Powered by Open edX"
src="https://logos.openedx.org/open-edx-logo-tag.png"
/>
</Hyperlink>
</ActionRow>
</>
);
};

Footer.defaultProps = {
marketingBaseUrl: null,
termsOfServiceUrl: null,
privacyPolicyUrl: null,
spanishPrivacyPolicy: null,
supportEmail: null,
};

Footer.propTypes = {
marketingBaseUrl: PropTypes.string,
termsOfServiceUrl: PropTypes.string,
privacyPolicyUrl: PropTypes.string,
spanishPrivacyPolicy: PropTypes.string,
supportEmail: PropTypes.string,
platformName: PropTypes.string.isRequired,
lmsBaseUrl: PropTypes.string.isRequired,
studioBaseUrl: PropTypes.string.isRequired,
showAccessibilityPage: PropTypes.bool.isRequired,
// injected
intl: intlShape.isRequired,
};

export default injectIntl(Footer);
120 changes: 120 additions & 0 deletions src/footer/Footer.test.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import React from 'react';
import { fireEvent, render, screen } from '@testing-library/react';
import '@testing-library/jest-dom/extend-expect';
import { IntlProvider } from '@edx/frontend-platform/i18n';
import { formatMessage } from '../testUtils';
import Footer from './Footer';
import messages from './messages';

const renderComponent = (
termsOfServiceUrl,
privacyPolicyUrl,
supportEmail,
showAccessibilityPage,
platformName,
) => {
render(
<IntlProvider locale="en">
<Footer
marketingBaseUrl="#"
termsOfServiceUrl={termsOfServiceUrl}
privacyPolicyUrl={privacyPolicyUrl}
supportEmail={supportEmail}
platformName={platformName || 'Test Platform'}
lmsBaseUrl="#"
studioBaseUrl="#"
showAccessibilityPage={showAccessibilityPage || false}
intl={{ formatMessage }}
/>
</IntlProvider>,
);
};

jest.unmock('@edx/paragon');

describe('Footer', () => {
describe('help section default view', () => {
it('help button should read Looking for help with Studio?', () => {
renderComponent();
expect(screen.getByText(messages.openHelpButtonLabel.defaultMessage))
.toBeVisible();
});
it('help button link row should not be visible', () => {
renderComponent();
expect(screen.queryByTestId('helpButtonRow')).toBeNull();
});
});
describe('help section expanded view', () => {
it('help button should read Hide Studio help', () => {
renderComponent();
const helpToggleButton = screen.getByText(messages.openHelpButtonLabel.defaultMessage);
fireEvent.click(helpToggleButton);
expect(screen.getByText(messages.closeHelpButtonLabel.defaultMessage))
.toBeVisible();
});
it('help button link row should be visible', () => {
renderComponent();
const helpToggleButton = screen.getByText(messages.openHelpButtonLabel.defaultMessage);
fireEvent.click(helpToggleButton);
expect(screen.getByTestId('helpButtonRow')).toBeVisible();
});
describe('portal button', () => {
it('should equal edX partner portal and edX equals platform name', () => {
renderComponent(null, null, null, false, 'edX');
const helpToggleButton = screen.getByText(messages.openHelpButtonLabel.defaultMessage);
fireEvent.click(helpToggleButton);
expect(screen.getByTestId('edXPortalButton')).toBeVisible();
expect(screen.queryByTestId('openEdXPortalButton')).toBeNull();
});
it('should equal Open edX portal and edX does not equal platform name', () => {
renderComponent();
const helpToggleButton = screen.getByText(messages.openHelpButtonLabel.defaultMessage);
fireEvent.click(helpToggleButton);
expect(screen.queryByTestId('edXPortalButton')).toBeNull();
expect(screen.getByTestId('openEdXPortalButton')).toBeVisible();
});
});
it('should not show contact us button', () => {
renderComponent();
const helpToggleButton = screen.getByText(messages.openHelpButtonLabel.defaultMessage);
fireEvent.click(helpToggleButton);
expect(screen.queryByTestId('contactUsButton')).toBeNull();
});
it('should show contact us button', () => {
renderComponent(null, null, '[email protected]', false, null);
const helpToggleButton = screen.getByText(messages.openHelpButtonLabel.defaultMessage);
fireEvent.click(helpToggleButton);
expect(screen.getByTestId('contactUsButton')).toBeVisible();
});
});
describe('policy link row', () => {
it('should only show LMS link', () => {
renderComponent();
expect(screen.getByText('LMS')).toBeVisible();
expect(screen.queryByTestId('termsOfService')).toBeNull();
expect(screen.queryByTestId('privacyPolicy')).toBeNull();
expect(screen.queryByTestId('accessibilityRequest')).toBeNull();
});
it('should show terms of service link', () => {
renderComponent('termsofserviceurl', null, null, false, null);
expect(screen.getByText('LMS')).toBeVisible();
expect(screen.queryByTestId('termsOfService')).toBeVisible();
expect(screen.queryByTestId('privacyPolicy')).toBeNull();
expect(screen.queryByTestId('accessibilityRequest')).toBeNull();
});
it('should show privacy policy link', () => {
renderComponent(null, 'privacypolicyurl', null, false, null);
expect(screen.getByText('LMS')).toBeVisible();
expect(screen.queryByTestId('termsOfService')).toBeNull();
expect(screen.queryByTestId('privacyPolicy')).toBeVisible();
expect(screen.queryByTestId('accessibilityRequest')).toBeNull();
});
it('should show accessibilty request link', () => {
renderComponent(null, null, null, true, null);
expect(screen.getByText('LMS')).toBeVisible();
expect(screen.queryByTestId('termsOfService')).toBeNull();
expect(screen.queryByTestId('privacyPolicy')).toBeNull();
expect(screen.queryByTestId('accessibilityRequest')).toBeVisible();
});
});
});
3 changes: 3 additions & 0 deletions src/footer/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import Footer from './Footer';

export default Footer;
66 changes: 66 additions & 0 deletions src/footer/messages.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { defineMessages } from '@edx/frontend-platform/i18n';

const messages = defineMessages({
openHelpButtonLabel: {
id: 'authoring.footer.help.openHelp.button.label',
defaultMessage: 'Looking for help with Studio?',
description: 'Label for button that opens the collapsed section with help buttons',
},
closeHelpButtonLabel: {
id: 'authoring.footer.help.closeHelp.button.label',
defaultMessage: 'Hide Studio help',
description: 'Label for button that closes the collapsed section with help buttons',
},
edxDocumentationButtonLabel: {
id: 'authoring.footer.help.edxDocumentation.button.label',
defaultMessage: 'edX documentation',
description: 'Label for button that links to the edX documentation site',
},
parnterPortalButtonLabel: {
id: 'authoring.footer.help.parnterPortal.button.label',
defaultMessage: 'edX partner portal',
description: 'Label for button that links to the edX partner portal',
},
openEdxPortalButtonLabel: {
id: 'authoring.footer.help.openEdxPortal.button.label',
defaultMessage: 'Open edX portal',
description: 'Label for button that links to the Open edX portal',
},
edx101ButtonLabel: {
id: 'authoring.footer.help.edx101.button.label',
defaultMessage: 'Enroll in edX 101',
description: 'Label for button that links to the edX 101 course',
},
studioXButtonLabel: {
id: 'authoring.footer.help.studioX.button.label',
defaultMessage: 'Enroll in StudioX',
description: 'Label for button that links to the edX StudioX course',
},
contactUsButtonLabel: {
id: 'authoring.footer.help.contactUs.button.label',
defaultMessage: 'Contact us',
description: 'Label for button that links to the email for partner support',
},
termsOfServiceLinkLabel: {
id: 'authoring.footer.termsOfService.link.label',
defaultMessage: 'Terms of Service',
description: 'Label for button that links to the terms of service page',
},
privacyPolicyLinkLabel: {
id: 'authoring.footer.privacyPolicy.link.label',
defaultMessage: 'Privacy Policy',
description: 'Label for button that links to the privacy policy page',
},
accessibilityRequestLinkLabel: {
id: 'authoring.footer.accessibilityRequest.link.label',
defaultMessage: 'Accessibility Accomodation Request',
description: 'Label for button that links to the accessibility accomodation requests page',
},
trademarkMessage: {
id: 'authoring.footer.trademark.message',
defaultMessage: 'edX and Open edX, and the edX and Open edX logos are registered trademarks of',
description: 'Message about the use of logos and names edX and Open edX',
},
});

export default messages;
Loading

0 comments on commit 3586307

Please sign in to comment.