feat: use frontend-plugin-framework to provide a FooterSlot

This commit is contained in:
Brian Smith
2024-05-10 12:03:44 -04:00
parent 61d881b1cd
commit 17eff1da7b
13 changed files with 176 additions and 587 deletions

View File

@@ -6,7 +6,7 @@ import { logError } from '@edx/frontend-platform/logging';
import { initializeHotjar } from '@edx/frontend-enterprise-hotjar';
import { ErrorPage, AppContext } from '@edx/frontend-platform/react';
import Footer from '@edx/frontend-component-footer';
import FooterSlot from '@openedx/frontend-slot-footer';
import { Alert } from '@openedx/paragon';
import { RequestKeys } from 'data/constants/requests';
@@ -109,7 +109,7 @@ export const App = () => {
)}
</main>
</AppWrapper>
<Footer logo={getConfig().LOGO_POWERED_BY_OPEN_EDX_URL_SVG} />
<FooterSlot />
<ZendeskFab />
</div>
</>

View File

@@ -2,7 +2,6 @@ import React from 'react';
import { Helmet } from 'react-helmet';
import { shallow } from '@edx/react-unit-test-utils';
import Footer from '@edx/frontend-component-footer';
import { useIntl } from '@edx/frontend-platform/i18n';
import { getConfig } from '@edx/frontend-platform';
@@ -15,7 +14,7 @@ import { ExperimentProvider } from 'ExperimentContext';
import { App } from './App';
import messages from './messages';
jest.mock('@edx/frontend-component-footer', () => 'Footer');
jest.mock('@edx/frontend-component-footer', () => ({ FooterSlot: 'Footer' }));
jest.mock('containers/Dashboard', () => 'Dashboard');
jest.mock('containers/LearnerDashboardHeader', () => 'LearnerDashboardHeader');
@@ -38,8 +37,6 @@ jest.mock('hooks', () => ({
}));
jest.mock('data/store', () => 'data/store');
const logo = 'fakeLogo.png';
jest.mock('@edx/frontend-platform', () => ({
getConfig: jest.fn(() => ({})),
}));
@@ -66,9 +63,6 @@ describe('App router component', () => {
it('displays learner dashboard header', () => {
expect(el.instance.findByType(LearnerDashboardHeader).length).toEqual(1);
});
test('Footer logo drawn from env variable', () => {
expect(el.instance.findByType(Footer)[0].props.logo).toEqual(logo);
});
it('wraps the header and main components in an AppWrapper widget container', () => {
const container = el.instance.findByType(AppWrapper)[0];
expect(container.children[0].type).toEqual('LearnerDashboardHeader');
@@ -78,7 +72,7 @@ describe('App router component', () => {
describe('no network failure', () => {
beforeAll(() => {
reduxHooks.useRequestIsFailed.mockReturnValue(false);
getConfig.mockReturnValue({ LOGO_POWERED_BY_OPEN_EDX_URL_SVG: logo });
getConfig.mockReturnValue({});
el = shallow(<App />);
});
runBasicTests();
@@ -96,7 +90,7 @@ describe('App router component', () => {
describe('no network failure with optimizely url', () => {
beforeAll(() => {
reduxHooks.useRequestIsFailed.mockReturnValue(false);
getConfig.mockReturnValue({ LOGO_POWERED_BY_OPEN_EDX_URL_SVG: logo, OPTIMIZELY_URL: 'fake.url' });
getConfig.mockReturnValue({ OPTIMIZELY_URL: 'fake.url' });
el = shallow(<App />);
});
runBasicTests();
@@ -114,7 +108,7 @@ describe('App router component', () => {
describe('no network failure with optimizely project id', () => {
beforeAll(() => {
reduxHooks.useRequestIsFailed.mockReturnValue(false);
getConfig.mockReturnValue({ LOGO_POWERED_BY_OPEN_EDX_URL_SVG: logo, OPTIMIZELY_PROJECT_ID: 'fakeId' });
getConfig.mockReturnValue({ OPTIMIZELY_PROJECT_ID: 'fakeId' });
el = shallow(<App />);
});
runBasicTests();
@@ -132,7 +126,7 @@ describe('App router component', () => {
describe('initialize failure', () => {
beforeAll(() => {
reduxHooks.useRequestIsFailed.mockImplementation((key) => key === RequestKeys.initialize);
getConfig.mockReturnValue({ LOGO_POWERED_BY_OPEN_EDX_URL_SVG: logo });
getConfig.mockReturnValue({});
el = shallow(<App />);
});
runBasicTests();
@@ -150,7 +144,7 @@ describe('App router component', () => {
describe('refresh failure', () => {
beforeAll(() => {
reduxHooks.useRequestIsFailed.mockImplementation((key) => key === RequestKeys.refreshList);
getConfig.mockReturnValue({ LOGO_POWERED_BY_OPEN_EDX_URL_SVG: logo });
getConfig.mockReturnValue({});
el = shallow(<App />);
});
runBasicTests();

View File

@@ -27,9 +27,7 @@ exports[`App router component component initialize failure snapshot 1`] = `
</Alert>
</main>
</AppWrapper>
<Footer
logo="fakeLogo.png"
/>
<FooterSlot />
<ZendeskFab />
</div>
</Fragment>
@@ -58,9 +56,7 @@ exports[`App router component component no network failure snapshot 1`] = `
</ExperimentProvider>
</main>
</AppWrapper>
<Footer
logo="fakeLogo.png"
/>
<FooterSlot />
<ZendeskFab />
</div>
</Fragment>
@@ -92,9 +88,7 @@ exports[`App router component component no network failure with optimizely proje
</ExperimentProvider>
</main>
</AppWrapper>
<Footer
logo="fakeLogo.png"
/>
<FooterSlot />
<ZendeskFab />
</div>
</Fragment>
@@ -126,9 +120,7 @@ exports[`App router component component no network failure with optimizely url s
</ExperimentProvider>
</main>
</AppWrapper>
<Footer
logo="fakeLogo.png"
/>
<FooterSlot />
<ZendeskFab />
</div>
</Fragment>
@@ -161,9 +153,7 @@ exports[`App router component component refresh failure snapshot 1`] = `
</Alert>
</main>
</AppWrapper>
<Footer
logo="fakeLogo.png"
/>
<FooterSlot />
<ZendeskFab />
</div>
</Fragment>

View File

@@ -0,0 +1,50 @@
# Footer Slot
### Slot ID: `footer_slot`
## Description
This slot is used to replace/modify/hide the footer.
The implementation of the `FooterSlot` component lives in [the `frontend-slot-footer` repository](https://github.com/openedx/frontend-slot-footer/).
## Example
The following `env.config.jsx` will replace the default footer.
![Screenshot of Default Footer](./images/default_footer.png)
with a simple custom footer
![Screenshot of Custom Footer](./images/custom_footer.png)
```jsx
import { DIRECT_PLUGIN, PLUGIN_OPERATIONS } from '@openedx/frontend-plugin-framework';
const config = {
pluginSlots: {
footer_slot: {
plugins: [
{
// Hide the default footer
op: PLUGIN_OPERATIONS.Hide,
widgetId: 'default_contents',
},
{
// Insert a custom footer
op: PLUGIN_OPERATIONS.Insert,
widget: {
id: 'custom_footer',
type: DIRECT_PLUGIN,
RenderWidget: () => (
<h1 style={{textAlign: 'center'}}>🦶</h1>
),
},
},
]
}
},
}
export default config;
```

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

View File

@@ -0,0 +1,3 @@
# `frontend-app-learner-dashboard` Plugin Slots
* [`footer_slot`](./FooterSlot/)