@ndla/ui 19.0.1 → 19.2.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 (64) hide show
  1. package/es/Breadcrumb/ActionBreadcrumb.js +9 -3
  2. package/es/MyNdla/Resource/Folder.js +7 -7
  3. package/es/Resource/ListResource.js +7 -7
  4. package/es/TreeStructure/FolderItem.js +54 -38
  5. package/es/TreeStructure/FolderItems.js +29 -35
  6. package/es/TreeStructure/FolderNameInput.js +11 -15
  7. package/es/TreeStructure/TreeStructure.js +64 -91
  8. package/es/TreeStructure/arrowNavigation.js +44 -0
  9. package/es/TreeStructure/helperFunctions.js +41 -35
  10. package/es/locale/messages-en.js +10 -1
  11. package/es/locale/messages-nb.js +10 -1
  12. package/es/locale/messages-nn.js +10 -1
  13. package/es/locale/messages-se.js +10 -1
  14. package/es/locale/messages-sma.js +10 -1
  15. package/lib/Breadcrumb/ActionBreadcrumb.js +9 -3
  16. package/lib/MyNdla/Resource/Folder.js +7 -7
  17. package/lib/Resource/ListResource.js +7 -7
  18. package/lib/TreeStructure/FolderItem.d.ts +6 -3
  19. package/lib/TreeStructure/FolderItem.js +55 -38
  20. package/lib/TreeStructure/FolderItems.d.ts +1 -1
  21. package/lib/TreeStructure/FolderItems.js +29 -35
  22. package/lib/TreeStructure/FolderNameInput.d.ts +3 -2
  23. package/lib/TreeStructure/FolderNameInput.js +11 -15
  24. package/lib/TreeStructure/TreeStructure.d.ts +1 -6
  25. package/lib/TreeStructure/TreeStructure.js +63 -92
  26. package/lib/TreeStructure/TreeStructure.types.d.ts +13 -20
  27. package/lib/TreeStructure/arrowNavigation.d.ts +9 -0
  28. package/lib/TreeStructure/arrowNavigation.js +54 -0
  29. package/lib/TreeStructure/helperFunctions.d.ts +3 -4
  30. package/lib/TreeStructure/helperFunctions.js +45 -35
  31. package/lib/locale/messages-en.d.ts +10 -1
  32. package/lib/locale/messages-en.js +10 -1
  33. package/lib/locale/messages-nb.d.ts +10 -1
  34. package/lib/locale/messages-nb.js +10 -1
  35. package/lib/locale/messages-nn.d.ts +10 -1
  36. package/lib/locale/messages-nn.js +10 -1
  37. package/lib/locale/messages-se.d.ts +10 -1
  38. package/lib/locale/messages-se.js +10 -1
  39. package/lib/locale/messages-sma.d.ts +10 -1
  40. package/lib/locale/messages-sma.js +10 -1
  41. package/package.json +5 -5
  42. package/src/Breadcrumb/ActionBreadcrumb.tsx +3 -0
  43. package/src/MyNdla/Resource/Folder.tsx +1 -1
  44. package/src/Resource/ListResource.tsx +4 -2
  45. package/src/TreeStructure/FolderItem.tsx +63 -40
  46. package/src/TreeStructure/FolderItems.tsx +26 -19
  47. package/src/TreeStructure/FolderNameInput.tsx +9 -11
  48. package/src/TreeStructure/TreeStructure.tsx +56 -71
  49. package/src/TreeStructure/TreeStructure.types.ts +13 -17
  50. package/src/TreeStructure/arrowNavigation.ts +53 -0
  51. package/src/TreeStructure/helperFunctions.ts +17 -25
  52. package/src/locale/messages-en.ts +10 -1
  53. package/src/locale/messages-nb.ts +10 -1
  54. package/src/locale/messages-nn.ts +10 -1
  55. package/src/locale/messages-se.ts +10 -1
  56. package/src/locale/messages-sma.ts +10 -1
  57. package/es/TreeStructure/keyboardNavigation/keyboardNavigation.js +0 -194
  58. package/es/TreeStructure/keyboardNavigation/keyboardNavigation.types.js +0 -0
  59. package/lib/TreeStructure/keyboardNavigation/keyboardNavigation.d.ts +0 -11
  60. package/lib/TreeStructure/keyboardNavigation/keyboardNavigation.js +0 -198
  61. package/lib/TreeStructure/keyboardNavigation/keyboardNavigation.types.d.ts +0 -26
  62. package/lib/TreeStructure/keyboardNavigation/keyboardNavigation.types.js +0 -1
  63. package/src/TreeStructure/keyboardNavigation/keyboardNavigation.ts +0 -161
  64. package/src/TreeStructure/keyboardNavigation/keyboardNavigation.types.ts +0 -28
