444 lines
14 KiB
JavaScript
444 lines
14 KiB
JavaScript
/*
|
|
* Copyright (C) 2011 - present Instructure, Inc.
|
|
*
|
|
* This file is part of Canvas.
|
|
*
|
|
* Canvas is free software: you can redistribute it and/or modify it under
|
|
* the terms of the GNU Affero General Public License as published by the Free
|
|
* Software Foundation, version 3 of the License.
|
|
*
|
|
* Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
* A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
|
* details.
|
|
*
|
|
* You should have received a copy of the GNU Affero General Public License along
|
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
import I18n from 'i18n!question_bank'
|
|
import $ from 'jquery'
|
|
import find_outcome from './find_outcome'
|
|
import moveQuestionTemplate from 'jst/quiz/move_question'
|
|
import htmlEscape from './str/htmlEscape'
|
|
import moveMultipleQuestionBanks from 'jsx/quizzes/question_bank/moveMultipleQuestionBanks'
|
|
import loadBanks from 'jsx/quizzes/question_bank/loadBanks'
|
|
import addBank from 'jsx/quizzes/question_bank/addBank'
|
|
import './jquery.ajaxJSON'
|
|
import './jquery.instructure_forms' /* formSubmit, getFormData, formErrors */
|
|
import 'jqueryui/dialog'
|
|
import './jquery.instructure_misc_helpers' /* replaceTags */
|
|
import './jquery.instructure_misc_plugins' /* confirmDelete, showIf, .dim */
|
|
import './jquery.keycodes'
|
|
import './jquery.loadingImg'
|
|
import './jquery.templateData'
|
|
|
|
export function updateAlignments(alignments) {
|
|
$('.add_outcome_text')
|
|
.text(I18n.t('updating_outcomes', 'Updating Outcomes...'))
|
|
.attr('disabled', true)
|
|
const params = {}
|
|
for (const idx in alignments) {
|
|
const alignment = alignments[idx]
|
|
params['assessment_question_bank[alignments][' + alignment[0] + ']'] = alignment[1]
|
|
}
|
|
if (alignments.length == 0) {
|
|
params['assessment_question_bank[alignments]'] = ''
|
|
}
|
|
const url = $('.edit_bank_link:last').attr('href')
|
|
$.ajaxJSON(
|
|
url,
|
|
'PUT',
|
|
params,
|
|
data => {
|
|
const alignments = data.assessment_question_bank.learning_outcome_alignments.sort((a, b) => {
|
|
const a_name = (
|
|
(a.content_tag &&
|
|
a.content_tag.learning_outcome &&
|
|
a.content_tag.learning_outcome.short_description) ||
|
|
'none'
|
|
).toLowerCase()
|
|
const b_name = (
|
|
(b.content_tag &&
|
|
b.content_tag.learning_outcome &&
|
|
b.content_tag.learning_outcome.short_description) ||
|
|
'none'
|
|
).toLowerCase()
|
|
if (a_name < b_name) {
|
|
return -1
|
|
} else if (a_name > b_name) {
|
|
return 1
|
|
} else {
|
|
return 0
|
|
}
|
|
})
|
|
$('.add_outcome_text')
|
|
.text(I18n.t('align_outcomes', 'Align Outcomes'))
|
|
.attr('disabled', false)
|
|
const $outcomes = $('#aligned_outcomes_list')
|
|
$outcomes.find('.outcome:not(.blank)').remove()
|
|
const $template = $outcomes
|
|
.find('.blank:first')
|
|
.clone(true)
|
|
.removeClass('blank')
|
|
for (const idx in alignments) {
|
|
const alignment = alignments[idx].content_tag
|
|
const outcome = {
|
|
short_description: alignment.learning_outcome.short_description,
|
|
mastery_threshold: Math.round(alignment.mastery_score * 10000) / 100.0
|
|
}
|
|
const $outcome = $template.clone(true)
|
|
$outcome.attr('data-id', alignment.learning_outcome_id)
|
|
$outcome.fillTemplateData({
|
|
data: outcome
|
|
})
|
|
$outcomes.append($outcome.show())
|
|
}
|
|
},
|
|
data => {
|
|
$('.add_outcome_text')
|
|
.text(I18n.t('update_outcomes_fail', 'Updating Outcomes Failed'))
|
|
.attr('disabled', false)
|
|
}
|
|
)
|
|
}
|
|
|
|
export function attachPageEvents(e) {
|
|
$('#aligned_outcomes_list').delegate('.delete_outcome_link', 'click', function(event) {
|
|
event.preventDefault()
|
|
const result = confirm(
|
|
I18n.t(
|
|
'remove_outcome_from_bank',
|
|
'Are you sure you want to remove this outcome from the bank?'
|
|
)
|
|
),
|
|
$outcome = $(event.target).parents('.outcome'),
|
|
alignments = [],
|
|
outcome_id = $outcome.data('id')
|
|
|
|
if (result) {
|
|
$outcome.dim()
|
|
$('#aligned_outcomes_list .outcome:not(.blank)').each(function() {
|
|
const id = $(this).attr('data-id')
|
|
const pct =
|
|
$(this).getTemplateData({textValues: ['mastery_threshold']}).mastery_threshold / 100
|
|
if (id != outcome_id) {
|
|
alignments.push([id, pct])
|
|
}
|
|
})
|
|
updateAlignments(alignments)
|
|
}
|
|
})
|
|
|
|
if ($('#more_questions').length > 0) {
|
|
$('.display_question .move').remove()
|
|
const url = $.replaceTags($('#bank_urls .more_questions_url').attr('href'), 'page', 1)
|
|
$.ajaxJSON(
|
|
url,
|
|
'GET',
|
|
{},
|
|
data => {
|
|
for (const idx in data.questions) {
|
|
const question = data.questions[idx].assessment_question
|
|
const $teaser = $('#question_teaser_' + question.id)
|
|
$teaser.data('question', question)
|
|
}
|
|
},
|
|
data => {}
|
|
)
|
|
}
|
|
$('.more_questions_link').click(function(event) {
|
|
event.preventDefault()
|
|
if ($(this).hasClass('loading')) {
|
|
return
|
|
}
|
|
const $link = $(this)
|
|
const $more_questions = $('#more_questions')
|
|
const currentPage = parseInt($more_questions.attr('data-current-page'))
|
|
const totalPages = parseInt($more_questions.attr('data-total-pages'))
|
|
let url = $(this).attr('href')
|
|
url = $.replaceTags(url, 'page', currentPage + 1)
|
|
$link.text('loading more questions...').addClass('loading')
|
|
$.ajaxJSON(
|
|
url,
|
|
'GET',
|
|
{},
|
|
data => {
|
|
$link.text(I18n.t('links.more_questions', 'more questions')).removeClass('loading')
|
|
$more_questions.attr('data-current-page', currentPage + 1)
|
|
$more_questions.showIf(currentPage + 1 < totalPages)
|
|
for (const idx in data.questions) {
|
|
const question = data.questions[idx].assessment_question
|
|
question.assessment_question_id = question.id
|
|
const $question = $('#question_teaser_blank')
|
|
.clone()
|
|
.removeAttr('id')
|
|
$question.fillTemplateData({
|
|
data: question,
|
|
id: 'question_teaser_' + question.id,
|
|
hrefValues: ['id']
|
|
})
|
|
$question.fillTemplateData({
|
|
data: question.question_data,
|
|
htmlValues: ['question_text']
|
|
})
|
|
$question.data('question', question)
|
|
$question.find('.assessment_question_id').text(question.id)
|
|
$('#questions').append($question)
|
|
$question.show()
|
|
}
|
|
},
|
|
() => {
|
|
$link
|
|
.text(I18n.t('loading_more_fail', 'loading more questions fails, please try again'))
|
|
.removeClass('loading')
|
|
}
|
|
)
|
|
})
|
|
$('.delete_bank_link').click(function(event) {
|
|
event.preventDefault()
|
|
$(this)
|
|
.parents('.question_bank')
|
|
.confirmDelete({
|
|
url: $(this).attr('href'),
|
|
message: I18n.t(
|
|
'delete_are_you_sure',
|
|
'Are you sure you want to delete this bank of questions?'
|
|
),
|
|
success() {
|
|
location.href = $('.assessment_question_banks_url').attr('href')
|
|
}
|
|
})
|
|
})
|
|
$('.bookmark_bank_link').click(function(event) {
|
|
event.preventDefault()
|
|
const $link = $(this)
|
|
$link.find('.message').text(I18n.t('bookmarking', 'Bookmarking...'))
|
|
$.ajaxJSON(
|
|
$(this).attr('href'),
|
|
'POST',
|
|
{},
|
|
data => {
|
|
$link.find('.message').text(I18n.t('already_bookmarked', 'Already Bookmarked'))
|
|
$link.attr('disabled', true)
|
|
},
|
|
() => {
|
|
$link.find('.message').text(I18n.t('bookmark_failed', 'Bookmark Failed'))
|
|
}
|
|
)
|
|
})
|
|
$('.edit_bank_link').click(event => {
|
|
event.preventDefault()
|
|
const val = $('#edit_bank_form h2').text()
|
|
$('#edit_bank_form')
|
|
.find('.displaying')
|
|
.hide()
|
|
.end()
|
|
.find('.editing')
|
|
.show()
|
|
$('.bank_name_box')
|
|
.val(val || I18n.t('question_bank', 'Question Bank'))
|
|
.focus()
|
|
.select()
|
|
})
|
|
$('#edit_bank_form .bank_name_box').keycodes('return esc', function(event) {
|
|
if (event.keyString == 'esc') {
|
|
$(this).blur()
|
|
} else if (event.keyString == 'return') {
|
|
$('#edit_bank_form').submit()
|
|
}
|
|
})
|
|
$('#edit_bank_form .bank_name_box').blur(() => {
|
|
$('#edit_bank_form')
|
|
.find('.displaying')
|
|
.show()
|
|
.end()
|
|
.find('.editing')
|
|
.hide()
|
|
})
|
|
$('#edit_bank_form').formSubmit({
|
|
object_name: 'assessment_question_bank',
|
|
beforeSubmit(data) {
|
|
$('#edit_bank_form h2').text(data.title)
|
|
$(this).loadingImage()
|
|
},
|
|
success(data) {
|
|
$(this).loadingImage('remove')
|
|
const bank = data.assessment_question_bank
|
|
$('#edit_bank_form .bank_name_box').blur()
|
|
$('#edit_bank_form h2').text(bank.title)
|
|
},
|
|
error(data) {
|
|
$(this).loadingImage('remove')
|
|
$('.edit_bank_link').click()
|
|
$('#edit_bank_form').formErrors(data)
|
|
}
|
|
})
|
|
$('#show_question_details')
|
|
.change(function() {
|
|
$('#questions').toggleClass('brief', !$(this).attr('checked'))
|
|
})
|
|
.change()
|
|
|
|
moveMultipleQuestionBanks.addEvents()
|
|
|
|
$('#questions').delegate('.move_question_link', 'click', function(event) {
|
|
event.preventDefault()
|
|
const $dialog = $('#move_question_dialog')
|
|
$dialog
|
|
.find('.question_text')
|
|
.show()
|
|
.end()
|
|
.find('.questions')
|
|
.hide()
|
|
$dialog.find('.copy_option').show()
|
|
$dialog.find('.submit_button').text(I18n.t('title.move_copy_questions', 'Move/Copy Questions'))
|
|
$dialog.find('.multiple_questions').val('0')
|
|
if (!$dialog.hasClass('loaded')) {
|
|
loadBanks($dialog)
|
|
} else {
|
|
$dialog.find('li.message').hide()
|
|
}
|
|
const template = $(this)
|
|
.parents('.question_holder')
|
|
.getTemplateData({textValues: ['question_name', 'question_text']})
|
|
$dialog.fillTemplateData({
|
|
data: template
|
|
})
|
|
$dialog.data('question', $(this).parents('.question_holder'))
|
|
$dialog.dialog({
|
|
width: 600,
|
|
title: I18n.t('title.move_copy_questions', 'Move/Copy Questions')
|
|
})
|
|
$dialog
|
|
.parent()
|
|
.find('.ui-dialog-titlebar-close')
|
|
.focus()
|
|
})
|
|
$('#move_question_dialog .submit_button').click(function() {
|
|
const $dialog = $('#move_question_dialog')
|
|
const data = $dialog.getFormData()
|
|
const multiple_questions = data.multiple_questions == '1'
|
|
const move = data.copy != '1'
|
|
let submitText = null
|
|
if (move) {
|
|
submitText = I18n.t(
|
|
'buttons.submit_moving',
|
|
{one: 'Moving Question...', other: 'Moving Questions...'},
|
|
{count: multiple_questions ? 2 : 1}
|
|
)
|
|
} else {
|
|
submitText = I18n.t(
|
|
'buttons.submit_copying',
|
|
{one: 'Copying Question...', other: 'Copying Questions...'},
|
|
{count: multiple_questions ? 2 : 1}
|
|
)
|
|
}
|
|
$dialog.find('button').attr('disabled', true)
|
|
$dialog.find('.submit_button').text(submitText)
|
|
const url = $('#bank_urls .move_questions_url').attr('href')
|
|
data.move = move ? '1' : '0'
|
|
if (!multiple_questions) {
|
|
const id = $dialog
|
|
.data('question')
|
|
.find('.assessment_question_id')
|
|
.text()
|
|
data['questions[' + id + ']'] = '1'
|
|
}
|
|
const ids = []
|
|
$dialog.find('.list_question :checkbox:checked').each(function() {
|
|
ids.push($(this).val())
|
|
})
|
|
const save = function(data) {
|
|
$.ajaxJSON(
|
|
url,
|
|
'POST',
|
|
data,
|
|
data => {
|
|
$dialog.find('button').attr('disabled', false)
|
|
$dialog.find('.submit_button').text('Move/Copy Question')
|
|
if (move) {
|
|
if ($dialog.data('question')) {
|
|
$dialog.data('question').remove()
|
|
} else {
|
|
for (const idx in ids) {
|
|
const id = ids[idx]
|
|
$('#question_' + id)
|
|
.parent('.question_holder')
|
|
.remove()
|
|
$('#question_teaser_' + id).remove()
|
|
}
|
|
$dialog.find
|
|
}
|
|
}
|
|
$dialog.dialog('close')
|
|
},
|
|
data => {
|
|
$dialog.find('button').attr('disabled', false)
|
|
let failedText = null
|
|
if (move) {
|
|
failedText = I18n.t(
|
|
'buttons.submit_moving_failed',
|
|
{
|
|
one: 'Moving Question Failed, please try again',
|
|
other: 'Moving Questions Failed, please try again'
|
|
},
|
|
{count: multiple_questions ? 2 : 1}
|
|
)
|
|
} else {
|
|
failedText = I18n.t(
|
|
'buttons.submit_copying_failed',
|
|
{
|
|
one: 'Copying Question Failed, please try again',
|
|
other: 'Copying Questions Failed, please try again'
|
|
},
|
|
{count: multiple_questions ? 2 : 1}
|
|
)
|
|
}
|
|
$dialog.find('.submit_button').text(failedText)
|
|
}
|
|
)
|
|
}
|
|
if (data.assessment_question_bank_id == 'new') {
|
|
const create_url = $('#bank_urls .assessment_question_banks_url').attr('href')
|
|
$.ajaxJSON(
|
|
create_url,
|
|
'POST',
|
|
{'assessment_question_bank[title]': data.assessment_question_bank_name},
|
|
bank_data => {
|
|
addBank(bank_data.assessment_question_bank)
|
|
data.assessment_question_bank_id = bank_data.assessment_question_bank.id
|
|
$dialog.find('.new_question_bank_name').hide()
|
|
save(data)
|
|
},
|
|
data => {
|
|
$dialog.find('button').attr('disabled', false)
|
|
let submitAgainText = null
|
|
if (move) {
|
|
submitAgainText = I18n.t(
|
|
'buttons.submit_retry_moving',
|
|
'Moving Question Failed, please try again...'
|
|
)
|
|
} else {
|
|
submitAgainText = I18n.t(
|
|
'buttons.submit_retry_copying',
|
|
'Copying Question Failed, please try again...'
|
|
)
|
|
}
|
|
$dialog.find('.submit_button').text(submitAgainText)
|
|
}
|
|
)
|
|
} else {
|
|
save(data)
|
|
}
|
|
})
|
|
$('#move_question_dialog .cancel_button').click(() => {
|
|
$('#move_question_dialog').dialog('close')
|
|
})
|
|
$('#move_question_dialog :radio').change(function() {
|
|
$('#move_question_dialog .new_question_bank_name').showIf(
|
|
$(this).attr('checked') && $(this).val() == 'new'
|
|
)
|
|
})
|
|
}
|