/*
* Copyright 2015 Anyware Services
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* This tool displays the surveys, with its pages and questions.
* @private
*/
Ext.define('Ametys.plugins.survey.SurveyTool', {
extend: 'Ametys.tool.Tool',
/**
* @private
* @property {Ametys.plugins.survey.SurveyTree} _tree The tree of this tool.
*/
constructor: function(config)
{
this.callParent(arguments);
Ametys.message.MessageBus.on(Ametys.message.Message.CREATED, this._onMessageCreated, this);
Ametys.message.MessageBus.on(Ametys.message.Message.MODIFIED, this._onMessageModified, this);
Ametys.message.MessageBus.on(Ametys.message.Message.DELETED, this._onMessageDeleted, this);
Ametys.message.MessageBus.on(Ametys.message.Message.WORKFLOW_CHANGED, this._onMessageWorkflowChanged, this);
},
createPanel: function()
{
this._tree = Ext.create('Ametys.plugins.survey.SurveyTree', {
// handle drag & drop
viewConfig: {
plugins: {
ptype: 'ametystreeviewdragdrop',
containerScroll: true,
appendOnly: false,
sortOnDrop: false,
expandDelay: 500,
allowContainerDrops: false,
setAmetysDragInfos: Ext.bind(this._getDragInfo, this),
setAmetysDropZoneInfos: Ext.bind(this._getDropInfo, this)
}
}
});
this._tree.on('selectionchange', this.sendCurrentSelection, this);
this._tree.on('itemdblclick', this._openPreviewTool, this);
return this._tree;
},
getMBSelectionInteraction: function()
{
return Ametys.tool.Tool.MB_TYPE_ACTIVE;
},
sendCurrentSelection: function()
{
var selection = this._tree.getSelectionModel().getSelection();
if (selection != null && selection.length > 0)
{
var node = selection[0];
var target = this._getMessageTargetConfiguration(node) || [];
var type = node.get('type'),
realTarget;
if (type == 'root' || type == 'survey')
{
realTarget = target;
}
else if (type == 'page')
{
var surveyNode = this._tree.getStore().getNodeById(node.get('parentId'));
realTarget = this._getMessageTargetConfiguration(surveyNode);
realTarget.subtargets = target;
}
else if (type == 'question')
{
var pageNode = this._tree.getStore().getNodeById(node.get('parentId'));
var surveyNode = this._tree.getStore().getNodeById(pageNode.get('parentId'));
realTarget = this._getMessageTargetConfiguration(surveyNode);
var subtarget = this._getMessageTargetConfiguration(pageNode);
subtarget.subtargets = target;
realTarget.subtargets = subtarget;
}
}
Ext.create('Ametys.message.Message', {
type: Ametys.message.Message.SELECTION_CHANGED,
targets: realTarget
});
},
/**
* Gets the selected language.
* @return {String} The selected language.
*/
getCurrentLanguage: function()
{
return this._tree.down("combobox[itemId='languages-combo']").getValue();
},
setParams: function (params)
{
this.callParent(arguments);
this.showOutOfDate();
},
refresh: function()
{
this.showRefreshing();
this._tree.getSelectionModel().select(this._tree.getRootNode());
this._tree.refreshNode(this._tree.getRootNode(), false, Ext.bind(this.showRefreshed, this));
},
/**
* @private
* This event is thrown by the getDragData to add the 'source' of the drag.
* @param {Object} item The default drag data that will be transmitted. You have to add a 'source' item in it:
* @param {Ametys.relation.RelationPoint} item.source The source (in the relation way) of the drag operation.
*/
_getDragInfo: function (item)
{
var targets = [];
for (var i = 0; i < item.records.length; i++)
{
var node = item.records[i];
if (node.get('type') == 'page' || node.get('type') == 'question')
{
targets.push(this._getMessageTargetConfiguration(node));
}
}
if (targets.length > 0)
{
item.source = {
relationTypes: [Ametys.relation.Relation.MOVE],
targets: targets
};
}
},
/**
* @private
* This event is thrown before the beforeDrop event and create the target of the drop operation relation.
* @param {Ext.data.Model[]} targetRecords The target records of the drop operation.
* @param {Object} item The default drag data that will be transmitted. You have to add a 'target' item in it:
* @param {Object} item.target The target (in the relation way) of the drop operation. A Ametys.relation.RelationPoint config.
* @param {String} dropPosition "before", "after" or "append" depending whether the dragged object (in item.target) should be inserted before, after the targetRecords, or appended to it.
*/
_getDropInfo: function(targetRecords, item, dropPosition)
{
var targets = [];
var positionInTargets = -1
for (var i = 0; i < targetRecords.length; i++)
{
var node = targetRecords[i];
if (dropPosition == 'append')
{
targets.push(this._getMessageTargetConfiguration(node));
}
else if (node.parentNode != null) // dropPosition == 'before' or 'after'
{
// Get node position
for (var i=0; i < node.parentNode.childNodes.length; i++)
{
if (node.parentNode.childNodes[i].getId() == node.getId())
{
positionInTargets = i + (dropPosition == 'after' ? + 1 : 0);
break;
}
}
targets.push(this._getMessageTargetConfiguration(node.parentNode));
}
}
if (targets.length > 0)
{
item.target = {
relationTypes: [Ametys.relation.Relation.MOVE],
targets: targets,
positionInTargets: positionInTargets
};
}
},
/**
* @private
* Get the target configuration object for given record
* @param {Ext.data.Model} record The tree record to convert to its Ametys.message.MessageTarget configuration
* @return {Object} The configuration to create a Ametys.message.MessageTarget. Can be null, if the record is null or not relevant to be a messagetarget.
*/
_getMessageTargetConfiguration: function (record)
{
if (record == null)
{
// Empty selection
return null;
}
else
{
if (record.get('type') == 'root')
{
return {
id: Ametys.message.MessageTarget.SURVEY_ROOT,
parameters: {}
};
}
else if (record.get('type') == 'survey')
{
return {
id: Ametys.message.MessageTarget.SURVEY,
parameters: {
id: record.getId()
}
};
}
else if (record.get('type') == 'page')
{
return {
id: Ametys.message.MessageTarget.SURVEY_PAGE,
parameters: {
id: record.getId(),
surveyId: record.get('parentId')
}
};
}
else if (record.get('type') == 'question')
{
var pageId = record.get('parentId');
var surveyId = this._tree.getStore().getNodeById(pageId).get('parentId');
return {
id: Ametys.message.MessageTarget.SURVEY_QUESTION,
parameters: {
id: record.getId(),
type: record.get('questionType'),
pageId: pageId,
surveyId: surveyId
}
};
}
}
},
/**
* Selects the specified node.
* @param {String} nodeId The node id
* @private
*/
_selectNode: function(nodeId)
{
var node = this._tree.getStore().getNodeById(nodeId);
this._tree.getSelectionModel().select(node);
},
/**
* Listener on creation message.
* @param {Ametys.message.Message} message The creation message.
* @private
*/
_onMessageCreated: function(message)
{
// Case survey
var target = message.getTarget(Ametys.message.MessageTarget.SURVEY);
if (target != null)
{
// Refresh root node
var parentNode = this._tree.getRootNode();
var newNodeId = target.getParameters().id;
this._tree.refreshNode(parentNode, false, Ext.bind(function(nodeId) {
var node = this._tree.getStore().getNodeById(nodeId);
this._tree.getSelectionModel().select(node);
Ext.defer(this._openPreviewTool, .1, this, [null, node]);
}, this, [newNodeId]));
}
// Case page
var target = message.getTarget(Ametys.message.MessageTarget.SURVEY_PAGE);
if (target != null)
{
// Refresh parent node
var surveyNode = this._tree.getStore().getNodeById(target.getParameters().surveyId);
var newNodeId = target.getParameters().id;
this._tree.refreshNode(surveyNode, false, Ext.bind(this._selectNode, this, [newNodeId]));
}
// Case question
var target = message.getTarget(Ametys.message.MessageTarget.SURVEY_QUESTION);
if (target != null)
{
// Refresh parent node
var pageNode = this._tree.getStore().getNodeById(target.getParameters().pageId);
var newNodeId = target.getParameters().id;
this._tree.refreshNode(pageNode, false, Ext.bind(this._selectNode, this, [newNodeId]));
}
},
/**
* Listener on edition message.
* @param {Ametys.message.Message} message The edition message.
* @private
*/
_onMessageModified: function(message)
{
var target = message.getTarget(function(target) {
return target.getId() == Ametys.message.MessageTarget.SURVEY
|| target.getId() == Ametys.message.MessageTarget.SURVEY_PAGE
|| target.getId() == Ametys.message.MessageTarget.SURVEY_QUESTION;
});
if (target != null)
{
var id = target.getParameters().id;
// Refresh parent node
var node = this._tree.getStore().getNodeById(id);
var parentId = node.get('parentId');
var parentNode = this._tree.getStore().getNodeById(parentId);
this._tree.refreshNode(parentNode, false, Ext.bind(this._selectNode, this, [id]));
}
},
/**
* Listener on deletion message.
* @param {Ametys.message.Message} message The deletion message.
* @private
*/
_onMessageDeleted: function(message)
{
var target = message.getTarget(function(target) {
return target.getId() == Ametys.message.MessageTarget.SURVEY
|| target.getId() == Ametys.message.MessageTarget.SURVEY_PAGE
|| target.getId() == Ametys.message.MessageTarget.SURVEY_QUESTION;
});
if (target != null)
{
var node = this._tree.getStore().getNodeById(target.getParameters().id);
var parentId = node.get('parentId');
var parentNode = this._tree.getStore().getNodeById(parentId);
// Select parent node and remove the node from the store
this._tree.getSelectionModel().select(parentNode);
node.remove();
}
},
/**
* Listener on workflow changing message.
* @param {Ametys.message.Message} message The wokflow changing message.
* @private
*/
_onMessageWorkflowChanged: function(message)
{
var target = message.getTarget(Ametys.message.MessageTarget.SURVEY);
if (target != null)
{
//var node = this._tree.getStore().getNodeById(target.getParameters().id);
this._tree.refreshNode(this._tree.getRootNode(), false);
}
},
/**
* Opens the preview tool for the record.
* @param {Ext.view.View} view The view.
* @param {Ext.data.Model} record The record that belongs to the item.
*/
_openPreviewTool: function(view, record)
{
var type = record.get('type');
switch (type) {
case 'survey':
var id = record.get('id');
break;
case 'page':
var pageId = record.get('id');
var id = record.get('parentId');
break;
case 'question':
var questionId = record.get('id');
var pageId = record.get('parentId');
var id = this._tree.getStore().getNodeById(pageId).get('parentId');
break;
case 'root':
default:
return;
}
var params = {
id: id,
pageId: pageId,
questionId: questionId
};
Ametys.tool.ToolsManager.openTool('uitool-survey-preview', params);
}
});
Ext.define("Ametys.message.SurveyMessageTarget",{
override: "Ametys.message.MessageTarget",
statics:
{
/**
* @member Ametys.message.MessageTarget
* @readonly
* @property {String} SURVEY_ROOT The target type is the survey tree root, which provides the surveys.
*/
SURVEY_ROOT: "survey-root",
/**
* @member Ametys.message.MessageTarget
* @readonly
* @property {String} SURVEY The target type is a survey. The expected parameters are:
* @property {String} SURVEY.id The id of this survey.
*/
SURVEY: "survey",
/**
* @member Ametys.message.MessageTarget
* @readonly
* @property {String} SURVEY_PAGE The target type is a survey page. The expected parameters are:
* @property {String} SURVEY_PAGE.id The id of this survey page.
* @property {String} SURVEY_PAGE.surveyId The id of the parent survey.
*/
SURVEY_PAGE: "survey-page",
/**
* @member Ametys.message.MessageTarget
* @readonly
* @property {String} SURVEY_QUESTION The target type is a survey question. The expected parameters are:
* @property {String} SURVEY_QUESTION.id The id of this question.
* @property {String} SURVEY_QUESTION.type The type of the question (FREE_TEXT, MULTILINE_FREE_TEXT, SINGLE_CHOICE, MULTIPLE_CHOICE, SINGLE_MATRIX, MUTLIPLE_MATRIX).
* @property {String} SURVEY_QUESTION.pageId The id of the parent page.
* @property {String} SURVEY_QUESTION.surveyId The id of the grandparent survey.
*/
SURVEY_QUESTION: "survey-question"
}
});