@@ -7,7 +7,6 @@
7
7
  */
8
8
 
9
9
  import React, { useEffect, useState, useRef, useMemo } from 'react';
10
- import { uuid } from '@ndla/util';
11
10
  import { AddButton } from '@ndla/button';
12
11
  import Tooltip from '@ndla/tooltip';
13
12
  import { useTranslation } from 'react-i18next';
@@ -16,9 +15,8 @@ import { spacing, fonts } from '@ndla/core';
16
15
  import { uniq } from 'lodash';
17
16
  import TreeStructureStyledWrapper from './TreeStructureWrapper';
18
17
  import FolderItems from './FolderItems';
19
- import { getIdPathsOfFolder, getPathOfFolder, getFolderName } from './helperFunctions';
20
- import keyboardNavigation, { KEYBOARD_KEYS_OF_INTEREST } from './keyboardNavigation/keyboardNavigation';
21
- import { NewFolderProps, TreeStructureProps } from './TreeStructure.types';
18
+ import { getPathOfFolder, getFolderName, flattenFolders } from './helperFunctions';
19
+ import { TreeStructureProps } from './TreeStructure.types';
22
20
 
23
21
  export const MAX_LEVEL_FOR_FOLDERS = 4;
24
22
 
@@ -32,26 +30,32 @@ const AddFolderWrapper = styled.div`
32
30
  `;
33
31
 
