@truedat/lm 6.15.2 → 6.16.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@truedat/lm",
3
- "version": "6.15.2",
3
+ "version": "6.16.3",
4
4
  "description": "Truedat Link Manager",
5
5
  "sideEffects": false,
6
6
  "jsnext:main": "src/index.js",
@@ -107,5 +107,5 @@
107
107
  "react-dom": ">= 16.8.6 < 17",
108
108
  "semantic-ui-react": ">= 2.0.3 < 2.2"
109
109
  },
110
- "gitHead": "15b38541393160ff92c8ecf96814c3218786a461"
110
+ "gitHead": "9ac7bd2ddab3f16be28269b3203e568c269cbd0e"
111
111
  }
@@ -1,52 +1,79 @@
1
1
  import React from "react";
2
2
  import PropTypes from "prop-types";
3
3
  import { connect } from "react-redux";
4
- import { Button, Card } from "semantic-ui-react";
5
- import { FormattedMessage } from "react-intl";
4
+ import { Button, Card, Checkbox } from "semantic-ui-react";
5
+ import { FormattedMessage, useIntl } from "react-intl";
6
6
  import { ConfirmModal } from "@truedat/core/components";
7
- import { deleteRelationTag } from "../routines";
7
+ import { deleteRelationTag, updateRelationTag } from "../routines";
8
8
 
9
9
  export const RelationTagCards = ({
10
10
  deleteRelationTag,
11
+ updateRelationTag,
11
12
  relationTags,
12
13
  relationTagsLoading,
13
14
  }) => {
15
+ const { formatMessage } = useIntl();
16
+
14
17
  if (relationTagsLoading) return <div />;
15
18
 
16
19
  return (
17
20
  <>
18
21
  <Card.Group>
19
- {relationTags.map((tag, i) => (
20
- <Card key={i}>
21
- <Card.Content>
22
- <Card.Header>
23
- <FormattedMessage
24
- id={`${"source"}.${tag.value.type}`}
25
- defaultMessage={tag.value.type}
26
- />
27
- </Card.Header>
28
- <Card.Description>{tag.value.target_type}</Card.Description>
29
- </Card.Content>
30
- <Card.Content extra>
31
- <div className="ui actions">
32
- <ConfirmModal
33
- icon="trash"
34
- trigger={<Button icon="trash" basic color="red" />}
35
- header={
36
- <FormattedMessage id="relationTag.actions.delete.confirmation.header" />
37
- }
38
- content={
39
- <FormattedMessage
40
- id="relationTag.actions.delete.confirmation.content"
41
- values={{ type: <i>{tag.value.type}</i> }}
22
+ {relationTags.map((tag, i) => {
23
+ const ref = React.createRef(); // Crea una referencia para el checkbox
24
+ return (
25
+ <Card key={i}>
26
+ <Card.Content>
27
+ <Card.Header>
28
+ <FormattedMessage
29
+ id={`${"source"}.${tag.value.type}`}
30
+ defaultMessage={tag.value.type}
31
+ />
32
+ </Card.Header>
33
+ <Card.Description>{tag.value.target_type}</Card.Description>
34
+ {tag.value.target_type == "business_concept" ? (
35
+ <Card.Meta>
36
+ <Checkbox
37
+ toggle
38
+ ref={ref}
39
+ label={formatMessage({
40
+ id: "relationTags.props.expandable",
41
+ })}
42
+ defaultChecked={tag.value.expandable}
43
+ onChange={(_e, { checked }) =>
44
+ updateRelationTag({
45
+ ...tag,
46
+ value: {
47
+ ...tag.value,
48
+ expandable: checked,
49
+ },
50
+ })
51
+ }
42
52
  />
43
- }
44
- onConfirm={() => deleteRelationTag({ id: tag.id })}
45
- />
46
- </div>
47
- </Card.Content>
48
- </Card>
49
- ))}
53
+ </Card.Meta>
54
+ ) : null}
55
+ </Card.Content>
56
+ <Card.Content extra>
57
+ <div className="ui actions">
58
+ <ConfirmModal
59
+ icon="trash"
60
+ trigger={<Button icon="trash" basic color="red" />}
61
+ header={
62
+ <FormattedMessage id="relationTag.actions.delete.confirmation.header" />
63
+ }
64
+ content={
65
+ <FormattedMessage
66
+ id="relationTag.actions.delete.confirmation.content"
67
+ values={{ type: <i>{tag.value.type}</i> }}
68
+ />
69
+ }
70
+ onConfirm={() => deleteRelationTag({ id: tag.id })}
71
+ />
72
+ </div>
73
+ </Card.Content>
74
+ </Card>
75
+ );
76
+ })}
50
77
  </Card.Group>
51
78
  </>
52
79
  );
@@ -54,6 +81,9 @@ export const RelationTagCards = ({
54
81
 
55
82
  RelationTagCards.propTypes = {
56
83
  relationTags: PropTypes.array,
84
+ deleteRelationTag: PropTypes.func,
85
+ updateRelationTag: PropTypes.func,
86
+ relationTagsLoading: PropTypes.bool,
57
87
  };
58
88
 
59
89
  const mapStateToProps = ({ relationTags, relationTagsLoading }) => ({
@@ -61,6 +91,7 @@ const mapStateToProps = ({ relationTags, relationTagsLoading }) => ({
61
91
  relationTagsLoading,
62
92
  });
63
93
 
64
- export default connect(mapStateToProps, { deleteRelationTag })(
65
- RelationTagCards
66
- );
94
+ export default connect(mapStateToProps, {
95
+ deleteRelationTag,
96
+ updateRelationTag,
97
+ })(RelationTagCards);
@@ -8,11 +8,12 @@ import { HistoryBackButton } from "@truedat/core/components";
8
8
 
9
9
  export const RelationTagForm = ({ relationTag, isSubmitting, onSubmit }) => {
10
10
  const { formatMessage } = useIntl();
11
- const { handleSubmit, control, formState } = useForm({
11
+ const { handleSubmit, control, formState, watch } = useForm({
12
12
  mode: "all",
13
13
  defaultValues: {
14
14
  type: "",
15
15
  target_type: "",
16
+ expandable: false,
16
17
  ...relationTag,
17
18
  },
18
19
  });
@@ -32,6 +33,7 @@ export const RelationTagForm = ({ relationTag, isSubmitting, onSubmit }) => {
32
33
  text: formatMessage({ id: "target_type.data_field" }),
33
34
  },
34
35
  ];
36
+ const currentTargetType = watch("target_type");
35
37
  return (
36
38
  <Form onSubmit={handleSubmit(onSubmit)}>
37
39
  <Controller
@@ -72,26 +74,54 @@ export const RelationTagForm = ({ relationTag, isSubmitting, onSubmit }) => {
72
74
  ),
73
75
  }}
74
76
  render={({ field: { onBlur, onChange, value } }) => (
75
- <Form.Dropdown
76
- id="target_type"
77
- autoComplete="off"
78
- error={errors.target_type?.message}
79
- label={{
80
- children: formatMessage({ id: "relationTags.props.target_type" }),
81
- htmlFor: "target_type",
82
- }}
83
- onBlur={onBlur}
84
- onChange={(_e, { value }) => onChange(value)}
85
- placeholder={formatMessage({
86
- id: "relationTags.props.target_type.placeholder",
87
- })}
88
- value={value || ""}
89
- selection
90
- options={targetTypeOptions}
91
- required
92
- />
77
+ <>
78
+ <Form.Dropdown
79
+ id="target_type"
80
+ autoComplete="off"
81
+ error={errors.target_type?.message}
82
+ label={{
83
+ children: formatMessage({
84
+ id: "relationTags.props.target_type",
85
+ }),
86
+ htmlFor: "target_type",
87
+ }}
88
+ onBlur={onBlur}
89
+ onChange={(_e, { value }) => onChange(value)}
90
+ placeholder={formatMessage({
91
+ id: "relationTags.props.target_type.placeholder",
92
+ })}
93
+ value={value}
94
+ selection
95
+ options={targetTypeOptions}
96
+ required
97
+ />
98
+ </>
93
99
  )}
94
100
  />
101
+ {currentTargetType == "business_concept" ? (
102
+ <Controller
103
+ control={control}
104
+ name="expandable"
105
+ render={({ field: { onBlur, onChange, value } }) => (
106
+ <Form.Field>
107
+ <Form.Checkbox
108
+ id="expandable"
109
+ toggle
110
+ onBlur={onBlur}
111
+ label={{
112
+ htmlFor: "expandable",
113
+ children: formatMessage({
114
+ id: "relationTags.props.expandable",
115
+ }),
116
+ }}
117
+ checked={value}
118
+ onChange={(_e, { checked }) => onChange(checked)}
119
+ />
120
+ </Form.Field>
121
+ )}
122
+ />
123
+ ) : null}
124
+
95
125
  <div className="actions">
96
126
  <Button
97
127
  content={formatMessage({ id: "actions.create" })}
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
- import { shallow } from "enzyme";
2
+ import { render } from "@truedat/test/render";
3
3
  import { RelationTagCards } from "../RelationTagCards";
4
4
 
5
5
  describe("<RelationTagCards />", () => {
@@ -7,10 +7,11 @@ describe("<RelationTagCards />", () => {
7
7
  const relationTags = [
8
8
  { id: 1, value: { type: "tag1", target_type: "business_concept" } },
9
9
  { id: 2, value: { type: "tag2", target_type: "data_field" } },
10
- { id: 3, value: { type: "tag3", target_type: "ingest" } }
10
+ { id: 3, value: { type: "tag3", target_type: "ingest" } },
11
11
  ];
12
12
  const props = { relationTags };
13
- const wrapper = shallow(<RelationTagCards {...props} />);
14
- expect(wrapper).toMatchSnapshot();
13
+
14
+ const { container } = render(<RelationTagCards {...props} />);
15
+ expect(container).toMatchSnapshot();
15
16
  });
16
17
  });
@@ -49,6 +49,12 @@ describe("<RelationTagForm />", () => {
49
49
  userEvent.click(await findByText("target"));
50
50
  userEvent.click(await findByRole("option", { name: "concept" }));
51
51
 
52
+ //expandable
53
+ const expandableCheckbox = await findByRole("checkbox", {
54
+ name: /expandable/,
55
+ });
56
+ userEvent.click(expandableCheckbox);
57
+
52
58
  // Submit button should now be enabled
53
59
  await waitFor(() =>
54
60
  expect(getByRole("button", { name: /create/ })).not.toBeDisabled()
@@ -61,6 +67,7 @@ describe("<RelationTagForm />", () => {
61
67
  expect(onSubmit).toHaveBeenCalledWith({
62
68
  type: "foo",
63
69
  target_type: "business_concept",
70
+ expandable: true,
64
71
  })
65
72
  );
66
73
  });
@@ -1,164 +1,130 @@
1
1
  // Jest Snapshot v1, https://goo.gl/fbAQLP
2
2
 
3
3
  exports[`<RelationTagCards /> matches the latest snapshot 1`] = `
4
- <Fragment>
5
- <CardGroup>
6
- <Card
7
- key="0"
4
+ <div>
5
+ <div
6
+ class="ui cards"
7
+ >
8
+ <div
9
+ class="ui card"
8
10
  >
9
- <CardContent>
10
- <CardHeader>
11
- <MemoizedFormattedMessage
12
- defaultMessage="tag1"
13
- id="source.tag1"
14
- />
15
- </CardHeader>
16
- <CardDescription>
11
+ <div
12
+ class="content"
13
+ >
14
+ <div
15
+ class="header"
16
+ >
17
+ tag1
18
+ </div>
19
+ <div
20
+ class="description"
21
+ >
17
22
  business_concept
18
- </CardDescription>
19
- </CardContent>
20
- <CardContent
21
- extra={true}
23
+ </div>
24
+ <div
25
+ class="meta"
26
+ >
27
+ <div
28
+ class="ui toggle checkbox"
29
+ >
30
+ <input
31
+ class="hidden"
32
+ readonly=""
33
+ tabindex="0"
34
+ type="checkbox"
35
+ value=""
36
+ />
37
+ <label>
38
+ relationTags.props.expandable
39
+ </label>
40
+ </div>
41
+ </div>
42
+ </div>
43
+ <div
44
+ class="extra content"
22
45
  >
23
46
  <div
24
- className="ui actions"
47
+ class="ui actions"
25
48
  >
26
- <ConfirmModal
27
- content={
28
- <Memo(MemoizedFormattedMessage)
29
- id="relationTag.actions.delete.confirmation.content"
30
- values={
31
- {
32
- "type": <i>
33
- tag1
34
- </i>,
35
- }
36
- }
37
- />
38
- }
39
- header={
40
- <Memo(MemoizedFormattedMessage)
41
- id="relationTag.actions.delete.confirmation.header"
42
- />
43
- }
44
- icon="trash"
45
- onConfirm={[Function]}
46
- trigger={
47
- <Button
48
- as="button"
49
- basic={true}
50
- color="red"
51
- icon="trash"
52
- />
53
- }
54
- />
49
+ <button
50
+ class="ui red basic icon button"
51
+ >
52
+ <i
53
+ aria-hidden="true"
54
+ class="trash icon"
55
+ />
56
+ </button>
55
57
  </div>
56
- </CardContent>
57
- </Card>
58
- <Card
59
- key="1"
58
+ </div>
59
+ </div>
60
+ <div
61
+ class="ui card"
60
62
  >
61
- <CardContent>
62
- <CardHeader>
63
- <MemoizedFormattedMessage
64
- defaultMessage="tag2"
65
- id="source.tag2"
66
- />
67
- </CardHeader>
68
- <CardDescription>
63
+ <div
64
+ class="content"
65
+ >
66
+ <div
67
+ class="header"
68
+ >
69
+ tag2
70
+ </div>
71
+ <div
72
+ class="description"
73
+ >
69
74
  data_field
70
- </CardDescription>
71
- </CardContent>
72
- <CardContent
73
- extra={true}
75
+ </div>
76
+ </div>
77
+ <div
78
+ class="extra content"
74
79
  >
75
80
  <div
76
- className="ui actions"
81
+ class="ui actions"
77
82
  >
78
- <ConfirmModal
79
- content={
80
- <Memo(MemoizedFormattedMessage)
81
- id="relationTag.actions.delete.confirmation.content"
82
- values={
83
- {
84
- "type": <i>
85
- tag2
86
- </i>,
87
- }
88
- }
89
- />
90
- }
91
- header={
92
- <Memo(MemoizedFormattedMessage)
93
- id="relationTag.actions.delete.confirmation.header"
94
- />
95
- }
96
- icon="trash"
97
- onConfirm={[Function]}
98
- trigger={
99
- <Button
100
- as="button"
101
- basic={true}
102
- color="red"
103
- icon="trash"
104
- />
105
- }
106
- />
83
+ <button
84
+ class="ui red basic icon button"
85
+ >
86
+ <i
87
+ aria-hidden="true"
88
+ class="trash icon"
89
+ />
90
+ </button>
107
91
  </div>
108
- </CardContent>
109
- </Card>
110
- <Card
111
- key="2"
92
+ </div>
93
+ </div>
94
+ <div
95
+ class="ui card"
112
96
  >
113
- <CardContent>
114
- <CardHeader>
115
- <MemoizedFormattedMessage
116
- defaultMessage="tag3"
117
- id="source.tag3"
118
- />
119
- </CardHeader>
120
- <CardDescription>
97
+ <div
98
+ class="content"
99
+ >
100
+ <div
101
+ class="header"
102
+ >
103
+ tag3
104
+ </div>
105
+ <div
106
+ class="description"
107
+ >
121
108
  ingest
122
- </CardDescription>
123
- </CardContent>
124
- <CardContent
125
- extra={true}
109
+ </div>
110
+ </div>
111
+ <div
112
+ class="extra content"
126
113
  >
127
114
  <div
128
- className="ui actions"
115
+ class="ui actions"
129
116
  >
130
- <ConfirmModal
131
- content={
132
- <Memo(MemoizedFormattedMessage)
133
- id="relationTag.actions.delete.confirmation.content"
134
- values={
135
- {
136
- "type": <i>
137
- tag3
138
- </i>,
139
- }
140
- }
141
- />
142
- }
143
- header={
144
- <Memo(MemoizedFormattedMessage)
145
- id="relationTag.actions.delete.confirmation.header"
146
- />
147
- }
148
- icon="trash"
149
- onConfirm={[Function]}
150
- trigger={
151
- <Button
152
- as="button"
153
- basic={true}
154
- color="red"
155
- icon="trash"
156
- />
157
- }
158
- />
117
+ <button
118
+ class="ui red basic icon button"
119
+ >
120
+ <i
121
+ aria-hidden="true"
122
+ class="trash icon"
123
+ />
124
+ </button>
159
125
  </div>
160
- </CardContent>
161
- </Card>
162
- </CardGroup>
163
- </Fragment>
126
+ </div>
127
+ </div>
128
+ </div>
129
+ </div>
164
130
  `;
@@ -49,6 +49,24 @@ exports[`<RelationTags /> matches the latest snapshot 1`] = `
49
49
  >
50
50
  business_concept
51
51
  </div>
52
+ <div
53
+ class="meta"
54
+ >
55
+ <div
56
+ class="ui toggle checkbox"
57
+ >
58
+ <input
59
+ class="hidden"
60
+ readonly=""
61
+ tabindex="0"
62
+ type="checkbox"
63
+ value=""
64
+ />
65
+ <label>
66
+ relationTags.props.expandable
67
+ </label>
68
+ </div>
69
+ </div>
52
70
  </div>
53
71
  <div
54
72
  class="extra content"
@@ -0,0 +1,10 @@
1
+ import _ from "lodash/fp";
2
+ import { compile } from "path-to-regexp";
3
+ import useSWRMutations from "swr/mutation";
4
+ import { apiJsonPatch } from "@truedat/core/services/api";
5
+ import { API_TAG } from "../api";
6
+
7
+ export const useTagUpdate = (id) => {
8
+ const url = compile(API_TAG)({ id });
9
+ return useSWRMutations(url, (url, { arg }) => apiJsonPatch(url, arg));
10
+ };
package/src/routines.js CHANGED
@@ -17,6 +17,7 @@ export const clearSelectedRelationTags = createRoutine(
17
17
  export const clearStructures = createRoutine("CLEAR_STRUCTURES");
18
18
 
19
19
  export const createRelationTag = createRoutine("CREATE_RELATION_TAG");
20
+ export const updateRelationTag = createRoutine("UPDATE_RELATION_TAG");
20
21
  export const deleteRelationTag = createRoutine("DELETE_RELATION_TAG");
21
22
 
22
23
  // Redefined here to remove dependency on bg
@@ -12,7 +12,7 @@ export function* createRelationSaga({ payload }) {
12
12
  "source_type",
13
13
  "target_id",
14
14
  "target_type",
15
- "tag_ids"
15
+ "tag_ids",
16
16
  ])(payload);
17
17
 
18
18
  const redirectUrl = _.prop("redirectUrl")(payload);
@@ -7,11 +7,15 @@ import { API_TAGS } from "../api";
7
7
  export function* createRelationTagSaga({ payload }) {
8
8
  try {
9
9
  const { relationTag } = payload;
10
- const relationTagValue = _.pick(["type", "target_type"])(relationTag);
10
+ const relationTagValue = _.pick(["type", "target_type", "expandable"])(
11
+ relationTag
12
+ );
11
13
 
12
14
  const redirectUrl = _.prop("redirectUrl")(payload);
13
15
  const meta = { redirectUrl };
14
- const requestData = { tag: { value: relationTagValue } };
16
+ const requestData = {
17
+ tag: { value: relationTagValue },
18
+ };
15
19
 
16
20
  yield put({ meta, ...createRelationTag.request() });
17
21
  const { data } = yield call(apiJsonPost, API_TAGS, requestData, JSON_OPTS);
@@ -5,6 +5,7 @@ import { createRelationRequestSaga } from "./createRelation";
5
5
  import { deleteRelationRequestSaga } from "./deleteRelation";
6
6
  import { deleteRelationTagRequestSaga } from "./deleteRelationTag";
7
7
  import { createRelationTagRequestSaga } from "./createRelationTag";
8
+ import { updateRelationTagRequestSaga } from "./updateRelationTag";
8
9
 
9
10
  export {
10
11
  fetchRelationTagsRequestSaga,
@@ -13,7 +14,8 @@ export {
13
14
  createRelationRequestSaga,
14
15
  deleteRelationRequestSaga,
15
16
  deleteRelationTagRequestSaga,
16
- createRelationTagRequestSaga
17
+ createRelationTagRequestSaga,
18
+ updateRelationTagRequestSaga,
17
19
  };
18
20
 
19
21
  export default [
@@ -23,5 +25,6 @@ export default [
23
25
  createRelationRequestSaga(),
24
26
  deleteRelationRequestSaga(),
25
27
  deleteRelationTagRequestSaga(),
26
- createRelationTagRequestSaga()
28
+ createRelationTagRequestSaga(),
29
+ updateRelationTagRequestSaga(),
27
30
  ];
@@ -0,0 +1,37 @@
1
+ import _ from "lodash/fp";
2
+ import { compile } from "path-to-regexp";
3
+ import { call, put, takeLatest } from "redux-saga/effects";
4
+ import { apiJsonPatch, JSON_OPTS } from "@truedat/core/services/api";
5
+ import { updateRelationTag } from "../routines";
6
+ import { API_TAG } from "../api";
7
+
8
+ export function* updateRelationTagSaga({ payload }) {
9
+ try {
10
+ const relationTagValue = _.pick(["type", "target_type", "expandable"])(
11
+ payload.value
12
+ );
13
+
14
+ const url = compile(API_TAG)(payload);
15
+
16
+ const requestData = {
17
+ tag: { value: relationTagValue },
18
+ };
19
+
20
+ yield put(updateRelationTag.request());
21
+ const { data } = yield call(apiJsonPatch, url, requestData, JSON_OPTS);
22
+ yield put(updateRelationTag.success(data));
23
+ } catch (error) {
24
+ if (error.response) {
25
+ const { status, data } = error.response;
26
+ yield put(updateRelationTag.failure({ status, data }));
27
+ } else {
28
+ yield put(updateRelationTag.failure(error.message));
29
+ }
30
+ } finally {
31
+ yield put(updateRelationTag.fulfill());
32
+ }
33
+ }
34
+
35
+ export function* updateRelationTagRequestSaga() {
36
+ yield takeLatest(updateRelationTag.TRIGGER, updateRelationTagSaga);
37
+ }