+
}
onClick={handleOnReturnButtonClick}
color="primary"
sx={{ marginLeft: '-0.5rem', fontSize: 16 }}
+ disabled={isSaving} // Disable button while saving
>
- Retour
+ {isSaving ? 'Enregistrement...' : 'Retour'}
- setShowDialog(false)}
- buttonOrderType="warning"
- />
);
};
diff --git a/client/src/pages/Teacher/EditorQuiz/EditorQuiz.tsx b/client/src/pages/Teacher/EditorQuiz/EditorQuiz.tsx
index 2b220da..12c0f65 100644
--- a/client/src/pages/Teacher/EditorQuiz/EditorQuiz.tsx
+++ b/client/src/pages/Teacher/EditorQuiz/EditorQuiz.tsx
@@ -1,22 +1,27 @@
-// EditorQuiz.tsx
-import React, { useState, useEffect, CSSProperties } from 'react';
+import React, { useState, useEffect, useRef, CSSProperties } from 'react';
import { useParams, useNavigate } from 'react-router-dom';
import { FolderType } from '../../../Types/FolderType';
+import NewEditor from 'src/components/Editor/newEditor';
import Editor from 'src/components/Editor/Editor';
+
import GiftCheatSheet from 'src/components/GIFTCheatSheet/GiftCheatSheet';
import GIFTTemplatePreview from 'src/components/GiftTemplate/GIFTTemplatePreview';
import { QuizType } from '../../../Types/QuizType';
+
import SaveIcon from '@mui/icons-material/Save';
-import './editorQuiz.css';
-import { Button, TextField, NativeSelect, Divider } from '@mui/material';
+import './EditorQuiz.css';
+import { Button, TextField, NativeSelect, Divider, Dialog, DialogTitle, DialogActions, DialogContent, MenuItem, Select, Snackbar } from '@mui/material';
import ReturnButton from 'src/components/ReturnButton/ReturnButton';
import ImageGalleryModal from 'src/components/ImageGallery/ImageGalleryModal/ImageGalleryModal';
import ApiService from '../../../services/ApiService';
import { escapeForGIFT } from '../../../utils/giftUtils';
+
+import { Upload } from '@mui/icons-material';
+import SaveIcon from '@mui/icons-material/Save';
import { ENV_VARIABLES } from 'src/constants';
interface EditQuizParams {
@@ -30,7 +35,7 @@ const QuizForm: React.FC = () => {
const [filteredValue, setFilteredValue] = useState
([]);
const { id } = useParams();
- const [value, setValue] = useState('');
+ const [values, setValues] = useState([]);
const [isNewQuiz, setNewQuiz] = useState(false);
const [quiz, setQuiz] = useState(null);
const navigate = useNavigate();
@@ -41,6 +46,31 @@ const QuizForm: React.FC = () => {
};
const [showScrollButton, setShowScrollButton] = useState(false);
+ const [isImagesCollapsed, setIsImagesCollapsed] = useState(true);
+ const [isCheatSheetCollapsed, setIsCheatSheetCollapsed] = useState(true);
+ const [isUploadCollapsed, setIsUploadCollapsed] = useState(true);
+ const [snackbarOpen, setSnackbarOpen] = useState(false);
+ const [snackbarMessage, setSnackbarMessage] = useState('');
+ const [copySuccess, setCopySuccess] = useState(null);
+ const [dialogOpen, setDialogOpen] = useState(false);
+ const fileInputRef = useRef(null);
+
+ const [useNewEditor, setUserNewEditor] = useState(false);
+
+ const QuestionVraiFaux = "::Exemple de question vrai/faux:: \n 2+2 \\= 4 ? {T} //Utilisez les valeurs {T}, {F}, {TRUE} et {FALSE}.";
+ const QuestionChoixMul = "::Ville capitale du Canada:: \nQuelle ville est la capitale du Canada? {\n~ Toronto\n~ Montréal\n= Ottawa #Rétroaction spécifique.\n} // Commentaire non visible (au besoin)";
+ const QuestionChoixMulMany = "::Villes canadiennes:: \n Quelles villes trouve-t-on au Canada? { \n~ %33.3% Montréal \n ~ %33.3% Ottawa \n ~ %33.3% Vancouver \n ~ %-100% New York \n ~ %-100% Paris \n#### Rétroaction globale de la question. \n} // Utilisez tilde (signe de vague) pour toutes les réponses. // On doit indiquer le pourcentage de chaque réponse.";
+ const QuestionCourte = "::Clé et porte:: \n Avec quoi ouvre-t-on une porte? { \n= clé \n= clef \n} // Permet de fournir plusieurs bonnes réponses. // Note: La casse n'est pas prise en compte.";
+ const QuestionNum = "::Question numérique avec marge:: \nQuel est un nombre de 1 à 5 ? {\n#3:2\n}\n \n// Plage mathématique spécifiée avec des points de fin d'intervalle. \n ::Question numérique avec plage:: \n Quel est un nombre de 1 à 5 ? {\n#1..5\n} \n\n// Réponses numériques multiples avec crédit partiel et commentaires.\n::Question numérique avec plusieurs réponses::\nQuand est né Ulysses S. Grant ? {\n# =1822:0 # Correct ! Crédit complet. \n=%50%1822:2 # Il est né en 1822. Demi-crédit pour être proche.\n}";
+
+ const templates = [
+ { label: 'Vrai/Faux', value: QuestionVraiFaux },
+ { label: 'Choix multiples R1', value: QuestionChoixMul },
+ { label: 'Choix multiples R2+', value: QuestionChoixMulMany },
+ { label: 'Réponse courte', value: QuestionCourte },
+ { label: 'Numérique', value: QuestionNum },
+ ];
+
const scrollToTop = () => {
window.scrollTo({ top: 0, behavior: 'smooth' });
};
@@ -100,7 +130,7 @@ const QuizForm: React.FC = () => {
setQuizTitle(title);
setSelectedFolder(folderId);
setFilteredValue(content);
- setValue(quiz.content.join('\n\n'));
+ setValues(content);
} catch (error) {
window.alert(`Une erreur est survenue.\n Veuillez réessayer plus tard`)
@@ -112,13 +142,25 @@ const QuizForm: React.FC = () => {
fetchData();
}, [id]);
- function handleUpdatePreview(value: string) {
+ const handleAddQuestion = () => {
+ console.log("Adding question");
+ console.log("Current values:", values); // Log current state
+ setValues([...values, '']);
+ console.log("Updated values:", [...values, '']); // Log new state
+ };
+
+ const newHandleUpdatePreview = (newValues: string[]) => {
+ setValues(newValues);
+ setFilteredValue(newValues.filter(value => value.trim() !== ''));
+ };
+
+ const handleUpdatePreview = (value: string) => {
if (value !== '') {
- setValue(value);
+ setValues([value]);
}
// split value when there is at least one blank line
- const linesArray = value.split(/\n{2,}/);
+ const linesArray = value.split(/\n{2,}/);
// if the first item in linesArray is blank, remove it
if (linesArray[0] === '') linesArray.shift();
@@ -134,7 +176,6 @@ const QuizForm: React.FC = () => {
const handleQuizSave = async () => {
try {
- // check if everything is there
if (quizTitle == '') {
alert("Veuillez choisir un titre");
return;
@@ -153,7 +194,8 @@ const QuizForm: React.FC = () => {
}
}
- navigate('/teacher/dashboard');
+ setSnackbarMessage('Quiz enregistré avec succès!');
+ setSnackbarOpen(true);
} catch (error) {
window.alert(`Une erreur est survenue.\n Veuillez réessayer plus tard`)
console.log(error)
@@ -165,124 +207,212 @@ const QuizForm: React.FC = () => {
return Chargement...
;
}
+ const handleSnackbarClose = () => {
+ setSnackbarOpen(false);
+ };
+
+ const handleSaveImage = async () => {
+ try {
+ const inputElement = document.getElementById('file-input') as HTMLInputElement;
+
+ if (!inputElement?.files || inputElement.files.length === 0) {
+ setDialogOpen(true);
+ return;
+ }
+
+ if (!inputElement.files || inputElement.files.length === 0) {
+ window.alert("Veuillez d'abord choisir une image à téléverser.")
+ return;
+ }
+
+ const imageUrl = await ApiService.uploadImage(inputElement.files[0]);
+
+ // Check for errors
+ if (imageUrl.indexOf("ERROR") >= 0) {
+ window.alert(`Une erreur est survenue.\n Veuillez réessayer plus tard`)
+ return;
+ }
+
+ setImageLinks(prevLinks => [...prevLinks, imageUrl]);
+
+ // Reset the file input element
+ if (fileInputRef.current) {
+ fileInputRef.current.value = '';
+ }
+ } catch (error) {
+ window.alert(`Une erreur est survenue.\n${error}\nVeuillez réessayer plus tard.`)
+
+ }
+ };
+
const handleCopyToClipboard = async (link: string) => {
navigator.clipboard.writeText(link);
}
+ const handleFocusQuestion = (index: number) => {
+ const previewElement = document.querySelector('.preview-column');
+ if (previewElement) {
+ const questionElements = previewElement.querySelectorAll('.question-item');
+ if (questionElements[index]) {
+ questionElements[index].scrollIntoView({ behavior: 'smooth', block: 'start' });
+ }
+ }
+ };
+
+ const copyToClipboard = (text: string, label: string) => {
+ navigator.clipboard.writeText(text)
+ .then(() => {
+ setCopySuccess(`Copié dans le presse-papier: ${label}`);
+ })
+ .catch((error) => console.error('Clipboard error:', error));
+ };
+
+ const handleSelectChange = (value: string, label: string) => {
+ copyToClipboard(value, label);
+ };
+
+ const toggleEditor = () => {
+ setUserNewEditor(!useNewEditor);
+ }
const handleCopyImage = (id: string) => {
const escLink = `${ENV_VARIABLES.BACKEND_URL}/api/image/get/${id}`;
setImageLinks(prevLinks => [...prevLinks, escLink]);
}
return (
-
-
-
-
-