@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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@truedat/bg",
3
- "version": "7.2.11",
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.2.11",
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.2.11",
90
- "@truedat/df": "7.2.11",
91
- "@truedat/lm": "7.2.11",
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": "74eb04f81dd49275229cf3050b56b897ff78410e"
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 missingRequiredFields = (concept, content) => {
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
- {_.negate(_.isEmpty)(missingRequiredFields(concept, content)) &&
59
- !_.includes(status)(["published", "versioned"]) && (
60
- <>
61
- <Header as="h4" dividing>
62
- <FormattedMessage
63
- id="concepts.props.missing_fields"
64
- defaultMessage="Missing required fields"
65
- />
66
- </Header>
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(concept, content))}
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 { noTranslatable: noTranslatableFields } = splitTranslatableFields(
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, is_required }) => is_enabled && is_required),
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(({ completeness, lang, langLocalName, content, isRequired }) => {
143
- return isRequired == true ? (
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
- ) : null;
154
- })(i18nConcept)}
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 ConceptForms from "./ConceptForms";
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
- setI18nConcept(updateI18nConcept);
33
+ if (!_.isEqual(i18nConcept, updateI18nConcept)) {
34
+ setI18nConcept(updateI18nConcept);
35
+ }
46
36
  }, [template]);
47
37
 
48
- if (_.isEmpty(i18nConcept)) {
49
- const i18nConceptInit = _.flow(
50
- _.filter(({ is_enabled }) => is_enabled),
51
- _.map(({ id, lang, is_default, is_required }) => {
52
- return { id, lang, is_default, is_required, name: "", content: {} };
53
- }),
54
- _.keyBy("lang")
55
- )(locales);
56
-
57
- if (i18nConceptInit) setI18nConcept(i18nConceptInit);
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
- const defaultContent = _.flow(_.find("is_default"))(i18nConcept);
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
- _.omit(defaultContent.lang),
62
+ _.pick(altLangs),
70
63
  _.omitBy(({ name, is_required }) => _.isEmpty(name) && !is_required),
71
- _.mapValues((langConcept) =>
72
- _.flow(_.pick(["name", "content"]), ({ name, content }) => {
73
- return { name, content: _.pick(translatableKeys)(content) };
74
- })(langConcept)
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
- <ConceptForms
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 ConceptForms from "./ConceptForms";
11
+ import ConceptForm from "./ConceptForm";
15
12
  const actionKey = "update";
16
13
 
17
14
  export const ConceptEdit = ({
18
15
  concept,
19
16
  content,
20
- loading,
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 = _.flow(_.find("is_default"))(i18nConcept);
34
+ const defaultContent = i18nConcept[defaultLang];
41
35
 
42
36
  const i18nSendConcept = _.flow(
43
- _.omit(defaultContent.lang),
37
+ _.pick(altLangs),
44
38
  _.omitBy(({ name, is_required }) => _.isEmpty(name) && !is_required),
45
- _.mapValues((langConcept) =>
46
- _.flow(_.pick(["name", "content"]), ({ name, content }) => {
47
- return { name, content: _.pick(translatableKeys)(content) };
48
- })(langConcept)
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
- <ConceptForms
64
+ <ConceptForm
72
65
  actionKey={actionKey}
73
66
  domainId={domain.id}
74
67
  template={template}
75
68
  i18nConcept={i18nConcept}
76
- loading={loading || localesLoading}
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
- templateName: PropTypes.string,
93
- loading: PropTypes.bool,
86
+ processedContent: PropTypes.func.isRequired,
94
87
  };
95
88
 
96
89
  export const ConceptEditLoader = (props) => {