@ndla/ui 18.0.1 → 19.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 (53) hide show
  1. package/es/Breadcrumb/ActionBreadcrumb.js +9 -3
  2. package/es/MyNdla/Resource/Folder.js +11 -10
  3. package/es/Resource/BlockResource.js +14 -8
  4. package/es/Resource/ListResource.js +16 -10
  5. package/es/Resource/resourceComponents.js +12 -11
  6. package/es/TreeStructure/FolderItem.js +7 -6
  7. package/es/TreeStructure/FolderItems.js +7 -6
  8. package/es/TreeStructure/TreeStructure.js +16 -9
  9. package/es/locale/messages-en.js +11 -1
  10. package/es/locale/messages-nb.js +11 -1
  11. package/es/locale/messages-nn.js +11 -1
  12. package/es/locale/messages-se.js +11 -1
  13. package/es/locale/messages-sma.js +11 -1
  14. package/lib/Breadcrumb/ActionBreadcrumb.js +9 -3
  15. package/lib/MyNdla/Resource/Folder.d.ts +4 -3
  16. package/lib/MyNdla/Resource/Folder.js +11 -10
  17. package/lib/Resource/BlockResource.d.ts +4 -3
  18. package/lib/Resource/BlockResource.js +14 -7
  19. package/lib/Resource/ListResource.d.ts +4 -3
  20. package/lib/Resource/ListResource.js +16 -9
  21. package/lib/Resource/resourceComponents.d.ts +4 -1
  22. package/lib/Resource/resourceComponents.js +14 -13
  23. package/lib/TreeStructure/FolderItem.js +8 -6
  24. package/lib/TreeStructure/FolderItems.d.ts +1 -1
  25. package/lib/TreeStructure/FolderItems.js +7 -7
  26. package/lib/TreeStructure/TreeStructure.d.ts +6 -1
  27. package/lib/TreeStructure/TreeStructure.js +16 -9
  28. package/lib/TreeStructure/TreeStructure.types.d.ts +3 -1
  29. package/lib/locale/messages-en.d.ts +11 -1
  30. package/lib/locale/messages-en.js +11 -1
  31. package/lib/locale/messages-nb.d.ts +11 -1
  32. package/lib/locale/messages-nb.js +11 -1
  33. package/lib/locale/messages-nn.d.ts +11 -1
  34. package/lib/locale/messages-nn.js +11 -1
  35. package/lib/locale/messages-se.d.ts +11 -1
  36. package/lib/locale/messages-se.js +11 -1
  37. package/lib/locale/messages-sma.d.ts +11 -1
  38. package/lib/locale/messages-sma.js +11 -1
  39. package/package.json +5 -5
  40. package/src/Breadcrumb/ActionBreadcrumb.tsx +3 -0
  41. package/src/MyNdla/Resource/Folder.tsx +6 -6
  42. package/src/Resource/BlockResource.tsx +7 -6
  43. package/src/Resource/ListResource.tsx +11 -8
  44. package/src/Resource/resourceComponents.tsx +5 -1
  45. package/src/TreeStructure/FolderItem.tsx +3 -2
  46. package/src/TreeStructure/FolderItems.tsx +3 -2
  47. package/src/TreeStructure/TreeStructure.tsx +21 -7
  48. package/src/TreeStructure/TreeStructure.types.ts +3 -1
  49. package/src/locale/messages-en.ts +11 -1
  50. package/src/locale/messages-nb.ts +11 -1
  51. package/src/locale/messages-nn.ts +11 -1
  52. package/src/locale/messages-se.ts +11 -1
  53. package/src/locale/messages-sma.ts +11 -1
@@ -58,7 +58,13 @@ declare const messages: {
58
58
  resources_plural: string;
59
59
  folders: string;
60
60
  folders_plural: string;
61
- folder: string;
61
+ folder: {
62
+ folder: string;
63
+ delete: string;
64
+ edit: string;
65
+ };
66
+ confirmDeleteFolder: string;
67
+ confirmDeleteTag: string;
62
68
  myFolders: string;
63
69
  myTags: string;
64
70
  newFolder: string;
@@ -104,6 +110,9 @@ declare const messages: {
104
110
  };
105
111
  };
106
112
  resource: {
113
+ add: string;
114
+ remove: string;
115
+ copyLink: string;
107
116
  addToMyNdla: string;
108
117
  addedToMyNdla: string;
109
118
  };
