Skip to content

Commit

Permalink
feat: add user menu slots in header
Browse files Browse the repository at this point in the history
  • Loading branch information
syedsajjadkazmii authored and mubbsharanwar committed Aug 2, 2024
1 parent 6e3948a commit 1642a6e
Show file tree
Hide file tree
Showing 18 changed files with 253 additions and 1 deletion.
6 changes: 6 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,12 @@ Usage

``import Header, { messages } from '@edx/frontend-component-header-edx';``

Plugins
=======
This component can be customized using `Frontend Plugin Framework <https://github.com/openedx/frontend-plugin-framework>`_.

The parts of this component that can be customized in that manner are documented `here </src/plugin-slots>`_.

Development
===========

Expand Down
50 changes: 50 additions & 0 deletions package-lock.json

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

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
"@fortawesome/free-regular-svg-icons": "^6.6.0",
"@fortawesome/free-solid-svg-icons": "^6.6.0",
"@fortawesome/react-fontawesome": "^0.2.0",
"@openedx/frontend-plugin-framework": "^1.2.1",
"@openedx/paragon": "^21.11.0",
"@reduxjs/toolkit": "1.9.7",
"axios-mock-adapter": "1.22.0",
Expand Down
4 changes: 4 additions & 0 deletions src/DesktopHeader.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { getConfig } from '@edx/frontend-platform';
import { AvatarButton, Dropdown } from '@openedx/paragon';

