Skip to content

Commit 30da109

Browse files
committed
Merge remote-tracking branch 'origin/1.11.x' into 1.11.x
2 parents d5c29cf + 5b52d2d commit 30da109

File tree

15 files changed

+694
-386
lines changed

15 files changed

+694
-386
lines changed

main/exercise/export/aiken/aiken_import.inc.php

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -44,36 +44,53 @@ function aiken_display_form()
4444
}
4545

4646
/**
47-
* Generates aiken format using AI api.
48-
* Requires plugin ai_helper to connect to the api.
47+
* Generates Aiken format using AI APIs (supports multiple providers).
48+
* Requires plugin ai_helper to connect to the API.
4949
*/
5050
function generateAikenForm()
5151
{
5252
if (!('true' === api_get_plugin_setting('ai_helper', 'tool_enable') && 'true' === api_get_plugin_setting('ai_helper', 'tool_quiz_enable'))) {
5353
return false;
5454
}
5555

56+
$plugin = AiHelperPlugin::create();
57+
$availableApis = $plugin->getApiList();
58+
59+
$configuredApi = $plugin->get('api_name');
60+
$hasSingleApi = count($availableApis) === 1 || isset($availableApis[$configuredApi]);
61+
5662
$form = new FormValidator(
5763
'aiken_generate',
5864
'post',
5965
api_get_self()."?".api_get_cidreq(),
6066
null
6167
);
6268
$form->addElement('header', get_lang('AIQuestionsGenerator'));
63-
$form->addElement('text', 'quiz_name', [get_lang('QuestionsTopic'), get_lang('QuestionsTopicHelp')]);
69+
70+
if ($hasSingleApi) {
71+
$apiName = $availableApis[$configuredApi] ?? $configuredApi;
72+
$form->addHtml('<div style="margin-bottom: 10px; font-size: 14px; color: #555;">'
73+
. sprintf(get_lang('UsingAIProviderX'), '<strong>'.htmlspecialchars($apiName).'</strong>').'</div>');
74+
}
75+
76+
$form->addElement('text', 'quiz_name', get_lang('QuestionsTopic'));
6477
$form->addRule('quiz_name', get_lang('ThisFieldIsRequired'), 'required');
65-
$form->addElement('number', 'nro_questions', [get_lang('NumberOfQuestions'), get_lang('AIQuestionsGeneratorNumberHelper')]);
78+
$form->addElement('number', 'nro_questions', get_lang('NumberOfQuestions'));
6679
$form->addRule('nro_questions', get_lang('ThisFieldIsRequired'), 'required');
6780

6881
$options = [
6982
'multiple_choice' => get_lang('MultipleAnswer'),
7083
];
71-
$form->addElement(
72-
'select',
73-
'question_type',
74-
get_lang('QuestionType'),
75-
$options
76-
);
84+
$form->addElement('select', 'question_type', get_lang('QuestionType'), $options);
85+
86+
if (!$hasSingleApi) {
87+
$form->addElement(
88+
'select',
89+
'ai_provider',
90+
get_lang('AIProvider'),
91+
array_combine(array_keys($availableApis), array_keys($availableApis))
92+
);
93+
}
7794

7895
$generateUrl = api_get_path(WEB_PLUGIN_PATH).'ai_helper/tool/answers.php';
7996
$language = api_get_interface_language();
@@ -87,10 +104,9 @@ function generateAikenForm()
87104
var btnGenerate = $(this);
88105
var quizName = $("[name=\'quiz_name\']").val();
89106
var nroQ = parseInt($("[name=\'nro_questions\']").val());
90-
var qType = $("[name=\'question_type\']").val();
91-
var valid = (quizName != \'\' && nroQ > 0);
92-
var qWeight = 1;
93-
107+
var qType = $("[name=\'question_type\']").val();'
108+
. (!$hasSingleApi ? 'var provider = $("[name=\'ai_provider\']").val();' : 'var provider = "' . $configuredApi . '";') .
109+
'var valid = (quizName != \'\' && nroQ > 0);
94110
if (valid) {
95111
btnGenerate.attr("disabled", true);
96112
btnGenerate.text("'.get_lang('PleaseWaitThisCouldTakeAWhile').'");
@@ -100,7 +116,8 @@ function generateAikenForm()
100116
"quiz_name": quizName,
101117
"nro_questions": nroQ,
102118
"question_type": qType,
103-
"language": "'.$language.'"
119+
"language": "'.$language.'",
120+
"ai_provider": provider
104121
}).done(function (data) {
105122
btnGenerate.attr("disabled", false);
106123
btnGenerate.text("'.get_lang('Generate').'");

main/lang/dutch/trad4all.inc.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5145,7 +5145,7 @@
51455145
$LinksContent = "<p>De linkmodule laat u toe een verzameling cursusmateriaal aan te leggen voor de studenten, vooral materiaal dat u niet zelf hebt aangemaakt.</p><p>Wanneer de lijst aangroeit, kan het relevant zijn om ze te organiseren in categorieën. U kan iedere link wijzigen om hem toe te kennen aan een categorie (u moet wel eerst een categorie aanmaken).</p><p>Het tekstvak 'Omschrijving' kan gebruikt worden om informatie te geven over het doel van websites maar ook om mee te geven wat de student met de link moet doen. Als, bijvoorbeeld, u verwijst naar een website op Aristoteles, kan u de student vragen om het verschil tussen synthese en analyse te bestuderen.</p>";
51465146
$MycoursesContent = "<p>Eenmaal ingelogd bent u op uw <em>persoonlijke startpagina</em>.</p><p>In het hoofdgedeelte (centrum) ziet u \"<b>Mijn cursussen</b>\", een lijst met al uw cursussen. Afhankelijk van uw gebruikersrechten kunt u ook de mogelijkheid hebben om nieuwe cursussen aan te maken (via het menu aan de rechterkant van de pagina).</p><p>Bovenaan ziet u<ul>\t<li>\"<b>Mijn profiel</b>\": hier kunt u verschillende zaken (naam, voornaam, e-mailadres…) wijzigen. U kunt ook de statistieken van uw platformgebruik opvragen.</li>\t<li>\"<b>Mijn agenda</b>\": dit bevat de agenda-items van al uw cursussen.</li></ul></p><p><b>Wijzig mijn cursuslijst</b>, in het menu aan de rechterkant, laat u toe in te schrijven voor nieuwe cursussen. Deze link laat u ook uitschrijven uit cursussen.</p><p>De links <b>Ondersteuningsforum</b> en <b>Documentatie</b> verwijzen naar de Chamilowebsite, waar u terecht kunt voor technische informatie of pedagogisch advies.</p><p>Om naar een cursus te gaan, klikt u op de naam. Uw status als cursusgebruiker kan variëren van de ene cursus tot de andere. Het is mogelijk dat u cursusbeheerder (lesgever) bent in een cursus, en student (leerling) in een andere.</p>";
51475147
$AgendaContent = "<p>De agenda verschijnt niet alleen in elke cursus zelf, maar ook als een overzichtsagenda voor de student ('Mijn agenda' in de menubalk bovenaan).</p><p>Binnen de cursus ziet de agenda eruit als een lijst met evenementen. U kan documenten of activiteiten met een agenda-item verbinden, zodat de agenda een chronologisch programma wordt voor uw leeractiviteiten.</p><p>Nieuwe agenda-items staan niet alleen in de agenda zelf, maar de student krijgt ook een aanduiding ervan wanneer hij/zij opnieuw inlogt. Het systeem geeft nieuwe items (sedert vorig bezoek) in de agenda (en de aankondigingen) aan: op de openingspagina ziet de student een icoontje naast alle cursussen waaraan een agenda-item of aankondiging is toegevoegd.</p><p>Wilt u werkelijk een chronologische structuur aanbrengen in de leeractiviteiten, dan kan u beter het leerpad gebruiken: dat gebruikt gelijkaardige principes, maar met meer geavanceerde mogelijkheden. Het leerpad kan beschouwd worden als een synthese van een inhoudstafel + een agenda + sequentie (opgelegde volgorde) + tracking.</p>";
5148-
$AnnouncementsContent = "<p>Met aankondigingen kan je een e-mailbericht sturen naar alle ingeschreven studenten, naar sommige ervan, of naar een of meer groepen. Zo kan je studenten die niet geregeld de cursuspagina's bezoeken daartoe aansporen.</p><p>Kies 'Aankondiging toevoegen' en selecteer groepen/gebruikers. Gebruik <span style=\"border: 1px solid; border-color: inherit;\"> Ctrl </span>+klik om er meerdere te kiezen, \">>\" om ze aan de bestemmelingen toe te voegen. Vink het hokje aan, vul onderwerp en bericht in en klik OK.</p>";
5148+
$AnnouncementsContent = "<p>Met aankondigingen kan je een e-mailbericht sturen naar alle ingeschreven studenten, naar sommige ervan, of naar een of meer groepen. Zo kan je studenten die niet geregeld de cursuspagina's bezoeken daartoe aansporen.</p><p>Kies 'Aankondiging toevoegen' en selecteer groepen/gebruikers. Gebruik <span style=\"border: 1px solid; border-color: inherit;\"> Ctrl </span>+klik om er meerdere te kiezen, '>>' om ze aan de bestemmelingen toe te voegen. Vink het hokje aan, vul onderwerp en bericht in en klik OK.</p>";
51495149
$ChatContent = "<p>In deze chatbox kunt u live met uw studenten discussiëren.</p><p>Deze chatfunctie werkt anders dan <acronym title=\"instant messaging\" xml:lang=\"en\" lang=\"en\">IM</acronym>-programma's (zoals MSN® of Yahoo Messenger®) omdat deze chat webgebaseerd is. Het nadeel daarvan is dat het bijwerken (refresh) slechts om de 10 seconden gebeurt, en niet onmiddellijk. Maar de voordelen zijn dat de chat geïntegreerd is in uw cursus, dat uw discussies worden opgeslagen in een map in de documentenmodule, en dat uw studenten geen extra plug-in hoeven te downloaden en te installeren.</p><p>Indien een gebruiker zijn/haar fotootje heeft toegevoegd bij 'Mijn profiel' (menubalk bovenaan), dan zal deze foto in de chatconversatie verschijnen, zodat hij/zij herkenbaar wordt.</p><p>Alleen de cursusbeheerder kan de discussie verwijderen wanneer hij/zij dit verkiest.</p><b>Pedagogische relevantie</b><p>Een chatfunctie in uw cursus heeft niet altijd een toegevoegde waarde, maar indien de chat in uw scenario past, kan de functie nuttig zijn. De docent kan de chatfunctie bijvoorbeeld verbergen, en alleen zichtbaar maken op bepaalde afgesproken tijdstippen, wanneer hij/zij live op vragen en opmerkingen van studenten wenst in te gaan. In een dergelijk scenario is de chat geen 'vrij discussiepaneel', terwijl studenten toch hun voordeel kunnen doen bij een liveontmoeting met de docent.</p>";
51505150
$WorkContent = "<p>Hier kunnen studenten documenten plaatsen. Via deze pagina is het mogelijk documenten uit te wisselen tussen studenten, studentengroepen en lesgevers. Als u via de groepsruimte een document publiceert (optie = publiceren), zal een verwijzing aangemaakt worden naar uw document, zonder dit te verplaatsen.</p><p>U kan kiezen of door de studenten geplaatste documenten standaard zichtbaar of onzichtbaar zijn.</p><p>Deze module heeft een <em>Introductietekst</em>gebied waarin u een vraag, richtlijnen, deadlines of andere zaken kan noteren.</p>";
51515151
$TrackingContent = "Statistieken helpen u om uw studenten op te volgen: hebben ze ingelogd op het systeem, wanneer en hoe vaak deden ze dat? Hebben ze hun scriptie al geüpload? Wanneer? Als u <acronym title=\"Sharable Content Object Reference Model\" xml:lang=\"en\" lang=\"en\">SCORM</acronym>-cursussen gebruikt, kan u zelfs nagaan hoeveel tijd een student gespendeerd heeft aan een module of hoofdstuk. De statistieken leveren informatie op twee niveaus:<ul>\t<li><b>Globaal</b>: Hoeveel studenten bezochten de cursus? Wat zijn de meest bezochte pagina's en links?</li>\t<li><b>Nominatief</b>: Welke pagina heeft Jan Janssens bezocht? Welke score behaalde hij op zijn tests? Wanneer heeft hij laatst ingelogd op het systeem?</li></ul>";
@@ -6910,4 +6910,4 @@
69106910
$AddEmailPictureComment = "De foto moet een minimale verhouding hebben van 25/7, u kunt de foto die u uploadt bijsnijden.";
69116911
$DeleteEmailPicture = "Verwijder site & e-mail banner";
69126912
$AddPictureComment = "De afbeelding moet een verhouding van 16/9 hebben, u kunt de afbeelding die u uploadt bijsnijden.";
6913-
?>
6913+
?>

main/lang/english/trad4all.inc.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9078,4 +9078,6 @@
90789078
$KeepGoing = "Keep going";
90799079
$SessionIsClosing = "Your session is closing";
90809080
$CannotChangeVisibilityOfBaseCourseResourceX = "The visibility of %s from the base course cannot be changed from the session.";
9081+
$UsingAIProviderX = "Using AI provider %s";
9082+
$AIProvider = "AI provider";
90819083
?>

main/lang/french/trad4all.inc.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9013,4 +9013,6 @@
90139013
$KeepGoing = "Rester connecté";
90149014
$SessionIsClosing = "Votre session est en cours de fermeture";
90159015
$CannotChangeVisibilityOfBaseCourseResourceX = "La visibilité de %s du cours de base ne peut être changée depuis une session.";
9016+
$UsingAIProviderX = "Utilisation du fournisseur d'IA %s";
9017+
$AIProvider = "Fournisseur d'IA";
90169018
?>

main/lang/spanish/trad4all.inc.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9103,4 +9103,6 @@
91039103
$KeepGoing = "Seguir conectado";
91049104
$SessionIsClosing = "Su sesión se está cerrando";
91059105
$CannotChangeVisibilityOfBaseCourseResourceX = "La visibilidad de %s del curso base no puede ser cambiada desde una sesión.";
9106+
$UsingAIProviderX = "Usando el proveedor de IA %s";
9107+
$AIProvider = "Proveedor de IA";
91069108
?>

main/lp/LpAiHelper.php

Lines changed: 55 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,25 @@ public function __construct()
1919
*/
2020
public function aiHelperForm()
2121
{
22+
$plugin = AiHelperPlugin::create();
23+
$availableApis = $plugin->getApiList();
24+
$configuredApi = $plugin->get('api_name');
25+
$hasSingleApi = count($availableApis) === 1 || isset($availableApis[$configuredApi]);
26+
2227
$form = new FormValidator(
2328
'lp_ai_generate',
2429
'post',
2530
api_get_self()."?".api_get_cidreq(),
2631
null
2732
);
2833
$form->addElement('header', get_lang('LpAiGenerator'));
34+
35+
if ($hasSingleApi) {
36+
$apiName = $availableApis[$configuredApi] ?? $configuredApi;
37+
$form->addHtml('<div style="margin-bottom: 10px; font-size: 14px; color: #555;">'
38+
.sprintf(get_lang('UsingAIProviderX'), '<strong>'.htmlspecialchars($apiName).'</strong>').'</div>');
39+
}
40+
2941
$form->addElement('text', 'lp_name', [get_lang('LpAiTopic'), get_lang('LpAiTopicHelp')]);
3042
$form->addRule('lp_name', get_lang('ThisFieldIsRequired'), 'required');
3143
$form->addElement('number', 'nro_items', [get_lang('LpAiNumberOfItems'), get_lang('LpAiNumberOfItemsHelper')]);
@@ -46,75 +58,55 @@ public function aiHelperForm()
4658
$sessionId = api_get_session_id();
4759
$redirectSuccess = api_get_path(WEB_CODE_PATH).'lp/lp_controller.php?'.api_get_cidreq().'&action=add_item&type=step&isStudentView=false&lp_id=';
4860
$form->addHtml('<script>
49-
$(function () {
50-
$("#lp-quiz-area").hide();
51-
$("#add-lp-quiz").change(function() {
52-
if ($(this).is(":checked")) {
53-
$("#lp-quiz-area").show();
54-
} else {
55-
$("#lp-quiz-area").hide();
56-
}
57-
});
61+
$(function () {
62+
$("#lp-quiz-area").hide();
63+
$("#add-lp-quiz").change(function() {
64+
$("#lp-quiz-area").toggle(this.checked);
65+
});
5866
59-
$("#create-lp-ai").on("click", function (e) {
60-
e.preventDefault();
61-
e.stopPropagation();
67+
$("#create-lp-ai").on("click", function (e) {
68+
e.preventDefault();
69+
e.stopPropagation();
6270
63-
var btnGenerate = $(this);
64-
var lpName = $("[name=\'lp_name\']").val();
65-
var nroItems = parseInt($("[name=\'nro_items\']").val());
66-
var wordsCount = parseInt($("[name=\'words_count\']").val());
67-
var valid = (lpName != \'\' && nroItems > 0 && wordsCount > 0);
68-
var addTests = $("#add-lp-quiz").is(":checked");
69-
var nroQuestions = parseInt($("[name=\'nro_questions\']").val());
71+
var btnGenerate = $(this);
72+
var lpName = $("[name=\'lp_name\']").val();
73+
var nroItems = parseInt($("[name=\'nro_items\']").val());
74+
var wordsCount = parseInt($("[name=\'words_count\']").val());
75+
var addTests = $("#add-lp-quiz").is(":checked");
76+
var nroQuestions = parseInt($("[name=\'nro_questions\']").val());
77+
var provider = "' . $configuredApi . '";
7078
71-
if (valid) {
72-
if (addTests) {
73-
var quizValid = (nroQuestions > 0 && nroQuestions <= 5);
74-
if (!quizValid) {
75-
alert("'.sprintf(get_lang('NumberOfQuestionsLimitedFromXToY'), 1, 5).'");
76-
return false;
77-
}
78-
}
79-
btnGenerate.attr("disabled", true);
80-
btnGenerate.text("'.get_lang('PleaseWaitThisCouldTakeAWhile').'");
81-
$.getJSON("'.$generateUrl.'", {
82-
"lp_name": lpName,
83-
"nro_items": nroItems,
84-
"words_count": wordsCount,
85-
"language": "'.$language.'",
86-
"course_code": "'.$courseCode.'",
87-
"session_id": "'.$sessionId.'",
88-
"add_tests": addTests,
89-
"nro_questions": nroQuestions
90-
}).done(function (data) {
91-
btnGenerate.attr("disabled", false);
92-
btnGenerate.text("'.get_lang('Generate').'");
93-
if (data.success && data.success == true) {
79+
if (lpName && nroItems > 0 && wordsCount > 0) {
80+
if (addTests && (nroQuestions <= 0 || nroQuestions > 5)) {
81+
alert("'.sprintf(get_lang('NumberOfQuestionsLimitedFromXToY'), 1, 5).'");
82+
return false;
83+
}
84+
85+
btnGenerate.attr("disabled", true).text("'.get_lang('PleaseWaitThisCouldTakeAWhile').'");
86+
$.getJSON("'.$generateUrl.'", {
87+
"lp_name": lpName,
88+
"nro_items": nroItems,
89+
"words_count": wordsCount,
90+
"language": "'.$language.'",
91+
"course_code": "'.$courseCode.'",
92+
"session_id": "'.$sessionId.'",
93+
"add_tests": addTests,
94+
"nro_questions": nroQuestions,
95+
"ai_provider": provider
96+
}).done(function (data) {
97+
btnGenerate.attr("disabled", false).text("'.get_lang('Generate').'");
98+
if (data.success) {
9499
location.href = "'.$redirectSuccess.'" + data.lp_id;
95-
} else {
96-
var errorMessage = "'.get_lang('NoSearchResults').'. '.get_lang('PleaseTryAgain').'";
97-
if (data.text) {
98-
errorMessage = data.text;
99-
}
100-
alert(errorMessage);
101-
}
102-
});
103-
}
100+
} else {
101+
alert(data.text || "'.get_lang('NoSearchResults').'. '.get_lang('PleaseTryAgain').'");
102+
}
104103
});
105-
});
106-
</script>');
107-
108-
$form->addButton(
109-
'create_lp_button',
110-
get_lang('LearnpathAddLearnpath'),
111-
'',
112-
'default',
113-
'default',
114-
null,
115-
['id' => 'create-lp-ai']
116-
);
104+
}
105+
});
106+
});
107+
</script>');
117108

109+
$form->addButton('create_lp_button', get_lang('LearnpathAddLearnpath'), '', 'default', 'default', null, ['id' => 'create-lp-ai']);
118110
echo $form->returnForm();
119111
}
120112
}

0 commit comments

Comments
 (0)