Commit 15792845 authored by Marcello Pivanti's avatar Marcello Pivanti
Browse files

Initial Commit

parents
#Amos Tag
Extension for tags and interest areas.
Installation
------------
1. The preferred way to install this extension is through [composer](http://getcomposer.org/download/).
Either run
```bash
composer require elitedivision/amos-tag
```
or add this row
```
"elitedivision/amos-tag": "dev-master"
```
to the require section of your `composer.json` file.
2. Add module to your main config in backend:
```php
'modules' => [
'tag' => [
'class' => 'elitedivision\amos\tag\AmosTag',
'modelsEnabled' => [
/**
* Add here the classnames of the models for whose you want to enable tags
* (i.e. 'elitedivision\amos\news\models\News')
*/
]
],
],
```
3. To enable user-profile interest areas (tags to match with content tags), amos-cwh installation is needed
4. Apply migrations
a. amos-tag migrations
```bash
php yii migrate/up --migrationPath=@vendor/elitedivision/amos-tag/src/migrations
```
or add this row to your migrations config in console:
```php
return [
.
.
.
'@vendor/elitedivision/amos-tag/src/migrations',
.
.
.
];
```
Configuration
------------
Tag management is available for admin role - url PlatformUrl **/tag/manager**.
In tag manager it is possible to:
- To add new trees or tags
- enable tag trees (by root selection) for specific models - to all roles (rbac) or to the specified ones
- change tree settings eg. root visible will allow the user to select all tags by root in TagWidget (see below)
Widgets
-----------
Amos Tag provides two Widgets:
* **TagWidget** *elitedivision\amos\tag\widgets\TagWidget*
Draws tag tree to select values for a model.
example of use in a form:
```php
echo elitedivision\amos\tag\widgets\TagWidget::widget([
'model' => $model,
'attribute' => 'tagValues',
'form' => \yii\base\Widget::$stack[0],
'singleFixedTreeId' => $treeRoot,
'id' => 'third-tree',
'hideHeader' => true
]);
```
In a search form you can use the same widget with options :
```php
$params = \Yii::$app->request->getQueryParams();
echo \elitedivision\amos\tag\widgets\TagWidget::widget([
'model' => $model,
'attribute' => 'tagValues',
'form' => $form,
'isSearch' => true,
'form_values' => isset($params[$model->formName()]['tagValues']) ? $params[$model->formName()]['tagValues'] : []
]);
```
If singleFixedTreeId is not specified, all enabled trees for the $model are considered (table tag_models_auth_items_mm).
singleFixedTreeId is now possible an array (tag roots in singleFixedTreeId will be considered).
* **ShowTagsWidget** *elitedivision\amos\tag\widgets\ShowTagsWidget*
Draws the selected tags for a model (in view mode).
It is possible to specify a tree (property 'rootId') or a set of trees (property 'rootIdsArray') to show; if nothing is specified, all enabled trees for the model are considered.
Example:
```
<?= \elitedivision\amos\tag\widgets\ShowTagsWidget::widget([
'model' => $model,
'rootId' => $rootId
]) ?>
```
{
"name": "arter/amos-tag",
"description": "Sistema AMOS per le TAG",
"keywords": [
"amos",
"yii2",
"tag"
],
"homepage": "http://www.example.com/",
"type": "project",
"license": "BSD-3-Clause",
"support": {
"forum": "http://www.example.com/forum/",
"wiki": "http://www.example.com/wiki/"
},
"require": {
"php": ">=5.4.0",
"arter/amos-core": "~1.9",
"arter/amos-admin": ">=1.8",
"arter/amos-dashboard": "~1.5",
"creocoder/yii2-nested-sets": "0.9.*",
"lispa/yii2-tree-manager": "~2.0.0"
},
"config": {
"process-timeout": 1800,
"secure-http": false
},
"extra": {
"asset-installer-paths": {
"npm-asset-library": "vendor/npm",
"bower-asset-library": "vendor/bower"
}
},
"autoload": {
"psr-4": {
"elitedivision\\amos\\tag\\": "src"
}
},
"require-dev": {
"yiisoft/yii2-faker": "*"
}
}
\ No newline at end of file
<?php
/**
* Art-ER Attrattività, ricerca e territorio dell’Emilia-Romagna
* OPEN 2.0
*
*
* @package elitedivision\amos\tag
* @category CategoryName
* @author Elite Division S.r.l.
*/
namespace elitedivision\amos\tag;
use elitedivision\amos\core\module\AmosModule;
use elitedivision\amos\core\record\Record;
use elitedivision\amos\tag\widgets\icons\WidgetIconTag;
use elitedivision\amos\tag\widgets\icons\WidgetIconTagManager;
use Yii;
class AmosTag extends AmosModule {
public $controllerNamespace = 'elitedivision\amos\tag\controllers';
/**
* @var string
*/
public $postKey = 'Tag';
/**
* @var array
*/
public $modelsEnabled = [
];
public $behaviors = [
'elitedivision\amos\core\behaviors\TaggableBehavior'
];
public $name = 'Tag';
public $selectSonsOnly = true;
/**
*
*/
public function init() {
parent::init();
Record::$modulesChainBehavior[] = 'tag';
Yii::setAlias('@elitedivision/amos/' . static::getModuleName() . '/controllers', __DIR__ . '/controllers');
//aggiunge le configurazioni trovate nel file config/config.php
Yii::configure($this, require(__DIR__ . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'config.php'));
}
/**
*
*/
public function bootstrap() {
$treeManagerModule = Yii::$app->getModule('treemanager');
if (!$treeManagerModule) {
Yii::$app->setModule('treemanager', $this->getModule('treemanager'));
}
}
/**
*
* @return string
*/
public static function getModuleName() {
return 'tag';
}
/**
*
*/
public function getWidgetGraphics() {
}
/**
*
* @return type
*/
public function getWidgetIcons() {
return [
WidgetIconTagManager::className(),
WidgetIconTag::className()
];
}
/**
* Chiave che verrà spedita in post
*
* @return string
*/
public function getPostKey() {
return $this->postKey;
}
/**
* @param string $postKey
*/
public function setPostKey($postKey) {
$this->postKey = $postKey;
}
protected function getDefaultModels() {
return [
'Tag' => __NAMESPACE__ . '\\' . 'models\\Tag',
];
}
}
\ No newline at end of file
<?php
/**
* Art-ER Attrattività, ricerca e territorio dell’Emilia-Romagna
* OPEN 2.0
*
*
* @package elitedivision\amos\tag
* @category CategoryName
* @author Elite Division S.r.l.
*/
namespace elitedivision\amos\tag\assets;
use yii\web\AssetBundle;
class ModuleTagAsset extends AssetBundle
{
public $sourcePath = '@vendor/elitedivision/amos-tag/src/assets/web';
public $css = [
];
public $js = [
'js/tag-js.js'
];
public $depends = [
];
public function init()
{
$moduleL = \Yii::$app->getModule('layout');
if(!empty($moduleL))
{ $this->depends [] = 'elitedivision\amos\layout\assets\BaseAsset'; }
else
{ $this->depends [] = 'elitedivision\amos\core\views\assets\AmosCoreAsset'; }
parent::init(); // TODO: Change the autogenerated stub
}
}
<?php
/**
* Art-ER Attrattività, ricerca e territorio dell’Emilia-Romagna
* OPEN 2.0
*
*
* @package elitedivision\amos\tag
* @category CategoryName
* @author Elite Division S.r.l.
*/
namespace elitedivision\amos\tag\assets;
use elitedivision\amos\core\widget\WidgetAbstract;
use yii\web\AssetBundle;
class ModuleTagFormAsset extends AssetBundle
{
public $sourcePath = '@vendor/elitedivision/amos-tag/src/assets/web';
public $css = [
'less/tag.less'
];
public $js = [
'js/tag-form.js',
];
public $depends = [
];
/*
//force reset cache asset (devel ONLY)
public $publishOptions = [
'forceCopy'=>true,
];
*/
public function init()
{
$moduleL = \Yii::$app->getModule('layout');
if(!empty(\Yii::$app->params['dashboardEngine']) && \Yii::$app->params['dashboardEngine'] == WidgetAbstract::ENGINE_ROWS){
$this->css = ['less/tag_fullsize.less'];
}
if(!empty($moduleL))
{ $this->depends [] = 'elitedivision\amos\layout\assets\BaseAsset'; }
else
{ $this->depends [] = 'elitedivision\amos\core\views\assets\AmosCoreAsset'; }
parent::init();
}
}
$(document).ready(function() {
if(typeof TagFormVars != 'undefined') {
TagFormVars.forEach(function (TagFormVar, indexTree) {
$.each(TagFormVar.data_trees, function (index, data_tree) {
var id_tree = data_tree['id'];
var limit_tree = data_tree['limit'];
var tags_selected = data_tree['tags_selected'];
//metodo comune che avvia la renderizzazione della preview dell'albero ed applica gli eventi
TagForm.initTree(tags_selected, id_tree, limit_tree, TagFormVar.data_trees, indexTree);
//avoid send malformed string as selected nodes on submit - eg. string will be directly used in search query
$('body').on('submit', 'form', function (e) {
var values = $("#tree_obj_"+id_tree).val();
if(values.length){
if(values.charAt(0)== ','){
values = values.substr(1);
}
if(values.charAt(values.length-1)== ','){
values = values.substr(0, values.length-1);
}
$("#tree_obj_"+id_tree).val(values);
}
});// end check on submit
});
onlyLeavesSelectable(TagFormVar.selectSonsOnly);
});
}
});
var TagForm = [];
TagForm.initTree = function(tags_selected, id_tree, limit_tree, data_trees, indexTree){
//renderizza la preview ed aggiorna il totale dei nodi selezionati
TagForm.renderPreview(tags_selected, id_tree, limit_tree, indexTree);
/* di seguito applica gli eventi sugli alberi */
$("#tree_obj_" + id_tree).on('treeview.checked', function (event, key) {
if (limit_tree >= 1) {
var selectedNodes = $(this).val();
if (selectedNodes) {
selectedNodes = selectedNodes.split(',');
if (
selectedNodes
&&
selectedNodes.length
&&
selectedNodes.length >= limit_tree
) {
$(this).treeview('uncheckNode', key);
alert(TagFormVars[indexTree].error_limit_tags);
}
}
}
else {
TagForm.updateTotale(id_tree, limit_tree, indexTree);
}
});
$("#tree_obj_" + id_tree).on('treeview.change', function (event, key, name) {
var key = key || '';
var name = name || '';
var tagsData = new Array();
var keyNodes = new Array();
var nameNodes = new Array();
if (key && name) {
keyNodes = key.split(',');
nameNodes = name.split('||');
$.each(keyNodes, function (index, keyNode) {
if (!keyNode) {
return;
}
if (nameNodes[index]) {
tagsData.push({
id: keyNode,
label: nameNodes[index],
});
}
});
}
//metodo comune per aggiornamento della preview e del totale
TagForm.renderPreview(tagsData, id_tree, limit_tree, indexTree);
});
$("#preview_tag_tree_" + id_tree).on("click", ".tag_selected_remove", function (event) {
event.stopImmediatePropagation();
//recupera la preview del relativo tag
var tag_selected = $(this).parents(".tag_selected").first();
if(tag_selected.length){
//recupera i dati di tag e albero
var id_tag = tag_selected.attr("data-tagid");
var id_tag_tree = tag_selected.attr("data-tagtree");
//se ci sono tutti i dati
if (id_tag && id_tag_tree) {
//rimuove il nodo
$("#tree_obj_" + id_tag_tree).treeview('uncheckNode', id_tag);
//identifica il limite di tag selezionabili per l'albero in esame, serve per
//l'aggiornamento del numero di selezioni rimaste
var limit_tag_tree = false;
$.each(data_trees, function (index, data_tree) {
var id_tree = data_tree['id'];
var limit_tree = data_tree['limit'];
if (id_tree == id_tag_tree) {
limit_tag_tree = limit_tree;
}
});
//metodo comune per l'aggiornamento del totale delle selezioni
TagForm.updateTotale(id_tag_tree, limit_tag_tree, indexTree);
}
}
});
$("#preview_tag_tree_" + id_tree).on("click", ".tag_selected", function (event) {
event.stopImmediatePropagation();
//identifica il tag preview
var tag_selected = $(this);
//recupera i dati di tag e albero
var id_tag = tag_selected.attr("data-tagid");
var id_tag_tree = tag_selected.attr("data-tagtree");
//se ci sono tutti i dati
if (id_tag && id_tag_tree) {
//identifica il tag a cui scrollare
var tagScrollTo = $("#tree_obj_" + id_tag_tree + "-tree").find('[data-key="' + id_tag + '"]');
if (tagScrollTo.length) {
//lancia la funzione ricorsiva che apre tutti i parent
TagForm.openNode(tagScrollTo);
//altezza dell'header
var headerHeight = $("#tree_obj_" + id_tag_tree + "-wrapper").find('.kv-header-container').height();
$("#tree_obj_" + id_tag_tree + "-tree").animate({
scrollTop: (tagScrollTo[0].offsetTop - headerHeight)
}, 'slow');
}
}
});
};
TagForm.renderPreview = function(tagsData, id_tree, limit_tree, indexTree){
//identifica il blocco di preview
var preview_block = $('#preview_tag_tree_'+id_tree);
//lo svuota
preview_block.empty();
//se ci sono elementi, li renderizza
if(tagsData.length > 0){
$.each(tagsData, function(index, tagData){
var id_tag = tagData.id;
var tag_tmp = "";
tag_tmp += "<div class='tag_selected col-xs-12' data-tagid='"+id_tag+"' data-tagtree='"+id_tree+"'>";
tag_tmp += " <div class='tag_selected_part tag_selected_remove_container'>";
tag_tmp += " <div class='tag_selected_remove'>"+TagFormVars[indexTree].icon_remove_tag+"</div>";
tag_tmp += " </div>";
tag_tmp += " <div class='tag_selected_part'>";
tag_tmp += " <div class='tag_selected_label'>";
tag_tmp += " "+tagData.label;
tag_tmp += " </div>";
tag_tmp += " <div class='tag_selected_parents'>";
tag_tmp += " "+TagForm.getParentsString(id_tag, id_tree);
tag_tmp += " </div>";
tag_tmp += " </div>";
tag_tmp += "</div>";
//lo inserisce nella preview
preview_block.append(tag_tmp);
});
}
//altrimenti inserisce una label generale
else{
var label_no_tag = "";
label_no_tag += "<span class='tree_no_tag'>";
label_no_tag += " "+TagFormVars[indexTree].no_tags_selected;
label_no_tag += "</span>";
preview_block.append(label_no_tag);
}
//metodo comune per l'aggiornamento del contatore dei nodi selezionati
TagForm.updateTotale(id_tree, limit_tree, indexTree);
};
TagForm.getParentsString = function(id_tag, id_tag_tree){
//identifica il tag
var currentTag = $("#tree_obj_" + id_tag_tree + "-tree").find('[data-key="' + id_tag + '"]');
//recupera ricorsivamente la label dei tag padri
var tag_parents = TagForm.getParentsStringFromTag(currentTag);
return tag_parents.join(" / ");
};
TagForm.updateTotale = function(id_tree, limit_tree, indexTree){
//identifica il blocco che contiene il contatore
var counter_block = $('#remaining_tag_tree_'+id_tree).find('.tree-remaining-tag-number');
//se il limite non è infinito
if(limit_tree){
//calcola il totale attuale
var selectedNodes = $("#tree_obj_"+id_tree).val();
//recupera il conteggio degli elementi
var count_selected = 0;
if(selectedNodes && selectedNodes != ''){
selectedNodes = selectedNodes.split(',');
count_selected = selectedNodes.length;
}
counter_block.html((limit_tree - count_selected)+"/"+limit_tree);
}
else{
counter_block.html(TagFormVars[indexTree].tags_unlimited);
}
};
TagForm.openNode = function(node){
//recupera il nodo parent e se chiuso lo apre
var parentNode = node.parents(".kv-parent").first();
//procede solo se ha identificato il nodo padre
if(parentNode.length){
//se il nodo è chiuso
if(parentNode.hasClass('kv-collapsed')){
parentNode.find('.kv-node-toggle').first().trigger('click');
}
TagForm.openNode(parentNode);
}
};
TagForm.getParentsStringFromTag = function(node){
//array con i parents
var parents = new Array();
//recupera il nodo parent
var parentNode = node.parents(".kv-parent").first();
//procede solo se ha identificato il nodo padre
if(parentNode.length){
//salva la label
parents.push(parentNode.find(".kv-node-label").html());
//lancia ricorsivamente per identificare i nodi padre del padre
var parent_parents = TagForm.getParentsStringFromTag(parentNode);