@ndla/ui 13.2.2 → 15.1.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 (236) hide show
  1. package/es/Article/Article.js +22 -3
  2. package/es/Article/ArticleFavoritesButton.js +38 -0
  3. package/es/Article/index.js +2 -1
  4. package/es/Breadcrumb/ActionBreadcrumb.js +57 -0
  5. package/es/Breadcrumb/index.js +1 -0
  6. package/es/Footer/FooterAuth.js +15 -22
  7. package/es/InfoBlock/InfoBlock.js +55 -0
  8. package/es/InfoBlock/index.js +1 -0
  9. package/es/LearningPaths/LearningPathMenu.js +3 -4
  10. package/es/Masthead/MastheadAuthModal.js +2 -2
  11. package/es/MyNdla/Navigation/VerticalNavigation.js +51 -0
  12. package/es/MyNdla/Navigation/index.js +2 -0
  13. package/es/MyNdla/Resource/Folder.js +86 -0
  14. package/es/MyNdla/Resource/FolderInput.js +96 -0
  15. package/{lib/MyNdla/ResourceDash/ResourcesView.d.ts → es/MyNdla/Resource/index.js} +3 -3
  16. package/es/MyNdla/index.js +4 -4
  17. package/es/Resource/BlockResource.js +73 -0
  18. package/es/Resource/ListResource.js +66 -0
  19. package/es/Resource/index.js +10 -0
  20. package/es/Resource/resourceComponents.js +97 -0
  21. package/es/ResourceGroup/ResourceGroup.js +7 -5
  22. package/es/ResourceGroup/ResourceItem.js +28 -30
  23. package/es/ResourceGroup/ResourceList.js +18 -6
  24. package/es/Search/ActiveFilters.js +6 -7
  25. package/es/Search/ContentTypeResult.js +6 -8
  26. package/es/SearchTypeResult/ActiveFilters.js +6 -10
  27. package/es/SnackBar/SnackBar.js +117 -0
  28. package/es/SnackBar/index.js +9 -0
  29. package/es/TagSelector/SuggestionInput.js +240 -0
  30. package/es/TagSelector/Suggestions.js +93 -0
  31. package/es/TagSelector/TagSelector.js +137 -0
  32. package/es/TagSelector/index.js +9 -0
  33. package/es/TopicIntroductionList/TopicIntroduction.js +2 -4
  34. package/es/TopicIntroductionList/TopicShortcutItem.js +1 -3
  35. package/es/TreeStructure/FolderItem.js +130 -0
  36. package/es/TreeStructure/FolderItems.js +123 -0
  37. package/es/TreeStructure/FolderNameInput.js +112 -0
  38. package/es/TreeStructure/TreeStructure.js +254 -0
  39. package/es/TreeStructure/TreeStructure.types.js +0 -0
  40. package/es/TreeStructure/TreeStructureWrapper.js +13 -0
  41. package/es/TreeStructure/helperFunctions.js +92 -0
  42. package/es/TreeStructure/index.js +9 -0
  43. package/es/TreeStructure/keyboardNavigation/keyboardNavigation.js +182 -0
  44. package/es/TreeStructure/keyboardNavigation/keyboardNavigation.types.js +0 -0
  45. package/es/User/AuthModal.js +15 -24
  46. package/es/User/UserInfo.js +70 -0
  47. package/es/User/apiTypes.js +0 -0
  48. package/es/User/index.js +2 -0
  49. package/es/User/parseUserObject.js +102 -0
  50. package/es/all.css +90 -0
  51. package/es/index.js +9 -3
  52. package/es/locale/messages-en.js +71 -4
  53. package/es/locale/messages-nb.js +70 -3
  54. package/es/locale/messages-nn.js +70 -3
  55. package/es/locale/messages-se.js +70 -3
  56. package/es/locale/messages-sma.js +70 -3
  57. package/lib/Article/Article.d.ts +3 -1
  58. package/lib/Article/Article.js +43 -23
  59. package/lib/Article/ArticleFavoritesButton.d.ts +15 -0
  60. package/lib/Article/ArticleFavoritesButton.js +56 -0
  61. package/lib/Article/index.d.ts +2 -1
  62. package/lib/Article/index.js +8 -0
  63. package/lib/Breadcrumb/ActionBreadcrumb.d.ts +16 -0
  64. package/lib/Breadcrumb/ActionBreadcrumb.js +72 -0
  65. package/lib/Breadcrumb/index.d.ts +1 -0
  66. package/lib/Breadcrumb/index.js +8 -0
  67. package/lib/Footer/FooterAuth.d.ts +1 -1
  68. package/lib/Footer/FooterAuth.js +17 -17
  69. package/lib/InfoBlock/InfoBlock.d.ts +8 -0
  70. package/lib/InfoBlock/InfoBlock.js +58 -0
  71. package/lib/InfoBlock/index.d.ts +1 -0
  72. package/lib/InfoBlock/index.js +13 -0
  73. package/lib/LearningPaths/LearningPathMenu.js +3 -4
  74. package/lib/Masthead/MastheadAuthModal.d.ts +3 -3
  75. package/lib/Masthead/MastheadAuthModal.js +3 -3
  76. package/lib/MyNdla/Navigation/VerticalNavigation.d.ts +10 -0
  77. package/lib/MyNdla/Navigation/VerticalNavigation.js +61 -0
  78. package/lib/MyNdla/Navigation/index.d.ts +2 -0
  79. package/lib/MyNdla/Navigation/index.js +15 -0
  80. package/lib/MyNdla/Resource/Folder.d.ts +20 -0
  81. package/lib/MyNdla/Resource/Folder.js +100 -0
  82. package/lib/MyNdla/Resource/FolderInput.d.ts +15 -0
  83. package/lib/MyNdla/Resource/FolderInput.js +116 -0
  84. package/lib/MyNdla/Resource/index.d.ts +10 -0
  85. package/lib/MyNdla/Resource/index.js +23 -0
  86. package/lib/MyNdla/index.d.ts +4 -4
  87. package/lib/MyNdla/index.js +13 -7
  88. package/lib/Resource/BlockResource.d.ts +20 -0
  89. package/lib/Resource/BlockResource.js +84 -0
  90. package/lib/Resource/ListResource.d.ts +20 -0
  91. package/lib/Resource/ListResource.js +78 -0
  92. package/lib/Resource/index.d.ts +11 -0
  93. package/lib/Resource/index.js +29 -0
  94. package/lib/Resource/resourceComponents.d.ts +24 -0
  95. package/lib/Resource/resourceComponents.js +106 -0
  96. package/lib/ResourceGroup/ResourceGroup.d.ts +2 -1
  97. package/lib/ResourceGroup/ResourceGroup.js +7 -5
  98. package/lib/ResourceGroup/ResourceItem.d.ts +5 -1
  99. package/lib/ResourceGroup/ResourceItem.js +29 -30
  100. package/lib/ResourceGroup/ResourceList.d.ts +3 -1
  101. package/lib/ResourceGroup/ResourceList.js +18 -6
  102. package/lib/Search/ActiveFilters.js +6 -7
  103. package/lib/Search/ContentTypeResult.js +6 -8
  104. package/lib/SearchTypeResult/ActiveFilters.js +6 -10
  105. package/lib/SnackBar/SnackBar.d.ts +23 -0
  106. package/lib/SnackBar/SnackBar.js +127 -0
  107. package/lib/SnackBar/index.d.ts +10 -0
  108. package/lib/SnackBar/index.js +15 -0
  109. package/lib/TagSelector/SuggestionInput.d.ts +19 -0
  110. package/lib/TagSelector/SuggestionInput.js +255 -0
  111. package/lib/TagSelector/Suggestions.d.ts +12 -0
  112. package/lib/TagSelector/Suggestions.js +96 -0
  113. package/lib/TagSelector/TagSelector.d.ts +16 -0
  114. package/lib/TagSelector/TagSelector.js +150 -0
  115. package/lib/TagSelector/index.d.ts +10 -0
  116. package/lib/TagSelector/index.js +19 -0
  117. package/lib/TopicIntroductionList/TopicIntroduction.js +2 -4
  118. package/lib/TopicIntroductionList/TopicShortcutItem.js +1 -3
  119. package/lib/TreeStructure/FolderItem.d.ts +27 -0
  120. package/lib/TreeStructure/FolderItem.js +140 -0
  121. package/lib/TreeStructure/FolderItems.d.ts +11 -0
  122. package/lib/TreeStructure/FolderItems.js +130 -0
  123. package/lib/TreeStructure/FolderNameInput.d.ts +15 -0
  124. package/lib/TreeStructure/FolderNameInput.js +125 -0
  125. package/lib/TreeStructure/TreeStructure.d.ts +12 -0
  126. package/lib/TreeStructure/TreeStructure.js +273 -0
  127. package/lib/TreeStructure/TreeStructure.types.d.ts +63 -0
  128. package/lib/TreeStructure/TreeStructure.types.js +1 -0
  129. package/lib/TreeStructure/TreeStructureWrapper.d.ts +12 -0
  130. package/lib/TreeStructure/TreeStructureWrapper.js +24 -0
  131. package/lib/TreeStructure/helperFunctions.d.ts +5 -0
  132. package/lib/TreeStructure/helperFunctions.js +103 -0
  133. package/lib/TreeStructure/index.d.ts +10 -0
  134. package/lib/TreeStructure/index.js +15 -0
  135. package/lib/TreeStructure/keyboardNavigation/keyboardNavigation.d.ts +11 -0
  136. package/lib/TreeStructure/keyboardNavigation/keyboardNavigation.js +186 -0
  137. package/lib/TreeStructure/keyboardNavigation/keyboardNavigation.types.d.ts +26 -0
  138. package/lib/TreeStructure/keyboardNavigation/keyboardNavigation.types.js +1 -0
  139. package/lib/User/AuthModal.d.ts +3 -3
  140. package/lib/User/AuthModal.js +16 -23
  141. package/lib/User/UserInfo.d.ts +13 -0
  142. package/lib/User/UserInfo.js +84 -0
  143. package/lib/User/apiTypes.d.ts +61 -0
  144. package/lib/User/apiTypes.js +1 -0
  145. package/lib/User/index.d.ts +4 -0
  146. package/lib/User/index.js +8 -0
  147. package/lib/User/parseUserObject.d.ts +32 -0
  148. package/lib/User/parseUserObject.js +105 -0
  149. package/lib/all.css +90 -0
  150. package/lib/index.d.ts +14 -3
  151. package/lib/index.js +83 -10
  152. package/lib/locale/messages-en.d.ts +67 -0
  153. package/lib/locale/messages-en.js +71 -4
  154. package/lib/locale/messages-nb.d.ts +67 -0
  155. package/lib/locale/messages-nb.js +70 -3
  156. package/lib/locale/messages-nn.d.ts +67 -0
  157. package/lib/locale/messages-nn.js +70 -3
  158. package/lib/locale/messages-se.d.ts +67 -0
  159. package/lib/locale/messages-se.js +70 -3
  160. package/lib/locale/messages-sma.d.ts +67 -0
  161. package/lib/locale/messages-sma.js +70 -3
  162. package/lib/types.d.ts +1 -1
  163. package/package.json +11 -11
  164. package/src/Article/Article.tsx +31 -0
  165. package/src/Article/ArticleFavoritesButton.tsx +40 -0
  166. package/src/Article/index.ts +2 -0
  167. package/src/Breadcrumb/ActionBreadcrumb.tsx +68 -0
  168. package/src/Breadcrumb/index.ts +2 -0
  169. package/src/Footer/FooterAuth.tsx +7 -9
  170. package/src/InfoBlock/InfoBlock.tsx +61 -0
  171. package/src/InfoBlock/index.ts +1 -0
  172. package/src/LearningPaths/LearningPathMenu.tsx +1 -1
  173. package/src/Masthead/MastheadAuthModal.tsx +4 -5
  174. package/src/MyNdla/Navigation/VerticalNavigation.tsx +93 -0
  175. package/src/MyNdla/Navigation/index.ts +2 -0
  176. package/src/MyNdla/Resource/Folder.tsx +145 -0
  177. package/src/MyNdla/Resource/FolderInput.tsx +104 -0
  178. package/src/MyNdla/Resource/index.ts +11 -0
  179. package/src/MyNdla/index.ts +4 -5
  180. package/src/Resource/BlockResource.tsx +101 -0
  181. package/src/Resource/ListResource.tsx +111 -0
  182. package/src/Resource/index.ts +12 -0
  183. package/src/Resource/resourceComponents.tsx +143 -0
  184. package/src/ResourceGroup/ResourceGroup.tsx +3 -0
  185. package/src/ResourceGroup/ResourceItem.tsx +20 -3
  186. package/src/ResourceGroup/ResourceList.tsx +16 -3
  187. package/src/Search/ActiveFilters.jsx +0 -1
  188. package/src/Search/ContentTypeResult.tsx +8 -9
  189. package/src/SearchTypeResult/ActiveFilters.tsx +1 -3
  190. package/src/SnackBar/SnackBar.tsx +183 -0
  191. package/src/SnackBar/index.ts +13 -0
  192. package/src/TagSelector/SuggestionInput.tsx +230 -0
  193. package/src/TagSelector/Suggestions.tsx +125 -0
  194. package/src/TagSelector/TagSelector.tsx +111 -0
  195. package/src/TagSelector/index.ts +13 -0
  196. package/src/TopicIntroductionList/TopicIntroduction.tsx +2 -2
  197. package/src/TopicIntroductionList/TopicShortcutItem.tsx +1 -5
  198. package/src/TreeStructure/FolderItem.tsx +160 -0
  199. package/src/TreeStructure/FolderItems.tsx +109 -0
  200. package/src/TreeStructure/FolderNameInput.tsx +109 -0
  201. package/src/TreeStructure/TreeStructure.tsx +184 -0
  202. package/src/TreeStructure/TreeStructure.types.ts +69 -0
  203. package/src/TreeStructure/TreeStructureWrapper.tsx +34 -0
  204. package/src/TreeStructure/helperFunctions.ts +52 -0
  205. package/src/TreeStructure/index.ts +11 -0
  206. package/src/TreeStructure/keyboardNavigation/keyboardNavigation.ts +161 -0
  207. package/src/TreeStructure/keyboardNavigation/keyboardNavigation.types.ts +28 -0
  208. package/src/User/AuthModal.tsx +5 -26
  209. package/src/User/UserInfo.tsx +80 -0
  210. package/src/User/__tests__/parseUserObject-test.ts +315 -0
  211. package/src/User/apiTypes.ts +74 -0
  212. package/src/User/index.ts +4 -0
  213. package/src/User/parseUserObject.ts +83 -0
  214. package/src/all.scss +2 -0
  215. package/src/index.ts +15 -4
  216. package/src/locale/messages-en.ts +65 -3
  217. package/src/locale/messages-nb.ts +64 -2
  218. package/src/locale/messages-nn.ts +64 -2
  219. package/src/locale/messages-se.ts +64 -2
  220. package/src/locale/messages-sma.ts +64 -2
  221. package/src/types.ts +1 -1
  222. package/es/MyNdla/ResourceDash/Breadcrumbs.js +0 -22
  223. package/es/MyNdla/ResourceDash/ResourceElement.js +0 -27
  224. package/es/MyNdla/ResourceDash/ResourcesView.js +0 -43
  225. package/es/MyNdla/ResourceDash/index.js +0 -4
  226. package/lib/MyNdla/ResourceDash/Breadcrumbs.d.ts +0 -15
  227. package/lib/MyNdla/ResourceDash/Breadcrumbs.js +0 -35
  228. package/lib/MyNdla/ResourceDash/ResourceElement.d.ts +0 -18
  229. package/lib/MyNdla/ResourceDash/ResourceElement.js +0 -38
  230. package/lib/MyNdla/ResourceDash/ResourcesView.js +0 -57
  231. package/lib/MyNdla/ResourceDash/index.d.ts +0 -4
  232. package/lib/MyNdla/ResourceDash/index.js +0 -31
  233. package/src/MyNdla/ResourceDash/Breadcrumbs.tsx +0 -31
  234. package/src/MyNdla/ResourceDash/ResourceElement.tsx +0 -50
  235. package/src/MyNdla/ResourceDash/ResourcesView.tsx +0 -42
  236. package/src/MyNdla/ResourceDash/index.ts +0 -5