@@ -132,6 +141,7 @@ declare const messages: {
132
141
  delete: string;
133
142
  };
134
143
  createFolder: string;
144
+ maxFoldersAlreadyAdded: string;
135
145
  newFolder: {
136
146
  placeholder: string;
137
147
  defaultName: string;
@@ -34,6 +34,7 @@ var messages = _objectSpread(_objectSpread({
34
34
  "delete": 'Slett'
35
35
  },
36
36
  createFolder: 'Lag mappe',
37
+ maxFoldersAlreadyAdded: 'Maks nivå av undermapper nådd',
37
38
  newFolder: {
38
39
  placeholder: 'Skriv namn på mappe',
39
40
  defaultName: 'Ny mappe'
@@ -950,7 +951,13 @@ var messages = _objectSpread(_objectSpread({
950
951
  resources_plural: '{{count}} ressursar',
951
952
  folders: '{{count}} mappe',
952
953
  folders_plural: '{{count}} mapper',
953
- folder: 'Mappe',
954
+ folder: {
955
+ folder: 'Mappe',
956
+ "delete": 'Slett',
957
+ edit: 'Rediger'
958
+ },
959
+ confirmDeleteFolder: 'Er du sikker på at du vil slette mappa? Denne handlinga kan ikkje angres.',
960
+ confirmDeleteTag: 'Er du sikker på at du vil slette tag? Denne handlinga kan ikkje angres.',
954
961
  myFolders: 'Mine mapper',
955
962
  myTags: 'Mine tags',
956
963
  newFolder: 'Ny mappe',
@@ -996,6 +1003,9 @@ var messages = _objectSpread(_objectSpread({
996
1003
  }
997
1004
  },
998
1005
  resource: {
1006
+ add: 'Legg til mappe/tag',
1007
+ remove: 'Fjern',
1008
+ copyLink: 'Kopier lenke til sida',
999
1009
  addToMyNdla: 'Legg i Min NDLA',
1000
1010
  addedToMyNdla: 'Lagt i Min NDLA'
1001
1011
  }
@@ -58,7 +58,13 @@ declare const messages: {
58
58
  resources_plural: string;
59
59
  folders: string;
60
60
  folders_plural: string;
61
- folder: string;
61
+ folder: {
62
+ folder: string;
63
+ delete: string;
64
+ edit: string;
65
+ };
66
+ confirmDeleteFolder: string;
67
+ confirmDeleteTag: string;
62
68
  myFolders: string;
63
69
  myTags: string;
64
70
  newFolder: string;
@@ -104,6 +110,9 @@ declare const messages: {
104
110
  };
105
111
  };
106
112
  resource: {
113
+ add: string;
114
+ remove: string;
115
+ copyLink: string;
107
116
  addToMyNdla: string;
108
117
  addedToMyNdla: string;
109
118
  };
@@ -132,6 +141,7 @@ declare const messages: {
132
141
  delete: string;
133
142
  };
134
143
  createFolder: string;
144
+ maxFoldersAlreadyAdded: string;
135
145
  newFolder: {
136
146
  placeholder: string;
137
147
  defaultName: string;
@@ -34,6 +34,7 @@ var messages = _objectSpread(_objectSpread({
34
34
  "delete": 'Slett'
35
35
  },
36
36
  createFolder: 'Lag mappe',
37
+ maxFoldersAlreadyAdded: 'Maks nivå av undermapper nådd',
37
38
  newFolder: {
38
39
  placeholder: 'Skriv navn på mappe',
39
40
  defaultName: 'Ny mappe'
@@ -950,7 +951,13 @@ var messages = _objectSpread(_objectSpread({
950
951
  resources_plural: '{{count}} ressurser',
951
952
  folders: '{{count}} mappe',
952
953
  folders_plural: '{{count}} mapper',
953
- folder: 'Mappe',
954
+ folder: {
955
+ folder: 'Mappe',
956
+ "delete": 'Slett',
957
+ edit: 'Rediger'
958
+ },
959
+ confirmDeleteFolder: 'Er du sikker på at du vil slette mappen? Denne handlingen kan ikke angres.',
960
+ confirmDeleteTag: 'Er du sikker på at du vil slette tag? Denne handlingen kan ikke angres.',
954
961
  myFolders: 'Mine mapper',
955
962
  myTags: 'Mine tags',
956
963
  newFolder: 'Ny mappe',
@@ -996,6 +1003,9 @@ var messages = _objectSpread(_objectSpread({
996
1003
  }
997
1004
  },
998
1005
  resource: {
1006
+ add: 'Legg til mappe/tag',
1007
+ remove: 'Fjern',
1008
+ copyLink: 'Kopier lenke til siden',
999
1009
  addToMyNdla: 'Legg i Min NDLA',
1000
1010
  addedToMyNdla: 'Lagt i Min NDLA'
1001
1011
  }
@@ -58,7 +58,13 @@ declare const messages: {
58
58
  resources_plural: string;
59
59
  folders: string;
60
60
  folders_plural: string;
61
- folder: string;
61
+ folder: {
62
+ folder: string;
63
+ delete: string;
64
+ edit: string;
65
+ };
66
+ confirmDeleteFolder: string;
67
+ confirmDeleteTag: string;
62
68
  myFolders: string;
63
69
  myTags: string;
64
70
  newFolder: string;
@@ -104,6 +110,9 @@ declare const messages: {
104
110
  };
105
111
  };
106
112
  resource: {
113
+ add: string;
114
+ remove: string;
115
+ copyLink: string;
107
116
  addToMyNdla: string;
108
117
  addedToMyNdla: string;
109
118
  };
@@ -132,6 +141,7 @@ declare const messages: {
132
141
  delete: string;
133
142
  };
134
143
  createFolder: string;
144
+ maxFoldersAlreadyAdded: string;
135
145
  newFolder: {
136
146
  placeholder: string;
137
147
  defaultName: string;
@@ -34,6 +34,7 @@ var messages = _objectSpread(_objectSpread({
34
34
  "delete": 'Slett'
35
35
  },
36
36
  createFolder: 'Lag mappe',
37
+ maxFoldersAlreadyAdded: 'Maks nivå av undermapper nådd',
37
38
  newFolder: {
38
39
  placeholder: 'Skriv navn på mappe',
39
40
  defaultName: 'Ny mappe'
@@ -950,7 +951,13 @@ var messages = _objectSpread(_objectSpread({
950
951
  resources_plural: '{{count}} ressurser',
951
952
  folders: '{{count}} mappe',
952
953
  folders_plural: '{{count}} mapper',
953
- folder: 'Mappe',
954
+ folder: {
955
+ folder: 'Mappe',
956
+ "delete": 'Slett',
957
+ edit: 'Rediger'
958
+ },
959
+ confirmDeleteFolder: 'Er du sikker på at du vil slette mappen? Denne handlingen kan ikke angres.',
960
+ confirmDeleteTag: 'Er du sikker på at du vil slette tag? Denne handlingen kan ikke angres.',
954
961
  myFolders: 'Mine mapper',
955
962
  myTags: 'Mine tags',
956
963
  newFolder: 'Ny mappe',
@@ -996,6 +1003,9 @@ var messages = _objectSpread(_objectSpread({
996
1003
  }
997
1004
  },
998
1005
  resource: {
1006
+ add: 'Legg til mappe/tag',
1007
+ remove: 'Fjern',
1008
+ copyLink: 'Kopier lenke til siden',
999
1009
  addToMyNdla: 'Legg i Min NDLA',
1000
1010
  addedToMyNdla: 'Lagt i Min NDLA'
1001
1011
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ndla/ui",
3
- "version": "18.0.1",
3
+ "version": "19.1.0",
4
4
  "description": "UI component library for NDLA.",
5
5
  "license": "GPL-3.0",
6
6
  "main": "lib/index.js",
@@ -31,15 +31,15 @@
31
31
  "types"
32
32
  ],
33
33
  "dependencies": {
34
- "@ndla/button": "^2.6.0",
34
+ "@ndla/button": "^3.1.0",
35
35
  "@ndla/carousel": "^1.2.11",
36
36
  "@ndla/core": "^2.3.0",
37
37
  "@ndla/hooks": "^1.1.4",
38
38
  "@ndla/icons": "^1.10.0",
39
39
  "@ndla/licenses": "^5.0.2",
40
40
  "@ndla/modal": "^1.2.12",
41
- "@ndla/notion": "^3.1.17",
42
- "@ndla/safelink": "^2.0.8",
41
+ "@ndla/notion": "^3.1.20",
42
+ "@ndla/safelink": "^2.1.1",
43
43
  "@ndla/switch": "^0.1.7",
44
44
  "@ndla/tabs": "^1.1.10",
45
45
  "@ndla/tooltip": "^2.1.2",
@@ -81,5 +81,5 @@
81
81
  "publishConfig": {
82
82
  "access": "public"
83
83
  },
84
- "gitHead": "841ff68015ec6032bed44a7c25eea2dfd9088a64"
84
+ "gitHead": "74b5027e25a33f81802c72b11901d59085bb290a"
85
85
  }
@@ -44,6 +44,9 @@ interface Props {
44
44
 
45
45
  const ActionBreadcrumb = ({ items, actionItems }: Props) => {
46
46
  const renderItem = (item: IndexedBreadcrumbItem, totalCount: number) => {
47
+ if (totalCount === 1) {
48
+ return <StyledSpan title={item.name}>{item.name}</StyledSpan>;
49
+ }
47
50
  if (item.index === totalCount - 1) {
48
51
  return (
49
52
  <MenuButton menuItems={actionItems} size="small">
@@ -7,14 +7,14 @@
7
7
  */
8
8
 
9
9
  import styled from '@emotion/styled';
10
- import React, { ReactNode } from 'react';
10
+ import React from 'react';
11
11
  import { FolderOutlined } from '@ndla/icons/contentType';
12
12
  import { FileDocumentOutline } from '@ndla/icons/common';
13
13
  import { fonts, spacing, colors, mq, breakpoints } from '@ndla/core';
14
14
  import { css } from '@emotion/core';
15
15
  import { useTranslation } from 'react-i18next';
16
16
  import SafeLink from '@ndla/safelink';
17
- import { MenuButton } from '@ndla/button';
17
+ import { MenuButton, MenuItemProps } from '@ndla/button';
18
18
 
19
19
  interface FolderIconWrapperProps {
20
20
  type?: LayoutType;
@@ -84,7 +84,7 @@ interface Props {
84
84
  description?: string;
85
85
  link: string;
86
86
  type: LayoutType;
87
- actionMenu?: ReactNode;
87
+ menuItems?: MenuItemProps[];
88
88
  }
89
89
 
90
90
  interface IconCountProps {
@@ -131,17 +131,17 @@ const IconCount = ({ type, count, layoutType }: IconCountProps) => {
131
131
 
132
132
  type LayoutType = 'list' | 'block';
133
133
 
134
- const Folder = ({ link, title, subFolders, subResources, type = 'list', actionMenu }: Props) => {
134
+ const Folder = ({ link, title, subFolders, subResources, type = 'list', menuItems }: Props) => {
135
135
  const { t } = useTranslation();
136
136
  return (
137
137
  <FolderWrapper to={link}>
138
138
  <FolderIconWrapper type={type}>
139
- <FolderOutlined aria-label={t('myNdla.folder')} />
139
+ <FolderOutlined aria-label={t('myNdla.folder.folder')} />
140
140
  </FolderIconWrapper>
141
141
  <FolderTitle>{title}</FolderTitle>
142
142
  <IconCount layoutType={type} type={'folder'} count={subFolders} />
143
143
  <IconCount layoutType={type} type={'resource'} count={subResources} />
144
- <MenuButton size="small" />
144
+ {menuItems && menuItems.length > 0 && <MenuButton size="small" menuItems={menuItems} />}
145
145
  </FolderWrapper>
146
146
  );
147
147
  };
@@ -7,11 +7,12 @@
7
7
  */
8
8
 
9
9
  import styled from '@emotion/styled';
10
- import React, { ReactNode } from 'react';
10
+ import React from 'react';
11
11
  import SafeLink from '@ndla/safelink';
12
12
  import { colors, fonts, spacing } from '@ndla/core';
13
+ import { MenuButton, MenuItemProps } from '@ndla/button';
13
14
  import Image from '../Image';
14
- import { CompressedTags, ResourceImageProps, ResourceTitle, Row, TopicList } from './resourceComponents';
15
+ import { CompressedTagList, ResourceImageProps, ResourceTitle, Row, TopicList } from './resourceComponents';
15
16
 
16
17
  interface BlockResourceProps {
17
18
  link: string;
@@ -20,7 +21,7 @@ interface BlockResourceProps {
20
21
  topics: string[];
21
22
  tags?: string[];
22
23
  description?: string;
23
- actionMenu?: ReactNode;
24
+ menuItems?: MenuItemProps[];
24
25
  }
25
26
 
26
27
  const BlockElementWrapper = styled(SafeLink)`
@@ -77,7 +78,7 @@ const ImageWrapper = styled.div`
77
78
  }
78
79
  `;
79
80
 
80
- const BlockResource = ({ link, title, tags, resourceImage, topics, description, actionMenu }: BlockResourceProps) => {
81
+ const BlockResource = ({ link, title, tags, resourceImage, topics, description, menuItems }: BlockResourceProps) => {
81
82
  return (
82
83
  <BlockElementWrapper to={link}>
83
84
  <ImageWrapper>
@@ -90,8 +91,8 @@ const BlockResource = ({ link, title, tags, resourceImage, topics, description,
90
91
  <TopicList topics={topics} />
91
92
  <BlockDescription>{description}</BlockDescription>
92
93
  <RightRow>
93
- {tags && CompressedTags(tags)}
94
- {actionMenu}
94
+ {tags && <CompressedTagList tags={tags} />}
95
+ {menuItems && menuItems.length > 0 && <MenuButton size="small" menuItems={menuItems} />}
95
96
  </RightRow>
96
97
  </BlockInfoWrapper>
97
98
  </BlockElementWrapper>
@@ -7,11 +7,12 @@
7
7
  */
8
8
 
9
9
  import styled from '@emotion/styled';
10
- import React, { ReactNode } from 'react';
10
+ import React from 'react';
11
11
  import SafeLink from '@ndla/safelink';
12
12
  import { fonts, spacing, colors, breakpoints, mq } from '@ndla/core';
13
+ import { MenuButton, MenuItemProps } from '@ndla/button';
13
14
  import Image from '../Image';
14
- import { CompressedTags, ResourceImageProps, ResourceTitle, TopicList } from './resourceComponents';
15
+ import { CompressedTagList, ResourceImageProps, ResourceTitle, TopicList } from './resourceComponents';
15
16
 
16
17
  const ResourceDescription = styled.p`
17
18
  grid-area: description;
@@ -30,12 +31,13 @@ const ResourceDescription = styled.p`
30
31
  `;
31
32
 
32
33
  const ResourceWrapper = styled(SafeLink)`
33
- display: grid;
34
34
  flex: 1;
35
+ display: grid;
36
+ grid-template-columns: auto 1fr auto;
35
37
  grid-template-areas:
36
38
  'image topicAndTitle tags'
37
39
  'image description description';
38
- grid-template-columns: auto 1fr auto;
40
+
39
41
  ${mq.range({ until: breakpoints.mobileWide })} {
40
42
  grid-template-columns: auto 1fr;
41
43
  grid-template-areas:
@@ -51,6 +53,7 @@ const ResourceWrapper = styled(SafeLink)`
51
53
  border-radius: 2px;
52
54
  color: ${colors.brand.greyDark};
53
55
  gap: 0 ${spacing.small};
56
+
54
57
  &:hover {
55
58
  box-shadow: 1px 1px 6px 2px rgba(9, 55, 101, 0.08);
56
59
  transition-duration: 0.2s;
@@ -109,10 +112,10 @@ export interface ListResourceProps {
109
112
  topics: string[];
110
113
  tags?: string[];
111
114
  description?: string;
112
- actionMenu?: ReactNode;
115
+ menuItems?: MenuItemProps[];
113
116
  }
114
117
 
115
- const ListResource = ({ link, title, tags, resourceImage, topics, description, actionMenu }: ListResourceProps) => {
118
+ const ListResource = ({ link, title, tags, resourceImage, topics, description, menuItems }: ListResourceProps) => {
116
119
  const showDescription = description !== undefined;
117
120
 
118
121
  return (
@@ -126,8 +129,8 @@ const ListResource = ({ link, title, tags, resourceImage, topics, description, a
126
129
  </TopicAndTitle>
127
130
  {showDescription && <ResourceDescription>{description}</ResourceDescription>}
128
131
  <TagsandActionMenu>
129
- {tags && CompressedTags(tags)}
130
- {actionMenu}
132
+ {tags && <CompressedTagList tags={tags} />}
133
+ {menuItems && menuItems.length > 0 && <MenuButton size="small" menuItems={menuItems} />}
131
134
  </TagsandActionMenu>
132
135
  </ResourceWrapper>
133
136
  );
@@ -103,7 +103,11 @@ export const TagList = ({ tags }: TagListProps) => {
103
103
  );
104
104
  };
105
105
 
106
- export const CompressedTags = (tags: string[]) => {
106
+ interface CompressedTagListProps {
107
+ tags: string[];
108
+ }
109
+
110
+ export const CompressedTagList = ({ tags }: CompressedTagListProps) => {
107
111
  const visibleTags = tags.slice(0, 3);
108
112
  const remainingTags = tags.slice(3, tags.length).map((tag) => {
109
113
  return {
@@ -11,6 +11,7 @@ import styled from '@emotion/styled';
11
11
  import { ArrowDropDown } from '@ndla/icons/common';
12
12
  import { FolderOutlined } from '@ndla/icons/contentType';
13
13
  import { colors, spacing, misc, animations } from '@ndla/core';
14
+ import SafeLink from '@ndla/safelink';
14
15
  import { SetFocusedFolderId, FolderChildFuncType } from './TreeStructure.types';
15
16
 
16
17
  const OpenButton = styled.button<{ isOpen: boolean }>`
@@ -75,7 +76,7 @@ const FolderName = styled.button<{ marked: boolean; noArrow?: boolean }>`
75
76
  text-align: left;
76
77
  `;
77
78
 
78
- const FolderNameLink = FolderName.withComponent('a');
79
+ const FolderNameLink = FolderName.withComponent(SafeLink);
79
80
 
80
81
  interface Props {
81
82
  name: string;
@@ -135,9 +136,9 @@ const FolderItem = ({
135
136
  <FolderNameLink
136
137
  ref={folderNameLinkRef}
137
138
  noArrow={hideArrow}
139
+ to={loading ? '' : url}
138
140
  tabIndex={marked ? 0 : -1}
139
141
  marked={marked}
140
- href={loading ? undefined : url}
141
142
  onFocus={() => {
142
143
  setFocusedFolderId(id);
143
144
  }}
@@ -12,7 +12,6 @@ import { animations, spacing } from '@ndla/core';
12
12
  import FolderItem from './FolderItem';
13
13
  import FolderNameInput from './FolderNameInput';
14
14
  import { FolderItemsProps } from './TreeStructure.types';
15
- import { MAX_LEVEL_FOR_FOLDERS } from './TreeStructure';
16
15
 
17
16
  const StyledUL = styled.ul<{ firstLevel?: boolean }>`
18
17
  ${animations.fadeInLeft(animations.durations.fast)};
@@ -49,6 +48,7 @@ const FolderItems = ({
49
48
  setFocusedFolderId,
50
49
  firstLevel,
51
50
  folderChild,
51
+ maximumLevelsOfFoldersAllowed,
52
52
  }: FolderItemsProps) => (
53
53
  <StyledUL role="group" firstLevel={firstLevel}>
54
54
  {data.map(({ name, data: dataChildren, id, url, icon }, _index) => {
@@ -69,7 +69,7 @@ const FolderItems = ({
69
69
  focusedFolderId={focusedFolderId}
70
70
  onToggleOpen={onToggleOpen}
71
71
  onMarkFolder={onMarkFolder}
72
- hideArrow={dataChildren?.length === 0 || newIdPaths.length >= MAX_LEVEL_FOR_FOLDERS}
72
+ hideArrow={dataChildren?.length === 0 || newIdPaths.length >= maximumLevelsOfFoldersAllowed}
73
73
  noPaddingWhenArrowIsHidden={editable && firstLevel && dataChildren?.length === 0}
74
74
  setFocusedFolderId={setFocusedFolderId}
75
75
  folderChild={folderChild}
@@ -101,6 +101,7 @@ const FolderItems = ({
101
101
  setFocusedFolderId={setFocusedFolderId}
102
102
  firstLevel={false}
103
103
  folderChild={folderChild}
104
+ maximumLevelsOfFoldersAllowed={maximumLevelsOfFoldersAllowed}
104
105
  />
105
106
  )}
106
107
  </StyledLI>
@@ -42,6 +42,7 @@ const TreeStructure = ({
42
42
  folderIdMarkedByDefault,
43
43
  defaultOpenFolders,
44
44
  folderChild,
45
+ maximumLevelsOfFoldersAllowed,
45
46
  }: TreeStructureProps) => {
46
47
  const { t } = useTranslation();
47
48
  const [newFolder, setNewFolder] = useState<NewFolderProps | undefined>();
@@ -117,6 +118,9 @@ const TreeStructure = ({
117
118
  setFocusedFolderId(id);
118
119
  };
119
120
 
121
+ const paths = getPathOfFolder(data, markedFolderId || '');
122
+ const canAddFolder = editable && paths.length < (maximumLevelsOfFoldersAllowed || 1);
123
+
120
124
  return (
121
125
  <div
122
126
  ref={treestructureRef}
@@ -132,7 +136,7 @@ const TreeStructure = ({
132
136
  });
133
137
  }
134
138
  }}>
135
- <StyledLabel htmlFor={rootLevelId}>{label}</StyledLabel>
139
+ {label && <StyledLabel htmlFor={rootLevelId}>{label}</StyledLabel>}
136
140
  <TreeStructureStyledWrapper ref={wrapperRef} id={rootLevelId} aria-label="Menu tree" role="tree" framed={framed}>
137
141
  <FolderItems
138
142
  idPaths={[]}
@@ -152,22 +156,28 @@ const TreeStructure = ({
152
156
  setFocusedFolderId={setFocusedFolderId}
153
157
  firstLevel
154
158
  folderChild={folderChild}
159
+ maximumLevelsOfFoldersAllowed={maximumLevelsOfFoldersAllowed}
155
160
  />
156
161
  </TreeStructureStyledWrapper>
157
162
  {editable && (
158
163
  <AddFolderWrapper>
159
164
  <Tooltip
160
- tooltip={t('myNdla.newFolderUnder', {
161
- folderName: getFolderName(data, markedFolderId),
162
- })}>
165
+ tooltip={
166
+ canAddFolder
167
+ ? t('myNdla.newFolderUnder', {
168
+ folderName: getFolderName(data, markedFolderId),
169
+ })
170
+ : t('myNdla.maxFoldersAlreadyAdded')
171
+ }>
163
172
  <AddButton
173
+ disabled={!canAddFolder}
164
174
  aria-label={t('myNdla.newFolder')}
165
175
  onClick={() => {
166
- const paths = getPathOfFolder(data, markedFolderId || '');
167
176
  const idPaths = getIdPathsOfFolder(data, markedFolderId || '');
168
177
  setNewFolder({ idPaths, parentId: paths[paths.length - 1] });
169
- }}
170
- />
178
+ }}>
179
+ {t('myNdla.newFolder')}
180
+ </AddButton>
171
181
  </Tooltip>
172
182
  </AddFolderWrapper>
173
183
  )}
@@ -175,4 +185,8 @@ const TreeStructure = ({
175
185
  );
176
186
  };
177
187
 
188
+ TreeStructure.defaultProps = {
189
+ maximumLevelsOfFoldersAllowed: MAX_LEVEL_FOR_FOLDERS,
190
+ };
191
+
178
192
  export default TreeStructure;
@@ -34,11 +34,12 @@ interface CommonFolderProps {
34
34
 
35
35
  export interface TreeStructureProps extends CommonFolderProps {
36
36
  framed?: boolean;
37
- label: string;
37
+ label?: string;
38
38
  folderIdMarkedByDefault?: string;
39
39
  onNewFolder: (props: { value: string; parentId?: string; idPaths: number[] }) => Promise<string>;
40
40
  defaultOpenFolders?: string[];
41
41
  folderChild?: FolderChildFuncType;
42
+ maximumLevelsOfFoldersAllowed: number;
42
43
  }
43
44
 
44
45
  export type onCreateNewFolderProp = ({
@@ -70,4 +71,5 @@ export interface FolderItemsProps extends CommonFolderProps {
70
71
  keyNavigationFocusIsCreateFolderButton?: boolean;
71
72
  icon?: ReactNode;
72
73
  folderChild?: FolderChildFuncType;
74
+ maximumLevelsOfFoldersAllowed: number;
73
75
  }
@@ -20,6 +20,7 @@ const messages = {
20
20
  delete: 'Delete',
21
21
  },
22
22
  createFolder: 'Create folder',
23
+ maxFoldersAlreadyAdded: 'Maximum subfolders reached',
23
24
  newFolder: {
24
25
  placeholder: 'Add foldername',
25
26
  defaultName: 'New folder',
@@ -988,7 +989,13 @@ const messages = {
988
989
  resources_plural: '{{count}} Resources',
989
990
  folders: '{{count}} Folder',
990
991
  folders_plural: '{{count}} Folders',
991
- folder: 'Folder',
992
+ folder: {
993
+ folder: 'Folder',
994
+ delete: 'Delete',
995
+ edit: 'Edit',
996
+ },
997
+ confirmDeleteFolder: 'Are you sure you want to delete this folder? This process cannot be undone.',
998
+ confirmDeleteTag: 'Are you sure you want to delete this tag? This process cannot be undone.',
992
999
  myFolders: 'My folders',
993
1000
  myTags: 'My tags',
994
1001
  newFolder: 'New folder',
@@ -1030,6 +1037,9 @@ const messages = {
1030
1037
  },
1031
1038
  },
1032
1039
  resource: {
1040
+ add: 'Add folder/tag',
1041
+ remove: 'Remove',
1042
+ copyLink: 'Copy link to this page',
1033
1043
  addToMyNdla: 'Add to My NDLA',
1034
1044
  addedToMyNdla: 'Added to My NDLA',
1035
1045
  },
@@ -20,6 +20,7 @@ const messages = {
20
20
  delete: 'Slett',
21
21
  },
22
22
  createFolder: 'Lag mappe',
23
+ maxFoldersAlreadyAdded: 'Maks nivå av undermapper nådd',
23
24
  newFolder: {
24
25
  placeholder: 'Skriv navn på mappe',
25
26
  defaultName: 'Ny mappe',
@@ -986,7 +987,13 @@ const messages = {
986
987
  resources_plural: '{{count}} ressurser',
987
988
  folders: '{{count}} mappe',
988
989
  folders_plural: '{{count}} mapper',
989
- folder: 'Mappe',
990
+ folder: {
991
+ folder: 'Mappe',
992
+ delete: 'Slett',
993
+ edit: 'Rediger',
994
+ },
995
+ confirmDeleteFolder: 'Er du sikker på at du vil slette mappen? Denne handlingen kan ikke angres.',
996
+ confirmDeleteTag: 'Er du sikker på at du vil slette tag? Denne handlingen kan ikke angres.',
990
997
  myFolders: 'Mine mapper',
991
998
  myTags: 'Mine tags',
992
999
  newFolder: 'Ny mappe',
@@ -1027,6 +1034,9 @@ const messages = {
1027
1034
  },
1028
1035
  },
1029
1036
  resource: {
1037
+ add: 'Legg til mappe/tag',
1038
+ remove: 'Fjern',
1039
+ copyLink: 'Kopier lenke til siden',
1030
1040
  addToMyNdla: 'Legg i Min NDLA',
1031
1041
  addedToMyNdla: 'Lagt i Min NDLA',
1032
1042
  },
@@ -20,6 +20,7 @@ const messages = {
20
20
  delete: 'Slett',
21
21
  },
22
22
  createFolder: 'Lag mappe',
23
+ maxFoldersAlreadyAdded: 'Maks nivå av undermapper nådd',
23
24
  newFolder: {
24
25
  placeholder: 'Skriv namn på mappe',
25
26
  defaultName: 'Ny mappe',
@@ -987,7 +988,13 @@ const messages = {
987
988
  resources_plural: '{{count}} ressursar',
988
989
  folders: '{{count}} mappe',
989
990
  folders_plural: '{{count}} mapper',
990
- folder: 'Mappe',
991
+ folder: {
992
+ folder: 'Mappe',
993
+ delete: 'Slett',
994
+ edit: 'Rediger',
995
+ },
996
+ confirmDeleteFolder: 'Er du sikker på at du vil slette mappa? Denne handlinga kan ikkje angres.',
997
+ confirmDeleteTag: 'Er du sikker på at du vil slette tag? Denne handlinga kan ikkje angres.',
991
998
  myFolders: 'Mine mapper',
992
999
  myTags: 'Mine tags',
993
1000
  newFolder: 'Ny mappe',
@@ -1028,6 +1035,9 @@ const messages = {
1028
1035
  },
1029
1036
  },
1030
1037
  resource: {
1038
+ add: 'Legg til mappe/tag',
1039
+ remove: 'Fjern',
1040
+ copyLink: 'Kopier lenke til sida',
1031
1041
  addToMyNdla: 'Legg i Min NDLA',
1032
1042
  addedToMyNdla: 'Lagt i Min NDLA',
1033
1043
  },