@truedat/dd 4.44.5 → 4.45.3

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 (31) hide show
  1. package/CHANGELOG.md +7 -1
  2. package/package.json +7 -7
  3. package/src/components/StructureCrumbs.js +28 -11
  4. package/src/components/StructureItem.js +2 -1
  5. package/src/components/StructureSummary.js +7 -9
  6. package/src/components/StructureTabPane.js +4 -2
  7. package/src/components/__tests__/StructureItem.spec.js +23 -6
  8. package/src/components/__tests__/StructureItems.spec.js +14 -4
  9. package/src/components/__tests__/StructureProperties.spec.js +1 -1
  10. package/src/components/__tests__/StructureSummary.spec.js +13 -0
  11. package/src/components/__tests__/__snapshots__/StructureItem.spec.js.snap +68 -43
  12. package/src/components/__tests__/__snapshots__/StructureItems.spec.js.snap +47 -4
  13. package/src/components/__tests__/__snapshots__/StructureProperties.spec.js.snap +22 -0
  14. package/src/components/__tests__/__snapshots__/StructureSummary.spec.js.snap +102 -11
  15. package/src/components/__tests__/__snapshots__/StructureTabPane.spec.js.snap +1 -1
  16. package/src/components/index.js +0 -6
  17. package/src/reducers/structure.js +1 -0
  18. package/src/reducers/structures.js +2 -0
  19. package/src/selectors/__tests__/getStructureParent.spec.js +13 -4
  20. package/src/selectors/__tests__/getStructureProperties.spec.js +2 -2
  21. package/src/selectors/getSortedStructureChildren.js +1 -1
  22. package/src/selectors/getStructureFieldColumns.js +20 -14
  23. package/src/selectors/getStructureParent.js +9 -4
  24. package/src/selectors/getStructureProperties.js +12 -0
  25. package/src/selectors/structureColumnsSelector.js +11 -3
  26. package/src/components/ProfilingElements.js +0 -89
  27. package/src/components/ProfilingGraph.js +0 -89
  28. package/src/components/ProfilingPatterns.js +0 -57
  29. package/src/components/StructureProfiling.js +0 -124
  30. package/src/components/__tests__/StructureProfiling.spec.js +0 -45
  31. package/src/components/__tests__/__snapshots__/StructureProfiling.spec.js.snap +0 -444
@@ -16,8 +16,65 @@ exports[`<StructureSummary /> matches the latest snapshot 1`] = `
16
16
  <HeaderContent>
17
17
  s1
18
18
  <Connect(StructureGrantRequestButton) />
19
+ </HeaderContent>
20
+ </Header>
21
+ <Dimmer
22
+ active={false}
23
+ inverted={true}
24
+ >
25
+ <Loader />
26
+ </Dimmer>
27
+ </DimmerDimmable>
28
+ </GridColumn>
29
+ <GridColumn
30
+ textAlign="right"
31
+ width={6}
32
+ >
33
+ <Date
34
+ className="alert warning"
35
+ date="2019-01-02T03:04:05Z"
36
+ icon={
37
+ <Icon
38
+ as="i"
39
+ color="red"
40
+ name="warning circle"
41
+ />
42
+ }
43
+ label="deleted_at"
44
+ />
45
+ <Connect(ShareLinkPopup)
46
+ description="dd"
47
+ name="s1"
48
+ title="structure.share.title"
49
+ url="http://localhost/"
50
+ />
51
+ <injectIntl(Connect(StructureConfidentialButton)) />
52
+ </GridColumn>
53
+ </GridRow>
54
+ </Grid>
55
+ <Connect(TagsHeader) />
56
+ <Connect(StructureProperties) />
57
+ </Fragment>
58
+ `;
59
+
60
+ exports[`<StructureSummary /> matches the latest snapshot with alias 1`] = `
61
+ <Fragment>
62
+ <Grid>
63
+ <GridRow>
64
+ <GridColumn
65
+ width={10}
66
+ >
67
+ <DimmerDimmable
68
+ dimmed={false}
69
+ >
70
+ <Header
71
+ as="h2"
72
+ >
73
+ <HeaderContent>
74
+ some alias
75
+ <Connect(StructureGrantRequestButton) />
19
76
  <HeaderSubheader>
20
- foo
77
+ s1
21
78
  </HeaderSubheader>
22
79
  </HeaderContent>
23
80
  </Header>
@@ -84,11 +141,6 @@ exports[`<StructureSummary /> renders custom grant label when grant provided 1`]
84
141
  <p>
85
142
  bar
86
143
  </p>
87
- <div
88
- class="sub header"
89
- >
90
- foo
91
- </div>
92
144
  </div>
93
145
  </h2>
94
146
  <div
@@ -198,6 +250,28 @@ exports[`<StructureSummary /> renders custom grant label when grant provided 1`]
198
250
  </div>
199
251
  </div>
200
252
  </div>
253
+ <div
254
+ class="three wide column"
255
+ >
256
+ <div
257
+ class="item"
258
+ >
259
+ <div
260
+ class="content"
261
+ >
262
+ <h5
263
+ class="header"
264
+ >
265
+ structure.type
266
+ </h5>
267
+ <div
268
+ class="description"
269
+ >
270
+ foo
271
+ </div>
272
+ </div>
273
+ </div>
274
+ </div>
201
275
  </div>
202
276
  </div>
203
277
  </div>
@@ -233,11 +307,6 @@ exports[`<StructureSummary /> renders label when grant provided 1`] = `
233
307
  />
