@nualang/nualang-ui-components 0.1.1173 → 0.1.1175
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/Forms/VoiceSelector/VoiceSelector.js +6 -4
- package/dist/Screens/Classrooms/ViewClassroom/ViewClassroom.js +6 -3
- package/dist/Screens/Courses/ViewCourse/ViewCourse.js +5 -3
- package/dist/Screens/Courses/ViewCourse/ViewTopic/ViewTopic.js +5 -3
- package/dist/Screens/GenerateAudio/GenerateAudio.js +585 -16
- package/package.json +3 -1
|
@@ -78,12 +78,14 @@ function VoiceSelector(props) {
|
|
|
78
78
|
value = "",
|
|
79
79
|
onVoicePitchChange,
|
|
80
80
|
voicePitch,
|
|
81
|
+
generateAudio = false,
|
|
82
|
+
csv = false,
|
|
81
83
|
...otherProps
|
|
82
84
|
} = props;
|
|
83
85
|
const voiceAccents = Object.values(voices);
|
|
84
86
|
const voicesArray = voiceAccents.flatMap(voiceOption => voiceOption.voiceOptions);
|
|
85
87
|
const selectedVoice = (voicesArray || []).find(v => v.name === value);
|
|
86
|
-
const
|
|
88
|
+
const audioOrStorybook = generateAudio || window.location.host === "localhost:9009";
|
|
87
89
|
return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_material.TextField, _extends({
|
|
88
90
|
select: true,
|
|
89
91
|
value: value
|
|
@@ -106,11 +108,11 @@ function VoiceSelector(props) {
|
|
|
106
108
|
alt: ""
|
|
107
109
|
}))), /*#__PURE__*/_react.default.createElement(_material.Grid, _extends({
|
|
108
110
|
item: true
|
|
109
|
-
},
|
|
111
|
+
}, audioOrStorybook ? {
|
|
110
112
|
sx: {
|
|
111
113
|
flexGrow: 1
|
|
112
114
|
}
|
|
113
|
-
} : {}), voiceOption.isChild && voiceOption.isChild === true ? /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, " ", `${voiceOption.name} (${t("child")}) `, " ") : /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, voiceOption.name)),
|
|
115
|
+
} : {}), voiceOption.isChild && voiceOption.isChild === true ? /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, " ", `${voiceOption.name} (${t("child")}) `, " ") : /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, voiceOption.name)), audioOrStorybook && /*#__PURE__*/_react.default.createElement(_material.Grid, {
|
|
114
116
|
item: true,
|
|
115
117
|
sx: {
|
|
116
118
|
mr: 2,
|
|
@@ -122,7 +124,7 @@ function VoiceSelector(props) {
|
|
|
122
124
|
}) : /*#__PURE__*/_react.default.createElement("img", {
|
|
123
125
|
src: _aws.default,
|
|
124
126
|
alt: "AWS Icon"
|
|
125
|
-
}))))])])), value && /*#__PURE__*/_react.default.createElement(_material.Box, {
|
|
127
|
+
}))))])])), value && !csv && /*#__PURE__*/_react.default.createElement(_material.Box, {
|
|
126
128
|
sx: {
|
|
127
129
|
width: "100%",
|
|
128
130
|
px: 1,
|
|
@@ -181,7 +181,8 @@ function OverflowMenu({
|
|
|
181
181
|
handleOpenInviteDialog,
|
|
182
182
|
refreshClassroomCourses,
|
|
183
183
|
courses,
|
|
184
|
-
isArchived
|
|
184
|
+
isArchived,
|
|
185
|
+
isTeacher
|
|
185
186
|
}) {
|
|
186
187
|
const isMediumScreen = (0, _useMediaQuery.default)("(max-width:600px)");
|
|
187
188
|
const [isShareDrawerOpen, setIsShareDrawerOpen] = (0, _react.useState)(false);
|
|
@@ -208,7 +209,7 @@ function OverflowMenu({
|
|
|
208
209
|
keepMounted: true,
|
|
209
210
|
open: Boolean(anchorEl),
|
|
210
211
|
onClose: handleClose
|
|
211
|
-
},
|
|
212
|
+
}, isTeacher && !isArchived && /*#__PURE__*/_react.default.createElement(_material.MenuItem, {
|
|
212
213
|
onClick: handleClick,
|
|
213
214
|
"data-cy": "share-classroom"
|
|
214
215
|
}, /*#__PURE__*/_react.default.createElement(_CardElements.CardMenuIcon, null, /*#__PURE__*/_react.default.createElement(_Share.default, {
|
|
@@ -342,6 +343,7 @@ function Classroom({
|
|
|
342
343
|
isNualangLiveEnabled,
|
|
343
344
|
handleCreateCourse,
|
|
344
345
|
refreshClassroomCourses,
|
|
346
|
+
isTeacher,
|
|
345
347
|
...otherProps
|
|
346
348
|
}) {
|
|
347
349
|
const {
|
|
@@ -1208,7 +1210,8 @@ function Classroom({
|
|
|
1208
1210
|
handleOpenUpgradeSubscriptionModal: true,
|
|
1209
1211
|
refreshClassroomCourses: refreshClassroomCourses,
|
|
1210
1212
|
courses: courses,
|
|
1211
|
-
isArchived: isArchived
|
|
1213
|
+
isArchived: isArchived,
|
|
1214
|
+
isTeacher: isTeacher
|
|
1212
1215
|
}), /*#__PURE__*/_react.default.createElement(_UpgradeSubscription.default, {
|
|
1213
1216
|
key: "UpgradeSubscription",
|
|
1214
1217
|
t: t,
|
|
@@ -129,7 +129,8 @@ function OverflowMenu({
|
|
|
129
129
|
mainSiteUrl,
|
|
130
130
|
loading,
|
|
131
131
|
verificationStatus,
|
|
132
|
-
handleUploadVideo
|
|
132
|
+
handleUploadVideo,
|
|
133
|
+
isTeacher
|
|
133
134
|
}) {
|
|
134
135
|
const [isShareDrawerOpen, setIsShareDrawerOpen] = (0, _react.useState)(false);
|
|
135
136
|
const [isUploadVideoOpen, setIsUploadVideoOpen] = (0, _react.useState)(false);
|
|
@@ -157,7 +158,7 @@ function OverflowMenu({
|
|
|
157
158
|
keepMounted: true,
|
|
158
159
|
open: Boolean(anchorEl),
|
|
159
160
|
onClose: handleClose
|
|
160
|
-
},
|
|
161
|
+
}, isTeacher && /*#__PURE__*/_react.default.createElement(_material.MenuItem, {
|
|
161
162
|
onClick: handleClick,
|
|
162
163
|
"data-cy": "share-course"
|
|
163
164
|
}, /*#__PURE__*/_react.default.createElement(_CardElements.CardMenuIcon, null, /*#__PURE__*/_react.default.createElement(_Share.default, {
|
|
@@ -893,7 +894,8 @@ function Course({
|
|
|
893
894
|
verificationStatus: verificationStatus,
|
|
894
895
|
gameAward: gameAward,
|
|
895
896
|
loading: loading,
|
|
896
|
-
handleUploadVideo: handleUploadVideo
|
|
897
|
+
handleUploadVideo: handleUploadVideo,
|
|
898
|
+
isTeacher: !isStudent
|
|
897
899
|
}), /*#__PURE__*/_react.default.createElement(_UpgradeSubscription.default, {
|
|
898
900
|
key: "UpgradeSubscription",
|
|
899
901
|
t: t,
|
|
@@ -274,7 +274,8 @@ function OverflowMenu({
|
|
|
274
274
|
pdfUrl,
|
|
275
275
|
deletePDF,
|
|
276
276
|
verificationStatus,
|
|
277
|
-
handleClickOpenUpload
|
|
277
|
+
handleClickOpenUpload,
|
|
278
|
+
isTeacher
|
|
278
279
|
}) {
|
|
279
280
|
const [isShareDrawerOpen, setIsShareDrawerOpen] = (0, _react.useState)(false);
|
|
280
281
|
const [isUploadVideoOpen, setIsUploadVideoOpen] = (0, _react.useState)(false);
|
|
@@ -309,7 +310,7 @@ function OverflowMenu({
|
|
|
309
310
|
onClick: leaveCourse
|
|
310
311
|
}, /*#__PURE__*/_react.default.createElement(_CardElements.CardMenuIcon, null, /*#__PURE__*/_react.default.createElement(_ExitToApp.default, {
|
|
311
312
|
fontSize: "small"
|
|
312
|
-
})), /*#__PURE__*/_react.default.createElement(_material.Typography, null, t("leave_course"))),
|
|
313
|
+
})), /*#__PURE__*/_react.default.createElement(_material.Typography, null, t("leave_course"))), isTeacher && /*#__PURE__*/_react.default.createElement(_material.MenuItem, {
|
|
313
314
|
onClick: handleClick,
|
|
314
315
|
"data-cy": "share-topic"
|
|
315
316
|
}, /*#__PURE__*/_react.default.createElement(_CardElements.CardMenuIcon, null, /*#__PURE__*/_react.default.createElement(_Share.default, {
|
|
@@ -1208,7 +1209,8 @@ function Topic({
|
|
|
1208
1209
|
videoUrl: videoUrl,
|
|
1209
1210
|
handleUpdateTopic: handleUpdateTopic,
|
|
1210
1211
|
handleUploadVideo: handleUploadVideo,
|
|
1211
|
-
deleteTopicVideo: deleteTopicVideo
|
|
1212
|
+
deleteTopicVideo: deleteTopicVideo,
|
|
1213
|
+
isTeacher: !isStudent
|
|
1212
1214
|
}), /*#__PURE__*/_react.default.createElement(_ResponsiveDialog.default, {
|
|
1213
1215
|
open: isUploadPdfOpen,
|
|
1214
1216
|
dialogTitle: t("upload_pdf"),
|
|
@@ -14,6 +14,16 @@ var _AvatarSelector = _interopRequireDefault(require("../../Misc/AvatarSelector/
|
|
|
14
14
|
var _InputHelper = _interopRequireDefault(require("../../Forms/InputHelper/InputHelper"));
|
|
15
15
|
var _utils = require("../../utils");
|
|
16
16
|
var _AudioNuala = _interopRequireDefault(require("../../img/AudioNuala.svg"));
|
|
17
|
+
var _papaparse = _interopRequireDefault(require("papaparse"));
|
|
18
|
+
var _PlayArrow = _interopRequireDefault(require("@mui/icons-material/PlayArrow"));
|
|
19
|
+
var _jszip = _interopRequireDefault(require("jszip"));
|
|
20
|
+
var _fileSaver = require("file-saver");
|
|
21
|
+
var _lab = require("@mui/lab");
|
|
22
|
+
var _Add = _interopRequireDefault(require("@mui/icons-material/Add"));
|
|
23
|
+
var _Download = _interopRequireDefault(require("@mui/icons-material/Download"));
|
|
24
|
+
var _FileUpload = _interopRequireDefault(require("@mui/icons-material/FileUpload"));
|
|
25
|
+
var _ResponsiveDialog = _interopRequireDefault(require("../../Dialogs/ResponsiveDialog/ResponsiveDialog"));
|
|
26
|
+
var _Delete = _interopRequireDefault(require("@mui/icons-material/Delete"));
|
|
17
27
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
18
28
|
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
19
29
|
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
@@ -97,7 +107,8 @@ function ActorForm({
|
|
|
97
107
|
filteredVoices,
|
|
98
108
|
setFieldValue,
|
|
99
109
|
setCheckAudioUrl,
|
|
100
|
-
formik
|
|
110
|
+
formik,
|
|
111
|
+
csv = false
|
|
101
112
|
}) {
|
|
102
113
|
const [avatarSelector, setAvatarSelector] = (0, _react.useState)(false);
|
|
103
114
|
const handleAvatarSelection = value => {
|
|
@@ -149,7 +160,9 @@ function ActorForm({
|
|
|
149
160
|
helperText: touched?.actor?.voice && errors?.actor?.voice,
|
|
150
161
|
error: touched?.actor?.voice && Boolean(errors?.actor?.voice),
|
|
151
162
|
voicePitch: actor.voicePitch,
|
|
152
|
-
onVoicePitchChange: handleVoicePitchChange
|
|
163
|
+
onVoicePitchChange: handleVoicePitchChange,
|
|
164
|
+
csv: csv,
|
|
165
|
+
generateAudio: true
|
|
153
166
|
}), /*#__PURE__*/_react.default.createElement(_AvatarSelector.default, {
|
|
154
167
|
t: t,
|
|
155
168
|
open: avatarSelector,
|
|
@@ -157,7 +170,7 @@ function ActorForm({
|
|
|
157
170
|
picture: actor.picture,
|
|
158
171
|
handleClose: () => setAvatarSelector(false),
|
|
159
172
|
handleSubmit: handleAvatarSelection
|
|
160
|
-
}), formik.values.actor.voice && /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_material.Box, {
|
|
173
|
+
}), formik.values.actor.voice && !csv && /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_material.Box, {
|
|
161
174
|
sx: {
|
|
162
175
|
width: "100%",
|
|
163
176
|
px: 1,
|
|
@@ -180,6 +193,193 @@ function ActorForm({
|
|
|
180
193
|
learnLang: learnLang
|
|
181
194
|
}))));
|
|
182
195
|
}
|
|
196
|
+
function getVoiceLanguageCode(voice, languages) {
|
|
197
|
+
for (const languageCode in languages) {
|
|
198
|
+
const voicesObject = languages[languageCode].Voices;
|
|
199
|
+
if (voicesObject) {
|
|
200
|
+
for (const langKey in voicesObject) {
|
|
201
|
+
const voiceOptions = voicesObject[langKey].voiceOptions;
|
|
202
|
+
const matchingVoice = voiceOptions?.find(option => option.name === voice);
|
|
203
|
+
if (matchingVoice) {
|
|
204
|
+
return langKey;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
return null;
|
|
210
|
+
}
|
|
211
|
+
function AddPhraseDialog({
|
|
212
|
+
t,
|
|
213
|
+
open,
|
|
214
|
+
onClose,
|
|
215
|
+
handleAddPhrase,
|
|
216
|
+
languages,
|
|
217
|
+
avatars,
|
|
218
|
+
handleSpeak,
|
|
219
|
+
langChar
|
|
220
|
+
}) {
|
|
221
|
+
const [checkAudioUrl, setCheckAudioUrl] = (0, _react.useState)(false);
|
|
222
|
+
const [filteredVoices, setFilteredVoices] = (0, _react.useState)([]);
|
|
223
|
+
const [learnLang, setLearnLang] = (0, _react.useState)("english");
|
|
224
|
+
const formik = (0, _formik.useFormik)({
|
|
225
|
+
initialValues: {
|
|
226
|
+
learnLang: "english",
|
|
227
|
+
actor: {
|
|
228
|
+
voice: "",
|
|
229
|
+
voiceLanguageCode: "",
|
|
230
|
+
voicePitch: "",
|
|
231
|
+
picture: ""
|
|
232
|
+
},
|
|
233
|
+
phraseToSpeak: "",
|
|
234
|
+
voiceSpeed: "",
|
|
235
|
+
fileName: ""
|
|
236
|
+
},
|
|
237
|
+
validationSchema: Yup.object({
|
|
238
|
+
actor: Yup.object().shape({
|
|
239
|
+
voice: Yup.string().nullable(),
|
|
240
|
+
voiceLanguageCode: Yup.string().nullable(),
|
|
241
|
+
voicePitch: Yup.string().nullable(),
|
|
242
|
+
picture: Yup.string().nullable()
|
|
243
|
+
}),
|
|
244
|
+
phraseToSpeak: Yup.string().required("Required"),
|
|
245
|
+
fileName: Yup.string()
|
|
246
|
+
}),
|
|
247
|
+
onSubmit: values => {
|
|
248
|
+
const phraseToAdd = {
|
|
249
|
+
phrase: values.phraseToSpeak,
|
|
250
|
+
actor: values.actor,
|
|
251
|
+
fileName: values.fileName
|
|
252
|
+
};
|
|
253
|
+
handleAddPhrase(phraseToAdd);
|
|
254
|
+
formik.resetForm();
|
|
255
|
+
onClose();
|
|
256
|
+
}
|
|
257
|
+
});
|
|
258
|
+
(0, _react.useEffect)(() => {
|
|
259
|
+
setCheckAudioUrl(true);
|
|
260
|
+
}, [formik.values.phraseToSpeak]);
|
|
261
|
+
(0, _react.useEffect)(() => {
|
|
262
|
+
if (learnLang) {
|
|
263
|
+
const voicesForLang = languages[learnLang]?.Voices || [];
|
|
264
|
+
setFilteredVoices(voicesForLang);
|
|
265
|
+
}
|
|
266
|
+
}, [learnLang, languages]);
|
|
267
|
+
const handleLanguageChange = e => {
|
|
268
|
+
const selectedLang = e.target.value;
|
|
269
|
+
setLearnLang(selectedLang);
|
|
270
|
+
formik.setFieldValue("actor.voice", "");
|
|
271
|
+
setCheckAudioUrl(true);
|
|
272
|
+
};
|
|
273
|
+
return /*#__PURE__*/_react.default.createElement(_ResponsiveDialog.default, {
|
|
274
|
+
open: open,
|
|
275
|
+
onClose: onClose,
|
|
276
|
+
maxWidth: "80%"
|
|
277
|
+
}, /*#__PURE__*/_react.default.createElement(_material.DialogTitle, null, t("add_phrase")), /*#__PURE__*/_react.default.createElement(_material.DialogContent, null, /*#__PURE__*/_react.default.createElement(_material.Grid, {
|
|
278
|
+
container: true,
|
|
279
|
+
spacing: 2
|
|
280
|
+
}, /*#__PURE__*/_react.default.createElement(_material.Grid, {
|
|
281
|
+
item: true,
|
|
282
|
+
xs: 12,
|
|
283
|
+
marginTop: 2
|
|
284
|
+
}, /*#__PURE__*/_react.default.createElement(_LanguageSelector.default, {
|
|
285
|
+
id: "learnLang",
|
|
286
|
+
name: "learnLang",
|
|
287
|
+
label: t("language"),
|
|
288
|
+
fullWidth: true,
|
|
289
|
+
required: true,
|
|
290
|
+
t: t,
|
|
291
|
+
languages: languages,
|
|
292
|
+
value: learnLang,
|
|
293
|
+
onChange: handleLanguageChange,
|
|
294
|
+
onBlur: formik.handleBlur
|
|
295
|
+
})), /*#__PURE__*/_react.default.createElement(_material.Grid, {
|
|
296
|
+
item: true,
|
|
297
|
+
xs: 12
|
|
298
|
+
}, /*#__PURE__*/_react.default.createElement(ActorForm, {
|
|
299
|
+
t: t,
|
|
300
|
+
actor: formik.values.actor,
|
|
301
|
+
handleBlur: formik.handleBlur,
|
|
302
|
+
touched: formik.touched,
|
|
303
|
+
errors: formik.errors,
|
|
304
|
+
learnLang: learnLang,
|
|
305
|
+
filteredVoices: filteredVoices,
|
|
306
|
+
handleSpeak: handleSpeak,
|
|
307
|
+
avatars: avatars,
|
|
308
|
+
langChar: langChar,
|
|
309
|
+
setFieldValue: formik.setFieldValue,
|
|
310
|
+
formik: formik,
|
|
311
|
+
setCheckAudioUrl: setCheckAudioUrl,
|
|
312
|
+
csv: true
|
|
313
|
+
})), /*#__PURE__*/_react.default.createElement(_material.Grid, {
|
|
314
|
+
item: true,
|
|
315
|
+
xs: 12
|
|
316
|
+
}, /*#__PURE__*/_react.default.createElement(_material.TextField, {
|
|
317
|
+
id: "fileName",
|
|
318
|
+
"data-cy": "fileName",
|
|
319
|
+
name: "fileName",
|
|
320
|
+
label: t("file_name"),
|
|
321
|
+
value: formik.values.fileName,
|
|
322
|
+
onChange: formik.handleChange,
|
|
323
|
+
onBlur: formik.handleBlur,
|
|
324
|
+
type: "text",
|
|
325
|
+
margin: "normal",
|
|
326
|
+
variant: "outlined",
|
|
327
|
+
fullWidth: true,
|
|
328
|
+
helperText: formik.touched.fileName && formik.errors.fileName,
|
|
329
|
+
error: formik.touched.fileName && Boolean(formik.errors.fileName),
|
|
330
|
+
InputProps: {
|
|
331
|
+
endAdornment: /*#__PURE__*/_react.default.createElement(_material.InputAdornment, {
|
|
332
|
+
position: "end"
|
|
333
|
+
}, ".mp3")
|
|
334
|
+
}
|
|
335
|
+
})), /*#__PURE__*/_react.default.createElement(_material.Grid, {
|
|
336
|
+
item: true,
|
|
337
|
+
xs: 12,
|
|
338
|
+
marginTop: -1
|
|
339
|
+
}, /*#__PURE__*/_react.default.createElement(_InputHelper.default, {
|
|
340
|
+
t: t,
|
|
341
|
+
id: "phraseToSpeak",
|
|
342
|
+
"data-cy": "phraseToSpeak",
|
|
343
|
+
name: "phraseToSpeak",
|
|
344
|
+
label: t("phrase_to_speak"),
|
|
345
|
+
value: formik.values.phraseToSpeak,
|
|
346
|
+
onChange: formik.handleChange,
|
|
347
|
+
onBlur: formik.handleBlur,
|
|
348
|
+
type: "text",
|
|
349
|
+
margin: "normal",
|
|
350
|
+
variant: "outlined",
|
|
351
|
+
fullWidth: true,
|
|
352
|
+
required: true,
|
|
353
|
+
multiline: true,
|
|
354
|
+
characters: langChar,
|
|
355
|
+
learnLang: learnLang,
|
|
356
|
+
helperText: formik.touched.phraseToSpeak && formik.errors.phraseToSpeak,
|
|
357
|
+
error: formik.touched.phraseToSpeak && Boolean(formik.errors.phraseToSpeak)
|
|
358
|
+
})))), /*#__PURE__*/_react.default.createElement(_material.DialogActions, null, /*#__PURE__*/_react.default.createElement(_material.Button, {
|
|
359
|
+
onClick: onClose
|
|
360
|
+
}, t("close")), /*#__PURE__*/_react.default.createElement(_material.Button, {
|
|
361
|
+
variant: "outlined",
|
|
362
|
+
color: "primary",
|
|
363
|
+
disabled: formik.values.phraseToSpeak === "" || !formik.values.actor.voice,
|
|
364
|
+
onClick: () => handleSpeak({
|
|
365
|
+
text: formik.values.phraseToSpeak,
|
|
366
|
+
learnLanguage: learnLang,
|
|
367
|
+
voiceName: formik.values.actor.voice,
|
|
368
|
+
mute: false,
|
|
369
|
+
callback: () => {},
|
|
370
|
+
textContainer: null,
|
|
371
|
+
languageCode: formik.values.actor.voiceLanguageCode,
|
|
372
|
+
isHoverText: false,
|
|
373
|
+
pitch: formik.values.actor.voicePitch,
|
|
374
|
+
voiceSpeed: formik.values.voiceSpeed
|
|
375
|
+
})
|
|
376
|
+
}, t("play_audio")), /*#__PURE__*/_react.default.createElement(_material.Button, {
|
|
377
|
+
variant: "contained",
|
|
378
|
+
onClick: formik.handleSubmit,
|
|
379
|
+
color: "primary",
|
|
380
|
+
disabled: formik.values.phraseToSpeak === "" || !formik.values.actor.voice
|
|
381
|
+
}, t("add_phrase"))));
|
|
382
|
+
}
|
|
183
383
|
function GenerateAudio({
|
|
184
384
|
t,
|
|
185
385
|
handleSpeak,
|
|
@@ -187,12 +387,18 @@ function GenerateAudio({
|
|
|
187
387
|
languages,
|
|
188
388
|
langChar,
|
|
189
389
|
downloadAudio,
|
|
190
|
-
audioUrl
|
|
390
|
+
audioUrl,
|
|
391
|
+
openSnackbar
|
|
191
392
|
}) {
|
|
192
393
|
const [learnLang, setLearnLang] = (0, _react.useState)("english");
|
|
193
394
|
const [filteredVoices, setFilteredVoices] = (0, _react.useState)([]);
|
|
194
395
|
const [checkAudioUrl, setCheckAudioUrl] = (0, _react.useState)(false);
|
|
195
396
|
const [voiceSpeed, setVoiceSpeed] = (0, _react.useState)(50);
|
|
397
|
+
const [showCSV, setShowCSV] = (0, _react.useState)(false);
|
|
398
|
+
const [csvData, setCsvData] = (0, _react.useState)([]);
|
|
399
|
+
const [csvHeaders, setCsvHeaders] = (0, _react.useState)(["phrase", "fileName", "voice"]);
|
|
400
|
+
const [isGenerating, setIsGenerating] = (0, _react.useState)(false);
|
|
401
|
+
const [dialogOpen, setDialogOpen] = (0, _react.useState)(false);
|
|
196
402
|
const formik = (0, _formik.useFormik)({
|
|
197
403
|
initialValues: {
|
|
198
404
|
actor: {
|
|
@@ -216,7 +422,7 @@ function GenerateAudio({
|
|
|
216
422
|
phraseToSpeak: Yup.string().required("Required").test("noSpecialChars", "No special characters", value => !(0, _utils.containsInvalidSymbols)(value))
|
|
217
423
|
}),
|
|
218
424
|
onSubmit: values => {
|
|
219
|
-
handleSpeak(values.phraseToSpeak,
|
|
425
|
+
handleSpeak(values.phraseToSpeak, values.actor.voice);
|
|
220
426
|
}
|
|
221
427
|
});
|
|
222
428
|
(0, _react.useEffect)(() => {
|
|
@@ -237,6 +443,187 @@ function GenerateAudio({
|
|
|
237
443
|
const handleSpeedChange = (event, newValue) => {
|
|
238
444
|
setVoiceSpeed(newValue);
|
|
239
445
|
};
|
|
446
|
+
const playPhraseAudio = (phrase, rowVoice) => {
|
|
447
|
+
const voiceToUse = rowVoice || formik.values.actor.voice || "Joey";
|
|
448
|
+
handleSpeak({
|
|
449
|
+
text: phrase,
|
|
450
|
+
learnLanguage: formik.values.learnLang || "english",
|
|
451
|
+
voiceName: voiceToUse,
|
|
452
|
+
mute: false,
|
|
453
|
+
callback: () => {},
|
|
454
|
+
textContainer: null,
|
|
455
|
+
languageCode: getVoiceLanguageCode(voiceToUse, languages),
|
|
456
|
+
isHoverText: false,
|
|
457
|
+
pitch: null,
|
|
458
|
+
voiceSpeed: null
|
|
459
|
+
});
|
|
460
|
+
};
|
|
461
|
+
const languagesContainsVoice = voice => {
|
|
462
|
+
for (const languageCode in languages) {
|
|
463
|
+
const voicesObject = languages[languageCode].Voices;
|
|
464
|
+
if (voicesObject) {
|
|
465
|
+
for (const langKey in voicesObject) {
|
|
466
|
+
const voiceOptions = voicesObject[langKey].voiceOptions;
|
|
467
|
+
if (voiceOptions?.find(option => option.name === voice)) {
|
|
468
|
+
return true;
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
return false;
|
|
474
|
+
};
|
|
475
|
+
const handleAddPhrase = newPhrase => {
|
|
476
|
+
csvHeaders.length === 0 && setCsvHeaders(["phrase", "fileName", "voice"]);
|
|
477
|
+
const fileName = `audio_${csvData.length + 1}_${new Date().toISOString().replace(/:/g, "-").slice(0, 19)}.mp3`;
|
|
478
|
+
if (newPhrase.fileName && !newPhrase.fileName.endsWith(".mp3")) {
|
|
479
|
+
newPhrase.fileName = `${newPhrase.fileName}.mp3`;
|
|
480
|
+
}
|
|
481
|
+
const phraseWithDefaults = {
|
|
482
|
+
phrase: newPhrase.phrase,
|
|
483
|
+
fileName: newPhrase.fileName || fileName,
|
|
484
|
+
voice: newPhrase.actor.voice || "Joey"
|
|
485
|
+
};
|
|
486
|
+
setCsvData([...csvData, phraseWithDefaults]);
|
|
487
|
+
};
|
|
488
|
+
const downloadCSVTemplate = () => {
|
|
489
|
+
const csvTemplate = "phrase,fileName,voice\nThis is a test phrase,Test.mp3,Joey\n";
|
|
490
|
+
downloadCSV(csvTemplate, "template.csv");
|
|
491
|
+
};
|
|
492
|
+
const handleCSVUpload = event => {
|
|
493
|
+
const file = event.target.files[0];
|
|
494
|
+
if (file) {
|
|
495
|
+
_papaparse.default.parse(file, {
|
|
496
|
+
header: true,
|
|
497
|
+
skipEmptyLines: true,
|
|
498
|
+
complete: function (results) {
|
|
499
|
+
let headers = results.meta.fields || [];
|
|
500
|
+
|
|
501
|
+
// Ensure 'phrase' is present in the headers
|
|
502
|
+
if (headers.includes("phrase")) {
|
|
503
|
+
if (!headers.includes("fileName")) {
|
|
504
|
+
headers.push("fileName");
|
|
505
|
+
}
|
|
506
|
+
if (!headers.includes("voice")) {
|
|
507
|
+
headers.push("voice");
|
|
508
|
+
}
|
|
509
|
+
const data = results.data.map((row, index) => {
|
|
510
|
+
if (!row.phrase) {
|
|
511
|
+
openSnackbar(`Row ${index + 1} is missing a phrase.`, "error");
|
|
512
|
+
return null; // Invalid row, will be filtered out
|
|
513
|
+
}
|
|
514
|
+
if (!row.fileName) {
|
|
515
|
+
row.fileName = `audio_${index + 1}_${new Date().toISOString().replace(/:/g, "-").slice(0, 19)}.mp3`;
|
|
516
|
+
} else {
|
|
517
|
+
row.fileName = row.fileName.endsWith(".mp3") ? row.fileName : `${row.fileName}.mp3`;
|
|
518
|
+
}
|
|
519
|
+
row.voice = languagesContainsVoice(row.voice) ? row.voice : "Joey";
|
|
520
|
+
return row;
|
|
521
|
+
}).filter(Boolean);
|
|
522
|
+
setCsvData(csvData.length > 0 ? [...csvData, ...data] : data);
|
|
523
|
+
setCsvHeaders(csvHeaders.length > 0 ? csvHeaders : headers);
|
|
524
|
+
} else {
|
|
525
|
+
openSnackbar("CSV must contain 'phrase' header.", "error");
|
|
526
|
+
removeCSVFile();
|
|
527
|
+
}
|
|
528
|
+
},
|
|
529
|
+
error: function (error) {
|
|
530
|
+
console.error("Error parsing CSV: ", error);
|
|
531
|
+
}
|
|
532
|
+
});
|
|
533
|
+
}
|
|
534
|
+
};
|
|
535
|
+
const removeCSVFile = () => {
|
|
536
|
+
setCsvData([]);
|
|
537
|
+
setCsvHeaders([]);
|
|
538
|
+
};
|
|
539
|
+
const handleDeleteRow = rowIndex => {
|
|
540
|
+
const updatedCsvData = csvData.filter((_, index) => index !== rowIndex);
|
|
541
|
+
setCsvData(updatedCsvData);
|
|
542
|
+
};
|
|
543
|
+
const handleChange = (event, newValue) => {
|
|
544
|
+
setShowCSV(newValue);
|
|
545
|
+
};
|
|
546
|
+
const downloadCSV = (text, filename) => {
|
|
547
|
+
const element = document.createElement("a");
|
|
548
|
+
const file = new Blob([text], {
|
|
549
|
+
type: "text/plain"
|
|
550
|
+
});
|
|
551
|
+
element.href = URL.createObjectURL(file);
|
|
552
|
+
element.download = filename;
|
|
553
|
+
document.body.appendChild(element); // Required for this to work in FireFox
|
|
554
|
+
element.click();
|
|
555
|
+
};
|
|
556
|
+
const generateAudioForCSV = async () => {
|
|
557
|
+
const zip = new _jszip.default();
|
|
558
|
+
const timestamp = new Date().toISOString().replace(/:/g, "-").slice(0, 19);
|
|
559
|
+
const folder = zip.folder(`audio_files_${timestamp}`);
|
|
560
|
+
setIsGenerating(true);
|
|
561
|
+
const fileNameCount = {};
|
|
562
|
+
try {
|
|
563
|
+
for (const row of csvData) {
|
|
564
|
+
const phrase = row.phrase;
|
|
565
|
+
let fileName = row.fileName || `audio_${new Date().toISOString().replace(/:/g, "-").slice(0, 19)}`;
|
|
566
|
+
const rowVoice = row.voice || formik.values.actor.voice;
|
|
567
|
+
if (!phrase) {
|
|
568
|
+
openSnackbar("Invalid CSV data: 'phrase' column is required", "error");
|
|
569
|
+
continue;
|
|
570
|
+
}
|
|
571
|
+
try {
|
|
572
|
+
const result = await handleSpeak({
|
|
573
|
+
text: phrase,
|
|
574
|
+
learnLanguage: learnLang,
|
|
575
|
+
voiceName: rowVoice,
|
|
576
|
+
mute: true,
|
|
577
|
+
callback: () => {},
|
|
578
|
+
textContainer: null,
|
|
579
|
+
languageCode: getVoiceLanguageCode(rowVoice, languages),
|
|
580
|
+
isHoverText: false,
|
|
581
|
+
pitch: null,
|
|
582
|
+
voiceSpeed: null
|
|
583
|
+
});
|
|
584
|
+
const audioUrl = result ? result.audioUrl : null;
|
|
585
|
+
if (!audioUrl) continue;
|
|
586
|
+
const response = await fetch(audioUrl);
|
|
587
|
+
if (!response.ok) {
|
|
588
|
+
openSnackbar(`Failed to fetch audio for phrase: "${phrase}"`, "error");
|
|
589
|
+
continue;
|
|
590
|
+
}
|
|
591
|
+
const blob = await response.blob();
|
|
592
|
+
let fileNameWithExtension = fileName.endsWith(".mp3") ? fileName : `${fileName}.mp3`;
|
|
593
|
+
const contentType = blob.type;
|
|
594
|
+
const allowedAudioTypes = ["audio/mpeg", "audio/wav", "audio/ogg", "application/octet-stream"];
|
|
595
|
+
if (!allowedAudioTypes.includes(contentType)) {
|
|
596
|
+
openSnackbar(`Unsupported audio type for phrase: "${phrase}"`, "error");
|
|
597
|
+
continue;
|
|
598
|
+
}
|
|
599
|
+
if (fileNameCount[fileNameWithExtension]) {
|
|
600
|
+
fileNameCount[fileNameWithExtension] += 1;
|
|
601
|
+
const baseName = fileNameWithExtension.replace(".mp3", "");
|
|
602
|
+
fileNameWithExtension = `${baseName}_${fileNameCount[fileNameWithExtension]}.mp3`;
|
|
603
|
+
} else {
|
|
604
|
+
fileNameCount[fileNameWithExtension] = 1;
|
|
605
|
+
}
|
|
606
|
+
folder.file(fileNameWithExtension, blob);
|
|
607
|
+
} catch (error) {
|
|
608
|
+
console.error(`Error generating audio for ${fileName}: ${error.message}`);
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
// Prepare CSV data with updated headers and rows
|
|
613
|
+
const csvContent = [csvHeaders.join(","), ...csvData.map(row => csvHeaders.map(header => row[header]).join(","))].join("\n");
|
|
614
|
+
|
|
615
|
+
// Add CSV file to zip
|
|
616
|
+
zip.file(`updated_data_${timestamp}.csv`, csvContent);
|
|
617
|
+
const zipBlob = await zip.generateAsync({
|
|
618
|
+
type: "blob"
|
|
619
|
+
});
|
|
620
|
+
(0, _fileSaver.saveAs)(zipBlob, `audio_files_${timestamp}.zip`);
|
|
621
|
+
} catch (error) {
|
|
622
|
+
console.error(`Error generating audio files: ${error.message}`);
|
|
623
|
+
} finally {
|
|
624
|
+
setIsGenerating(false);
|
|
625
|
+
}
|
|
626
|
+
};
|
|
240
627
|
return /*#__PURE__*/_react.default.createElement("form", {
|
|
241
628
|
onSubmit: formik.handleSubmit
|
|
242
629
|
}, /*#__PURE__*/_react.default.createElement(_material.Grid, {
|
|
@@ -248,16 +635,43 @@ function GenerateAudio({
|
|
|
248
635
|
}
|
|
249
636
|
}, /*#__PURE__*/_react.default.createElement(_material.Grid, {
|
|
250
637
|
item: true,
|
|
251
|
-
xs:
|
|
638
|
+
xs: 6,
|
|
639
|
+
md: 4,
|
|
252
640
|
style: {
|
|
253
|
-
textAlign: "center"
|
|
641
|
+
textAlign: "center",
|
|
642
|
+
marginTop: "15px"
|
|
254
643
|
}
|
|
255
644
|
}, /*#__PURE__*/_react.default.createElement("img", {
|
|
256
645
|
src: _AudioNuala.default,
|
|
257
646
|
alt: "Audio Nuala",
|
|
258
647
|
style: {
|
|
259
|
-
maxWidth: "
|
|
260
|
-
|
|
648
|
+
maxWidth: "300px"
|
|
649
|
+
}
|
|
650
|
+
})), /*#__PURE__*/_react.default.createElement(_material.Grid, {
|
|
651
|
+
item: true,
|
|
652
|
+
xs: 6,
|
|
653
|
+
md: 4,
|
|
654
|
+
style: {
|
|
655
|
+
textAlign: "left"
|
|
656
|
+
}
|
|
657
|
+
}, /*#__PURE__*/_react.default.createElement(_material.Typography, {
|
|
658
|
+
variant: "h5",
|
|
659
|
+
fontWeight: "bold"
|
|
660
|
+
}, t("text_studio")), /*#__PURE__*/_react.default.createElement(_material.Typography, {
|
|
661
|
+
variant: "body1",
|
|
662
|
+
gutterBottom: true
|
|
663
|
+
}, t("text_studio_description"))), /*#__PURE__*/_react.default.createElement(_material.Grid, {
|
|
664
|
+
item: true,
|
|
665
|
+
xs: 12,
|
|
666
|
+
md: 8,
|
|
667
|
+
marginTop: 2,
|
|
668
|
+
marginBottom: 1,
|
|
669
|
+
style: {
|
|
670
|
+
textAlign: "center"
|
|
671
|
+
}
|
|
672
|
+
}, /*#__PURE__*/_react.default.createElement(_material.Divider, {
|
|
673
|
+
sx: {
|
|
674
|
+
borderBottomWidth: 4
|
|
261
675
|
}
|
|
262
676
|
})), /*#__PURE__*/_react.default.createElement(_material.Grid, {
|
|
263
677
|
item: true,
|
|
@@ -268,9 +682,28 @@ function GenerateAudio({
|
|
|
268
682
|
}, /*#__PURE__*/_react.default.createElement(_material.Grid, {
|
|
269
683
|
item: true,
|
|
270
684
|
xs: 12,
|
|
271
|
-
md:
|
|
272
|
-
|
|
273
|
-
|
|
685
|
+
md: 12,
|
|
686
|
+
marginTop: 2,
|
|
687
|
+
marginBottom: 1.5
|
|
688
|
+
}, /*#__PURE__*/_react.default.createElement(_material.ToggleButtonGroup, {
|
|
689
|
+
color: "primary",
|
|
690
|
+
value: showCSV,
|
|
691
|
+
exclusive: true,
|
|
692
|
+
onChange: handleChange,
|
|
693
|
+
"aria-label": "Platform",
|
|
694
|
+
sx: {
|
|
695
|
+
marginLeft: "auto",
|
|
696
|
+
height: "30px"
|
|
697
|
+
}
|
|
698
|
+
}, /*#__PURE__*/_react.default.createElement(_material.ToggleButton, {
|
|
699
|
+
value: false
|
|
700
|
+
}, t("single_phrase")), /*#__PURE__*/_react.default.createElement(_material.ToggleButton, {
|
|
701
|
+
value: true
|
|
702
|
+
}, t("list_of_phrases")))), /*#__PURE__*/_react.default.createElement(_material.Grid, {
|
|
703
|
+
item: true,
|
|
704
|
+
xs: 12,
|
|
705
|
+
md: 12
|
|
706
|
+
}, !showCSV && /*#__PURE__*/_react.default.createElement(_LanguageSelector.default, {
|
|
274
707
|
id: "learnLang",
|
|
275
708
|
name: "learnLang",
|
|
276
709
|
"data-cy": "learnLang",
|
|
@@ -287,9 +720,8 @@ function GenerateAudio({
|
|
|
287
720
|
})), /*#__PURE__*/_react.default.createElement(_material.Grid, {
|
|
288
721
|
item: true,
|
|
289
722
|
xs: 12,
|
|
290
|
-
md:
|
|
291
|
-
|
|
292
|
-
}, /*#__PURE__*/_react.default.createElement(ActorForm, {
|
|
723
|
+
md: 12
|
|
724
|
+
}, !showCSV && /*#__PURE__*/_react.default.createElement(ActorForm, {
|
|
293
725
|
t: t,
|
|
294
726
|
actor: formik.values.actor,
|
|
295
727
|
handleBlur: formik.handleBlur,
|
|
@@ -311,7 +743,7 @@ function GenerateAudio({
|
|
|
311
743
|
xs: 12,
|
|
312
744
|
md: 12,
|
|
313
745
|
marginBottom: 2
|
|
314
|
-
}, /*#__PURE__*/_react.default.createElement(_InputHelper.default, {
|
|
746
|
+
}, !showCSV ? /*#__PURE__*/_react.default.createElement(_InputHelper.default, {
|
|
315
747
|
t: t,
|
|
316
748
|
id: "phraseToSpeak",
|
|
317
749
|
"data-cy": "phraseToSpeak",
|
|
@@ -330,7 +762,144 @@ function GenerateAudio({
|
|
|
330
762
|
learnLang: learnLang,
|
|
331
763
|
helperText: formik.touched.phraseToSpeak && formik.errors.phraseToSpeak,
|
|
332
764
|
error: formik.touched.phraseToSpeak && Boolean(formik.errors.phraseToSpeak)
|
|
765
|
+
}) : /*#__PURE__*/_react.default.createElement(_material.Grid, {
|
|
766
|
+
container: true,
|
|
767
|
+
item: true,
|
|
768
|
+
xs: 12,
|
|
769
|
+
md: 12,
|
|
770
|
+
spacing: 1,
|
|
771
|
+
marginTop: 0.5,
|
|
772
|
+
marginBottom: 1,
|
|
773
|
+
sx: {
|
|
774
|
+
display: "flex",
|
|
775
|
+
justifyContent: "left",
|
|
776
|
+
alignItems: "center"
|
|
777
|
+
}
|
|
778
|
+
}, /*#__PURE__*/_react.default.createElement(_material.Grid, {
|
|
779
|
+
item: true
|
|
780
|
+
}, /*#__PURE__*/_react.default.createElement(_material.Button, {
|
|
781
|
+
startIcon: /*#__PURE__*/_react.default.createElement(_Add.default, null),
|
|
782
|
+
onClick: () => setDialogOpen(true),
|
|
783
|
+
variant: "contained",
|
|
784
|
+
sx: {
|
|
785
|
+
marginBottom: 2
|
|
786
|
+
}
|
|
787
|
+
}, t("add_phrase"))), /*#__PURE__*/_react.default.createElement(_material.Grid, {
|
|
788
|
+
item: true
|
|
789
|
+
}, /*#__PURE__*/_react.default.createElement("label", {
|
|
790
|
+
htmlFor: "upload-csv"
|
|
791
|
+
}, /*#__PURE__*/_react.default.createElement(_material.Button, {
|
|
792
|
+
variant: "contained",
|
|
793
|
+
component: "span",
|
|
794
|
+
startIcon: /*#__PURE__*/_react.default.createElement(_FileUpload.default, null),
|
|
795
|
+
sx: {
|
|
796
|
+
marginBottom: 2
|
|
797
|
+
}
|
|
798
|
+
}, t("upload_csv"))), /*#__PURE__*/_react.default.createElement("input", {
|
|
799
|
+
id: "upload-csv",
|
|
800
|
+
type: "file",
|
|
801
|
+
accept: ".csv",
|
|
802
|
+
onChange: handleCSVUpload,
|
|
803
|
+
style: {
|
|
804
|
+
display: "none"
|
|
805
|
+
}
|
|
333
806
|
})), /*#__PURE__*/_react.default.createElement(_material.Grid, {
|
|
807
|
+
item: true
|
|
808
|
+
}, /*#__PURE__*/_react.default.createElement(_material.Button, {
|
|
809
|
+
variant: "outlined",
|
|
810
|
+
startIcon: /*#__PURE__*/_react.default.createElement(_Download.default, null),
|
|
811
|
+
onClick: downloadCSVTemplate,
|
|
812
|
+
sx: {
|
|
813
|
+
marginBottom: 2
|
|
814
|
+
}
|
|
815
|
+
}, t("download_csv_template"))), /*#__PURE__*/_react.default.createElement(_material.Grid, {
|
|
816
|
+
item: true,
|
|
817
|
+
xs: 12,
|
|
818
|
+
sx: {
|
|
819
|
+
justifyContent: "left"
|
|
820
|
+
}
|
|
821
|
+
}, csvData.length === 0 && /*#__PURE__*/_react.default.createElement(_material.Typography, {
|
|
822
|
+
variant: "body1",
|
|
823
|
+
sx: {
|
|
824
|
+
marginTop: 1
|
|
825
|
+
}
|
|
826
|
+
}, t("no_phrases_yet"))), /*#__PURE__*/_react.default.createElement(_material.Grid, {
|
|
827
|
+
container: true,
|
|
828
|
+
item: true,
|
|
829
|
+
xs: 12,
|
|
830
|
+
md: 12,
|
|
831
|
+
spacing: 1,
|
|
832
|
+
marginBottom: 1
|
|
833
|
+
}, csvData.length > 0 && /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_material.Grid, {
|
|
834
|
+
item: true,
|
|
835
|
+
xs: 12
|
|
836
|
+
}, /*#__PURE__*/_react.default.createElement(_material.TableContainer, {
|
|
837
|
+
component: _material.Paper
|
|
838
|
+
}, /*#__PURE__*/_react.default.createElement(_material.Table, {
|
|
839
|
+
sx: {
|
|
840
|
+
minWidth: 650
|
|
841
|
+
},
|
|
842
|
+
"aria-label": "csv table"
|
|
843
|
+
}, /*#__PURE__*/_react.default.createElement(_material.TableHead, null, /*#__PURE__*/_react.default.createElement(_material.TableRow, null, csvHeaders.map((header, index) => /*#__PURE__*/_react.default.createElement(_material.TableCell, {
|
|
844
|
+
key: index,
|
|
845
|
+
align: "center"
|
|
846
|
+
}, /*#__PURE__*/_react.default.createElement("strong", null, header))), /*#__PURE__*/_react.default.createElement(_material.TableCell, {
|
|
847
|
+
align: "center"
|
|
848
|
+
}, /*#__PURE__*/_react.default.createElement("strong", null, t("play_audio"))), /*#__PURE__*/_react.default.createElement(_material.TableCell, {
|
|
849
|
+
align: "center"
|
|
850
|
+
}, /*#__PURE__*/_react.default.createElement("strong", null, t("delete")), " "))), /*#__PURE__*/_react.default.createElement(_material.TableBody, null, csvData.map((row, rowIndex) => /*#__PURE__*/_react.default.createElement(_material.TableRow, {
|
|
851
|
+
key: rowIndex
|
|
852
|
+
}, csvHeaders.map((header, colIndex) => /*#__PURE__*/_react.default.createElement(_material.TableCell, {
|
|
853
|
+
key: colIndex,
|
|
854
|
+
align: "center"
|
|
855
|
+
}, row[header] || null)), /*#__PURE__*/_react.default.createElement(_material.TableCell, {
|
|
856
|
+
align: "center"
|
|
857
|
+
}, /*#__PURE__*/_react.default.createElement(_material.IconButton, {
|
|
858
|
+
onClick: () => playPhraseAudio(row.phrase, row.voice),
|
|
859
|
+
"aria-label": "play"
|
|
860
|
+
}, /*#__PURE__*/_react.default.createElement(_PlayArrow.default, null))), /*#__PURE__*/_react.default.createElement(_material.TableCell, {
|
|
861
|
+
align: "center"
|
|
862
|
+
}, /*#__PURE__*/_react.default.createElement(_material.IconButton, {
|
|
863
|
+
onClick: () => handleDeleteRow(rowIndex) // Call the row deletion function
|
|
864
|
+
,
|
|
865
|
+
"aria-label": "delete"
|
|
866
|
+
}, /*#__PURE__*/_react.default.createElement(_Delete.default, null))))))))))), csvData.length > 0 && /*#__PURE__*/_react.default.createElement(_material.Grid, {
|
|
867
|
+
item: true,
|
|
868
|
+
xs: 12,
|
|
869
|
+
sx: {
|
|
870
|
+
display: "flex",
|
|
871
|
+
justifyContent: "left",
|
|
872
|
+
alignItems: "center",
|
|
873
|
+
marginTop: 1
|
|
874
|
+
}
|
|
875
|
+
}, /*#__PURE__*/_react.default.createElement(_lab.LoadingButton, {
|
|
876
|
+
variant: "contained",
|
|
877
|
+
onClick: generateAudioForCSV,
|
|
878
|
+
loading: isGenerating,
|
|
879
|
+
startIcon: /*#__PURE__*/_react.default.createElement(_Download.default, null),
|
|
880
|
+
sx: {
|
|
881
|
+
marginBottom: 2
|
|
882
|
+
}
|
|
883
|
+
}, t("download_audio")))), /*#__PURE__*/_react.default.createElement(AddPhraseDialog, {
|
|
884
|
+
t: t,
|
|
885
|
+
open: dialogOpen,
|
|
886
|
+
onClose: () => setDialogOpen(false),
|
|
887
|
+
handleAddPhrase: handleAddPhrase,
|
|
888
|
+
initialValues: {
|
|
889
|
+
learnLang: "english",
|
|
890
|
+
actor: {
|
|
891
|
+
voice: "",
|
|
892
|
+
voiceLanguageCode: "",
|
|
893
|
+
voicePitch: "",
|
|
894
|
+
picture: ""
|
|
895
|
+
},
|
|
896
|
+
phraseToSpeak: "",
|
|
897
|
+
voiceSpeed: 50
|
|
898
|
+
},
|
|
899
|
+
languages: languages,
|
|
900
|
+
avatars: avatars,
|
|
901
|
+
handleSpeak: handleSpeak
|
|
902
|
+
})), !showCSV && /*#__PURE__*/_react.default.createElement(_material.Grid, {
|
|
334
903
|
container: true,
|
|
335
904
|
item: true,
|
|
336
905
|
xs: 12,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nualang/nualang-ui-components",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1175",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist",
|
|
@@ -41,6 +41,7 @@
|
|
|
41
41
|
"easymde": "2.18.0",
|
|
42
42
|
"emoji-mart": "5.5.2",
|
|
43
43
|
"export-to-csv": "^1.3.0",
|
|
44
|
+
"file-saver": "^2.0.5",
|
|
44
45
|
"formik": "^2.2.9",
|
|
45
46
|
"fs": "^0.0.1-security",
|
|
46
47
|
"immutability-helper": "^3.0",
|
|
@@ -48,6 +49,7 @@
|
|
|
48
49
|
"json-2-csv": "^5.5.1",
|
|
49
50
|
"jsonlint": "^1.6.3",
|
|
50
51
|
"jsonrepair": "^3.6.0",
|
|
52
|
+
"jszip": "^3.10.1",
|
|
51
53
|
"luxon": "^3.3.0",
|
|
52
54
|
"moment": "^2.29.4",
|
|
53
55
|
"n2words": "^1.21.0",
|