@truedat/bg 7.5.0 → 7.5.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/bg",
3
- "version": "7.5.0",
3
+ "version": "7.5.2",
4
4
  "description": "Truedat Web Business Glossary",
5
5
  "sideEffects": false,
6
6
  "jsnext:main": "src/index.js",
@@ -34,7 +34,7 @@
34
34
  "@testing-library/jest-dom": "^5.16.5",
35
35
  "@testing-library/react": "^12.0.0",
36
36
  "@testing-library/user-event": "^13.2.1",
37
- "@truedat/test": "7.5.0",
37
+ "@truedat/test": "7.5.2",
38
38
  "babel-jest": "^28.1.0",
39
39
  "babel-plugin-dynamic-import-node": "^2.3.3",
40
40
  "babel-plugin-lodash": "^3.3.4",
@@ -86,9 +86,9 @@
86
86
  ]
87
87
  },
88
88
  "dependencies": {
89
- "@truedat/core": "7.5.0",
90
- "@truedat/df": "7.5.0",
91
- "@truedat/lm": "7.5.0",
89
+ "@truedat/core": "7.5.2",
90
+ "@truedat/df": "7.5.2",
91
+ "@truedat/lm": "7.5.2",
92
92
  "decode-uri-component": "^0.2.2",
93
93
  "file-saver": "^2.0.5",
94
94
  "moment": "^2.29.4",
@@ -111,5 +111,5 @@
111
111
  "react-dom": ">= 16.8.6 < 17",
112
112
  "semantic-ui-react": ">= 2.0.3 < 2.2"
113
113
  },
114
- "gitHead": "c6088400f5b3724b8b358e9c4893096005fe4e42"
114
+ "gitHead": "ad97d87e1fbf676638c24286299a661698e2271c"
115
115
  }
@@ -10,6 +10,8 @@ const API_BUSINESS_CONCEPT_VERSIONS_SEARCH =
10
10
  const API_BUSINESS_CONCEPT_VERSIONS_UPLOAD =
11
11
  "/api/business_concept_versions/upload";
12
12
  const API_CONCEPT_ARCHIVE = "/api/business_concepts/:id/versions";
13
+ const API_CONCEPT_LINKS_DOWNLOAD =
14
+ "/api/business_concept_versions/links/download";
13
15
  const API_CONCEPT_FILTERS = "/api/business_concept_filters/search";
14
16
  const API_CONCEPT_SHARED_DOMAINS = "/api/business_concepts/:id/shared_domains";
15
17
  const API_BUSINESS_CONCEPT_BULK_UPDATE =