234
308
  structure.grant.has_grant
235
309
  </div>
236
- <div
237
- class="sub header"
238
- >
239
- foo
240
- </div>
241
310
  </div>
242
311
  </h2>
243
312
  <div
@@ -347,6 +416,28 @@ exports[`<StructureSummary /> renders label when grant provided 1`] = `
347
416
  </div>
348
417
  </div>
349
418
  </div>
419
+ <div
420
+ class="three wide column"
421
+ >
422
+ <div
423
+ class="item"
424
+ >
425
+ <div
426
+ class="content"
427
+ >
428
+ <h5
429
+ class="header"
430
+ >
431
+ structure.type
432
+ </h5>
433
+ <div
434
+ class="description"
435
+ >
436
+ foo
437
+ </div>
438
+ </div>
439
+ </div>
440
+ </div>
350
441
  </div>
351
442
  </div>
352
443
  </div>
@@ -55,7 +55,7 @@ exports[`<StructureTabPane /> matches the latest snapshot: notes 1`] = `
55
55
 
56
56
  exports[`<StructureTabPane /> matches the latest snapshot: profile 1`] = `
57
57
  <ErrorBoundary>
58
- <Connect(StructureProfiling) />
58
+ <lazy />
59
59
  </ErrorBoundary>
60
60
  `;
61
61
 
@@ -8,8 +8,6 @@ import LineageDownloadButton from "./LineageDownloadButton";
8
8
  import LineageGroup from "./LineageGroup";
9
9
  import LineageLink from "./LineageLink";
10
10
  import LineageRoutes from "./LineageRoutes";
11
- import ProfilingGraph from "./ProfilingGraph";
12
- import ProfilingPatterns from "./ProfilingPatterns";
13
11
  import StructureCrumbs from "./StructureCrumbs";
14
12
  import StructureEvents from "./StructureEvents";
15
13
  import StructureFieldRow from "./StructureFieldRow";
@@ -23,7 +21,6 @@ import StructureLoader from "./StructureLoader";
23
21
  import StructureNav from "./StructureNav";
24
22
  import StructureNotes from "./StructureNotes";
25
23
  import StructureNotesEdit from "./StructureNotesEdit";
26
- import StructureProfiling from "./StructureProfiling";
27
24
  import StructureProperties from "./StructureProperties";
28
25
  import StructureRow from "./StructureRow";