// Local Components
import UserMenuGroupItemSlot from './plugin-slots/UserMenuGroupItemSlot';
import UserMenuGroupSlot from './plugin-slots/UserMenuGroupSlot';
import UserMenuItem from './common/UserMenuItem';
import { Menu, MenuTrigger, MenuContent } from './Menu';
import { LinkedLogo, Logo } from './Logo';
Expand Down Expand Up @@ -104,10 +106,12 @@ class DesktopHeader extends React.Component {
/>
</Dropdown.Item>
)}
<UserMenuGroupSlot />
{userMenu.map((group, index) => (
// eslint-disable-next-line react/jsx-no-comment-textnodes,react/no-array-index-key
<React.Fragment key={index}>
{group.heading && <Dropdown.Header>{group.heading}</Dropdown.Header>}
{index === 0 && (<UserMenuGroupItemSlot />)}
{group.items.map(({
type, content, href, disabled, isActive, onClick,
}) => (
Expand Down
9 changes: 8 additions & 1 deletion src/MobileHeader.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { getConfig } from '@edx/frontend-platform';

// Local Components
import { AvatarButton } from '@openedx/paragon';
import UserMenuGroupSlot from './plugin-slots/UserMenuGroupSlot';
import UserMenuGroupItemSlot from './plugin-slots/UserMenuGroupItemSlot';
import { Menu, MenuTrigger, MenuContent } from './Menu';
import { LinkedLogo, Logo } from './Logo';
import UserMenuItem from './common/UserMenuItem';
Expand Down Expand Up @@ -97,7 +99,12 @@ class MobileHeader extends React.Component {
))
));

return userInfoItem ? [userInfoItem, ...userMenuItems] : userMenuItems;
const userMenuGroupSlot = <UserMenuGroupSlot />;
const userMenuGroupItemSlot = <UserMenuGroupItemSlot />;

return userInfoItem
? [userInfoItem, userMenuGroupSlot, userMenuGroupItemSlot, ...userMenuItems]
: [userMenuGroupSlot, userMenuGroupItemSlot, ...userMenuItems];
}

renderLoggedOutItems() {
Expand Down
4 changes: 4 additions & 0 deletions src/plugin-slots/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# `frontend-component-header-edx` Plugin Slots

* [`header_user_menu_group_slot`](./UserMenuGroupSlot/)
* [`header_user_menu_group_item_slot`](./UserMenuGroupItemSlot/)
72 changes: 72 additions & 0 deletions src/plugin-slots/UserMenuGroupItemSlot/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# Header User Menu Group Slot

### Slot ID: `header_user_menu_group_item_slot`

## Description

This slot allows you to insert a user menu item into a group within the header's user menu for both desktop and mobile screens.

Note: Ensure the slot is provided with appropriate JSX that can render smoothly on both desktop and mobile screens.

## Example

The following ``env.config.jsx`` demonstrates how to insert a user menu item into a group within the header's user menu
for both desktop and mobile screens.

**Default Behaviour:**

Desktop:
![Screenshot of Default Header_User_Menu](./images/default_user_menu_desktop.png)

Mobile:
![Screenshot of Default Header_User_Menu](./images/default_user_menu_mobile.png)

**Inserted a user menu group:**

Desktop:
![Screenshot of Inserted_User_Menu_Group](./images/inserted_user_menu_item_desktop.png)

Mobile:
![Screenshot of Inserted_User_Menu_Group](./images/inserted_user_menu_item_mobile.png)

```jsx
import { DIRECT_PLUGIN, PLUGIN_OPERATIONS } from '@openedx/frontend-plugin-framework';
import { breakpoints, Dropdown, useWindowSize } from '@openedx/paragon';

const config = {
pluginSlots: {
header_user_menu_group_slot: {
plugins: [
{
// Insert some user menu group item
op: PLUGIN_OPERATIONS.Insert,
widget: {
id: 'user_menu_group',
type: DIRECT_PLUGIN,
RenderWidget: () => {
const { width } = useWindowSize();
const isMobile = width <= breakpoints.small.maxWidth;
if (!isMobile) {
return (
<Dropdown.Item as="a" href="#">
User Menu Group Item
</Dropdown.Item>
);
}
return (
<li className="nav-item">
<a href="#" className="nav-link">
User Menu Group Item
</a>
</li>
);
},
},
},
],
},
},
}

export default config;
```
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 11 additions & 0 deletions src/plugin-slots/UserMenuGroupItemSlot/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import React from 'react';

import { PluginSlot } from '@openedx/frontend-plugin-framework';

const UserMenuGroupItemSlot = () => (
<PluginSlot
id="header_user_menu_group_item_slot"
/>
);

export default UserMenuGroupItemSlot;
86 changes: 86 additions & 0 deletions src/plugin-slots/UserMenuGroupSlot/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# Header User Menu Group Slot

### Slot ID: `header_user_menu_group_slot`

## Description

This slot is used to insert a user menu group in the header's user menu for both desktop and mobile screens.

Note: Ensure the slot is provided with appropriate JSX that can render smoothly on both desktop and mobile screens.

## Example

The following ``env.config.jsx`` demonstrates how to insert a user menu group into the header's user menu
for both mobile and desktop screens.

**Default Behaviour:**

Desktop:
![Screenshot of Default Header_User_Menu_Desktop](./images/default_user_menu_desktop.png)

Mobile:
![Screenshot of Default Header_User_Menu_Mobile](./images/default_user_menu_mobile.png)

**Inserted a user menu group:**

Desktop:
![Screenshot of Inserted_User_Menu_Group_Desktop](./images/inserted_user_menu_desktop.png)

Mobile:
![Screenshot of Inserted_User_Menu_Group_Mobile](./images/inserted_user_menu_mobile.png)

```jsx
import { DIRECT_PLUGIN, PLUGIN_OPERATIONS } from '@openedx/frontend-plugin-framework';
import { breakpoints, Dropdown, useWindowSize } from '@openedx/paragon';

const config = {
pluginSlots: {
header_user_menu_group_slot: {
plugins: [
{
// Insert some user menu group
op: PLUGIN_OPERATIONS.Insert,
widget: {
id: 'user_menu_group',
type: DIRECT_PLUGIN,
RenderWidget: () => {
const { width } = useWindowSize();
const isMobile = width <= breakpoints.small.maxWidth;
if (!isMobile) {
return (
<>
<Dropdown.Header>User Menu Group Header</Dropdown.Header>
<Dropdown.Item as="a" href="#" className="active">
User Menu Group Item - Active
</Dropdown.Item>
<Dropdown.Item as="a" href="#">
User Menu Group Item 2
</Dropdown.Item>
<Dropdown.Divider />
</>
);
}
return (
<>
<li className="nav-item">
<a href="#" className="nav-link active">
User Menu Group Item - Active
</a>
</li>
<li className="nav-item">
<a href="#" className="nav-link active">
User Menu Group Item 2
</a>
</li>
</>
);
},
},
},
],
},
},
}

export default config;
```
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 11 additions & 0 deletions src/plugin-slots/UserMenuGroupSlot/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import React from 'react';

import { PluginSlot } from '@openedx/frontend-plugin-framework';

const UserMenuGroupSlot = () => (
<PluginSlot
id="header_user_menu_group_slot"
/>
);

export default UserMenuGroupSlot;

0 comments on commit 1642a6e

Please sign in to comment.