@truedat/core 5.9.1 → 5.9.2

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@truedat/core",
3
- "version": "5.9.1",
3
+ "version": "5.9.2",
4
4
  "description": "Truedat Web Core",
5
5
  "sideEffects": false,
6
6
  "jsnext:main": "src/index.js",
@@ -35,7 +35,7 @@
35
35
  "@testing-library/jest-dom": "^5.16.5",
36
36
  "@testing-library/react": "^12.0.0",
37
37
  "@testing-library/user-event": "^13.2.1",
38
- "@truedat/test": "5.8.5",
38
+ "@truedat/test": "5.9.2",
39
39
  "babel-jest": "^28.1.0",
40
40
  "babel-plugin-dynamic-import-node": "^2.3.3",
41
41
  "babel-plugin-lodash": "^3.3.4",
@@ -117,5 +117,5 @@
117
117
  "react-dom": ">= 16.8.6 < 17",
118
118
  "semantic-ui-react": ">= 2.0.3 < 2.2"
119
119
  },
120
- "gitHead": "aaeee38d6569e8c4c6bb605b0cc9b888bd4723a3"
120
+ "gitHead": "ba5871e60ce56d909e08e0ec304f9b9c6a30ca1c"
121
121
  }
@@ -1,6 +1,12 @@
1
+ import _ from "lodash/fp";
2
+ import PropTypes from "prop-types";
1
3
  import React from "react";
4
+ import { useQuery } from "@apollo/client";
5
+ import { CATALOG_VIEW_CONFIGS_QUERY } from "@truedat/dd/api/queries";
6
+ import { linkTo } from "@truedat/core/routes";
2
7
  import { useAuthorized } from "../hooks";
