@truedat/bg 7.3.3 → 7.3.4

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.3.3",
3
+ "version": "7.3.4",
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.3.3",
37
+ "@truedat/test": "7.3.4",
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.3.3",
90
- "@truedat/df": "7.3.3",
91
- "@truedat/lm": "7.3.3",
89
+ "@truedat/core": "7.3.4",
90
+ "@truedat/df": "7.3.4",
91
+ "@truedat/lm": "7.3.4",
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": "23b3cc6b8c2749a173f779390866b715d653d377"
114
+ "gitHead": "681c0d026b5477fadf9b53fe5242cfb0ed11d973"
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>
@@ -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
- const template1 = {
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: template1 },
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";