tao-test/app/tao/views/js/layout/tree/provider/resourceSelector.js

216 lines
10 KiB
JavaScript

/**
* 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) 2014-2017 Open Assessment Technologies SA;
*/
/**
* Tree provider : resource-selector
*
* @author Bertrand Chevrier <bertrand@taotesting.com>
*/
define([
'lodash',
'i18n',
'core/promise',
'core/store',
'core/logger',
'layout/actions',
'layout/generisRouter',
'layout/permissions',
'provider/resources',
'ui/resource/selector'
], function(_, __, Promise, store, loggerFactory, actionManager, generisRouter, permissionsManager, resourceProviderFactory, resourceSelectorFactory){
'use strict';
var logger = loggerFactory('layout/tree/provider/resourceSelector');
var resourceProvider = resourceProviderFactory();
/**
* The resource-selector tree provider
*/
return {
/**
* Tree provider name
*/
name : 'resource-selector',
/**
* Init is the tree provider entry point
* @param {jQueryElement} $container - that will contain the tree
* @param {Object} [options] - additional configuration options
* @param {String} [options.id] - the tree identifier
* @param {String} [options.url] - the endpoint to load data
* @param {String} [options.rootClassUri] - the URI of the root class
* @param {Object} [options.actions] - which actions to perform from the tree
* @param {String} [options.loadNode] - the URI of the node to select by default
* @param {String} [options.sectionId] - the section the selector belongs to
* @returns {Promise} resolves when the tree is rendered
*/
init: function init($container, options){
return new Promise(function(resolve){
store('taotree').then(function(treeStore){
return Promise.all([
resourceProvider.getClasses(options.rootClassUri),
resourceProvider.getClassProperties(options.rootClassUri),
treeStore.getItem(options.id)
])
.then(function(results) {
var classes = results[0];
var filters = results[1];
var defaultNode = results[2];
var preloadNode = typeof options.loadNode !== 'undefined';
resourceSelectorFactory($container, {
icon : options.icon || 'test',
searchPlaceholder : __('Filter'),
selectionMode: 'both',
selectClass : true,
classUri: options.rootClassUri,
classes: classes,
filters: filters
})
.on('init', function(){
actionManager.exec(options.actions.init, {
uri: options.rootClassUri
});
})
.on('render', function() {
var self = this;
actionManager.on('removeNodes', function(actionContext, nodes){
//make the component in loading state
//to prevent handling intermediate changes
self.setState('loading', true);
_.forEach(nodes, self.removeNode, self);
self.changeSelectionMode('single');
self.setState('loading', false);
self.selectDefaultNode(defaultNode);
});
actionManager.on('removeNode', function(actionContext, node){
self.removeNode(node);
self.selectDefaultNode(defaultNode);
});
actionManager.on('subClass instanciate duplicateNode', function(actionContext, node){
self
.after('update.add', function() {
self.off('update.add');
self.select(node);
})
.changeSelectionMode('single')
.query({classUri: node.classUri});
});
actionManager.on('copyTo moveTo', function(actionContext, node){
self.refresh(node || defaultNode);
});
actionManager.on('refresh', function(node){
self.refresh(node || defaultNode);
});
generisRouter.on('urichange', function(nodeUri, sectionId) {
if (options.sectionId === sectionId) {
self.refresh(nodeUri);
}
});
resolve();
})
.on('query', function(params) {
var self = this;
if(preloadNode){
params.selectedUri = options.loadNode;
preloadNode = false;
}
//ask the server the resources from the component query
resourceProvider.getResources(params, true)
.then(function(resources) {
self.update(resources, params);
})
.catch(function(err) {
logger.error(err);
});
})
.on('update.first', function(){
this.off('update.first');
//on the 1st update we select the default node
//or fallback on 1st instance, or even 1st class
this.selectDefaultNode(options.loadNode || defaultNode);
})
.on('selectionmodechange', function(mode) {
if (mode === 'single' && defaultNode) {
this.selectDefaultNode(defaultNode);
}
})
.on('change', function(selection) {
var self = this;
var length = _.size(selection);
var getContext = function getContext(resource) {
return _.defaults(resource, {
id : resource.uri,
rootClassUri : self.classUri
});
};
//ignore changes while loading or modifying the selector
if(self.is('loading')){
return;
}
if(length === 1){
_.forEach(selection, function(resource) {
var selectedContext = getContext(resource);
actionManager.updateContext(selectedContext);
if(selectedContext.type === 'class'){
actionManager.exec(options.actions.selectClass, selectedContext);
}
if(selectedContext.type === 'instance'){
actionManager.exec(options.actions.selectInstance, selectedContext);
}
generisRouter.pushNodeState(location.href, resource.uri);
defaultNode = resource;
treeStore.setItem(options.id, defaultNode);
});
} else {
actionManager.updateContext( _.transform(selection, function(acc, resource){
acc.push(getContext(resource));
return acc;
}, []));
}
})
.on('error', function(err){
logger.error(err);
});
});
});
});
}
};
});