3
8
  import {
9
+ BUCKET_VIEW_CONFIGS,
4
10
  PENDING_STRUCTURE_NOTES,
5
11
  REFERENCE_DATASETS,
6
12
  STRUCTURES,
@@ -9,14 +15,20 @@ import {
9
15
  SYSTEMS,
10
16
  STRUCTURE_TAGS,
11
17
  } from "../routes";
18
+ import { Loading } from "./Loading";
12
19
  import Submenu from "./Submenu";
13
20
 
14
21
  const items = [
15
- { name: "structures", routes: [STRUCTURES, SYSTEMS] },
22
+ { name: "structures", routes: [STRUCTURES, SYSTEMS], beforeRest: true },
16
23
  { name: "referenceData", routes: [REFERENCE_DATASETS] },
17
24
  ];
18
25
 
19
26
  const adminItems = [
27
+ {
28
+ name: "catalogViewConfigs",
29
+ routes: [BUCKET_VIEW_CONFIGS],
30
+ beforeRest: true,
31
+ },
20
32
  { name: "structureTypes", routes: [STRUCTURE_TYPES] },
21
33
  { name: "structureTags", routes: [STRUCTURE_TAGS] },
22
34
  ];
@@ -26,17 +38,32 @@ const structureNoteItems = [
26
38
  { name: "structures_upload_events", routes: [STRUCTURES_UPLOAD_EVENTS] },
27
39
  ];
28
40
 
29
- export const CatalogMenu = () => {
41
+ const catalogViewConfigItems = _.flow(
42
+ _.map(({ fieldType, fieldName }) => ({
43
+ name: `${fieldType}.${fieldName}`,
44
+ routes: [
45
+ linkTo.BUCKETS_VIEW({ propertyPath: `${fieldType}.${fieldName}` }),
46
+ ],
47
+ beforeRest: true,
48
+ })),
49
+ _.orderBy(["name"], ["asc"])
50
+ );
51
+
52
+ export const CatalogMenu = ({ catalogViewConfigs }) => {
30
53
  const adminAuthorized = useAuthorized();
31
54
  const structureNotesAuthorized = useAuthorized(
32
55
  "data_dictionary_structure_notes"
33
56
  );
34
57
 
35
- const submenuItems = [
58
+ const submenuItems = _.flow(
59
+ _.partition({ beforeRest: true }),
60
+ _.flatten
61
+ )([
36
62
  ...items,
63
+ ...catalogViewConfigItems(catalogViewConfigs),
37
64
  ...(adminAuthorized ? adminItems : []),
38
65
  ...(structureNotesAuthorized ? structureNoteItems : []),
39
- ];
66
+ ]);
40
67
 
41
68
  const authorized = useAuthorized("data_dictionary");
42
69
  return authorized ? (
@@ -44,4 +71,20 @@ export const CatalogMenu = () => {
44
71
  ) : null;
45
72
  };
46
73
 
47
- export default CatalogMenu;
74
+ CatalogMenu.propTypes = {
75
+ catalogViewConfigs: PropTypes.array,
76
+ };
77
+
78
+ export const CatalogMenuLoader = (props) => {
79
+ const { loading, error, data } = useQuery(CATALOG_VIEW_CONFIGS_QUERY, {
80
+ fetchPolicy: "cache-and-network",
81
+ });
82
+ if (error) return null;
83
+ if (loading) return <Loading />;
84
+ const configs = data?.catalogViewConfigs || [];
85
+ return (
86
+ <CatalogMenu loading={loading} catalogViewConfigs={configs} {...props} />
87
+ );
88
+ };
89
+
90
+ export default CatalogMenuLoader;
@@ -6,11 +6,13 @@ import { FormattedMessage } from "react-intl";
6
6
  const defaultActions = (onConfirm) => [
7
7
  {
8
8
  key: "no",
9
+ "aria-label": "modal-negative-action",
9
10
  secondary: true,
10
11
  content: <FormattedMessage id="confirmation.no" />,
11
12
  },
12
13
  {
13
14
  key: "yes",
15
+ "aria-label": "modal-affirmative-action",
14
16
  negative: true,
15
17
  content: <FormattedMessage id="confirmation.yes" />,
16
18
  onClick: onConfirm,
@@ -6,10 +6,10 @@ import { connect } from "react-redux";
6
6
  import { useLocation, useHistory, Link } from "react-router-dom";
7
7
  import { Dropdown, Icon, Menu } from "semantic-ui-react";
8
8
  import { useAuthorizedItems, useActiveRoutes } from "@truedat/core/hooks";
9
+ import { clearNavFilter as clearBucketFilterRoutine } from "@truedat/dd/routines";
9
10
 
10
- export const MenuItem = ({ name, routes }) => {
11
+ export const MenuItem = ({ active, clearNavFilter, name, routes }) => {
11
12
  const { formatMessage } = useIntl();
12
- const active = useActiveRoutes(routes);
13
13
  const primaryRoute = _.flow(_.castArray, _.head)(routes);
14
14
  return (
15
15
  <Menu.Item
@@ -19,19 +19,23 @@ export const MenuItem = ({ name, routes }) => {
19
19
  to={primaryRoute}
20
20
  active={active}
21
21
  content={formatMessage({ id: `sidemenu.${name}`, defaultMessage: name })}
22
- onClick={(e) => e.stopPropagation()}
22
+ onClick={(e) => {
23
+ clearNavFilter();
24
+ return e.stopPropagation();
25
+ }}
23
26
  />
24
27
  );
25
28
  };
26
29
 
27
30
  MenuItem.propTypes = {
31
+ active: PropTypes.bool,
32
+ clearNavFilter: PropTypes.func,
28
33
  name: PropTypes.string,
29
34
  routes: PropTypes.array,
30
35
  };
31
36
 
32
- export const DropdownItem = ({ name, routes }) => {
37
+ export const DropdownItem = ({ active, clearNavFilter, name, routes }) => {
33
38
  const { formatMessage } = useIntl();
34
- const active = useActiveRoutes(routes);
35
39
  const primaryRoute = _.flow(_.castArray, _.head)(routes);
36
40
  return (
37
41
  <Dropdown.Item
@@ -40,19 +44,31 @@ export const DropdownItem = ({ name, routes }) => {
40
44
  to={primaryRoute}
41
45
  active={active}
42
46
  content={formatMessage({ id: `sidemenu.${name}`, defaultMessage: name })}
43
- onClick={(e) => e.stopPropagation()}
47
+ onClick={(e) => {
48
+ clearNavFilter();
49
+ return e.stopPropagation();
50
+ }}
44
51
  />
45
52
  );
46
53
  };
47
54
 
48
55
  DropdownItem.propTypes = {
56
+ active: PropTypes.bool,
57
+ clearNavFilter: PropTypes.func,
49
58
  name: PropTypes.string,
50
59
  routes: PropTypes.array,
51
60
  };
52
61
 
53
- export const Submenu = ({ items, icon, name, sidebarVisible }) => {
62
+ export const Submenu = ({
63
+ navFilter,
64
+ clearNavFilter,
65
+ items,
66
+ icon,
67
+ name,
68
+ sidebarVisible,
69
+ }) => {
54
70
  const [open, setOpen] = useState(false);
55
- const active = useActiveRoutes(_.flatMap("routes")(items));
71
+ const active = useActiveRoutes(_.flatMap("routes")(items), navFilter);
56
72
  const filteredItems = useAuthorizedItems(items);
57
73
  const location = useLocation();
58
74
  const history = useHistory();
@@ -62,7 +78,14 @@ export const Submenu = ({ items, icon, name, sidebarVisible }) => {
62
78
  const primaryRoute = _.flow(_.flatMap("routes"), _.head)(filteredItems);
63
79
  if (active && sidebarVisible) {
64
80
  const menuItems = filteredItems.map((item, i) => (
65
- <MenuItem key={i} {...item} />
81
+ <MenuItem
82
+ key={i}
83
+ {...{
84
+ ...item,
85
+ clearNavFilter,
86
+ active: _.includes(active, item?.routes),
87
+ }}
88
+ />
66
89
  ));
67
90
  return (
68
91
  <Menu.Item
@@ -91,8 +114,17 @@ export const Submenu = ({ items, icon, name, sidebarVisible }) => {
91
114
  </Link>
92
115
  );
93
116
  const dropdownItems = filteredItems.map((item, i) => (
94
- <DropdownItem key={i} {...item} />
117
+ <DropdownItem
118
+ key={i}
119
+ {...{
120
+ ...item,
121
+ navFilter,
122
+ clearNavFilter,
123
+ active: _.includes(active, item?.routes),
124
+ }}
125
+ />
95
126
  ));
127
+
96
128
  return (
97
129
  <div
98
130
  className={className}
@@ -131,11 +163,19 @@ export const Submenu = ({ items, icon, name, sidebarVisible }) => {
131
163
  };
132
164
 
133
165
  Submenu.propTypes = {
166
+ active: PropTypes.bool,
167
+ navFilter: PropTypes.object,
168
+ clearNavFilter: PropTypes.func,
134
169
  items: PropTypes.array,
135
170
  icon: PropTypes.string,
171
+ name: PropTypes.string,
136
172
  sidebarVisible: PropTypes.bool,
137
173
  };
138
174
 
139
- export const mapStateToProps = ({ sidebarVisible }) => ({ sidebarVisible });
175
+ export const mapStateToProps = ({ sidebarVisible, navFilter }) => {
176
+ return { sidebarVisible, navFilter };
177
+ };
140
178
 
141
- export default connect(mapStateToProps)(Submenu);
179
+ export default connect(mapStateToProps, {
180
+ clearNavFilter: clearBucketFilterRoutine,
181
+ })(Submenu);
@@ -1,5 +1,9 @@
1
+ import _ from "lodash/fp";
1
2
  import React from "react";
2
3
  import { render } from "@truedat/test/render";
4
+ import { within } from "@testing-library/react";
5
+ import { MemoryRouter } from "react-router-dom";
6
+ import { linkTo } from "@truedat/core/routes";
3
7
  import { CatalogMenu } from "../CatalogMenu";
4
8
 
5
9
  jest.mock("../../hooks", () => ({
@@ -7,7 +11,7 @@ jest.mock("../../hooks", () => ({
7
11
  useAuthorized: jest.fn(() => true),
8
12
  }));
9
13
 
10
- const renderOpts = {
14
+ const commonRenderOpts = {
11
15
  messages: {
12
16
  en: {},
13
17
  },
@@ -15,7 +19,63 @@ const renderOpts = {
15
19
 
16
20
  describe("<CatalogMenu />", () => {
17
21
  it("matches the latest snapshot", () => {
18
- const { container } = render(<CatalogMenu />, renderOpts);
22
+ const { container } = render(<CatalogMenu />, commonRenderOpts);
19
23
  expect(container).toMatchSnapshot();
20
24
  });
25
+
26
+ it("Path active route", () => {
27
+ const { container } = render(
28
+ <MemoryRouter initialEntries={[linkTo.STRUCTURE({ id: 1234 })]}>
29
+ <CatalogMenu />
30
+ </MemoryRouter>,
31
+ commonRenderOpts
32
+ );
33
+
34
+ const activeMenus = container.querySelectorAll('a[aria-checked="true"]');
35
+ expect(activeMenus.length).toBe(1);
36
+ expect(within(activeMenus[0]).getByText("structures")).toBeInTheDocument();
37
+ });
38
+
39
+ it("Navigation filter has priority over path for active menu and submenu", () => {
40
+ const renderOpts = {
41
+ ...commonRenderOpts,
42
+ state: {
43
+ navFilter: { "metadata.region": "eu-west-1" },
44
+ },
45
+ };
46
+
47
+ const catalogViewConfigs = [
48
+ {
49
+ id: "1",
50
+ fieldType: "metadata",
51
+ fieldName: "region",
52
+ },
53
+ {
54
+ id: "2",
55
+ fieldType: "note",
56
+ fieldName: "layer",
57
+ },
58
+ ];
59
+
60
+ const { getByText, container } = render(
61
+ <MemoryRouter initialEntries={[linkTo.STRUCTURE({ id: 1234 })]}>
62
+ <CatalogMenu catalogViewConfigs={catalogViewConfigs} />
63
+ </MemoryRouter>,
64
+ renderOpts
65
+ );
66
+
67
+ const structuresMenu = getByText("structures").closest("a");
68
+ const metadataBucketMenu = getByText("metadata.region").closest("a");
69
+ const noteBucketMenu = getByText("note.layer").closest("a");
70
+
71
+ expect(structuresMenu).toBeInTheDocument();
72
+ expect(metadataBucketMenu).toBeInTheDocument();
73
+ expect(noteBucketMenu).toBeInTheDocument();
74
+
75
+ const activeMenus = container.querySelectorAll('a[aria-checked="true"]');
76
+ expect(activeMenus.length).toBe(1);
77
+ expect(
78
+ within(activeMenus[0]).getByText("metadata.region")
79
+ ).toBeInTheDocument();
80
+ });
21
81
  });
@@ -42,6 +42,19 @@ exports[`<CatalogMenu /> matches the latest snapshot 1`] = `
42
42
  structures
43
43
  </span>
44
44
  </a>
45
+ <a
46
+ aria-checked="false"
47
+ class="item"
48
+ href="/bucketViewConfigs"
49
+ name="catalogViewConfigs"
50
+ role="option"
51
+ >
52
+ <span
53
+ class="text"
54
+ >
55
+ catalogViewConfigs
56
+ </span>
57
+ </a>
45
58
  <a
46
59
  aria-checked="false"
47
60
  class="item"
@@ -32,8 +32,8 @@ exports[`<GlossaryMenu /> matches the latest snapshot, finds fixed and subscopes
32
32
  class="divider"
33
33
  />
34
34
  <a
35
- aria-checked="true"
36
- class="active item"
35
+ aria-checked="false"
36
+ class="item"
37
37
  href="/concepts"
38
38
  name="concepts"
39
39
  role="option"
@@ -45,8 +45,8 @@ exports[`<GlossaryMenu /> matches the latest snapshot, finds fixed and subscopes
45
45
  </span>
46
46
  </a>
47
47
  <a
48
- aria-checked="true"
49
- class="active item"
48
+ aria-checked="false"
49
+ class="item"
50
50
  href="/subscopedConcepts/subscope1"
51
51
  name="subscope1"
52
52
  role="option"
@@ -58,8 +58,8 @@ exports[`<GlossaryMenu /> matches the latest snapshot, finds fixed and subscopes
58
58
  </span>
59
59
  </a>
60
60
  <a
61
- aria-checked="true"
62
- class="active item"
61
+ aria-checked="false"
62
+ class="item"
63
63
  href="/subscopedConcepts/subscope2"
64
64
  name="subscope2"
65
65
  role="option"
@@ -71,8 +71,8 @@ exports[`<GlossaryMenu /> matches the latest snapshot, finds fixed and subscopes
71
71
  </span>
72
72
  </a>
73
73
  <a
74
- aria-checked="true"
75
- class="active item"
74
+ aria-checked="false"
75
+ class="item"
76
76
  href="/pendingConcepts"
77
77
  name="concepts_management"
78
78
  role="option"
@@ -84,8 +84,8 @@ exports[`<GlossaryMenu /> matches the latest snapshot, finds fixed and subscopes
84
84
  </span>
85
85
  </a>
86
86
  <a
87
- aria-checked="true"
88
- class="active item"
87
+ aria-checked="false"
88
+ class="item"
89
89
  href="/links/concepts/management"
90
90
  name="concepts_links_management"
91
91
  role="option"
@@ -32,8 +32,8 @@ exports[`<QualityMenu /> matches the latest snapshot 1`] = `
32
32
  class="divider"
33
33
  />
34
34
  <a
35
- aria-checked="true"
36
- class="active item"
35
+ aria-checked="false"
36
+ class="item"
37
37
  href="/rules"
38
38
  name="rules"
39
39
  role="option"
@@ -45,8 +45,8 @@ exports[`<QualityMenu /> matches the latest snapshot 1`] = `
45
45
  </span>
46
46
  </a>
47
47
  <a
48
- aria-checked="true"
49
- class="active item"
48
+ aria-checked="false"
49
+ class="item"
50
50
  href="/implementations"
51
51
  name="implementations"
52
52
  role="option"
@@ -58,8 +58,8 @@ exports[`<QualityMenu /> matches the latest snapshot 1`] = `
58
58
  </span>
59
59
  </a>
60
60
  <a
61
- aria-checked="true"
62
- class="active item"
61
+ aria-checked="false"
62
+ class="item"
63
63
  href="/pendingImplementations"
64
64
  name="implementations_management"
65
65
  role="option"
@@ -71,8 +71,8 @@ exports[`<QualityMenu /> matches the latest snapshot 1`] = `
71
71
  </span>
72
72
  </a>
73
73
  <a
74
- aria-checked="true"
75
- class="active item"
74
+ aria-checked="false"
75
+ class="item"
76
76
  href="/deprecatedImplementations"
77
77
  name="implementations_deprecated"
78
78
  role="option"
@@ -84,8 +84,8 @@ exports[`<QualityMenu /> matches the latest snapshot 1`] = `
84
84
  </span>
85
85
  </a>
86
86
  <a
87
- aria-checked="true"
88
- class="active item"
87
+ aria-checked="false"
88
+ class="item"
89
89
  href="/executionGroups"
90
90
  name="executions"
91
91
  role="option"
@@ -44,6 +44,9 @@ exports[`<SideMenu /> matches the latest snapshot 1`] = `
44
44
  </div>
45
45
  </div>
46
46
  </div>
47
+ <div
48
+ class="ui active loader"
49
+ />
47
50
  <a
48
51
  class="item bottom"
49
52
  >
@@ -1,7 +1,7 @@
1
1
  import _ from "lodash/fp";
2
2
  import { useRouteMatch } from "react-router-dom";
3
3
 
4
- export const useActiveRoute = props => {
4
+ export const useActiveRoute = (props) => {
5
5
  const match = useRouteMatch(props);
6
6
  return _.has("path")(match);
7
7
  };
@@ -1,12 +1,32 @@
1
1
  import _ from "lodash/fp";
2
2
  import { useLocation } from "react-router-dom";
3
+ import { BUCKETS_VIEW } from "@truedat/core/routes";
4
+ import { matchPath } from "react-router";
3
5
 
4
- export const useActiveRoutes = route => {
6
+ export const useActiveRoutes = (route, navFilter) => {
5
7
  const location = useLocation();
6
8
  const pathname = _.prop("pathname")(location);
7
9
  const routes = _.castArray(route);
8
- return (
9
- _.any(_.eq(pathname))(routes) ||
10
- _.any(route => _.startsWith(`${route}/`)(pathname))(routes)
11
- );
10
+
11
+ return _.flow(
12
+ _.map((route) => ({
13
+ route,
14
+ filterMatch: matchPath(route, { path: BUCKETS_VIEW }),
15
+ })),
16
+ _.reduce(
17
+ (acc, { route, filterMatch }) => {
18
+ const { filterMatchRoutes, pathMatchRoutes } = acc;
19
+
20
+ return navFilter &&
21
+ _.includes(filterMatch?.params?.propertyPath, Object.keys(navFilter))
22
+ ? { ...acc, filterMatchRoutes: route }
23
+ : route === pathname || _.startsWith(`${route}/`)(pathname)
24
+ ? { ...acc, pathMatchRoutes: route }
25
+ : { filterMatchRoutes, pathMatchRoutes };
26
+ },
27
+ { filterMatchRoutes: null, pathMatchRoutes: null }
28
+ ),
29
+ ({ filterMatchRoutes, pathMatchRoutes }) =>
30
+ !_.isEmpty(filterMatchRoutes) ? filterMatchRoutes : pathMatchRoutes
31
+ )(routes);
12
32
  };
@@ -32,6 +32,9 @@ export default {
32
32
  "alert.status.500.header": "Internal Server Error (500)",
33
33
  "alert.status.504.content": "No response received from service ({text}).",
34
34
  "alert.status.504.header": "Gateway Timeout (504)",
35
+ "bucketViewConfig.fieldName": "Field name",
36
+ "bucketViewConfig.fieldType": "Field type",
37
+ "bucketViewConfigs.new": "New catalog view",
35
38
  "comments.actions.new": "New comment",
36
39
  "comments.header": "Comments",
37
40
  "components.CardGroupsAccordion.withoutGroups": "Without Groups",
@@ -73,7 +76,7 @@ export default {
73
76
  "i18n.messages.locale.es": "Spanish",
74
77
  "i18n.messages.locale.en": "English",
75
78
  "i18n.messages.search.placeholder": "Search messages",
76
-
79
+ missingBucket: "(Missing selected bucket)",
77
80
  "navigation.dashboard": "Dashboard",
78
81
  "navigation.menu": "Menu",
79
82
  "search.applied_filters": "Filters:",
@@ -100,6 +103,7 @@ export default {
100
103
  "validation.header.message.error": "Could you check something!",
101
104
  "sidemenu.admin": "Administration",
102
105
  "sidemenu.catalog": "Catalog",
106
+ "sidemenu.catalogViewConfigs": "Bucket view config",
103
107
  "sidemenu.concepts_links_management": "Links manager",
104
108
  "sidemenu.concepts_management": "Drafts",
105
109
  "sidemenu.concepts": "Glossary",
@@ -33,6 +33,9 @@ export default {
33
33
  "alert.status.504.content":
34
34
  "No se ha recibido ninguna respuesta del servicio ({text})",
35
35
  "alert.status.504.header": "Gateway Timeout (504)",
36
+ "bucketViewConfig.fieldName": "Nombre del campo",
37
+ "bucketViewConfig.fieldType": "Tipo de campo",
38
+ "bucketViewConfigs.new": "Nueva vista de catálogo",
36
39
  "comments.actions.new": "Añadir comentario",
37
40
  "comments.header": "Comentarios",
38
41
  "components.CardGroupsAccordion.withoutGroups": "Sin Agrupación",
@@ -75,6 +78,7 @@ export default {
75
78
  "i18n.messages.search.placeholder": "Buscar mensajes",
76
79
 
77
80
  loading: "cargando...",
81
+ missingBucket: "(Sin bucket seleccionado)",
78
82
  "navigation.dashboard": "Dashboard",
79
83
  "navigation.menu": "Menú",
80
84
  "search.applied_filters": "Filtros aplicados:",
@@ -103,6 +107,7 @@ export default {
103
107
  "validation.header.message.error": "Faltan campos por rellenar!",
104
108
  "sidemenu.admin": "Administración",
105
109
  "sidemenu.catalog": "Catálogo",
110
+ "sidemenu.catalogViewConfigs": "Config vistas bucket",
106
111
  "sidemenu.concepts_links_management": "Gestión de vínculos",
107
112
  "sidemenu.concepts_management": "Borradores",
108
113
  "sidemenu.concepts": "Glosario",
package/src/routes.js CHANGED
@@ -2,6 +2,11 @@ import _ from "lodash/fp";
2
2
  import { compile } from "path-to-regexp";
3
3
 
4
4
  export const CALLBACK = "/callback";
5
+ export const BUCKETS_VIEW = "/buckets/:propertyPath";
6
+ export const BUCKET_VIEW = "/bucketStructures";
7
+ export const BUCKET_VIEW_CONFIGS = "/bucketViewConfigs";
8
+ export const BUCKET_VIEW_CONFIG_EDIT = "/bucketViewConfigs/:id/edit";
9
+ export const BUCKET_VIEW_CONFIG_NEW = "/bucketViewConfigs/new";
5
10
  export const CONCEPTS = "/concepts";
6
11
  export const CONCEPTS_BULK_UPDATE = "/concepts/bulk_update";
7
12
  export const CONCEPTS_NEW = "/concepts/new";
@@ -226,6 +231,11 @@ export const USER_EDIT_PASSWORD = "/users/:id/password";
226
231
 
227
232
  const routes = {
228
233
  CALLBACK,
234
+ BUCKETS_VIEW,
235
+ BUCKET_VIEW,
236
+ BUCKET_VIEW_CONFIG_EDIT,
237
+ BUCKET_VIEW_CONFIG_NEW,
238
+ BUCKET_VIEW_CONFIGS,
229
239
  CONCEPTS,
230
240
  CONCEPTS_BULK_UPDATE,
231
241
  CONCEPTS_NEW,