@nualang/nualang-ui-components 0.1.1340 → 0.1.1350
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/dist/Dialogs/CreatePhrase/CreatePhrase.js +291 -186
- package/dist/Dialogs/GeneratePhrases/GeneratePhrases.js +51 -11
- package/dist/Editors/Phrases/Phrases.js +2 -1
- package/dist/Forms/InputHelper/InputHelper.js +49 -20
- package/dist/Lists/Phrases/Phrases.js +136 -11
- package/dist/Screens/Classrooms/Classrooms.js +1 -0
- package/dist/Screens/Classrooms/ViewClassroom/ViewClassroom.js +1 -0
- package/dist/Screens/Courses/ViewCourse/ViewTopic/ViewTopic.js +1 -0
- package/package.json +1 -1
|
@@ -15,8 +15,10 @@ import CircularProgress from "@mui/material/CircularProgress";
|
|
|
15
15
|
import HelpIcon from "@mui/icons-material/Help";
|
|
16
16
|
import AutoFixHighIcon from "@mui/icons-material/AutoFixHigh";
|
|
17
17
|
import { removeAllSymbols, localeCompare } from "../../utils/index";
|
|
18
|
+
import LinearProgress from "@mui/material/LinearProgress";
|
|
18
19
|
// components
|
|
19
20
|
import ResponsiveDialog from "../ResponsiveDialog/ResponsiveDialog";
|
|
21
|
+
import NualaCreating from "../../Misc/NualaCreating/NualaCreating";
|
|
20
22
|
import { capitalize } from "../../utils/index";
|
|
21
23
|
import InputHelper from "../../Forms/InputHelper/InputHelper";
|
|
22
24
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
@@ -42,13 +44,10 @@ function CreatePhrase({
|
|
|
42
44
|
open,
|
|
43
45
|
handleClose,
|
|
44
46
|
handleTranslate,
|
|
45
|
-
submitText,
|
|
46
|
-
dialogTitle,
|
|
47
47
|
learnLang = "",
|
|
48
48
|
forLang = "",
|
|
49
49
|
onSubmit,
|
|
50
50
|
update = false,
|
|
51
|
-
handleChange,
|
|
52
51
|
image = "",
|
|
53
52
|
forLangCharacters,
|
|
54
53
|
learnLangCharacters,
|
|
@@ -76,11 +75,52 @@ function CreatePhrase({
|
|
|
76
75
|
const [englishTranslation, setEnglishTranslation] = useState("");
|
|
77
76
|
const [autoSuggestedImages, setAutoSuggestedImages] = useState([]);
|
|
78
77
|
const [translationList, setTranslationList] = useState(otherProps.translations || []);
|
|
78
|
+
const [definition, setDefinition] = useState("");
|
|
79
|
+
const [definitionList, setDefinitionList] = useState(otherProps.definitions || []);
|
|
79
80
|
const [autoTranslatedText, setAutoTranslatedText] = useState(false);
|
|
80
81
|
const [checkingRecogniton, setCheckingRecogniton] = useState(false);
|
|
81
82
|
const [recognised, setRecognised] = useState(false);
|
|
82
83
|
const [notRecognised, setNotRecognised] = useState(false);
|
|
83
84
|
const [recognisedPhrase, setRecognisedPhrase] = useState("");
|
|
85
|
+
|
|
86
|
+
// Keep definitionList in sync when editing an existing phrase in update mode
|
|
87
|
+
// (e.g. switching between different phrases while dialog stays mounted)
|
|
88
|
+
useEffect(() => {
|
|
89
|
+
setDefinitionList(otherProps.definitions || []);
|
|
90
|
+
}, [otherProps.definitions, otherProps.definition, open]);
|
|
91
|
+
const handleEditDefinition = (event, index) => {
|
|
92
|
+
const {
|
|
93
|
+
target: {
|
|
94
|
+
value
|
|
95
|
+
}
|
|
96
|
+
} = event;
|
|
97
|
+
const tempArray = definitionList.slice();
|
|
98
|
+
tempArray[index] = value;
|
|
99
|
+
setDefinitionList([...tempArray]);
|
|
100
|
+
};
|
|
101
|
+
useEffect(() => {
|
|
102
|
+
if (open) {
|
|
103
|
+
setPhrase(otherProps.phrase || "");
|
|
104
|
+
setAlternativeVersions(otherProps.alternativeVersions || []);
|
|
105
|
+
setTranslationList(otherProps.translations || []);
|
|
106
|
+
setDefinitionList(otherProps.definitions || []);
|
|
107
|
+
setSelectedImage({
|
|
108
|
+
image: image || "",
|
|
109
|
+
imageSelectionMethod: "default_image"
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
}, [open, otherProps.phrase, otherProps.alternativeVersions, otherProps.translations, otherProps.definitions, image]);
|
|
113
|
+
const handleAddDefinition = () => {
|
|
114
|
+
setDefinitionList(prev => {
|
|
115
|
+
const trimmed = definition ? definition.trim() : "";
|
|
116
|
+
if (trimmed && !prev.includes(trimmed)) return [...prev, trimmed];
|
|
117
|
+
return prev;
|
|
118
|
+
});
|
|
119
|
+
setDefinition("");
|
|
120
|
+
};
|
|
121
|
+
const handleRemoveDefinition = index => {
|
|
122
|
+
setDefinitionList(prev => prev.filter((_, i) => i !== index));
|
|
123
|
+
};
|
|
84
124
|
const checkIsPronunciationCorrect = (finalTranscript, alternativeTranscripts, alternativeVersions) => {
|
|
85
125
|
let stringMatch;
|
|
86
126
|
if (alternativeTranscripts && alternativeTranscripts.length > 0) {
|
|
@@ -179,6 +219,13 @@ function CreatePhrase({
|
|
|
179
219
|
});
|
|
180
220
|
}
|
|
181
221
|
}, [image]);
|
|
222
|
+
|
|
223
|
+
// reset form state whenever the dialog is closed
|
|
224
|
+
useEffect(() => {
|
|
225
|
+
if (!open) {
|
|
226
|
+
resetPhraseState();
|
|
227
|
+
}
|
|
228
|
+
}, [open]);
|
|
182
229
|
const handleEditAlternative = (event, index) => {
|
|
183
230
|
const {
|
|
184
231
|
target: {
|
|
@@ -199,21 +246,6 @@ function CreatePhrase({
|
|
|
199
246
|
const handleRemoveAlternative = index => {
|
|
200
247
|
setAlternativeVersions(prevAlternativeVersions => prevAlternativeVersions.filter((t, i) => i !== index));
|
|
201
248
|
};
|
|
202
|
-
|
|
203
|
-
// // translation
|
|
204
|
-
// const generateTranslations = async () => {
|
|
205
|
-
// const translatedText = await handleTranslate(phrase, learnLang, forLang);
|
|
206
|
-
// if (translatedText && translatedText !== "") {
|
|
207
|
-
// setAutoTranslatedText(translatedText);
|
|
208
|
-
// setTranslationList((prevTranslationList) => {
|
|
209
|
-
// if (!prevTranslationList.includes(translatedText)) {
|
|
210
|
-
// return [...prevTranslationList, translatedText];
|
|
211
|
-
// }
|
|
212
|
-
// return prevTranslationList;
|
|
213
|
-
// });
|
|
214
|
-
// }
|
|
215
|
-
// };
|
|
216
|
-
|
|
217
249
|
function validateResponse(response) {
|
|
218
250
|
if (!Array.isArray(response)) {
|
|
219
251
|
return false;
|
|
@@ -230,6 +262,7 @@ function CreatePhrase({
|
|
|
230
262
|
}
|
|
231
263
|
const generateTranslations = async () => {
|
|
232
264
|
try {
|
|
265
|
+
setIsSubmitting(true);
|
|
233
266
|
let chatGptResponse = await makeChatGptApiRequest({
|
|
234
267
|
model: "gpt-4o",
|
|
235
268
|
promptKey: "generateTranslations",
|
|
@@ -257,8 +290,7 @@ function CreatePhrase({
|
|
|
257
290
|
const handleEditTranslation = (event, index) => {
|
|
258
291
|
const {
|
|
259
292
|
target: {
|
|
260
|
-
value
|
|
261
|
-
dataset
|
|
293
|
+
value
|
|
262
294
|
}
|
|
263
295
|
} = event;
|
|
264
296
|
const tempArray = translationList.slice();
|
|
@@ -267,15 +299,16 @@ function CreatePhrase({
|
|
|
267
299
|
};
|
|
268
300
|
const handleAddTranslation = () => {
|
|
269
301
|
setTranslationList(prevTranslationList => {
|
|
270
|
-
|
|
271
|
-
|
|
302
|
+
const trimmed = translation ? translation.trim() : "";
|
|
303
|
+
if (trimmed && !prevTranslationList.includes(trimmed)) {
|
|
304
|
+
return [...prevTranslationList, trimmed];
|
|
272
305
|
}
|
|
273
306
|
return prevTranslationList;
|
|
274
307
|
});
|
|
275
308
|
setTranslation("");
|
|
276
309
|
};
|
|
277
310
|
const handleRemoveTranslation = index => {
|
|
278
|
-
setTranslationList(prevTranslationList => prevTranslationList.filter((
|
|
311
|
+
setTranslationList(prevTranslationList => prevTranslationList.filter((_, i) => i !== index));
|
|
279
312
|
};
|
|
280
313
|
const resetPhraseState = () => {
|
|
281
314
|
setPhrase("");
|
|
@@ -283,6 +316,8 @@ function CreatePhrase({
|
|
|
283
316
|
setAlternativeVersions([]);
|
|
284
317
|
setTranslation("");
|
|
285
318
|
setTranslationList([]);
|
|
319
|
+
setDefinition("");
|
|
320
|
+
setDefinitionList([]);
|
|
286
321
|
setSelectedImage(initialSelectedImagestate);
|
|
287
322
|
setAutoTranslatedText("");
|
|
288
323
|
};
|
|
@@ -296,16 +331,26 @@ function CreatePhrase({
|
|
|
296
331
|
const finalTranslation = translation ? translation.trim() : "";
|
|
297
332
|
let finalTranslationList = translationList;
|
|
298
333
|
let finalAlternativeVersionsList = alternativeVersions.filter(str => str.replace(/\s/g, "").length);
|
|
334
|
+
|
|
299
335
|
// If a user has entered the translation but hasn't clicked the button, add it to the list
|
|
300
336
|
if (finalTranslation !== "" && !finalTranslationList.includes(finalTranslation)) {
|
|
301
337
|
finalTranslationList = [...finalTranslationList, finalTranslation];
|
|
302
338
|
}
|
|
339
|
+
|
|
303
340
|
// Same idea for the alternative versions
|
|
304
341
|
if (alternativeVersion !== "" && !finalAlternativeVersionsList.includes(alternativeVersion)) {
|
|
305
342
|
finalAlternativeVersionsList = [...finalAlternativeVersionsList, alternativeVersion];
|
|
306
343
|
}
|
|
344
|
+
|
|
345
|
+
// Definitions: add pending input if not submitted via Enter
|
|
346
|
+
let finalDefinitionList = definitionList;
|
|
347
|
+
const finalDefinitionInput = definition ? definition.trim() : "";
|
|
348
|
+
if (finalDefinitionInput !== "" && !finalDefinitionList.includes(finalDefinitionInput)) {
|
|
349
|
+
finalDefinitionList = [...finalDefinitionList, finalDefinitionInput];
|
|
350
|
+
}
|
|
307
351
|
const response = await onSubmit({
|
|
308
352
|
phrase: phrase.trim(),
|
|
353
|
+
definitions: finalDefinitionList,
|
|
309
354
|
translations: finalTranslationList,
|
|
310
355
|
alternativeVersions: finalAlternativeVersionsList,
|
|
311
356
|
image: selectedImage.image,
|
|
@@ -376,123 +421,148 @@ function CreatePhrase({
|
|
|
376
421
|
submitText: title,
|
|
377
422
|
dialogTitle: title,
|
|
378
423
|
isSubmitDisabled: isSubmitting,
|
|
379
|
-
children: [/*#__PURE__*/
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
value: phrase,
|
|
384
|
-
onChange: e => {
|
|
385
|
-
setPhrase(e.target.value);
|
|
386
|
-
if (notRecognised || recognised) {
|
|
387
|
-
setNotRecognised(false);
|
|
388
|
-
setRecognised(false);
|
|
389
|
-
}
|
|
390
|
-
},
|
|
391
|
-
onKeyDown: e => {
|
|
392
|
-
if (e.key === "Enter" && translationInputRef && translationInputRef.current) {
|
|
393
|
-
translationInputRef.current.focus();
|
|
394
|
-
}
|
|
424
|
+
children: [/*#__PURE__*/_jsxs(Grid, {
|
|
425
|
+
container: true,
|
|
426
|
+
sx: {
|
|
427
|
+
width: "100%"
|
|
395
428
|
},
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
}),
|
|
403
|
-
type: "text",
|
|
404
|
-
variant: "outlined",
|
|
405
|
-
fullWidth: true,
|
|
406
|
-
characters: learnLangCharacters ? learnLangCharacters : null
|
|
407
|
-
}), phrase && phrase.trim() !== "" && /*#__PURE__*/_jsxs(_Fragment, {
|
|
408
|
-
children: [/*#__PURE__*/_jsx(Tooltip, {
|
|
409
|
-
title: t(`add_alternative_version_explanation`),
|
|
410
|
-
classes: {
|
|
411
|
-
tooltip: classes.tooltip
|
|
429
|
+
children: [/*#__PURE__*/_jsx(Grid, {
|
|
430
|
+
textAlign: "center",
|
|
431
|
+
sx: {
|
|
432
|
+
...(!isSubmitting && {
|
|
433
|
+
display: "none"
|
|
434
|
+
})
|
|
412
435
|
},
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
className: classes.alternativeVersionButton,
|
|
418
|
-
children: t("add_alternative_version")
|
|
419
|
-
})
|
|
420
|
-
}), learnLang !== forLang && /*#__PURE__*/_jsx(DefaultButton, {
|
|
421
|
-
onClick: generateTranslations,
|
|
422
|
-
disabled: !phrase || Array.isArray(translationList) && translationList.includes(autoTranslatedText),
|
|
423
|
-
size: "sm",
|
|
424
|
-
className: classes.alternativeVersionButton,
|
|
425
|
-
startIcon: /*#__PURE__*/_jsx(AutoFixHighIcon, {}),
|
|
426
|
-
children: t("auto_generate_phrase_translation")
|
|
427
|
-
}), learnLang !== forLang && (import.meta.env.REACT_APP_STAGE === "dev" || window.location.host === "localhost:9009") && /*#__PURE__*/_jsx(Box, {
|
|
436
|
+
mx: 2,
|
|
437
|
+
size: 12,
|
|
438
|
+
children: /*#__PURE__*/_jsx(NualaCreating, {})
|
|
439
|
+
}), /*#__PURE__*/_jsx(Grid, {
|
|
428
440
|
sx: {
|
|
429
|
-
|
|
430
|
-
|
|
441
|
+
...(!isSubmitting && {
|
|
442
|
+
display: "none"
|
|
443
|
+
})
|
|
444
|
+
},
|
|
445
|
+
mt: 2,
|
|
446
|
+
size: 12,
|
|
447
|
+
children: /*#__PURE__*/_jsx(LinearProgress, {})
|
|
448
|
+
})]
|
|
449
|
+
}), !isSubmitting && /*#__PURE__*/_jsxs(_Fragment, {
|
|
450
|
+
children: [/*#__PURE__*/_jsx(DialogContentText, {
|
|
451
|
+
children: desc
|
|
452
|
+
}), /*#__PURE__*/_jsx(InputHelper, {
|
|
453
|
+
t: t,
|
|
454
|
+
value: phrase,
|
|
455
|
+
onChange: e => {
|
|
456
|
+
setPhrase(e.target.value);
|
|
457
|
+
if (notRecognised || recognised) {
|
|
458
|
+
setNotRecognised(false);
|
|
459
|
+
setRecognised(false);
|
|
460
|
+
}
|
|
461
|
+
},
|
|
462
|
+
onKeyDown: e => {
|
|
463
|
+
if (e.key === "Enter" && translationInputRef?.current) {
|
|
464
|
+
translationInputRef.current.focus();
|
|
465
|
+
}
|
|
431
466
|
},
|
|
432
|
-
|
|
467
|
+
margin: "normal",
|
|
468
|
+
autoFocus: true,
|
|
469
|
+
id: "phrase",
|
|
470
|
+
name: "phrase",
|
|
471
|
+
label: t("language_phrase", {
|
|
472
|
+
language: capitalize(t(learnLang.toLowerCase()))
|
|
473
|
+
}),
|
|
474
|
+
type: "text",
|
|
475
|
+
variant: "outlined",
|
|
476
|
+
fullWidth: true,
|
|
477
|
+
characters: learnLangCharacters ? learnLangCharacters : null
|
|
478
|
+
}), phrase && phrase.trim() !== "" && /*#__PURE__*/_jsxs(_Fragment, {
|
|
479
|
+
children: [/*#__PURE__*/_jsx(Tooltip, {
|
|
480
|
+
title: t(`add_alternative_version_explanation`),
|
|
481
|
+
classes: {
|
|
482
|
+
tooltip: classes.tooltip
|
|
483
|
+
},
|
|
484
|
+
children: /*#__PURE__*/_jsx(DefaultButton, {
|
|
485
|
+
onClick: () => handleAddAlternative(phrase),
|
|
486
|
+
disabled: !phrase,
|
|
487
|
+
size: "sm",
|
|
488
|
+
className: classes.alternativeVersionButton,
|
|
489
|
+
children: t("add_alternative_version")
|
|
490
|
+
})
|
|
491
|
+
}), learnLang !== forLang && /*#__PURE__*/_jsx(DefaultButton, {
|
|
492
|
+
onClick: generateTranslations,
|
|
493
|
+
disabled: !phrase || Array.isArray(translationList) && translationList.includes(autoTranslatedText),
|
|
494
|
+
size: "sm",
|
|
495
|
+
className: classes.alternativeVersionButton,
|
|
496
|
+
startIcon: /*#__PURE__*/_jsx(AutoFixHighIcon, {}),
|
|
497
|
+
children: t("auto_generate_phrase_translation")
|
|
498
|
+
}), learnLang !== forLang && (import.meta.env.REACT_APP_STAGE === "dev" || window.location.host === "localhost:9009") && /*#__PURE__*/_jsx(Box, {
|
|
433
499
|
sx: {
|
|
434
|
-
|
|
500
|
+
display: "inline-flex",
|
|
501
|
+
alignItems: "center"
|
|
435
502
|
},
|
|
436
|
-
children:
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
recognisedPhrase: `"${recognisedPhrase}"`
|
|
440
|
-
}) : t("speech_recognition_error_info_no_phrase"),
|
|
441
|
-
classes: {
|
|
442
|
-
tooltip: classes.tooltip
|
|
503
|
+
children: /*#__PURE__*/_jsx(Box, {
|
|
504
|
+
sx: {
|
|
505
|
+
position: "relative"
|
|
443
506
|
},
|
|
444
|
-
children: /*#__PURE__*/_jsx(
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
color: "error"
|
|
450
|
-
}),
|
|
451
|
-
disabled: true,
|
|
452
|
-
children: t("phrase_not_recognised")
|
|
453
|
-
})
|
|
454
|
-
})
|
|
455
|
-
}) : /*#__PURE__*/_jsxs(_Fragment, {
|
|
456
|
-
children: [/*#__PURE__*/_jsxs(DefaultButton, {
|
|
457
|
-
size: "sm",
|
|
458
|
-
className: classes.alternativeVersionButton,
|
|
459
|
-
onClick: handleCheckRecognition,
|
|
460
|
-
disabled: checkingRecogniton || recognised || notRecognised,
|
|
461
|
-
startIcon: endIcon,
|
|
462
|
-
children: [recognised ? t("phrase_recognised") : null, checkingRecogniton ? t("checking_recognition") : null, !checkingRecogniton && !recognised && !notRecognised ? t("check_recognition") : null]
|
|
463
|
-
}), !checkingRecogniton && !recognised && !notRecognised ? /*#__PURE__*/_jsx(Tooltip, {
|
|
464
|
-
title: t("speech_recognition_info"),
|
|
507
|
+
children: notRecognised ? /*#__PURE__*/_jsx(Tooltip, {
|
|
508
|
+
title: recognisedPhrase !== "" ? t("speech_recognition_error_info", {
|
|
509
|
+
phrase: `"${phrase}"`,
|
|
510
|
+
recognisedPhrase: `"${recognisedPhrase}"`
|
|
511
|
+
}) : t("speech_recognition_error_info_no_phrase"),
|
|
465
512
|
classes: {
|
|
466
513
|
tooltip: classes.tooltip
|
|
467
514
|
},
|
|
468
|
-
children: /*#__PURE__*/_jsx(
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
515
|
+
children: /*#__PURE__*/_jsx(Box, {
|
|
516
|
+
children: /*#__PURE__*/_jsx(DefaultButton, {
|
|
517
|
+
size: "sm",
|
|
518
|
+
className: classes.alternativeVersionButton,
|
|
519
|
+
startIcon: /*#__PURE__*/_jsx(WarningIcon, {
|
|
520
|
+
color: "error"
|
|
521
|
+
}),
|
|
522
|
+
disabled: true,
|
|
523
|
+
children: t("phrase_not_recognised")
|
|
474
524
|
})
|
|
475
525
|
})
|
|
476
|
-
}) : /*#__PURE__*/
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
}
|
|
485
|
-
|
|
526
|
+
}) : /*#__PURE__*/_jsxs(_Fragment, {
|
|
527
|
+
children: [/*#__PURE__*/_jsxs(DefaultButton, {
|
|
528
|
+
size: "sm",
|
|
529
|
+
className: classes.alternativeVersionButton,
|
|
530
|
+
onClick: handleCheckRecognition,
|
|
531
|
+
disabled: checkingRecogniton || recognised || notRecognised,
|
|
532
|
+
startIcon: endIcon,
|
|
533
|
+
children: [recognised ? t("phrase_recognised") : null, checkingRecogniton ? t("checking_recognition") : null, !checkingRecogniton && !recognised && !notRecognised ? t("check_recognition") : null]
|
|
534
|
+
}), !checkingRecogniton && !recognised && !notRecognised ? /*#__PURE__*/_jsx(Tooltip, {
|
|
535
|
+
title: t("speech_recognition_info"),
|
|
536
|
+
classes: {
|
|
537
|
+
tooltip: classes.tooltip
|
|
538
|
+
},
|
|
539
|
+
children: /*#__PURE__*/_jsx(IconButton, {
|
|
540
|
+
sx: {
|
|
541
|
+
padding: 0
|
|
542
|
+
},
|
|
543
|
+
children: /*#__PURE__*/_jsx(HelpIcon, {
|
|
544
|
+
fontSize: "small"
|
|
545
|
+
})
|
|
546
|
+
})
|
|
547
|
+
}) : null, checkingRecogniton && /*#__PURE__*/_jsx(CircularProgress, {
|
|
548
|
+
size: 24,
|
|
549
|
+
sx: {
|
|
550
|
+
position: "absolute",
|
|
551
|
+
top: "50%",
|
|
552
|
+
left: "50%",
|
|
553
|
+
marginTop: "-12px",
|
|
554
|
+
marginLeft: "-12px"
|
|
555
|
+
}
|
|
556
|
+
})]
|
|
557
|
+
})
|
|
486
558
|
})
|
|
487
|
-
})
|
|
488
|
-
})
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
children: alternativeVersions ? alternativeVersions.map((alternativeAns, idx) => {
|
|
495
|
-
return /*#__PURE__*/_jsxs(Fragment, {
|
|
559
|
+
})]
|
|
560
|
+
}), phrase && /*#__PURE__*/_jsx(Grid, {
|
|
561
|
+
container: true,
|
|
562
|
+
direction: "row",
|
|
563
|
+
justifyContent: "center",
|
|
564
|
+
alignItems: "flex-end",
|
|
565
|
+
children: alternativeVersions?.map((alternativeAns, idx) => /*#__PURE__*/_jsxs(Fragment, {
|
|
496
566
|
children: [/*#__PURE__*/_jsx(Grid, {
|
|
497
567
|
className: classes.alternativeVersionItem,
|
|
498
568
|
size: 10,
|
|
@@ -500,9 +570,7 @@ function CreatePhrase({
|
|
|
500
570
|
t: t,
|
|
501
571
|
name: `alternativeVersion${idx}`,
|
|
502
572
|
value: alternativeAns,
|
|
503
|
-
onChange: e =>
|
|
504
|
-
handleEditAlternative(e, idx);
|
|
505
|
-
},
|
|
573
|
+
onChange: e => handleEditAlternative(e, idx),
|
|
506
574
|
margin: "none",
|
|
507
575
|
autoFocus: true,
|
|
508
576
|
type: "text",
|
|
@@ -513,53 +581,45 @@ function CreatePhrase({
|
|
|
513
581
|
className: classes.alternativeVersionItem,
|
|
514
582
|
size: 1,
|
|
515
583
|
children: /*#__PURE__*/_jsx(IconButton, {
|
|
516
|
-
onClick: () =>
|
|
517
|
-
handleRemoveAlternative(idx);
|
|
518
|
-
},
|
|
584
|
+
onClick: () => handleRemoveAlternative(idx),
|
|
519
585
|
size: "large",
|
|
520
586
|
"aria-label": "Remove Alternative",
|
|
521
587
|
children: /*#__PURE__*/_jsx(CloseIcon, {})
|
|
522
588
|
})
|
|
523
589
|
})]
|
|
524
|
-
}, `alternative_answers_${idx}`)
|
|
525
|
-
})
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
justifyContent: "center",
|
|
551
|
-
alignItems: "flex-end",
|
|
552
|
-
children: [translationList ? translationList.map((translation, idx) => {
|
|
553
|
-
return /*#__PURE__*/_jsxs(Fragment, {
|
|
590
|
+
}, `alternative_answers_${idx}`))
|
|
591
|
+
}), learnLang !== forLang && /*#__PURE__*/_jsx(InputHelper, {
|
|
592
|
+
inputRef: translationInputRef,
|
|
593
|
+
t: t,
|
|
594
|
+
value: translation,
|
|
595
|
+
onChange: e => setTranslation(e.target.value),
|
|
596
|
+
onKeyDown: e => {
|
|
597
|
+
if (e.key === "Enter") handleAddTranslation();
|
|
598
|
+
},
|
|
599
|
+
margin: "normal",
|
|
600
|
+
id: "translation",
|
|
601
|
+
name: "translation",
|
|
602
|
+
label: t("language_translation", {
|
|
603
|
+
language: capitalize(t(forLang.toLowerCase()))
|
|
604
|
+
}),
|
|
605
|
+
helperText: translation && translation.trim() !== "" ? t("language_translation_helper_text") : "",
|
|
606
|
+
type: "text",
|
|
607
|
+
variant: "outlined",
|
|
608
|
+
fullWidth: true,
|
|
609
|
+
characters: forLangCharacters ? forLangCharacters : null
|
|
610
|
+
}), /*#__PURE__*/_jsxs(Grid, {
|
|
611
|
+
container: true,
|
|
612
|
+
direction: "row",
|
|
613
|
+
justifyContent: "center",
|
|
614
|
+
alignItems: "flex-end",
|
|
615
|
+
children: [translationList?.map((translationItem, idx) => /*#__PURE__*/_jsxs(Fragment, {
|
|
554
616
|
children: [/*#__PURE__*/_jsx(Grid, {
|
|
555
617
|
className: classes.translationItem,
|
|
556
618
|
size: 10,
|
|
557
619
|
children: /*#__PURE__*/_jsx(InputHelper, {
|
|
558
620
|
t: t,
|
|
559
|
-
value:
|
|
560
|
-
onChange: e =>
|
|
561
|
-
handleEditTranslation(e, idx);
|
|
562
|
-
},
|
|
621
|
+
value: translationItem,
|
|
622
|
+
onChange: e => handleEditTranslation(e, idx),
|
|
563
623
|
margin: "none",
|
|
564
624
|
type: "text",
|
|
565
625
|
fullWidth: true,
|
|
@@ -572,30 +632,75 @@ function CreatePhrase({
|
|
|
572
632
|
className: classes.translationItem,
|
|
573
633
|
size: 1,
|
|
574
634
|
children: /*#__PURE__*/_jsx(IconButton, {
|
|
575
|
-
onClick: () =>
|
|
576
|
-
handleRemoveTranslation(idx);
|
|
577
|
-
},
|
|
635
|
+
onClick: () => handleRemoveTranslation(idx),
|
|
578
636
|
size: "large",
|
|
579
637
|
"aria-label": "Remove Translation",
|
|
580
638
|
children: /*#__PURE__*/_jsx(CloseIcon, {})
|
|
581
639
|
})
|
|
582
640
|
})]
|
|
583
|
-
}, `translist_${idx}`)
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
641
|
+
}, `translist_${idx}`)), learnLang !== forLang && /*#__PURE__*/_jsxs(_Fragment, {
|
|
642
|
+
children: [/*#__PURE__*/_jsx(Grid, {
|
|
643
|
+
size: 12,
|
|
644
|
+
children: /*#__PURE__*/_jsx(InputHelper, {
|
|
645
|
+
t: t,
|
|
646
|
+
value: definition,
|
|
647
|
+
onChange: e => setDefinition(e.target.value),
|
|
648
|
+
onKeyDown: e => {
|
|
649
|
+
if (e.key === "Enter") handleAddDefinition();
|
|
650
|
+
},
|
|
651
|
+
margin: "normal",
|
|
652
|
+
id: "definition",
|
|
653
|
+
name: "definition",
|
|
654
|
+
label: t("phrase_definition"),
|
|
655
|
+
helperText: definition && definition.trim() !== "" ? t("phrase_definition_helper_text") : "",
|
|
656
|
+
type: "text",
|
|
657
|
+
variant: "outlined",
|
|
658
|
+
fullWidth: true,
|
|
659
|
+
characters: forLangCharacters ? forLangCharacters : null
|
|
660
|
+
})
|
|
661
|
+
}), definitionList?.map((def, idx) => /*#__PURE__*/_jsxs(Fragment, {
|
|
662
|
+
children: [/*#__PURE__*/_jsx(Grid, {
|
|
663
|
+
className: classes.translationItem,
|
|
664
|
+
size: 10,
|
|
665
|
+
children: /*#__PURE__*/_jsx(InputHelper, {
|
|
666
|
+
t: t,
|
|
667
|
+
value: def,
|
|
668
|
+
onChange: e => handleEditDefinition(e, idx),
|
|
669
|
+
margin: "none",
|
|
670
|
+
type: "text",
|
|
671
|
+
fullWidth: true,
|
|
672
|
+
characters: forLangCharacters ? forLangCharacters : null,
|
|
673
|
+
inputProps: {
|
|
674
|
+
"data-definition-index": idx
|
|
675
|
+
}
|
|
676
|
+
})
|
|
677
|
+
}), /*#__PURE__*/_jsx(Grid, {
|
|
678
|
+
className: classes.translationItem,
|
|
679
|
+
size: 1,
|
|
680
|
+
children: /*#__PURE__*/_jsx(IconButton, {
|
|
681
|
+
onClick: () => handleRemoveDefinition(idx),
|
|
682
|
+
size: "large",
|
|
683
|
+
"aria-label": "Remove Definition",
|
|
684
|
+
children: /*#__PURE__*/_jsx(CloseIcon, {})
|
|
685
|
+
})
|
|
686
|
+
})]
|
|
687
|
+
}, `deflist_${idx}`))]
|
|
688
|
+
}), /*#__PURE__*/_jsx(Grid, {
|
|
689
|
+
size: 12,
|
|
690
|
+
children: /*#__PURE__*/_jsx(ImageSelector, {
|
|
691
|
+
t: t,
|
|
692
|
+
name: "image",
|
|
693
|
+
value: selectedImage.image,
|
|
694
|
+
handleChange: handleImageSelection,
|
|
695
|
+
fileSizeLimit: fileSizeLimit,
|
|
696
|
+
removeImage: removePhraseImage,
|
|
697
|
+
autoCrop: true,
|
|
698
|
+
autoSuggest: true,
|
|
699
|
+
autoSuggestedImages: autoSuggestedImages,
|
|
700
|
+
selectedImage: selectedImage,
|
|
701
|
+
verificationStatus: verificationStatus
|
|
702
|
+
})
|
|
703
|
+
})]
|
|
599
704
|
})]
|
|
600
705
|
})]
|
|
601
706
|
});
|
|
@@ -12,11 +12,13 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
12
12
|
const useStyles = makeStyles()(theme => ({
|
|
13
13
|
phraseText: {
|
|
14
14
|
width: "80%",
|
|
15
|
-
wordBreak: "break-
|
|
15
|
+
wordBreak: "break-word",
|
|
16
|
+
overflowWrap: "break-word"
|
|
16
17
|
},
|
|
17
18
|
phraseTextSmall: {
|
|
18
19
|
width: "60%",
|
|
19
|
-
wordBreak: "break-
|
|
20
|
+
wordBreak: "break-word",
|
|
21
|
+
overflowWrap: "break-word"
|
|
20
22
|
},
|
|
21
23
|
avatar: {
|
|
22
24
|
cursor: "pointer",
|
|
@@ -29,6 +31,7 @@ const useStyles = makeStyles()(theme => ({
|
|
|
29
31
|
function Phrase({
|
|
30
32
|
alternativeVersions,
|
|
31
33
|
translations,
|
|
34
|
+
definitions,
|
|
32
35
|
phrase
|
|
33
36
|
}) {
|
|
34
37
|
const theme = useTheme();
|
|
@@ -36,6 +39,27 @@ function Phrase({
|
|
|
36
39
|
classes
|
|
37
40
|
} = useStyles();
|
|
38
41
|
const isLargeScreen = useMediaQuery(theme.breakpoints.up("sm"));
|
|
42
|
+
const primary = `${phrase}${Array.isArray(alternativeVersions) && alternativeVersions.length ? " - " : ""}${(alternativeVersions || []).join(", ")}`;
|
|
43
|
+
|
|
44
|
+
// Show translations first, then definitions (if any) on a new line.
|
|
45
|
+
const secondaryParts = [];
|
|
46
|
+
if (Array.isArray(translations) && translations.length) {
|
|
47
|
+
secondaryParts.push((translations || []).join(", "));
|
|
48
|
+
}
|
|
49
|
+
if (Array.isArray(definitions) && definitions.length) {
|
|
50
|
+
secondaryParts.push((definitions || []).join(", "));
|
|
51
|
+
}
|
|
52
|
+
const secondary = secondaryParts.join("\n");
|
|
53
|
+
console.log({
|
|
54
|
+
primary,
|
|
55
|
+
secondary
|
|
56
|
+
});
|
|
57
|
+
console.log("Phrase render", {
|
|
58
|
+
phrase,
|
|
59
|
+
translations,
|
|
60
|
+
definitions,
|
|
61
|
+
alternativeVersions
|
|
62
|
+
});
|
|
39
63
|
return /*#__PURE__*/_jsx(ListItem, {
|
|
40
64
|
"data-cy": "phrase-list-item",
|
|
41
65
|
children: isLargeScreen ? /*#__PURE__*/_jsx(Grid, {
|
|
@@ -46,8 +70,13 @@ function Phrase({
|
|
|
46
70
|
className: classes.phraseText,
|
|
47
71
|
children: /*#__PURE__*/_jsx(ListItemText, {
|
|
48
72
|
className: classes.phrases,
|
|
49
|
-
primary:
|
|
50
|
-
secondary:
|
|
73
|
+
primary: primary,
|
|
74
|
+
secondary: secondary,
|
|
75
|
+
secondaryTypographyProps: {
|
|
76
|
+
style: {
|
|
77
|
+
whiteSpace: "pre-line"
|
|
78
|
+
}
|
|
79
|
+
}
|
|
51
80
|
})
|
|
52
81
|
}) : /*#__PURE__*/_jsx(Grid, {
|
|
53
82
|
container: true,
|
|
@@ -57,8 +86,13 @@ function Phrase({
|
|
|
57
86
|
className: classes.phraseTextSmall,
|
|
58
87
|
children: /*#__PURE__*/_jsx(ListItemText, {
|
|
59
88
|
className: classes.phrases,
|
|
60
|
-
primary:
|
|
61
|
-
secondary:
|
|
89
|
+
primary: primary,
|
|
90
|
+
secondary: secondary,
|
|
91
|
+
secondaryTypographyProps: {
|
|
92
|
+
style: {
|
|
93
|
+
whiteSpace: "pre-line"
|
|
94
|
+
}
|
|
95
|
+
}
|
|
62
96
|
})
|
|
63
97
|
})
|
|
64
98
|
});
|
|
@@ -85,11 +119,13 @@ function GeneratePhrases({
|
|
|
85
119
|
const phrases = isPhrases ? currentPhrases.map(({
|
|
86
120
|
phrase,
|
|
87
121
|
translations,
|
|
122
|
+
definitions,
|
|
88
123
|
image,
|
|
89
124
|
voices
|
|
90
125
|
}) => ({
|
|
91
126
|
phrase,
|
|
92
127
|
translations,
|
|
128
|
+
definitions,
|
|
93
129
|
image,
|
|
94
130
|
voices
|
|
95
131
|
})) : null;
|
|
@@ -114,6 +150,7 @@ function GeneratePhrases({
|
|
|
114
150
|
if (typeof item !== "object" || item === null || Array.isArray(item)) {
|
|
115
151
|
return false;
|
|
116
152
|
}
|
|
153
|
+
// definitions is OPTIONAL and we do NOT validate it per your request
|
|
117
154
|
if (!Object.hasOwn(item, "phrase") || !Object.hasOwn(item, "translations") || !Object.hasOwn(item, "image")) {
|
|
118
155
|
return false;
|
|
119
156
|
}
|
|
@@ -158,7 +195,13 @@ function GeneratePhrases({
|
|
|
158
195
|
if (!validateResponse(phrasesArray)) {
|
|
159
196
|
throw new Error("Invalid AI response");
|
|
160
197
|
}
|
|
161
|
-
|
|
198
|
+
|
|
199
|
+
// Ensure definitions exists as an array (assumed array; no validation)
|
|
200
|
+
const normalized = phrasesArray.map(p => ({
|
|
201
|
+
...p,
|
|
202
|
+
definitions: Array.isArray(p.definitions) ? p.definitions : []
|
|
203
|
+
}));
|
|
204
|
+
setGeneratedPhrases(normalized);
|
|
162
205
|
setIsGenerating(false);
|
|
163
206
|
} catch (error) {
|
|
164
207
|
console.error(error);
|
|
@@ -238,7 +281,6 @@ function GeneratePhrases({
|
|
|
238
281
|
onChange: handleChange,
|
|
239
282
|
multiline: true,
|
|
240
283
|
rows: 3
|
|
241
|
-
// maxLength={300}
|
|
242
284
|
})
|
|
243
285
|
}), /*#__PURE__*/_jsx(Grid, {
|
|
244
286
|
mb: 2,
|
|
@@ -254,9 +296,7 @@ function GeneratePhrases({
|
|
|
254
296
|
margin: "normal",
|
|
255
297
|
variant: "outlined",
|
|
256
298
|
fullWidth: true,
|
|
257
|
-
onChange: handleChange
|
|
258
|
-
// inputProps={{ maxLength: 200 }}
|
|
259
|
-
,
|
|
299
|
+
onChange: handleChange,
|
|
260
300
|
InputProps: {
|
|
261
301
|
endAdornment: /*#__PURE__*/_jsx(InputAdornment, {
|
|
262
302
|
position: "end",
|
|
@@ -9,8 +9,9 @@ import InputAdornment from "@mui/material/InputAdornment";
|
|
|
9
9
|
import FormControl from "@mui/material/FormControl";
|
|
10
10
|
import Translate from "@mui/icons-material/Translate";
|
|
11
11
|
import Tooltip from "@mui/material/Tooltip";
|
|
12
|
-
import
|
|
13
|
-
import
|
|
12
|
+
import Popover from "@mui/material/Popover";
|
|
13
|
+
import Box from "@mui/material/Box";
|
|
14
|
+
import ButtonBase from "@mui/material/ButtonBase";
|
|
14
15
|
import FormHelperText from "@mui/material/FormHelperText";
|
|
15
16
|
import { Smile } from "react-feather";
|
|
16
17
|
import Picker from "emoji-picker-react";
|
|
@@ -29,7 +30,6 @@ export function Adornment(props) {
|
|
|
29
30
|
adornmentPosition = "end",
|
|
30
31
|
iconButtonEdge = "end",
|
|
31
32
|
icon = /*#__PURE__*/_jsx(Translate, {}),
|
|
32
|
-
width = 90,
|
|
33
33
|
title = "accents_and_special_characters",
|
|
34
34
|
activeRef,
|
|
35
35
|
whiteIcon = false,
|
|
@@ -77,6 +77,24 @@ export function Adornment(props) {
|
|
|
77
77
|
}
|
|
78
78
|
}
|
|
79
79
|
};
|
|
80
|
+
const cellSx = {
|
|
81
|
+
width: 40,
|
|
82
|
+
height: 40,
|
|
83
|
+
display: "flex",
|
|
84
|
+
alignItems: "center",
|
|
85
|
+
justifyContent: "center",
|
|
86
|
+
fontSize: "1.15rem",
|
|
87
|
+
borderRadius: 1,
|
|
88
|
+
cursor: "pointer",
|
|
89
|
+
transition: "background-color 0.1s",
|
|
90
|
+
"&:hover": {
|
|
91
|
+
backgroundColor: theme.palette.mode === "dark" ? "rgba(255,255,255,0.12)" : "rgba(0,0,0,0.08)"
|
|
92
|
+
},
|
|
93
|
+
"&:focus-visible": {
|
|
94
|
+
outline: `2px solid ${theme.palette.primary.main}`,
|
|
95
|
+
outlineOffset: -2
|
|
96
|
+
}
|
|
97
|
+
};
|
|
80
98
|
return /*#__PURE__*/_jsx(_Fragment, {
|
|
81
99
|
children: /*#__PURE__*/_jsxs(InputAdornment, {
|
|
82
100
|
position: adornmentPosition,
|
|
@@ -113,7 +131,7 @@ export function Adornment(props) {
|
|
|
113
131
|
children: /*#__PURE__*/_jsx(Smile, {})
|
|
114
132
|
})
|
|
115
133
|
})]
|
|
116
|
-
}), characters && /*#__PURE__*/_jsxs(_Fragment, {
|
|
134
|
+
}), characters && characters.length > 0 && /*#__PURE__*/_jsxs(_Fragment, {
|
|
117
135
|
children: [/*#__PURE__*/_jsx(Tooltip, {
|
|
118
136
|
title: t(title),
|
|
119
137
|
children: /*#__PURE__*/_jsx(IconButton, {
|
|
@@ -140,22 +158,35 @@ export function Adornment(props) {
|
|
|
140
158
|
},
|
|
141
159
|
children: icon
|
|
142
160
|
})
|
|
143
|
-
}), /*#__PURE__*/_jsx(
|
|
144
|
-
id: `char-
|
|
161
|
+
}), /*#__PURE__*/_jsx(Popover, {
|
|
162
|
+
id: `char-grid-${name}`,
|
|
145
163
|
anchorEl: anchorEl,
|
|
146
|
-
keepMounted: true,
|
|
147
164
|
open: Boolean(anchorEl),
|
|
148
165
|
onClose: handleCloseAccents,
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
166
|
+
anchorOrigin: {
|
|
167
|
+
vertical: "bottom",
|
|
168
|
+
horizontal: "center"
|
|
169
|
+
},
|
|
170
|
+
transformOrigin: {
|
|
171
|
+
vertical: "top",
|
|
172
|
+
horizontal: "center"
|
|
154
173
|
},
|
|
155
|
-
children:
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
174
|
+
children: /*#__PURE__*/_jsx(Box, {
|
|
175
|
+
sx: {
|
|
176
|
+
display: "grid",
|
|
177
|
+
gridTemplateColumns: "repeat(7, 40px)",
|
|
178
|
+
gap: 0.25,
|
|
179
|
+
p: 1
|
|
180
|
+
},
|
|
181
|
+
role: "grid",
|
|
182
|
+
"aria-label": t(title),
|
|
183
|
+
children: characters.map(c => /*#__PURE__*/_jsx(ButtonBase, {
|
|
184
|
+
sx: cellSx,
|
|
185
|
+
onClick: () => handleClickOption(c),
|
|
186
|
+
"aria-label": c,
|
|
187
|
+
children: c
|
|
188
|
+
}, c))
|
|
189
|
+
})
|
|
159
190
|
})]
|
|
160
191
|
})]
|
|
161
192
|
})
|
|
@@ -172,8 +203,7 @@ function InputHelper(props) {
|
|
|
172
203
|
margin,
|
|
173
204
|
inputRef,
|
|
174
205
|
maxLength,
|
|
175
|
-
autoFocus
|
|
176
|
-
learnLang
|
|
206
|
+
autoFocus
|
|
177
207
|
} = props;
|
|
178
208
|
const textInput = useRef(null);
|
|
179
209
|
const activeRef = inputRef || textInput;
|
|
@@ -188,10 +218,9 @@ function InputHelper(props) {
|
|
|
188
218
|
}
|
|
189
219
|
}
|
|
190
220
|
};
|
|
191
|
-
const adornment = characters ? /*#__PURE__*/_jsx(Adornment, {
|
|
221
|
+
const adornment = characters && characters.length > 0 ? /*#__PURE__*/_jsx(Adornment, {
|
|
192
222
|
...props,
|
|
193
223
|
activeRef: activeRef,
|
|
194
|
-
learnLang: learnLang,
|
|
195
224
|
id: `${id}-adornment`,
|
|
196
225
|
role: "button",
|
|
197
226
|
tabIndex: 0,
|
|
@@ -7,9 +7,10 @@ import MoreVertIcon from "@mui/icons-material/MoreVert";
|
|
|
7
7
|
import EditIcon from "@mui/icons-material/Edit";
|
|
8
8
|
import DeleteIcon from "@mui/icons-material/Delete";
|
|
9
9
|
import ImageSearchIcon from "@mui/icons-material/ImageSearch";
|
|
10
|
+
import GTranslateIcon from "@mui/icons-material/GTranslate";
|
|
11
|
+
import MenuBookIcon from '@mui/icons-material/MenuBook';
|
|
10
12
|
import ListenerDialog from "../../Dialogs/Listener/Listener";
|
|
11
13
|
import UpdatePhraseDialog from "../../Dialogs/CreatePhrase/CreatePhrase";
|
|
12
|
-
import DragIndicatorIcon from "@mui/icons-material/DragIndicator";
|
|
13
14
|
import ViewImageDialog from "../../Dialogs/ViewImageDialog/ViewImageDialog";
|
|
14
15
|
import { propsAreEqual } from "../../utils";
|
|
15
16
|
import { useTheme } from "@mui/material/styles";
|
|
@@ -22,6 +23,21 @@ const useStyles = makeStyles()(theme => ({
|
|
|
22
23
|
root: {
|
|
23
24
|
width: "100%"
|
|
24
25
|
},
|
|
26
|
+
translationRow: {
|
|
27
|
+
display: "flex",
|
|
28
|
+
alignItems: "flex-start",
|
|
29
|
+
gap: "6px",
|
|
30
|
+
lineHeight: 1.2
|
|
31
|
+
},
|
|
32
|
+
iconBeforeText: {
|
|
33
|
+
display: "inline-flex",
|
|
34
|
+
alignItems: "center",
|
|
35
|
+
justifyContent: "center",
|
|
36
|
+
width: 14,
|
|
37
|
+
height: 14,
|
|
38
|
+
color: theme.palette.text.secondary,
|
|
39
|
+
marginTop: 1
|
|
40
|
+
},
|
|
25
41
|
phraseText: {
|
|
26
42
|
width: "80%",
|
|
27
43
|
wordBreak: "break-all"
|
|
@@ -31,15 +47,27 @@ const useStyles = makeStyles()(theme => ({
|
|
|
31
47
|
wordBreak: "break-all"
|
|
32
48
|
},
|
|
33
49
|
avatar: {
|
|
34
|
-
// width: 50,
|
|
35
|
-
// height: 50,
|
|
36
50
|
cursor: "pointer",
|
|
37
|
-
margin: theme.spacing()
|
|
51
|
+
margin: theme.spacing(),
|
|
52
|
+
marginRight: 20,
|
|
53
|
+
width: 55,
|
|
54
|
+
height: 55
|
|
38
55
|
},
|
|
39
56
|
avatarNoClick: {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
57
|
+
margin: theme.spacing(),
|
|
58
|
+
marginRight: 20,
|
|
59
|
+
width: 55,
|
|
60
|
+
height: 55
|
|
61
|
+
},
|
|
62
|
+
translationsText: {
|
|
63
|
+
overflow: "hidden",
|
|
64
|
+
whiteSpace: "nowrap",
|
|
65
|
+
textOverflow: "ellipsis"
|
|
66
|
+
},
|
|
67
|
+
definitionsText: {
|
|
68
|
+
overflow: "hidden",
|
|
69
|
+
whiteSpace: "nowrap",
|
|
70
|
+
textOverflow: "ellipsis"
|
|
43
71
|
}
|
|
44
72
|
}));
|
|
45
73
|
function Phrase(props) {
|
|
@@ -61,7 +89,6 @@ function Phrase(props) {
|
|
|
61
89
|
learnLang,
|
|
62
90
|
handleSpeak,
|
|
63
91
|
userAttributes,
|
|
64
|
-
disableDragAndDrop = false,
|
|
65
92
|
handleUpdatePhrase,
|
|
66
93
|
uploadAudio,
|
|
67
94
|
voices = {},
|
|
@@ -77,10 +104,14 @@ function Phrase(props) {
|
|
|
77
104
|
} = props;
|
|
78
105
|
const {
|
|
79
106
|
phrase = "",
|
|
80
|
-
translations,
|
|
107
|
+
translations = [],
|
|
108
|
+
definitions = [],
|
|
81
109
|
alternativeVersions,
|
|
82
110
|
image
|
|
83
111
|
} = props.phrase || {};
|
|
112
|
+
const hasDefinitions = (definitions || []).length > 0;
|
|
113
|
+
const hasTranslations = (translations || []).length > 0;
|
|
114
|
+
const useCompactSecondary = hasDefinitions && hasTranslations;
|
|
84
115
|
const handleImageOpen = () => {
|
|
85
116
|
setImageOpen(true);
|
|
86
117
|
};
|
|
@@ -111,6 +142,11 @@ function Phrase(props) {
|
|
|
111
142
|
return;
|
|
112
143
|
}
|
|
113
144
|
};
|
|
145
|
+
console.log("Phrase render", {
|
|
146
|
+
phrase,
|
|
147
|
+
translations,
|
|
148
|
+
alternativeVersions
|
|
149
|
+
});
|
|
114
150
|
const handleCloseMenu = () => {
|
|
115
151
|
setAnchorEl(null);
|
|
116
152
|
};
|
|
@@ -159,7 +195,51 @@ function Phrase(props) {
|
|
|
159
195
|
children: /*#__PURE__*/_jsx(ListItemText, {
|
|
160
196
|
className: classes.phrases,
|
|
161
197
|
primary: `${phrase}${Array.isArray(alternativeVersions) && alternativeVersions.length ? " - " : ""}${(alternativeVersions || []).join(", ")}`,
|
|
162
|
-
secondary: (
|
|
198
|
+
secondary: /*#__PURE__*/_jsxs("div", {
|
|
199
|
+
children: [/*#__PURE__*/_jsxs(Box, {
|
|
200
|
+
mt: 0.25,
|
|
201
|
+
className: classes.translationRow,
|
|
202
|
+
children: [/*#__PURE__*/_jsx(Tooltip, {
|
|
203
|
+
title: t("translation") || "Translation",
|
|
204
|
+
children: /*#__PURE__*/_jsx("span", {
|
|
205
|
+
className: classes.iconBeforeText,
|
|
206
|
+
"aria-hidden": true,
|
|
207
|
+
children: /*#__PURE__*/_jsx(GTranslateIcon, {
|
|
208
|
+
fontSize: "small"
|
|
209
|
+
})
|
|
210
|
+
})
|
|
211
|
+
}), /*#__PURE__*/_jsx(Tooltip, {
|
|
212
|
+
title: (translations || []).join(", "),
|
|
213
|
+
children: /*#__PURE__*/_jsx(Typography, {
|
|
214
|
+
variant: "body2",
|
|
215
|
+
color: "textSecondary",
|
|
216
|
+
className: classes.translationsText,
|
|
217
|
+
children: (translations || []).join(", ")
|
|
218
|
+
})
|
|
219
|
+
})]
|
|
220
|
+
}), (props.phrase.definitions || []).length > 0 && /*#__PURE__*/_jsxs(Box, {
|
|
221
|
+
mt: 0.25,
|
|
222
|
+
className: classes.translationRow,
|
|
223
|
+
children: [/*#__PURE__*/_jsx(Tooltip, {
|
|
224
|
+
title: t("definition") || "Definition",
|
|
225
|
+
children: /*#__PURE__*/_jsx("span", {
|
|
226
|
+
className: classes.iconBeforeText,
|
|
227
|
+
"aria-hidden": true,
|
|
228
|
+
children: /*#__PURE__*/_jsx(MenuBookIcon, {
|
|
229
|
+
fontSize: "small"
|
|
230
|
+
})
|
|
231
|
+
})
|
|
232
|
+
}), /*#__PURE__*/_jsx(Tooltip, {
|
|
233
|
+
title: (props.phrase.definitions || []).join("; "),
|
|
234
|
+
children: /*#__PURE__*/_jsx(Typography, {
|
|
235
|
+
variant: "body2",
|
|
236
|
+
color: "textSecondary",
|
|
237
|
+
className: `${useCompactSecondary ? classes.secondaryTextCompact : ""} ${classes.definitionsText}`,
|
|
238
|
+
children: (props.phrase.definitions || []).join("; ")
|
|
239
|
+
})
|
|
240
|
+
})]
|
|
241
|
+
})]
|
|
242
|
+
})
|
|
163
243
|
})
|
|
164
244
|
}) : /*#__PURE__*/_jsx(Grid, {
|
|
165
245
|
container: true,
|
|
@@ -170,7 +250,51 @@ function Phrase(props) {
|
|
|
170
250
|
children: /*#__PURE__*/_jsx(ListItemText, {
|
|
171
251
|
className: classes.phrases,
|
|
172
252
|
primary: `${phrase}${Array.isArray(alternativeVersions) && alternativeVersions.length ? " - " : ""}${(alternativeVersions || []).join(", ")}`,
|
|
173
|
-
secondary: (
|
|
253
|
+
secondary: /*#__PURE__*/_jsxs("div", {
|
|
254
|
+
children: [/*#__PURE__*/_jsxs(Box, {
|
|
255
|
+
mt: 0.25,
|
|
256
|
+
className: classes.translationRow,
|
|
257
|
+
children: [/*#__PURE__*/_jsx(Tooltip, {
|
|
258
|
+
title: t("translation") || "Translation",
|
|
259
|
+
children: /*#__PURE__*/_jsx("span", {
|
|
260
|
+
className: classes.iconBeforeText,
|
|
261
|
+
"aria-hidden": true,
|
|
262
|
+
children: /*#__PURE__*/_jsx(GTranslateIcon, {
|
|
263
|
+
fontSize: "small"
|
|
264
|
+
})
|
|
265
|
+
})
|
|
266
|
+
}), /*#__PURE__*/_jsx(Tooltip, {
|
|
267
|
+
title: (translations || []).join(", "),
|
|
268
|
+
children: /*#__PURE__*/_jsx(Typography, {
|
|
269
|
+
variant: "body2",
|
|
270
|
+
color: "textSecondary",
|
|
271
|
+
className: classes.translationsText,
|
|
272
|
+
children: (translations || []).join(", ")
|
|
273
|
+
})
|
|
274
|
+
})]
|
|
275
|
+
}), (props.phrase.definitions || []).length > 0 && /*#__PURE__*/_jsxs(Box, {
|
|
276
|
+
mt: 0.25,
|
|
277
|
+
className: classes.translationRow,
|
|
278
|
+
children: [/*#__PURE__*/_jsx(Tooltip, {
|
|
279
|
+
title: t("definition") || "Definition",
|
|
280
|
+
children: /*#__PURE__*/_jsx("span", {
|
|
281
|
+
className: classes.iconBeforeText,
|
|
282
|
+
"aria-hidden": true,
|
|
283
|
+
children: /*#__PURE__*/_jsx(MenuBookIcon, {
|
|
284
|
+
fontSize: "small"
|
|
285
|
+
})
|
|
286
|
+
})
|
|
287
|
+
}), /*#__PURE__*/_jsx(Tooltip, {
|
|
288
|
+
title: (props.phrase.definitions || []).join("; "),
|
|
289
|
+
children: /*#__PURE__*/_jsx(Typography, {
|
|
290
|
+
variant: "body2",
|
|
291
|
+
color: "textSecondary",
|
|
292
|
+
className: classes.definitionsText,
|
|
293
|
+
children: (props.phrase.definitions || []).join("; ")
|
|
294
|
+
})
|
|
295
|
+
})]
|
|
296
|
+
})]
|
|
297
|
+
})
|
|
174
298
|
})
|
|
175
299
|
}), /*#__PURE__*/_jsxs(ListItemSecondaryAction, {
|
|
176
300
|
children: [!disableActions && !isLargeScreen && isCreator && /*#__PURE__*/_jsxs("div", {
|
|
@@ -287,6 +411,7 @@ function Phrase(props) {
|
|
|
287
411
|
image: props.phrase.image,
|
|
288
412
|
translations: translations,
|
|
289
413
|
alternativeVersions: props.phrase.alternativeVersions,
|
|
414
|
+
definitions: props.phrase.definitions,
|
|
290
415
|
voices: props.phrase.voices,
|
|
291
416
|
learnLang: learnLang,
|
|
292
417
|
forLang: forLang,
|