@@ -27,6 +29,7 @@ export {
27
29
  API_BUSINESS_CONCEPT_VERSIONS_SEARCH,
28
30
  API_BUSINESS_CONCEPT_VERSIONS_UPLOAD,
29
31
  API_CONCEPT_ARCHIVE,
32
+ API_CONCEPT_LINKS_DOWNLOAD,
30
33
  API_CONCEPT_FILTERS,
31
34
  API_CONCEPT_SHARED_DOMAINS,
32
35
  API_BUSINESS_CONCEPT_BULK_UPDATE,
@@ -11,8 +11,8 @@ export const ConceptArchiveRow = ({
11
11
  business_concept_id,
12
12
  id,
13
13
  status,
14
- updated_at,
15
- last_change_by,
14
+ bcv_last_change_at,
15
+ bcv_last_change_by,
16
16
  version,
17
17
  }) => {
18
18
  const history = useHistory();
@@ -31,8 +31,8 @@ export const ConceptArchiveRow = ({
31
31
  }
32
32
  />
33
33
  <Table.Cell content={version} />
34
- <Table.Cell content={_.propOr("", "full_name")(last_change_by)} />
35
- <Table.Cell content={<DateTime value={updated_at} />} />
34
+ <Table.Cell content={_.propOr("", "full_name")(bcv_last_change_by)} />
35
+ <Table.Cell content={<DateTime value={bcv_last_change_at} />} />
36
36
  </Table.Row>
37
37
  );
38
38
  };
@@ -41,7 +41,7 @@ ConceptArchiveRow.propTypes = {
41
41
  business_concept_id: PropTypes.number,
42
42
  id: PropTypes.number,
43
43
  status: PropTypes.string,
44
- updated_at: PropTypes.string,
44
+ bcv_last_change_at: PropTypes.string,
45
45
  last_change_by: PropTypes.string,
46
46
  version: PropTypes.number,
47
47
  };
@@ -26,7 +26,14 @@ FieldValue.propTypes = {
26
26
  };
27
27
 
28
28
  export const ConceptSummary = ({
29
- concept: { status, version, last_change_at, last_change_user },
29
+ concept: {
30
+ status,
31
+ version,
32
+ last_change_at,
33
+ last_change_user,
34
+ bcv_last_change_at,
35
+ bcv_last_change_user,
36
+ },
30
37
  }) => (
31
38
  <Segment>
32
39
  <Header as="h3" dividing>
@@ -43,16 +50,41 @@ export const ConceptSummary = ({
43
50
  color={mapStatusColor[status]}
44
51
  />
45
52
  <FieldValue field="version" value={version} />
46
- <FieldValue
47
- field="last_update_at"
48
- value={
49
- <Moment locale="es" date={last_change_at} format="YYYY-MM-DD HH:mm" />
50
- }
51
- />
52
- <FieldValue
53
- field="last_update_by"
54
- value={(last_change_user && last_change_user.full_name) || ""}
55
- />
53
+ {status == "versioned" ? (
54
+ <>
55
+ <FieldValue
56
+ field="last_update_at"
57
+ value={
58
+ <Moment
59
+ locale="es"
60
+ date={bcv_last_change_at}
61
+ format="YYYY-MM-DD HH:mm"
62
+ />
63
+ }
64
+ />
65
+ <FieldValue
66
+ field="last_update_by"
67
+ value={(bcv_last_change_user && bcv_last_change_user.full_name) || ""}
68
+ />
69
+ </>
70
+ ) : (
71
+ <>
72
+ <FieldValue
73
+ field="last_update_at"
74
+ value={
75
+ <Moment
76
+ locale="es"
77
+ date={last_change_at}
78
+ format="YYYY-MM-DD HH:mm"
79
+ />
80
+ }
81
+ />
82
+ <FieldValue
83
+ field="last_update_by"
84
+ value={(last_change_user && last_change_user.full_name) || ""}
85
+ />
86
+ </>
87
+ )}
56
88
  </Segment>
57
89
  );
58
90
 
@@ -8,7 +8,7 @@ describe("<ConceptArchive />", () => {
8
8
  {
9
9
  id: 123,
10
10
  status: "status",
11
- updated_at: "2018-06-27T07:32:53.154377Z",
11
+ bcv_last_change_at: "2018-06-27T07:32:53.154377Z",
12
12
  last_change_by: "maixu",
13
13
  version: 1,
14
14
  },
@@ -7,7 +7,7 @@ describe("<ConceptArchiveRow />", () => {
7
7
  const props = {
8
8
  id: 123,
9
9
  status: "draft",
10
- last_change_at: "2018-06-27T07:32:53.154377Z",
10
+ bcv_last_change_at: "2018-06-27T07:32:53.154377Z",
11
11
  last_change_by: "maixu",
12
12
  version: 1,
13
13
  };
@@ -19,7 +19,7 @@ describe("<ConceptRow />", () => {
19
19
  id: 42,
20
20
  name: "foo",
21
21
  status: "draft",
22
- last_change_at: "2018-06-27T07:32:53.154377Z",
22
+ bcv_last_change_at: "2018-06-27T07:32:53.154377Z",
23
23
  };
24
24
  const props = { columns, concept };
25
25
  const { container } = render(
@@ -40,7 +40,7 @@ describe("<ConceptRow />", () => {
40
40
  id: 42,
41
41
  name: "foo",
42
42
  status: "draft",
43
- last_change_at: "2018-06-27T07:32:53.154377Z",
43
+ bcv_last_change_at: "2018-06-27T07:32:53.154377Z",
44
44
  };
45
45
  const props = { columns, concept };
46
46
  const wrapper = render(
@@ -0,0 +1,37 @@
1
+ import React from "react";
2
+ import { render } from "@truedat/test/render";
3
+ import { ConceptSummary } from "../ConceptSummary";
4
+
5
+ const concept = {
6
+ id: 1,
7
+ version: 1,
8
+ status: "draft",
9
+ last_change_at: "2025-01-01T10:00:00Z",
10
+ last_change_user: {
11
+ full_name: "bar",
12
+ },
13
+ bcv_last_change_at: "2024-01-01T10:00:00Z",
14
+ bcv_last_change_user: { full_name: "foo" },
15
+ };
16
+
17
+ const props = { concept };
18
+
19
+ describe("<ConceptSummary />", () => {
20
+ it("matches the latest snapshot", () => {
21
+ const { container } = render(<ConceptSummary {...props} />);
22
+ expect(container).toMatchSnapshot();
23
+ });
24
+
25
+ it("show correct change and user for versioned", () => {
26
+ const newProps = {
27
+ concept: {
28
+ ...concept,
29
+ status: "versioned",
30
+ },
31
+ };
32
+ const { queryByText } = render(<ConceptSummary {...newProps} />);
33
+ expect(queryByText(/Versioned/)).toBeInTheDocument();
34
+ expect(queryByText(/foo/)).toBeInTheDocument();
35
+ expect(queryByText(/2024-01-01/)).toBeInTheDocument();
36
+ });
37
+ });
@@ -12,8 +12,8 @@ const data = {
12
12
  name: "s1",
13
13
  description: "dd",
14
14
  version: "vs",
15
- status: "st",
16
- last_change_at: "2020-01-01T00:00:00.000Z",
15
+ status: "published",
16
+ bcv_last_change_at: "2020-01-01T00:00:00.000Z",
17
17
  },
18
18
  ],
19
19
  };
@@ -12,7 +12,7 @@ const data = {
12
12
  name: "concept",
13
13
  domain: { name: "domain" },
14
14
  status: "published",
15
- last_change_at: "2020-01-01T00:00:00.000Z",
15
+ bcv_last_change_at: "2020-01-01T00:00:00.000Z",
16
16
  },
17
17
  ],
18
18
  };
@@ -56,11 +56,11 @@ exports[`<ConceptArchive /> matches the latest snapshot 1`] = `
56
56
  as="tbody"
57
57
  >
58
58
  <ConceptArchiveRow
59
+ bcv_last_change_at="2018-06-27T07:32:53.154377Z"
59
60
  id={123}
60
61
  key="0"
61
62
  last_change_by="maixu"
62
63
  status="status"
63
- updated_at="2018-06-27T07:32:53.154377Z"
64
64
  version={1}
65
65
  />
66
66
  </TableBody>
@@ -24,7 +24,13 @@ exports[`<ConceptArchiveRow /> matches the latest snapshot 1`] = `
24
24
  </td>
25
25
  <td
26
26
  class=""
27
- />
27
+ >
28
+ <time
29
+ datetime="1530084773154"
30
+ >
31
+ 2018-06-27 07:32
32
+ </time>
33
+ </td>
28
34
  </tr>
29
35
  </tbody>
30
36
  </table>
@@ -0,0 +1,99 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`<ConceptSummary /> matches the latest snapshot 1`] = `
4
+ <div>
5
+ <div
6
+ class="ui segment"
7
+ >
8
+ <h3
9
+ class="ui dividing header"
10
+ >
11
+ Summary
12
+ </h3>
13
+ <div
14
+ class="item concept-summary"
15
+ role="listitem"
16
+ >
17
+ <div
18
+ class="content concept-summary__content"
19
+ >
20
+ <div
21
+ class="concept-summary__content-bold"
22
+ >
23
+ Status
24
+ :
25
+ </div>
26
+ <div
27
+ class="ui olive label"
28
+ >
29
+ Draft
30
+ </div>
31
+ </div>
32
+ </div>
33
+ <div
34
+ class="item concept-summary"
35
+ role="listitem"
36
+ >
37
+ <div
38
+ class="content concept-summary__content"
39
+ >
40
+ <div
41
+ class="concept-summary__content-bold"
42
+ >
43
+ Version
44
+ :
45
+ </div>
46
+ <div
47
+ class="ui label"
48
+ >
49
+ 1
50
+ </div>
51
+ </div>
52
+ </div>
53
+ <div
54
+ class="item concept-summary"
55
+ role="listitem"
56
+ >
57
+ <div
58
+ class="content concept-summary__content"
59
+ >
60
+ <div
61
+ class="concept-summary__content-bold"
62
+ >
63
+ Update
64
+ :
65
+ </div>
66
+ <div
67
+ class="ui label"
68
+ >
69
+ <time
70
+ datetime="1735725600000"
71
+ >
72
+ 2025-01-01 10:00
73
+ </time>
74
+ </div>
75
+ </div>
76
+ </div>
77
+ <div
78
+ class="item concept-summary"
79
+ role="listitem"
80
+ >
81
+ <div
82
+ class="content concept-summary__content"
83
+ >
84
+ <div
85
+ class="concept-summary__content-bold"
86
+ >
87
+ User
88
+ :
89
+ </div>
90
+ <div
91
+ class="ui label"
92
+ >
93
+ bar
94
+ </div>
95
+ </div>
96
+ </div>
97
+ </div>
98
+ </div>
99
+ `;
@@ -1,13 +1,24 @@
1
1
  import useSWR from "swr";
2
2
  import useSWRMutations from "swr/mutation";
3
- import { apiJson, apiJsonPost } from "@truedat/core/services/api";
3
+ import FileSaver from "file-saver";
4
+ import { apiJson, apiJsonPost, JSON_OPTS } from "@truedat/core/services/api";
4
5
 
5
6
  import {
6
7
  API_CONCEPT_FILTERS,
8
+ API_CONCEPT_LINKS_DOWNLOAD,
7
9
  API_BUSINESS_CONCEPT_VERSIONS_SEARCH,
8
10
  API_BUSINESS_CONCEPT_VERSIONS_ACTIONS,
9
11
  } from "../api";
10
12
 
13
+ function saveFile({ data, headers }) {
14
+ const contentDisposition = headers["content-disposition"];
15
+ const regex = /filename=(.+)$/;
16
+ const match = regex.exec(contentDisposition);
17
+ const fileName = match ? match[1] : "links.xlsx";
18
+
19
+ FileSaver.saveAs(data, fileName);
20
+ }
21
+
11
22
  export const useConceptFilters = () => {
12
23
  return useSWRMutations(API_CONCEPT_FILTERS, (url, { arg }) =>
13
24
  apiJsonPost(url, arg)
@@ -32,3 +43,13 @@ export const useConceptVersionsActions = () => {
32
43
  mutate,
33
44
  };
34
45
  };
46
+
47
+ export const useConceptLinksDownload = () => {
48
+ return useSWRMutations(API_CONCEPT_LINKS_DOWNLOAD, (url, { arg }) => {
49
+ return apiJsonPost(url, arg, { ...JSON_OPTS, responseType: "blob" }).then(
50
+ ({ data, headers }) => {
51
+ saveFile({ data, headers });
52
+ }
53
+ );
54
+ });
55
+ };
@@ -21,8 +21,8 @@ describe("reducers: conceptArchive", () => {
21
21
  {
22
22
  id: 123,
23
23
  status: "status",
24
- updated_at: "2018-06-27T07:32:53.154377Z",
25
- last_change_by: "maixu",
24
+ bcv_last_change_at: "2018-06-27T07:32:53.154377Z",
25
+ bcv_last_change_by: "maixu",
26
26
  version: 1,
27
27
  },
28
28
  ];
@@ -25,6 +25,8 @@ const pickFields = _.pick([
25
25
  "last_change_at",
26
26
  "last_change_by",
27
27
  "last_change_user",
28
+ "bcv_last_change_user",
29
+ "bcv_last_change_at",
28
30
  "graphs",
29
31
  "completeness",
30
32
  "in_progress",
@@ -6,8 +6,8 @@ const initialState = [];
6
6
  const pickFields = _.pick([
7
7
  "id",
8
8
  "business_concept_id",
9
- "updated_at",
10
- "last_change_by",
9
+ "bcv_last_change_at",
10
+ "bcv_last_change_by",
11
11
  "status",
12
12
  "version",
13
13
  ]);
@@ -2,8 +2,15 @@ import _ from "lodash/fp";
2
2
  import React from "react";
3
3
  import PropTypes from "prop-types";
4
4
  import { connect } from "react-redux";
5
- import { Table, Message, Label, Icon, Segment } from "semantic-ui-react";
6
- import { FormattedMessage } from "react-intl";
5
+ import {
6
+ Button,
7
+ Table,
8
+ Message,
9
+ Label,
10
+ Icon,
11
+ Segment,
12
+ } from "semantic-ui-react";
13
+ import { FormattedMessage, useIntl } from "react-intl";
7
14
  import SearchWidget from "@truedat/core/search/SearchWidget";
8
15
  import {
9
16
  SearchContextProvider,
@@ -14,6 +21,7 @@ import { mapStatusColor } from "../../constants/mappings";
14
21
  import { translations } from "../../utils/filterOptions";
15
22
 
16
23
  import {
24
+ useConceptLinksDownload,
17
25
  useConceptVersionsSearch,
18
26
  useConceptFilters,
19
27
  } from "../../hooks/useConcepts";
@@ -78,8 +86,12 @@ export function ConceptSelectorContent({
78
86
  showTitle = true,
79
87
  links,
80
88
  }) {
81
- const { searchData } = useSearchContext();
89
+ const { searchData, filterParams: searchParams } = useSearchContext();
90
+ const { trigger: triggerDownload, isMutating: downloading } =
91
+ useConceptLinksDownload();
92
+ const { formatMessage } = useIntl();
82
93
  const concepts = searchData?.data;
94
+ const conceptsActions = _.propOr({}, "_actions")(searchData);
83
95
 
84
96
  const selectedConceptIsFiltered = !_.reduce(
85
97
  (acc, c) => (selectedConcept && c.id == selectedConcept.id) || acc,
@@ -103,6 +115,18 @@ export function ConceptSelectorContent({
103
115
  </label>
104
116
  )}
105
117
  <Segment>
118
+ {conceptsActions?.downloadLinks && (
119
+ <Button
120
+ icon="download"
121
+ floated="right"
122
+ secondary
123
+ loading={downloading}
124
+ onClick={() => triggerDownload(searchParams)}
125
+ data-tooltip={formatMessage({
126
+ id: "concepts.actions.downloadLinks.tooltip",
127
+ })}
128
+ />
129
+ )}
106
130
  <SearchWidget />
107
131
  {!_.isEmpty(concepts) || selectedConcept ? (
108
132
  <Table selectable size="small">
@@ -25,6 +25,7 @@ const data = {
25
25
  last_change_at: "2020-01-01T00:00:00.000Z",
26
26
  },
27
27
  ],
28
+ _actions: { downloadLinks: {} },
28
29
  };
29
30
 
30
31
  const filterData = {
@@ -91,6 +92,11 @@ describe("<ConceptSelector />", () => {
91
92
  await waitFor(() => {
92
93
  expect(container.querySelector(".loading")).toBeNull();
93
94
  });
95
+ expect(
96
+ container.querySelector(
97
+ 'button[data-tooltip="concepts.actions.downloadLinks.tooltip"]'
98
+ )
99
+ ).toBeInTheDocument();
94
100
  expect(container).toMatchSnapshot();
95
101
  });
96
102
 
@@ -8,6 +8,15 @@ exports[`<ConceptSelector /> matches the latest snapshot 1`] = `
8
8
  <div
9
9
  class="ui segment"
10
10
  >
11
+ <button
12
+ class="ui icon secondary right floated button"
13
+ data-tooltip="concepts.actions.downloadLinks.tooltip"
14
+ >
15
+ <i
16
+ aria-hidden="true"
17
+ class="download icon"
18
+ />
19
+ </button>
11
20
  <div
12
21
  class="ui action left icon input"
13
22
  >
@@ -17,7 +17,7 @@ const iconDecorator = (field) =>
17
17
 
18
18
  const translateDecorator = (text) => <FormattedMessage id={text} />;
19
19
 
20
- const dateDecorator = (date) => (
20
+ const dateDecorator = ({ date }) => (
21
21
  <Moment locale="es" date={date} format="YYYY-MM-DD HH:mm" />
22
22
  );
23
23
 
@@ -57,7 +57,10 @@ export const defaultConceptColumns = [
57
57
  },
58
58
  {
59
59
  name: "last_change_at",
60
- sort: { name: "last_change_at" },
60
+ sort: { name: "bcv_last_change_at" },
61
+ fieldSelector: ({ bcv_last_change_at }) => ({
62
+ date: bcv_last_change_at,
63
+ }),
61
64
  fieldDecorator: dateDecorator,
62
65
  textAlign: "center",
63
66
  width: 2,