@truedat/core 5.0.1 → 5.0.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/CHANGELOG.md +8 -0
- package/package.json +3 -3
- package/src/components/AdminMenu.js +3 -1
- package/src/components/CSVFileModal.js +63 -0
- package/src/components/DescriptionInput.js +39 -0
- package/src/components/__tests__/__snapshots__/AdminMenu.spec.js.snap +13 -0
- package/src/components/index.js +6 -2
- package/src/messages/en.js +1 -0
- package/src/messages/es.js +1 -0
- package/src/routes.js +14 -0
- package/src/services/message.js +21 -0
- package/src/services/swr.js +43 -0
package/CHANGELOG.md
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@truedat/core",
|
|
3
|
-
"version": "5.0.
|
|
3
|
+
"version": "5.0.3",
|
|
4
4
|
"description": "Truedat Web Core",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"jsnext:main": "src/index.js",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"@testing-library/jest-dom": "^5.16.5",
|
|
36
36
|
"@testing-library/react": "^12.0.0",
|
|
37
37
|
"@testing-library/user-event": "^13.2.1",
|
|
38
|
-
"@truedat/test": "5.0.
|
|
38
|
+
"@truedat/test": "5.0.3",
|
|
39
39
|
"babel-jest": "^28.1.0",
|
|
40
40
|
"babel-plugin-dynamic-import-node": "^2.3.3",
|
|
41
41
|
"babel-plugin-lodash": "^3.3.4",
|
|
@@ -117,5 +117,5 @@
|
|
|
117
117
|
"react-dom": ">= 16.8.6 < 17",
|
|
118
118
|
"semantic-ui-react": ">= 2.0.3 < 2.2"
|
|
119
119
|
},
|
|
120
|
-
"gitHead": "
|
|
120
|
+
"gitHead": "ee802e3e32b52638cb4723fcab3cdeca266a666c"
|
|
121
121
|
}
|
|
@@ -2,8 +2,9 @@ import React from "react";
|
|
|
2
2
|
import { useAuthorized } from "../hooks";
|
|
3
3
|
import {
|
|
4
4
|
CONFIGURATIONS,
|
|
5
|
-
|
|
5
|
+
HIERARCHIES,
|
|
6
6
|
I18N_MESSAGES,
|
|
7
|
+
JOBS,
|
|
7
8
|
RELATION_TAGS,
|
|
8
9
|
SOURCES,
|
|
9
10
|
SUBSCRIPTIONS,
|
|
@@ -13,6 +14,7 @@ import Submenu from "./Submenu";
|
|
|
13
14
|
|
|
14
15
|
const items = [
|
|
15
16
|
{ name: "templates", routes: [TEMPLATES] },
|
|
17
|
+
{ name: "hierarchies", routes: [HIERARCHIES] },
|
|
16
18
|
{ name: "relations", routes: [RELATION_TAGS] },
|
|
17
19
|
{ name: "subscriptions", routes: [SUBSCRIPTIONS] },
|
|
18
20
|
{ name: "sources", routes: [SOURCES] },
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import _ from "lodash/fp";
|
|
2
|
+
import React, { useState } from "react";
|
|
3
|
+
import PropTypes from "prop-types";
|
|
4
|
+
import { Button } from "semantic-ui-react";
|
|
5
|
+
import { useIntl } from "react-intl";
|
|
6
|
+
import { UploadModal } from "./UploadModal";
|
|
7
|
+
|
|
8
|
+
const CSVFileModal = ({ onSubmit, param }) => {
|
|
9
|
+
const { formatMessage } = useIntl();
|
|
10
|
+
const [processing, setProcessing] = useState(false);
|
|
11
|
+
|
|
12
|
+
const processCSV = (str, delim = ",") => {
|
|
13
|
+
const breakLine = "\n";
|
|
14
|
+
const lines = _.split(breakLine)(str);
|
|
15
|
+
const headers = _.flow(_.head, _.split(delim))(lines);
|
|
16
|
+
const rows = _.tail(lines);
|
|
17
|
+
|
|
18
|
+
const csvMap = rows.map((row) => {
|
|
19
|
+
const values = _.split(delim)(row);
|
|
20
|
+
return headers.reduce(
|
|
21
|
+
(map, header, pos) => _.set(header, values[pos])(map),
|
|
22
|
+
{}
|
|
23
|
+
);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
return csvMap;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const onload = _.flow(_.pathOr("", "target.result"), processCSV, onSubmit);
|
|
30
|
+
|
|
31
|
+
const reader = new FileReader();
|
|
32
|
+
// eslint-disable-next-line fp/no-mutation
|
|
33
|
+
reader.onload = onload;
|
|
34
|
+
|
|
35
|
+
const process = (data) => {
|
|
36
|
+
setProcessing(true);
|
|
37
|
+
const file = data.get(param);
|
|
38
|
+
reader.readAsText(file);
|
|
39
|
+
setProcessing(false);
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
return (
|
|
43
|
+
<UploadModal
|
|
44
|
+
icon="upload"
|
|
45
|
+
trigger={
|
|
46
|
+
<Button secondary floated="right" icon="upload" loading={processing} />
|
|
47
|
+
}
|
|
48
|
+
header={formatMessage({ id: "uploadModal.actions.upload" })}
|
|
49
|
+
content={formatMessage({
|
|
50
|
+
id: "uploadModal.actions.upload.confirmation.content",
|
|
51
|
+
})}
|
|
52
|
+
param={param}
|
|
53
|
+
handleSubmit={process}
|
|
54
|
+
/>
|
|
55
|
+
);
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
CSVFileModal.propTypes = {
|
|
59
|
+
onSubmit: PropTypes.func,
|
|
60
|
+
param: PropTypes.object,
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
export default CSVFileModal;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import React, { useState } from "react";
|
|
2
|
+
import PropTypes from "prop-types";
|
|
3
|
+
import { useIntl } from "react-intl";
|
|
4
|
+
import { Input } from "semantic-ui-react";
|
|
5
|
+
|
|
6
|
+
const DescriptionInput = ({ value, onChange, disabled = false }) => {
|
|
7
|
+
const { formatMessage } = useIntl();
|
|
8
|
+
const [editionMode, setEditMode] = useState();
|
|
9
|
+
return !editionMode ? (
|
|
10
|
+
<div
|
|
11
|
+
onClick={() => setEditMode(true && !disabled)}
|
|
12
|
+
onFocus={() => setEditMode(true && !disabled)}
|
|
13
|
+
className={disabled ? "description disabled" : "description"}
|
|
14
|
+
>
|
|
15
|
+
{!value || typeof value !== "string"
|
|
16
|
+
? disabled
|
|
17
|
+
? ""
|
|
18
|
+
: formatMessage({ id: "hierarchy.add_description" })
|
|
19
|
+
: value}
|
|
20
|
+
</div>
|
|
21
|
+
) : (
|
|
22
|
+
<Input
|
|
23
|
+
style={{ width: "100%" }}
|
|
24
|
+
onBlur={() => setEditMode(false)}
|
|
25
|
+
placeholder={formatMessage({ id: "hierarchy.add_description" })}
|
|
26
|
+
onChange={onChange}
|
|
27
|
+
value={value == null ? "" : value}
|
|
28
|
+
autoFocus
|
|
29
|
+
/>
|
|
30
|
+
);
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
DescriptionInput.propTypes = {
|
|
34
|
+
value: PropTypes.string,
|
|
35
|
+
onChange: PropTypes.func,
|
|
36
|
+
disabled: PropTypes.bool,
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export default DescriptionInput;
|
|
@@ -43,6 +43,19 @@ exports[`<AdminMenu /> matches the latest snapshot 1`] = `
|
|
|
43
43
|
Templates
|
|
44
44
|
</span>
|
|
45
45
|
</a>
|
|
46
|
+
<a
|
|
47
|
+
aria-checked="false"
|
|
48
|
+
class="item"
|
|
49
|
+
href="/hierarchies"
|
|
50
|
+
name="hierarchies"
|
|
51
|
+
role="option"
|
|
52
|
+
>
|
|
53
|
+
<span
|
|
54
|
+
class="text"
|
|
55
|
+
>
|
|
56
|
+
Hierarchies
|
|
57
|
+
</span>
|
|
58
|
+
</a>
|
|
46
59
|
<a
|
|
47
60
|
aria-checked="false"
|
|
48
61
|
class="item"
|
package/src/components/index.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import ActiveRoute from "./ActiveRoute";
|
|
2
2
|
import AdminMenu from "./AdminMenu";
|
|
3
|
-
import MembersMenu from "./MembersMenu";
|
|
4
3
|
import Alert from "./Alert";
|
|
5
4
|
import Authorized from "./Authorized";
|
|
6
5
|
import AvailableFilters from "./AvailableFilters";
|
|
@@ -9,12 +8,14 @@ import CatalogMenu from "./CatalogMenu";
|
|
|
9
8
|
import Comments from "./Comments";
|
|
10
9
|
import CommentsLoader from "./CommentsLoader";
|
|
11
10
|
import ConfirmModal from "./ConfirmModal";
|
|
11
|
+
import CSVFileModal from "./CSVFileModal";
|
|
12
12
|
import CursorPagination from "./CursorPagination";
|
|
13
13
|
import DashboardMenu from "./DashboardMenu";
|
|
14
14
|
import Date from "./Date";
|
|
15
15
|
import DateFilter from "./DateFilter";
|
|
16
16
|
import DateRangeFilter from "./DateRangeFilter";
|
|
17
17
|
import DateTime from "./DateTime";
|
|
18
|
+
import DescriptionInput from "./DescriptionInput";
|
|
18
19
|
import DomainSelector from "./DomainSelector";
|
|
19
20
|
import DropdownMenuItem from "./DropdownMenuItem";
|
|
20
21
|
import ErrorBoundary from "./ErrorBoundary";
|
|
@@ -26,6 +27,7 @@ import HistoryBackButton from "./HistoryBackButton";
|
|
|
26
27
|
import IngestMenu from "./IngestMenu";
|
|
27
28
|
import LineageMenu from "./LineageMenu";
|
|
28
29
|
import Loading from "./Loading";
|
|
30
|
+
import MembersMenu from "./MembersMenu";
|
|
29
31
|
import OptionGroup from "./OptionGroup";
|
|
30
32
|
import OptionModal from "./OptionModal";
|
|
31
33
|
import Pagination from "./Pagination";
|
|
@@ -50,7 +52,6 @@ import UploadModal from "./UploadModal";
|
|
|
50
52
|
export {
|
|
51
53
|
ActiveRoute,
|
|
52
54
|
AdminMenu,
|
|
53
|
-
MembersMenu,
|
|
54
55
|
Alert,
|
|
55
56
|
Authorized,
|
|
56
57
|
AvailableFilters,
|
|
@@ -59,12 +60,14 @@ export {
|
|
|
59
60
|
Comments,
|
|
60
61
|
CommentsLoader,
|
|
61
62
|
ConfirmModal,
|
|
63
|
+
CSVFileModal,
|
|
62
64
|
CursorPagination,
|
|
63
65
|
DashboardMenu,
|
|
64
66
|
Date,
|
|
65
67
|
DateFilter,
|
|
66
68
|
DateRangeFilter,
|
|
67
69
|
DateTime,
|
|
70
|
+
DescriptionInput,
|
|
68
71
|
DomainSelector,
|
|
69
72
|
DropdownMenuItem,
|
|
70
73
|
ErrorBoundary,
|
|
@@ -76,6 +79,7 @@ export {
|
|
|
76
79
|
IngestMenu,
|
|
77
80
|
LineageMenu,
|
|
78
81
|
Loading,
|
|
82
|
+
MembersMenu,
|
|
79
83
|
OptionGroup,
|
|
80
84
|
OptionModal,
|
|
81
85
|
Pagination,
|
package/src/messages/en.js
CHANGED
|
@@ -107,6 +107,7 @@ export default {
|
|
|
107
107
|
"sidemenu.grant_request_approvals": "Approve Grant Requests",
|
|
108
108
|
"sidemenu.grant_requests": "Grant Requests",
|
|
109
109
|
"sidemenu.grants": "Grants",
|
|
110
|
+
"sidemenu.hierarchies": "Hierarchies",
|
|
110
111
|
"sidemenu.hide": "Collapse sidebar",
|
|
111
112
|
"sidemenu.i18nMessages": "Translations",
|
|
112
113
|
"sidemenu.implementations": "Implementations",
|
package/src/messages/es.js
CHANGED
|
@@ -110,6 +110,7 @@ export default {
|
|
|
110
110
|
"sidemenu.grant_request_approvals": "Aprobar Peticiones de Accesos",
|
|
111
111
|
"sidemenu.grant_requests": "Peticiones de Accesos",
|
|
112
112
|
"sidemenu.grants": "Accesos",
|
|
113
|
+
"sidemenu.hierarchies": "Jerarquías",
|
|
113
114
|
"sidemenu.hide": "Ocultar",
|
|
114
115
|
"sidemenu.i18nMessages": "Traducciones",
|
|
115
116
|
"sidemenu.implementations": "Implementaciones",
|
package/src/routes.js
CHANGED
|
@@ -62,6 +62,10 @@ export const GROUP = "/groups/:id";
|
|
|
62
62
|
export const GROUPS = "/groups";
|
|
63
63
|
export const GROUP_CREATE = "/groups/new";
|
|
64
64
|
export const GROUP_EDIT = "/groups/:id/edit";
|
|
65
|
+
export const HIERARCHIES = "/hierarchies";
|
|
66
|
+
export const HIERARCHY = "/hierarchies/:hierarchyId";
|
|
67
|
+
export const HIERARCHY_EDIT = "/hierarchies/:hierarchyId/edit";
|
|
68
|
+
export const HIERARCHY_CREATE = "/hierarchies/new";
|
|
65
69
|
export const I18N = "/i18n";
|
|
66
70
|
export const I18N_MESSAGES = "/i18n/messages";
|
|
67
71
|
export const I18N_MESSAGES_NEW = "/i18n/messages/new";
|
|
@@ -75,6 +79,10 @@ export const IMPLEMENTATION_CONCEPT_LINKS =
|
|
|
75
79
|
export const IMPLEMENTATION_CONCEPT_LINKS_NEW =
|
|
76
80
|
"/implementations/:implementation_id/links/concepts/new";
|
|
77
81
|
export const IMPLEMENTATION_EDIT = "/implementations/:implementation_id/edit";
|
|
82
|
+
export const IMPLEMENTATION_EDIT_AS_DEFAULT =
|
|
83
|
+
"/implementations/:implementation_id/edit_as_default";
|
|
84
|
+
export const IMPLEMENTATION_EDIT_AS_RAW =
|
|
85
|
+
"/implementations/:implementation_id/edit_as_raw";
|
|
78
86
|
export const IMPLEMENTATION_EVENTS =
|
|
79
87
|
"/implementations/:implementation_id/events";
|
|
80
88
|
export const IMPLEMENTATION_EXECUTIONS =
|
|
@@ -261,6 +269,10 @@ const routes = {
|
|
|
261
269
|
GROUPS,
|
|
262
270
|
GROUP_CREATE,
|
|
263
271
|
GROUP_EDIT,
|
|
272
|
+
HIERARCHIES,
|
|
273
|
+
HIERARCHY,
|
|
274
|
+
HIERARCHY_EDIT,
|
|
275
|
+
HIERARCHY_CREATE,
|
|
264
276
|
I18N,
|
|
265
277
|
I18N_MESSAGES,
|
|
266
278
|
I18N_MESSAGES_NEW,
|
|
@@ -272,6 +284,8 @@ const routes = {
|
|
|
272
284
|
IMPLEMENTATION_CONCEPT_LINKS,
|
|
273
285
|
IMPLEMENTATION_CONCEPT_LINKS_NEW,
|
|
274
286
|
IMPLEMENTATION_EDIT,
|
|
287
|
+
IMPLEMENTATION_EDIT_AS_DEFAULT,
|
|
288
|
+
IMPLEMENTATION_EDIT_AS_RAW,
|
|
275
289
|
IMPLEMENTATION_EVENTS,
|
|
276
290
|
IMPLEMENTATION_EXECUTIONS,
|
|
277
291
|
IMPLEMENTATION_HISTORY,
|
package/src/services/message.js
CHANGED
|
@@ -14,6 +14,9 @@ export const defaultMessage = (state, type, payload) => {
|
|
|
14
14
|
if (type === "LOG_ERROR/TRIGGER" && _.has("graphQLErrors")(payload))
|
|
15
15
|
return graphQLErrors(payload);
|
|
16
16
|
|
|
17
|
+
if (type === "LOG_ERROR/TRIGGER" && _.has("swrErrors")(payload))
|
|
18
|
+
return swrErrors(payload);
|
|
19
|
+
|
|
17
20
|
if (_.endsWith("/TRIGGER")(type)) return state;
|
|
18
21
|
|
|
19
22
|
if (_.endsWith("/FAILURE")(type)) {
|
|
@@ -27,6 +30,24 @@ export const defaultMessage = (state, type, payload) => {
|
|
|
27
30
|
return state;
|
|
28
31
|
};
|
|
29
32
|
|
|
33
|
+
const swrErrors = ({ swrErrors, prefix }) => {
|
|
34
|
+
const errors = _.flow(
|
|
35
|
+
_.toPairs,
|
|
36
|
+
_.flatMap(([field, errors]) =>
|
|
37
|
+
_.map((v) => `${prefix}.${field}.${v}`)(errors)
|
|
38
|
+
),
|
|
39
|
+
_.map((name) => ({ name }))
|
|
40
|
+
)(swrErrors);
|
|
41
|
+
|
|
42
|
+
return {
|
|
43
|
+
error: true,
|
|
44
|
+
header: "Error",
|
|
45
|
+
icon: "attention",
|
|
46
|
+
errorList: errors,
|
|
47
|
+
text: "List of errors",
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
|
|
30
51
|
export const graphQLErrors = (payload) => {
|
|
31
52
|
const errorList = _.map(_.pick(["path", "field", "message"]))(
|
|
32
53
|
payload.graphQLErrors
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import _ from "lodash/fp";
|
|
2
|
+
import { unauthorized, logError } from "../routines";
|
|
3
|
+
|
|
4
|
+
function isNumeric(str) {
|
|
5
|
+
if (typeof str != "string") return false;
|
|
6
|
+
return !isNaN(str) && !isNaN(parseInt(str));
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const getPrefix = _.flow(
|
|
10
|
+
_.replace("/api/", ""),
|
|
11
|
+
_.split("/"),
|
|
12
|
+
_.reject(isNumeric),
|
|
13
|
+
_.join(".")
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
const createErrorMiddleware = ({ dispatch }) => {
|
|
17
|
+
return (useSWRNext) => {
|
|
18
|
+
return (key, fetcher, config) => {
|
|
19
|
+
return useSWRNext(key, fetcher, {
|
|
20
|
+
...config,
|
|
21
|
+
onError: (error) => {
|
|
22
|
+
config.onError(error);
|
|
23
|
+
const statusCode = _.pathOr(null, "response.status")(error);
|
|
24
|
+
const swrErrors = _.pathOr(null, "response.data.errors")(error);
|
|
25
|
+
|
|
26
|
+
if (statusCode === 401) {
|
|
27
|
+
dispatch(unauthorized());
|
|
28
|
+
} else if (swrErrors !== null) {
|
|
29
|
+
const prefix = getPrefix(key);
|
|
30
|
+
dispatch(logError({ swrErrors, prefix }));
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
});
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export const createSwrConfig = (store) => {
|
|
39
|
+
const errorMiddleware = createErrorMiddleware(store);
|
|
40
|
+
return {
|
|
41
|
+
use: [errorMiddleware],
|
|
42
|
+
};
|
|
43
|
+
};
|