@@ -0,0 +1,161 @@
1
+ /**
2
+ * Copyright (c) 2022-present, NDLA.
3
+ *
4
+ * This source code is licensed under the GPLv3 license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ */
8
+
9
+ import { FolderStructureProps, SetFocusedFolderId } from '../TreeStructure.types';
10
+ import { KeyboardNavigationProps, ElementWithKeyFocusProps } from './keyboardNavigation.types';
11
+ import { MAX_LEVEL_FOR_FOLDERS } from '../TreeStructure';
12
+
13
+ export const KEYBOARD_KEYS_OF_INTEREST = ['ArrowDown', 'ArrowUp', 'ArrowRight', 'ArrowLeft', ' '];
14
+
15
+ // Traverse upwards, incase parent is last element of its parent..
16
+ const traverseUpwards = (
17
+ inital: FolderStructureProps[],
18
+ setFocusedFolderId: SetFocusedFolderId,
19
+ paths: number[],
20
+ index: number,
21
+ ) => {
22
+ let findParent: FolderStructureProps[] = inital;
23
+ const parentNextIds: (string | false)[] = [];
24
+ paths.forEach((pathIndex) => {
25
+ const nextParent = findParent ? findParent[pathIndex + 1] : undefined;
26
+ parentNextIds.push(nextParent?.id || false);
27
+ findParent = findParent[pathIndex].data || [];
28
+ });
29
+ if (!parentNextIds.length) {
30
+ parentNextIds.push(findParent[index + 1]?.id || false);
31
+ }
32
+ // We use a reversed version of parentNextIds, filtered out falses, to find the next element
33
+ // No newId? We are at the end of the tree so we wont update.
34
+ const newId = parentNextIds.reverse().filter((id) => id)[0];
35
+ if (newId) {
36
+ setFocusedFolderId(newId);
37
+ }
38
+ };
39
+
40
+ const keyboardNavigation = ({
41
+ e,
42
+ data,
43
+ onToggleOpen,
44
+ setFocusedFolderId,
45
+ focusedFolderId: id,
46
+ openFolders,
47
+ }: KeyboardNavigationProps): string | undefined => {
48
+ if (e.key === ' ' && document.activeElement?.nodeName === 'INPUT') {
49
+ return;
50
+ }
51
+
52
+ // We are navigating in the tree.
53
+ // We need to find the next folder in the tree
54
+ const elementWithKeyFocus: ElementWithKeyFocusProps = {
55
+ paths: [],
56
+ index: 0,
57
+ };
58
+
59
+ const updatePathToElementWithKeyFocus = (
60
+ data: FolderStructureProps[],
61
+ paths: number[],
62
+ parent: FolderStructureProps[],
63
+ parentId?: string,
64
+ ): boolean =>
65
+ data.some(({ data: childData, id: dataId, url }, _index) => {
66
+ if (dataId === id) {
67
+ elementWithKeyFocus.paths = paths;
68
+ elementWithKeyFocus.index = _index;
69
+ elementWithKeyFocus.isOpen = openFolders.has(dataId) && childData && childData.length > 0;
70
+ elementWithKeyFocus.data = childData;
71
+ elementWithKeyFocus.parent = parent;
72
+ elementWithKeyFocus.parentId = parentId;
73
+ elementWithKeyFocus.url = url;
74
+ return true;
75
+ }
76
+ return childData ? updatePathToElementWithKeyFocus(childData, [...paths, _index], [...childData], dataId) : false;
77
+ });
78
+ if (!updatePathToElementWithKeyFocus(data, [], data)) {
79
+ // Couldn't find its location in the tree.
80
+ // This should not happen, reset its value to root.
81
+ setFocusedFolderId(e.key === 'ArrowDown' ? data[0].id : undefined);
82
+ return;
83
+ }
84
+ e.preventDefault();
85
+ e.stopPropagation();
86
+
87
+ if (e.key === ' ') {
88
+ const simulatedEvent = new MouseEvent('click', {
89
+ bubbles: true,
90
+ cancelable: true,
91
+ view: window,
92
+ });
93
+ document.activeElement && document.activeElement.dispatchEvent(simulatedEvent);
94
+ return;
95
+ }
96
+
97
+ if (e.key === 'ArrowRight') {
98
+ if (
99
+ !elementWithKeyFocus.isOpen &&
100
+ elementWithKeyFocus.data?.length &&
101
+ id &&
102
+ elementWithKeyFocus.paths.length < MAX_LEVEL_FOR_FOLDERS - 1
103
+ ) {
104
+ onToggleOpen(id);
105
+ }
106
+ return;
107
+ }
108
+ if (e.key === 'ArrowLeft') {
109
+ if (id && elementWithKeyFocus.isOpen) {
110
+ onToggleOpen(id);
111
+ }
112
+ return;
113
+ }
114
+
115
+ if (!id && e.key === 'ArrowDown') {
116
+ setFocusedFolderId(data[0].id);
117
+ return;
118
+ }
119
+ if (!id) {
120
+ return;
121
+ }
122
+ // Move up
123
+ if (e.key === 'ArrowUp') {
124
+ if (elementWithKeyFocus.index > 0) {
125
+ // Move upwards to the parent folder
126
+ setFocusedFolderId(
127
+ elementWithKeyFocus.parent ? elementWithKeyFocus.parent[elementWithKeyFocus.index - 1].id : undefined,
128
+ );
129
+ } else if (elementWithKeyFocus.paths.length > 0) {
130
+ elementWithKeyFocus.paths.pop();
131
+ let findParent = data;
132
+ elementWithKeyFocus.paths.forEach((index) => {
133
+ findParent = findParent[index].data as FolderStructureProps[];
134
+ });
135
+ const parentsCurrentIndex = findParent.findIndex(({ id }) => id === elementWithKeyFocus.parentId);
136
+ setFocusedFolderId(findParent[parentsCurrentIndex].id);
137
+ }
138
+ return;
139
+ }
140
+
141
+ if (elementWithKeyFocus.isOpen) {
142
+ if (elementWithKeyFocus.data?.length) {
143
+ setFocusedFolderId(elementWithKeyFocus.data[0].id);
144
+ } else {
145
+ // move to next child of parent if any... need new traverse :-/
146
+ traverseUpwards(data, setFocusedFolderId, elementWithKeyFocus.paths, elementWithKeyFocus.index);
147
+ }
148
+ return;
149
+ }
150
+
151
+ if (elementWithKeyFocus.parent && elementWithKeyFocus.index < elementWithKeyFocus.parent?.length - 1) {
152
+ // Move downwards to the next child
153
+ setFocusedFolderId(elementWithKeyFocus.parent[elementWithKeyFocus.index + 1].id);
154
+ return;
155
+ }
156
+
157
+ traverseUpwards(data, setFocusedFolderId, elementWithKeyFocus.paths, elementWithKeyFocus.index);
158
+ return;
159
+ };
160
+
161
+ export default keyboardNavigation;
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Copyright (c) 2022-present, NDLA.
3
+ *
4
+ * This source code is licensed under the GPLv3 license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ */
8
+
9
+ import { FolderStructureProps, SetFocusedFolderId } from '../TreeStructure.types';
10
+
11
+ export interface KeyboardNavigationProps {
12
+ e: React.KeyboardEvent<HTMLElement>;
13
+ data: FolderStructureProps[];
14
+ setFocusedFolderId: SetFocusedFolderId;
15
+ openFolders: Set<string>;
16
+ onToggleOpen: (id: string) => void;
17
+ focusedFolderId: string | undefined;
18
+ }
19
+
20
+ export interface ElementWithKeyFocusProps {
21
+ paths: number[];
22
+ index: number;
23
+ data?: FolderStructureProps[];
24
+ parent?: FolderStructureProps[];
25
+ parentId?: string;
26
+ isOpen?: boolean;
27
+ url?: string;
28
+ }
@@ -13,6 +13,8 @@ import Modal, { ModalCloseButton } from '@ndla/modal';
13
13
  import Button from '@ndla/button';
