@nualang/nualang-ui-components 0.1.1412 → 0.1.1414
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/Assignments/AssignmentCardsList/AssignmentCardsList.js +4 -2
- package/dist/Dialogs/CreatePhrase/CreatePhrase.js +3 -1
- package/dist/Dialogs/CreatePhraseGroupDialog/CreatePhraseGroupDialog.js +4 -2
- package/dist/Dialogs/ImageBuilder/ImageBuilderDialog.js +3 -14
- package/dist/Dialogs/ImageBuilder/imageBuilderUtils.js +47 -5
- package/dist/Dialogs/QuickCreateChatbotDialog/QuickCreateChatbotDialog.js +146 -34
- package/dist/Dialogs/QuickCreateClassroomDialog/QuickCreateClassroomDialog.js +4 -2
- package/dist/Dialogs/QuickCreateCourseDialog/QuickCreateCourseDialog.js +4 -2
- package/dist/Dialogs/QuickCreateScenarioDialog/QuickCreateScenarioDialog.js +0 -1
- package/dist/Dialogs/QuickCreateTopicDialog/QuickCreateTopicDialog.js +4 -2
- package/dist/Editors/Bot/Bot.js +4 -2
- package/dist/Editors/Bot/Editor/BotDesigner/AddImageModal/AddImageModal.js +4 -2
- package/dist/Editors/Bot/Editor/BotDesigner/BotDesigner.js +4 -2
- package/dist/Editors/Bot/Editor/BotDesigner/VarList.js +7 -3
- package/dist/Editors/Bot/Editor/Editor.js +6 -3
- package/dist/Editors/PhraseList/PhraseList.js +6 -3
- package/dist/Editors/Phrases/Phrases.js +4 -2
- package/dist/Editors/Roleplay/Roleplay.js +4 -2
- package/dist/Exercises/ListenAndSpeak/ListenAndSpeak.js +1 -18
- package/dist/Exercises/Meaning/Meaning.js +1 -18
- package/dist/Exercises/Translator/Translator.js +27 -7
- package/dist/Forms/CreateBot/Steps/BotInformation/BotInformation.js +4 -2
- package/dist/Forms/CreateClassroom/Steps/Customization/Customization.js +6 -3
- package/dist/Forms/CreateCourse/Steps/Customization/Customization.js +6 -3
- package/dist/Forms/CreateMeetingMultiStepForm/CreateMeetingMultiStepForm.js +6 -3
- package/dist/Forms/CreateMeetingMultiStepForm/MeetingForm.js +6 -3
- package/dist/Forms/CreateRoleplay/Steps/RoleplayInformation/RoleplayInformation.js +4 -2
- package/dist/Forms/CreateTopic/Steps/Customization/Customization.js +6 -3
- package/dist/Forms/ImageSelector/ImageSelector.js +39 -9
- package/dist/Forms/UpdateBot/UpdateBot.js +3 -1
- package/dist/Forms/UpdateClassroom/UpdateClassroom.js +3 -1
- package/dist/Forms/UpdateCourse/UpdateCourse.js +3 -1
- package/dist/Forms/UpdatePhraseList/UpdatePhraseList.js +4 -2
- package/dist/Forms/UpdateRoleplay/UpdateRoleplay.js +4 -2
- package/dist/Forms/UpdateTopic/UpdateTopic.js +3 -1
- package/dist/Forms/VoiceSelector/VoiceSelector.js +713 -296
- package/dist/Forms/VoiceSelector/VoiceSelector.test.js +247 -4
- package/dist/Lists/CourseOutline/CourseOutline.js +3 -1
- package/dist/Lists/Exercises/Exercises.js +8 -3
- package/dist/Lists/Phrases/Phrases.js +4 -2
- package/dist/Misc/NotFound/ClassCourses.js +2 -1
- package/dist/Misc/NotFound/Courses.js +2 -1
- package/dist/Navigation/ResponsiveTabs/ResponsiveTabs.js +1 -1
- package/dist/Tables/MeetingPrompstList/MeetingPromptsList.js +4 -2
- package/dist/hooks/useExerciseState.js +92 -26
- package/dist/utils/canvasUtils.js +1 -1
- package/dist/utils/voices.js +26 -0
- package/package.json +1 -1
- package/dist/Forms/CreateRoleplayHook/CreateRoleplayHook.js +0 -83
- package/dist/Forms/CreateRoleplayHook/CreateRoleplayHook.test.js +0 -20
- package/dist/Forms/CreateRoleplayHook/Steps/Confirmation/Confirmation.js +0 -174
- package/dist/Forms/CreateRoleplayHook/Steps/Confirmation/package.json +0 -6
- package/dist/Forms/CreateRoleplayHook/Steps/RoleplayInformation/RoleplayInformation.js +0 -487
- package/dist/Forms/CreateRoleplayHook/Steps/RoleplayInformation/package.json +0 -6
- package/dist/Forms/CreateRoleplayHook/Steps/RoleplaySettings/RoleplaySettings.js +0 -330
- package/dist/Forms/CreateRoleplayHook/Steps/RoleplaySettings/package.json +0 -6
- package/dist/Forms/CreateRoleplayHook/Steps/index.js +0 -4
- package/dist/Forms/CreateRoleplayHook/package.json +0 -6
|
@@ -30,7 +30,8 @@ const AssignmentCardsList = ({
|
|
|
30
30
|
isLoadingAssignments,
|
|
31
31
|
isChallengeModeStudent,
|
|
32
32
|
isReadWriteModeStudent,
|
|
33
|
-
scrollableTarget = null
|
|
33
|
+
scrollableTarget = null,
|
|
34
|
+
openSnackbar
|
|
34
35
|
}) => {
|
|
35
36
|
const [lastClickedExerciseId, setLastClickedExerciseId] = useState(null);
|
|
36
37
|
const [filter, setFilter] = useState("all");
|
|
@@ -355,7 +356,8 @@ const AssignmentCardsList = ({
|
|
|
355
356
|
handleViewProgress: handleViewProgress,
|
|
356
357
|
assignedStudents: assignmentMembersById[assignment.assignmentId] || [],
|
|
357
358
|
isChallengeModeStudent: isChallengeModeStudent,
|
|
358
|
-
isReadWriteModeStudent: isReadWriteModeStudent
|
|
359
|
+
isReadWriteModeStudent: isReadWriteModeStudent,
|
|
360
|
+
openSnackbar: openSnackbar
|
|
359
361
|
}, assignment.assignmentId))
|
|
360
362
|
})]
|
|
361
363
|
});
|
|
@@ -57,6 +57,7 @@ function CreatePhrase({
|
|
|
57
57
|
verificationStatus,
|
|
58
58
|
makeChatGptApiRequest,
|
|
59
59
|
difficulty,
|
|
60
|
+
openSnackbar,
|
|
60
61
|
...otherProps
|
|
61
62
|
}) {
|
|
62
63
|
const translationInputRef = useRef();
|
|
@@ -723,7 +724,8 @@ function CreatePhrase({
|
|
|
723
724
|
autoSuggest: true,
|
|
724
725
|
autoSuggestedImages: autoSuggestedImages,
|
|
725
726
|
selectedImage: selectedImage,
|
|
726
|
-
verificationStatus: verificationStatus
|
|
727
|
+
verificationStatus: verificationStatus,
|
|
728
|
+
openSnackbar: openSnackbar
|
|
727
729
|
})
|
|
728
730
|
})]
|
|
729
731
|
})]
|
|
@@ -71,7 +71,8 @@ export default function CreatePhraseGroupDialog({
|
|
|
71
71
|
onCreated,
|
|
72
72
|
t = text => text,
|
|
73
73
|
fileSizeLimit,
|
|
74
|
-
verificationStatus
|
|
74
|
+
verificationStatus,
|
|
75
|
+
openSnackbar
|
|
75
76
|
}) {
|
|
76
77
|
const [name, setName] = useState("");
|
|
77
78
|
const [description, setDescription] = useState("");
|
|
@@ -180,7 +181,8 @@ export default function CreatePhraseGroupDialog({
|
|
|
180
181
|
autoCrop: true,
|
|
181
182
|
autoSuggest: false,
|
|
182
183
|
selectedImage: selectedImage,
|
|
183
|
-
verificationStatus: verificationStatus
|
|
184
|
+
verificationStatus: verificationStatus,
|
|
185
|
+
openSnackbar: openSnackbar
|
|
184
186
|
})
|
|
185
187
|
})]
|
|
186
188
|
})
|
|
@@ -7,13 +7,8 @@ import ImageBuilderControls from "./ImageBuilderControls";
|
|
|
7
7
|
import ImageBuilderPreview from "./ImageBuilderPreview";
|
|
8
8
|
import ResponsiveDialog from "../ResponsiveDialog/ResponsiveDialog";
|
|
9
9
|
import { PRESET_COLORS, ICON_KEYS } from "./iconPaths";
|
|
10
|
-
import {
|
|
11
|
-
|
|
12
|
-
// Matches placeholder SVG ratio (21144 x 4890), scaled down 10x
|
|
10
|
+
import { generateBuilderImages, getOptimalIconOpacity, shouldUseDarkIcons } from "./imageBuilderUtils";
|
|
13
11
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
14
|
-
const BANNER_W = 2114;
|
|
15
|
-
const BANNER_H = 489;
|
|
16
|
-
const CARD_SIZE = 489;
|
|
17
12
|
const useStyles = makeStyles()(theme => ({
|
|
18
13
|
body: {
|
|
19
14
|
display: "flex",
|
|
@@ -51,19 +46,13 @@ export default function ImageBuilderDialog({
|
|
|
51
46
|
cardDataUrl: null
|
|
52
47
|
};
|
|
53
48
|
}
|
|
54
|
-
|
|
49
|
+
return generateBuilderImages({
|
|
55
50
|
color,
|
|
56
51
|
iconKey,
|
|
57
52
|
density: "dense",
|
|
58
53
|
iconOpacity,
|
|
59
|
-
darkIcons
|
|
60
|
-
width: BANNER_W,
|
|
61
|
-
height: BANNER_H
|
|
54
|
+
darkIcons
|
|
62
55
|
});
|
|
63
|
-
return {
|
|
64
|
-
bannerDataUrl: canvas.toDataURL("image/png"),
|
|
65
|
-
cardDataUrl: getCenterCropDataUrl(canvas, CARD_SIZE)
|
|
66
|
-
};
|
|
67
56
|
}, [color, iconKey, iconOpacity, darkIcons]);
|
|
68
57
|
|
|
69
58
|
// Reset state when dialog opens
|
|
@@ -4,6 +4,19 @@ const DENSITY_COLS = {
|
|
|
4
4
|
medium: 10,
|
|
5
5
|
dense: 14
|
|
6
6
|
};
|
|
7
|
+
|
|
8
|
+
// Base (logical) dimensions of a builder image. Matches placeholder SVG ratio
|
|
9
|
+
// (21144 x 4890), scaled down 10x. The card is a centre-cropped square.
|
|
10
|
+
export const BANNER_W = 2114;
|
|
11
|
+
export const BANNER_H = 489;
|
|
12
|
+
export const CARD_SIZE = 489;
|
|
13
|
+
|
|
14
|
+
// Supersampling factor applied to the generated pixel dimensions so the stored
|
|
15
|
+
// image stays crisp when scaled up on large / HiDPI screens. Device-independent
|
|
16
|
+
// on purpose — the image is persisted and shared across devices, so we must not
|
|
17
|
+
// bake window.devicePixelRatio into it. Tune this single knob to trade payload
|
|
18
|
+
// size against sharpness.
|
|
19
|
+
export const OUTPUT_SCALE = 2;
|
|
7
20
|
function hexToRgb(hex) {
|
|
8
21
|
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
|
|
9
22
|
return result ? {
|
|
@@ -87,6 +100,7 @@ export function generatePatternCanvas({
|
|
|
87
100
|
canvas.width = width;
|
|
88
101
|
canvas.height = height;
|
|
89
102
|
const ctx = canvas.getContext("2d");
|
|
103
|
+
ctx.imageSmoothingQuality = "high";
|
|
90
104
|
|
|
91
105
|
// 1. Solid background
|
|
92
106
|
ctx.fillStyle = color;
|
|
@@ -107,10 +121,18 @@ export function generatePatternCanvas({
|
|
|
107
121
|
};
|
|
108
122
|
const maxDim = Math.max(vb.width, vb.height);
|
|
109
123
|
const scale = iconSize / maxDim;
|
|
124
|
+
|
|
125
|
+
// Rasterise the stamp at its final on-canvas size by filling the vector paths
|
|
126
|
+
// through a scaled context. Previously the stamp was drawn at the raw viewBox
|
|
127
|
+
// size (e.g. 24px) and then upscaled ~4x when blitted onto the pattern canvas,
|
|
128
|
+
// which baked a blurry raster upscale into the source image. Filling from
|
|
129
|
+
// vectors at the target size keeps icons crisp while preserving the single
|
|
130
|
+
// stamp (so overlapping sub-paths don't double-composite at globalAlpha < 1).
|
|
110
131
|
const stampCanvas = document.createElement("canvas");
|
|
111
|
-
stampCanvas.width = vb.width;
|
|
112
|
-
stampCanvas.height = vb.height;
|
|
132
|
+
stampCanvas.width = Math.ceil(vb.width * scale);
|
|
133
|
+
stampCanvas.height = Math.ceil(vb.height * scale);
|
|
113
134
|
const stampCtx = stampCanvas.getContext("2d");
|
|
135
|
+
stampCtx.scale(scale, scale);
|
|
114
136
|
stampCtx.fillStyle = darkIcons ? "#000" : "#fff";
|
|
115
137
|
const path2Ds = iconData.paths.map(d => new Path2D(d));
|
|
116
138
|
for (const p of path2Ds) {
|
|
@@ -131,9 +153,8 @@ export function generatePatternCanvas({
|
|
|
131
153
|
ctx.save();
|
|
132
154
|
ctx.translate(x, y);
|
|
133
155
|
ctx.rotate(rotation);
|
|
134
|
-
|
|
135
|
-
ctx.
|
|
136
|
-
ctx.drawImage(stampCanvas, 0, 0);
|
|
156
|
+
// Draw the pre-scaled stamp 1:1 (centred) — no upscaling here.
|
|
157
|
+
ctx.drawImage(stampCanvas, -stampCanvas.width / 2, -stampCanvas.height / 2);
|
|
137
158
|
ctx.restore();
|
|
138
159
|
}
|
|
139
160
|
}
|
|
@@ -156,4 +177,25 @@ export function getCenterCropDataUrl(source, size) {
|
|
|
156
177
|
const sx = (source.width - source.height) / 2;
|
|
157
178
|
ctx.drawImage(source, sx, 0, source.height, source.height, 0, 0, size, size);
|
|
158
179
|
return cropCanvas.toDataURL("image/png");
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Generate the builder images (banner + centre-cropped card) at the shared
|
|
184
|
+
* supersampled output resolution. Single source of truth for the builder
|
|
185
|
+
* dimensions so callers don't duplicate the magic numbers.
|
|
186
|
+
*
|
|
187
|
+
* @param {Object} opts – forwarded to generatePatternCanvas (color, iconKey,
|
|
188
|
+
* density, iconOpacity, darkIcons, seed)
|
|
189
|
+
* @returns {{ bannerDataUrl: string, cardDataUrl: string }}
|
|
190
|
+
*/
|
|
191
|
+
export function generateBuilderImages(opts) {
|
|
192
|
+
const canvas = generatePatternCanvas({
|
|
193
|
+
...opts,
|
|
194
|
+
width: BANNER_W * OUTPUT_SCALE,
|
|
195
|
+
height: BANNER_H * OUTPUT_SCALE
|
|
196
|
+
});
|
|
197
|
+
return {
|
|
198
|
+
bannerDataUrl: canvas.toDataURL("image/png"),
|
|
199
|
+
cardDataUrl: getCenterCropDataUrl(canvas, CARD_SIZE * OUTPUT_SCALE)
|
|
200
|
+
};
|
|
159
201
|
}
|
|
@@ -1,10 +1,14 @@
|
|
|
1
|
-
import { useState, useEffect, forwardRef,
|
|
2
|
-
import { TextField, MenuItem, ListSubheader, Box, Paper, Typography } from "@mui/material";
|
|
3
|
-
import { ForumRounded, QuizRounded, ImageRounded, SentimentSatisfiedRounded, CheckRounded } from "@mui/icons-material";
|
|
1
|
+
import { useState, useEffect, forwardRef, createElement } from "react";
|
|
2
|
+
import { TextField, MenuItem, ListSubheader, Box, Paper, Typography, Grid, Button, Avatar } from "@mui/material";
|
|
3
|
+
import { ForumRounded, QuizRounded, ImageRounded, SentimentSatisfiedRounded, CheckRounded, Person } from "@mui/icons-material";
|
|
4
4
|
import { useTheme, alpha } from "@mui/material/styles";
|
|
5
5
|
import { keyframes } from "@emotion/react";
|
|
6
6
|
import ResponsiveDialog from "../ResponsiveDialog/ResponsiveDialog";
|
|
7
7
|
import ChatbotNualaAnimation from "../../Misc/QuickCreateNualaAnimations/ChatbotNualaAnimation";
|
|
8
|
+
import VoiceSelector from "../../Forms/VoiceSelector/VoiceSelector";
|
|
9
|
+
import { findVoice, pickRandomVoice } from "../../utils/voices";
|
|
10
|
+
import { makeStyles } from "tss-react/mui";
|
|
11
|
+
import AvatarSelector from "../../Misc/AvatarSelector/AvatarSelector";
|
|
8
12
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
9
13
|
export const BOT_NAME_MAX_LENGTH = 100;
|
|
10
14
|
const peekAnimation = keyframes`
|
|
@@ -14,6 +18,18 @@ const peekAnimation = keyframes`
|
|
|
14
18
|
67% { transform: translateX(-150px) rotate(75deg); }
|
|
15
19
|
100% { transform: translateX(-150px) rotate(75deg); }
|
|
16
20
|
`;
|
|
21
|
+
const useStyles = makeStyles()(theme => ({
|
|
22
|
+
avatar: {
|
|
23
|
+
width: 70,
|
|
24
|
+
height: 70,
|
|
25
|
+
marginBottom: theme.spacing(2),
|
|
26
|
+
cursor: "pointer"
|
|
27
|
+
},
|
|
28
|
+
avatarIcon: {
|
|
29
|
+
width: "80%",
|
|
30
|
+
height: "80%"
|
|
31
|
+
}
|
|
32
|
+
}));
|
|
17
33
|
const ChatbotDialogPaper = /*#__PURE__*/forwardRef(function ChatbotDialogPaper({
|
|
18
34
|
children,
|
|
19
35
|
className,
|
|
@@ -378,7 +394,11 @@ export default function QuickCreateChatbotDialog({
|
|
|
378
394
|
topicDifficulty,
|
|
379
395
|
topicPicture,
|
|
380
396
|
defaultNumberOfQuestions = 5,
|
|
381
|
-
voices = []
|
|
397
|
+
voices = [],
|
|
398
|
+
handleSpeak,
|
|
399
|
+
isUserInternal = false,
|
|
400
|
+
avatars,
|
|
401
|
+
learnLang
|
|
382
402
|
}) {
|
|
383
403
|
const [botTitle, setBotTitle] = useState("");
|
|
384
404
|
const [difficulty, setDifficulty] = useState(topicDifficulty || "");
|
|
@@ -387,6 +407,14 @@ export default function QuickCreateChatbotDialog({
|
|
|
387
407
|
const [riveFile, setRiveFile] = useState("");
|
|
388
408
|
const [numberOfQuestions, setNumberOfQuestions] = useState(defaultNumberOfQuestions);
|
|
389
409
|
const [isLoading, setIsLoading] = useState(false);
|
|
410
|
+
const [selectedVoice, setSelectedVoice] = useState(null);
|
|
411
|
+
const [selectedVoiceLanguageCode, setSelectedVoiceLanguageCode] = useState(null);
|
|
412
|
+
const [selectedVoicePitch, setSelectedVoicePitch] = useState(null);
|
|
413
|
+
const [botPicture, setBotPicture] = useState("");
|
|
414
|
+
const [avatarSelector, setAvatarSelector] = useState(false);
|
|
415
|
+
const {
|
|
416
|
+
classes
|
|
417
|
+
} = useStyles();
|
|
390
418
|
|
|
391
419
|
// Keep the questions field in sync if the default changes while closed.
|
|
392
420
|
useEffect(() => {
|
|
@@ -408,31 +436,31 @@ export default function QuickCreateChatbotDialog({
|
|
|
408
436
|
setTemplateId("");
|
|
409
437
|
setNumberOfQuestions(defaultNumberOfQuestions);
|
|
410
438
|
handleClose();
|
|
439
|
+
// Cleared so the next open seeds a fresh random voice.
|
|
440
|
+
setSelectedVoice(null);
|
|
441
|
+
setSelectedVoiceLanguageCode(null);
|
|
442
|
+
setSelectedVoicePitch(null);
|
|
443
|
+
setBotPicture("");
|
|
444
|
+
setAvatarSelector(false);
|
|
445
|
+
};
|
|
446
|
+
const handleAvatarSelection = value => {
|
|
447
|
+
setBotPicture(value);
|
|
448
|
+
setAvatarSelector(false);
|
|
411
449
|
};
|
|
412
|
-
const voicesArray = useMemo(() => {
|
|
413
|
-
return Object.entries(voices).flatMap(([key, dialect]) => {
|
|
414
|
-
if (!dialect?.voiceOptions || !Array.isArray(dialect.voiceOptions)) {
|
|
415
|
-
return [];
|
|
416
|
-
}
|
|
417
|
-
return dialect.voiceOptions.filter(voice => voice?.name) // Validate required properties
|
|
418
|
-
.map(voice => ({
|
|
419
|
-
voice,
|
|
420
|
-
dialect,
|
|
421
|
-
key
|
|
422
|
-
}));
|
|
423
|
-
});
|
|
424
|
-
}, [voices]);
|
|
425
450
|
|
|
426
|
-
//
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
voice
|
|
433
|
-
dialect
|
|
434
|
-
|
|
435
|
-
|
|
451
|
+
// ActorForm assigns each actor a random voice on mount; standalone, the same
|
|
452
|
+
// seeding happens here each time the dialog opens with nothing chosen yet.
|
|
453
|
+
useEffect(() => {
|
|
454
|
+
if (!open || selectedVoice) return;
|
|
455
|
+
const picked = pickRandomVoice(voices);
|
|
456
|
+
if (!picked) return;
|
|
457
|
+
setSelectedVoice(picked.voice.name);
|
|
458
|
+
setSelectedVoiceLanguageCode(picked.dialect.languageCode);
|
|
459
|
+
setSelectedVoicePitch(null);
|
|
460
|
+
setBotPicture(picked.voice.userImage || "");
|
|
461
|
+
}, [open, selectedVoice, voices]);
|
|
462
|
+
const selectedVoiceOption = findVoice(voices, selectedVoice)?.voice;
|
|
463
|
+
const hasAvailableVoice = Boolean(selectedVoice && selectedVoiceLanguageCode);
|
|
436
464
|
const isValid = Boolean(botTitle.trim()) && Boolean(difficulty) && Boolean(templateId) && Boolean(template && template.botId === templateId) && Number(numberOfQuestions) > 0 && hasAvailableVoice;
|
|
437
465
|
const handleSubmit = async () => {
|
|
438
466
|
if (!isValid) return;
|
|
@@ -449,10 +477,11 @@ export default function QuickCreateChatbotDialog({
|
|
|
449
477
|
selectedTemplate: templateId,
|
|
450
478
|
numberOfQuestions: Number(numberOfQuestions),
|
|
451
479
|
courseSectionTopicId: `${courseId}|${sectionId}|${topicId}`,
|
|
452
|
-
voice:
|
|
453
|
-
voiceLanguageCode:
|
|
454
|
-
name:
|
|
455
|
-
|
|
480
|
+
voice: selectedVoice,
|
|
481
|
+
voiceLanguageCode: selectedVoiceLanguageCode,
|
|
482
|
+
name: selectedVoice,
|
|
483
|
+
voicePitch: selectedVoicePitch,
|
|
484
|
+
botAvatar: botPicture,
|
|
456
485
|
isChallengeBot: false,
|
|
457
486
|
isDynamicResponsesEnabled: "enable",
|
|
458
487
|
picture: topicPicture || template.picture
|
|
@@ -467,7 +496,7 @@ export default function QuickCreateChatbotDialog({
|
|
|
467
496
|
setIsLoading(false);
|
|
468
497
|
}
|
|
469
498
|
};
|
|
470
|
-
return /*#__PURE__*/
|
|
499
|
+
return /*#__PURE__*/_jsxs(ResponsiveDialog, {
|
|
471
500
|
open: open,
|
|
472
501
|
handleClose: isLoading ? undefined : resetAndClose,
|
|
473
502
|
handleSubmit: handleSubmit,
|
|
@@ -476,7 +505,7 @@ export default function QuickCreateChatbotDialog({
|
|
|
476
505
|
closeText: t("cancel") || "Cancel",
|
|
477
506
|
submitText: t("create") || "Create",
|
|
478
507
|
PaperComponent: ChatbotDialogPaper,
|
|
479
|
-
children: /*#__PURE__*/_jsxs(Box, {
|
|
508
|
+
children: [/*#__PURE__*/_jsxs(Box, {
|
|
480
509
|
display: "flex",
|
|
481
510
|
flexDirection: "column",
|
|
482
511
|
gap: 1,
|
|
@@ -537,7 +566,90 @@ export default function QuickCreateChatbotDialog({
|
|
|
537
566
|
},
|
|
538
567
|
onKeyDown: e => e.key === "Enter" && handleSubmit(),
|
|
539
568
|
margin: "normal"
|
|
569
|
+
}), /*#__PURE__*/_jsxs(Grid, {
|
|
570
|
+
size: 12,
|
|
571
|
+
sx: {
|
|
572
|
+
mt: 1
|
|
573
|
+
},
|
|
574
|
+
children: [botPicture ? /*#__PURE__*/_jsx(Avatar, {
|
|
575
|
+
"aria-label": selectedVoiceOption?.name,
|
|
576
|
+
src: botPicture,
|
|
577
|
+
className: classes.avatar,
|
|
578
|
+
onClick: () => setAvatarSelector(true),
|
|
579
|
+
alt: ""
|
|
580
|
+
}) : /*#__PURE__*/_jsx(Avatar, {
|
|
581
|
+
"aria-label": selectedVoiceOption?.name,
|
|
582
|
+
sx: theme => ({
|
|
583
|
+
backgroundColor: theme.palette.mode === "dark" ? "white" : "",
|
|
584
|
+
color: theme.palette.mode === "dark" ? theme.palette.background.default : ""
|
|
585
|
+
}),
|
|
586
|
+
className: classes.avatar,
|
|
587
|
+
onClick: () => setAvatarSelector(true),
|
|
588
|
+
alt: "",
|
|
589
|
+
children: /*#__PURE__*/_jsx(Person, {
|
|
590
|
+
className: classes.avatarIcon
|
|
591
|
+
})
|
|
592
|
+
}), /*#__PURE__*/_jsx(Button, {
|
|
593
|
+
color: "primary",
|
|
594
|
+
component: "span",
|
|
595
|
+
onClick: () => setAvatarSelector(true),
|
|
596
|
+
children: t("choose_avatar")
|
|
597
|
+
}), /*#__PURE__*/_jsx(VoiceSelector, {
|
|
598
|
+
id: "voiceSelector",
|
|
599
|
+
"data-cy": "voiceSelector",
|
|
600
|
+
name: "voiceSelector",
|
|
601
|
+
label: t("bot_voice"),
|
|
602
|
+
value: selectedVoice || "",
|
|
603
|
+
margin: "normal",
|
|
604
|
+
variant: "outlined",
|
|
605
|
+
fullWidth: true,
|
|
606
|
+
required: learnLang !== "irish",
|
|
607
|
+
t: t,
|
|
608
|
+
voices: voices,
|
|
609
|
+
onChange: e => {
|
|
610
|
+
if (e && e.target && e.target.value) {
|
|
611
|
+
const selectedVoice = e.target.value;
|
|
612
|
+
const languageCode = e.target.languageCode;
|
|
613
|
+
setSelectedVoice(selectedVoice);
|
|
614
|
+
handleSpeak?.({
|
|
615
|
+
text: selectedVoice,
|
|
616
|
+
learnLanguage: learnLang,
|
|
617
|
+
voiceName: selectedVoice,
|
|
618
|
+
languageCode
|
|
619
|
+
});
|
|
620
|
+
setSelectedVoiceLanguageCode(languageCode);
|
|
621
|
+
setSelectedVoicePitch(null);
|
|
622
|
+
setBotPicture(e.target.picture);
|
|
623
|
+
}
|
|
624
|
+
},
|
|
625
|
+
onVoicePitchChange: e => {
|
|
626
|
+
if (e && e.target) {
|
|
627
|
+
setSelectedVoicePitch(e.target.value);
|
|
628
|
+
handleSpeak?.({
|
|
629
|
+
text: selectedVoiceLanguageCode ? t("voice_pitch_example", {
|
|
630
|
+
name: selectedVoice,
|
|
631
|
+
lng: selectedVoiceLanguageCode?.substring(0, 2)
|
|
632
|
+
}) : selectedVoice,
|
|
633
|
+
learnLanguage: learnLang,
|
|
634
|
+
voiceName: selectedVoice,
|
|
635
|
+
languageCode: selectedVoiceLanguageCode,
|
|
636
|
+
pitch: e.target.value
|
|
637
|
+
});
|
|
638
|
+
}
|
|
639
|
+
},
|
|
640
|
+
voicePitch: selectedVoicePitch,
|
|
641
|
+
isUserInternal: isUserInternal,
|
|
642
|
+
handleSpeak: handleSpeak,
|
|
643
|
+
learnLang: learnLang
|
|
644
|
+
})]
|
|
540
645
|
})]
|
|
541
|
-
})
|
|
646
|
+
}), /*#__PURE__*/_jsx(AvatarSelector, {
|
|
647
|
+
t: t,
|
|
648
|
+
open: avatarSelector,
|
|
649
|
+
avatars: avatars,
|
|
650
|
+
picture: botPicture,
|
|
651
|
+
handleClose: () => setAvatarSelector(false),
|
|
652
|
+
handleSubmit: value => handleAvatarSelection(value)
|
|
653
|
+
})]
|
|
542
654
|
});
|
|
543
655
|
}
|
|
@@ -80,7 +80,8 @@ export default function QuickCreateClassroomDialog({
|
|
|
80
80
|
userImage,
|
|
81
81
|
forLang,
|
|
82
82
|
languages,
|
|
83
|
-
forLanguages
|
|
83
|
+
forLanguages,
|
|
84
|
+
openSnackbar
|
|
84
85
|
}) {
|
|
85
86
|
const [classroomName, setClassroomName] = useState("");
|
|
86
87
|
const [classroomDescription, setClassroomDescription] = useState("");
|
|
@@ -275,7 +276,8 @@ export default function QuickCreateClassroomDialog({
|
|
|
275
276
|
autoSuggest: false,
|
|
276
277
|
selectedImage: selectedImage,
|
|
277
278
|
verificationStatus: verificationStatus,
|
|
278
|
-
onBuilderSettingsChange: setBuilderSettings
|
|
279
|
+
onBuilderSettingsChange: setBuilderSettings,
|
|
280
|
+
openSnackbar: openSnackbar
|
|
279
281
|
})
|
|
280
282
|
})]
|
|
281
283
|
})
|
|
@@ -83,7 +83,8 @@ export default function QuickCreateCourseDialog({
|
|
|
83
83
|
difficulties = ["A1", "A2", "B1", "B2", "C1", "C2"],
|
|
84
84
|
fileSizeLimit,
|
|
85
85
|
verificationStatus,
|
|
86
|
-
userImage
|
|
86
|
+
userImage,
|
|
87
|
+
openSnackbar
|
|
87
88
|
}) {
|
|
88
89
|
const defaultSelectedImage = {
|
|
89
90
|
image: "",
|
|
@@ -289,7 +290,8 @@ export default function QuickCreateCourseDialog({
|
|
|
289
290
|
autoSuggest: false,
|
|
290
291
|
selectedImage: selectedImage,
|
|
291
292
|
verificationStatus: verificationStatus,
|
|
292
|
-
onBuilderSettingsChange: setBuilderSettings
|
|
293
|
+
onBuilderSettingsChange: setBuilderSettings,
|
|
294
|
+
openSnackbar: openSnackbar
|
|
293
295
|
})
|
|
294
296
|
})]
|
|
295
297
|
})
|
|
@@ -83,7 +83,8 @@ export default function QuickCreateTopicDialog({
|
|
|
83
83
|
userImage,
|
|
84
84
|
coursePicture,
|
|
85
85
|
coursePictureBuilderColor,
|
|
86
|
-
coursePictureBuilderIcon
|
|
86
|
+
coursePictureBuilderIcon,
|
|
87
|
+
openSnackbar
|
|
87
88
|
}) {
|
|
88
89
|
// Only inherit the parent course image when it's a real user-set image.
|
|
89
90
|
// If the course has no image, or its image was itself generated by the image
|
|
@@ -274,7 +275,8 @@ export default function QuickCreateTopicDialog({
|
|
|
274
275
|
autoSuggest: false,
|
|
275
276
|
selectedImage: selectedImage,
|
|
276
277
|
verificationStatus: verificationStatus,
|
|
277
|
-
onBuilderSettingsChange: setBuilderSettings
|
|
278
|
+
onBuilderSettingsChange: setBuilderSettings,
|
|
279
|
+
openSnackbar: openSnackbar
|
|
278
280
|
})
|
|
279
281
|
})]
|
|
280
282
|
})
|
package/dist/Editors/Bot/Bot.js
CHANGED
|
@@ -770,7 +770,8 @@ function Bot({
|
|
|
770
770
|
courseId: courseId,
|
|
771
771
|
sectionId: sectionId,
|
|
772
772
|
topicId: topicId,
|
|
773
|
-
initialTopicGoal: initialTopicGoal
|
|
773
|
+
initialTopicGoal: initialTopicGoal,
|
|
774
|
+
openSnackbar: openSnackbar
|
|
774
775
|
}) : null, tabValue === 1 ? /*#__PURE__*/_jsx(Box, {
|
|
775
776
|
className: hidden ? classes.paneFull : classes.pane,
|
|
776
777
|
children: BotPreview
|
|
@@ -791,7 +792,8 @@ function Bot({
|
|
|
791
792
|
subscription: subscription,
|
|
792
793
|
handleBotInstructionsImageUpload: handleBotInstructionsImageUpload,
|
|
793
794
|
isUserInternal: isUserInternal,
|
|
794
|
-
verificationStatus: verificationStatus
|
|
795
|
+
verificationStatus: verificationStatus,
|
|
796
|
+
openSnackbar: openSnackbar
|
|
795
797
|
})
|
|
796
798
|
}) : null]
|
|
797
799
|
}), /*#__PURE__*/_jsx(ResponsiveDialog, {
|
|
@@ -14,7 +14,8 @@ function AddImageModal(props) {
|
|
|
14
14
|
open,
|
|
15
15
|
handleUploadBotExerciseImage,
|
|
16
16
|
botId,
|
|
17
|
-
verificationStatus
|
|
17
|
+
verificationStatus,
|
|
18
|
+
openSnackbar
|
|
18
19
|
} = props;
|
|
19
20
|
const theme = useTheme();
|
|
20
21
|
const fullScreen = useMediaQuery(theme.breakpoints.down("sm"));
|
|
@@ -76,7 +77,8 @@ function AddImageModal(props) {
|
|
|
76
77
|
name: "image",
|
|
77
78
|
value: selectedImage.image,
|
|
78
79
|
handleChange: handleImageChange,
|
|
79
|
-
verificationStatus: verificationStatus
|
|
80
|
+
verificationStatus: verificationStatus,
|
|
81
|
+
openSnackbar: openSnackbar
|
|
80
82
|
})]
|
|
81
83
|
}), /*#__PURE__*/_jsxs(DialogActions, {
|
|
82
84
|
children: [/*#__PURE__*/_jsx(Button, {
|
|
@@ -36,7 +36,8 @@ function BotDesigner(props) {
|
|
|
36
36
|
handleUpdateAllVariables,
|
|
37
37
|
handleUploadBotExerciseImage,
|
|
38
38
|
botId,
|
|
39
|
-
handleOnBlur
|
|
39
|
+
handleOnBlur,
|
|
40
|
+
openSnackbar
|
|
40
41
|
} = props;
|
|
41
42
|
return /*#__PURE__*/_jsxs(_Fragment, {
|
|
42
43
|
children: [rivescriptJSON && rivescriptJSON.begin.var && /*#__PURE__*/_jsx(VarList, {
|
|
@@ -49,7 +50,8 @@ function BotDesigner(props) {
|
|
|
49
50
|
handleUploadBotExerciseImage: handleUploadBotExerciseImage,
|
|
50
51
|
botId: botId,
|
|
51
52
|
handleOnBlur: handleOnBlur,
|
|
52
|
-
handleUpdateVariable: handleUpdateVariable
|
|
53
|
+
handleUpdateVariable: handleUpdateVariable,
|
|
54
|
+
openSnackbar: openSnackbar
|
|
53
55
|
}), rivescriptJSON && rivescriptJSON.begin.array && /*#__PURE__*/_jsx(AlternativesList, {
|
|
54
56
|
t: t,
|
|
55
57
|
alternatives: rivescriptJSON.begin.array,
|
|
@@ -26,7 +26,8 @@ function VarListItem({
|
|
|
26
26
|
handleOnBlur,
|
|
27
27
|
handleUploadBotExerciseImage,
|
|
28
28
|
verificationStatus,
|
|
29
|
-
botId
|
|
29
|
+
botId,
|
|
30
|
+
openSnackbar
|
|
30
31
|
}) {
|
|
31
32
|
const [selectedImage, setSelectedImage] = useState("");
|
|
32
33
|
if (varValue && markdownImageLinkRegex.test(varValue)) {
|
|
@@ -72,6 +73,7 @@ function VarListItem({
|
|
|
72
73
|
handleChange: handleImageChange,
|
|
73
74
|
cropCompletedCallback: cropCompletedCallback,
|
|
74
75
|
verificationStatus: verificationStatus,
|
|
76
|
+
openSnackbar: openSnackbar,
|
|
75
77
|
autoGenerateDefault: false
|
|
76
78
|
// fileSizeLimit={fileSizeLimit}
|
|
77
79
|
,
|
|
@@ -256,7 +258,8 @@ function VarList({
|
|
|
256
258
|
handleSelectCurrentInput,
|
|
257
259
|
handleUploadBotExerciseImage,
|
|
258
260
|
botId,
|
|
259
|
-
handleOnBlur
|
|
261
|
+
handleOnBlur,
|
|
262
|
+
openSnackbar
|
|
260
263
|
}) {
|
|
261
264
|
const [open, setOpen] = useState(true);
|
|
262
265
|
const [varUploader, setVarUploader] = useState(false);
|
|
@@ -276,7 +279,8 @@ function VarList({
|
|
|
276
279
|
handleUploadBotExerciseImage: handleUploadBotExerciseImage,
|
|
277
280
|
handleOnBlur: handleOnBlur,
|
|
278
281
|
botId: botId,
|
|
279
|
-
handleUpdateVariable: handleUpdateVariable
|
|
282
|
+
handleUpdateVariable: handleUpdateVariable,
|
|
283
|
+
openSnackbar: openSnackbar
|
|
280
284
|
}));
|
|
281
285
|
}
|
|
282
286
|
return /*#__PURE__*/_jsxs(List, {
|
|
@@ -93,7 +93,8 @@ function Editor({
|
|
|
93
93
|
sectionId,
|
|
94
94
|
topicId,
|
|
95
95
|
initialTopicGoal,
|
|
96
|
-
verificationStatus
|
|
96
|
+
verificationStatus,
|
|
97
|
+
openSnackbar
|
|
97
98
|
}) {
|
|
98
99
|
const [formattingOptionsAnchorEl, setFormattingOptionsAnchorEl] = useState(null);
|
|
99
100
|
const isFormattingOptionsOpen = Boolean(formattingOptionsAnchorEl);
|
|
@@ -566,7 +567,8 @@ function Editor({
|
|
|
566
567
|
handleUpdateAlternatives: handleUpdateAlternatives,
|
|
567
568
|
handleUploadBotExerciseImage: handleUploadBotExerciseImage,
|
|
568
569
|
botId: bot.botId,
|
|
569
|
-
handleUpdateVariable: handleUpdateVariable
|
|
570
|
+
handleUpdateVariable: handleUpdateVariable,
|
|
571
|
+
openSnackbar: openSnackbar
|
|
570
572
|
}), /*#__PURE__*/_jsx(TriggerDialog, {
|
|
571
573
|
t: t,
|
|
572
574
|
open: isTriggerModalOpen,
|
|
@@ -602,7 +604,8 @@ function Editor({
|
|
|
602
604
|
botId: bot.botId,
|
|
603
605
|
handleUploadBotExerciseImage: handleUploadBotExerciseImage,
|
|
604
606
|
handleAddImage: handleAddImage,
|
|
605
|
-
verificationStatus: verificationStatus
|
|
607
|
+
verificationStatus: verificationStatus,
|
|
608
|
+
openSnackbar: openSnackbar
|
|
606
609
|
}), /*#__PURE__*/_jsx(AddLinkModal, {
|
|
607
610
|
classes: {},
|
|
608
611
|
t: t,
|
|
@@ -96,7 +96,8 @@ function PhraseList({
|
|
|
96
96
|
otherPhraseLists,
|
|
97
97
|
otherPhraseListsLoading,
|
|
98
98
|
handleTransferPhrase,
|
|
99
|
-
handleCreatePhraseListFromSelection
|
|
99
|
+
handleCreatePhraseListFromSelection,
|
|
100
|
+
openSnackbar
|
|
100
101
|
}) {
|
|
101
102
|
const theme = useTheme();
|
|
102
103
|
const {
|
|
@@ -357,7 +358,8 @@ function PhraseList({
|
|
|
357
358
|
isGeneratePhrasesDialogOpen: isGeneratePhrasesDialogOpen,
|
|
358
359
|
setIsGeneratePhrasesDialogOpen: setIsGeneratePhrasesDialogOpen,
|
|
359
360
|
mode: mode,
|
|
360
|
-
scriptDownloadRef: scriptDownloadRef
|
|
361
|
+
scriptDownloadRef: scriptDownloadRef,
|
|
362
|
+
openSnackbar: openSnackbar
|
|
361
363
|
})
|
|
362
364
|
}) : null, tabValue === 1 ? /*#__PURE__*/_jsx(Box, {
|
|
363
365
|
sx: {
|
|
@@ -378,7 +380,8 @@ function PhraseList({
|
|
|
378
380
|
onSubmitExerciseSettings: onSubmitExerciseSettings,
|
|
379
381
|
handleSpeak: handleSpeak,
|
|
380
382
|
fileSizeLimit: fileSizeLimit,
|
|
381
|
-
verificationStatus: verificationStatus
|
|
383
|
+
verificationStatus: verificationStatus,
|
|
384
|
+
openSnackbar: openSnackbar
|
|
382
385
|
})
|
|
383
386
|
}) : null]
|
|
384
387
|
})
|