/*
* 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.
*/
/**
* Singleton class to handle the branch action on a survey page.
* @private
*/
Ext.define('Ametys.plugins.survey.BranchAction', {
singleton: true,
/**
* @private
* @property {Ametys.window.DialogBox} _branchesDialogBox The dialog box for creating/editing branches.
*/
/**
* @private
* @property {Ext.panel.Panel} _rulesPanel The rules panel of the dialog box.
*/
/**
* @private
* @property {Boolean} _initialized Indicates if the dialog box is initialized.
*/
/**
* @private
* @property {Object} _rulesDataviews A map containing the dataviews of the rules. The key is the question id or page id (for inconditional rule).
*/
/**
* @private
* @property {Ext.XTemplate} _questionRuleTpl The template used for the question dataview
*/
_questionRuleTpl: Ext.create('Ext.XTemplate', [
'<tpl for=".">',
'<div class="rule-wrap {cls}" id="rule-{option}">',
'<button onclick="Ametys.plugins.survey.BranchAction._deleteRule(\'{qId}\', \'{option}\'); return false;" title="{{i18n PLUGINS_SURVEY_BRANCH_DELETE_RULE}}"><span class="ametysicon-delete30"></span></button>',
'{{i18n PLUGINS_SURVEY_BRANCH_HINT}}<b>{optionLabel}</b>,<br/>',
'<tpl if="type == \'JUMP\'">',
'{{i18n PLUGINS_SURVEY_BRANCH_HINT_JUMP}} <b>{pageLabel}</b><br/>',
'</tpl>',
'<tpl if="type == \'FINISH\'">',
'{{i18n PLUGINS_SURVEY_BRANCH_HINT_FINISH}}',
'</tpl>',
'</div>',
'</tpl>'
]),
/**
* @private
* @property {Ext.XTemplate} _pageRuleTpl The template used for the page dataview
*/
_pageRuleTpl: Ext.create('Ext.XTemplate', [
'<tpl for=".">',
'<div class="rule-wrap" id="rule-{pageId}">',
'<button onclick="Ametys.plugins.survey.BranchAction._deleteInconditionalRule(\'{pageId}\'); return false;" title="{{i18n PLUGINS_SURVEY_BRANCH_DELETE_RULE}}"><span class="ametysicon-delete30"></span></button>',
'{{i18n PLUGINS_SURVEY_BRANCH_HINT_NO_RULE}},<br/>',
'<tpl if="type == \'JUMP\'">',
'{{i18n PLUGINS_SURVEY_BRANCH_HINT_JUMP}} <b>{pageLabel}</b><br/>',
'</tpl>',
'<tpl if="type == \'FINISH\'">',
'{{i18n PLUGINS_SURVEY_BRANCH_HINT_FINISH}}',
'</tpl>',
'</div>',
'</tpl>'
]),
/**
* Enables to manage branches on a page through a dilog box.
* @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function.
*/
act: function(controller)
{
var pageTarget = controller.getMatchingTargets()[0];
this._surveyId = pageTarget.getParameters().surveyId;
this._pageId = pageTarget.getParameters().id;
Ametys.cms.survey.PageDAO.isLastPage([this._pageId], this._doAct, {scope: this, arguments: [pageTarget]});
},
/**
* Shows the branch dialog box, or a message if this is the last page.
* @param {Boolean} isLast True if the current page is the last one.
* @param {Array} args The arguments.
* @private
*/
_doAct: function(isLast, args)
{
var pageTarget = args[0];
if (isLast)
{
Ametys.Msg.show({
title: "{{i18n PLUGINS_SURVEY_BRANCH_LABEL}}",
msg: "{{i18n PLUGINS_SURVEY_BRANCH_LAST_PAGE}}",
buttons: Ext.Msg.OK,
icon: Ext.MessageBox.INFO
});
return;
}
this._delayedInitialize();
// Load the branches
Ametys.cms.survey.PageDAO.getBranches([this._pageId], this._getBranchesCb, {scope: this});
},
/**
* Initializes the dialog box.
* @private
*/
_delayedInitialize: function()
{
if (!this._initialized)
{
this._rulesPanel = Ext.create('Ext.panel.Panel', {
scrollable: 'vertical',
layout: 'anchor',
flex: 1,
defaults: {
anchor: '95%'
}
});
this._branchesDialogBox = Ext.create('Ametys.window.DialogBox', {
title: "{{i18n PLUGINS_SURVEY_BRANCH_LABEL}}",
iconCls: "ametysicon-turn-right5",
width: 650,
maxHeight: 600,
layout: {
type: 'vbox',
align: 'stretch'
},
scrollable: false,
border: false,
items: [
{
xtype: 'component',
cls: 'a-text',
html: "{{i18n PLUGINS_SURVEY_BRANCH_HELP_TEXT}}"
},
this._rulesPanel
],
closeAction: 'hide',
referenceHolder: true,
defaultButton: 'validate',
buttons: [{
reference: 'validate',
text: "{{i18n PLUGINS_SURVEY_DIALOG_BUTTON_OK}}",
handler: function() {this._branchesDialogBox.close();},
scope: this
}]
});
this._initialized = true;
}
},
/**
* Shows the branch dialog box after retrieving the branches from the server.
* @param {Object} branches The branches retrieved from the server.
* @private
*/
_getBranchesCb: function(branches)
{
this._rulesDataviews = {};
this._rulesPanel.removeAll();
var questions = branches.questions;
var hintHtml = "{{i18n PLUGINS_SURVEY_BRANCH_QUESTIONS_LIST_HINT_TEXT}}";
if (questions.length > 0)
{
hintHtml += "{{i18n PLUGINS_SURVEY_BRANCH_QUESTIONS_LIST_NB_HINT_TEXT_1}}" + questions.length + "{{i18n PLUGINS_SURVEY_BRANCH_QUESTIONS_LIST_NB_HINT_TEXT_2}}";
}
else
{
hintHtml += "{{i18n PLUGINS_SURVEY_BRANCH_NO_QUESTION_LIST_HINT_TEXT}}";
}
var me = this;
me._rulesPanel.add({
xtype: 'component',
cls: 'a-text',
html: hintHtml
});
// Add questions
Ext.Array.each (questions, function (question) {
me._rulesPanel.add(me._createQuestionRulePanel(question));
});
// Inconditional jump
me._rulesPanel.add({
xtype: 'component',
cls: 'a-text',
html: "{{i18n PLUGINS_SURVEY_BRANCH_UNCONDITIONAL_JUMP_HINT_TEXT}}"
});
me._rulesPanel.add(me._createInconditionalJumpPanel(branches));
this._branchesDialogBox.show();
},
/**
* @private
* Create a question rules item.
* @param {Object} question the question
*/
_createQuestionRulePanel: function (question)
{
var qId = question.id;
var qNumber = question.number;
var qTitle = "Q." + qNumber + " - " + question.title;
var rulesStore = Ext.create('Ext.data.Store', {
fields: ['qId', 'option', 'optionLabel', 'type', 'page', 'pageLabel', 'cls']
});
Ext.Array.each (question.rules, function (rule, index) {
rulesStore.add({
qId: qId,
option: rule.option,
optionLabel: rule.optionLabel,
type: rule.type,
page: rule.page,
pageLabel: rule.pageName,
cls: index % 2 == 0 ? ' even' : ' odd'
});
});
var dataview = Ext.create('Ext.view.View', {
// title: qTitle,
store: rulesStore,
tpl: this._questionRuleTpl,
height: 'auto',
overItemCls:'x-view-over',
itemSelector:'div.rule-wrap'
});
this._rulesDataviews[qId] = dataview;
return Ext.create ('Ext.Panel', {
xtype: 'panel',
style: {
marginBottom: '15px'
},
header: {
titlePosition: 1,
title: qTitle,
style: "border-width: 1px !important"
},
ui: 'light',
border: true,
collapsible: true,
collapsed: false,
titleCollapse: true,
items: [dataview],
tools: [{
type: 'plus',
qtip: "{{i18n PLUGINS_SURVEY_ADD_RULE_LABEL}}",
handler: Ext.bind(this._addRule, this, [qId]),
scope: this
}]
});
},
/**
* @private
* Create a item for inconditional jump
* @param {Object} branches the branches
*/
_createInconditionalJumpPanel: function (branches)
{
var store = Ext.create('Ext.data.Store', {
fields: ['pageId', 'type', 'page', 'pageLabel']
});
if (branches.rule != null)
{
store.add({
pageId: this._pageId,
type: branches.rule.type,
page: branches.rule.page,
pageLabel: branches.rule.pageName
});
}
var dataview = Ext.create('Ext.view.View', {
// title: qTitle,
store: store,
tpl: this._pageRuleTpl,
height: 'auto',
overItemCls:'x-view-over',
itemSelector:'div.rule-wrap'
});
this._rulesDataviews[this._pageId] = dataview;
return Ext.create('Ext.Panel', {
xtype: 'panel',
header: {
titlePosition: 1,
title: "{{i18n PLUGINS_SURVEY_BRANCH_INCONDITIONAL_JUMP}}",
style: "border-width: 1px !important"
},
ui: 'light',
border: true,
collapsible: true,
titleCollapse: true,
collapsed: false,
items:[dataview],
tools: [{
type: 'plus',
qtip: "{{i18n PLUGINS_SURVEY_ADD_RULE_LABEL}}",
handler: this._addInconditionalRule,
scope: this
}]
});
},
/**
* Opens a dialog box for creating a new rule.
* @param {String} qId The question id
* @private
*/
_addRule: function(qId)
{
Ametys.plugins.survey.RulesDialog.open({
mode: 'newRule',
surveyId: this._surveyId,
pageId: this._pageId,
questionId: qId,
callback: Ext.bind(this._loadQuestionRules, this, [qId])
});
},
/**
* Deletes the selected option.
* @param {String} qId The question id
* @param {String} option The option to delete
* @private
*/
_deleteRule: function(qId, option)
{
Ext.create('Ext.window.MessageBox', {
closeAction: 'destroy',
alwaysOnTop: true
}).confirm(
"{{i18n PLUGINS_SURVEY_BRANCH_DELETE_RULE}}",
"{{i18n PLUGINS_SURVEY_BRANCH_DELETE_RULE_CONFIRM}}",
Ext.bind(this._doDelete, this, ['question', qId, option], 1),
this
);
},
/**
* Opens a dialog box for creating an inconditional rule.
* @private
*/
_addInconditionalRule: function()
{
Ametys.plugins.survey.RulesDialog.open({
mode: 'inconditionalJump',
surveyId: this._surveyId,
pageId: this._pageId,
callback: Ext.bind(this._loadPageRule, this, [this._pageId])
});
},
/**
* Deletes the selected inconditional rule.
* @param {String} pageId The page id
* @private
*/
_deleteInconditionalRule: function(pageId)
{
Ext.create('Ext.window.MessageBox', {
closeAction: 'destroy',
alwaysOnTop: true
}).confirm("{{i18n PLUGINS_SURVEY_BRANCH_DELETE_RULE}}",
"{{i18n PLUGINS_SURVEY_BRANCH_DELETE_RULE_CONFIRM}}",
Ext.bind(this._doDelete, this, ['page', pageId], 1),
this
);
},
/**
* @private
* The action to perform when the user clicks on a button from the removing message box.
* @param {String} btn The pressed button. Can only be 'yes'/'no'
* @param {String} type The type of deletion. Can only be 'question'/'page'.
* @param {String} id the question id (for type 'question') or the page id (for type 'page')
* @param {String} [option] The option to delete
*/
_doDelete: function(btn, type, id, option)
{
if (btn == 'yes')
{
if (type == 'question')
{
Ametys.cms.survey.QuestionDAO.deleteRule([id, option], this._doDeleteCb, {scope: this, arguments: [type]});
}
else if (type == 'page')
{
Ametys.cms.survey.PageDAO.deleteRule([id], this._doDeleteCb, {scope: this, arguments: [type]});
}
}
},
/**
* The callback function after {@link #_doDelete} succeeded.
* @param {Object} response The server response
* @param {Array} args The arguments
* @param {Array} params The callback parameters
* @private
*/
_doDeleteCb: function(response, args, params)
{
if (args[0] == 'question')
{
this._loadQuestionRules(params[0]);
}
else
{
this._loadPageRule(params[0]);
}
},
/**
* Loads and displays the question rules.
* @param {String} qId The question id
* @private
*/
_loadQuestionRules: function(qId)
{
Ametys.cms.survey.QuestionDAO.getRules([qId, 0], this._loadQuestionRulesCb, {scope: this});
},
/**
* The callback function after {@link #_loadQuestionRules} succeeded.
* @param {Object} response The server response
* @param {Array} args The arguments
* @param {Array} params The callback parameters
* @private
*/
_loadQuestionRulesCb: function(response, args, params)
{
var qId = params[0];
var dataview = this._rulesDataviews[qId];
var store = dataview.getStore();
store.removeAll();
for (var i = 0; i < response.rules.length; i++) {
store.add({
qId: qId,
option: response.rules[i].option,
optionLabel: response.rules[i].optionLabel,
type: response.rules[i].type,
page: response.rules[i].page,
pageLabel: response.rules[i].pageName
});
}
},
/**
* Loads and displays the page rule.
* @param {String} pageId The page id
* @private
*/
_loadPageRule: function(pageId)
{
Ametys.cms.survey.PageDAO.getRule([pageId], this._loadPageRuleCb, {scope: this});
},
/**
* The callback function after {@link #_loadPageRule} succeeded.
* @param {Object} response The server response
* @param {Array} args The arguments
* @param {Array} params The callback parameters
* @private
*/
_loadPageRuleCb: function(response, args, params)
{
var pageId = params[0];
var dataview = this._rulesDataviews[pageId];
var store = dataview.getStore();
store.removeAll();
if (response != null)
{
store.add({
pageId: pageId,
type: response.type,
page: response.page,
pageLabel: response.pageName
});
}
}
});