@epec-fcfm-uchile/frontend-component-header 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (180) hide show
  1. package/LICENSE +661 -0
  2. package/README.rst +194 -0
  3. package/dist/Avatar.js +43 -0
  4. package/dist/Avatar.js.map +1 -0
  5. package/dist/Header.js +120 -0
  6. package/dist/Header.js.map +1 -0
  7. package/dist/Header.messages.js +110 -0
  8. package/dist/Header.messages.js.map +1 -0
  9. package/dist/Header.test.jsx +107 -0
  10. package/dist/Icons.js +52 -0
  11. package/dist/Icons.js.map +1 -0
  12. package/dist/Logo.js +28 -0
  13. package/dist/Logo.js.map +1 -0
  14. package/dist/Menu/Menu.js +321 -0
  15. package/dist/Menu/Menu.js.map +1 -0
  16. package/dist/Menu/index.js +3 -0
  17. package/dist/Menu/index.js.map +1 -0
  18. package/dist/Menu/menu.scss +45 -0
  19. package/dist/__snapshots__/Header.test.jsx.snap +445 -0
  20. package/dist/desktop-header/DesktopHeader.js +129 -0
  21. package/dist/desktop-header/DesktopHeader.js.map +1 -0
  22. package/dist/desktop-header/DesktopHeaderMainOrSecondaryMenu.js +51 -0
  23. package/dist/desktop-header/DesktopHeaderMainOrSecondaryMenu.js.map +1 -0
  24. package/dist/desktop-header/DesktopHeaderUserMenu.js +49 -0
  25. package/dist/desktop-header/DesktopHeaderUserMenu.js.map +1 -0
  26. package/dist/desktop-header/DesktopLoggedOutItems.js +22 -0
  27. package/dist/desktop-header/DesktopLoggedOutItems.js.map +1 -0
  28. package/dist/desktop-header/DesktopUserMenuToggle.js +25 -0
  29. package/dist/desktop-header/DesktopUserMenuToggle.js.map +1 -0
  30. package/dist/frontend-platform.d.ts +41 -0
  31. package/dist/generic/messages.js +15 -0
  32. package/dist/generic/messages.js.map +1 -0
  33. package/dist/i18n/index.js +2 -0
  34. package/dist/i18n/index.js.map +1 -0
  35. package/dist/index.js +7 -0
  36. package/dist/index.js.map +1 -0
  37. package/dist/index.scss +137 -0
  38. package/dist/learning-header/AnonymousUserMenu.js +22 -0
  39. package/dist/learning-header/AnonymousUserMenu.js.map +1 -0
  40. package/dist/learning-header/AuthenticatedUserDropdown.js +53 -0
  41. package/dist/learning-header/AuthenticatedUserDropdown.js.map +1 -0
  42. package/dist/learning-header/LearningHeader.js +59 -0
  43. package/dist/learning-header/LearningHeader.js.map +1 -0
  44. package/dist/learning-header/LearningHeaderCourseInfo.js +24 -0
  45. package/dist/learning-header/LearningHeaderCourseInfo.js.map +1 -0
  46. package/dist/learning-header/LearningHeaderHelpLink.js +13 -0
  47. package/dist/learning-header/LearningHeaderHelpLink.js.map +1 -0
  48. package/dist/learning-header/LearningHeaderUserMenuItems.js +20 -0
  49. package/dist/learning-header/LearningHeaderUserMenuItems.js.map +1 -0
  50. package/dist/learning-header/LearningLoggedOutButtons.js +24 -0
  51. package/dist/learning-header/LearningLoggedOutButtons.js.map +1 -0
  52. package/dist/learning-header/LearningUserMenuToggle.js +26 -0
  53. package/dist/learning-header/LearningUserMenuToggle.js.map +1 -0
  54. package/dist/learning-header/messages.js +45 -0
  55. package/dist/learning-header/messages.js.map +1 -0
  56. package/dist/mobile-header/MobileHeader.js +157 -0
  57. package/dist/mobile-header/MobileHeader.js.map +1 -0
  58. package/dist/mobile-header/MobileHeaderMainMenu.js +46 -0
  59. package/dist/mobile-header/MobileHeaderMainMenu.js.map +1 -0
  60. package/dist/mobile-header/MobileHeaderUserMenu.js +38 -0
  61. package/dist/mobile-header/MobileHeaderUserMenu.js.map +1 -0
  62. package/dist/mobile-header/MobileLoggedOutItems.js +27 -0
  63. package/dist/mobile-header/MobileLoggedOutItems.js.map +1 -0
  64. package/dist/mobile-header/MobileUserMenuToggle.js +19 -0
  65. package/dist/mobile-header/MobileUserMenuToggle.js.map +1 -0
  66. package/dist/plugin-slots/CourseInfoSlot/README.md +128 -0
  67. package/dist/plugin-slots/CourseInfoSlot/images/add_custom_components_before_and_after_course_info.png +0 -0
  68. package/dist/plugin-slots/CourseInfoSlot/images/replace_course_info_with_custom_component.png +0 -0
  69. package/dist/plugin-slots/CourseInfoSlot/images/replace_course_title.png +0 -0
  70. package/dist/plugin-slots/CourseInfoSlot/index.js +32 -0
  71. package/dist/plugin-slots/CourseInfoSlot/index.js.map +1 -0
  72. package/dist/plugin-slots/DesktopHeaderSlot/README.md +44 -0
  73. package/dist/plugin-slots/DesktopHeaderSlot/images/desktop_header_custom_component.png +0 -0
  74. package/dist/plugin-slots/DesktopHeaderSlot/index.js +16 -0
  75. package/dist/plugin-slots/DesktopHeaderSlot/index.js.map +1 -0
  76. package/dist/plugin-slots/DesktopLoggedOutItemsSlot/README.md +137 -0
  77. package/dist/plugin-slots/DesktopLoggedOutItemsSlot/images/desktop_logged_out_items_custom_component.png +0 -0
  78. package/dist/plugin-slots/DesktopLoggedOutItemsSlot/images/desktop_logged_out_items_custom_components_before_after.png +0 -0
  79. package/dist/plugin-slots/DesktopLoggedOutItemsSlot/images/desktop_logged_out_items_modify_items.png +0 -0
  80. package/dist/plugin-slots/DesktopLoggedOutItemsSlot/index.js +20 -0
  81. package/dist/plugin-slots/DesktopLoggedOutItemsSlot/index.js.map +1 -0
  82. package/dist/plugin-slots/DesktopMainMenuSlot/README.md +190 -0
  83. package/dist/plugin-slots/DesktopMainMenuSlot/images/desktop_main_menu_add_items.png +0 -0
  84. package/dist/plugin-slots/DesktopMainMenuSlot/images/desktop_main_menu_custom_component.png +0 -0
  85. package/dist/plugin-slots/DesktopMainMenuSlot/images/desktop_main_menu_custom_components_before_after.png +0 -0
  86. package/dist/plugin-slots/DesktopMainMenuSlot/images/desktop_main_menu_replace_all_items.png +0 -0
  87. package/dist/plugin-slots/DesktopMainMenuSlot/index.js +20 -0
  88. package/dist/plugin-slots/DesktopMainMenuSlot/index.js.map +1 -0
  89. package/dist/plugin-slots/DesktopSecondaryMenuSlot/README.md +132 -0
  90. package/dist/plugin-slots/DesktopSecondaryMenuSlot/images/desktop_secondary_menu_custom_component.png +0 -0
  91. package/dist/plugin-slots/DesktopSecondaryMenuSlot/images/desktop_secondary_menu_custom_components_before_after.png +0 -0
  92. package/dist/plugin-slots/DesktopSecondaryMenuSlot/images/desktop_secondary_menu_modify_items.png +0 -0
  93. package/dist/plugin-slots/DesktopSecondaryMenuSlot/index.js +20 -0
  94. package/dist/plugin-slots/DesktopSecondaryMenuSlot/index.js.map +1 -0
  95. package/dist/plugin-slots/DesktopUserMenuSlot/README.md +144 -0
  96. package/dist/plugin-slots/DesktopUserMenuSlot/images/desktop_user_menu_custom_component.png +0 -0
  97. package/dist/plugin-slots/DesktopUserMenuSlot/images/desktop_user_menu_custom_components_before_after.png +0 -0
  98. package/dist/plugin-slots/DesktopUserMenuSlot/images/desktop_user_menu_modify_items.png +0 -0
  99. package/dist/plugin-slots/DesktopUserMenuSlot/index.js +20 -0
  100. package/dist/plugin-slots/DesktopUserMenuSlot/index.js.map +1 -0
  101. package/dist/plugin-slots/DesktopUserMenuToggleSlot/README.md +74 -0
  102. package/dist/plugin-slots/DesktopUserMenuToggleSlot/images/desktop_user_menu_custom_component.png +0 -0
  103. package/dist/plugin-slots/DesktopUserMenuToggleSlot/images/desktop_user_menu_modified_toggle.png +0 -0
  104. package/dist/plugin-slots/DesktopUserMenuToggleSlot/index.js +19 -0
  105. package/dist/plugin-slots/DesktopUserMenuToggleSlot/index.js.map +1 -0
  106. package/dist/plugin-slots/LearningHelpSlot/README.md +44 -0
  107. package/dist/plugin-slots/LearningHelpSlot/images/learning_help_custom_component.png +0 -0
  108. package/dist/plugin-slots/LearningHelpSlot/index.js +11 -0
  109. package/dist/plugin-slots/LearningHelpSlot/index.js.map +1 -0
  110. package/dist/plugin-slots/LearningLoggedOutItemsSlot/README.md +135 -0
  111. package/dist/plugin-slots/LearningLoggedOutItemsSlot/images/learning_logged_out_items_custom_component.png +0 -0
  112. package/dist/plugin-slots/LearningLoggedOutItemsSlot/images/learning_logged_out_items_custom_components_before_after.png +0 -0
  113. package/dist/plugin-slots/LearningLoggedOutItemsSlot/images/learning_logged_out_items_modified_items.png +0 -0
  114. package/dist/plugin-slots/LearningLoggedOutItemsSlot/index.js +18 -0
  115. package/dist/plugin-slots/LearningLoggedOutItemsSlot/index.js.map +1 -0
  116. package/dist/plugin-slots/LearningUserMenuSlot/README.md +133 -0
  117. package/dist/plugin-slots/LearningUserMenuSlot/images/learning_user_menu_custom_component.png +0 -0
  118. package/dist/plugin-slots/LearningUserMenuSlot/images/learning_user_menu_custom_components_before_after.png +0 -0
  119. package/dist/plugin-slots/LearningUserMenuSlot/images/learning_user_menu_modified_items.png +0 -0
  120. package/dist/plugin-slots/LearningUserMenuSlot/index.js +18 -0
  121. package/dist/plugin-slots/LearningUserMenuSlot/index.js.map +1 -0
  122. package/dist/plugin-slots/LearningUserMenuToggleSlot/README.md +74 -0
  123. package/dist/plugin-slots/LearningUserMenuToggleSlot/images/learning_user_menu_toggle_custom_component.png +0 -0
  124. package/dist/plugin-slots/LearningUserMenuToggleSlot/images/learning_user_menu_toggle_modified_items.png +0 -0
  125. package/dist/plugin-slots/LearningUserMenuToggleSlot/index.js +19 -0
  126. package/dist/plugin-slots/LearningUserMenuToggleSlot/index.js.map +1 -0
  127. package/dist/plugin-slots/LogoSlot/README.md +72 -0
  128. package/dist/plugin-slots/LogoSlot/index.js +27 -0
  129. package/dist/plugin-slots/LogoSlot/index.js.map +1 -0
  130. package/dist/plugin-slots/MobileHeaderSlot/README.md +44 -0
  131. package/dist/plugin-slots/MobileHeaderSlot/images/mobile_header_custom_component.png +0 -0
  132. package/dist/plugin-slots/MobileHeaderSlot/index.js +16 -0
  133. package/dist/plugin-slots/MobileHeaderSlot/index.js.map +1 -0
  134. package/dist/plugin-slots/MobileLoggedOutItemsSlot/README.md +136 -0
  135. package/dist/plugin-slots/MobileLoggedOutItemsSlot/images/mobile_logged_out_items_custom_component.png +0 -0
  136. package/dist/plugin-slots/MobileLoggedOutItemsSlot/images/mobile_logged_out_items_custom_components_before_after.png +0 -0
  137. package/dist/plugin-slots/MobileLoggedOutItemsSlot/images/mobile_logged_out_items_modify_items.png +0 -0
  138. package/dist/plugin-slots/MobileLoggedOutItemsSlot/index.js +20 -0
  139. package/dist/plugin-slots/MobileLoggedOutItemsSlot/index.js.map +1 -0
  140. package/dist/plugin-slots/MobileMainMenuSlot/README.md +190 -0
  141. package/dist/plugin-slots/MobileMainMenuSlot/images/mobile_main_menu_add_items.png +0 -0
  142. package/dist/plugin-slots/MobileMainMenuSlot/images/mobile_main_menu_custom_component.png +0 -0
  143. package/dist/plugin-slots/MobileMainMenuSlot/images/mobile_main_menu_custom_components_before_after.png +0 -0
  144. package/dist/plugin-slots/MobileMainMenuSlot/images/mobile_main_menu_replace_all_items.png +0 -0
  145. package/dist/plugin-slots/MobileMainMenuSlot/index.js +20 -0
  146. package/dist/plugin-slots/MobileMainMenuSlot/index.js.map +1 -0
  147. package/dist/plugin-slots/MobileUserMenuSlot/README.md +144 -0
  148. package/dist/plugin-slots/MobileUserMenuSlot/images/mobile_user_menu_custom_component.png +0 -0
  149. package/dist/plugin-slots/MobileUserMenuSlot/images/mobile_user_menu_custom_components_before_after.png +0 -0
  150. package/dist/plugin-slots/MobileUserMenuSlot/images/mobile_user_menu_modify_items.png +0 -0
  151. package/dist/plugin-slots/MobileUserMenuSlot/index.js +20 -0
  152. package/dist/plugin-slots/MobileUserMenuSlot/index.js.map +1 -0
  153. package/dist/plugin-slots/MobileUserMenuToggleSlot/README.md +74 -0
  154. package/dist/plugin-slots/MobileUserMenuToggleSlot/images/mobile_user_menu_toggle_custom_component.png +0 -0
  155. package/dist/plugin-slots/MobileUserMenuToggleSlot/images/mobile_user_menu_toggle_modified_items.png +0 -0
  156. package/dist/plugin-slots/MobileUserMenuToggleSlot/index.js +19 -0
  157. package/dist/plugin-slots/MobileUserMenuToggleSlot/index.js.map +1 -0
  158. package/dist/plugin-slots/README.md +26 -0
  159. package/dist/setupTest.js +123 -0
  160. package/dist/studio-header/BrandNav.test.tsx +40 -0
  161. package/dist/studio-header/BrandNav.tsx +25 -0
  162. package/dist/studio-header/CourseLockUp.test.tsx +59 -0
  163. package/dist/studio-header/CourseLockUp.tsx +58 -0
  164. package/dist/studio-header/HeaderBody.test.tsx +102 -0
  165. package/dist/studio-header/HeaderBody.tsx +196 -0
  166. package/dist/studio-header/MobileHeader.tsx +74 -0
  167. package/dist/studio-header/MobileMenu.test.tsx +81 -0
  168. package/dist/studio-header/MobileMenu.tsx +50 -0
  169. package/dist/studio-header/NavDropdownMenu.test.tsx +67 -0
  170. package/dist/studio-header/NavDropdownMenu.tsx +42 -0
  171. package/dist/studio-header/StudioHeader.scss +49 -0
  172. package/dist/studio-header/StudioHeader.test.tsx +200 -0
  173. package/dist/studio-header/StudioHeader.tsx +84 -0
  174. package/dist/studio-header/UserMenu.tsx +66 -0
  175. package/dist/studio-header/index.ts +3 -0
  176. package/dist/studio-header/messages.ts +56 -0
  177. package/dist/studio-header/utils.ts +33 -0
  178. package/dist/test-utils.js +25 -0
  179. package/dist/test-utils.js.map +1 -0
  180. package/package.json +73 -0
@@ -0,0 +1,200 @@
1
+ /* eslint-disable react/prop-types */
2
+ import React, { useMemo } from 'react';
3
+ import {
4
+ render,
5
+ fireEvent,
6
+ waitFor,
7
+ } from '@testing-library/react';
8
+
9
+ import { AppContext } from '@edx/frontend-platform/react';
10
+ import { IntlProvider } from '@edx/frontend-platform/i18n';
11
+ import { Context as ResponsiveContext } from 'react-responsive';
12
+ import { MemoryRouter } from 'react-router-dom';
13
+
14
+ import StudioHeader from './StudioHeader';
15
+
16
+ const authenticatedUser = {
17
+ userId: 3,
18
+ username: 'abc123',
19
+ administrator: true,
20
+ roles: [],
21
+ avatar: '/imges/test.png',
22
+ };
23
+ let currentUser;
24
+ let screenWidth = 1280;
25
+
26
+ const RootWrapper = ({
27
+ ...props
28
+ }: React.ComponentProps<typeof StudioHeader>) => {
29
+ const appContextValue = useMemo(() => ({
30
+ authenticatedUser: currentUser,
31
+ config: {
32
+ LOGOUT_URL: process.env.LOGOUT_URL,
33
+ LOGO_URL: process.env.LOGO_URL,
34
+ SITE_NAME: process.env.SITE_NAME,
35
+ STUDIO_BASE_URL: process.env.STUDIO_BASE_URL,
36
+ LOGIN_URL: process.env.LOGIN_URL,
37
+ },
38
+ }), []);
39
+ const responsiveContextValue = useMemo(() => ({ width: screenWidth }), []);
40
+
41
+ return (
42
+ // eslint-disable-next-line react/jsx-no-constructed-context-values, react/prop-types
43
+ <MemoryRouter>
44
+ <IntlProvider locale="en">
45
+ <AppContext.Provider value={appContextValue}>
46
+ <ResponsiveContext.Provider value={responsiveContextValue}>
47
+ <StudioHeader
48
+ {...props}
49
+ />
50
+ </ResponsiveContext.Provider>
51
+ </AppContext.Provider>
52
+ </IntlProvider>
53
+ </MemoryRouter>
54
+ );
55
+ };
56
+
57
+ const props: React.ComponentProps<typeof StudioHeader> = {
58
+ number: '123',
59
+ org: 'Ed',
60
+ title: 'test',
61
+ mainMenuDropdowns: [
62
+ {
63
+ id: 'testId',
64
+ buttonTitle: 'test',
65
+ items: [
66
+ {
67
+ title: 'link',
68
+ href: '#',
69
+ },
70
+ ],
71
+ },
72
+ ],
73
+ outlineLink: 'tEsTLInK',
74
+ searchButtonAction: null,
75
+ isNewHomePage: true,
76
+ // These default values shouldn't be needed but typescript is confused by propTypes; can remove after converting
77
+ // from propTypes to TypeScript:
78
+ containerProps: {},
79
+ isHiddenMainMenu: false,
80
+ };
81
+
82
+ describe('Header', () => {
83
+ beforeEach(() => {
84
+ jest.clearAllMocks();
85
+ currentUser = authenticatedUser;
86
+ });
87
+ describe('desktop', () => {
88
+ it('course lock up should be visible', () => {
89
+ const { getByTestId } = render(<RootWrapper {...props} />);
90
+ const courseLockUpBlock = getByTestId('course-lock-up-block');
91
+
92
+ expect(courseLockUpBlock).toBeVisible();
93
+ });
94
+
95
+ it('mobile menu should not be visible', () => {
96
+ const { queryByTestId } = render(<RootWrapper {...props} />);
97
+ const mobileMenuButton = queryByTestId('mobile-menu-button');
98
+
99
+ expect(mobileMenuButton).toBeNull();
100
+ });
101
+
102
+ it('desktop menu should be visible', () => {
103
+ const { getByTestId } = render(<RootWrapper {...props} />);
104
+ const desktopMenu = getByTestId('desktop-menu');
105
+
106
+ expect(desktopMenu).toBeVisible();
107
+ });
108
+
109
+ it('should render one dropdown', async () => {
110
+ const { getAllByRole, getByText } = render(<RootWrapper {...props} />);
111
+ const dropdownMenu = getAllByRole('button')[0];
112
+
113
+ expect(dropdownMenu).toBeVisible();
114
+
115
+ await waitFor(() => fireEvent.click(dropdownMenu));
116
+ const dropdownOption = getByText('link');
117
+
118
+ expect(dropdownOption).toBeVisible();
119
+ });
120
+
121
+ it('user menu should use avatar icon', async () => {
122
+ currentUser = { ...authenticatedUser, avatar: null };
123
+ const { getByTestId } = render(<RootWrapper {...props} />);
124
+ const avatarIcon = getByTestId('avatar-icon');
125
+
126
+ expect(avatarIcon).toBeVisible();
127
+ });
128
+
129
+ it('should hide nav items if prop isHiddenMainMenu true', async () => {
130
+ const initialProps = { ...props, isHiddenMainMenu: true };
131
+ const { queryByTestId } = render(<RootWrapper {...initialProps} />);
132
+ const desktopMenu = queryByTestId('desktop-menu');
133
+ const mobileMenuButton = queryByTestId('mobile-menu-button');
134
+
135
+ expect(mobileMenuButton).toBeNull();
136
+
137
+ expect(desktopMenu).toBeNull();
138
+ });
139
+
140
+ it('should show search button', async () => {
141
+ const testProps = { ...props, searchButtonAction: () => undefined };
142
+ const { getByRole } = render(<RootWrapper {...testProps} />);
143
+ const searchButton = getByRole('button', { name: 'Search content' });
144
+
145
+ expect(searchButton).toBeVisible();
146
+ });
147
+
148
+ it('should not show search button', async () => {
149
+ const testProps = { ...props, searchButtonAction: null };
150
+ const { queryByRole } = render(<RootWrapper {...testProps} />);
151
+ expect(queryByRole('button', { name: 'Search content' })).not.toBeInTheDocument();
152
+ });
153
+ });
154
+
155
+ describe('mobile', () => {
156
+ beforeEach(() => { screenWidth = 500; });
157
+ it('course lock up should not be visible', async () => {
158
+ const { queryByTestId } = render(<RootWrapper {...props} />);
159
+ const courseLockUpBlock = queryByTestId('course-lock-up-block');
160
+
161
+ expect(courseLockUpBlock).toBeNull();
162
+ });
163
+
164
+ it('mobile menu should be visible', async () => {
165
+ const { getByTestId } = render(<RootWrapper {...props} />);
166
+ const mobileMenuButton = getByTestId('mobile-menu-button');
167
+
168
+ expect(mobileMenuButton).toBeVisible();
169
+ await waitFor(() => fireEvent.click(mobileMenuButton));
170
+ const mobileMenu = getByTestId('mobile-menu');
171
+
172
+ expect(mobileMenu).toBeVisible();
173
+ });
174
+
175
+ it('desktop menu should not be visible', () => {
176
+ const { queryByTestId } = render(<RootWrapper {...props} />);
177
+ const desktopMenu = queryByTestId('desktop-menu');
178
+
179
+ expect(desktopMenu).toBeNull();
180
+ });
181
+
182
+ it('user menu should use avatar image', async () => {
183
+ const { getByTestId } = render(<RootWrapper {...props} />);
184
+ const avatarImage = getByTestId('avatar-image');
185
+
186
+ expect(avatarImage).toBeVisible();
187
+ });
188
+
189
+ it('should hide nav items if prop isHiddenMainMenu true', async () => {
190
+ const initialProps = { ...props, isHiddenMainMenu: true };
191
+ const { queryByTestId } = render(<RootWrapper {...initialProps} />);
192
+ const desktopMenu = queryByTestId('desktop-menu');
193
+ const mobileMenuButton = queryByTestId('mobile-menu-button');
194
+
195
+ expect(mobileMenuButton).toBeNull();
196
+
197
+ expect(desktopMenu).toBeNull();
198
+ });
199
+ });
200
+ });
@@ -0,0 +1,84 @@
1
+ import React, { useContext } from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import Responsive from 'react-responsive';
4
+ import { AppContext } from '@edx/frontend-platform/react';
5
+ import { ensureConfig } from '@edx/frontend-platform';
6
+
7
+ import MobileHeader from './MobileHeader';
8
+ import HeaderBody from './HeaderBody';
9
+
10
+ ensureConfig([
11
+ 'STUDIO_BASE_URL',
12
+ 'SITE_NAME',
13
+ 'LOGOUT_URL',
14
+ 'LOGIN_URL',
15
+ 'LOGO_URL',
16
+ ], 'Studio Header component');
17
+
18
+ const StudioHeader = ({
19
+ number, org, title, containerProps, isHiddenMainMenu, mainMenuDropdowns,
20
+ outlineLink, searchButtonAction, isNewHomePage,
21
+ }) => {
22
+ // @ts-expect-error - frontend-platform doesn't yet have type information :/
23
+ const { authenticatedUser, config } = useContext(AppContext);
24
+ const props = {
25
+ logo: config.LOGO_URL,
26
+ logoAltText: `Studio ${config.SITE_NAME}`,
27
+ number,
28
+ org,
29
+ title,
30
+ containerProps,
31
+ username: authenticatedUser?.username,
32
+ isAdmin: authenticatedUser?.administrator,
33
+ authenticatedUserAvatar: authenticatedUser?.avatar,
34
+ studioBaseUrl: isNewHomePage ? '/home' : config.STUDIO_BASE_URL,
35
+ logoutUrl: config.LOGOUT_URL,
36
+ isHiddenMainMenu,
37
+ mainMenuDropdowns,
38
+ outlineLink,
39
+ searchButtonAction,
40
+ };
41
+
42
+ return (
43
+ <div className="studio-header">
44
+ <a className="nav-skip sr-only sr-only-focusable" href="#main">Skip to content</a>
45
+ <Responsive maxWidth={841}>
46
+ <MobileHeader {...props} />
47
+ </Responsive>
48
+ <Responsive minWidth={842}>
49
+ <HeaderBody {...props} />
50
+ </Responsive>
51
+ </div>
52
+ );
53
+ };
54
+
55
+ StudioHeader.propTypes = {
56
+ number: PropTypes.string,
57
+ org: PropTypes.string,
58
+ title: PropTypes.string.isRequired,
59
+ containerProps: HeaderBody.propTypes.containerProps,
60
+ isHiddenMainMenu: PropTypes.bool,
61
+ mainMenuDropdowns: PropTypes.arrayOf(PropTypes.shape({
62
+ id: PropTypes.string,
63
+ buttonTitle: PropTypes.node,
64
+ items: PropTypes.arrayOf(PropTypes.shape({
65
+ href: PropTypes.string,
66
+ title: PropTypes.node,
67
+ })),
68
+ })),
69
+ outlineLink: PropTypes.string,
70
+ searchButtonAction: PropTypes.func,
71
+ isNewHomePage: PropTypes.bool.isRequired,
72
+ };
73
+
74
+ StudioHeader.defaultProps = {
75
+ number: '',
76
+ org: '',
77
+ containerProps: {},
78
+ isHiddenMainMenu: false,
79
+ mainMenuDropdowns: [],
80
+ outlineLink: null,
81
+ searchButtonAction: null,
82
+ };
83
+
84
+ export default StudioHeader;
@@ -0,0 +1,66 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { useIntl } from '@edx/frontend-platform/i18n';
4
+ import {
5
+ Avatar,
6
+ } from '@openedx/paragon';
7
+ import NavDropdownMenu from './NavDropdownMenu';
8
+ import getUserMenuItems from './utils';
9
+
10
+ const UserMenu = ({
11
+ username,
12
+ studioBaseUrl,
13
+ logoutUrl,
14
+ authenticatedUserAvatar,
15
+ isMobile,
16
+ isAdmin,
17
+ }) => {
18
+ const intl = useIntl();
19
+ const avatar = authenticatedUserAvatar ? (
20
+ <img
21
+ className="d-block w-100 h-100"
22
+ src={authenticatedUserAvatar}
23
+ alt={username}
24
+ data-testid="avatar-image"
25
+ />
26
+ ) : (
27
+ <Avatar
28
+ size="sm"
29
+ className="mr-2"
30
+ alt={username}
31
+ data-testid="avatar-icon"
32
+ />
33
+ );
34
+ const title = isMobile ? avatar : <>{avatar}{username}</>;
35
+
36
+ return (
37
+ <NavDropdownMenu
38
+ buttonTitle={title}
39
+ id="user-dropdown-menu"
40
+ items={getUserMenuItems({
41
+ studioBaseUrl,
42
+ logoutUrl,
43
+ intl,
44
+ isAdmin,
45
+ })}
46
+ />
47
+ );
48
+ };
49
+
50
+ UserMenu.propTypes = {
51
+ username: PropTypes.string,
52
+ studioBaseUrl: PropTypes.string.isRequired,
53
+ logoutUrl: PropTypes.string.isRequired,
54
+ authenticatedUserAvatar: PropTypes.string,
55
+ isMobile: PropTypes.bool,
56
+ isAdmin: PropTypes.bool,
57
+ };
58
+
59
+ UserMenu.defaultProps = {
60
+ isMobile: false,
61
+ isAdmin: false,
62
+ authenticatedUserAvatar: null,
63
+ username: null,
64
+ };
65
+
66
+ export default UserMenu;
@@ -0,0 +1,3 @@
1
+ import StudioHeader from './StudioHeader';
2
+
3
+ export default StudioHeader;
@@ -0,0 +1,56 @@
1
+ import { defineMessages } from '@edx/frontend-platform/i18n';
2
+
3
+ const messages = defineMessages({
4
+ 'header.user.menu.studio': {
5
+ id: 'header.user.menu.studio',
6
+ defaultMessage: 'Studio Home',
7
+ description: 'Link to Studio Home',
8
+ },
9
+ 'header.user.menu.logout': {
10
+ id: 'header.user.menu.logout',
11
+ defaultMessage: 'Logout',
12
+ description: 'Logout link',
13
+ },
14
+ 'header.label.account.menu': {
15
+ id: 'header.label.account.menu',
16
+ defaultMessage: 'Account Menu',
17
+ description: 'The aria label for the account menu trigger',
18
+ },
19
+ 'header.label.account.menu.for': {
20
+ id: 'header.label.account.menu.for',
21
+ defaultMessage: 'Account menu for {username}',
22
+ description: 'The aria label for the account menu trigger when the username is displayed in it',
23
+ },
24
+ 'header.label.main.nav': {
25
+ id: 'header.label.main.nav',
26
+ defaultMessage: 'Main',
27
+ description: 'The aria label for the main menu nav',
28
+ },
29
+ 'header.label.main.menu': {
30
+ id: 'header.label.main.menu',
31
+ defaultMessage: 'Main Menu',
32
+ description: 'The aria label for the main menu trigger',
33
+ },
34
+ 'header.label.main.header': {
35
+ id: 'header.label.main.header',
36
+ defaultMessage: 'Main',
37
+ description: 'The aria label for the main header',
38
+ },
39
+ 'header.label.secondary.nav': {
40
+ id: 'header.label.secondary.nav',
41
+ defaultMessage: 'Secondary',
42
+ description: 'The aria label for the seconary nav',
43
+ },
44
+ 'header.label.courseOutline': {
45
+ id: 'header.label.courseOutline',
46
+ defaultMessage: 'Back to course outline in Studio',
47
+ description: 'The aria label for the link back to the Studio Course Outline',
48
+ },
49
+ 'header.label.search.nav': {
50
+ id: 'header.label.search.nav',
51
+ defaultMessage: 'Search content',
52
+ description: 'The aria label for the search content button nav',
53
+ },
54
+ });
55
+
56
+ export default messages;
@@ -0,0 +1,33 @@
1
+ import messages from './messages';
2
+
3
+ const getUserMenuItems = ({
4
+ studioBaseUrl,
5
+ logoutUrl,
6
+ intl,
7
+ isAdmin,
8
+ }) => {
9
+ let items = [
10
+ {
11
+ href: `${studioBaseUrl}`,
12
+ title: intl.formatMessage(messages['header.user.menu.studio']),
13
+ }, {
14
+ href: `${logoutUrl}`,
15
+ title: intl.formatMessage(messages['header.user.menu.logout']),
16
+ },
17
+ ];
18
+ if (isAdmin) {
19
+ items = [
20
+ {
21
+ href: `${studioBaseUrl}`,
22
+ title: intl.formatMessage(messages['header.user.menu.studio']),
23
+ }, {
24
+ href: `${logoutUrl}`,
25
+ title: intl.formatMessage(messages['header.user.menu.logout']),
26
+ },
27
+ ];
28
+ }
29
+
30
+ return items;
31
+ };
32
+
33
+ export default getUserMenuItems;
@@ -0,0 +1,25 @@
1
+ function _regenerator() { /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */ var e, t, r = "function" == typeof Symbol ? Symbol : {}, n = r.iterator || "@@iterator", o = r.toStringTag || "@@toStringTag"; function i(r, n, o, i) { var c = n && n.prototype instanceof Generator ? n : Generator, u = Object.create(c.prototype); return _regeneratorDefine2(u, "_invoke", function (r, n, o) { var i, c, u, f = 0, p = o || [], y = !1, G = { p: 0, n: 0, v: e, a: d, f: d.bind(e, 4), d: function d(t, r) { return i = t, c = 0, u = e, G.n = r, a; } }; function d(r, n) { for (c = r, u = n, t = 0; !y && f && !o && t < p.length; t++) { var o, i = p[t], d = G.p, l = i[2]; r > 3 ? (o = l === n) && (u = i[(c = i[4]) ? 5 : (c = 3, 3)], i[4] = i[5] = e) : i[0] <= d && ((o = r < 2 && d < i[1]) ? (c = 0, G.v = n, G.n = i[1]) : d < l && (o = r < 3 || i[0] > n || n > l) && (i[4] = r, i[5] = n, G.n = l, c = 0)); } if (o || r > 1) return a; throw y = !0, n; } return function (o, p, l) { if (f > 1) throw TypeError("Generator is already running"); for (y && 1 === p && d(p, l), c = p, u = l; (t = c < 2 ? e : u) || !y;) { i || (c ? c < 3 ? (c > 1 && (G.n = -1), d(c, u)) : G.n = u : G.v = u); try { if (f = 2, i) { if (c || (o = "next"), t = i[o]) { if (!(t = t.call(i, u))) throw TypeError("iterator result is not an object"); if (!t.done) return t; u = t.value, c < 2 && (c = 0); } else 1 === c && (t = i["return"]) && t.call(i), c < 2 && (u = TypeError("The iterator does not provide a '" + o + "' method"), c = 1); i = e; } else if ((t = (y = G.n < 0) ? u : r.call(n, G)) !== a) break; } catch (t) { i = e, c = 1, u = t; } finally { f = 1; } } return { value: t, done: y }; }; }(r, o, i), !0), u; } var a = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} t = Object.getPrototypeOf; var c = [][n] ? t(t([][n]())) : (_regeneratorDefine2(t = {}, n, function () { return this; }), t), u = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(c); function f(e) { return Object.setPrototypeOf ? Object.setPrototypeOf(e, GeneratorFunctionPrototype) : (e.__proto__ = GeneratorFunctionPrototype, _regeneratorDefine2(e, o, "GeneratorFunction")), e.prototype = Object.create(u), e; } return GeneratorFunction.prototype = GeneratorFunctionPrototype, _regeneratorDefine2(u, "constructor", GeneratorFunctionPrototype), _regeneratorDefine2(GeneratorFunctionPrototype, "constructor", GeneratorFunction), GeneratorFunction.displayName = "GeneratorFunction", _regeneratorDefine2(GeneratorFunctionPrototype, o, "GeneratorFunction"), _regeneratorDefine2(u), _regeneratorDefine2(u, o, "Generator"), _regeneratorDefine2(u, n, function () { return this; }), _regeneratorDefine2(u, "toString", function () { return "[object Generator]"; }), (_regenerator = function _regenerator() { return { w: i, m: f }; })(); }
2
+ function _regeneratorDefine2(e, r, n, t) { var i = Object.defineProperty; try { i({}, "", {}); } catch (e) { i = 0; } _regeneratorDefine2 = function _regeneratorDefine(e, r, n, t) { function o(r, n) { _regeneratorDefine2(e, r, function (e) { return this._invoke(r, n, e); }); } r ? i ? i(e, r, { value: n, enumerable: !t, configurable: !t, writable: !t }) : e[r] = n : (o("next", 0), o("throw", 1), o("return", 2)); }, _regeneratorDefine2(e, r, n, t); }
3
+ function asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }
4
+ function _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, "next", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, "throw", n); } _next(void 0); }); }; }
5
+ var executeThunk = /*#__PURE__*/function () {
6
+ var _ref = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee(thunk, dispatch, getState) {
7
+ return _regenerator().w(function (_context) {
8
+ while (1) switch (_context.n) {
9
+ case 0:
10
+ _context.n = 1;
11
+ return thunk(dispatch, getState);
12
+ case 1:
13
+ _context.n = 2;
14
+ return new Promise(setImmediate);
15
+ case 2:
16
+ return _context.a(2);
17
+ }
18
+ }, _callee);
19
+ }));
20
+ return function executeThunk(_x, _x2, _x3) {
21
+ return _ref.apply(this, arguments);
22
+ };
23
+ }();
24
+ export default executeThunk;
25
+ //# sourceMappingURL=test-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-utils.js","names":["e","t","r","Symbol","n","iterator","o","toStringTag","i","c","prototype","Generator","u","Object","create","_regeneratorDefine2","f","p","y","G","v","a","d","bind","length","l","TypeError","call","done","value","GeneratorFunction","GeneratorFunctionPrototype","getPrototypeOf","setPrototypeOf","__proto__","displayName","_regenerator","w","m","defineProperty","_regeneratorDefine","_invoke","enumerable","configurable","writable","asyncGeneratorStep","Promise","resolve","then","_asyncToGenerator","arguments","apply","_next","_throw","executeThunk","_ref","_callee","thunk","dispatch","getState","_context","setImmediate","_x","_x2","_x3"],"sources":["../src/test-utils.js"],"sourcesContent":["const executeThunk = async (thunk, dispatch, getState) => {\n await thunk(dispatch, getState);\n await new Promise(setImmediate);\n};\n\nexport default executeThunk;\n"],"mappings":"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","ignoreList":[]}
package/package.json ADDED
@@ -0,0 +1,73 @@
1
+ {
2
+ "name": "@epec-fcfm-uchile/frontend-component-header",
3
+ "version": "1.0.0",
4
+ "description": "The EPEC FCFM header for Open edX",
5
+ "main": "dist/index.js",
6
+ "publishConfig": {
7
+ "access": "public"
8
+ },
9
+ "scripts": {
10
+ "build": "make build",
11
+ "i18n_extract": "fedx-scripts formatjs extract",
12
+ "lint": "fedx-scripts eslint --ext .js --ext .jsx .",
13
+ "lint:fix": "fedx-scripts eslint --fix --ext .js --ext .jsx .",
14
+ "snapshot": "fedx-scripts jest --updateSnapshot",
15
+ "start": "fedx-scripts webpack-dev-server --progress",
16
+ "test": "fedx-scripts jest --coverage",
17
+ "test:dev": "fedx-scripts jest --watchAll",
18
+ "types": "tsc --noEmit"
19
+ },
20
+ "files": [
21
+ "/dist"
22
+ ],
23
+ "repository": {
24
+ "type": "git",
25
+ "url": "git+https://github.com/epec-fcfm-uchile/frontend-component-header.git"
26
+ },
27
+ "author": "edX",
28
+ "license": "AGPL-3.0",
29
+ "bugs": {
30
+ "url": "https://github.com/epec-fcfm-uchile/frontend-component-header/issues"
31
+ },
32
+ "homepage": "https://github.com/epec-fcfm-uchile/frontend-component-header#readme",
33
+ "devDependencies": {
34
+ "@edx/brand": "npm:@openedx/brand-openedx@^1.2.2",
35
+ "@edx/browserslist-config": "^1.1.1",
36
+ "@edx/frontend-platform": "^8.3.1",
37
+ "@openedx/frontend-build": "^14.3.2",
38
+ "@openedx/paragon": "^23.0.0",
39
+ "@testing-library/dom": "^10.4.0",
40
+ "@testing-library/jest-dom": "5.17.0",
41
+ "@testing-library/react": "^16.2.0",
42
+ "jest": "30.2.0",
43
+ "jest-environment-jsdom": "^30.0.0",
44
+ "prop-types": "15.8.1",
45
+ "react": "^18.3.1",
46
+ "react-dom": "^18.3.1",
47
+ "react-redux": "^8.1.1",
48
+ "react-router-dom": "6.30.1",
49
+ "react-test-renderer": "^18.3.1",
50
+ "redux": "4.2.1",
51
+ "redux-saga": "1.3.0",
52
+ "ts-jest": "^29.4.4"
53
+ },
54
+ "dependencies": {
55
+ "@fortawesome/fontawesome-svg-core": "6.7.2",
56
+ "@fortawesome/free-brands-svg-icons": "6.7.2",
57
+ "@fortawesome/free-regular-svg-icons": "6.7.2",
58
+ "@fortawesome/free-solid-svg-icons": "6.7.2",
59
+ "@fortawesome/react-fontawesome": "^0.2.0",
60
+ "@openedx/frontend-plugin-framework": "^1.7.0",
61
+ "classnames": "^2.5.1",
62
+ "react-responsive": "8.2.0",
63
+ "react-transition-group": "4.4.5"
64
+ },
65
+ "peerDependencies": {
66
+ "@edx/frontend-platform": "^7.0.0 || ^8.0.0",
67
+ "@openedx/paragon": ">= 22.0.0 < 24.0.0",
68
+ "prop-types": "^15.5.10",
69
+ "react": "^16.9.0 || ^17.0.0 || ^18.0.0",
70
+ "react-dom": "^16.9.0 || ^17.0.0 || ^18.0.0",
71
+ "react-router-dom": "^6.14.2"
72
+ }
73
+ }