/* * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; under version 2 * of the License (non-upgradable). * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * Copyright (c) 2016-2017 (original work) Open Assessment Technologies SA; * */ define([ 'jquery', 'i18n', 'lodash', 'helpers', 'ui/component', 'ui/hider', 'ui/switch/switch', 'ui/button', 'tpl!qtiItemPci/pciManager/tpl/layout', 'tpl!qtiItemPci/pciManager/tpl/listing', 'tpl!qtiItemPci/pciManager/tpl/packageMeta', 'async', 'ui/dialog/confirm', 'ui/dialog', 'ui/feedback', 'ui/modal', 'ui/uploader', 'ui/filesender' ], function ($, __, _, helpers, component, hider, switchFactory, buttonFactory, layoutTpl, listingTpl, packageMetaTpl, asyncLib, confirmBox, dialog, feedback) { 'use strict'; var _fileTypeFilters = ['application/zip', 'application/x-zip-compressed', 'application/x-zip'], _fileExtFilter = /.+\.(zip)$/; var _defaults = { loadUrl: null, disableUrl: null, enableUrl: null, verifyUrl: null, addUrl: null }; var pciManager = { open: function open() { this.trigger('showListing'); this.getElement().appendTo('.pci-manager'); } }; /** * Create a pci manager * * @param {Object} config * @param {String} config.loadUrl - the service be called to load the list of pcis * @param {String} config.verifyUrl - the service be called to verify a pci package * @param {String} config.addUrl - the service be called to add a pci * @param {String} config.enableUrl - the service be called to enable the pcis * @param {String} config.disableUrl - the service be called to disable the pcis * @returns {*} */ return function pciManagerFactory(config) { var listing = {}; /** * Create pci manager component * * @returns {Object} a pciManager component * @fires pciManager#loaded - when the pci manager is initially loaded * @fires pciManager#showListing - when the list of pci is displayed * @fires pciManager#hideListing - when the list of pci is hidden * @fires pciManager#updateListing - when the list of pci is updated * @fires pciManager#pciEnabled - when a pci is enabled * @fires pciManager#pciDisabled - when a pci is pci-disabled */ return component(pciManager, _defaults) .setTemplate(layoutTpl) .on('showListing', function () { var $fileSelector = this.getElement().find('.file-selector'), $title = $fileSelector.find('.title'), $uploader = $fileSelector.find('.file-upload-container'), $uploadForm = $uploader.parent('form'), $switcher = $fileSelector.find('.upload-switcher a'); hider.show($switcher.filter('.upload')); hider.hide($switcher.filter('.listing')); $uploadForm.hide(); hider.hide($uploader); $title.text(__('Manage custom interactions')); this.trigger('updateListing'); }) .on('hideListing', function () { var $fileSelector = this.getElement().find('.file-selector'), $fileContainer = $fileSelector.find('.files'), $placeholder = $fileSelector.find('.empty'), $title = $fileSelector.find('.title'), $uploader = $fileSelector.find('.file-upload-container'), $uploadForm = $uploader.parent('form'), $switcher = $fileSelector.find('.upload-switcher a'); hider.show($switcher.filter('.listing')); hider.hide($switcher.filter('.upload')); $switcher.filter('.listing').css({display: 'inline-block'}); $uploadForm.show(); hider.hide($fileContainer); hider.hide($placeholder); $title.text(__('Upload new custom interaction (zip package)')); $uploader.uploader('reset'); hider.show($uploader); }) .on('updateListing', function () { var self = this, urls = _.pick(this.config, ['disableUrl', 'enableUrl', 'unregisterUrl', 'exportPciUrl']), $fileSelector = this.getElement().find('.file-selector'), $fileContainer = $fileSelector.find('.files'), $placeholder = $fileSelector.find('.empty'); if (_.size(listing)) { hider.hide($placeholder); $fileContainer .empty() .html(listingTpl({ interactions: listing })); $fileContainer.find('.actions').each(function () { var pciDownloadButton = $(this).find('.pci-download-button'); var pciswitch = $(this).find('.pci-switch'); var pciUnregisterButton = $(this).find('.pci-unregister-button'); var $li = $(this).closest('li'); var typeIdentifier = $li.data('typeIdentifier'); var runtimeOnly = listing[typeIdentifier].runtimeOnly; if (!runtimeOnly) { switchFactory(pciswitch, { on: { active: !$li.hasClass('pci-disabled') }, off: { active: $li.hasClass('pci-disabled') } }) .on('on', function () { $li.removeClass('pci-disabled'); $.getJSON(urls.enableUrl, {typeIdentifier: typeIdentifier}, function (data) { if (data.success) { listing[typeIdentifier].enabled = true; self.trigger('pciEnabled', typeIdentifier); } }); }) .on('off', function () { $li.addClass('pci-disabled'); $.getJSON(urls.disableUrl, {typeIdentifier: typeIdentifier}, function (data) { if (data.success) { listing[typeIdentifier].enabled = false; self.trigger('pciDisabled', typeIdentifier); } }); }); } buttonFactory({ id: 'unregister', type: 'info', icon: 'bin', label: __('Delete'), class: 'unregister', renderTo: pciUnregisterButton }) .on('click', function confirmDialog() { dialog({ class: 'icon-warning', heading: __('Warning'), message: __('You are about to delete the Portable Custom Interaction %s from the system.', typeIdentifier), content: __('This action will affect all items that may be using it and cannot be undone. Please confirm your choice.'), autoRender: true, autoDestroy: true, buttons: [ { id: 'cancel', type: 'regular', label: __('Cancel'), close: true }, { id: 'delete', type: 'error', label: __('Delete'), close: true }], onDeleteBtn: function onDeleteBtn() { $.getJSON(urls.unregisterUrl, {typeIdentifier: typeIdentifier}, function (data) { if (data.success) { delete listing[typeIdentifier]; self.trigger('pciDisabled', typeIdentifier); } }); } }); }); if(!runtimeOnly) { buttonFactory({ id: 'exportPci', type: 'info', icon: 'import', label: __('Download'), renderTo: pciDownloadButton }) .on('click', function () { window.location = (urls.exportPciUrl + '?typeIdentifier=' + typeIdentifier); }) } }); hider.show($fileContainer); } else { hider.hide($fileContainer); hider.show($placeholder); } }) .on('pciEnabled', function () { this.trigger('updateListing'); }) .on('pciDisabled', function () { this.trigger('updateListing'); }) .on('render', function () { //init variables: var self = this, urls = _.pick(this.config, ['loadUrl', 'disableUrl', 'enableUrl', 'verifyUrl', 'addUrl']), $container = this.getElement(), $fileSelector = $container.find('.file-selector'), $uploader = $fileSelector.find('.file-upload-container'), $switcher = $fileSelector.find('.upload-switcher a'), $uploadForm; //init event listeners initEventListeners(); initUploader(); //load list of custom interactions from server $.getJSON(urls.loadUrl, function (data) { //note : init as empty object and not array otherwise _.size will fail later listing = _.size(data) ? data : {}; self.trigger('updateListing', data); self.trigger('loaded', data); }); function initEventListeners() { //switch to upload mode $switcher.on('click', function (e) { e.preventDefault(); if (hider.isHidden($uploader)) { self.trigger('hideListing'); } else { self.trigger('showListing'); } }); } function initUploader() { var errors = [], selectedFiles = {}; $uploader.on('upload.uploader', function (e, file, interactionHook) { listing[interactionHook.typeIdentifier] = interactionHook; self.trigger('pciAdded', interactionHook.typeIdentifier); }) .on('fail.uploader', function (e, file, err) { errors.push(__('Unable to upload file %s : %s', file.name, err)); }) .on('end.uploader', function () { if (errors.length === 0) { self.trigger('showListing'); } else { feedback().error("