Skip to content

Commit 3ac1398

Browse files
author
laurent.abbal
committed
Ajout de styles pour le bouton IA et mise à jour de la logique d'affichage des boutons d'exécution et de redémarrage dans l'éditeur de code.
1 parent 2b66fc3 commit 3ac1398

File tree

3 files changed

+211
-8
lines changed

3 files changed

+211
-8
lines changed

public/css/custom.css

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -644,6 +644,43 @@ svg {
644644

645645

646646
/* BUTTONS */
647+
648+
/* Bouton IA */
649+
.btn-ia {
650+
color: #fff;
651+
background-color: #6f42c1;
652+
border-color: #6f42c1;
653+
}
654+
.btn-ia:hover,
655+
.btn-ia:focus,
656+
.btn-ia.focus {
657+
color: #fff;
658+
background-color: #5a379e;
659+
border-color: #52348a;
660+
text-decoration: none;
661+
}
662+
.btn-ia:active,
663+
.btn-ia.active,
664+
.show > .btn-ia.dropdown-toggle {
665+
color: #fff;
666+
background-color: #52348a;
667+
border-color: #472f7a;
668+
}
669+
.btn-ia.disabled,
670+
.btn-ia:disabled {
671+
color: #fff;
672+
background-color: #6f42c1;
673+
border-color: #6f42c1;
674+
opacity: 0.65;
675+
}
676+
677+
/* Optionnel : ombre au focus */
678+
.btn-ia:focus {
679+
box-shadow: 0 0 0 0.2rem rgba(111, 66, 193, 0.5);
680+
}
681+
682+
683+
/* Bouton sm */
647684
.btn-sm, .btn-group-sm > .btn {
648685
padding: 6px 8px 4px 8px;
649686
font-size: 80%;

resources/views/copies/inc-copie-correction-afficher-js.blade.php

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,23 @@ function updateEditors(status) {
2222
if (status === 'init') {
2323
console.log
2424
document.getElementById("output_" + editor_id).innerText = "Prêt!\n";
25+
document.getElementById("run_" + editor_id).style.display = 'inline-block';
2526
document.getElementById("run_" + editor_id).innerHTML = '<i class="fas fa-play"></i>';
2627
document.getElementById("run_" + editor_id).disabled = false;
2728
document.getElementById("restart_" + editor_id).style.display = 'none';
2829
}
2930
if (status === 'completed') {
31+
document.getElementById("run_" + editor_id).style.display = 'inline-block';
3032
document.getElementById("run_" + editor_id).innerHTML = '<i class="fas fa-play"></i>';
3133
document.getElementById("run_" + editor_id).disabled = false;
3234
document.getElementById("restart_" + editor_id).style.display = 'none';
33-
}
35+
}
36+
if (status === 'running') {
37+
//document.getElementById("run_" + event.data.id).innerHTML = '<i class="fas fa-cog fa-spin"></i>';
38+
//document.getElementById("run_" + event.data.id).disabled = true;
39+
document.getElementById("run_" + event.data.id).style.display = 'none';
40+
document.getElementById("restart_" + event.data.id).style.display = 'inline-block';
41+
}
3442
}
3543
}
3644
@@ -45,9 +53,7 @@ function setupWorkerListener(worker) {
4553
4654
if (typeof event.data.status !== 'undefined') {
4755
if (event.data.status === 'running') {
48-
document.getElementById("run_" + event.data.id).innerHTML = '<i class="fas fa-cog fa-spin"></i>';
49-
document.getElementById("run_" + event.data.id).disabled = true;
50-
document.getElementById("restart_" + event.data.id).style.display = 'block';
56+
updateEditors('running');
5157
}
5258
5359
if (event.data.status === 'completed') {
@@ -99,6 +105,7 @@ function restart(id) {
99105
setupWorkerListener(pyodideWorker);
100106
101107
// Réinitialiser les boutons d'exécution et d'arrêt
108+
document.getElementById("run_" + id).style.display = 'inline-block';
102109
document.getElementById("run_" + id).innerHTML = '<i class="fas fa-circle-notch fa-spin"></i>';
103110
document.getElementById("run_" + id).disabled = true;
104111
document.getElementById("restart_" + id).style.display = 'none';

resources/views/copies/inc-copie-correction-afficher.blade.php

Lines changed: 163 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,19 +39,108 @@
3939
<span class="text-monospace small text-muted"><kbd>1</kbd><span class="ml-1 mr-1">+</span><kbd>2</kbd></span>
4040
<input id="code_option_2_devoir-{{$loop->iteration}}" name="code_option_devoir-{{$loop->iteration}}" class="ml-1 align-middle" style="display:inline;cursor:pointer" type="radio" checked />
4141
</div>
42+
4243
<div class="form-check d-block text-right pl-0">
4344
<span class="text-monospace small text-muted"><kbd>2</kbd></span>
4445
<input id="code_option_3_devoir-{{$loop->iteration}}" name="code_option_devoir-{{$loop->iteration}}" class="ml-1 align-middle" style="display:inline;cursor:pointer" type="radio" />
4546
</div>
47+
4648
<div class="mt-2 text-right">
47-
<button id="run_{{ $loop->iteration }}" data-pyodide="run" onclick="run('{{ $loop->iteration }}')" style="width:40px;" type="button" class="btn btn-primary text-center mb-1 btn-sm"><i class="fas fa-circle-notch fa-spin"></i></button>
49+
<!-- BOUTON RUN -->
50+
<button id="run_{{ $loop->iteration }}" data-pyodide="run" onclick="run('{{ $loop->iteration }}')" type="button" class="btn btn-primary text-center mb-1" style="width:40px;"><i class="fas fa-circle-notch fa-spin"></i></button>
51+
52+
<!-- BOUTON RESTART -->
53+
<button id="restart_{{ $loop->iteration }}" data-pyodide="restart" onclick="restart('{{ $loop->iteration }}')" type="button" class="btn btn-dark text-center mb-1" style="width:40px;display:none;" data-toggle="tooltip" data-placement="right" data-trigger="hover" title="{{__('Cliquer ici pour interrompre l\'exécution du code. Python redémarrera complètement mais votre code sera conservé dans l\'éditeur. Le redémarrage peut prendre quelques secondes.')}}"><i class="fas fa-stop"></i></button>
4854
</div>
49-
<div id="restart_{{ $loop->iteration }}" style="display:none;">
50-
<button style="width:40px;" type="button" data-pyodide="restart" onclick="restart('{{ $loop->iteration }}')" class="btn btn-dark btn-sm" style="padding-top:6px;" data-toggle="tooltip" data-placement="right" data-trigger="hover" title="{{__('Si le bouton d\'arrêt ne permet pas d\'interrompre l\'exécution du code, cliquer ici. Python redémarrera complètement mais votre code sera conservé dans l\'éditeur. Le redémarrage peut prendre quelques secondes.')}}"><i class="fas fa-stop"></i></button>
55+
56+
<!-- copier prompt dans presse papier -->
57+
<?php
58+
if ($sujet->type == 'exo'){
59+
60+
$prompt = "
61+
Vous êtes un assistant pédagogique expert en Python.
62+
Je vais vous fournir :
63+
1. L'énoncé complet de l'exercice.
64+
2. Le code que l'élève a proposé.
65+
66+
Merci de me rendre un rapport structuré comportant deux parties.
67+
68+
**PARTIE 1 - Présentation synthétique**
69+
Dire si code est correct. Et si il ne l'est pas, faire la liste des erreurs en faisant référence, si possible, aux numéros de ligne du code.
70+
71+
**PARTIE 2 - Présentation détaillée**
72+
1. **Résumé de l'exercice** (en vos propres mots) - pour vérifier la bonne compréhension du sujet.
73+
2. **Analyse de la correction fonctionnelle**
74+
- Le code répond-il à tous les points de l'énoncé ?
75+
- Cas limites ou d'erreurs non gérés.
76+
3. **Points techniques et logiques**
77+
- Erreurs à corriger (avec référence aux numéros de ligne).
78+
- Améliorations possibles de l'algorithme (complexité, clarté).
79+
4. **Qualité du code**
80+
- Respect des conventions Python (PEP 8, noms de variables, docstrings, etc.).
81+
- Lisibilité et structuration (fonctions, modularité).
82+
5. **Propositions de tests**
83+
- Jeux de données pour tester chaque situation (valeurs normales, extrêmes, cas particuliers).
84+
- Version avec des `assert` prêts à être copiés-collés
85+
6. **Suggestions pédagogiques**
86+
- Explications à donner à l'élève pour chaque erreur.
87+
- Exercices complémentaires ou variantes pour approfondir.
88+
89+
---
90+
91+
**ÉNONCÉ DE L'EXERCICE :**
92+
{$sujet_json->enonce}
93+
94+
**CODE DE L'ÉLÈVE :**
95+
```python
96+
{$copie_cell->source[0]}
97+
```
98+
Merci de structurer votre réponse en sections numérotées et de citer les lignes de code concernées lorsque vous signalez un problème.";
99+
100+
}else {
101+
102+
$prompt = "
103+
Vous êtes un assistant pédagogique expert en Python.
104+
Je vais vous fournir le code que l'élève a proposé.
105+
106+
Merci de me rendre un rapport structuré comportant deux parties.
107+
108+
**PARTIE 1 - Présentation synthétique**
109+
Dire si code est correct. Et si il ne l'est pas, faire la liste des erreurs en faisant référence, si possible, aux numéros de ligne du code.
110+
111+
**PARTIE 2 - Présentation détaillée**
112+
1. **Points techniques et logiques**
113+
- Erreurs à corriger (avec référence aux numéros de ligne).
114+
- Améliorations possibles de l'algorithme (complexité, clarté).
115+
2. **Qualité du code**
116+
- Respect des conventions Python (PEP 8, noms de variables, docstrings, etc.).
117+
- Lisibilité et structuration (fonctions, modularité).
118+
3. **Propositions de tests**
119+
- Jeux de données pour tester chaque situation (valeurs normales, extrêmes, cas particuliers).
120+
- Version avec des `assert` prêts à être copiés-collés
121+
4. **Suggestions pédagogiques**
122+
- Explications à donner à l'élève pour chaque erreur.
123+
- Exercices complémentaires ou variantes pour approfondir.
124+
125+
---
126+
127+
**CODE DE L'ÉLÈVE :**
128+
```python
129+
{$copie_cell->source[0]}
130+
```
131+
Merci de structurer votre réponse en sections numérotées et de citer les lignes de code concernées lorsque vous signalez un problème.";
132+
133+
}
134+
?>
135+
136+
<div class="mt-1 text-right">
137+
<button type="button" onclick='copyAndNotify(this, {!! json_encode($prompt, JSON_UNESCAPED_UNICODE|JSON_HEX_APOS) !!})' class="btn btn-ia btn-xs"><i class="fa-solid fa-wand-magic-sparkles" style="padding-top:5px;padding-bottom:3px;"></i></button>
51138
</div>
139+
140+
52141
</div>
53142
<div id="console_{{ $loop->iteration }}" class="col">
54-
<div class="text-dark small text-monospace" style="float:right;padding:5px 12px 0px 0px">console</div>
143+
<div class="text-dark text-monospace" style="float:right;font-size:70%;padding:5px 12px 0px 0px">console</div>
55144
<div id="output_{{ $loop->iteration }}" class="text-monospace p-3 text-white bg-secondary small" style="white-space: pre-wrap;border-radius:4px;min-height:100px;height:100%;">Prêt!</div>
56145
</div>
57146
</div>
@@ -66,3 +155,73 @@
66155
<br />
67156

68157
</div>
158+
159+
<script>
160+
function copyAndNotify(button, text) {
161+
const onSuccess = () => {
162+
animateOpacity(button);
163+
showCopiedMessage(button);
164+
};
165+
166+
if (navigator.clipboard && navigator.clipboard.writeText) {
167+
navigator.clipboard.writeText(text).then(onSuccess, () => {
168+
fallbackCopy(text, button);
169+
showCopiedMessage(button);
170+
});
171+
} else {
172+
fallbackCopy(text, button);
173+
showCopiedMessage(button);
174+
}
175+
}
176+
177+
function fallbackCopy(text, button) {
178+
const ta = document.createElement('textarea');
179+
ta.value = text;
180+
ta.style.position = 'fixed';
181+
ta.style.top = '-9999px';
182+
document.body.appendChild(ta);
183+
ta.select();
184+
try { document.execCommand('copy'); }
185+
catch (err) { console.error('Copy failed', err); }
186+
document.body.removeChild(ta);
187+
}
188+
189+
function animateOpacity(button) {
190+
button.style.transition = 'none';
191+
button.style.opacity = '0.1';
192+
void button.offsetWidth;
193+
button.style.transition = 'opacity 2s ease-in-out';
194+
button.style.opacity = '1';
195+
}
196+
197+
function showCopiedMessage(button) {
198+
// 1) Calculer la position du bouton dans la page
199+
const rect = button.getBoundingClientRect();
200+
const msg = document.createElement('span');
201+
msg.innerText = 'copié !';
202+
203+
// 2) Styles inline pour que rien d'autre ne bouge
204+
Object.assign(msg.style, {
205+
position: 'absolute',
206+
left: (rect.left + rect.width/2 + window.pageXOffset) + 'px',
207+
top: (rect.bottom + window.pageYOffset + 4) + 'px',
208+
transform: 'translateX(-50%)',
209+
whiteSpace: 'nowrap',
210+
pointerEvents: 'none',
211+
opacity: '1',
212+
zIndex: '9999',
213+
fontSize: '0.9em',
214+
transition: 'transform 2s ease-out, opacity 2s ease-out'
215+
});
216+
217+
document.body.appendChild(msg);
218+
219+
// 3) Déclencher l’animation de descente + disparition
220+
void msg.offsetWidth;
221+
msg.style.transform = 'translateX(-50%) translateY(20px)';
222+
msg.style.opacity = '0';
223+
224+
// 4) Nettoyage après animation
225+
msg.addEventListener('transitionend', () => msg.remove());
226+
}
227+
</script>

0 commit comments

Comments
 (0)