@truedat/cx 4.38.1 → 4.38.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/CHANGELOG.md +6 -0
- package/package.json +4 -4
- package/src/messages/en.js +1 -0
- package/src/messages/es.js +1 -0
- package/src/sources/components/Source.js +40 -5
- package/src/sources/components/__tests__/EditSource.spec.js +1 -1
- package/src/sources/components/__tests__/__snapshots__/Source.spec.js.snap +7 -2
- package/src/sources/reducers/__tests__/sourceUpdateStatus.spec.js +40 -0
- package/src/sources/reducers/index.js +9 -1
- package/src/sources/reducers/source.js +4 -1
- package/src/sources/reducers/sourceUpdateStatus.js +18 -0
- package/src/sources/routines.js +1 -0
- package/src/sources/sagas/__tests__/updateSourceConfig.spec.js +73 -0
- package/src/sources/sagas/index.js +3 -0
- package/src/sources/sagas/updateSourceConfig.js +29 -0
package/CHANGELOG.md
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@truedat/cx",
|
|
3
|
-
"version": "4.38.
|
|
3
|
+
"version": "4.38.2",
|
|
4
4
|
"description": "Truedat Web Connectors",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"jsnext:main": "src/index.js",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"@babel/plugin-transform-modules-commonjs": "^7.15.0",
|
|
32
32
|
"@babel/preset-env": "^7.15.0",
|
|
33
33
|
"@babel/preset-react": "^7.14.5",
|
|
34
|
-
"@truedat/test": "4.38.
|
|
34
|
+
"@truedat/test": "4.38.2",
|
|
35
35
|
"babel-jest": "^27.0.6",
|
|
36
36
|
"babel-plugin-dynamic-import-node": "^2.3.3",
|
|
37
37
|
"babel-plugin-lodash": "^3.3.4",
|
|
@@ -85,7 +85,7 @@
|
|
|
85
85
|
]
|
|
86
86
|
},
|
|
87
87
|
"dependencies": {
|
|
88
|
-
"@truedat/core": "4.38.
|
|
88
|
+
"@truedat/core": "4.38.2",
|
|
89
89
|
"lodash": "^4.17.21",
|
|
90
90
|
"match-sorter": "^6.3.1",
|
|
91
91
|
"path-to-regexp": "^1.7.0",
|
|
@@ -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": "
|
|
106
|
+
"gitHead": "41504c0c5ccc40ea20e67985e3957fd7c1897e2e"
|
|
107
107
|
}
|
package/src/messages/en.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
export default {
|
|
3
3
|
"alert.fetchSource.failed.header": "Error retrieving source",
|
|
4
4
|
"alert.signConfiguration.failed.header": "Error signing configuration",
|
|
5
|
+
"alert.updateSource.failed.header": "Error editing source",
|
|
5
6
|
"configuration.content.label": "Content",
|
|
6
7
|
"configuration.props.external_id": "Id Externo",
|
|
7
8
|
"configuration.search.no_results": "No configurations found",
|
package/src/messages/es.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
export default {
|
|
3
3
|
"alert.fetchSource.failed.header": "Error al recuperar origen",
|
|
4
4
|
"alert.signConfiguration.failed.header": "Error firmando configuración",
|
|
5
|
+
"alert.updateSource.failed.header": "Error al editar origen",
|
|
5
6
|
"configuration.content.label": "Contenido",
|
|
6
7
|
"configuration.props.external_id": "External Id",
|
|
7
8
|
"configuration.search.no_results": "Ninguna configuración encontrada",
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import _ from "lodash/fp";
|
|
2
|
-
import React from "react";
|
|
2
|
+
import React, { useState, useEffect } from "react";
|
|
3
3
|
import PropTypes from "prop-types";
|
|
4
4
|
import { Header, Icon, Grid, Segment } from "semantic-ui-react";
|
|
5
5
|
import { connect } from "react-redux";
|
|
6
|
+
import { updateSourceConfig } from "../routines";
|
|
6
7
|
import SourceActions from "./SourceActions";
|
|
7
8
|
import SourceBreadcrumbs from "./SourceBreadcrumbs";
|
|
8
9
|
|
|
@@ -10,7 +11,34 @@ const DynamicFormViewer = React.lazy(() =>
|
|
|
10
11
|
import("@truedat/df/components/DynamicFormViewer")
|
|
11
12
|
);
|
|
12
13
|
|
|
13
|
-
export const Source = ({
|
|
14
|
+
export const Source = ({
|
|
15
|
+
source,
|
|
16
|
+
template,
|
|
17
|
+
updateSourceConfig,
|
|
18
|
+
sourceUpdateStatus,
|
|
19
|
+
}) => {
|
|
20
|
+
const [editingField, setEditingField] = useState();
|
|
21
|
+
const [sourceConfig, setSourceConfig] = useState();
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
if (source) {
|
|
24
|
+
setSourceConfig(source?.config);
|
|
25
|
+
}
|
|
26
|
+
}, [source]);
|
|
27
|
+
const editFunctions = {
|
|
28
|
+
onChange: (e, { name, value }) => {
|
|
29
|
+
e && e.preventDefault();
|
|
30
|
+
setSourceConfig({ ...sourceConfig, [name]: value });
|
|
31
|
+
},
|
|
32
|
+
onCancel: () => setSourceConfig(source?.config),
|
|
33
|
+
onSubmit: (field) =>
|
|
34
|
+
updateSourceConfig({
|
|
35
|
+
source: { ...source, config: _.pick(field)(sourceConfig) },
|
|
36
|
+
}),
|
|
37
|
+
editingField,
|
|
38
|
+
setEditingField,
|
|
39
|
+
updateStatus: sourceUpdateStatus,
|
|
40
|
+
};
|
|
41
|
+
|
|
14
42
|
return _.isEmpty(source) ? null : (
|
|
15
43
|
<>
|
|
16
44
|
<SourceBreadcrumbs text={source.external_id} />
|
|
@@ -29,7 +57,11 @@ export const Source = ({ source, template }) => {
|
|
|
29
57
|
<SourceActions />
|
|
30
58
|
</Grid.Column>
|
|
31
59
|
<Grid.Column width={8}>
|
|
32
|
-
<DynamicFormViewer
|
|
60
|
+
<DynamicFormViewer
|
|
61
|
+
template={template}
|
|
62
|
+
content={sourceConfig}
|
|
63
|
+
editFunctions={editFunctions}
|
|
64
|
+
/>
|
|
33
65
|
</Grid.Column>
|
|
34
66
|
</Grid>
|
|
35
67
|
</Segment>
|
|
@@ -39,12 +71,15 @@ export const Source = ({ source, template }) => {
|
|
|
39
71
|
|
|
40
72
|
Source.propTypes = {
|
|
41
73
|
source: PropTypes.object.isRequired,
|
|
74
|
+
sourceUpdateStatus: PropTypes.string,
|
|
42
75
|
template: PropTypes.object,
|
|
76
|
+
updateSourceConfig: PropTypes.func.isRequired,
|
|
43
77
|
};
|
|
44
78
|
|
|
45
|
-
const mapStateToProps = ({ source, templates }) => ({
|
|
79
|
+
const mapStateToProps = ({ source, templates, sourceUpdateStatus }) => ({
|
|
46
80
|
source,
|
|
47
81
|
template: _.find(_.propEq("name", source.type))(templates),
|
|
82
|
+
sourceUpdateStatus,
|
|
48
83
|
});
|
|
49
84
|
|
|
50
|
-
export default connect(mapStateToProps)(Source);
|
|
85
|
+
export default connect(mapStateToProps, { updateSourceConfig })(Source);
|
|
@@ -36,9 +36,14 @@ exports[`<Source /> matches the latest snapshot 1`] = `
|
|
|
36
36
|
width={8}
|
|
37
37
|
>
|
|
38
38
|
<lazy
|
|
39
|
-
|
|
39
|
+
editFunctions={
|
|
40
40
|
Object {
|
|
41
|
-
"
|
|
41
|
+
"editingField": undefined,
|
|
42
|
+
"onCancel": [Function],
|
|
43
|
+
"onChange": [Function],
|
|
44
|
+
"onSubmit": [Function],
|
|
45
|
+
"setEditingField": [Function],
|
|
46
|
+
"updateStatus": undefined,
|
|
42
47
|
}
|
|
43
48
|
}
|
|
44
49
|
template={
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { updateSourceConfig } from "../../routines";
|
|
2
|
+
import { sourceUpdateStatus } from "..";
|
|
3
|
+
|
|
4
|
+
const fooState = { foo: "bar" };
|
|
5
|
+
|
|
6
|
+
describe("reducers: sourceUpdateStatus", () => {
|
|
7
|
+
const initialState = "none";
|
|
8
|
+
|
|
9
|
+
it("should provide the initial state", () => {
|
|
10
|
+
expect(sourceUpdateStatus(undefined, {})).toEqual(initialState);
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
it("should handle the updateSourceConfig.TRIGGER action", () => {
|
|
14
|
+
expect(
|
|
15
|
+
sourceUpdateStatus(fooState, { type: updateSourceConfig.TRIGGER })
|
|
16
|
+
).toEqual("updating");
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it("should handle the updateSourceConfig.SUCCESS action", () => {
|
|
20
|
+
expect(
|
|
21
|
+
sourceUpdateStatus(fooState, { type: updateSourceConfig.SUCCESS })
|
|
22
|
+
).toEqual("success");
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it("should handle the updateSourceConfig.FAILURE action", () => {
|
|
26
|
+
expect(
|
|
27
|
+
sourceUpdateStatus(fooState, { type: updateSourceConfig.FAILURE })
|
|
28
|
+
).toEqual("fail");
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it("should handle the updateSourceConfig.FULFILL action", () => {
|
|
32
|
+
expect(
|
|
33
|
+
sourceUpdateStatus(fooState, { type: updateSourceConfig.FULFILL })
|
|
34
|
+
).toEqual("none");
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it("should ignore unknown actions", () => {
|
|
38
|
+
expect(sourceUpdateStatus(fooState, { type: "FOO" })).toBe(fooState);
|
|
39
|
+
});
|
|
40
|
+
});
|
|
@@ -3,5 +3,13 @@ import { sources } from "./sources";
|
|
|
3
3
|
import { source } from "./source";
|
|
4
4
|
import { sourceLoading } from "./sourceLoading";
|
|
5
5
|
import { sourceRedirect } from "./sourceRedirect";
|
|
6
|
+
import { sourceUpdateStatus } from "./sourceUpdateStatus";
|
|
6
7
|
|
|
7
|
-
export {
|
|
8
|
+
export {
|
|
9
|
+
source,
|
|
10
|
+
sources,
|
|
11
|
+
sourceLoading,
|
|
12
|
+
sourcesLoading,
|
|
13
|
+
sourceRedirect,
|
|
14
|
+
sourceUpdateStatus,
|
|
15
|
+
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import _ from "lodash/fp";
|
|
2
|
-
import { fetchSource, clearSource } from "../routines";
|
|
2
|
+
import { fetchSource, clearSource, updateSourceConfig } from "../routines";
|
|
3
3
|
|
|
4
4
|
const pickFields = _.pick([
|
|
5
5
|
"active",
|
|
@@ -22,6 +22,9 @@ const source = (state = initialState, { type, payload }) => {
|
|
|
22
22
|
const data = _.propOr({}, "data")(payload);
|
|
23
23
|
return pickFields(data);
|
|
24
24
|
}
|
|
25
|
+
case updateSourceConfig.SUCCESS:
|
|
26
|
+
const data = _.propOr({}, "data")(payload);
|
|
27
|
+
return pickFields(data);
|
|
25
28
|
case fetchSource.FAILURE:
|
|
26
29
|
return initialState;
|
|
27
30
|
default:
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { updateSourceConfig } from "../routines";
|
|
2
|
+
|
|
3
|
+
const sourceUpdateStatus = (state = "none", { type }) => {
|
|
4
|
+
switch (type) {
|
|
5
|
+
case updateSourceConfig.TRIGGER:
|
|
6
|
+
return "updating";
|
|
7
|
+
case updateSourceConfig.SUCCESS:
|
|
8
|
+
return "success";
|
|
9
|
+
case updateSourceConfig.FAILURE:
|
|
10
|
+
return "fail";
|
|
11
|
+
case updateSourceConfig.FULFILL:
|
|
12
|
+
return "none";
|
|
13
|
+
default:
|
|
14
|
+
return state;
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export { sourceUpdateStatus };
|
package/src/sources/routines.js
CHANGED
|
@@ -10,3 +10,4 @@ export const enableSource = createRoutine("ENABLE_SOURCE");
|
|
|
10
10
|
export const fetchSource = createRoutine("FETCH_SOURCE");
|
|
11
11
|
export const fetchSources = createRoutine("FETCH_SOURCES");
|
|
12
12
|
export const updateSource = createRoutine("UPDATE_SOURCE");
|
|
13
|
+
export const updateSourceConfig = createRoutine("UPDATE_SOURCE_CONFIG");
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { compile } from "path-to-regexp";
|
|
2
|
+
import { testSaga } from "redux-saga-test-plan";
|
|
3
|
+
import { apiJsonPut, JSON_OPTS } from "@truedat/core/services/api";
|
|
4
|
+
import {
|
|
5
|
+
updateSourceConfigRequestSaga,
|
|
6
|
+
updateSourceConfigSaga,
|
|
7
|
+
} from "../updateSourceConfig";
|
|
8
|
+
import { updateSourceConfig } from "../../routines";
|
|
9
|
+
import { API_SOURCE } from "../../api";
|
|
10
|
+
|
|
11
|
+
describe("sagas: updateSourceConfigRequestSaga", () => {
|
|
12
|
+
it("should invoke updateSourceConfigSaga on trigger", () => {
|
|
13
|
+
expect(() => {
|
|
14
|
+
testSaga(updateSourceConfigRequestSaga)
|
|
15
|
+
.next()
|
|
16
|
+
.takeLatest(updateSourceConfig.TRIGGER, updateSourceConfigSaga)
|
|
17
|
+
.finish()
|
|
18
|
+
.isDone();
|
|
19
|
+
}).not.toThrow();
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it("should throw exception if an unhandled action is received", () => {
|
|
23
|
+
expect(() => {
|
|
24
|
+
testSaga(updateSourceConfigRequestSaga)
|
|
25
|
+
.next()
|
|
26
|
+
.takeLatest("FOO", updateSourceConfigSaga);
|
|
27
|
+
}).toThrow();
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
describe("sagas: updateSourceConfigSaga", () => {
|
|
32
|
+
const external_id = "Micro1";
|
|
33
|
+
const url = compile(API_SOURCE)({ external_id });
|
|
34
|
+
const config = { a: 1 };
|
|
35
|
+
const source = { external_id, config };
|
|
36
|
+
const payload = { source };
|
|
37
|
+
const requestData = { source_config: config };
|
|
38
|
+
|
|
39
|
+
it("should put a success action when a response is returned", () => {
|
|
40
|
+
expect(() => {
|
|
41
|
+
testSaga(updateSourceConfigSaga, { payload })
|
|
42
|
+
.next()
|
|
43
|
+
.put(updateSourceConfig.request())
|
|
44
|
+
.next()
|
|
45
|
+
.call(apiJsonPut, url, requestData, JSON_OPTS)
|
|
46
|
+
.next({ data: payload })
|
|
47
|
+
.put(updateSourceConfig.success({ source }))
|
|
48
|
+
.next()
|
|
49
|
+
.put(updateSourceConfig.fulfill())
|
|
50
|
+
.next()
|
|
51
|
+
.isDone();
|
|
52
|
+
}).not.toThrow();
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it("should put a failure action when the call returns an error", () => {
|
|
56
|
+
const message = "Request failed";
|
|
57
|
+
const error = { message };
|
|
58
|
+
|
|
59
|
+
expect(() => {
|
|
60
|
+
testSaga(updateSourceConfigSaga, { payload })
|
|
61
|
+
.next()
|
|
62
|
+
.put(updateSourceConfig.request())
|
|
63
|
+
.next()
|
|
64
|
+
.call(apiJsonPut, url, requestData, JSON_OPTS)
|
|
65
|
+
.throw(error)
|
|
66
|
+
.put(updateSourceConfig.failure(message))
|
|
67
|
+
.next()
|
|
68
|
+
.put(updateSourceConfig.fulfill())
|
|
69
|
+
.next()
|
|
70
|
+
.isDone();
|
|
71
|
+
}).not.toThrow();
|
|
72
|
+
});
|
|
73
|
+
});
|
|
@@ -5,6 +5,7 @@ import { enableSourceRequestSaga } from "./enableSource";
|
|
|
5
5
|
import { fetchSourceRequestSaga } from "./fetchSource";
|
|
6
6
|
import { fetchSourcesRequestSaga } from "./fetchSources";
|
|
7
7
|
import { updateSourceRequestSaga } from "./updateSource";
|
|
8
|
+
import { updateSourceConfigRequestSaga } from "./updateSourceConfig";
|
|
8
9
|
|
|
9
10
|
export {
|
|
10
11
|
createSourceRequestSaga,
|
|
@@ -14,6 +15,7 @@ export {
|
|
|
14
15
|
fetchSourceRequestSaga,
|
|
15
16
|
fetchSourcesRequestSaga,
|
|
16
17
|
updateSourceRequestSaga,
|
|
18
|
+
updateSourceConfigRequestSaga,
|
|
17
19
|
};
|
|
18
20
|
|
|
19
21
|
export default [
|
|
@@ -24,4 +26,5 @@ export default [
|
|
|
24
26
|
fetchSourceRequestSaga(),
|
|
25
27
|
fetchSourcesRequestSaga(),
|
|
26
28
|
updateSourceRequestSaga(),
|
|
29
|
+
updateSourceConfigRequestSaga(),
|
|
27
30
|
];
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { compile } from "path-to-regexp";
|
|
2
|
+
import { call, put, takeLatest } from "redux-saga/effects";
|
|
3
|
+
import { apiJsonPut, JSON_OPTS } from "@truedat/core/services/api";
|
|
4
|
+
import { updateSourceConfig } from "../routines";
|
|
5
|
+
import { API_SOURCE } from "../api";
|
|
6
|
+
|
|
7
|
+
export function* updateSourceConfigSaga({ payload }) {
|
|
8
|
+
try {
|
|
9
|
+
const { source } = payload;
|
|
10
|
+
const url = compile(API_SOURCE)(source);
|
|
11
|
+
const requestData = { source_config: source?.config };
|
|
12
|
+
yield put(updateSourceConfig.request());
|
|
13
|
+
const { data } = yield call(apiJsonPut, url, requestData, JSON_OPTS);
|
|
14
|
+
yield put(updateSourceConfig.success(data));
|
|
15
|
+
} catch (error) {
|
|
16
|
+
if (error.response) {
|
|
17
|
+
const { status, data } = error.response;
|
|
18
|
+
yield put(updateSourceConfig.failure({ status, data }));
|
|
19
|
+
} else {
|
|
20
|
+
yield put(updateSourceConfig.failure(error.message));
|
|
21
|
+
}
|
|
22
|
+
} finally {
|
|
23
|
+
yield put(updateSourceConfig.fulfill());
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function* updateSourceConfigRequestSaga() {
|
|
28
|
+
yield takeLatest(updateSourceConfig.TRIGGER, updateSourceConfigSaga);
|
|
29
|
+
}
|