@truedat/bg 7.2.11 → 7.3.0
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 +6 -6
- package/src/concepts/components/ConceptCompleteness.js +51 -27
- package/src/concepts/components/ConceptCreate.js +30 -40
- package/src/concepts/components/ConceptEdit.js +17 -24
- package/src/concepts/components/ConceptForm.js +259 -97
- package/src/concepts/components/__tests__/ConceptForm.spec.js +4 -6
- package/src/concepts/components/__tests__/__snapshots__/ConceptEdit.spec.js.snap +105 -98
- package/src/concepts/components/__tests__/__snapshots__/ConceptForm.spec.js.snap +283 -143
- package/src/concepts/components/ConceptFormTabs.js +0 -75
- package/src/concepts/components/ConceptForms.js +0 -200
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@truedat/bg",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.3.0",
|
|
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.
|
|
37
|
+
"@truedat/test": "7.3.0",
|
|
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.
|
|
90
|
-
"@truedat/df": "7.
|
|
91
|
-
"@truedat/lm": "7.
|
|
89
|
+
"@truedat/core": "7.3.0",
|
|
90
|
+
"@truedat/df": "7.3.0",
|
|
91
|
+
"@truedat/lm": "7.3.0",
|
|
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": "
|
|
114
|
+
"gitHead": "cbf85fe17b535953689418b85658cc804d095dfb"
|
|
115
115
|
}
|
|
@@ -5,15 +5,23 @@ import { connect } from "react-redux";
|
|
|
5
5
|
import { List, Header, Progress, Segment, Icon } from "semantic-ui-react";
|
|
6
6
|
import { FormattedMessage } from "react-intl";
|
|
7
7
|
import { isRequired } from "@truedat/df/utils";
|
|
8
|
-
import { useLanguage } from "@truedat/core/i18n";
|
|
8
|
+
import { useLanguage, I18nProvider } from "@truedat/core/i18n";
|
|
9
9
|
import { splitTranslatableFields } from "@truedat/core/services/i18nContent";
|
|
10
10
|
|
|
11
|
-
const
|
|
11
|
+
const fetchMissingRequiredFields = (
|
|
12
|
+
concept,
|
|
13
|
+
content,
|
|
14
|
+
isDefault,
|
|
15
|
+
splitFields
|
|
16
|
+
) => {
|
|
12
17
|
return _.flow(
|
|
13
18
|
_.path("template.content"),
|
|
14
19
|
_.flatMap(({ fields }) =>
|
|
15
20
|
_.filter((field) => {
|
|
16
21
|
const name = field?.name;
|
|
22
|
+
if (!isDefault && !splitFields.translatable[name]) {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
17
25
|
const value = _.prop(name)(content);
|
|
18
26
|
return (
|
|
19
27
|
!_.isNumber(value) &&
|
|
@@ -32,7 +40,14 @@ export const Completeness = ({
|
|
|
32
40
|
langLocalName,
|
|
33
41
|
concept,
|
|
34
42
|
content,
|
|
43
|
+
isRequired,
|
|
44
|
+
isDefault,
|
|
45
|
+
splitFields,
|
|
35
46
|
}) => {
|
|
47
|
+
const missingRequiredFields =
|
|
48
|
+
isRequired && !_.includes(status)(["published", "versioned"])
|
|
49
|
+
? fetchMissingRequiredFields(concept, content, isDefault, splitFields)
|
|
50
|
+
: [];
|
|
36
51
|
return (
|
|
37
52
|
<>
|
|
38
53
|
<Header as="h3" dividing>
|
|
@@ -55,16 +70,15 @@ export const Completeness = ({
|
|
|
55
70
|
percent={completeness}
|
|
56
71
|
progress
|
|
57
72
|
/>
|
|
58
|
-
{_.
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
<
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
73
|
+
{!_.isEmpty(missingRequiredFields) && (
|
|
74
|
+
<>
|
|
75
|
+
<Header as="h4" dividing>
|
|
76
|
+
<FormattedMessage
|
|
77
|
+
id="concepts.props.missing_fields"
|
|
78
|
+
defaultMessage="Missing required fields"
|
|
79
|
+
/>
|
|
80
|
+
</Header>
|
|
81
|
+
<I18nProvider lang={lang}>
|
|
68
82
|
<List>
|
|
69
83
|
{_.map.convert({ cap: false })(({ label }, i) => (
|
|
70
84
|
<List.Item key={i}>
|
|
@@ -76,10 +90,11 @@ export const Completeness = ({
|
|
|
76
90
|
/>
|
|
77
91
|
) : null}
|
|
78
92
|
</List.Item>
|
|
79
|
-
))(missingRequiredFields
|
|
93
|
+
))(missingRequiredFields)}
|
|
80
94
|
</List>
|
|
81
|
-
|
|
82
|
-
|
|
95
|
+
</I18nProvider>
|
|
96
|
+
</>
|
|
97
|
+
)}
|
|
83
98
|
</>
|
|
84
99
|
);
|
|
85
100
|
};
|
|
@@ -91,6 +106,9 @@ Completeness.propTypes = {
|
|
|
91
106
|
lang: PropTypes.string,
|
|
92
107
|
langLocalName: PropTypes.string,
|
|
93
108
|
content: PropTypes.object,
|
|
109
|
+
isRequired: PropTypes.bool,
|
|
110
|
+
isDefault: PropTypes.bool,
|
|
111
|
+
splitFields: PropTypes.object,
|
|
94
112
|
};
|
|
95
113
|
|
|
96
114
|
export const ConceptCompleteness = ({ concept }) => {
|
|
@@ -101,19 +119,15 @@ export const ConceptCompleteness = ({ concept }) => {
|
|
|
101
119
|
const status = _.get("status")(concept);
|
|
102
120
|
|
|
103
121
|
const i18nContent = concept.i18n_content || {};
|
|
104
|
-
|
|
105
|
-
const
|
|
106
|
-
concept.template
|
|
107
|
-
);
|
|
108
|
-
|
|
109
|
-
const noTranslatableContent = _.pick(_.keys(noTranslatableFields))(
|
|
122
|
+
const splitFields = splitTranslatableFields(concept.template);
|
|
123
|
+
const noTranslatableContent = _.pick(_.keys(splitFields.noTranslatable))(
|
|
110
124
|
concept.content
|
|
111
125
|
);
|
|
126
|
+
|
|
112
127
|
const i18nConcept = _.flow(
|
|
113
|
-
_.filter(({ is_enabled
|
|
128
|
+
_.filter(({ is_enabled }) => is_enabled),
|
|
114
129
|
_.map(({ id, lang, is_default, is_required, local_name }) => {
|
|
115
130
|
const contentLang = _.get(lang)(i18nContent);
|
|
116
|
-
|
|
117
131
|
const langContent = is_default
|
|
118
132
|
? content
|
|
119
133
|
: { ...noTranslatableContent, ...contentLang?.content };
|
|
@@ -139,8 +153,15 @@ export const ConceptCompleteness = ({ concept }) => {
|
|
|
139
153
|
|
|
140
154
|
return (
|
|
141
155
|
<Segment className="completeness">
|
|
142
|
-
{_.map(
|
|
143
|
-
|
|
156
|
+
{_.map(
|
|
157
|
+
({
|
|
158
|
+
completeness,
|
|
159
|
+
lang,
|
|
160
|
+
langLocalName,
|
|
161
|
+
content,
|
|
162
|
+
isRequired,
|
|
163
|
+
isDefault,
|
|
164
|
+
}) => (
|
|
144
165
|
<Completeness
|
|
145
166
|
key={lang}
|
|
146
167
|
status={status}
|
|
@@ -149,9 +170,12 @@ export const ConceptCompleteness = ({ concept }) => {
|
|
|
149
170
|
langLocalName={_.size(i18nConcept) > 1 ? langLocalName : null}
|
|
150
171
|
concept={concept}
|
|
151
172
|
content={content}
|
|
173
|
+
isRequired={isRequired}
|
|
174
|
+
isDefault={isDefault}
|
|
175
|
+
splitFields={splitFields}
|
|
152
176
|
/>
|
|
153
|
-
)
|
|
154
|
-
|
|
177
|
+
)
|
|
178
|
+
)(i18nConcept)}
|
|
155
179
|
</Segment>
|
|
156
180
|
);
|
|
157
181
|
};
|
|
@@ -3,35 +3,23 @@ import React, { useState, useEffect } from "react";
|
|
|
3
3
|
import PropTypes from "prop-types";
|
|
4
4
|
import { connect } from "react-redux";
|
|
5
5
|
import { useLanguage } from "@truedat/core/i18n";
|
|
6
|
-
import {
|
|
7
|
-
splitTranslatableFields,
|
|
8
|
-
formatLocales,
|
|
9
|
-
} from "@truedat/core/services/i18nContent";
|
|
6
|
+
import { splitTranslatableFields } from "@truedat/core/services/i18nContent";
|
|
10
7
|
import { conceptAction } from "../routines";
|
|
11
8
|
import { useConceptVersionsActions } from "../hooks/useConcepts";
|
|
12
|
-
import
|
|
9
|
+
import ConceptForm from "./ConceptForm";
|
|
13
10
|
|
|
14
11
|
const actionKey = "create";
|
|
15
12
|
|
|
16
13
|
const ConceptCreate = ({ conceptActionLoading, conceptAction }) => {
|
|
17
|
-
const { locales } = useLanguage();
|
|
14
|
+
const { locales, defaultLang, altLangs } = useLanguage();
|
|
18
15
|
const { actions: conceptsActions } = useConceptVersionsActions();
|
|
19
16
|
|
|
20
17
|
const [i18nConcept, setI18nConcept] = useState({});
|
|
21
18
|
const [domainId, setDomainId] = useState();
|
|
22
19
|
const [template, setTemplate] = useState();
|
|
23
|
-
const [translatableKeys, setTranslatableKeys] = useState([]);
|
|
24
|
-
const [noTranslatableKeys, setNoTranslatableKeys] = useState([]);
|
|
25
20
|
|
|
26
21
|
useEffect(() => {
|
|
27
22
|
const templateFields = splitTranslatableFields(template);
|
|
28
|
-
|
|
29
|
-
const translatableFields = _.keys(templateFields.translatable);
|
|
30
|
-
const noTranslatableFields = _.keys(templateFields.noTranslatable);
|
|
31
|
-
|
|
32
|
-
setTranslatableKeys(translatableFields);
|
|
33
|
-
setNoTranslatableKeys(noTranslatableFields);
|
|
34
|
-
|
|
35
23
|
const updateI18nConcept = _.flow(
|
|
36
24
|
_.map((langContent) => ({
|
|
37
25
|
...langContent,
|
|
@@ -42,37 +30,41 @@ const ConceptCreate = ({ conceptActionLoading, conceptAction }) => {
|
|
|
42
30
|
_.keyBy("lang")
|
|
43
31
|
)(i18nConcept);
|
|
44
32
|
|
|
45
|
-
|
|
33
|
+
if (!_.isEqual(i18nConcept, updateI18nConcept)) {
|
|
34
|
+
setI18nConcept(updateI18nConcept);
|
|
35
|
+
}
|
|
46
36
|
}, [template]);
|
|
47
37
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
_.
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
38
|
+
useEffect(() => {
|
|
39
|
+
if (_.isEmpty(i18nConcept)) {
|
|
40
|
+
const i18nConceptInit = _.flow(
|
|
41
|
+
_.filter(({ is_enabled }) => is_enabled),
|
|
42
|
+
_.map(({ id, lang, is_default, is_required }) => {
|
|
43
|
+
return { id, lang, is_default, is_required, name: "", content: {} };
|
|
44
|
+
}),
|
|
45
|
+
_.keyBy("lang")
|
|
46
|
+
)(locales);
|
|
47
|
+
setI18nConcept(i18nConceptInit);
|
|
48
|
+
}
|
|
49
|
+
}, [locales]);
|
|
59
50
|
|
|
60
51
|
const action = _.prop(actionKey)(conceptsActions);
|
|
61
52
|
|
|
62
|
-
const langs = formatLocales(locales);
|
|
63
|
-
|
|
64
53
|
const handleSubmit = (e) => {
|
|
65
54
|
e.preventDefault();
|
|
66
|
-
|
|
55
|
+
|
|
56
|
+
const defaultContent = i18nConcept[defaultLang];
|
|
57
|
+
|
|
58
|
+
const { translatable } = splitTranslatableFields(template);
|
|
59
|
+
const translatableKeys = Object.keys(translatable);
|
|
67
60
|
|
|
68
61
|
const i18nSendConcept = _.flow(
|
|
69
|
-
_.
|
|
62
|
+
_.pick(altLangs),
|
|
70
63
|
_.omitBy(({ name, is_required }) => _.isEmpty(name) && !is_required),
|
|
71
|
-
_.mapValues((langConcept) =>
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
)
|
|
64
|
+
_.mapValues((langConcept) => ({
|
|
65
|
+
name: langConcept.name,
|
|
66
|
+
content: _.pick(translatableKeys, langConcept.content),
|
|
67
|
+
}))
|
|
76
68
|
)(i18nConcept);
|
|
77
69
|
|
|
78
70
|
const business_concept_version = {
|
|
@@ -89,16 +81,14 @@ const ConceptCreate = ({ conceptActionLoading, conceptAction }) => {
|
|
|
89
81
|
business_concept_version,
|
|
90
82
|
});
|
|
91
83
|
};
|
|
84
|
+
|
|
92
85
|
return (
|
|
93
|
-
<
|
|
86
|
+
<ConceptForm
|
|
94
87
|
actionKey={actionKey}
|
|
95
88
|
domainId={domainId}
|
|
96
89
|
template={template}
|
|
97
90
|
i18nConcept={i18nConcept}
|
|
98
91
|
loading={conceptActionLoading}
|
|
99
|
-
langs={langs}
|
|
100
|
-
noTranslatableFields={noTranslatableKeys}
|
|
101
|
-
translatableFields={translatableKeys}
|
|
102
92
|
setI18nConcept={setI18nConcept}
|
|
103
93
|
setDomainId={setDomainId}
|
|
104
94
|
setTemplate={setTemplate}
|
|
@@ -5,20 +5,16 @@ import { compose } from "redux";
|
|
|
5
5
|
import { connect } from "react-redux";
|
|
6
6
|
import { applyTemplate } from "@truedat/df/utils";
|
|
7
7
|
import { useLanguage } from "@truedat/core/i18n";
|
|
8
|
-
import {
|
|
9
|
-
splitTranslatableFields,
|
|
10
|
-
formatLocales,
|
|
11
|
-
} from "@truedat/core/services/i18nContent";
|
|
8
|
+
import { splitTranslatableFields } from "@truedat/core/services/i18nContent";
|
|
12
9
|
import { useTemplate } from "@truedat/core/hooks";
|
|
13
10
|
import { conceptAction } from "../routines";
|
|
14
|
-
import
|
|
11
|
+
import ConceptForm from "./ConceptForm";
|
|
15
12
|
const actionKey = "update";
|
|
16
13
|
|
|
17
14
|
export const ConceptEdit = ({
|
|
18
15
|
concept,
|
|
19
16
|
content,
|
|
20
|
-
|
|
21
|
-
locales,
|
|
17
|
+
templateLoading,
|
|
22
18
|
localesLoading,
|
|
23
19
|
template,
|
|
24
20
|
action,
|
|
@@ -26,27 +22,24 @@ export const ConceptEdit = ({
|
|
|
26
22
|
processedContent,
|
|
27
23
|
}) => {
|
|
28
24
|
const { domain } = concept;
|
|
29
|
-
|
|
30
25
|
const [i18nConcept, setI18nConcept] = useState(content);
|
|
26
|
+
const { defaultLang, altLangs } = useLanguage();
|
|
31
27
|
|
|
32
28
|
const templateFields = splitTranslatableFields(template);
|
|
33
29
|
|
|
34
30
|
const translatableKeys = _.keys(templateFields.translatable);
|
|
35
|
-
const noTranslatableKeys = _.keys(templateFields.noTranslatable);
|
|
36
|
-
const langs = formatLocales(locales);
|
|
37
31
|
|
|
38
32
|
const handleSubmit = (e) => {
|
|
39
33
|
e.preventDefault();
|
|
40
|
-
const defaultContent =
|
|
34
|
+
const defaultContent = i18nConcept[defaultLang];
|
|
41
35
|
|
|
42
36
|
const i18nSendConcept = _.flow(
|
|
43
|
-
_.
|
|
37
|
+
_.pick(altLangs),
|
|
44
38
|
_.omitBy(({ name, is_required }) => _.isEmpty(name) && !is_required),
|
|
45
|
-
_.mapValues((langConcept) =>
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
)
|
|
39
|
+
_.mapValues((langConcept) => ({
|
|
40
|
+
name: langConcept.name,
|
|
41
|
+
content: _.pick(translatableKeys, langConcept.content),
|
|
42
|
+
}))
|
|
50
43
|
)(i18nConcept);
|
|
51
44
|
|
|
52
45
|
const newContent = processedContent(defaultContent.content, domain?.id);
|
|
@@ -68,15 +61,12 @@ export const ConceptEdit = ({
|
|
|
68
61
|
|
|
69
62
|
return (
|
|
70
63
|
<>
|
|
71
|
-
<
|
|
64
|
+
<ConceptForm
|
|
72
65
|
actionKey={actionKey}
|
|
73
66
|
domainId={domain.id}
|
|
74
67
|
template={template}
|
|
75
68
|
i18nConcept={i18nConcept}
|
|
76
|
-
loading={
|
|
77
|
-
langs={langs}
|
|
78
|
-
noTranslatableFields={noTranslatableKeys}
|
|
79
|
-
translatableFields={translatableKeys}
|
|
69
|
+
loading={templateLoading || localesLoading}
|
|
80
70
|
setI18nConcept={setI18nConcept}
|
|
81
71
|
onSubmit={handleSubmit}
|
|
82
72
|
setTemplate={() => null} // In ConceptEdit, the template is already selected and cannot be changed
|
|
@@ -88,9 +78,12 @@ export const ConceptEdit = ({
|
|
|
88
78
|
ConceptEdit.propTypes = {
|
|
89
79
|
action: PropTypes.object,
|
|
90
80
|
concept: PropTypes.object,
|
|
81
|
+
content: PropTypes.object.isRequired,
|
|
82
|
+
templateLoading: PropTypes.bool,
|
|
83
|
+
localesLoading: PropTypes.bool,
|
|
84
|
+
template: PropTypes.object,
|
|
91
85
|
conceptAction: PropTypes.func.isRequired,
|
|
92
|
-
|
|
93
|
-
loading: PropTypes.bool,
|
|
86
|
+
processedContent: PropTypes.func.isRequired,
|
|
94
87
|
};
|
|
95
88
|
|
|
96
89
|
export const ConceptEditLoader = (props) => {
|