@truedat/core 4.28.2 → 4.28.6

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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## [4.28.6] 2021-09-20
4
+
5
+ ### Added
6
+
7
+ - [TD-3950] My grants table
8
+
3
9
  ## [4.27.5] 2021-08-31
4
10
 
5
11
  ### Changed
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@truedat/core",
3
- "version": "4.28.2",
3
+ "version": "4.28.6",
4
4
  "description": "Truedat Web Core",
5
5
  "sideEffects": false,
6
6
  "jsnext:main": "src/index.js",
@@ -32,7 +32,7 @@
32
32
  "@babel/plugin-transform-modules-commonjs": "^7.15.0",
33
33
  "@babel/preset-env": "^7.15.0",
34
34
  "@babel/preset-react": "^7.14.5",
35
- "@truedat/test": "4.28.2",
35
+ "@truedat/test": "4.28.6",
36
36
  "babel-jest": "^27.0.6",
37
37
  "babel-plugin-dynamic-import-node": "^2.3.3",
38
38
  "babel-plugin-lodash": "^3.3.4",
@@ -103,5 +103,5 @@
103
103
  "react-dom": ">= 16.8.6 < 17",
104
104
  "semantic-ui-react": ">= 0.88.2 < 2.1"
105
105
  },
106
- "gitHead": "b781ac2283e04337d5754ff1e0a28a8f2a4ffdfe"
106
+ "gitHead": "c1ed65b6c8440e73e478f07db743c0fd3a473c24"
107
107
  }
@@ -5,15 +5,21 @@ import {
5
5
  STRUCTURES,
6
6
  SYSTEMS,
7
7
  STRUCTURE_TAGS,
8
- STRUCTURE_TYPES
8
+ STRUCTURE_TYPES,
9
+ MY_GRANTS,
10
+ GRANTS,
9
11
  } from "../routes";
10
12
  import Submenu from "./Submenu";
11
13
 
12
- const items = [{ name: "structures", routes: [STRUCTURES, SYSTEMS] }];
14
+ const items = [
15
+ { name: "structures", routes: [STRUCTURES, SYSTEMS] },
16
+ { name: "my_grants", routes: [MY_GRANTS] },
17
+ { name: "grants", routes: [GRANTS] },
18
+ ];
13
19
 
14
20
  const adminItems = [
15
21
  { name: "structure_types", routes: [STRUCTURE_TYPES] },
16
- { name: "structure_tags", routes: [STRUCTURE_TAGS] }
22
+ { name: "structure_tags", routes: [STRUCTURE_TAGS] },
17
23
  ];
18
24
 
