@nualang/nualang-ui-components 0.1.1362 → 0.1.1365
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/CreatePhraseListFromSelectionDialog/CreatePhraseListFromSelectionDialog.js +49 -0
- package/dist/Dialogs/TransferPhrase/TransferPhrase.js +113 -0
- package/dist/Editors/PhraseList/PhraseList.js +128 -24
- package/dist/Editors/Phrases/Phrases.js +115 -262
- package/dist/Editors/Phrases/SpreadsheetEditor/SpreadsheetEditor.js +91 -44
- package/dist/Exercises/Meaning/Meaning.js +8 -1
- package/dist/Forms/DiscussMultiStepFormDialog/MultiStepFormDialog.js +9 -2
- package/dist/Lists/Phrases/Phrases.js +173 -281
- package/dist/Misc/PhraseDisplay/PhraseDisplay.js +5 -5
- package/dist/Screens/Classrooms/ViewClassroom/ViewClassroom.js +4 -1
- package/dist/hooks/useSpreadsheetState.js +59 -55
- package/package.json +2 -2
- package/dist/Lists/SpreadsheetGrid/SpreadsheetGrid.js +0 -88
package/dist/Dialogs/CreatePhraseListFromSelectionDialog/CreatePhraseListFromSelectionDialog.js
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { useState } from "react";
|
|
2
|
+
import { TextField } from "@mui/material";
|
|
3
|
+
import ResponsiveDialog from "../ResponsiveDialog/ResponsiveDialog";
|
|
4
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
5
|
+
export default function CreatePhraseListFromSelectionDialog({
|
|
6
|
+
open,
|
|
7
|
+
handleClose,
|
|
8
|
+
phraseIds = [],
|
|
9
|
+
handleCreatePhraseListFromSelection,
|
|
10
|
+
t = text => text
|
|
11
|
+
}) {
|
|
12
|
+
const [phraseListName, setPhraseListName] = useState("");
|
|
13
|
+
const handleSubmit = async () => {
|
|
14
|
+
if (!phraseListName.trim()) return;
|
|
15
|
+
try {
|
|
16
|
+
await handleCreatePhraseListFromSelection(phraseIds, phraseListName.trim());
|
|
17
|
+
setPhraseListName("");
|
|
18
|
+
handleClose();
|
|
19
|
+
} catch (error) {
|
|
20
|
+
console.error("Failed to create phrase list:", error);
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
const handleCloseReset = () => {
|
|
24
|
+
setPhraseListName("");
|
|
25
|
+
handleClose();
|
|
26
|
+
};
|
|
27
|
+
return /*#__PURE__*/_jsx(ResponsiveDialog, {
|
|
28
|
+
open: open,
|
|
29
|
+
handleClose: handleCloseReset,
|
|
30
|
+
handleSubmit: handleSubmit,
|
|
31
|
+
dialogTitle: t("create_phrase_list_from_selection"),
|
|
32
|
+
submitText: t("create"),
|
|
33
|
+
isSubmitDisabled: !phraseListName.trim(),
|
|
34
|
+
t: t,
|
|
35
|
+
children: /*#__PURE__*/_jsx(TextField, {
|
|
36
|
+
autoFocus: true,
|
|
37
|
+
fullWidth: true,
|
|
38
|
+
label: t("phrase_list_name"),
|
|
39
|
+
value: phraseListName,
|
|
40
|
+
onChange: e => setPhraseListName(e.target.value),
|
|
41
|
+
onKeyDown: e => e.key === "Enter" && handleSubmit(),
|
|
42
|
+
variant: "outlined",
|
|
43
|
+
size: "small",
|
|
44
|
+
sx: {
|
|
45
|
+
mt: 1
|
|
46
|
+
}
|
|
47
|
+
})
|
|
48
|
+
});
|
|
49
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { useState } from "react";
|
|
2
|
+
import { Typography, Avatar, Checkbox, CircularProgress, List, ListItem, ListItemText, ListItemAvatar, ListItemButton, Box } from "@mui/material";
|
|
3
|
+
import ImageSearchIcon from "@mui/icons-material/ImageSearch";
|
|
4
|
+
import AddIcon from "@mui/icons-material/Add";
|
|
5
|
+
import ResponsiveDialog from "../ResponsiveDialog/ResponsiveDialog";
|
|
6
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
7
|
+
export default function TransferPhraseDialog({
|
|
8
|
+
open,
|
|
9
|
+
handleClose,
|
|
10
|
+
phraseIds = [],
|
|
11
|
+
otherPhraseLists = [],
|
|
12
|
+
otherPhraseListsLoading = false,
|
|
13
|
+
handleTransferPhrase,
|
|
14
|
+
handleCreateNew,
|
|
15
|
+
t = text => text
|
|
16
|
+
}) {
|
|
17
|
+
const [selectedIds, setSelectedIds] = useState([]);
|
|
18
|
+
const toggleId = id => setSelectedIds(prev => prev.includes(id) ? prev.filter(x => x !== id) : [...prev, id]);
|
|
19
|
+
const handleSubmit = async () => {
|
|
20
|
+
if (selectedIds.length === 0) return;
|
|
21
|
+
await handleTransferPhrase(phraseIds, selectedIds);
|
|
22
|
+
setSelectedIds([]);
|
|
23
|
+
handleClose();
|
|
24
|
+
};
|
|
25
|
+
const handleCloseReset = () => {
|
|
26
|
+
setSelectedIds([]);
|
|
27
|
+
handleClose();
|
|
28
|
+
};
|
|
29
|
+
return /*#__PURE__*/_jsx(ResponsiveDialog, {
|
|
30
|
+
open: open,
|
|
31
|
+
handleClose: handleCloseReset,
|
|
32
|
+
handleSubmit: handleSubmit,
|
|
33
|
+
dialogTitle: t("transfer_phrases"),
|
|
34
|
+
submitText: t("transfer"),
|
|
35
|
+
isSubmitDisabled: selectedIds.length === 0,
|
|
36
|
+
t: t,
|
|
37
|
+
children: /*#__PURE__*/_jsxs(Box, {
|
|
38
|
+
sx: {
|
|
39
|
+
mt: 1
|
|
40
|
+
},
|
|
41
|
+
children: [otherPhraseListsLoading ? /*#__PURE__*/_jsx(Box, {
|
|
42
|
+
sx: {
|
|
43
|
+
display: "flex",
|
|
44
|
+
justifyContent: "center",
|
|
45
|
+
py: 2
|
|
46
|
+
},
|
|
47
|
+
children: /*#__PURE__*/_jsx(CircularProgress, {
|
|
48
|
+
size: 24
|
|
49
|
+
})
|
|
50
|
+
}) : otherPhraseLists.length === 0 ? /*#__PURE__*/_jsx(Typography, {
|
|
51
|
+
color: "textSecondary",
|
|
52
|
+
sx: {
|
|
53
|
+
mb: 1
|
|
54
|
+
},
|
|
55
|
+
children: t("no_other_phrase_lists")
|
|
56
|
+
}) : /*#__PURE__*/_jsx(List, {
|
|
57
|
+
disablePadding: true,
|
|
58
|
+
children: otherPhraseLists.map(list => {
|
|
59
|
+
const checked = selectedIds.includes(list.phraseListId);
|
|
60
|
+
return /*#__PURE__*/_jsx(ListItem, {
|
|
61
|
+
disablePadding: true,
|
|
62
|
+
secondaryAction: /*#__PURE__*/_jsx(Checkbox, {
|
|
63
|
+
edge: "end",
|
|
64
|
+
checked: checked,
|
|
65
|
+
onChange: () => toggleId(list.phraseListId),
|
|
66
|
+
inputProps: {
|
|
67
|
+
"aria-label": list.phraseListName
|
|
68
|
+
}
|
|
69
|
+
}),
|
|
70
|
+
children: /*#__PURE__*/_jsxs(ListItemButton, {
|
|
71
|
+
onClick: () => toggleId(list.phraseListId),
|
|
72
|
+
children: [/*#__PURE__*/_jsx(ListItemAvatar, {
|
|
73
|
+
children: list.picture ? /*#__PURE__*/_jsx(Avatar, {
|
|
74
|
+
src: list.picture,
|
|
75
|
+
alt: list.phraseListName
|
|
76
|
+
}) : /*#__PURE__*/_jsx(Avatar, {
|
|
77
|
+
children: /*#__PURE__*/_jsx(ImageSearchIcon, {
|
|
78
|
+
fontSize: "small"
|
|
79
|
+
})
|
|
80
|
+
})
|
|
81
|
+
}), /*#__PURE__*/_jsx(ListItemText, {
|
|
82
|
+
primary: list.phraseListName
|
|
83
|
+
})]
|
|
84
|
+
})
|
|
85
|
+
}, list.phraseListId);
|
|
86
|
+
})
|
|
87
|
+
}), handleCreateNew && /*#__PURE__*/_jsx(List, {
|
|
88
|
+
disablePadding: true,
|
|
89
|
+
children: /*#__PURE__*/_jsx(ListItem, {
|
|
90
|
+
disablePadding: true,
|
|
91
|
+
children: /*#__PURE__*/_jsxs(ListItemButton, {
|
|
92
|
+
onClick: handleCreateNew,
|
|
93
|
+
children: [/*#__PURE__*/_jsx(ListItemAvatar, {
|
|
94
|
+
children: /*#__PURE__*/_jsx(Avatar, {
|
|
95
|
+
sx: {
|
|
96
|
+
backgroundColor: "transparent"
|
|
97
|
+
},
|
|
98
|
+
children: /*#__PURE__*/_jsx(AddIcon, {
|
|
99
|
+
fontSize: "small",
|
|
100
|
+
sx: {
|
|
101
|
+
color: "secondary.main"
|
|
102
|
+
}
|
|
103
|
+
})
|
|
104
|
+
})
|
|
105
|
+
}), /*#__PURE__*/_jsx(ListItemText, {
|
|
106
|
+
primary: t("create_phrase_list_from_selection")
|
|
107
|
+
})]
|
|
108
|
+
})
|
|
109
|
+
})
|
|
110
|
+
})]
|
|
111
|
+
})
|
|
112
|
+
});
|
|
113
|
+
}
|
|
@@ -1,15 +1,22 @@
|
|
|
1
|
-
import { useState,
|
|
1
|
+
import { useState, useRef } from "react";
|
|
2
2
|
import useMediaQuery from "@mui/material/useMediaQuery";
|
|
3
3
|
import { useTheme } from "@mui/material/styles";
|
|
4
4
|
import { makeStyles } from "tss-react/mui";
|
|
5
|
-
import { Slide, IconButton, Dialog, AppBar, Toolbar, Typography } from "@mui/material";
|
|
5
|
+
import { Slide, IconButton, Dialog, AppBar, Toolbar, Typography, Button, Paper, ToggleButton, ToggleButtonGroup } from "@mui/material";
|
|
6
6
|
import CloseIcon from "@mui/icons-material/Close";
|
|
7
|
+
import PublishIcon from "@mui/icons-material/Publish";
|
|
8
|
+
import GetAppIcon from "@mui/icons-material/GetApp";
|
|
9
|
+
import AddIcon from "@mui/icons-material/Add";
|
|
10
|
+
import AutoFixHighIcon from "@mui/icons-material/AutoFixHigh";
|
|
11
|
+
import ListIcon from "@mui/icons-material/List";
|
|
12
|
+
import TableChartIcon from "@mui/icons-material/TableChart";
|
|
13
|
+
import DefaultButton from "../../Misc/DefaultColourButton/DefaultColourButton";
|
|
7
14
|
import { Tabs, Tab, Box, Tooltip } from "@mui/material";
|
|
8
15
|
import ArrowDropDownIcon from "@mui/icons-material/ArrowDropDown";
|
|
9
16
|
import ArrowDropUpIcon from "@mui/icons-material/ArrowDropUp";
|
|
10
17
|
import Share from "@mui/icons-material/Share";
|
|
11
18
|
import PlayCircleFilledIcon from "@mui/icons-material/PlayCircleFilled";
|
|
12
|
-
import PhrasesEditor from "../Phrases/Phrases";
|
|
19
|
+
import PhrasesEditor, { Modes } from "../Phrases/Phrases";
|
|
13
20
|
import UpdatePhraseList from "../../Forms/UpdatePhraseList/UpdatePhraseList";
|
|
14
21
|
import { randomId } from "../../utils/index";
|
|
15
22
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
@@ -27,18 +34,6 @@ const useStyles = makeStyles()(theme => ({
|
|
|
27
34
|
button: {
|
|
28
35
|
margin: theme.spacing(1)
|
|
29
36
|
},
|
|
30
|
-
pane: {
|
|
31
|
-
height: "calc(100vh - 104px)",
|
|
32
|
-
[theme.breakpoints.up("sm")]: {
|
|
33
|
-
height: "calc(100vh - 112px)"
|
|
34
|
-
}
|
|
35
|
-
},
|
|
36
|
-
paneFull: {
|
|
37
|
-
height: "calc(100%)",
|
|
38
|
-
[theme.breakpoints.up("sm")]: {
|
|
39
|
-
height: "calc(100vh - 48px)"
|
|
40
|
-
}
|
|
41
|
-
},
|
|
42
37
|
settings: {
|
|
43
38
|
backgroundColor: theme.palette.background.default,
|
|
44
39
|
overflow: "scroll"
|
|
@@ -95,7 +90,11 @@ function PhraseList({
|
|
|
95
90
|
onSubmit,
|
|
96
91
|
handleChange,
|
|
97
92
|
handleUpdatePhrases,
|
|
98
|
-
handlePlayPhraseList
|
|
93
|
+
handlePlayPhraseList,
|
|
94
|
+
otherPhraseLists,
|
|
95
|
+
otherPhraseListsLoading,
|
|
96
|
+
handleTransferPhrase,
|
|
97
|
+
handleCreatePhraseListFromSelection
|
|
99
98
|
}) {
|
|
100
99
|
const theme = useTheme();
|
|
101
100
|
const {
|
|
@@ -105,9 +104,19 @@ function PhraseList({
|
|
|
105
104
|
const isSmallScreen = useMediaQuery(theme.breakpoints.down("md"));
|
|
106
105
|
const tabVariant = isSmallScreen ? "fullWidth" : null;
|
|
107
106
|
const [tabValue, setTabValue] = useState(0);
|
|
108
|
-
const
|
|
107
|
+
const [isGeneratePhrasesDialogOpen, setIsGeneratePhrasesDialogOpen] = useState(false);
|
|
108
|
+
const [mode, setMode] = useState(Modes.NORMAL);
|
|
109
|
+
const handleCloseWithReset = () => {
|
|
110
|
+
setIsGeneratePhrasesDialogOpen(false);
|
|
111
|
+
handleClose();
|
|
112
|
+
};
|
|
113
|
+
const scriptDownloadRef = useRef(null);
|
|
114
|
+
const handleChangeTab = (_, newValue) => {
|
|
109
115
|
setTabValue(newValue);
|
|
110
116
|
};
|
|
117
|
+
const handleModeSelection = (_, newMode) => {
|
|
118
|
+
if (newMode) setMode(newMode);
|
|
119
|
+
};
|
|
111
120
|
const updatePhrases = async phrases => {
|
|
112
121
|
try {
|
|
113
122
|
handleUpdatePhrases(courseId, sectionId, topicId, phrases);
|
|
@@ -124,12 +133,16 @@ function PhraseList({
|
|
|
124
133
|
children: /*#__PURE__*/_jsxs(Dialog, {
|
|
125
134
|
fullScreen: true,
|
|
126
135
|
open: open,
|
|
127
|
-
onClose:
|
|
128
|
-
|
|
136
|
+
onClose: handleCloseWithReset,
|
|
137
|
+
slots: {
|
|
138
|
+
transition: Transition
|
|
139
|
+
},
|
|
129
140
|
"data-cy": "bot-editor-dialog",
|
|
130
141
|
sx: theme => ({
|
|
131
142
|
"& .MuiDialog-paper": {
|
|
132
|
-
backgroundColor: theme.palette.mode === "light" ? theme.palette.grey[200] : null
|
|
143
|
+
backgroundColor: theme.palette.mode === "light" ? theme.palette.grey[200] : null,
|
|
144
|
+
display: "flex",
|
|
145
|
+
flexDirection: "column"
|
|
133
146
|
}
|
|
134
147
|
}),
|
|
135
148
|
children: [/*#__PURE__*/_jsxs(AppBar, {
|
|
@@ -140,7 +153,7 @@ function PhraseList({
|
|
|
140
153
|
"data-cy": "close-dialog",
|
|
141
154
|
edge: "start",
|
|
142
155
|
color: "inherit",
|
|
143
|
-
onClick:
|
|
156
|
+
onClick: handleCloseWithReset,
|
|
144
157
|
"aria-label": "Close",
|
|
145
158
|
size: "large",
|
|
146
159
|
children: /*#__PURE__*/_jsx(CloseIcon, {})
|
|
@@ -213,9 +226,91 @@ function PhraseList({
|
|
|
213
226
|
})]
|
|
214
227
|
})
|
|
215
228
|
})]
|
|
229
|
+
}), isCreator && tabValue === 0 && /*#__PURE__*/_jsxs(Paper, {
|
|
230
|
+
elevation: 0,
|
|
231
|
+
sx: {
|
|
232
|
+
flexShrink: 0,
|
|
233
|
+
px: 2,
|
|
234
|
+
py: 1.5,
|
|
235
|
+
display: "flex",
|
|
236
|
+
alignItems: "center",
|
|
237
|
+
justifyContent: "space-between",
|
|
238
|
+
flexWrap: "wrap",
|
|
239
|
+
gap: 1,
|
|
240
|
+
borderRadius: 0,
|
|
241
|
+
borderBottom: 1,
|
|
242
|
+
borderColor: "divider"
|
|
243
|
+
},
|
|
244
|
+
children: [/*#__PURE__*/_jsx(Typography, {
|
|
245
|
+
variant: "subtitle1",
|
|
246
|
+
sx: {
|
|
247
|
+
fontWeight: "bold"
|
|
248
|
+
},
|
|
249
|
+
children: t("phrases")
|
|
250
|
+
}), /*#__PURE__*/_jsxs(Box, {
|
|
251
|
+
sx: {
|
|
252
|
+
display: "flex",
|
|
253
|
+
alignItems: "center",
|
|
254
|
+
gap: 1,
|
|
255
|
+
flexWrap: "wrap"
|
|
256
|
+
},
|
|
257
|
+
children: [subscription?.isPaidUser && /*#__PURE__*/_jsx(Button, {
|
|
258
|
+
color: "secondary",
|
|
259
|
+
variant: "contained",
|
|
260
|
+
size: "small",
|
|
261
|
+
startIcon: /*#__PURE__*/_jsx(AutoFixHighIcon, {}),
|
|
262
|
+
onClick: () => setIsGeneratePhrasesDialogOpen(true),
|
|
263
|
+
children: t("generate_phrases")
|
|
264
|
+
}), /*#__PURE__*/_jsx(Button, {
|
|
265
|
+
color: "primary",
|
|
266
|
+
variant: "contained",
|
|
267
|
+
size: "small",
|
|
268
|
+
startIcon: /*#__PURE__*/_jsx(AddIcon, {}),
|
|
269
|
+
onClick: () => setIsCreatePhraseDialogOpen(true),
|
|
270
|
+
children: t("add_phrase")
|
|
271
|
+
}), /*#__PURE__*/_jsx(DefaultButton, {
|
|
272
|
+
variant: "contained",
|
|
273
|
+
size: "small",
|
|
274
|
+
onClick: () => setIsUploadPhrasesDialogOpen(true),
|
|
275
|
+
endIcon: /*#__PURE__*/_jsx(PublishIcon, {}),
|
|
276
|
+
children: t("upload")
|
|
277
|
+
}), /*#__PURE__*/_jsx(DefaultButton, {
|
|
278
|
+
variant: "contained",
|
|
279
|
+
size: "small",
|
|
280
|
+
onClick: () => scriptDownloadRef.current?.(),
|
|
281
|
+
endIcon: /*#__PURE__*/_jsx(GetAppIcon, {}),
|
|
282
|
+
children: t("download")
|
|
283
|
+
}), /*#__PURE__*/_jsxs(ToggleButtonGroup, {
|
|
284
|
+
size: "small",
|
|
285
|
+
value: mode,
|
|
286
|
+
exclusive: true,
|
|
287
|
+
onChange: handleModeSelection,
|
|
288
|
+
"aria-label": t("editor_mode"),
|
|
289
|
+
children: [/*#__PURE__*/_jsx(ToggleButton, {
|
|
290
|
+
value: Modes.NORMAL,
|
|
291
|
+
"aria-label": t("normal_mode"),
|
|
292
|
+
children: /*#__PURE__*/_jsx(Tooltip, {
|
|
293
|
+
title: t("normal_mode"),
|
|
294
|
+
children: /*#__PURE__*/_jsx(ListIcon, {
|
|
295
|
+
fontSize: "small"
|
|
296
|
+
})
|
|
297
|
+
})
|
|
298
|
+
}), /*#__PURE__*/_jsx(ToggleButton, {
|
|
299
|
+
value: Modes.SPREADSHEET,
|
|
300
|
+
"data-cy": "spreadsheet-toggle",
|
|
301
|
+
"aria-label": t("spreadsheet_mode"),
|
|
302
|
+
children: /*#__PURE__*/_jsx(Tooltip, {
|
|
303
|
+
title: t("spreadsheet_mode"),
|
|
304
|
+
children: /*#__PURE__*/_jsx(TableChartIcon, {
|
|
305
|
+
fontSize: "small"
|
|
306
|
+
})
|
|
307
|
+
})
|
|
308
|
+
})]
|
|
309
|
+
})]
|
|
310
|
+
})]
|
|
216
311
|
}), tabValue === 0 ? /*#__PURE__*/_jsx(Box, {
|
|
217
|
-
className: hidden ? classes.paneFull : classes.pane,
|
|
218
312
|
sx: {
|
|
313
|
+
flex: 1,
|
|
219
314
|
overflowY: "auto"
|
|
220
315
|
},
|
|
221
316
|
children: /*#__PURE__*/_jsx(PhrasesEditor, {
|
|
@@ -250,13 +345,22 @@ function PhraseList({
|
|
|
250
345
|
subscription: subscription,
|
|
251
346
|
topicGoal: topicGoal,
|
|
252
347
|
verificationStatus: verificationStatus,
|
|
253
|
-
phraseListName: initialValues.phraseListName
|
|
348
|
+
phraseListName: initialValues.phraseListName,
|
|
349
|
+
otherPhraseLists: otherPhraseLists,
|
|
350
|
+
otherPhraseListsLoading: otherPhraseListsLoading,
|
|
351
|
+
handleTransferPhrase: handleTransferPhrase,
|
|
352
|
+
handleCreatePhraseListFromSelection: handleCreatePhraseListFromSelection,
|
|
353
|
+
isGeneratePhrasesDialogOpen: isGeneratePhrasesDialogOpen,
|
|
354
|
+
setIsGeneratePhrasesDialogOpen: setIsGeneratePhrasesDialogOpen,
|
|
355
|
+
mode: mode,
|
|
356
|
+
scriptDownloadRef: scriptDownloadRef
|
|
254
357
|
})
|
|
255
358
|
}) : null, tabValue === 1 ? /*#__PURE__*/_jsx(Box, {
|
|
256
|
-
className: hidden ? classes.paneFull : classes.pane,
|
|
257
359
|
sx: {
|
|
360
|
+
flex: 1,
|
|
258
361
|
overflowY: "auto"
|
|
259
362
|
},
|
|
363
|
+
className: classes.settings,
|
|
260
364
|
children: /*#__PURE__*/_jsx(UpdatePhraseList, {
|
|
261
365
|
t: t,
|
|
262
366
|
touched: touched,
|