mirror of
https://github.com/Combodo/iTop.git
synced 2026-04-19 16:48:42 +02:00
N°2313 - Markup extensibility: Add markup hooks on BrowseBrick and ManageBrick tables
This commit is contained in:
@@ -30,6 +30,7 @@ use BinaryExpression;
|
||||
use CMDBSource;
|
||||
use Combodo\iTop\Portal\Brick\AbstractBrick;
|
||||
use Combodo\iTop\Portal\Brick\ManageBrick;
|
||||
use Combodo\iTop\Portal\Helper\ApplicationHelper;
|
||||
use DBObject;
|
||||
use DBObjectSet;
|
||||
use DBSearch;
|
||||
@@ -592,6 +593,9 @@ class ManageBrickController extends BrickController
|
||||
/** @var DBObject $oCurrentRow */
|
||||
while ($oCurrentRow = $oSet->Fetch())
|
||||
{
|
||||
$sCurrentObjectClass = get_class($oCurrentRow);
|
||||
$sCurrentObjectId = $oCurrentRow->GetKey();
|
||||
|
||||
// ... Retrieving item's attributes values
|
||||
$aItemAttrs = array();
|
||||
foreach ($aColumnsAttrs as $sItemAttr)
|
||||
@@ -631,6 +635,7 @@ class ManageBrickController extends BrickController
|
||||
|
||||
/** @var \AttributeDefinition $oAttDef */
|
||||
$oAttDef = MetaModel::GetAttributeDef($sCurrentClass, $sItemAttr);
|
||||
$sAttDefClass = get_class($oAttDef);
|
||||
if ($oAttDef->IsExternalKey())
|
||||
{
|
||||
/** @var \AttributeExternalKey $oAttDef */
|
||||
@@ -688,9 +693,25 @@ class ManageBrickController extends BrickController
|
||||
}
|
||||
unset($oAttDef);
|
||||
|
||||
// For simple fields, we get the raw (stored) value as well
|
||||
$bExcludeRawValue = false;
|
||||
foreach (ApplicationHelper::GetAttDefClassesToExcludeFromMarkupMetadataRawValue() as $sAttDefClassToExclude)
|
||||
{
|
||||
if (is_a($sAttDefClass, $sAttDefClassToExclude, true))
|
||||
{
|
||||
$bExcludeRawValue = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
$attValueRaw = ($bExcludeRawValue === false) ? $oCurrentRow->Get($sItemAttr) : null;
|
||||
|
||||
$aItemAttrs[$sItemAttr] = array(
|
||||
'att_code' => $sItemAttr,
|
||||
'value' => $sValue,
|
||||
'object_class' => $sCurrentObjectClass,
|
||||
'object_id' => $sCurrentObjectId,
|
||||
'attribute_code' => $sItemAttr,
|
||||
'attribute_type' => $sAttDefClass,
|
||||
'value_raw' => $attValueRaw,
|
||||
'value_html' => $sValue,
|
||||
'sort_value' => $sSortValue,
|
||||
'actions' => $aActions,
|
||||
);
|
||||
|
||||
@@ -469,4 +469,23 @@ class ApplicationHelper
|
||||
return $aForm;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an array of AttributeDefinition classes for which the raw value should be excluded from the markup meta (because its too big / complex)
|
||||
* IMPORTANT: This needs to be refactored when the portal will handle attributes display in a better way. Also this is a duplicate from cmdbAbstractObject::GetAttDefClassesToExcludeFromMarkupMetadataRawValue() as for the moment we have no clean place to put this.
|
||||
*
|
||||
* @return array
|
||||
* @since 2.7.0
|
||||
*/
|
||||
public static function GetAttDefClassesToExcludeFromMarkupMetadataRawValue(){
|
||||
return array(
|
||||
'AttributeBlob',
|
||||
'AttributeCustomFields',
|
||||
'AttributeDashboard',
|
||||
'AttributeLinkedSet',
|
||||
'AttributeStopWatch',
|
||||
'AttributeSubItem',
|
||||
'AttributeTable',
|
||||
'AttributeText'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -322,12 +322,26 @@ class BrowseBrickHelper
|
||||
// Retrieving objects from all levels
|
||||
$aItems = array_values($aCurrentRow);
|
||||
|
||||
$sCurrentObjectClass = get_class($value);
|
||||
$sCurrentObjectId = $value->GetKey();
|
||||
|
||||
$sNameAttCode = $aLevelsProperties[$key]['name_att'];
|
||||
$sNameAttDef = MetaModel::GetAttributeDef($sCurrentObjectClass, $sNameAttCode);
|
||||
$sNameAttDefClass = get_class($sNameAttDef);
|
||||
|
||||
$aRow[$key] = array(
|
||||
'level_alias' => $key,
|
||||
'id' => $value->GetKey(),
|
||||
'name' => $value->Get($aLevelsProperties[$key]['name_att']),
|
||||
'class' => get_class($value),
|
||||
'id' => $sCurrentObjectId,
|
||||
'name' => $value->Get($sNameAttCode),
|
||||
'class' => $sCurrentObjectClass,
|
||||
'action_rules_token' => $this->PrepareActionRulesForItems($aItems, $key, $aLevelsProperties),
|
||||
'metadata' => array(
|
||||
'object_class' => $sCurrentObjectClass,
|
||||
'object_id' => $sCurrentObjectId,
|
||||
'attribute_code' => $sNameAttCode,
|
||||
'attribute_type' => $sNameAttDefClass,
|
||||
'value_raw' => $value->Get($sNameAttCode),
|
||||
),
|
||||
);
|
||||
|
||||
// Adding optional attributes if necessary
|
||||
@@ -336,7 +350,7 @@ class BrowseBrickHelper
|
||||
if ($aLevelsProperties[$key][$sOptionalAttribute] !== null)
|
||||
{
|
||||
$sPropertyName = substr($sOptionalAttribute, 0, -4);
|
||||
$oAttDef = MetaModel::GetAttributeDef(get_class($value), $aLevelsProperties[$key][$sOptionalAttribute]);
|
||||
$oAttDef = MetaModel::GetAttributeDef($sCurrentObjectClass, $aLevelsProperties[$key][$sOptionalAttribute]);
|
||||
|
||||
if ($oAttDef instanceof AttributeImage)
|
||||
{
|
||||
@@ -346,8 +360,8 @@ class BrowseBrickHelper
|
||||
if (is_object($tmpAttValue) && !$tmpAttValue->IsEmpty())
|
||||
{
|
||||
$tmpAttValue = $this->oUrlGenerator->generate('p_object_document_display', array(
|
||||
'sObjectClass' => get_class($value),
|
||||
'sObjectId' => $value->GetKey(),
|
||||
'sObjectClass' => $sCurrentObjectClass,
|
||||
'sObjectId' => $sCurrentObjectId,
|
||||
'sObjectField' => $aLevelsProperties[$key][$sOptionalAttribute],
|
||||
'cache' => 86400,
|
||||
));
|
||||
@@ -372,7 +386,8 @@ class BrowseBrickHelper
|
||||
$aRow[$key]['fields'] = array();
|
||||
foreach ($aLevelsProperties[$key]['fields'] as $aField)
|
||||
{
|
||||
$oAttDef = MetaModel::GetAttributeDef(get_class($value), $aField['code']);
|
||||
$oAttDef = MetaModel::GetAttributeDef($sCurrentObjectClass, $aField['code']);
|
||||
$sAttDefClass = get_class($oAttDef);
|
||||
|
||||
switch (true)
|
||||
{
|
||||
@@ -390,8 +405,8 @@ class BrowseBrickHelper
|
||||
if (is_object($oOrmDoc) && !$oOrmDoc->IsEmpty())
|
||||
{
|
||||
$sUrl = $this->oUrlGenerator->generate('p_object_document_display', array(
|
||||
'sObjectClass' => get_class($value),
|
||||
'sObjectId' => $value->GetKey(),
|
||||
'sObjectClass' => $sCurrentObjectClass,
|
||||
'sObjectId' => $sCurrentObjectId,
|
||||
'sObjectField' => $aField['code'],
|
||||
'cache' => 86400,
|
||||
));
|
||||
@@ -408,7 +423,26 @@ class BrowseBrickHelper
|
||||
break;
|
||||
}
|
||||
|
||||
$aRow[$key]['fields'][$aField['code']] = $sHtmlForFieldValue;
|
||||
// For simple fields, we get the raw (stored) value as well
|
||||
$bExcludeRawValue = false;
|
||||
foreach (ApplicationHelper::GetAttDefClassesToExcludeFromMarkupMetadataRawValue() as $sAttDefClassToExclude)
|
||||
{
|
||||
if (is_a($sAttDefClass, $sAttDefClassToExclude, true))
|
||||
{
|
||||
$bExcludeRawValue = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
$attValueRaw = ($bExcludeRawValue === false) ? $value->Get($aField['code']) : null;
|
||||
|
||||
$aRow[$key]['fields'][$aField['code']] = array(
|
||||
'object_class' => $sCurrentObjectClass,
|
||||
'object_id' => $sCurrentObjectId,
|
||||
'attribute_code' => $aField['code'],
|
||||
'attribute_type' => $sAttDefClass,
|
||||
'value_raw' => $attValueRaw,
|
||||
'value_html' => $sHtmlForFieldValue,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,7 +67,14 @@
|
||||
// Preparing the cell data
|
||||
cellElem = (levelActionsKeys.length > 0) ? $('<a></a>') : $('<span></span>');
|
||||
cellElem.attr('data-item-id', data.id).attr('data-level-alias', data.level_alias);
|
||||
|
||||
|
||||
// Building metadata
|
||||
for(var sPropName in data.metadata)
|
||||
{
|
||||
var propValue = data.metadata[sPropName];
|
||||
cellElem.attr('data-'+sPropName.replace('_', '-'), propValue);
|
||||
}
|
||||
|
||||
// Building tooltip for the node
|
||||
// We have to concatenate the HTML as we return the raw HTML of the cell. If we did a jQuery.insertAfter, the tooltip would not be returned.
|
||||
// For the same reason, tooltip widget is created in "drawCallback" instead of here.
|
||||
@@ -187,7 +194,26 @@
|
||||
"title": oLevelsProperties[sKey].fields[i].label,
|
||||
"defaultContent": "",
|
||||
"type": "html",
|
||||
"data": oLevelsProperties[sKey].alias+".fields."+oLevelsProperties[sKey].fields[i].code
|
||||
"data": oLevelsProperties[sKey].alias+".fields."+oLevelsProperties[sKey].fields[i].code,
|
||||
"render": function(data, type, row){
|
||||
var cellElem = $('<span></span>');
|
||||
|
||||
// Building value and metadata
|
||||
for(var sPropName in data)
|
||||
{
|
||||
var sPropValue = data[sPropName];
|
||||
if(sPropName === 'value_html')
|
||||
{
|
||||
cellElem.html(sPropValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
cellElem.attr('data-'+sPropName.replace('_', '-'), sPropValue);
|
||||
}
|
||||
}
|
||||
|
||||
return cellElem.prop('outerHTML');
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
{% if aGroupingTabsValues|length > 1 %}
|
||||
<ul class="nav nav-pills grouping_tabs">
|
||||
{% for aGroupingTab in aGroupingTabsValues %}
|
||||
<li{% if sGroupingTab is defined and sGroupingTab == aGroupingTab.value %} class="active"{% endif %}>
|
||||
<li{% if sGroupingTab is defined and sGroupingTab == aGroupingTab.value %} class="active"{% endif %} data-id="{{ aGroupingTab.value }}" data-label="{{ aGroupingTab.label }}" data-item-count="{{ aGroupingTab.count }}">
|
||||
<a href="{{ app.url_generator.generate('p_manage_brick_display_as', {'sBrickId': sBrickId, 'sDisplayMode': sDisplayMode, 'sGroupingTab': aGroupingTab.value}) }}"
|
||||
id="btn_tab_for_{{ aGroupingTab.value }}">
|
||||
{{ aGroupingTab.label|raw }}
|
||||
@@ -105,20 +105,33 @@
|
||||
"title": tableProperties[key].title,
|
||||
"defaultContent": "",
|
||||
"type": "html",
|
||||
"data": "attributes." + key + ".att_code",
|
||||
"data": "attributes." + key + ".attribute_code",
|
||||
"render": {
|
||||
_: function (att_code, type, row) {
|
||||
_: function (attribute_code, type, row) {
|
||||
var cellElem;
|
||||
var itemActions;
|
||||
var itemPrimarayAction;
|
||||
var itemPrimaryAction;
|
||||
var metadataNames = ['object_class', 'object_id', 'attribute_code', 'attribute_type', 'value_raw'];
|
||||
|
||||
// Preparing action on the cell
|
||||
// Note : For now we will use only one action, the secondary actions are therefore not implemented. Only the data structure is done.
|
||||
itemActions = row.attributes[att_code].actions;
|
||||
itemActions = row.attributes[attribute_code].actions;
|
||||
|
||||
// Preparing the cell data
|
||||
cellElem = (itemActions.length > 0) ? $('<a></a>') : $('<span></span>');
|
||||
cellElem.html(row.attributes[att_code].value);
|
||||
for(var sPropName in row.attributes[attribute_code])
|
||||
{
|
||||
var propValue = row.attributes[attribute_code][sPropName];
|
||||
if(sPropName === 'value_html')
|
||||
{
|
||||
cellElem.html(propValue);
|
||||
}
|
||||
else if(metadataNames.indexOf(sPropName) > -1)
|
||||
{
|
||||
cellElem.attr('data-'+sPropName.replace('_', '-'), propValue)
|
||||
}
|
||||
}
|
||||
|
||||
// Building actions
|
||||
if (itemActions.length > 0) {
|
||||
// - Primary action
|
||||
@@ -144,8 +157,8 @@
|
||||
|
||||
return cellElem.prop('outerHTML');
|
||||
},
|
||||
sort: function (att_code, type, row) {
|
||||
return row.attributes[att_code].sort_value;
|
||||
sort: function (attribute_code, type, row) {
|
||||
return row.attributes[attribute_code].sort_value;
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -159,8 +172,8 @@
|
||||
"title": tableProperties[key].title,
|
||||
"defaultContent": "",
|
||||
"type": "html",
|
||||
"data": "attributes." + key + ".att_code",
|
||||
"render": function (att_code, type, row) {
|
||||
"data": "attributes." + key + ".attribute_code",
|
||||
"render": function (attribute_code, type, row) {
|
||||
var cellElem = $('<div class="group-actions-wrapper"></div>');
|
||||
var actionsCount = row.actions.length;
|
||||
|
||||
@@ -300,11 +313,11 @@
|
||||
for (var iSortIdx in d.order) {
|
||||
/* oSortedColumnData {column: index, dir: 'asc'|'desc'} */
|
||||
var oSortedColumnData = d.order[iSortIdx];
|
||||
/* sSortedColumnId (eg. 'attributes.ATT_CODE.att_code') */
|
||||
/* sSortedColumnId (eg. 'attributes.ATT_CODE.attribute_code') */
|
||||
var sSortedColumnId = d.columns[oSortedColumnData.column].data;
|
||||
|
||||
// Make proper attribute alias for OQL from column ID
|
||||
sSortedColumnId = sSortedColumnId.replace(/^attributes\./, '').replace(/\.att_code$/, '');
|
||||
sSortedColumnId = sSortedColumnId.replace(/^attributes\./, '').replace(/\.attribute_code$/, '');
|
||||
|
||||
d.aSortParams[sSortedColumnId] = (oSortedColumnData.dir === 'asc');
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user