Merge branch 'release' into stable
commit
6fea91b7cf
|
@ -161,7 +161,9 @@ H5P.QuestionSet = function (options, contentId, contentData) {
|
||||||
var randomizeQuestionOrdering = function (questions) {
|
var randomizeQuestionOrdering = function (questions) {
|
||||||
|
|
||||||
// Save the original order of the questions in a multidimensional array [[question0,0],[question1,1]...
|
// Save the original order of the questions in a multidimensional array [[question0,0],[question1,1]...
|
||||||
var questionOrdering = questions.map(function (questionInstance, index) { return [questionInstance, index]; });
|
var questionOrdering = questions.map(function (questionInstance, index) {
|
||||||
|
return [questionInstance, index];
|
||||||
|
});
|
||||||
|
|
||||||
// Shuffle the multidimensional array
|
// Shuffle the multidimensional array
|
||||||
questionOrdering = H5P.shuffleArray(questionOrdering);
|
questionOrdering = H5P.shuffleArray(questionOrdering);
|
||||||
|
@ -463,7 +465,7 @@ H5P.QuestionSet = function (options, contentId, contentData) {
|
||||||
questionInstances[i].showSolutions();
|
questionInstances[i].showSolutions();
|
||||||
questionInstances[i].toggleReadSpeaker(false);
|
questionInstances[i].toggleReadSpeaker(false);
|
||||||
}
|
}
|
||||||
catch(error) {
|
catch (error) {
|
||||||
H5P.error("subcontent does not contain a valid showSolutions function");
|
H5P.error("subcontent does not contain a valid showSolutions function");
|
||||||
H5P.error(error);
|
H5P.error(error);
|
||||||
}
|
}
|
||||||
|
@ -515,7 +517,7 @@ H5P.QuestionSet = function (options, contentId, contentData) {
|
||||||
questionInstances[i].hideButton('prev');
|
questionInstances[i].hideButton('prev');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch(error) {
|
catch (error) {
|
||||||
H5P.error("subcontent does not contain a valid resetTask function");
|
H5P.error("subcontent does not contain a valid resetTask function");
|
||||||
H5P.error(error);
|
H5P.error(error);
|
||||||
}
|
}
|
||||||
|
@ -553,7 +555,8 @@ H5P.QuestionSet = function (options, contentId, contentData) {
|
||||||
// Update buttons
|
// Update buttons
|
||||||
initializeQuestion();
|
initializeQuestion();
|
||||||
|
|
||||||
} else if (params.randomQuestions) {
|
}
|
||||||
|
else if (params.randomQuestions) {
|
||||||
randomizeQuestions();
|
randomizeQuestions();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1084,7 +1087,8 @@ H5P.QuestionSet = function (options, contentId, contentData) {
|
||||||
var questionCopyrights;
|
var questionCopyrights;
|
||||||
for (var i = 0; i < questionInstances.length; i++) {
|
for (var i = 0; i < questionInstances.length; i++) {
|
||||||
var instance = questionInstances[i];
|
var instance = questionInstances[i];
|
||||||
var qParams = params.questions[i].params;
|
var instanceParams = params.questions[i].params;
|
||||||
|
|
||||||
questionCopyrights = undefined;
|
questionCopyrights = undefined;
|
||||||
|
|
||||||
if (instance.getCopyrights !== undefined) {
|
if (instance.getCopyrights !== undefined) {
|
||||||
|
@ -1094,13 +1098,16 @@ H5P.QuestionSet = function (options, contentId, contentData) {
|
||||||
if (questionCopyrights === undefined) {
|
if (questionCopyrights === undefined) {
|
||||||
// Create a generic flat copyright list
|
// Create a generic flat copyright list
|
||||||
questionCopyrights = new H5P.ContentCopyrights();
|
questionCopyrights = new H5P.ContentCopyrights();
|
||||||
H5P.findCopyrights(questionCopyrights, qParams, contentId);
|
H5P.findCopyrights(questionCopyrights, instanceParams.params, contentId,{
|
||||||
|
metadata: instanceParams.metadata,
|
||||||
|
machineName: instanceParams.library.split(' ')[0]
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine label
|
// Determine label
|
||||||
var label = (params.texts.questionLabel + ' ' + (i + 1));
|
var label = (params.texts.questionLabel + ' ' + (i + 1));
|
||||||
if (qParams.contentName !== undefined) {
|
if (instanceParams.params.contentName !== undefined) {
|
||||||
label += ': ' + qParams.contentName;
|
label += ': ' + instanceParams.params.contentName;
|
||||||
}
|
}
|
||||||
else if (instance.getTitle !== undefined) {
|
else if (instance.getTitle !== undefined) {
|
||||||
label += ': ' + instance.getTitle();
|
label += ': ' + instance.getTitle();
|
||||||
|
|
210
language/pt.json
210
language/pt.json
|
@ -1,165 +1,165 @@
|
||||||
{
|
{
|
||||||
"semantics": [
|
"semantics": [
|
||||||
{
|
{
|
||||||
"label": "Quiz introduction",
|
"label": "Introdução ao questionário",
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"label": "Display introduction"
|
"label": "Mostrar introdução"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "Title",
|
"label": "Título",
|
||||||
"description": "This title will be displayed above the introduction text."
|
"description": "Este título vai ser mostrado acima do texto introdutório."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "Introduction text",
|
"label": "Texto introdutório",
|
||||||
"description": "This text will be displayed before the quiz starts."
|
"description": "Este texto vai ser mostrado antes do início do questionário."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "Start button text",
|
"label": "Texto de iníco do questionário",
|
||||||
"default": "Start Quiz"
|
"default": "Iniciar questionário"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "Background image",
|
"label": "Imagem de fundo",
|
||||||
"description": "An optional background image for the introduction."
|
"description": "Uma imagem de fundo opcional para a introdução."
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "Background image",
|
"label": "Imagem de fundo",
|
||||||
"description": "An optional background image for the Question set."
|
"description": "Uma imagem de fundo opcional para a Série de questões."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "Progress indicator",
|
"label": "Indicador de progresso",
|
||||||
"description": "Question set progress indicator style.",
|
"description": "Estilo do indicador da série de questões.",
|
||||||
"options": [
|
"options": [
|
||||||
{
|
{
|
||||||
"label": "Textual"
|
"label": "Textual"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "Dots"
|
"label": "Pontos"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "Pass percentage",
|
"label": "Percentagem de aprovação",
|
||||||
"description": "Percentage of Total score required for passing the quiz."
|
"description": "Percentagem necessária para aprovação no questionário."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "Questions",
|
"label": "Questões",
|
||||||
"widgets": [
|
"widgets": [
|
||||||
{
|
{
|
||||||
"label": "Default"
|
"label": "Por defeito"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "Textual"
|
"label": "Textual"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"entity": "question",
|
"entity": "questão",
|
||||||
"field": {
|
"field": {
|
||||||
"label": "Question type",
|
"label": "Tipo de questão",
|
||||||
"description": "Library for this question."
|
"description": "Biblioteca para esta questão."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "Interface texts in quiz",
|
"label": "Textos do interface para o questionário",
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"label": "Back button",
|
"label": "Botão para questão anterior",
|
||||||
"default": "Previous question"
|
"default": "Questão anterior"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "Next button",
|
"label": "Botão para questão seguinte",
|
||||||
"default": "Next question"
|
"default": "Questão seguinte"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "Finish button",
|
"label": "Botão para terminar",
|
||||||
"default": "Finish"
|
"default": "Terminar"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "Progress text",
|
"label": "Texto do progresso",
|
||||||
"description": "Text used if textual progress is selected.",
|
"description": "Texto a utilizar se o progresso textual estiver ativo.",
|
||||||
"default": "Question: @current of @total questions"
|
"default": "Questão: @current de @total questões"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "Label for jumping to a certain question",
|
"label": "Etiqueta para saltar para um questão",
|
||||||
"description": "You must use the placeholder '%d' instead of the question number, and %total instead of total amount of questions.",
|
"description": "Tem de utilizar o espaço reservado (placeholder) '%d' em vez de o número da questão, e %total em vez do total de questões.",
|
||||||
"default": "Question %d of %total"
|
"default": "Questão %d de %total"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "Copyright dialog question label",
|
"label": "Etiqueta da caixa de diálogo para direitos de autor",
|
||||||
"default": "Question"
|
"default": "Questão"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "Readspeaker progress",
|
"label": "Progresso em texto para voz",
|
||||||
"description": "May use @current and @total question variables",
|
"description": "Pode utilizar @current e @total como variáveis da questão",
|
||||||
"default": "Question @current of @total"
|
"default": "Questão @current de @total"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "Unanswered question text",
|
"label": "Texto para questões não respondidas",
|
||||||
"default": "Unanswered"
|
"default": "Não respondida"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "Answered question text",
|
"label": "Texto para questões respondidas",
|
||||||
"default": "Answered"
|
"default": "Respondida"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "Current question text",
|
"label": "Texto para pergunta atual",
|
||||||
"default": "Current question"
|
"default": "Pergunta atual"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "Disable backwards navigation",
|
"label": "Desativar a opção de navegar para trás",
|
||||||
"description": "This option will only allow you to move forward in Question Set"
|
"description": "Esta opção só lhe permitirá navegar para a frente numa Série de questões"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "Randomize questions",
|
"label": "Tornar aleatório",
|
||||||
"description": "Enable to randomize the order of questions on display."
|
"description": "Ative para tornar aletória a ordem das questões."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "Number of questions to be shown:",
|
"label": "Número de questões a mostrar:",
|
||||||
"description": "Create a randomized batch of questions from the total."
|
"description": "Criar um grupo de questões aleatório de entre o total"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "Quiz finished",
|
"label": "Questionário terminado",
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"label": "Display results"
|
"label": "Mostrar resultados"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "Display solution button"
|
"label": "Mostrar botão de solução"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "No results message",
|
"label": "Mensagem quando não existem resultados",
|
||||||
"description": "Text displayed on end page when \"Display results\" is disabled",
|
"description": "Textos a exibir no final da página quando \"Mostrar resultados\" está desabilitado",
|
||||||
"default": "Finished"
|
"default": "Terminado"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "Feedback heading",
|
"label": "Cabeçalho do Feedback",
|
||||||
"default": "Your result:",
|
"default": "O seu resultado:",
|
||||||
"description": "This heading will be displayed at the end of the quiz when the user has answered all questions."
|
"description": "Este cabeçalho será mostrado no final questionário assim que o utilizador tiver respondido a todas as questões."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "Overall Feedback",
|
"label": "Feedback Geral",
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"widgets": [
|
"widgets": [
|
||||||
{
|
{
|
||||||
"label": "Default"
|
"label": "Por defeito"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"label": "Define custom feedback for any score range",
|
"label": "Defina feedback personalizado para cada intervalo de pontuação",
|
||||||
"description": "Example: 0-20% Bad score, 21-91% Average Score, 91-100% Great Score!",
|
"description": "Exemplo: 0-20% Mau, 21-91% Mediano, 91-100% Excelente!",
|
||||||
"entity": "range",
|
"entity": "intervalo",
|
||||||
"field": {
|
"field": {
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"label": "Score Range"
|
"label": "Intervalo de pontuação"
|
||||||
},
|
},
|
||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
"label": "Feedback for defined score range",
|
"label": "Feedback para o intervalo definido",
|
||||||
"placeholder": "Fill in the feedback"
|
"placeholder": "Preencha com o feedback"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -167,88 +167,88 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "Old Feedback",
|
"label": "Feedback antigo",
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"label": "Quiz passed greeting",
|
"label": "Saudação por avaliação positiva",
|
||||||
"description": "This text will be displayed above the score if the user has successfully passed the quiz."
|
"description": "Este texto vai ser mostrado acima do resultado obtido se o utilizador obtiver aproveitamento positivo no questionário."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "Passed comment",
|
"label": "Comentário para availiação positiva",
|
||||||
"description": "This comment will be displayed after the score if the user has successfully passed the quiz."
|
"description": "Este comentário vai ser mostrado depois do resultado se o utilizador obtiver aproveitamento positivo no questionário."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "Quiz failed title",
|
"label": "Título para avaliação negativa",
|
||||||
"description": "This text will be displayed above the score if the user has failed the quiz."
|
"description": "Este texto será mostrado acima do resultado obtido se o utilizador obtiver aproveitamento negativo no questionário."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "Failed comment",
|
"label": "Comentário para availiação negativa",
|
||||||
"description": "This comment will be displayed after the score if the user has failed the quiz."
|
"description": "Este comentário será mostrado depois do resultado se o utilizador obtiver aproveitamento negativo no questionário."
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "Solution button label",
|
"label": "Etiqueta do botão de soluções",
|
||||||
"default": "Show solution",
|
"default": "Mostrar soluções",
|
||||||
"description": "Text for the solution button."
|
"description": "Texto para o botão de soluções."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "Retry button label",
|
"label": "Etiqueta do botão de repetir",
|
||||||
"default": "Retry",
|
"default": "Repetir",
|
||||||
"description": "Text for the retry button."
|
"description": "Texto para o botão de repetir."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "Finish button text",
|
"label": "Texto para o botão terminar",
|
||||||
"default": "Finish"
|
"default": "Terminar"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "Display video before quiz results"
|
"label": "Mostrar video antes dos resultados do questionário"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "Enable skip video button"
|
"label": "Ativar botão de saltar vídeo"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "Skip video button label",
|
"label": "Etiqueta de botão de saltar vídeo",
|
||||||
"default": "Skip video"
|
"default": "Saltar vídeo"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "Passed video",
|
"label": "Vídeo de sucesso",
|
||||||
"description": "This video will be played if the user successfully passed the quiz."
|
"description": "Este vídeo vai ser apresentado se o utilizador obtiver avaliação positiva no questionário."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "Fail video",
|
"label": "Vídeo de insucesso",
|
||||||
"description": "This video will be played if the user failes the quiz."
|
"description": "Este vídeo vai ser apresentado se o utilizador obtiver avaliação negativa no questionário."
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "Settings for \"Show solution\" and \"Retry\" buttons",
|
"label": "Definições para os botões de \"Mostrar solução\" e \"Repetir\"",
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"label": "Show \"Check\" buttons",
|
"label": "Mostrar botões de \"Verificar\"",
|
||||||
"description": "This option determines if the \"Check\" button will be shown for all questions."
|
"description": "Esta opção determina se o botão \"Verificar\" será mostrado para todas as questões."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "Override \"Show Solution\" button",
|
"label": "Sobrepor botão \"Mostrar solução\"",
|
||||||
"description": "This option determines if the \"Show Solution\" button will be shown for all questions, disabled for all or configured for each question individually.",
|
"description": "Esta opção determina se o botão \"Mostrar solução\" será mostrado para todas as questões, desativado para todas ou configurado individualmente para cada questão.",
|
||||||
"options": [
|
"options": [
|
||||||
{
|
{
|
||||||
"label": "Enabled"
|
"label": "Ativado"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "Disabled"
|
"label": "Desativado"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "Override \"Retry\" button",
|
"label": "Sobrepor botão \"Repetir\"",
|
||||||
"description": "This option determines if the \"Retry\" button will be shown for all questions, disabled for all or configured for each question individually.",
|
"description": "Esta opção determina se o botão \"Repetir\" será mostrado para todas as questões, desativado para todas ou configurado individualmente para cada questão.",
|
||||||
"options": [
|
"options": [
|
||||||
{
|
{
|
||||||
"label": "Enabled"
|
"label": "Ativado"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "Disabled"
|
"label": "Desativado"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
"description": "Put together a set of different questions that has to be solved. (Quiz)",
|
"description": "Put together a set of different questions that has to be solved. (Quiz)",
|
||||||
"contentType": "question",
|
"contentType": "question",
|
||||||
"majorVersion": 1,
|
"majorVersion": 1,
|
||||||
"minorVersion": 15,
|
"minorVersion": 16,
|
||||||
"patchVersion": 3,
|
"patchVersion": 2,
|
||||||
"embedTypes": [
|
"embedTypes": [
|
||||||
"iframe"
|
"iframe"
|
||||||
],
|
],
|
||||||
|
@ -14,7 +14,7 @@
|
||||||
"author": "Joubel",
|
"author": "Joubel",
|
||||||
"coreApi": {
|
"coreApi": {
|
||||||
"majorVersion": 1,
|
"majorVersion": 1,
|
||||||
"minorVersion": 14
|
"minorVersion": 19
|
||||||
},
|
},
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"preloadedJs": [
|
"preloadedJs": [
|
||||||
|
@ -41,7 +41,7 @@
|
||||||
{
|
{
|
||||||
"machineName": "H5P.Video",
|
"machineName": "H5P.Video",
|
||||||
"majorVersion": 1,
|
"majorVersion": 1,
|
||||||
"minorVersion": 4
|
"minorVersion": 5
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"machineName": "H5P.JoubelUI",
|
"machineName": "H5P.JoubelUI",
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
var H5PPresave = H5PPresave || {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolve the presave logic for the content type Question Set
|
||||||
|
*
|
||||||
|
* @param {object} content
|
||||||
|
* @param finished
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
|
H5PPresave['H5P.QuestionSet'] = function (content, finished) {
|
||||||
|
var presave = H5PEditor.Presave;
|
||||||
|
|
||||||
|
if (isContentInvalid()) {
|
||||||
|
throw new presave.exceptions.InvalidContentSemanticsException('Invalid Question Set Error');
|
||||||
|
}
|
||||||
|
|
||||||
|
var score = content.questions
|
||||||
|
.filter(function (action) {
|
||||||
|
return action.hasOwnProperty('library') && action.hasOwnProperty('params');
|
||||||
|
})
|
||||||
|
.map(function (action) {
|
||||||
|
return (new presave).process(action.library, action.params).maxScore;
|
||||||
|
})
|
||||||
|
.reduce(function (currentScore, scoreToAdd) {
|
||||||
|
if (presave.isInt(scoreToAdd)) {
|
||||||
|
currentScore += scoreToAdd;
|
||||||
|
}
|
||||||
|
return currentScore;
|
||||||
|
}, 0);
|
||||||
|
|
||||||
|
presave.validateScore(score);
|
||||||
|
|
||||||
|
finished({maxScore: score});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if required parameters is present
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
function isContentInvalid() {
|
||||||
|
return !presave.checkNestedRequirements(content, 'content.questions') || !Array.isArray(content.questions);
|
||||||
|
}
|
||||||
|
};
|
|
@ -121,12 +121,12 @@
|
||||||
"importance": "high",
|
"importance": "high",
|
||||||
"description": "Library for this question.",
|
"description": "Library for this question.",
|
||||||
"options": [
|
"options": [
|
||||||
"H5P.MultiChoice 1.12",
|
"H5P.MultiChoice 1.13",
|
||||||
"H5P.DragQuestion 1.12",
|
"H5P.DragQuestion 1.13",
|
||||||
"H5P.Blanks 1.10",
|
"H5P.Blanks 1.11",
|
||||||
"H5P.MarkTheWords 1.8",
|
"H5P.MarkTheWords 1.9",
|
||||||
"H5P.DragText 1.7",
|
"H5P.DragText 1.8",
|
||||||
"H5P.TrueFalse 1.4"
|
"H5P.TrueFalse 1.5"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue