@truedat/bg 7.3.3 → 7.4.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/ConceptForm.js +67 -0
- package/src/concepts/components/ConceptsActions.js +15 -11
- package/src/concepts/components/ConceptsPanel.js +8 -3
- package/src/concepts/components/__tests__/ConceptEdit.spec.js +27 -2
- package/src/concepts/components/__tests__/ConceptForm.spec.js +7 -0
- package/src/taxonomy/components/__tests__/DomainForm.spec.js +1 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@truedat/bg",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.4.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.4.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.4.0",
|
|
90
|
+
"@truedat/df": "7.4.0",
|
|
91
|
+
"@truedat/lm": "7.4.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": "65eb6322cc8478fd4c35f2268c8ac1a41e8f129d"
|
|
115
115
|
}
|
|
@@ -23,6 +23,9 @@ import {
|
|
|
23
23
|
} from "@truedat/core/components";
|
|
24
24
|
import { useLanguage, I18nProvider } from "@truedat/core/i18n";
|
|
25
25
|
import SuggestionsWidget from "@truedat/ai/components/suggestions/SuggestionsWidget";
|
|
26
|
+
import { useAvailabilityCheck as useTranslatableCheck } from "@truedat/ai/hooks/useTranslations";
|
|
27
|
+
import { splitTranslatableFields } from "@truedat/core/services/i18nContent";
|
|
28
|
+
import { TranslationModal } from "@truedat/ai/components";
|
|
26
29
|
|
|
27
30
|
const SelectDynamicFormWithTranslations = lazy(() =>
|
|
28
31
|
import("@truedat/df/components/SelectDynamicFormWithTranslations")
|
|
@@ -51,9 +54,14 @@ const ConceptForm = ({
|
|
|
51
54
|
const [domains, setDomains] = useState();
|
|
52
55
|
const [domainsLoading, setDomainsLoading] = useState(true);
|
|
53
56
|
const [hasSuggestions, setHasSuggestions] = useState(false);
|
|
57
|
+
const [canTranslate, setCanTranslate] = useState(false);
|
|
58
|
+
const [showTranslationModal, setShowTranslationModal] = useState(false);
|
|
54
59
|
const isNonEmptyString = useCallback(_.flow(_.trim, _.negate(_.isEmpty)), []);
|
|
55
60
|
const { trigger: checkSuggestionAvailability } = useAvailabilityCheck();
|
|
56
61
|
const templateId = template?.id;
|
|
62
|
+
const { trigger: checkTranslationAvailability } = useTranslatableCheck();
|
|
63
|
+
const { translatable: translatableFields } =
|
|
64
|
+
splitTranslatableFields(template);
|
|
57
65
|
|
|
58
66
|
const handleDomainChange = (_e, { value }) => setDomainId(_.toInteger(value));
|
|
59
67
|
const handleTemplateChange = (value) => setTemplate(value);
|
|
@@ -66,6 +74,10 @@ const ConceptForm = ({
|
|
|
66
74
|
});
|
|
67
75
|
};
|
|
68
76
|
|
|
77
|
+
useEffect(() => {
|
|
78
|
+
checkCanTranslate();
|
|
79
|
+
}, []);
|
|
80
|
+
|
|
69
81
|
useEffect(() => {
|
|
70
82
|
if (templateId && domainId) {
|
|
71
83
|
checkSuggestionAvailability({
|
|
@@ -75,6 +87,7 @@ const ConceptForm = ({
|
|
|
75
87
|
}).then((res) =>
|
|
76
88
|
setHasSuggestions(_.get("data.data.status", res) === "ok")
|
|
77
89
|
);
|
|
90
|
+
checkCanTranslate();
|
|
78
91
|
}
|
|
79
92
|
}, [templateId, domainId, checkSuggestionAvailability]);
|
|
80
93
|
|
|
@@ -107,6 +120,28 @@ const ConceptForm = ({
|
|
|
107
120
|
});
|
|
108
121
|
};
|
|
109
122
|
|
|
123
|
+
const checkCanTranslate = () => {
|
|
124
|
+
if (templateId && domainId) {
|
|
125
|
+
checkTranslationAvailability({
|
|
126
|
+
domain_ids: [domainId],
|
|
127
|
+
resource_type: "business_concept",
|
|
128
|
+
}).then((res) =>
|
|
129
|
+
setCanTranslate(
|
|
130
|
+
_.get("data.data.status", res) === "ok" &&
|
|
131
|
+
isMultilingual &&
|
|
132
|
+
!_.isEmpty(translatableFields)
|
|
133
|
+
)
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
const setTranslations = (translations) => {
|
|
139
|
+
setI18nConcept({
|
|
140
|
+
...i18nConcept,
|
|
141
|
+
...translations,
|
|
142
|
+
});
|
|
143
|
+
};
|
|
144
|
+
|
|
110
145
|
const renderNameField = useCallback(
|
|
111
146
|
(lang, value, onChange, showValidation = false) => (
|
|
112
147
|
<I18nProvider lang={lang}>
|
|
@@ -254,6 +289,15 @@ const ConceptForm = ({
|
|
|
254
289
|
/>
|
|
255
290
|
));
|
|
256
291
|
|
|
292
|
+
const isThereAnyTranslatableField =
|
|
293
|
+
_.flow(
|
|
294
|
+
_.keys,
|
|
295
|
+
_.some((key) => !_.isEmpty(i18nConcept[defaultLang]?.content?.[key]))
|
|
296
|
+
)(translatableFields) || !_.isEmpty(i18nConcept[defaultLang]?.name);
|
|
297
|
+
|
|
298
|
+
const disableTranslationButton =
|
|
299
|
+
!domainId || !template?.name || !isThereAnyTranslatableField;
|
|
300
|
+
|
|
257
301
|
const commonForm = (
|
|
258
302
|
<>
|
|
259
303
|
{isMultilingual ? (
|
|
@@ -275,6 +319,16 @@ const ConceptForm = ({
|
|
|
275
319
|
/>
|
|
276
320
|
<div className="concept-forms-actions actions">
|
|
277
321
|
<HistoryBackButton content={formatMessage({ id: "actions.cancel" })} />
|
|
322
|
+
{canTranslate ? (
|
|
323
|
+
<Button
|
|
324
|
+
disabled={disableTranslationButton}
|
|
325
|
+
onClick={() => setShowTranslationModal(true)}
|
|
326
|
+
content={formatMessage({
|
|
327
|
+
id: `actions.translate`,
|
|
328
|
+
defaultMessageMessage: "Translate",
|
|
329
|
+
})}
|
|
330
|
+
/>
|
|
331
|
+
) : null}
|
|
278
332
|
<Button
|
|
279
333
|
primary
|
|
280
334
|
disabled={isInvalid}
|
|
@@ -300,12 +354,25 @@ const ConceptForm = ({
|
|
|
300
354
|
</Header>
|
|
301
355
|
);
|
|
302
356
|
|
|
357
|
+
const renderTranslationModal = (
|
|
358
|
+
<TranslationModal
|
|
359
|
+
open={showTranslationModal}
|
|
360
|
+
onClose={() => setShowTranslationModal(false)}
|
|
361
|
+
i18nContent={i18nConcept}
|
|
362
|
+
template={template}
|
|
363
|
+
domainId={domainId}
|
|
364
|
+
resourceType="business_concept"
|
|
365
|
+
setTranslations={setTranslations}
|
|
366
|
+
/>
|
|
367
|
+
);
|
|
368
|
+
|
|
303
369
|
return isMultilingual ? (
|
|
304
370
|
<>
|
|
305
371
|
{renderHeader()}
|
|
306
372
|
<Form loading={Boolean(loading) || Boolean(domainsLoading)}>
|
|
307
373
|
{commonForm}
|
|
308
374
|
</Form>
|
|
375
|
+
{canTranslate ? renderTranslationModal : null}
|
|
309
376
|
</>
|
|
310
377
|
) : (
|
|
311
378
|
<Container as={Segment} text>
|
|
@@ -13,6 +13,7 @@ import ConceptsUploadButton from "./ConceptsUploadButton";
|
|
|
13
13
|
|
|
14
14
|
export const ConceptsActions = ({
|
|
15
15
|
create,
|
|
16
|
+
download,
|
|
16
17
|
conceptsDownloading,
|
|
17
18
|
downloadConcepts,
|
|
18
19
|
upload,
|
|
@@ -24,7 +25,6 @@ export const ConceptsActions = ({
|
|
|
24
25
|
const createUrl = conceptsActions?.create ? CONCEPTS_NEW : null;
|
|
25
26
|
const canAutoPublish = conceptsActions?.autoPublish && true;
|
|
26
27
|
const { formatMessage, locale } = useIntl();
|
|
27
|
-
|
|
28
28
|
return hidden ? null : (
|
|
29
29
|
<div>
|
|
30
30
|
{create && createUrl ? (
|
|
@@ -36,16 +36,19 @@ export const ConceptsActions = ({
|
|
|
36
36
|
content={formatMessage({ id: "concepts.actions.create" })}
|
|
37
37
|
/>
|
|
38
38
|
) : null}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
39
|
+
{create || download ? (
|
|
40
|
+
<Button
|
|
41
|
+
floated="right"
|
|
42
|
+
secondary
|
|
43
|
+
icon="download"
|
|
44
|
+
onClick={() => downloadConcepts({ lang: locale, searchParams })}
|
|
45
|
+
loading={conceptsDownloading}
|
|
46
|
+
data-tooltip={formatMessage({
|
|
47
|
+
id: "concepts.actions.download.tooltip",
|
|
48
|
+
})}
|
|
49
|
+
/>
|
|
50
|
+
) : null}
|
|
51
|
+
|
|
49
52
|
{upload ? <ConceptsUploadButton canAutoPublish={canAutoPublish} /> : null}
|
|
50
53
|
{update ? <ConceptsUpdateButton /> : null}
|
|
51
54
|
</div>
|
|
@@ -55,6 +58,7 @@ export const ConceptsActions = ({
|
|
|
55
58
|
ConceptsActions.propTypes = {
|
|
56
59
|
conceptsDownloading: PropTypes.bool,
|
|
57
60
|
create: PropTypes.bool,
|
|
61
|
+
download: PropTypes.bool,
|
|
58
62
|
downloadConcepts: PropTypes.func,
|
|
59
63
|
upload: PropTypes.bool,
|
|
60
64
|
update: PropTypes.bool,
|
|
@@ -18,12 +18,17 @@ import ConceptsLabelResults from "./ConceptsLabelResults";
|
|
|
18
18
|
import ConceptsPagination from "./ConceptsPagination";
|
|
19
19
|
import ConceptsTable from "./ConceptsTable";
|
|
20
20
|
|
|
21
|
-
export function ConceptsPanelContent({
|
|
22
|
-
const { loading } = useSearchContext();
|
|
21
|
+
export function ConceptsPanelContent({ subscope }) {
|
|
22
|
+
const { loading, searchData } = useSearchContext();
|
|
23
|
+
const actions = _.propOr({}, "_actions")(searchData);
|
|
24
|
+
const download = (actions) =>
|
|
25
|
+
"downloadPublishedConcepts" in actions ||
|
|
26
|
+
"downloadDeprecatedConcepts" in actions ||
|
|
27
|
+
"downloadDraftConcepts" in actions;
|
|
23
28
|
|
|
24
29
|
return (
|
|
25
30
|
<>
|
|
26
|
-
<ConceptsActions {...actions} />
|
|
31
|
+
<ConceptsActions {...actions} download={download(actions)} />
|
|
27
32
|
<SearchWidget />
|
|
28
33
|
<Dimmer.Dimmable dimmed={loading}>
|
|
29
34
|
<Dimmer active={loading} inverted>
|
|
@@ -1,10 +1,34 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
+
import { act } from "react-dom/test-utils";
|
|
2
3
|
import { render } from "@truedat/test/render";
|
|
3
4
|
import { waitFor } from "@testing-library/react";
|
|
4
5
|
import { LangProviderWrapper } from "@truedat/core/i18n";
|
|
5
6
|
import ConceptEdit from "../ConceptEdit";
|
|
6
7
|
|
|
7
|
-
|
|
8
|
+
jest.mock("@truedat/ai/hooks/useTranslations", () => {
|
|
9
|
+
const originalModule = jest.requireActual(
|
|
10
|
+
"@truedat/ai/hooks/useTranslations"
|
|
11
|
+
);
|
|
12
|
+
|
|
13
|
+
return {
|
|
14
|
+
__esModule: true,
|
|
15
|
+
...originalModule,
|
|
16
|
+
useAvailabilityCheck: () => ({
|
|
17
|
+
trigger: jest.fn(
|
|
18
|
+
() =>
|
|
19
|
+
new Promise(() => ({
|
|
20
|
+
data: {
|
|
21
|
+
data: {
|
|
22
|
+
status: "ok",
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
}))
|
|
26
|
+
),
|
|
27
|
+
}),
|
|
28
|
+
};
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const template = {
|
|
8
32
|
id: 1,
|
|
9
33
|
name: "template1",
|
|
10
34
|
label: "template1",
|
|
@@ -30,7 +54,7 @@ const template1 = {
|
|
|
30
54
|
jest.mock("@truedat/core/hooks", () => ({
|
|
31
55
|
useTemplate: jest.fn(() => ({
|
|
32
56
|
loading: false,
|
|
33
|
-
data: { template
|
|
57
|
+
data: { template },
|
|
34
58
|
})),
|
|
35
59
|
}));
|
|
36
60
|
|
|
@@ -99,6 +123,7 @@ describe("<ConceptEdit />", () => {
|
|
|
99
123
|
};
|
|
100
124
|
it("matches the latest snapshot", async () => {
|
|
101
125
|
const { container, queryByText } = renderComponent(props);
|
|
126
|
+
|
|
102
127
|
await waitFor(() => expect(queryByText(/foo_user/i)).toBeInTheDocument());
|
|
103
128
|
expect(container).toMatchSnapshot();
|
|
104
129
|
});
|
|
@@ -25,6 +25,13 @@ jest.mock("@truedat/ai/hooks/useSuggestions", () => {
|
|
|
25
25
|
};
|
|
26
26
|
});
|
|
27
27
|
|
|
28
|
+
jest.mock("@truedat/ai/hooks/useTranslations", () => ({
|
|
29
|
+
useAvailabilityCheck: jest.fn(() => ({
|
|
30
|
+
reason: null,
|
|
31
|
+
status: "ok",
|
|
32
|
+
})),
|
|
33
|
+
}));
|
|
34
|
+
|
|
28
35
|
const props = {
|
|
29
36
|
actionKey: "create",
|
|
30
37
|
domainId: 1,
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import userEvent from "@testing-library/user-event";
|
|
3
|
-
import { fireEvent } from "@testing-library/react";
|
|
4
|
-
import { waitFor } from "@testing-library/react";
|
|
3
|
+
import { fireEvent, waitFor } from "@testing-library/react";
|
|
5
4
|
import { render } from "@truedat/test/render";
|
|
6
5
|
import { DomainForm } from "../DomainForm";
|
|
7
6
|
import { useDomains } from "../../../hooks/useDomains";
|