29
26
  import StructureSelectedFilters from "./StructureSelectedFilters";
@@ -64,8 +61,6 @@ export {
64
61
  LineageGroup,
65
62
  LineageLink,
66
63
  LineageRoutes,
67
- ProfilingGraph,
68
- ProfilingPatterns,
69
64
  StructureCrumbs,
70
65
  StructureEvents,
71
66
  StructureFieldRow,
@@ -79,7 +74,6 @@ export {
79
74
  StructureNav,
80
75
  StructureNotes,
81
76
  StructureNotesEdit,
82
- StructureProfiling,
83
77
  StructureProperties,
84
78
  StructureMetadata,
85
79
  StructureRow,
@@ -35,6 +35,7 @@ const structureVersionFields = _.pick([
35
35
  "grant",
36
36
  "grants",
37
37
  "siblings",
38
+ "published_note",
38
39
  ]);
39
40
 
40
41
  const structure = (state = initialState, { type, payload }) => {
@@ -19,6 +19,8 @@ const pickFields = _.pick([
19
19
  "domain",
20
20
  "metadata",
21
21
  "mutable_metadata",
22
+ "latest_note",
23
+ "published_note",
22
24
  ]);
23
25
 
24
26
  const structures = (state = initialState, { type, payload }) => {
@@ -2,24 +2,33 @@ import _ from "lodash/fp";
2
2
  import { getStructureParent } from "..";
3
3
 
4
4
  const structureParents = [
5
- { id: "1", name: "structure", type: "structure type" }
5
+ {
6
+ id: "1",
7
+ name: "structure",
8
+ type: "structure type",
9
+ published_note: { alias: "alias" },
10
+ },
6
11
  ];
7
12
  const system = { id: "1", name: "system", type: "system" };
8
13
 
9
14
  const structure = {
10
15
  id: "1",
11
16
  name: "structure",
12
- system: _.omit(["type"])(system)
17
+ system: _.omit(["type"])(system),
13
18
  };
14
19
 
15
20
  describe("selectors: getStructureParent", () => {
16
21
  const state = {
17
22
  structureParents,
18
- structure
23
+ structure,
19
24
  };
20
25
 
21
26
  it("get structure parent from state when is not empty", () => {
22
- const reply = _.flow(_.head, _.set("name", ".."))(structureParents);
27
+ const reply = _.flow(
28
+ _.head,
29
+ _.set("name", ".."),
30
+ _.omit("published_note")
31
+ )(structureParents);
23
32
  expect(getStructureParent(state)).toEqual(reply);
24
33
  });
25
34
 
@@ -10,9 +10,9 @@ describe("selectors: getStructureProperties", () => {
10
10
  });
11
11
 
12
12
  describe("selectors: getStructureProperties", () => {
13
- it("should return should return default properties when present", () => {
13
+ it("should return default properties when present", () => {
14
14
  const res = getStructureProperties({});
15
- expect(res).toHaveLength(2);
15
+ expect(res).toHaveLength(3);
16
16
  expect(res).toEqual(defaultStructureProperties);
17
17
  });
18
18
  });
@@ -7,7 +7,7 @@ export const getSortedStructureChildren = createSelector(
7
7
  _.propOr([], "structureChildren"),
8
8
  _.propOr([], "structureSiblings"),
9
9
  _.propOr([], "systemStructures"),
10
- getStructureSortingCriteria
10
+ getStructureSortingCriteria,
11
11
  ],
12
12
  (
13
13
  structureChildren,
@@ -7,25 +7,31 @@ import { Link } from "react-router-dom";
7
7
  import { linkTo } from "@truedat/core/routes";
8
8
  import { accentInsensitivePathOrder } from "@truedat/core/services/sort";
9
9
 
10
- const translateDecorator = text => <FormattedMessage id={text} />;
10
+ const translateDecorator = (text) => <FormattedMessage id={text} />;
11
11
 
12
12
  const translateDecoratorWithDefault = (text, default_text) => (
13
13
  <FormattedMessage id={text} defaultMessage={default_text} />
14
14
  );
15
15
 
16
- const typeDecorator = field =>
16
+ const typeDecorator = (field) =>
17
17
  translateDecoratorWithDefault(`structure.type.${field}`, field);
18
18
 
19
- const linkToStructureDecorator = ({ data_structure_id: id, name }) => (
20
- <Link to={linkTo.STRUCTURE({ id })}>{name}</Link>
19
+ const linkToStructureDecorator = ({
20
+ data_structure_id: id,
21
+ name,
22
+ published_note,
23
+ }) => (
24
+ <Link to={linkTo.STRUCTURE({ id })}>
25
+ {_.isEmpty(published_note?.alias) ? name : published_note.alias}
26
+ </Link>
21
27
  );
22
28
 
23
- const nullableDecorator = field =>
29
+ const nullableDecorator = (field) =>
24
30
  field
25
31
  ? translateDecorator("structure.field.nullable.true")
26
32
  : translateDecorator("structure.field.nullable.false");
27
33
 
28
- const hasDfContentDecorator = has_df_content =>
34
+ const hasDfContentDecorator = (has_df_content) =>
29
35
  has_df_content && translateDecorator("structure.field.nullable.true");
30
36
 
31
37
  const lineageLinkDecorator = ({ degree, data_structure_id: id }) =>
@@ -42,7 +48,7 @@ const lineageLinkDecorator = ({ degree, data_structure_id: id }) =>
42
48
  </Link>
43
49
  );
44
50
 
45
- export const linksDecorator = links => {
51
+ export const linksDecorator = (links) => {
46
52
  const sortedLinks = _.sortBy(accentInsensitivePathOrder("name"))(links);
47
53
  return (
48
54
  !_.isEmpty(sortedLinks) && (
@@ -52,7 +58,7 @@ export const linksDecorator = links => {
52
58
  <Link
53
59
  to={linkTo.CONCEPT_VERSION({
54
60
  business_concept_id: resource.resource_id,
55
- id: "current"
61
+ id: "current",
56
62
  })}
57
63
  >
58
64
  {resource.name}
@@ -67,8 +73,8 @@ export const linksDecorator = links => {
67
73
  export const defaultStructureFieldColumns = [
68
74
  {
69
75
  name: "name",
70
- fieldSelector: _.pick(["data_structure_id", "name"]),
71
- fieldDecorator: linkToStructureDecorator
76
+ fieldSelector: _.pick(["data_structure_id", "name", "published_note"]),
77
+ fieldDecorator: linkToStructureDecorator,
72
78
  },
73
79
  { name: "type", fieldDecorator: typeDecorator },
74
80
  { name: "precision" },
@@ -76,18 +82,18 @@ export const defaultStructureFieldColumns = [
76
82
  { name: "description" },
77
83
  {
78
84
  name: "has_df_content",
79
- fieldDecorator: hasDfContentDecorator
85
+ fieldDecorator: hasDfContentDecorator,
80
86
  },
81
87
  {
82
88
  name: "degree",
83
89
  fieldSelector: _.pick(["degree", "data_structure_id"]),
84
90
  fieldDecorator: lineageLinkDecorator,
85
- textAlign: "center"
91
+ textAlign: "center",
86
92
  },
87
93
  {
88
94
  name: "links",
89
- fieldDecorator: linksDecorator
90
- }
95
+ fieldDecorator: linksDecorator,
96
+ },
91
97
  ];
92
98
 
93
99
  export const getStructureFieldColumns = createSelector(
@@ -3,16 +3,21 @@ import { createSelector } from "reselect";
3
3
 
4
4
  const defaultName = "..";
5
5
 
6
- const systemNavItem = structure =>
6
+ const systemNavItem = (structure) =>
7
7
  _.flow(
8
8
  _.propOr({}, "system"),
9
9
  _.pick(["id", "name"]),
10
10
  _.set("type", "system"),
11
- _.set("name", defaultName)
11
+ _.set("name", defaultName),
12
+ _.omit(["published_note"])
12
13
  )(structure);
13
14
 
14
- const structureNavItem = structures =>
15
- _.flow(_.head, _.set("name", defaultName))(structures);
15
+ const structureNavItem = (structures) =>
16
+ _.flow(
17
+ _.head,
18
+ _.set("name", defaultName),
19
+ _.omit(["published_note"])
20
+ )(structures);
16
21
 
17
22
  export const getStructureParent = createSelector(
18
23
  [_.propOr({}, "structure"), _.propOr([], "structureParents")],
@@ -1,6 +1,7 @@
1
1
  import _ from "lodash/fp";
2
2
  import React from "react";
3
3
  import { createSelector } from "reselect";
4
+ import { FormattedMessage } from "react-intl";
4
5
  import EditDomainPopup from "../components/EditDomainPopup";
5
6
 
6
7
  const domainDecorator = (domainNames) => (
@@ -10,6 +11,12 @@ const domainDecorator = (domainNames) => (
10
11
  </>
11
12
  );
12
13
 
14
+ const typeDecorator = ({ type, data_structure_type }) => (
15
+ <FormattedMessage
16
+ id={`structure.type.${type}.text`}
17
+ defaultMessage={_.get("translation")(data_structure_type) || type}
18
+ />
19
+ );
13
20
  export const defaultStructureProperties = [
14
21
  {
15
22
  name: "domain",
@@ -17,6 +24,11 @@ export const defaultStructureProperties = [
17
24
  fieldDecorator: domainDecorator,
18
25
  },
19
26
  { name: "group" },
27
+ {
28
+ name: "type",
29
+ fieldSelector: _.pick(["type", "data_structure_type"]),
30
+ fieldDecorator: typeDecorator,
31
+ },
20
32
  ];
21
33
 
22
34
  export const getStructureProperties = createSelector(
@@ -14,9 +14,15 @@ const typeTranslateDecorator = ({ type, data_structure_type }) => (
14
14
  const dateDecorator = (date) => (
15
15
  <Moment locale="es" date={date} format="YYYY-MM-DD HH:mm" />
16
16
  );
17
-
17
+ const nameFieldSelector = ({ name, published_note }) =>
18
+ _.isEmpty(published_note?.alias) ? name : published_note.alias;
18
19
  export const defaultStructureColumns = [
19
- { name: "name", sort: { name: "name.sort" }, width: 2 },
20
+ {
21
+ name: "name",
22
+ fieldSelector: nameFieldSelector,
23
+ sort: { name: "name.sort" },
24
+ width: 2,
25
+ },
20
26
  {
21
27
  name: "type",
22
28
  fieldSelector: _.pick(["type", "data_structure_type"]),
@@ -82,5 +88,7 @@ export const structureRowsSelector = createSelector(
82
88
  getStructures,
83
89
  getStructureColumnNames,
84
90
  (structures, columnNames) =>
85
- _.map(_.pick([...columnNames, "id", "domain_id"]))(structures)
91
+ _.map(_.pick([...columnNames, "id", "domain_id", "published_note"]))(
92
+ structures
93
+ )
86
94
  );
@@ -1,89 +0,0 @@
1
- import _ from "lodash/fp";
2
- import React, { useState } from "react";
3
- import PropTypes from "prop-types";
4
- import { connect } from "react-redux";
5
- import { Button, Icon, Grid } from "semantic-ui-react";
6
- import { FormattedMessage } from "react-intl";
7
- import ProfilingGraph from "./ProfilingGraph";
8
- import ProfilingPatterns from "./ProfilingPatterns";
9
-
10
- export const ProfilingElements = ({ profile }) => {
11
- const { most_frequent, patterns } = profile || {};
12
- const [elementActive, setElementActive] = useState("graph");
13
- const titleElement =
14
- elementActive === "graph"
15
- ? "structure.field.graph.title"
16
- : "structure.field.patterns.title";
17
- return (
18
- <>
19
- {!_.isEmpty(most_frequent) && !_.isEmpty(patterns) && (
20
- <>
21
- <Grid>
22
- <Grid.Column width={8}>
23
- <p>
24
- <FormattedMessage id={titleElement} />:
25
- </p>
26
- </Grid.Column>
27
- <Grid.Column width={8} textAlign="right">
28
- <Button.Group floated="right">
29
- <Button
30
- active={elementActive === "graph"}
31
- icon
32
- onClick={() => setElementActive("graph")}
33
- >
34
- <Icon name="chart line" />
35
- </Button>
36
- <Button
37
- active={elementActive === "patterns"}
38
- icon
39
- onClick={() => setElementActive("patterns")}
40
- >
41
- <Icon name="list ul" />
42
- </Button>
43
- </Button.Group>
44
- </Grid.Column>
45
- </Grid>
46
-
47
- {elementActive === "graph" && <ProfilingGraph />}
48
- {elementActive === "patterns" && <ProfilingPatterns />}
49
- </>
50
- )}
51
-
52
- {!_.isEmpty(most_frequent) && _.isEmpty(patterns) && (
53
- <>
54
- <Grid>
55
- <Grid.Column width={16}>
56
- <p>
57
- <FormattedMessage id="structure.field.graph.title" />:
58
- </p>
59
- </Grid.Column>
60
- </Grid>
61
-
62
- <ProfilingGraph />
63
- </>
64
- )}
65
-
66
- {_.isEmpty(most_frequent) && !_.isEmpty(patterns) && (
67
- <>
68
- <Grid>
69
- <Grid.Column width={16}>
70
- <p>
71
- <FormattedMessage id="structure.field.patterns.title" />
72
- </p>
73
- </Grid.Column>
74
- </Grid>
75
-
76
- <ProfilingPatterns />
77
- </>
78
- )}
79
- </>
80
- );
81
- };
82
-
83
- ProfilingElements.propTypes = {
84
- profile: PropTypes.object,
85
- };
86
-
87
- const mapStateToProps = ({ structureProfile: profile }) => ({ profile });
88
-
89
- export default connect(mapStateToProps)(ProfilingElements);
@@ -1,89 +0,0 @@
1
- import _ from "lodash/fp";
2
- import React, { useState } from "react";
3
- import PropTypes from "prop-types";
4
- import { connect } from "react-redux";
5
- import { Label } from "semantic-ui-react";
6
- import { FormattedMessage } from "react-intl";
7
- import { XYPlot, XAxis, YAxis, HorizontalBarSeries, Hint } from "react-vis";
8
-
9
- const getDistribution = _.flow(
10
- _.pathOr("[]", "most_frequent"),
11
- _.map(({ k, v }) => ({ x: v, y: k })),
12
- _.orderBy("x", "desc"),
13
- _.take(30),
14
- _.reverse
15
- );
16
-
17
- const getMinMax = _.flow(
18
- _.map("x"),
19
- (d) => [_.min(d) - 1, _.max(d)],
20
- _.defaultTo([-Infinity, Infinity])
21
- );
22
-
23
- const formatNumber = (num) =>
24
- num.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, "$1,");
25
-
26
- export const ProfilingGraph = ({ count, distribution }) => {
27
- const [hintValue, setHintValue] = useState(null);
28
- const data = _.map((d) => ({ color: d.y == hintValue?.y ? 0 : 1, ...d }))(
29
- distribution
30
- );
31
- return (
32
- <XYPlot
33
- yType="ordinal"
34
- xType="linear"
35
- width={800}
36
- height={400}
37
- margin={{ left: 180 }}
38
- xDomain={getMinMax(data)}
39
- colorRange={["#ed5c17", "#002057"]}
40
- >
41
- <YAxis
42
- tickFormat={_.truncate({ length: 30 })}
43
- style={{ fontSize: "12px", width: "100px" }}
44
- />
45
- <XAxis style={{ fontSize: "12px" }} />
46
- <HorizontalBarSeries
47
- onValueMouseOver={setHintValue}
48
- onValueMouseOut={() => setHintValue(null)}
49
- data={data}
50
- />
51
- {hintValue ? (
52
- <Hint
53
- style={{ width: "500px", bottom: "190px" }}
54
- align={{ horizontal: "right", vertical: "top" }}
55
- value={hintValue}
56
- >
57
- <Label pointing="left" className="graph">
58
- <div>
59
- <div>
60
- <FormattedMessage id="structure.field.graph.value" />
61
- {hintValue.y}
62
- </div>
63
- <div>
64
- <FormattedMessage id="structure.field.graph.count" />
65
- {formatNumber(hintValue.x)}
66
- </div>
67
- <div>
68
- <FormattedMessage id="structure.field.graph.percentage" />
69
- {Math.floor((hintValue.x / count) * 100) + "%"}
70
- </div>
71
- </div>
72
- </Label>
73
- </Hint>
74
- ) : null}
75
- </XYPlot>
76
- );
77
- };
78
-
79
- ProfilingGraph.propTypes = {
80
- count: PropTypes.number,
81
- distribution: PropTypes.arrayOf(PropTypes.object),
82
- };
83
-
84
- const mapStateToProps = ({ structureProfile }) => ({
85
- count: structureProfile?.total_count,
86
- distribution: getDistribution(structureProfile),
87
- });
88
-
89
- export default connect(mapStateToProps)(ProfilingGraph);
@@ -1,57 +0,0 @@
1
- import _ from "lodash/fp";
2
- import React from "react";
3
- import PropTypes from "prop-types";
4
- import { connect } from "react-redux";
5
- import { Table } from "semantic-ui-react";
6
- import { useIntl } from "react-intl";
7
-
8
- export const ProfilingPatterns = ({ patterns, totalCount }) => {
9
- const { formatNumber, formatMessage } = useIntl();
10
- const dataPatterns = _.flow(
11
- _.orderBy("v", "desc"),
12
- _.map(({ k, v }) => ({
13
- frecuency: k,
14
- count: formatNumber(v),
15
- percentage: parseFloat(((v / totalCount) * 100).toFixed(2)),
16
- }))
17
- )(patterns);
18
-
19
- return !_.isEmpty(dataPatterns) ? (
20
- <Table>
21
- <Table.Header>
22
- <Table.Row>
23
- <Table.HeaderCell>
24
- {formatMessage({ id: "structure.field.patterns.frecuency" })}
25
- </Table.HeaderCell>
26
- <Table.HeaderCell>
27
- {formatMessage({ id: "structure.field.patterns.count" })}
28
- </Table.HeaderCell>
29
- <Table.HeaderCell>
30
- {formatMessage({ id: "structure.field.patterns.percentage" })}
31
- </Table.HeaderCell>
32
- </Table.Row>
33
- </Table.Header>
34
- <Table.Body>
35
- {dataPatterns.map((pattern, i) => (
36
- <Table.Row key={i}>
37
- <Table.Cell>{pattern.frecuency}</Table.Cell>
38
- <Table.Cell>{pattern.count}</Table.Cell>
39
- <Table.Cell>{`${pattern.percentage} %`}</Table.Cell>
40
- </Table.Row>
41
- ))}
42
- </Table.Body>
43
- </Table>
44
- ) : null;
45
- };
46
-
47
- ProfilingPatterns.propTypes = {
48
- patterns: PropTypes.array,
49
- totalCount: PropTypes.number,
50
- };
51
-
52
- const mapStateToProps = ({ structureProfile }) => ({
53
- patterns: structureProfile?.patterns,
54
- totalCount: structureProfile?.total_count,
55
- });
56
-
57
- export default connect(mapStateToProps)(ProfilingPatterns);