l-min-components 1.0.879 → 1.0.883

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": "l-min-components",
3
- "version": "1.0.879",
3
+ "version": "1.0.883",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "src/assets",
@@ -27,7 +27,6 @@ import useHeader from "../header/getHeaderDetails";
27
27
  import GracePeriod from "../deactivated";
28
28
  import MobileLayout from "../mobileLayout";
29
29
  import useTranslation from "../../hooks/useTranslation";
30
- import { preLoadWords } from "../../hooks/utils/translation";
31
30
 
32
31
  const AppMainLayout = () => {
33
32
  const [isOpen, setIsOpen] = useState(true);
@@ -98,11 +97,6 @@ const AppMainLayout = () => {
98
97
  // set access token from cookie to context
99
98
 
100
99
  useEffect(() => {
101
- try {
102
- preLoadWords();
103
- } catch (err) {
104
- console.error("Error preloading translations::", err);
105
- }
106
100
 
107
101
  let cookieValue = null;
108
102
  const cookieName = "access";
@@ -157,26 +151,38 @@ const AppMainLayout = () => {
157
151
  const currentPlan = userPlanData?.data?.current_plan;
158
152
  const planState = userPlanData?.data?.state;
159
153
 
154
+ const wordBank = [
155
+ "Sign Out",
156
+ "Learning",
157
+ "Community",
158
+ "Fun",
159
+ "Duet",
160
+ "Speech",
161
+ "Settings",
162
+ "Notifications",
163
+ "Hello",
164
+ "API",
165
+ "Documentation",
166
+ "Report",
167
+ "Created",
168
+ "Report",
169
+ ];
170
+
160
171
  const {
161
- textSchema,
162
172
  setDefaultLang,
163
173
  defaultLang,
164
174
  findText,
165
- isLoading,
166
- setIsLoading,
167
- textSchemaLoading
168
- } = useTranslation();
169
- // //console.log(findText());
175
+ translateData,
176
+ isTranslationsComplete
177
+ } = useTranslation(wordBank);
178
+
170
179
  return (
171
- !textSchemaLoading && (
180
+ !translateData?.loading && !isTranslationsComplete && (
172
181
  <OutletContext.Provider
173
182
  value={{
174
- textSchema,
175
183
  findText,
176
184
  defaultLang,
177
185
  setDefaultLang,
178
- isLoading,
179
- setIsLoading,
180
186
  setRightComponent,
181
187
  setRightLayout,
182
188
  generalData,
@@ -11,10 +11,9 @@ import { FaArrowRight } from "react-icons/fa";
11
11
  import useTranslation from "../../hooks/useTranslation";
12
12
 
13
13
  const Banner = () => {
14
- const { textSchema, findText } = useTranslation();
14
+ const { findText } = useTranslation();
15
15
 
16
16
  return (
17
- textSchema && (
18
17
  <BannerWrapper>
19
18
  <BannerTitle>
20
19
  {" "}
@@ -39,7 +38,6 @@ const Banner = () => {
39
38
  }}
40
39
  />
41
40
  </BannerWrapper>
42
- )
43
41
  );
44
42
  };
45
43
 
@@ -20,7 +20,7 @@ import useTranslation from "../../hooks/useTranslation";
20
20
  *
21
21
  */
22
22
  const ButtonComponent = (props) => {
23
- const { textSchema, findText } = useTranslation();
23
+ const { findText } = useTranslation();
24
24
 
25
25
  const handleClick = useCallback((e) => {
26
26
  props.onClick && props.onClick(e);
@@ -29,7 +29,6 @@ const ButtonComponent = (props) => {
29
29
  switch (props.type) {
30
30
  case "primary":
31
31
  return (
32
- textSchema && (
33
32
  <Button
34
33
  disabled={props.disabled}
35
34
  onClick={handleClick}
@@ -75,10 +74,8 @@ const ButtonComponent = (props) => {
75
74
  )}
76
75
  </Button>
77
76
  )
78
- );
79
77
  case "secondary":
80
78
  return (
81
- textSchema && (
82
79
  <SecondaryButton
83
80
  disabled={props.disabled}
84
81
  onClick={handleClick}
@@ -123,7 +120,6 @@ const ButtonComponent = (props) => {
123
120
  )
124
121
  )}
125
122
  </SecondaryButton>
126
- )
127
123
  );
128
124
  case "tertiary":
129
125
  return (
@@ -174,7 +170,6 @@ const ButtonComponent = (props) => {
174
170
  );
175
171
  default:
176
172
  return (
177
- textSchema && (
178
173
  <Button
179
174
  disabled={props.disabled}
180
175
  onClick={handleClick}
@@ -219,7 +214,6 @@ const ButtonComponent = (props) => {
219
214
  )
220
215
  )}
221
216
  </Button>
222
- )
223
217
  );
224
218
  }
225
219
  };
@@ -81,10 +81,9 @@ const DropDownComponent = (props) => {
81
81
  }
82
82
  }, [props.dropdownData]);
83
83
 
84
- const { textSchema, findText } = useTranslation();
84
+ const { findText } = useTranslation();
85
85
 
86
86
  return (
87
- textSchema && (
88
87
  <DropDownContainer
89
88
  className={props?.className}
90
89
  ref={dropdownRef}
@@ -165,7 +164,6 @@ const DropDownComponent = (props) => {
165
164
  )}
166
165
  </DropDownControls>
167
166
  </DropDownContainer>
168
- )
169
167
  );
170
168
  };
171
169
  export default DropDownComponent;
@@ -26,7 +26,7 @@ import LanguageDropdown from "./languageDropdown";
26
26
  import { getCookie } from "./getCookies";
27
27
  // import { data } from "../GraphMap/data";
28
28
  import { languagesData } from "./languages";
29
- import loadTranslations, { preLoadWords } from "../../hooks/utils/translation";
29
+ import useTranslation from "../../hooks/useTranslation";
30
30
  /**
31
31
  * @param {{
32
32
  * type: string,
@@ -67,14 +67,26 @@ const HeaderComponent = (props) => {
67
67
  setGeneralData,
68
68
  generalData,
69
69
  notificationMarkReadData,
70
- findText,
71
- defaultLang,
72
- isLoading,
73
- setIsLoading,
74
- setDefaultLang
75
70
  } = useContext(OutletContext);
76
71
  const [selectedAccount, setSelectedAccount] = useState();
77
72
  const { setDefaultAccount, handleSetDefaultAccount } = useHeader();
73
+ const wordBank = [
74
+ "Sign Out",
75
+ "Learning",
76
+ "Community",
77
+ "Fun",
78
+ "Duet",
79
+ "Speech",
80
+ "Settings",
81
+ "Notifications",
82
+ "Hello",
83
+ "API",
84
+ "Documentation",
85
+ "Report",
86
+ "Created",
87
+ "Report",
88
+ ];
89
+ const { findText, translateData, defaultLang, setDefaultLang } = useTranslation(wordBank);
78
90
 
79
91
  useEffect(() => {
80
92
  setIsOpen(false);
@@ -402,7 +414,7 @@ const HeaderComponent = (props) => {
402
414
 
403
415
  return (
404
416
  <Navbar>
405
- {isLoading && <FullPageLoader hasBackground={true} />}
417
+ {translateData?.loading && <FullPageLoader hasBackground={true} />}
406
418
 
407
419
  <img src={logo} alt="Learngual logo" />
408
420
  <Nav
@@ -1,7 +1,7 @@
1
1
  import React, { useState, useEffect, useRef, useContext } from "react";
2
2
  import ReactFlagsSelect from "react-flags-select";
3
3
  import useHeader from "./getHeaderDetails";
4
- import { OutletContext } from "..";
4
+ import { OutletContext, useTranslation } from "..";
5
5
  import { useLocation } from "react-router-dom";
6
6
  import usFlag from "../../assets/images/usFlag.png";
7
7
  import koreanFlag from "../../assets/images/koreaFlag.png";
@@ -24,11 +24,6 @@ const LanguageDropdown = ({ languageDropdown, setLanguageDropdown }) => {
24
24
  const {
25
25
  setGeneralData,
26
26
  generalData,
27
- defaultLang,
28
- setDefaultLang,
29
- findText,
30
- isLoading,
31
- setIsLoading,
32
27
  } = useContext(OutletContext);
33
28
  const {
34
29
  retrieveUserDetailsData,
@@ -36,6 +31,7 @@ const LanguageDropdown = ({ languageDropdown, setLanguageDropdown }) => {
36
31
  updateUserAccountData,
37
32
  handleUpdateUserAccount,
38
33
  } = useHeader();
34
+ const { findText, translateData, defaultLang, setDefaultLang, handleTranslate, wordsToTranslate } = useTranslation();
39
35
 
40
36
  const languagesData = [
41
37
  {
@@ -96,9 +92,10 @@ const LanguageDropdown = ({ languageDropdown, setLanguageDropdown }) => {
96
92
  }
97
93
  setLanguageDropdown();
98
94
  setDefaultLang(item?.slug);
99
- item?.slug === defaultLang
100
- ? setIsLoading(false)
101
- : setIsLoading(true);
95
+ handleTranslate(item?.slug, wordsToTranslate)
96
+ // item?.slug === defaultLang
97
+ // ? setIsLoading(false)
98
+ // : setIsLoading(true);
102
99
  localStorage.setItem("defaultLang", JSON.stringify(item));
103
100
  console.log("general id", generalData?.defaultAccount?.id)
104
101
 
@@ -51,6 +51,5 @@ export { default as AdminRolesPermissions } from "./AdminRolesPermission";
51
51
  export { default as AdminCreateRolesPermissions } from "./AdminRolesPermission/create";
52
52
  export { default as MobileLayout } from "./mobileLayout";
53
53
  export { default as useTranslation } from "../hooks/useTranslation";
54
- export { default as preLoadWords } from "../hooks/utils/translation";
55
54
  export { default as ImageComponent } from "./ImageComponent";
56
55
 
@@ -18,7 +18,7 @@ import useTranslation from "../../hooks/useTranslation";
18
18
  const InputComponent = (props) => {
19
19
  const [value, setValue] = useState("");
20
20
  const [formErrors, setFormErrors] = useState(false);
21
- const { textSchema, findText } = useTranslation();
21
+ const { findText } = useTranslation();
22
22
 
23
23
  const validate = (e) => {
24
24
  if (!e.target.value) {
@@ -37,7 +37,6 @@ const InputComponent = (props) => {
37
37
  };
38
38
 
39
39
  return (
40
- textSchema && (
41
40
  <div style={props.style}>
42
41
  <Label htmlFor={props.in} style={props.customLabelStyle}>
43
42
  {findText(props.label)}
@@ -65,7 +64,6 @@ const InputComponent = (props) => {
65
64
  </ErrorMsg>
66
65
  )}
67
66
  </div>
68
- )
69
67
  );
70
68
  };
71
69
 
@@ -23,9 +23,8 @@ const Radio = ({
23
23
  setValue(newValue);
24
24
  onChange && onChange(newValue);
25
25
  };
26
- const { textSchema, findText } = useTranslation();
26
+ const { findText } = useTranslation();
27
27
  return (
28
- textSchema &&
29
28
  <Container direction={direction} {...props}>
30
29
  {options.map((option) => (
31
30
  <RadioWrapper key={option.value}>
@@ -15,6 +15,7 @@ import cx from "classnames";
15
15
  import InstructorRightBar from "../../fileRightBar/instructorRightBar";
16
16
  import EnterpriseRightBar from "../../fileRightBar/enterpriseRightBar";
17
17
  import { OutletContext } from "../../AppMainLayout";
18
+ import useTranslation from "../../../hooks/useTranslation";
18
19
 
19
20
  const SideMenu = ({
20
21
  user,
@@ -31,7 +32,8 @@ const SideMenu = ({
31
32
  // const [isOpen, setIsOpen] = useState(false);
32
33
  const [gracePeriod, setGracePeriod] = useState(true);
33
34
 
34
- const { setGeneralData, generalData, findText } = useContext(OutletContext);
35
+ const { setGeneralData, generalData } = useContext(OutletContext);
36
+ const { findText } = useTranslation();
35
37
  const onToggle = () => {
36
38
  setIsOpen(!isOpen);
37
39
  };
@@ -11,12 +11,14 @@ import useHeader from "../../header/getHeaderDetails";
11
11
  import Loader from "../../loader";
12
12
  import avatar from "../../../assets/images/avatar.png";
13
13
  import { OutletContext } from "../../AppMainLayout";
14
+ import useTranslation from "../../../hooks/useTranslation";
14
15
 
15
16
  const UserCard = ({ user, isOpen }) => {
16
17
  const { handleGetUserDetails, userDetails, handleSetDefaultAccount } =
17
18
  useHeader();
18
19
  const [organizationName, setOrganizationName] = useState();
19
- const { generalData, findText } = useContext(OutletContext);
20
+ const { generalData } = useContext(OutletContext);
21
+ const { findText } = useTranslation();
20
22
  useEffect(() => {
21
23
  handleGetUserDetails();
22
24
  if (generalData?.selectedAccount) {
@@ -11,9 +11,10 @@ import LogoutIcon from "./svg/logout";
11
11
  // import deleteCookies from "../../utils/deleteCookies";
12
12
  import Cookies from "js-cookie";
13
13
  import { OutletContext } from "../AppMainLayout";
14
+ import useTranslation from "../../hooks/useTranslation";
14
15
 
15
16
  const SideBar = ({ routes }) => {
16
- const { findText } = useContext(OutletContext);
17
+ const { findText } = useTranslation();
17
18
 
18
19
  const deleteCookies = (name) => {
19
20
  const date = new Date();
@@ -1,82 +1,108 @@
1
- import React, { useCallback, useContext, useEffect, useState } from "react";
2
- import loadTranslations from "./utils/translation";
3
- import { db } from "./utils/db";
4
- import { useLiveQuery } from "dexie-react-hooks";
5
- import { OutletContext } from "../components";
1
+ import React, { useCallback, useEffect, useState } from "react";
2
+ import useAxios from "axios-hooks";
6
3
 
7
- const useTranslation = () => {
8
- const screenId = btoa(window.location.href);
4
+ const useTranslation = (initialSentences = []) => {
9
5
  const value = JSON?.parse(localStorage.getItem("defaultLang"));
10
- const { generalData } = useContext(OutletContext);
11
6
 
12
7
  const [defaultLang, setDefaultLang] = useState(value?.slug ?? "en");
13
- const [isLoading, setIsLoading] = useState(false);
14
- const [textSchemaLoading, setTextSchemaLoading] = useState(true);
8
+ const [translations, setTranslations] = useState({}); // returned translation from backend
9
+ const [wordsToTranslate, setWordsToTranslate] = useState([]); // sent translations to backend
10
+ const isTranslationsComplete = Object.keys(translations)?.length === 0;
15
11
 
16
- /**
17
- * @type {{key: string; value: string; updatedAt: string; screenId: string}[]}
18
- */
19
- const textSchema =
20
- useLiveQuery(
21
- async () => db[defaultLang?.toLowerCase()]?.toArray(),
22
- [defaultLang]
23
- ) ?? [];
24
-
25
- useEffect(() => {
26
- if (textSchema.length) {
27
- setTextSchemaLoading(false); // textSchema has been loaded, so stop loading
12
+ const findText = useCallback(
13
+ (word, kwargs = {}) => {
14
+ // Check if the word is not already translated and not already in the list to avoid duplicates
15
+ if (!translations[word] && !wordsToTranslate.includes(word)) {
16
+ setWordsToTranslate((prevWords) => {
17
+ // Ensure the word is only added if it's not already in the list
18
+ if (!prevWords.includes(word)) {
19
+ return [...prevWords, word];
20
+ }
21
+ return prevWords;
22
+ });
28
23
  }
29
- }, [textSchema]);
24
+ return formatSentence(translations[word] || word, kwargs); // Return translated word or original word if not yet translated
25
+ },
26
+ [translations, wordsToTranslate]
27
+ );
30
28
 
31
- const findText = useCallback(
32
- (str, kwarg = {}) => {
33
- if (!str) return "";
34
- // add text to db if not exist
35
- db.words.add({
36
- text: str,
37
- screenId,
38
- updatedAt: new Date().toDateString(),
29
+ // api request for sending data to backend
30
+ const [{ ...translateData }, translate] = useAxios(
31
+ {
32
+ method: "POST",
33
+ },
34
+ {
35
+ manual: true,
36
+ }
37
+ );
38
+
39
+ const handleTranslate = async (language, words) => {
40
+ try {
41
+ await translate({
42
+ url: `/iam/v1/utils/translate/`,
43
+ data: {
44
+ language,
45
+ sentences: words,
46
+ // kwargs,
47
+ },
48
+ params: {},
39
49
  });
50
+ } catch (err) {
51
+ console.log(err);
52
+ }
53
+ };
40
54
 
41
- if (Object.keys(kwarg).length) {
42
- db.kwarg.bulkPut(
43
- Object.keys(kwarg).map((x) => ({ key: x, value: kwarg[x], screenId }))
44
- );
45
- }
46
- const schema = textSchema?.reduce(
47
- (x, y) => ({ ...x, [y.key]: y.value }),
48
- {}
55
+ useEffect(() => {
56
+ if (initialSentences.length > 0) {
57
+ // Add initial sentences while ensuring no duplicates
58
+ const uniqueSentences = initialSentences.filter(
59
+ (word, index) => initialSentences.indexOf(word) === index
49
60
  );
50
- if (schema[str]) {
51
- return schema[str];
52
- } else {
53
- return formatSentence(str, kwarg);
54
- }
55
- },
56
- [textSchema, defaultLang]
57
- );
61
+ setWordsToTranslate((prevWords) => [
62
+ ...prevWords,
63
+ ...uniqueSentences.filter((word) => !prevWords.includes(word)),
64
+ ]);
65
+ }
66
+ }, []);
58
67
 
59
68
  useEffect(() => {
60
- loadTranslations(defaultLang, setIsLoading);
61
- }, [defaultLang]);
69
+ if (wordsToTranslate?.length > 0) {
70
+ handleTranslate(defaultLang, wordsToTranslate);
71
+ // setWordsToTranslate([]); // Clear the list after translating
72
+ }
73
+ }, [defaultLang, wordsToTranslate]);
74
+
75
+ useEffect(() => {
76
+ if (translateData?.response) {
77
+
78
+ const newTranslations = {};
79
+ wordsToTranslate.forEach((word, index) => {
80
+ newTranslations[word] = translateData?.data?.result[index];
81
+ });
82
+ setTranslations((prevTranslations) => ({
83
+ ...prevTranslations,
84
+ ...newTranslations,
85
+ }));
86
+ }
87
+ }, [translateData?.response]);
88
+
62
89
 
63
90
  return {
64
- textSchema,
65
- // setTextSchema,
66
- setDefaultLang,
67
91
  defaultLang,
92
+ setDefaultLang,
93
+ translateData,
94
+ handleTranslate,
95
+ translations,
68
96
  findText,
69
- isLoading,
70
- setIsLoading,
71
- textSchemaLoading,
72
- setTextSchemaLoading
97
+ wordsToTranslate,
98
+ isTranslationsComplete,
73
99
  };
74
100
  };
75
101
 
76
102
  export function formatSentence(sentence, kwargs) {
77
103
  // console.log(sentence);
78
104
  // Use replace with a regular expression and a callback function
79
- const finalSentence = sentence.replace(/\{(\w+)\}/g, (match, key) => {
105
+ const finalSentence = sentence?.replace(/\{(\w+)\}/g, (match, key) => {
80
106
  // If the key exists in kwargs, replace it with the corresponding value
81
107
  // Otherwise, keep the original placeholder
82
108
  return kwargs[key] !== undefined ? kwargs[key] : match;
@@ -84,4 +110,5 @@ export function formatSentence(sentence, kwargs) {
84
110
 
85
111
  return finalSentence;
86
112
  }
113
+
87
114
  export default useTranslation;
@@ -1,13 +0,0 @@
1
- import Dexie from "dexie";
2
- import locale from "iso-639-1";
3
- export const db = new Dexie("translations");
4
-
5
- const languages = locale.getAllCodes();
6
- db.version(2).stores({
7
- kwarg: "&key, value, screenId",
8
- ...languages.reduce(
9
- (x, y) => ({ ...x, [y]: "&key, value, screenId, updatedAt" }),
10
- {}
11
- ),
12
- words: "&text, screenId, updatedAt",
13
- });
@@ -1,89 +0,0 @@
1
- import { db } from "./db";
2
- import axios from "./axiosConfig";
3
-
4
- async function loadTranslations(language = "en", setIsLoading) {
5
- await new Promise((resolve) => {
6
- //check if loading else resolve
7
- if (document.readyState === "complete") {
8
- return resolve();
9
- }
10
- window.addEventListener("load", resolve);
11
- });
12
-
13
- const screenId = btoa(window.location.href);
14
-
15
- /**
16
- * @typedef {{text: string; screenId: string; updatedAt: string}} WORDS
17
- * @type {WORDS[]}
18
- */
19
- const words = await db.words.toArray();
20
- const texts = words.map((x) => x.text.trim() !== "" && x.text).filter((x) => x); // list of texts
21
-
22
- /**
23
- * @typedef {{ key: string; value: string; screenId: string }} Kwarg
24
- * @type {Kwarg[]} kwargList
25
- */
26
- const kwargList = await db.kwarg.where({ screenId }).toArray();
27
- const kwargs = kwargList.reduce((x, t) => ({ ...x, [t.key]: t.value }), {});
28
- /**
29
- * @type {{ data: {has_translated: boolean; result: string[]} }}
30
- */
31
-
32
- try {
33
- const res = await axios({
34
- url: "/iam/v1/utils/translate/",
35
- method: "POST",
36
- data: {
37
- language,
38
- sentences: texts,
39
- kwargs,
40
- },
41
- // params: {},
42
- });
43
- // build an object using texts as key and results from request as value
44
- if (!res.data) return {}; // somehow data was not found
45
- const translations = texts.reduce(
46
- (x, y, z) => ({ ...x, [y]: res.data.result[z] }),
47
- {}
48
- );
49
- db[language].bulkPut(
50
- Object.keys(translations).map((x, i) => ({
51
- key: texts[i],
52
- value: translations[x],
53
- screenId,
54
- updatedAt: new Date().toDateString(),
55
- }))
56
- );
57
-
58
- return translations;
59
- } catch (error) {
60
- console.error("clg Error fetching data:", error);
61
- } finally {
62
- setIsLoading(false);
63
- }
64
- }
65
-
66
- export function extractBracedText(text) {
67
- const pattern = /\{([^}]+)\}/g; // Match all occurrences of text within {}
68
- const matches = text.match(pattern);
69
- return matches ? matches.map((match) => match.slice(1, -1)) : []; // Remove braces
70
- }
71
-
72
- export async function preLoadWords(cb) {
73
- const screenId = btoa(window.location.href);
74
- const updatedAt = new Date().toDateString();
75
- const response = await axios({
76
- url: "iam/v1/utils/translations/",
77
- });
78
- /**
79
- * @type {{[key: string]: string }}
80
- */
81
- const data = response.data;
82
- db.words.bulkPut(
83
- Object?.keys(data).map((x) => ({ text: x, screenId, updatedAt }))
84
- );
85
- if (typeof cb === "function") cb(data);
86
- return true;
87
- }
88
-
89
- export default loadTranslations;