14
14
  import { FeideText, LogIn, LogOut, HumanMaleBoard } from '@ndla/icons/common';
15
15
  import { fonts, spacing } from '@ndla/core';
16
+ import { UserInfo } from './UserInfo';
17
+ import { FeideUserApiType } from './apiTypes';
16
18
 
17
19
  const StyledModalBody = styled.div`
18
20
  padding: ${spacing.normal} ${spacing.medium} ${spacing.medium};
@@ -38,17 +40,6 @@ const StyledHeading = styled.h2`
38
40
  }
39
41
  `;
40
42
 
41
- const StyledAuthorizedInfoList = styled.ul`
42
- margin: 0;
43
- padding: 0 0 0 ${spacing.normal};
44
- list-style-image: unset;
45
-
46
- li {
47
- margin: 0;
48
- font-weight: ${fonts.weight.semibold};
49
- }
50
- `;
51
-
52
43
  const StyledHumanMaleBoardIconWrapper = styled.span`
53
44
  margin-left: ${spacing.xsmall};
54
45
  `;
@@ -63,9 +54,8 @@ const StyledButtonWrapper = styled.div`
63
54
 
64
55
  export type AuthModalProps = {
65
56
  isAuthenticated?: boolean;
57
+ user?: FeideUserApiType;
66
58
  showGeneralMessage?: boolean;
67
- authorizedRole?: string;
68
- authorizedCollectedInfo?: string[];
69
59
  onAuthenticateClick: () => void;
70
60
  position?: 'top' | 'bottom';
71
61
  activateButton?: ReactElement;
@@ -76,9 +66,8 @@ export type AuthModalProps = {
76
66
 
77
67
  const AuthModal = ({
78
68
  isAuthenticated,
69
+ user,
79
70
  showGeneralMessage = true,
80
- authorizedRole,
81
- authorizedCollectedInfo,
82
71
  onAuthenticateClick,
83
72
  position = 'top',
84
73
  activateButton,
@@ -104,17 +93,7 @@ const AuthModal = ({
104
93
  <ModalCloseButton onClick={onClose} title="Lukk" />
105
94
  </StyledModalHeader>
106
95
  <StyledModalContent>
107
- {authorizedRole && <p>{t('user.loggedInAs', { role: authorizedRole })}</p>}
108
- {authorizedCollectedInfo && authorizedCollectedInfo.length > 0 && (
109
- <div>
110
- {t('user.modal.collectedInfo')}
111
- <StyledAuthorizedInfoList>
112
- {authorizedCollectedInfo.map((value) => (
113
- <li key={value}>{value}</li>
114
- ))}
115
- </StyledAuthorizedInfoList>
116
- </div>
117
- )}
96
+ {user && <UserInfo user={user} />}
118
97
  {children}
119
98
  {showGeneralMessage && (
120
99
  <p>
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Copyright (c) 2022-present, NDLA.
3
+ *
4
+ * This source code is licensed under the GPLv3 license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ import styled from '@emotion/styled';
9
+ import { spacing } from '@ndla/core';
10
+ import React from 'react';
11
+ import { useTranslation } from 'react-i18next';
12
+ import { FeideUserApiType } from './apiTypes';
13
+ import { parseUserObject } from './parseUserObject';
14
+
15
+ const InfoList = styled.ul`
16
+ padding: 0 0 0 ${spacing.normal};
17
+ `;
18
+
19
+ interface Props {
20
+ user: FeideUserApiType;
21
+ }
22
+
23
+ const ShortInfoDiv = styled.div`
24
+ margin: 2rem auto;
25
+ `;
26
+
27
+ export const UserInfo = ({ user }: Props) => {
28
+ const { t } = useTranslation();
29
+
30
+ const parsedUser = parseUserObject(user);
31
+
32
+ return (
33
+ <div>
34
+ {
35
+ <p>
36
+ {t('user.loggedInAs', {
37
+ role: t(`user.role.${parsedUser.primaryAffiliation}`),
38
+ })}
39
+ </p>
40
+ }
41
+
42
+ <ShortInfoDiv>
43
+ <div>
44
+ {t('user.username')}: <b>{user.uid}</b>
45
+ </div>
46
+ <div>
47
+ {t('user.name')}: <b>{user.displayName}</b>
48
+ </div>
49
+ <div>
50
+ {t('user.mail')}: <b>{user.mail?.join(', ')}</b>
51
+ </div>
52
+ </ShortInfoDiv>
53
+
54
+ {t('user.modal.collectedInfo')}
55
+
56
+ <InfoList>
57
+ {parsedUser.organizations.map((org) => (
58
+ <li key={org.id}>
59
+ {`${org.displayName}${org.membership.primarySchool ? ` (${t('user.primarySchool')})` : ''}`}
60
+ <InfoList>
61
+ {Object.entries(org.children).map(([groupType, val]) => {
62
+ if (val.length < 1) return null;
63
+ return (
64
+ <li key={groupType}>
65
+ {t(`user.groupTypes.${groupType}`)}
66
+ <InfoList>
67
+ {val.map((group) => (
68
+ <li key={group.id}>{`${group.displayName}${group.grep ? ` (${group.grep.code})` : ''}`}</li>
69
+ ))}
70
+ </InfoList>
71
+ </li>
72
+ );
73
+ })}
74
+ </InfoList>
75
+ </li>
76
+ ))}
77
+ </InfoList>
78
+ </div>
79
+ );
80
+ };
@@ -0,0 +1,315 @@
1
+ /**
2
+ * Copyright (c) 2022-present, NDLA.
3
+ *
4
+ * This source code is licensed under the GPLv3 license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ */
8
+
9
+ import { FeideUserApiType } from '../apiTypes';
10
+ import { parseUserObject } from '../parseUserObject';
11
+
12
+ const feideUserLaerer: FeideUserApiType = {
13
+ cn: ['David LærerVGS Jonsen'],
14
+ displayName: 'David LærerVGS Jonsen',
15
+ eduPersonAffiliation: ['member', 'employee', 'faculty'],
16
+ eduPersonPrimaryAffiliation: 'employee',
17
+ eduPersonPrincipalName: 'david_laerervgs@spusers.feide.no',
18
+ givenName: ['David LærerVGS'],
19
+ mail: ['david_laerervgs@feide.no'],
20
+ sn: ['Jonsen'],
21
+ uid: ['david_laerervgs'],
22
+ groups: [
23
+ {
24
+ id: 'fc:org:spusers.feide.no',
25
+ displayName: 'Rogn fylkeskommune',
26
+ type: 'fc:org',
27
+ public: false,
28
+ membership: {
29
+ basic: 'admin',
30
+ affiliation: ['member', 'employee', 'faculty'],
31
+ primaryAffiliation: 'employee',
32
+ displayName: 'Akademisk ansatt',
33
+ },
34
+ orgType: ['higher_education', 'upper_secondary_owner', 'primary_and_lower_secondary_owner'],
35
+ norEduOrgNIN: 'NO956326503',
36
+ eduOrgLegalName: 'Rogn fylkeskommune',
37
+ mail: 'support@feide.no',
38
+ },
39
+ {
40
+ id: 'fc:org:spusers.feide.no:unit:NO956326504',
41
+ parent: 'fc:org:spusers.feide.no',
42
+ displayName: 'Lind VGS',
43
+ type: 'fc:org',
44
+ public: false,
45
+ membership: {
46
+ basic: 'member',
47
+ primarySchool: true,
48
+ },
49
+ orgType: ['primary_and_lower_secondary'],
50
+ },
51
+ {
52
+ id: 'fc:org:spusers.feide.no:unit:NO856326501',
53
+ parent: 'fc:org:spusers.feide.no',
54
+ displayName: 'Lerk VGS',
55
+ type: 'fc:org',
56
+ public: false,
57
+ membership: {
58
+ basic: 'member',
59
+ primarySchool: false,
60
+ },
61
+ orgType: ['primary_and_lower_secondary'],
62
+ },
63
+ {
64
+ id: 'fc:gogroup:spusers.feide.no:b:NO856326501:1sta:2000-07-01:2100-06-30',
65
+ displayName: 'Klasse 1STA',
66
+ type: 'fc:gogroup',
67
+ notBefore: '2000-06-30T22:00:00Z',
68
+ notAfter: '2100-06-30T23:00:00Z',
69
+ go_type: 'b',
70
+ parent: 'fc:org:spusers.feide.no:unit:NO856326501',
71
+ membership: {
72
+ basic: 'member',
73
+ affiliation: 'employee',
74
+ displayName: 'Ansatt',
75
+ },
76
+ go_type_displayName: 'basisgruppe',
77
+ },
78
+ {
79
+ id: 'fc:gogroup:spusers.feide.no:a:NO856326501:1sta-lab1:2000-07-01:2100-06-30',
80
+ displayName: 'Laboratoriegruppe 1',
81
+ type: 'fc:gogroup',
82
+ notBefore: '2000-06-30T22:00:00Z',
83
+ notAfter: '2100-06-30T23:00:00Z',
84
+ go_type: 'a',
85
+ parent: 'fc:org:spusers.feide.no:unit:NO856326501',
86
+ membership: {
87
+ basic: 'member',
88
+ affiliation: 'employee',
89
+ displayName: 'Ansatt',
90
+ },
91
+ go_type_displayName: 'other groups',
92
+ },
93
+ {
94
+ id: 'fc:gogroup:spusers.feide.no:a:NO856326501:1sta-lab2:2000-07-01:2100-06-30',
95
+ displayName: 'Laboratoriegruppe 2',
96
+ type: 'fc:gogroup',
97
+ notBefore: '2000-06-30T22:00:00Z',
98
+ notAfter: '2100-06-30T23:00:00Z',
99
+ go_type: 'a',
100
+ parent: 'fc:org:spusers.feide.no:unit:NO856326501',
101
+ membership: {
102
+ basic: 'member',
103
+ affiliation: 'employee',
104
+ displayName: 'Ansatt',
105
+ },
106
+ go_type_displayName: 'other groups',
107
+ },
108
+ {
109
+ id: 'fc:gogroup:spusers.feide.no:u:NO856326501:1mat11-1map1:2000-07-01:2100-06-30',
110
+ displayName: 'Matematikk 1P',
111
+ type: 'fc:gogroup',
112
+ notBefore: '2000-06-30T22:00:00Z',
113
+ notAfter: '2100-06-30T23:00:00Z',
114
+ go_type: 'u',
115
+ parent: 'fc:org:spusers.feide.no:unit:NO856326501',
116
+ membership: {
117
+ basic: 'member',
118
+ affiliation: 'employee',
119
+ displayName: 'Ansatt',
120
+ },
121
+ go_type_displayName: 'undervisningsgruppe',
122
+ grep: {
123
+ displayName: 'Mathematics 1P',
124
+ code: 'MAT1011',
125
+ },
126
+ },
127
+ {
128
+ id: 'fc:gogroup:spusers.feide.no:u:NO856326501:1mat13-1mat1:2000-07-01:2100-06-30',
129
+ displayName: 'Matematikk 1T',
130
+ type: 'fc:gogroup',
131
+ notBefore: '2000-06-30T22:00:00Z',
132
+ notAfter: '2100-06-30T23:00:00Z',
133
+ go_type: 'u',
134
+ parent: 'fc:org:spusers.feide.no:unit:NO856326501',
135
+ membership: {
136
+ basic: 'member',
137
+ affiliation: 'employee',
138
+ displayName: 'Ansatt',
139
+ },
140
+ go_type_displayName: 'undervisningsgruppe',
141
+ grep: {
142
+ displayName: 'Mathematics 1T',
143
+ code: 'MAT1013',
144
+ },
145
+ },
146
+ ],
147
+ primarySchool: {
148
+ id: 'fc:org:spusers.feide.no:unit:NO956326504',
149
+ parent: 'fc:org:spusers.feide.no',
150
+ displayName: 'Lind VGS',
151
+ type: 'fc:org',
152
+ public: false,
153
+ membership: {
154
+ basic: 'member',
155
+ primarySchool: true,
156
+ },
157
+ orgType: ['primary_and_lower_secondary'],
158
+ },
159
+ };
160
+
161
+ describe('parseUserObject', () => {
162
+ it('Correctly parses Feide user', () => {
163
+ const expected = {
164
+ uid: ['david_laerervgs'],
165
+ primaryAffiliation: 'employee',
166
+ displayName: 'David LærerVGS Jonsen',
167
+ mail: ['david_laerervgs@feide.no'],
168
+ organizations: [
169
+ {
170
+ id: 'fc:org:spusers.feide.no',
171
+ displayName: 'Rogn fylkeskommune',
172
+ type: 'fc:org',
173
+ public: false,
174
+ membership: {
175
+ basic: 'admin',
176
+ affiliation: ['member', 'employee', 'faculty'],
177
+ primaryAffiliation: 'employee',
178
+ displayName: 'Akademisk ansatt',
179
+ },
180
+ orgType: ['higher_education', 'upper_secondary_owner', 'primary_and_lower_secondary_owner'],
181
+ norEduOrgNIN: 'NO956326503',
182
+ eduOrgLegalName: 'Rogn fylkeskommune',
183
+ mail: 'support@feide.no',
184
+ children: {
185
+ basic: [],
186
+ teaching: [],
187
+ other: [],
188
+ },
189
+ },
190
+ {
191
+ id: 'fc:org:spusers.feide.no:unit:NO956326504',
192
+ parent: 'fc:org:spusers.feide.no',
193
+ displayName: 'Lind VGS',
194
+ type: 'fc:org',
195
+ public: false,
196
+ membership: {
197
+ basic: 'member',
198
+ primarySchool: true,
199
+ },
200
+ orgType: ['primary_and_lower_secondary'],
201
+ children: {
202
+ basic: [],
203
+ teaching: [],
204
+ other: [],
205
+ },
206
+ },
207
+ {
208
+ id: 'fc:org:spusers.feide.no:unit:NO856326501',
209
+ parent: 'fc:org:spusers.feide.no',
210
+ displayName: 'Lerk VGS',
211
+ type: 'fc:org',
212
+ public: false,
213
+ membership: {
214
+ basic: 'member',
215
+ primarySchool: false,
216
+ },
217
+ orgType: ['primary_and_lower_secondary'],
218
+ children: {
219
+ basic: [
220
+ {
221
+ id: 'fc:gogroup:spusers.feide.no:b:NO856326501:1sta:2000-07-01:2100-06-30',
222
+ displayName: 'Klasse 1STA',
223
+ type: 'fc:gogroup',
224
+ notBefore: '2000-06-30T22:00:00Z',
225
+ notAfter: '2100-06-30T23:00:00Z',
226
+ go_type: 'b',
227
+ parent: 'fc:org:spusers.feide.no:unit:NO856326501',
228
+ membership: {
229
+ basic: 'member',
230
+ affiliation: 'employee',
231
+ displayName: 'Ansatt',
232
+ },
233
+ go_type_displayName: 'basisgruppe',
234
+ },
235
+ ],
236
+ teaching: [
237
+ {
238
+ id: 'fc:gogroup:spusers.feide.no:u:NO856326501:1mat11-1map1:2000-07-01:2100-06-30',
239
+ displayName: 'Matematikk 1P',
240
+ type: 'fc:gogroup',
241
+ notBefore: '2000-06-30T22:00:00Z',
242
+ notAfter: '2100-06-30T23:00:00Z',
243
+ go_type: 'u',
244
+ parent: 'fc:org:spusers.feide.no:unit:NO856326501',
245
+ membership: {
246
+ basic: 'member',
247
+ affiliation: 'employee',
248
+ displayName: 'Ansatt',
249
+ },
250
+ go_type_displayName: 'undervisningsgruppe',
251
+ grep: {
252
+ displayName: 'Mathematics 1P',
253
+ code: 'MAT1011',
254
+ },
255
+ },
256
+ {
257
+ id: 'fc:gogroup:spusers.feide.no:u:NO856326501:1mat13-1mat1:2000-07-01:2100-06-30',
258
+ displayName: 'Matematikk 1T',
259
+ type: 'fc:gogroup',
260
+ notBefore: '2000-06-30T22:00:00Z',
261
+ notAfter: '2100-06-30T23:00:00Z',
262
+ go_type: 'u',
263
+ parent: 'fc:org:spusers.feide.no:unit:NO856326501',
264
+ membership: {
265
+ basic: 'member',
266
+ affiliation: 'employee',
267
+ displayName: 'Ansatt',
268
+ },
269
+ go_type_displayName: 'undervisningsgruppe',
270
+ grep: {
271
+ displayName: 'Mathematics 1T',
272
+ code: 'MAT1013',
273
+ },
274
+ },
275
+ ],
276
+ other: [
277
+ {
278
+ id: 'fc:gogroup:spusers.feide.no:a:NO856326501:1sta-lab1:2000-07-01:2100-06-30',
279
+ displayName: 'Laboratoriegruppe 1',
280
+ type: 'fc:gogroup',
281
+ notBefore: '2000-06-30T22:00:00Z',
282
+ notAfter: '2100-06-30T23:00:00Z',
283
+ go_type: 'a',
284
+ parent: 'fc:org:spusers.feide.no:unit:NO856326501',
285
+ membership: {
286
+ basic: 'member',
287
+ affiliation: 'employee',
288
+ displayName: 'Ansatt',
289
+ },
290
+ go_type_displayName: 'other groups',
291
+ },
292
+ {
293
+ id: 'fc:gogroup:spusers.feide.no:a:NO856326501:1sta-lab2:2000-07-01:2100-06-30',
294
+ displayName: 'Laboratoriegruppe 2',
295
+ type: 'fc:gogroup',
296
+ notBefore: '2000-06-30T22:00:00Z',
297
+ notAfter: '2100-06-30T23:00:00Z',
298
+ go_type: 'a',
299
+ parent: 'fc:org:spusers.feide.no:unit:NO856326501',
300
+ membership: {
301
+ basic: 'member',
302
+ affiliation: 'employee',
303
+ displayName: 'Ansatt',
304
+ },
305
+ go_type_displayName: 'other groups',
306
+ },
307
+ ],
308
+ },
309
+ },
310
+ ],
311
+ };
312
+ const actual = parseUserObject(feideUserLaerer);
313
+ expect(actual).toEqual(expected);
314
+ });
315
+ });