19
25
  export const CatalogMenu = () => {
@@ -0,0 +1,56 @@
1
+ import React, { useEffect, useState } from "react";
2
+ import moment from "moment";
3
+ import PropTypes from "prop-types";
4
+ import { useIntl } from "react-intl";
5
+ import { Form, Input, Label, Dropdown } from "semantic-ui-react";
6
+ import { DatesRangeInput } from "semantic-ui-calendar-react";
7
+
8
+ const validNumber = (value) => RegExp("^\\d+$").test(value);
9
+ const validRange = (value) =>
10
+ RegExp("^\\d{4}-\\d\\d-\\d\\d *- *\\d{4}-\\d\\d-\\d\\d$").test(value);
11
+
12
+ export const DateRangeFilter = ({
13
+ label,
14
+ onChange,
15
+ defaultValues,
16
+ size = "small",
17
+ name = "date",
18
+ dateFormat = "YYYY-MM-DD",
19
+ }) => {
20
+ const type = "range";
21
+ const unit = defaultValues?.unit || "d";
22
+ const value = defaultValues?.value || "1";
23
+ const [range, setRange] = useState(defaultValues?.range || "");
24
+ useEffect(() => {
25
+ const valid = type === "range" ? validRange(range) : validNumber(value);
26
+ if (valid) {
27
+ onChange({ name, type, range, unit, value });
28
+ }
29
+ }, [name, type, unit, value, range, onChange]);
30
+ const currentDate = moment();
31
+ return (
32
+ <DatesRangeInput
33
+ animation={null}
34
+ name="range"
35
+ placeholder="yyyy-mm-dd - yyyy-mm-dd"
36
+ iconPosition="left"
37
+ icon="calendar alternate outline"
38
+ allowSameEndDate
39
+ value={range}
40
+ maxDate={currentDate}
41
+ onChange={(_e, { value }) => setRange(value)}
42
+ dateFormat={dateFormat}
43
+ />
44
+ );
45
+ };
46
+
47
+ DateRangeFilter.propTypes = {
48
+ dateFormat: PropTypes.string,
49
+ defaultValues: PropTypes.object,
50
+ label: PropTypes.node,
51
+ name: PropTypes.string,
52
+ onChange: PropTypes.func,
53
+ size: PropTypes.string,
54
+ };
55
+
56
+ export default DateRangeFilter;
@@ -15,7 +15,7 @@ export const FilterDropdown = ({
15
15
  openFilter,
16
16
  options,
17
17
  removeFilter,
18
- toggleFilterValue
18
+ toggleFilterValue,
19
19
  }) => (
20
20
  <Dropdown
21
21
  item
@@ -28,7 +28,7 @@ export const FilterDropdown = ({
28
28
  <FormattedMessage id={`filters.${filter}`} defaultMessage={filter} />
29
29
  <Icon
30
30
  name="delete"
31
- onClick={e => {
31
+ onClick={(e) => {
32
32
  e.preventDefault();
33
33
  e.stopPropagation();
34
34
  removeFilter({ filter });
@@ -71,7 +71,7 @@ FilterDropdown.propTypes = {
71
71
  openFilter: PropTypes.func,
72
72
  options: PropTypes.array,
73
73
  removeFilter: PropTypes.func,
74
- toggleFilterValue: PropTypes.func
74
+ toggleFilterValue: PropTypes.func,
75
75
  };
76
76
 
77
77
  export default FilterDropdown;
@@ -5,7 +5,7 @@ import Submenu from "./Submenu";
5
5
 
6
6
  const items = [
7
7
  { name: "users", routes: [USERS, GROUPS] },
8
- { name: "roles", routes: [ROLES] }
8
+ { name: "roles", routes: [ROLES] },
9
9
  ];
10
10
 
11
11
  export const MembersMenu = () => {
@@ -12,6 +12,18 @@ exports[`<CatalogMenu /> matches the latest snapshot 1`] = `
12
12
  "/systems",
13
13
  ],
14
14
  },
15
+ Object {
16
+ "name": "my_grants",
17
+ "routes": Array [
18
+ "/my_grants",
19
+ ],
20
+ },
21
+ Object {
22
+ "name": "grants",
23
+ "routes": Array [
24
+ "/grants",
25
+ ],
26
+ },
15
27
  Object {
16
28
  "name": "structure_types",
17
29
  "routes": Array [
@@ -10,6 +10,7 @@ import CommentsLoader from "./CommentsLoader";
10
10
  import ConfirmModal from "./ConfirmModal";
11
11
  import DashboardMenu from "./DashboardMenu";
12
12
  import DateFilter from "./DateFilter";
13
+ import DateRangeFilter from "./DateRangeFilter";
13
14
  import DateTime from "./DateTime";
14
15
  import DropdownMenuItem from "./DropdownMenuItem";
15
16
  import ErrorBoundary from "./ErrorBoundary";
@@ -50,6 +51,7 @@ export {
50
51
  ConfirmModal,
51
52
  DashboardMenu,
52
53
  DateFilter,
54
+ DateRangeFilter,
53
55
  DateTime,
54
56
  DropdownMenuItem,
55
57
  ErrorBoundary,
@@ -1,7 +1,7 @@
1
1
  import _ from "lodash/fp";
2
2
  import { useSelector } from "react-redux";
3
3
 
4
- export const useAuthorized = allowedRoles => {
4
+ export const useAuthorized = (allowedRoles) => {
5
5
  const authentication = useSelector(_.propOr({}, "authentication"));
6
6
  const { role, groups } = authentication;
7
7
  return role === "admin"
@@ -9,14 +9,14 @@ export const useAuthorized = allowedRoles => {
9
9
  : _.flow(
10
10
  _.defaultTo([]),
11
11
  _.castArray,
12
- _.some(r => _.includes(r)(groups))
12
+ _.some((r) => _.includes(r)(groups))
13
13
  )(allowedRoles);
14
14
  };
15
15
 
16
- const filterByGroups = groups => itemGroups =>
17
- _.isEmpty(itemGroups) || _.some(r => _.includes(r)(groups))(itemGroups);
16
+ const filterByGroups = (groups) => (itemGroups) =>
17
+ _.isEmpty(itemGroups) || _.some((r) => _.includes(r)(groups))(itemGroups);
18
18
 
19
- export const useAuthorizedItems = items => {
19
+ export const useAuthorizedItems = (items) => {
20
20
  const authentication = useSelector(_.propOr({}, "authentication"));
21
21
  const { role, groups } = authentication;
22
22
 
@@ -25,6 +25,8 @@ export const useAuthorizedItems = items => {
25
25
  : _.flow(
26
26
  _.defaultTo([]),
27
27
  _.castArray,
28
- _.filter(i => _.flow(_.pathOr([], "groups"), filterByGroups(groups))(i))
28
+ _.filter((i) =>
29
+ _.flow(_.pathOr([], "groups"), filterByGroups(groups))(i)
30
+ )
29
31
  )(items);
30
32
  };
@@ -73,11 +73,13 @@ export default {
73
73
  "sidemenu.configurations": "Configuration",
74
74
  "sidemenu.dashboard": "Dashboard",
75
75
  "sidemenu.glossary": "Glossary",
76
+ "sidemenu.grants": "Grants",
76
77
  "sidemenu.hide": "Collapse sidebar",
77
78
  "sidemenu.ingests": "Data Requests",
78
79
  "sidemenu.implementations": "Implementations",
79
80
  "sidemenu.jobs": "Jobs",
80
81
  "sidemenu.lineage": "Lineage Analysis",
82
+ "sidemenu.my_grants": "My grants",
81
83
  "sidemenu.quality": "Data Quality",
82
84
  "sidemenu.quality_dashboard": "Quality Dashboard",
83
85
  "sidemenu.roles": "Roles",
@@ -76,11 +76,13 @@ export default {
76
76
  "sidemenu.configurations": "Configuración",
77
77
  "sidemenu.dashboard": "Dashboard",
78
78
  "sidemenu.glossary": "Glosario",
79
+ "sidemenu.grants": "Accesos",
79
80
  "sidemenu.hide": "Ocultar",
80
81
  "sidemenu.implementations": "Implementaciones",
81
82
  "sidemenu.ingests": "Peticiones de datos",
82
83
  "sidemenu.jobs": "Jobs",
83
84
  "sidemenu.lineage": "Linaje",
85
+ "sidemenu.my_grants": "Mis accesos",
84
86
  "sidemenu.quality": "Calidad",
85
87
  "sidemenu.quality_dashboard": "Dashboard de Calidad",
86
88
  "sidemenu.roles": "Roles",
package/src/routes.js CHANGED
@@ -40,6 +40,7 @@ export const DOMAIN_MEMBERS = "/domains/:id/members";
40
40
  export const DOMAIN_MEMBERS_NEW = "/domains/:id/members/new";
41
41
  export const DOMAIN_NEW = "/domains/:id/new";
42
42
  export const EXECUTION_GROUP = "/executionGroups/:id";
43
+ export const GRANTS = "/grants";
43
44
  export const GRANTS_REQUESTS_CHECKOUT = "/grants_requests/checkout";
44
45
  export const GRAPH = "/graphs/:id";
45
46
  export const GRAPHS = "/graphs";
@@ -66,6 +67,7 @@ export const INGEST_RELATIONS_STRUCTURES_NEW =
66
67
  export const JOB = "/jobs/:id";
67
68
  export const JOBS = "/jobs";
68
69
  export const LOGIN = "/login";
70
+ export const MY_GRANTS = "/my_grants";
69
71
  export const PASSWORD = "/password";
70
72
  export const PROFILE_EXECUTION =
71
73
  "/profileGroups/:group_id/profileExecutions/:id";
@@ -180,6 +182,7 @@ const routes = {
180
182
  DOMAINS_SEARCH,
181
183
  DOMAINS,
182
184
  EXECUTION_GROUP,
185
+ GRANTS,
183
186
  GRANTS_REQUESTS_CHECKOUT,
184
187
  GRAPH,
185
188
  GRAPHS,
@@ -204,6 +207,7 @@ const routes = {
204
207
  JOB,
205
208
  JOBS,
206
209
  LOGIN,
210
+ MY_GRANTS,
207
211
  PASSWORD,
208
212
  PROFILE_EXECUTION,
209
213
  PROFILE_GROUP,
@@ -6,33 +6,48 @@ import {
6
6
  propEq,
7
7
  propOr,
8
8
  split,
9
- stubTrue
9
+ stubTrue,
10
10
  } from "lodash/fp";
11
11
  import { createSelector } from "reselect";
12
12
 
13
13
  const relativeDate = ({ unit, value }) => `now-${value}${unit}`;
14
14
  const toDateRange = ([from, to]) => ({ gte: from, lt: `${to}||+1d` });
15
15
  const sinceDate = ({ name, ...props }) => ({
16
- [name]: { gte: relativeDate(props) }
16
+ [name]: { gte: relativeDate(props) },
17
17
  });
18
18
  const untilDate = ({ name, ...props }) => ({
19
- [name]: { lt: relativeDate(props) }
19
+ [name]: { lt: relativeDate(props) },
20
20
  });
21
21
  const dateRange = ({ name, range }) => ({
22
- [name]: toDateRange(split(" - ")(range))
22
+ [name]: toDateRange(split(" - ")(range)),
23
23
  });
24
24
 
25
+ const grantDateRange = ({ name, range }) => {
26
+ const [start_date, end_date] = split(",")(name);
27
+ const [from, to] = split(" - ")(range);
28
+
29
+ return from && to
30
+ ? {
31
+ [start_date]: { gte: from },
32
+ [end_date]: { lt: to },
33
+ }
34
+ : constant(empty);
35
+ };
36
+
25
37
  const empty = {};
26
38
 
27
- export const makeDateFiltersSelector = dateFilterProp =>
28
- createSelector(
39
+ export const makeDateFiltersSelector = (dateFilterProp) => {
40
+ const dateRangeFilter =
41
+ dateFilterProp === "grantDateFilter" ? grantDateRange : dateRange;
42
+ return createSelector(
29
43
  propOr(empty, dateFilterProp),
30
44
  cond([
31
45
  [negate(propEq("active", true)), constant(empty)],
32
46
  [negate(has("name")), constant(empty)],
33
47
  [propEq("type", "since"), sinceDate],
34
48
  [propEq("type", "before"), untilDate],
35
- [propEq("type", "range"), dateRange],
36
- [stubTrue, constant(empty)]
49
+ [propEq("type", "range"), dateRangeFilter],
50
+ [stubTrue, constant(empty)],
37
51
  ])
38
52
  );
53
+ };
@@ -2,14 +2,20 @@ import axios from "axios";
2
2
  import { readToken } from "./storage";
3
3
 
4
4
  axios.interceptors.request.use(
5
- function(config) {
5
+ function (config) {
6
6
  const token = readToken();
7
7
  if (token != null && !config.url.match(/\/sessions/)) {
8
- config.headers.Authorization = `Bearer ${token}`;
8
+ return {
9
+ ...config,
10
+ headers: {
11
+ ...config.headers,
12
+ Authorization: `Bearer ${token}`,
13
+ },
14
+ };
9
15
  }
10
16
  return config;
11
17
  },
12
- function(err) {
18
+ function (err) {
13
19
  return Promise.reject(err);
14
20
  }
15
21
  );
@@ -1,6 +1,6 @@
1
1
  import _ from "lodash/fp";
2
2
 
3
- export const columnDecorator = column => obj => {
3
+ export const columnDecorator = (column) => (obj) => {
4
4
  const { fieldSelector, fieldDecorator, name } = column || {};
5
5
  const field = _.isFunction(fieldSelector)
6
6
  ? fieldSelector(obj)
@@ -0,0 +1,24 @@
1
+ import _ from "lodash/fp";
2
+ import React from "react";
3
+
4
+ export const columnDecoratorComponent = (column) => (obj) => {
5
+ const { fieldSelector, fieldDecorator, name } = column || {};
6
+
7
+ if (_.isFunction(fieldSelector)) {
8
+ fieldSelector(obj);
9
+ }
10
+ const field = _.isFunction(fieldSelector)
11
+ ? fieldSelector(obj)
12
+ : _.path(_.defaultTo(name)(fieldSelector))(obj);
13
+
14
+ /*
15
+ * React.createElement to svoid warning "React has detected a change in the order of Hooks"
16
+ * caused by child fieldDecorator component calls to useIntl hook.
17
+ * https://stackoverflow.com/a/57456179
18
+ */
19
+ return _.isFunction(fieldDecorator)
20
+ ? React.createElement(fieldDecorator, field)
21
+ : field;
22
+ };
23
+
24
+ export default columnDecoratorComponent;
@@ -1 +1 @@
1
- export const formatNumber = value => value?.toLocaleString();
1
+ export const formatNumber = (value) => value?.toLocaleString();
@@ -6,14 +6,16 @@ import * as message from "./message";
6
6
  import * as sort from "./sort";
7
7
  import * as format from "./format";
8
8
  import columnDecorator from "./columnDecorator";
9
+ import columnDecoratorComponent from "./columnDecoratorComponent";
9
10
 
10
11
  export {
11
12
  api,
12
13
  arrays,
13
14
  columnDecorator,
15
+ columnDecoratorComponent,
14
16
  fieldType,
15
17
  filters,
16
18
  format,
17
19
  message,
18
- sort
20
+ sort,
19
21
  };
@@ -2,23 +2,24 @@ import _ from "lodash/fp";
2
2
 
3
3
  export const lowerDeburr = _.flow(_.toLower, _.deburr);
4
4
 
5
- export const lowerDeburrPath = path =>
5
+ export const lowerDeburrPath = (path) =>
6
6
  _.flow(_.path(path), _.toLower, _.deburr);
7
7
 
8
8
  export const accentInsensitiveOrder = [lowerDeburr, _.identity];
9
9
 
10
- export const accentInsensitivePathOrder = path => [
10
+ export const accentInsensitivePathOrder = (path) => [
11
11
  lowerDeburrPath(path),
12
- _.identity
12
+ _.identity,
13
13
  ];
14
14
 
15
15
  export const i18nOrder = (formatMessage, prefix) =>
16
16
  _.flow(
17
- value => formatMessage({ id: `${prefix}.${value}`, defaultMessage: value }),
17
+ (value) =>
18
+ formatMessage({ id: `${prefix}.${value}`, defaultMessage: value }),
18
19
  lowerDeburr
19
20
  );
20
21
 
21
- export const getSortInfo = sorting => {
22
+ export const getSortInfo = (sorting) => {
22
23
  const columnSorted = _.flow(_.nth(0), _.keys, _.nth(0))(sorting);
23
24
 
24
25
  const direction =
@@ -44,14 +45,14 @@ export const sortColumn = (
44
45
  setColumn(clickedColumn.sort.name);
45
46
  setDirection("ascending");
46
47
  const sortValues = {
47
- [columnName]: "asc"
48
+ [columnName]: "asc",
48
49
  };
49
50
  sort([sortValues]);
50
51
  return;
51
52
  } else {
52
53
  setDirection(currentDirection === "ascending" ? "descending" : "ascending");
53
54
  const sortValues = {
54
- [columnName]: currentDirection === "ascending" ? "desc" : "asc"
55
+ [columnName]: currentDirection === "ascending" ? "desc" : "asc",
55
56
  };
56
57
  sort([sortValues]);
57
58
  return;
@@ -1,5 +1,5 @@
1
1
  const token_key = "td_access_token";
2
2
 
3
3
  export const readToken = () => localStorage.getItem(token_key);
4
- export const saveToken = token => localStorage.setItem(token_key, token);
4
+ export const saveToken = (token) => localStorage.setItem(token_key, token);
5
5
  export const clearToken = () => localStorage.removeItem(token_key);