34
32
  const TreeStructure = ({
35
- data,
33
+ folders,
36
34
  label,
37
35
  editable,
38
36
  loading,
39
37
  onNewFolder,
38
+ onSelectFolder,
40
39
  openOnFolderClick,
41
40
  framed,
42
41
  folderIdMarkedByDefault,
43
42
  defaultOpenFolders,
44
43
  folderChild,
45
- maximumLevelsOfFoldersAllowed,
44
+ maximumLevelsOfFoldersAllowed = MAX_LEVEL_FOR_FOLDERS,
46
45
  }: TreeStructureProps) => {
47
46
  const { t } = useTranslation();
48
- const [newFolder, setNewFolder] = useState<NewFolderProps | undefined>();
47
+ const [newFolderParentId, setNewFolderParentId] = useState<string | undefined>();
49
48
  const [openFolders, setOpenFolders] = useState<string[]>(defaultOpenFolders || []);
50
49
  const [focusedFolderId, setFocusedFolderId] = useState<string | undefined>();
51
- const [markedFolderId, setMarkedFolderId] = useState<string | undefined>(folderIdMarkedByDefault || data[0]?.id);
50
+ const [markedFolderId, setMarkedFolderId] = useState<string | undefined>(folderIdMarkedByDefault || folders[0]?.id);
52
51
  const treestructureRef = useRef<HTMLDivElement>(null);
53
52
  const wrapperRef = useRef<HTMLDivElement>(null);
54
- const rootLevelId = useMemo(() => uuid(), []); // TODO: use useId hook when we update to React 18
53
+ const rootLevelId = 'treestructure-root';
54
+
55
+ const visibleFolders = useMemo(
56
+ () => flattenFolders(folders, openFolders).map((folder) => folder.id),
57
+ [folders, openFolders],
58
+ );
55
59
 
56
60
  useEffect(() => {
57
61
  if (defaultOpenFolders) {
@@ -63,54 +67,51 @@ const TreeStructure = ({
63
67
 
64
68
  useEffect(() => {
65
69
  if (!loading) {
66
- setNewFolder(undefined);
70
+ setNewFolderParentId(undefined);
67
71
  }
68
72
  }, [loading]);
69
73
 
70
- const onToggleOpen = (id: string) => {
71
- if (openFolders.includes(id)) {
72
- // Did we just closed a folder with a marked folder inside it?
73
- // If so, we need to mark the folder we just closed.
74
- if (markedFolderId) {
75
- const closingFolderPath = getPathOfFolder(data, id);
76
- const markedFolderPath = getPathOfFolder(data, markedFolderId);
77
- const markedFolderIsSubPath = closingFolderPath.every(
78
- (folderId, _index) => markedFolderPath[_index] === folderId,
79
- );
80
- if (markedFolderIsSubPath) {
74
+ const onCloseFolder = (id: string) => {
75
+ // Did we just closed a folder with a marked folder inside it?
76
+ // If so, we need to mark the folder we just closed.
77
+ if (markedFolderId) {
78
+ const closingFolderPath = getPathOfFolder(folders, id);
79
+ const markedFolderPath = getPathOfFolder(folders, markedFolderId);
80
+ const markedFolderIsSubPath = closingFolderPath.every(
81
+ (folderId, _index) => markedFolderPath[_index] === folderId,
82
+ );
83
+ if (markedFolderIsSubPath) {
84
+ if (onSelectFolder) {
81
85
  setMarkedFolderId(closingFolderPath[closingFolderPath.length - 1]);
86
+ onSelectFolder(closingFolderPath[closingFolderPath.length - 1]);
87
+ } else {
88
+ setFocusedFolderId(closingFolderPath[closingFolderPath.length - 1]);
82
89
  }
83
90
  }
84
- setOpenFolders(openFolders.filter((folder) => folder !== id));
85
- } else {
86
- setOpenFolders(uniq([...openFolders, id]));
87
91
  }
92
+ setOpenFolders(openFolders.filter((folder) => folder !== id));
88
93
  };
89
94
 
90
- const onCreateNewFolder = (props: { idPaths: number[]; parentId?: string }) => {
91
- setNewFolder(props);
95
+ const onOpenFolder = (id: string) => {
96
+ setOpenFolders(uniq(openFolders.concat(id)));
92
97
  };
93
98
 
94
- const onSaveNewFolder = (value: string) => {
95
- if (newFolder) {
96
- // We would like to create a new folder with the name of value.
97
- // Its location in structure is based on newFolder object
98
- onNewFolder({ ...newFolder, value }).then((newFolderId) => {
99
- if (newFolderId) {
100
- setMarkedFolderId(newFolderId);
101
- setFocusedFolderId(newFolderId);
102
- // Open current folder in case it was closed..
103
-
104
- if (newFolder.parentId) {
105
- setOpenFolders(uniq([...openFolders, newFolder.parentId]));
106
- }
107
- }
108
- });
109
- }
99
+ const onCreateNewFolder = (parentId: string) => {
100
+ setNewFolderParentId(parentId);
101
+ };
102
+
103
+ const onSaveNewFolder = (name: string, parentId: string) => {
104
+ onNewFolder(name, parentId).then((newFolderId) => {
105
+ if (newFolderId) {
106
+ setMarkedFolderId(newFolderId);
107
+ setFocusedFolderId(newFolderId);
108
+ setOpenFolders(uniq(openFolders.concat(parentId)));
109
+ }
110
+ });
110
111
  };
111
112
 
112
113
  const onCancelNewFolder = () => {
113
- setNewFolder(undefined);
114
+ setNewFolderParentId(undefined);
114
115
  };
115
116
 
116
117
  const onMarkFolder = (id: string) => {
@@ -118,35 +119,25 @@ const TreeStructure = ({
118
119
  setFocusedFolderId(id);
119
120
  };
120
121
 
121
- const paths = getPathOfFolder(data, markedFolderId || '');
122
+ const paths = getPathOfFolder(folders, markedFolderId || '');
122
123
  const canAddFolder = editable && paths.length < (maximumLevelsOfFoldersAllowed || 1);
123
124
 
124
125
  return (
125
- <div
126
- ref={treestructureRef}
127
- onKeyDown={(e) => {
128
- if (wrapperRef.current?.contains(document.activeElement) && KEYBOARD_KEYS_OF_INTEREST.includes(e.key)) {
129
- keyboardNavigation({
130
- e,
131
- data,
132
- setFocusedFolderId,
133
- focusedFolderId,
134
- onToggleOpen,
135
- openFolders,
136
- });
137
- }
138
- }}>
126
+ <div ref={treestructureRef}>
139
127
  {label && <StyledLabel htmlFor={rootLevelId}>{label}</StyledLabel>}
140
128
  <TreeStructureStyledWrapper ref={wrapperRef} id={rootLevelId} aria-label="Menu tree" role="tree" framed={framed}>
141
129
  <FolderItems
142
- idPaths={[]}
143
- data={data}
130
+ onSelectFolder={onSelectFolder}
131
+ level={1}
132
+ folders={folders}
144
133
  editable={editable}
145
- onToggleOpen={onToggleOpen}
146
- newFolder={newFolder}
134
+ onOpenFolder={onOpenFolder}
135
+ onCloseFolder={onCloseFolder}
136
+ newFolderParentId={newFolderParentId}
147
137
  onCreateNewFolder={onCreateNewFolder}
148
138
  onCancelNewFolder={onCancelNewFolder}
149
139
  onSaveNewFolder={onSaveNewFolder}
140
+ visibleFolders={visibleFolders}
150
141
  openFolders={openFolders}
151
142
  markedFolderId={markedFolderId}
152
143
  onMarkFolder={onMarkFolder}
@@ -154,7 +145,6 @@ const TreeStructure = ({
154
145
  loading={loading}
155
146
  focusedFolderId={focusedFolderId}
156
147
  setFocusedFolderId={setFocusedFolderId}
157
- firstLevel
158
148
  folderChild={folderChild}
159
149
  maximumLevelsOfFoldersAllowed={maximumLevelsOfFoldersAllowed}
160
150
  />
@@ -165,16 +155,15 @@ const TreeStructure = ({
165
155
  tooltip={
166
156
  canAddFolder
167
157
  ? t('myNdla.newFolderUnder', {
168
- folderName: getFolderName(data, markedFolderId),
158
+ folderName: getFolderName(folders, markedFolderId),
169
159
  })
170
- : t('myNdla.maxFoldersAlreadyAdded')
160
+ : t('treeStructure.maxFoldersAlreadyAdded')
171
161
  }>
172
162
  <AddButton
173
163
  disabled={!canAddFolder}
174
164
  aria-label={t('myNdla.newFolder')}
175
165
  onClick={() => {
176
- const idPaths = getIdPathsOfFolder(data, markedFolderId || '');
177
- setNewFolder({ idPaths, parentId: paths[paths.length - 1] });
166
+ setNewFolderParentId(markedFolderId);
178
167
  }}>
179
168
  {t('myNdla.newFolder')}
180
169
  </AddButton>
@@ -185,8 +174,4 @@ const TreeStructure = ({
185
174
  );
186
175
  };
187
176
 
188
- TreeStructure.defaultProps = {
189
- maximumLevelsOfFoldersAllowed: MAX_LEVEL_FOR_FOLDERS,
190
- };
191
-
192
177
  export default TreeStructure;
@@ -11,35 +11,29 @@ import React, { ReactNode } from 'react';
11
11
  export interface FolderStructureProps {
12
12
  id: string;
13
13
  name: string;
14
- isOpen?: boolean;
15
- data?: FolderStructureProps[];
14
+ subfolders: FolderStructureProps[];
16
15
  isFavorite?: boolean;
17
16
  status?: string;
18
17
  openAsDefault?: boolean;
19
- url?: string;
20
18
  icon?: ReactNode;
21
19
  }
22
20
 
23
- export interface NewFolderProps {
24
- parentId?: string;
25
- idPaths: number[];
26
- }
27
-
28
21
  interface CommonFolderProps {
29
- data: FolderStructureProps[];
30
22
  editable?: boolean;
31
23
  loading?: boolean;
32
24
  openOnFolderClick?: boolean;
25
+ onSelectFolder?: (id: string) => void;
33
26
  }
34
27
 
35
28
  export interface TreeStructureProps extends CommonFolderProps {
29
+ folders: FolderStructureProps[];
36
30
  framed?: boolean;
37
31
  label?: string;
38
32
  folderIdMarkedByDefault?: string;
39
- onNewFolder: (props: { value: string; parentId?: string; idPaths: number[] }) => Promise<string>;
33
+ onNewFolder: (name: string, parentId: string) => Promise<string>;
40
34
  defaultOpenFolders?: string[];
41
35
  folderChild?: FolderChildFuncType;
42
- maximumLevelsOfFoldersAllowed: number;
36
+ maximumLevelsOfFoldersAllowed?: number;
43
37
  }
44
38
 
45
39
  export type onCreateNewFolderProp = ({
@@ -56,18 +50,20 @@ export type SetFocusedFolderId = React.Dispatch<React.SetStateAction<string | un
56
50
  export type FolderChildFuncType = (id: string, tabIndex: number) => ReactNode;
57
51
 
58
52
  export interface FolderItemsProps extends CommonFolderProps {
59
- onToggleOpen: (id: string) => void;
60
- onSaveNewFolder: (value: string) => void;
53
+ folders: FolderStructureProps[];
54
+ onCloseFolder: (id: string) => void;
55
+ onOpenFolder: (id: string) => void;
56
+ onSaveNewFolder: (name: string, parentId: string) => void;
61
57
  onCancelNewFolder: () => void;
62
- onCreateNewFolder: onCreateNewFolderProp;
63
- newFolder: NewFolderProps | undefined;
58
+ onCreateNewFolder: (parentId: string) => void;
59
+ newFolderParentId: string | undefined;
60
+ visibleFolders: string[];
64
61
  openFolders: string[];
65
62
  markedFolderId?: string;
66
63
  onMarkFolder: (id: string) => void;
67
- idPaths: number[];
64
+ level: number;
68
65
  focusedFolderId: string | undefined;
69
66
  setFocusedFolderId: SetFocusedFolderId;
70
- firstLevel: boolean;
71
67
  keyNavigationFocusIsCreateFolderButton?: boolean;
72
68
  icon?: ReactNode;
73
69
  folderChild?: FolderChildFuncType;
@@ -0,0 +1,53 @@
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 { KeyboardEvent } from 'react';
10
+
11
+ const navigateVertical = (
12
+ visibleFolders: string[],
13
+ folderId: string,
14
+ setFocusedFolderId: (id: string) => void,
15
+ direction: 1 | -1,
16
+ ) => {
17
+ const currentIndex = visibleFolders.findIndex((id) => id === folderId);
18
+ const target = visibleFolders[currentIndex + direction];
19
+ if (target !== undefined) {
20
+ setFocusedFolderId(target);
21
+ }
22
+ };
23
+
24
+ const arrowKeys = ['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'];
25
+
26
+ export const arrowNavigation = (
27
+ e: KeyboardEvent<HTMLElement>,
28
+ id: string,
29
+ visibleFolders: string[],
30
+ setFocusedFolderId: (id: string) => void,
31
+ onOpen: (id: string) => void,
32
+ onClose: (id: string) => void,
33
+ ) => {
34
+ if (!arrowKeys.includes(e.key)) {
35
+ return;
36
+ }
37
+
38
+ e.preventDefault();
39
+ e.stopPropagation();
40
+
41
+ switch (e.key) {
42
+ case 'ArrowUp':
43
+ return navigateVertical(visibleFolders, id, setFocusedFolderId, -1);
44
+ case 'ArrowDown':
45
+ return navigateVertical(visibleFolders, id, setFocusedFolderId, 1);
46
+ case 'ArrowLeft':
47
+ return onClose(id);
48
+ case 'ArrowRight':
49
+ return onOpen(id);
50
+ default:
51
+ return;
52
+ }
53
+ };
@@ -1,12 +1,12 @@
1
1
  import { FolderStructureProps } from './TreeStructure.types';
2
2
 
3
- const getPathOfFolder = (data: FolderStructureProps[], findId: string): string[] => {
4
- const paths = (dataChildren: FolderStructureProps[], path: string[]): string[] => {
5
- for (const { id, data: dataChildrenSub } of dataChildren) {
3
+ export const getPathOfFolder = (data: FolderStructureProps[], findId: string): string[] => {
4
+ const paths = (folders: FolderStructureProps[], path: string[]): string[] => {
5
+ for (const { id, subfolders } of folders) {
6
6
  if (id === findId) {
7
7
  return [...path, id];
8
- } else if (dataChildrenSub?.length) {
9
- return paths(dataChildrenSub, [...path, id]);
8
+ } else if (subfolders?.length) {
9
+ return paths(subfolders, [...path, id]);
10
10
  }
11
11
  }
12
12
  return [];
@@ -14,33 +14,18 @@ const getPathOfFolder = (data: FolderStructureProps[], findId: string): string[]
14
14
  return paths(data, []);
15
15
  };
16
16
 
17
- const getIdPathsOfFolder = (data: FolderStructureProps[], findId: string): number[] => {
18
- let currentPath: number[] = [];
19
- const paths = (dataChildren: FolderStructureProps[], path: number[]) => {
20
- dataChildren.forEach(({ id, data: dataChildrenSub }, _index) => {
21
- if (id === findId) {
22
- currentPath = [...path, _index];
23
- } else if (dataChildrenSub?.length) {
24
- paths(dataChildrenSub, [...path, _index]);
25
- }
26
- });
27
- };
28
- paths(data, []);
29
- return currentPath;
30
- };
31
-
32
- const getFolderName = (data: FolderStructureProps[], findId: string | undefined): string | undefined => {
17
+ export const getFolderName = (data: FolderStructureProps[], findId: string | undefined): string | undefined => {
33
18
  if (!findId) {
34
19
  return undefined;
35
20
  }
36
21
  let folderName: string | undefined;
37
22
  const paths = (dataChildren: FolderStructureProps[]) => {
38
- dataChildren.some(({ id, name, data: dataChildrenSub }, _index) => {
23
+ dataChildren.some(({ id, name, subfolders }, _index) => {
39
24
  if (id === findId) {
40
25
  folderName = name;
41
26
  return true;
42
- } else if (dataChildrenSub?.length) {
43
- return paths(dataChildrenSub);
27
+ } else if (subfolders?.length) {
28
+ return paths(subfolders);
44
29
  }
45
30
  return false;
46
31
  });
@@ -49,4 +34,11 @@ const getFolderName = (data: FolderStructureProps[], findId: string | undefined)
49
34
  return folderName;
50
35
  };
51
36
 
52
- export { getPathOfFolder, getIdPathsOfFolder, getFolderName };
37
+ export const flattenFolders = (folders: FolderStructureProps[], openFolders?: string[]): FolderStructureProps[] => {
38
+ return folders.reduce((acc, { subfolders, id, ...rest }) => {
39
+ if (!subfolders || (openFolders && !openFolders.includes(id))) {
40
+ return acc.concat({ subfolders, id, ...rest });
41
+ }
42
+ return acc.concat({ subfolders, id, ...rest }, flattenFolders(subfolders, openFolders));
43
+ }, [] as FolderStructureProps[]);
44
+ };
@@ -989,7 +989,13 @@ const messages = {
989
989
  resources_plural: '{{count}} Resources',
990
990
  folders: '{{count}} Folder',
991
991
  folders_plural: '{{count}} Folders',
992
- 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.',
993
999
  myFolders: 'My folders',
994
1000
  myTags: 'My tags',
995
1001
  newFolder: 'New folder',
@@ -1031,6 +1037,9 @@ const messages = {
1031
1037
  },
1032
1038
  },
1033
1039
  resource: {
1040
+ add: 'Add folder/tag',
1041
+ remove: 'Remove',
1042
+ copyLink: 'Copy link to this page',
1034
1043
  addToMyNdla: 'Add to My NDLA',
1035
1044
  addedToMyNdla: 'Added to My NDLA',
1036
1045
  },
@@ -987,7 +987,13 @@ const messages = {
987
987
  resources_plural: '{{count}} ressurser',
988
988
  folders: '{{count}} mappe',
989
989
  folders_plural: '{{count}} mapper',
990
- 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.',
991
997
  myFolders: 'Mine mapper',
992
998
  myTags: 'Mine tags',
993
999
  newFolder: 'Ny mappe',
@@ -1028,6 +1034,9 @@ const messages = {
1028
1034
  },
1029
1035
  },
1030
1036
  resource: {
1037
+ add: 'Legg til mappe/tag',
1038
+ remove: 'Fjern',
1039
+ copyLink: 'Kopier lenke til siden',
1031
1040
  addToMyNdla: 'Legg i Min NDLA',
1032
1041
  addedToMyNdla: 'Lagt i Min NDLA',
1033
1042
  },
@@ -988,7 +988,13 @@ const messages = {
988
988
  resources_plural: '{{count}} ressursar',
989
989
  folders: '{{count}} mappe',
990
990
  folders_plural: '{{count}} mapper',
991
- 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.',
992
998
  myFolders: 'Mine mapper',
993
999
  myTags: 'Mine tags',
994
1000
  newFolder: 'Ny mappe',
@@ -1029,6 +1035,9 @@ const messages = {
1029
1035
  },
1030
1036
  },
1031
1037
  resource: {
1038
+ add: 'Legg til mappe/tag',
1039
+ remove: 'Fjern',
1040
+ copyLink: 'Kopier lenke til sida',
1032
1041
  addToMyNdla: 'Legg i Min NDLA',
1033
1042
  addedToMyNdla: 'Lagt i Min NDLA',
1034
1043
  },
@@ -987,7 +987,13 @@ const messages = {
987
987
  resources_plural: '{{count}} ressurser',
988
988
  folders: '{{count}} mappe',
989
989
  folders_plural: '{{count}} mapper',
990
- 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.',
991
997
  myFolders: 'Mine mapper',
992
998
  myTags: 'Mine tags',
993
999
  newFolder: 'Ny mappe',
@@ -1028,6 +1034,9 @@ const messages = {
1028
1034
  },
1029
1035
  },
1030
1036
  resource: {
1037
+ add: 'Legg til mappe/tag',
1038
+ remove: 'Fjern',
1039
+ copyLink: 'Kopier lenke til siden',
1031
1040
  addToMyNdla: 'Legg i Min NDLA',
1032
1041
  addedToMyNdla: 'Lagt i Min NDLA',
1033
1042
  },
@@ -987,7 +987,13 @@ const messages = {
987
987
  resources_plural: '{{count}} ressurser',
988
988
  folders: '{{count}} mappe',
989
989
  folders_plural: '{{count}} mapper',
990
- 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.',
991
997
  myFolders: 'Mine mapper',
992
998
  myTags: 'Mine tags',
993
999
  newFolder: 'Ny mappe',
@@ -1028,6 +1034,9 @@ const messages = {
1028
1034
  },
1029
1035
  },
1030
1036
  resource: {
1037
+ add: 'Legg til mappe/tag',
1038
+ remove: 'Fjern',
1039
+ copyLink: 'Kopier lenke til siden',
1031
1040
  addToMyNdla: 'Legg i Min NDLA',
1032
1041
  addedToMyNdla: 'Lagt i Min NDLA',
1033
1042
  },