/*
* 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 class provides a tree panel for newsletters
* @private
*/
Ext.define('Ametys.plugins.newsletter.NewslettersTree', {
extend: 'Ext.tree.Panel',
/**
* @cfg {String} langContext The language code (defaults to null for all languages, a combobox will thus be drawn for choosing it).
*/
/**
* @cfg {boolean} categoriesOnly To display only categories. Defaults to 'false'.
*/
/**
* @cfg {Boolean} checkMode To select tags by checkboxes. Defaults to 'false'.
*/
checkMode : false,
/**
* @cfg {String[]} values List of checkboxes name to check, if checkMode=true.
*/
values : [],
/**
* @private
* @property {String} _lang The language code. Null if there is a combobox on top of the tree.
*/
initComponent: function ()
{
this.on('load', this._onLoad, this);
this.on('checkchange', this._onCheckChange, this);
this.callParent(arguments);
},
/**
* @private
* Function after tree loading
* @param {Ext.data.TreeStore} store The tree store
* @param {Ext.data.TreeModel[]} records The records
* @param {Boolean} successful True if the operation was successful.
* @param {Ext.data.Operation} operation The operation that triggered this load.
* @param {Ext.data.NodeInterface} node The loaded node
*/
_onLoad: function (store, records, successful, operation, node)
{
this._setInfos(node);
if (this.checkMode === true)
{
this._setCheckboxes(node);
}
},
/**
* Iterate through the node childs, and call #_setInfo
* @param {Ext.data.Model} node The node to iterate
* @private
*/
_setInfos: function (node)
{
var childNodes = node.childNodes;
for (var i=0; i < childNodes.length; i++)
{
this._setInfo (childNodes[i]);
this._setInfos (childNodes[i]);
}
},
/**
* Initialize the node, by setting the tooltip and autoexpand the providers
* @param {Ext.data.Model} node The node to initialize
* @private
*/
_setInfo: function (node)
{
// auto expand providers
if (node.get('type') == 'newsletter-category-provider')
{
this.expandNode(node);
}
if (node.get("disabled") == true)
{
var cls = node.get('cls');
cls += (cls ? ' ' : '') + 'disabled';
node.set('cls', cls);
}
},
/**
* Iterate through the children nodes, and call #_setCheckbox
* @param {Ext.data.Model} node The node to iterate
* @private
*/
_setCheckboxes: function (node)
{
var childNodes = node.childNodes;
for (var i=0; i < childNodes.length; i++)
{
this._setCheckbox (childNodes[i]);
this._setCheckboxes (childNodes[i]);
}
},
/**
* Put a checkbox on nodes that can be checked, with the corresponding state. Does not verify any rights.
* @param {Ext.data.Model} node The node
* @private
*/
_setCheckbox: function (node)
{
if (node.get('type') !== 'newsletter-category-provider')
{
node.set('checked', Ext.Array.contains(this.values, node.get('id')));
}
else
{
node.set('checked', null);
}
},
/**
* Verify if a node can be checked. If it can, his value is updated
* @param {Ext.data.Model} node The node which state was updated
* @param {Boolean} checked The new node state
* @private
*/
_onCheckChange: function(node, checked)
{
if (node.get('disabled') === true)
{
node.set('checked', !checked);
return ;
}
if (checked === true && Ext.Array.contains(this.values, node.get('id')) === false)
{
this.values.push(node.get('id'));
}
else if (checked === false && Ext.Array.contains(this.values, node.get('id')) === true)
{
Ext.Array.remove(this.values, node.get('id'));
if (this._checkFilter === true)
{
this._filterByCheckedNodes(null, true);
}
}
},
constructor: function(config)
{
this._categoriesOnly = config.categoriesOnly || false;
var store = Ext.create('Ext.data.TreeStore', {
model: 'Ametys.plugins.newsletter.NewslettersTree.NewsletterNodeEntry',
autoLoad: false,
proxy: {
type: 'ametys',
plugin: 'newsletter',
url: 'newsletters.json',
reader: {
type: 'json'
},
extraParams: {
sitename: Ametys.getAppParameter('siteName'),
categoriesOnly: this._categoriesOnly
}
},
sorters: [
{
property: 'type', // do not mix nodes with different types
direction: 'DESC'
},
{
property: 'text',
direction: 'ASC'
}
]
});
store.on('beforeload', this._onBeforeLoad, this);
var root = {
expanded: false,
iconCls: 'a-tree-glyph ametysicon-categories',
text: '{{i18n PLUGINS_NEWSLETTER_UITOOL_CATEGORIES_ROOT_NODE_LABEL}}',
id: 'root',
type: 'newsletter-category-provider',
allowDrag: false,
allowDrop: false
};
Ext.apply(config, {
store: store,
root: root,
rootVisible: true,
scrollable: true,
animate: true
});
if (config.langContext == null)
{
// Add form to select language in a combobox
var langCombo = Ametys.cms.language.LanguageDAO.createComboBox({
itemId: 'languages-combo',
fieldLabel: "{{i18n PLUGINS_NEWSLETTER_UITOOL_LANGUAGES_LABEL}}",
flex: 1,
listeners: {
'change': Ext.bind(this._onChangeLang, this)
}
});
config.dockedItems = [{
dock: 'top',
xtype: 'toolbar',
layout: {
type: 'hbox',
align: 'stretch'
},
border: false,
defaults : {
cls: 'ametys',
labelWidth: 55,
labelSeparator: ''
},
items: langCombo
}]
}
else
{
this._lang = config.langContext;
}
this.callParent(arguments);
this.on('itemmouseenter', this._createQtip, this);
},
/**
* Listens before loading categories.
* The load action will be canceled if it returns false
* @param {Ext.data.Store} store The store.
* @param {Ext.data.operation.Operation} operation The Ext.data.operation.Operation object that will be passed to the Proxy to load the Store.
* @param {Object} eOpts The options object passed to Ext.util.Observable.addListener.
* @return {Boolean} False if the load action will be canceled.
* @private
*/
_onBeforeLoad: function(store, operation, eOpts)
{
var lang = this.getLang();
operation.setParams( Ext.apply(operation.getParams() || {}, {
checkMode: this.checkMode,
lang: lang
}));
},
/**
* Listens when a lang is changed.
* @param {Ext.form.field.Field} field The field
* @param {Object} newValue The new value.
* @param {Object} oldValue The original value.
* @private
*/
_onChangeLang: function(field, newValue, oldValue)
{
this.getSelectionModel().select(this.getRootNode());
// Refresh the root node.
this.refreshNode();
},
/**
* Refreshes the given node
* @param {Ext.data.NodeInterface} [node] The node to refresh. Root node by default.
* @param {Function} [callback] The callback function to call when the refresh is over.
*/
refreshNode: function(node, callback)
{
node = node || this.getRootNode();
if (!Ext.isFunction(callback))
{
callback = Ext.emptyFn;
}
this.getStore().load({
node : node,
callback : function()
{
callback();
Ext.defer(this.expandNode, 200, this, [ node, false, null ]);
},
scope : this
});
},
/**
* Gets the current lang.
* @return {String} The lang.
*/
getLang: function()
{
if (this._lang)
{
return this._lang;
}
else
{
return this.down("combobox[itemId='languages-combo']").getValue();
}
},
/**
* @private
* Destroy and create the node tooltip when the mouse enters the node
* @param {Ext.view.View} view The tree view
* @param {Ext.data.Model} node The tree node
* @param {HTMLElement} el The node's element
*/
_createQtip: function (view, node, el)
{
if (!node.isRoot())
{
Ext.QuickTips.unregister(el);
Ext.QuickTips.register(Ext.apply({target: el, id: el.id + '-tooltip'}, this._getTooltip(node)));
}
},
/**
* Get the tooltip configuration
* @param {Ext.data.Model} node The tree node
* @returns {Object} The tooltip configuration. See Ametys.ui.fluent.Tooltip.
* @private
*/
_getTooltip: function(node)
{
return {
title: node.get('text'),
glyphIcon: node.get('tooltipIconCls'),
imageWidth: 48,
imageHeight: 48,
text: node.get('description'),
inribbon: false
};
},
});