mirror of
https://github.com/ets-cfuhrman-pfe/EvalueTonSavoir.git
synced 2025-08-11 21:23:54 -04:00
Modèle de questions dans un dropdown
This commit is contained in:
parent
d6508826fc
commit
36d0755105
4 changed files with 90 additions and 74 deletions
75
client/package-lock.json
generated
75
client/package-lock.json
generated
|
|
@ -16,7 +16,7 @@
|
|||
"@fortawesome/react-fontawesome": "^0.2.0",
|
||||
"@mui/icons-material": "^6.4.6",
|
||||
"@mui/lab": "^5.0.0-alpha.153",
|
||||
"@mui/material": "^6.4.6",
|
||||
"@mui/material": "^6.4.9",
|
||||
"@types/uuid": "^9.0.7",
|
||||
"axios": "^1.8.1",
|
||||
"dompurify": "^3.2.3",
|
||||
|
|
@ -2044,7 +2044,6 @@
|
|||
"version": "11.14.0",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.14.0.tgz",
|
||||
"integrity": "sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.18.3",
|
||||
"@emotion/babel-plugin": "^11.13.5",
|
||||
|
|
@ -2087,7 +2086,6 @@
|
|||
"version": "11.14.0",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.14.0.tgz",
|
||||
"integrity": "sha512-XxfOnXFffatap2IyCeJyNov3kiDQWoR08gPUQxvbL7fxKryGBKUZUkG6Hz48DZwVrJSVh9sJboyV1Ds4OW6SgA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.18.3",
|
||||
"@emotion/babel-plugin": "^11.13.5",
|
||||
|
|
@ -3397,10 +3395,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@mui/core-downloads-tracker": {
|
||||
"version": "6.4.6",
|
||||
"resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-6.4.6.tgz",
|
||||
"integrity": "sha512-rho5Q4IscbrVmK9rCrLTJmjLjfH6m/NcqKr/mchvck0EIXlyYUB9+Z0oVmkt/+Mben43LMRYBH8q/Uzxj/c4Vw==",
|
||||
"license": "MIT",
|
||||
"version": "6.4.9",
|
||||
"resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-6.4.9.tgz",
|
||||
"integrity": "sha512-3UvsvOjqZJcokHKSzA1lskj2XMM/G5GBgge6ykwmAij2pGGxydGxAXirQlLaeoMwTKDS6BcrLqPZyPVwzri20A==",
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/mui-org"
|
||||
|
|
@ -3474,16 +3471,15 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@mui/material": {
|
||||
"version": "6.4.6",
|
||||
"resolved": "https://registry.npmjs.org/@mui/material/-/material-6.4.6.tgz",
|
||||
"integrity": "sha512-6UyAju+DBOdMogfYmLiT3Nu7RgliorimNBny1pN/acOjc+THNFVE7hlxLyn3RDONoZJNDi/8vO4AQQr6dLAXqA==",
|
||||
"license": "MIT",
|
||||
"version": "6.4.9",
|
||||
"resolved": "https://registry.npmjs.org/@mui/material/-/material-6.4.9.tgz",
|
||||
"integrity": "sha512-+5dExw9xUUFujIW889gB3qrfjeNo3YjYW7aWVZ6BlBIJnKpJ0jNcYZJpBUFoXt/FUV5Wy1V+/+XzR3Is2mXX2w==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.26.0",
|
||||
"@mui/core-downloads-tracker": "^6.4.6",
|
||||
"@mui/system": "^6.4.6",
|
||||
"@mui/types": "^7.2.21",
|
||||
"@mui/utils": "^6.4.6",
|
||||
"@mui/core-downloads-tracker": "^6.4.9",
|
||||
"@mui/system": "^6.4.9",
|
||||
"@mui/types": "~7.2.24",
|
||||
"@mui/utils": "^6.4.8",
|
||||
"@popperjs/core": "^2.11.8",
|
||||
"@types/react-transition-group": "^4.4.12",
|
||||
"clsx": "^2.1.1",
|
||||
|
|
@ -3502,7 +3498,7 @@
|
|||
"peerDependencies": {
|
||||
"@emotion/react": "^11.5.0",
|
||||
"@emotion/styled": "^11.3.0",
|
||||
"@mui/material-pigment-css": "^6.4.6",
|
||||
"@mui/material-pigment-css": "^6.4.9",
|
||||
"@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0",
|
||||
"react": "^17.0.0 || ^18.0.0 || ^19.0.0",
|
||||
"react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||
|
|
@ -3523,13 +3519,12 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@mui/material/node_modules/@mui/private-theming": {
|
||||
"version": "6.4.6",
|
||||
"resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-6.4.6.tgz",
|
||||
"integrity": "sha512-T5FxdPzCELuOrhpA2g4Pi6241HAxRwZudzAuL9vBvniuB5YU82HCmrARw32AuCiyTfWzbrYGGpZ4zyeqqp9RvQ==",
|
||||
"license": "MIT",
|
||||
"version": "6.4.8",
|
||||
"resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-6.4.8.tgz",
|
||||
"integrity": "sha512-sWwQoNSn6elsPTAtSqCf+w5aaGoh7AASURNmpy+QTTD/zwJ0Jgwt0ZaaP6mXq2IcgHxYnYloM/+vJgHPMkRKTQ==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.26.0",
|
||||
"@mui/utils": "^6.4.6",
|
||||
"@mui/utils": "^6.4.8",
|
||||
"prop-types": "^15.8.1"
|
||||
},
|
||||
"engines": {
|
||||
|
|
@ -3550,10 +3545,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@mui/material/node_modules/@mui/styled-engine": {
|
||||
"version": "6.4.6",
|
||||
"resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-6.4.6.tgz",
|
||||
"integrity": "sha512-vSWYc9ZLX46be5gP+FCzWVn5rvDr4cXC5JBZwSIkYk9xbC7GeV+0kCvB8Q6XLFQJy+a62bbqtmdwS4Ghi9NBlQ==",
|
||||
"license": "MIT",
|
||||
"version": "6.4.9",
|
||||
"resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-6.4.9.tgz",
|
||||
"integrity": "sha512-qZRWO0cT407NI4ZRjZcH+1SOu8f3JzLHqdMlg52GyEufM9pkSZFnf7xjpwnlvkixcGjco6wLlMD0VB43KRcBuA==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.26.0",
|
||||
"@emotion/cache": "^11.13.5",
|
||||
|
|
@ -3584,16 +3578,15 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@mui/material/node_modules/@mui/system": {
|
||||
"version": "6.4.6",
|
||||
"resolved": "https://registry.npmjs.org/@mui/system/-/system-6.4.6.tgz",
|
||||
"integrity": "sha512-FQjWwPec7pMTtB/jw5f9eyLynKFZ6/Ej9vhm5kGdtmts1z5b7Vyn3Rz6kasfYm1j2TfrfGnSXRvvtwVWxjpz6g==",
|
||||
"license": "MIT",
|
||||
"version": "6.4.9",
|
||||
"resolved": "https://registry.npmjs.org/@mui/system/-/system-6.4.9.tgz",
|
||||
"integrity": "sha512-JOj7efXGtZn+NIzX8KDyMpO1QKc0DhilPBsxvci1xAvI1e5AtAtfzrEuV5ZvN+lz2BDuzngCWlllnqQ/cg40RQ==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.26.0",
|
||||
"@mui/private-theming": "^6.4.6",
|
||||
"@mui/styled-engine": "^6.4.6",
|
||||
"@mui/types": "^7.2.21",
|
||||
"@mui/utils": "^6.4.6",
|
||||
"@mui/private-theming": "^6.4.8",
|
||||
"@mui/styled-engine": "^6.4.9",
|
||||
"@mui/types": "~7.2.24",
|
||||
"@mui/utils": "^6.4.8",
|
||||
"clsx": "^2.1.1",
|
||||
"csstype": "^3.1.3",
|
||||
"prop-types": "^15.8.1"
|
||||
|
|
@ -3624,13 +3617,12 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@mui/material/node_modules/@mui/utils": {
|
||||
"version": "6.4.6",
|
||||
"resolved": "https://registry.npmjs.org/@mui/utils/-/utils-6.4.6.tgz",
|
||||
"integrity": "sha512-43nZeE1pJF2anGafNydUcYFPtHwAqiBiauRtaMvurdrZI3YrUjHkAu43RBsxef7OFtJMXGiHFvq43kb7lig0sA==",
|
||||
"license": "MIT",
|
||||
"version": "6.4.8",
|
||||
"resolved": "https://registry.npmjs.org/@mui/utils/-/utils-6.4.8.tgz",
|
||||
"integrity": "sha512-C86gfiZ5BfZ51KqzqoHi1WuuM2QdSKoFhbkZeAfQRB+jCc4YNhhj11UXFVMMsqBgZ+Zy8IHNJW3M9Wj/LOwRXQ==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.26.0",
|
||||
"@mui/types": "^7.2.21",
|
||||
"@mui/types": "~7.2.24",
|
||||
"@types/prop-types": "^15.7.14",
|
||||
"clsx": "^2.1.1",
|
||||
"prop-types": "^15.8.1",
|
||||
|
|
@ -3753,10 +3745,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@mui/types": {
|
||||
"version": "7.2.21",
|
||||
"resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.21.tgz",
|
||||
"integrity": "sha512-6HstngiUxNqLU+/DPqlUJDIPbzUBxIVHb1MmXP0eTWDIROiCR2viugXpEif0PPe2mLqqakPzzRClWAnK+8UJww==",
|
||||
"license": "MIT",
|
||||
"version": "7.2.24",
|
||||
"resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.24.tgz",
|
||||
"integrity": "sha512-3c8tRt/CbWZ+pEg7QpSwbdxOk36EfmhbKf6AGZsD1EcLDLTSZoxxJ86FVtcjxvjuhdyBiWKSTGZFaXCnidO2kw==",
|
||||
"peerDependencies": {
|
||||
"@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
"@fortawesome/react-fontawesome": "^0.2.0",
|
||||
"@mui/icons-material": "^6.4.6",
|
||||
"@mui/lab": "^5.0.0-alpha.153",
|
||||
"@mui/material": "^6.4.6",
|
||||
"@mui/material": "^6.4.9",
|
||||
"@types/uuid": "^9.0.7",
|
||||
"axios": "^1.8.1",
|
||||
"dompurify": "^3.2.3",
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import GIFTTemplatePreview from 'src/components/GiftTemplate/GIFTTemplatePreview
|
|||
import { QuizType } from '../../../Types/QuizType';
|
||||
|
||||
import './editorQuiz.css';
|
||||
import { Button, TextField, NativeSelect, Divider, Dialog, DialogTitle, DialogActions, DialogContent } from '@mui/material';
|
||||
import { Button, TextField, NativeSelect, Divider, Dialog, DialogTitle, DialogActions, DialogContent, MenuItem, Select, Snackbar } from '@mui/material';
|
||||
import ReturnButton from 'src/components/ReturnButton/ReturnButton';
|
||||
|
||||
import ApiService from '../../../services/ApiService';
|
||||
|
|
@ -41,12 +41,26 @@ const QuizForm: React.FC = () => {
|
|||
const fileInputRef = useRef<HTMLInputElement>(null);
|
||||
const [dialogOpen, setDialogOpen] = useState(false);
|
||||
const [showScrollButton, setShowScrollButton] = useState(false);
|
||||
const [copySuccess, setCopySuccess] = useState(false);
|
||||
const [copySuccess, setCopySuccess] = useState<string | null>(null);
|
||||
|
||||
const scrollToTop = () => {
|
||||
window.scrollTo({ top: 0, behavior: 'smooth' });
|
||||
};
|
||||
|
||||
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 },
|
||||
];
|
||||
|
||||
useEffect(() => {
|
||||
const handleScroll = () => {
|
||||
if (window.scrollY > 300) {
|
||||
|
|
@ -205,26 +219,17 @@ const QuizForm: React.FC = () => {
|
|||
navigator.clipboard.writeText(link);
|
||||
}
|
||||
|
||||
const copyToClipboard = (text: string) => {
|
||||
const copyToClipboard = (text: string, label: string) => {
|
||||
navigator.clipboard.writeText(text)
|
||||
.then(() => {
|
||||
setCopySuccess(true); // Afficher le message de succès
|
||||
console.log(copySuccess);
|
||||
// Masquer le message de succès après quelques secondes
|
||||
setTimeout(() => {
|
||||
setCopySuccess(false);
|
||||
}, 3000); // 3 secondes
|
||||
setCopySuccess(`Copié dans le presse-papier: ${label}`);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Erreur lors de la copie dans le presse-papiers : ', error);
|
||||
});
|
||||
.catch((error) => console.error('Clipboard error:', error));
|
||||
};
|
||||
|
||||
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 handleSelectChange = (value: string, label: string) => {
|
||||
copyToClipboard(value, label);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className='quizEditor'>
|
||||
|
|
@ -265,21 +270,29 @@ const QuizForm: React.FC = () => {
|
|||
))}
|
||||
</NativeSelect></label>
|
||||
|
||||
<div style={{ display: "flex", flexDirection: "column", gap: "8px" }}>
|
||||
<div>
|
||||
<Button variant="contained" onClick={handleQuizSave}>
|
||||
Enregistrer
|
||||
</Button>
|
||||
<div className='sticky-buttons'>
|
||||
<Select
|
||||
value=""
|
||||
displayEmpty
|
||||
onChange={(e) => handleSelectChange(e.target.value, templates.find(t => t.value === e.target.value)?.label || '')}
|
||||
style={{ width: '210px' }}
|
||||
>
|
||||
<MenuItem value="" disabled>Modèles de questions</MenuItem>
|
||||
{templates.map((template, index) => (
|
||||
<MenuItem key={index} value={template.value}>{template.label}</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
<Button variant="contained" onClick={handleQuizSave}>Enregistrer</Button>
|
||||
</div>
|
||||
|
||||
<div style={{ display: "flex", flexWrap: "wrap", gap: "8px" }}>
|
||||
<Button variant="contained" onClick={() => copyToClipboard(QuestionVraiFaux)}>Vrai/Faux</Button>
|
||||
<Button variant="contained" onClick={() => copyToClipboard(QuestionChoixMul)}>Choix multiples R1</Button>
|
||||
<Button variant="contained" onClick={() => copyToClipboard(QuestionChoixMulMany)}>Choix multiples R2+</Button>
|
||||
<Button variant="contained" onClick={() => copyToClipboard(QuestionCourte)}>Réponse courte</Button>
|
||||
<Button variant="contained" onClick={() =>copyToClipboard(QuestionNum)}>Numérique</Button>
|
||||
</div>
|
||||
</div>
|
||||
<Snackbar
|
||||
open={!!copySuccess}
|
||||
autoHideDuration={3000}
|
||||
onClose={() => setCopySuccess(null)}
|
||||
message={copySuccess}
|
||||
anchorOrigin={{ vertical: 'bottom', horizontal: 'center' }}
|
||||
key={copySuccess ? 'open' : 'close'}
|
||||
/>
|
||||
|
||||
<Divider style={{ margin: '16px 0' }} />
|
||||
|
||||
|
|
|
|||
|
|
@ -83,3 +83,15 @@ input[type="file"] {
|
|||
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.sticky-buttons {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
background: #fff;
|
||||
z-index: 1000;
|
||||
padding: 8px 0;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue