mirror of
https://github.com/Combodo/iTop.git
synced 2026-04-19 00:28:47 +02:00
N°2847 - Datatables for static data
This commit is contained in:
@@ -415,75 +415,8 @@ class DisplayBlock
|
||||
switch($this->m_sStyle)
|
||||
{
|
||||
case 'count':
|
||||
if (isset($aExtraParams['group_by']))
|
||||
{
|
||||
$this->MakeGroupByQuery($aExtraParams, $oGroupByExp, $sGroupByLabel, $aGroupBy, $sAggregationFunction, $sFctVar, $sAggregationAttr, $sSql);
|
||||
|
||||
$aRes = CMDBSource::QueryToArray($sSql);
|
||||
|
||||
$aGroupBy = array();
|
||||
$aLabels = array();
|
||||
$aValues = array();
|
||||
$iTotalCount = 0;
|
||||
foreach ($aRes as $iRow => $aRow)
|
||||
{
|
||||
$sValue = $aRow['grouped_by_1'];
|
||||
$aValues[$iRow] = $sValue;
|
||||
$sHtmlValue = $oGroupByExp->MakeValueLabel($this->m_oFilter, $sValue, $sValue);
|
||||
$aLabels[$iRow] = $sHtmlValue;
|
||||
$aGroupBy[$iRow] = (int) $aRow[$sFctVar];
|
||||
$iTotalCount += $aRow['_itop_count_'];
|
||||
}
|
||||
|
||||
|
||||
$aData = array();
|
||||
$oAppContext = new ApplicationContext();
|
||||
$sParams = $oAppContext->GetForLink();
|
||||
foreach($aGroupBy as $iRow => $iCount)
|
||||
{
|
||||
// Build the search for this subset
|
||||
$oSubsetSearch = $this->m_oFilter->DeepClone();
|
||||
$oCondition = new BinaryExpression($oGroupByExp, '=', new ScalarExpression($aValues[$iRow]));
|
||||
$oSubsetSearch->AddConditionExpression($oCondition);
|
||||
if (isset($aExtraParams['query_params']))
|
||||
{
|
||||
$aQueryParams = $aExtraParams['query_params'];
|
||||
}
|
||||
else
|
||||
{
|
||||
$aQueryParams = array();
|
||||
}
|
||||
$sFilter = rawurlencode($oSubsetSearch->serialize(false, $aQueryParams));
|
||||
|
||||
$aData[] = array ('group' => $aLabels[$iRow],
|
||||
'value' => "<a href=\"".utils::GetAbsoluteUrlAppRoot()."pages/UI.php?operation=search&dosearch=1&$sParams&filter=$sFilter\">$iCount</a>"); // TO DO: add the context information
|
||||
}
|
||||
$aAttribs =array(
|
||||
'group' => array('label' => $sGroupByLabel, 'description' => ''),
|
||||
'value' => array(
|
||||
'label' => Dict::S('UI:GroupBy:'.$sAggregationFunction),
|
||||
'description' => Dict::Format('UI:GroupBy:'.$sAggregationFunction.'+', $sAggregationAttr),
|
||||
),
|
||||
);
|
||||
$sFormat = isset($aExtraParams['format']) ? $aExtraParams['format'] : 'UI:Pagination:HeaderNoSelection';
|
||||
$sHtml .= $oPage->GetP(Dict::Format($sFormat, $iTotalCount));
|
||||
$sHtml .= $oPage->GetTable($aAttribs, $aData);
|
||||
|
||||
$oPage->add_ready_script("LoadGroupBySortOrder('$sId');\n$('#{$sId} table.listResults').unbind('sortEnd.group_by').bind('sortEnd.group_by', function() { SaveGroupBySortOrder('$sId', $(this)[0].config.sortList); })");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Simply count the number of elements in the set
|
||||
$iCount = $this->m_oSet->Count();
|
||||
$sFormat = 'UI:CountOfObjects';
|
||||
if (isset($aExtraParams['format']))
|
||||
{
|
||||
$sFormat = $aExtraParams['format'];
|
||||
}
|
||||
$sHtml .= $oPage->GetP(Dict::Format($sFormat, $iCount));
|
||||
}
|
||||
|
||||
break;
|
||||
$oBlock = $this->RenderCount($aExtraParams, $oPage, $sId);
|
||||
break;
|
||||
|
||||
case 'join':
|
||||
$aDisplayAliases = isset($aExtraParams['display_aliases']) ? explode(',', $aExtraParams['display_aliases']): array();
|
||||
@@ -1382,6 +1315,83 @@ JS
|
||||
|
||||
return $oBlock;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $aExtraParams
|
||||
* @param \WebPage $oPage
|
||||
* @param string|null $sId
|
||||
*
|
||||
* @return \Combodo\iTop\Application\UI\iUIBlock
|
||||
* @throws \ArchivedObjectException
|
||||
* @throws \CoreException
|
||||
* @throws \MissingQueryArgument
|
||||
* @throws \MySQLException
|
||||
* @throws \MySQLHasGoneAwayException
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function RenderCount(array $aExtraParams, WebPage $oPage, ?string $sId): iUIBlock
|
||||
{
|
||||
if (isset($aExtraParams['group_by'])) {
|
||||
$this->MakeGroupByQuery($aExtraParams, $oGroupByExp, $sGroupByLabel, $aGroupBy, $sAggregationFunction, $sFctVar, $sAggregationAttr, $sSql);
|
||||
|
||||
$aRes = CMDBSource::QueryToArray($sSql);
|
||||
|
||||
$aGroupBy = array();
|
||||
$aLabels = array();
|
||||
$aValues = array();
|
||||
$iTotalCount = 0;
|
||||
foreach ($aRes as $iRow => $aRow) {
|
||||
$sValue = $aRow['grouped_by_1'];
|
||||
$aValues[$iRow] = $sValue;
|
||||
$sHtmlValue = $oGroupByExp->MakeValueLabel($this->m_oFilter, $sValue, $sValue);
|
||||
$aLabels[$iRow] = $sHtmlValue;
|
||||
$aGroupBy[$iRow] = (int)$aRow[$sFctVar];
|
||||
$iTotalCount += $aRow['_itop_count_'];
|
||||
}
|
||||
|
||||
$aData = array();
|
||||
$oAppContext = new ApplicationContext();
|
||||
$sParams = $oAppContext->GetForLink();
|
||||
foreach ($aGroupBy as $iRow => $iCount) {
|
||||
// Build the search for this subset
|
||||
$oSubsetSearch = $this->m_oFilter->DeepClone();
|
||||
$oCondition = new BinaryExpression($oGroupByExp, '=', new ScalarExpression($aValues[$iRow]));
|
||||
$oSubsetSearch->AddConditionExpression($oCondition);
|
||||
if (isset($aExtraParams['query_params'])) {
|
||||
$aQueryParams = $aExtraParams['query_params'];
|
||||
} else {
|
||||
$aQueryParams = array();
|
||||
}
|
||||
$sFilter = rawurlencode($oSubsetSearch->serialize(false, $aQueryParams));
|
||||
|
||||
$aData[] = array(
|
||||
'group' => $aLabels[$iRow],
|
||||
'value' => "<a href=\"".utils::GetAbsoluteUrlAppRoot()."pages/UI.php?operation=search&dosearch=1&$sParams&filter=$sFilter\">$iCount</a>"
|
||||
); // TO DO: add the context information
|
||||
}
|
||||
$aAttribs = array(
|
||||
'group' => array('label' => $sGroupByLabel, 'description' => ''),
|
||||
'value' => array(
|
||||
'label' => Dict::S('UI:GroupBy:'.$sAggregationFunction),
|
||||
'description' => Dict::Format('UI:GroupBy:'.$sAggregationFunction.'+', $sAggregationAttr),
|
||||
),
|
||||
);
|
||||
$sFormat = isset($aExtraParams['format']) ? $aExtraParams['format'] : 'UI:Pagination:HeaderNoSelection';
|
||||
$sTitle = Dict::Format($sFormat, $iTotalCount);
|
||||
$oBlock = DataTableFactory::MakeForStaticData($sTitle, $aAttribs, $aData);
|
||||
|
||||
// $oPage->add_ready_script("LoadGroupBySortOrder('$sId');\n$('#{$sId} table.listResults').unbind('sortEnd.group_by').bind('sortEnd.group_by', function() { SaveGroupBySortOrder('$sId', $(this)[0].config.sortList); })");
|
||||
} else {
|
||||
// Simply count the number of elements in the set
|
||||
$iCount = $this->m_oSet->Count();
|
||||
$sFormat = 'UI:CountOfObjects';
|
||||
if (isset($aExtraParams['format'])) {
|
||||
$sFormat = $aExtraParams['format'];
|
||||
}
|
||||
$oBlock = new Html($oPage->GetP(Dict::Format($sFormat, $iCount)));
|
||||
}
|
||||
return $oBlock;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -72,7 +72,7 @@
|
||||
}
|
||||
.ibo-datatable-toolbar {
|
||||
/*position: relative;*/
|
||||
height: 30px;
|
||||
//height: 30px;
|
||||
}
|
||||
.ibo-criterion-area{
|
||||
font-size: $ibo-font-size-50 ;
|
||||
|
||||
@@ -21,9 +21,9 @@
|
||||
Dict::Add('EN US', 'English', 'English', array(
|
||||
'UI:Datatables:Language:Processing' => 'Please wait...',
|
||||
'UI:Datatables:Language:Search' => 'Filter:',
|
||||
'UI:Datatables:Language:LengthMenu' => 'Showing _MENU_ out',
|
||||
'UI:Datatables:Language:LengthMenu' => 'Showing _MENU_ out of',
|
||||
'UI:Datatables:Language:ZeroRecords' => 'No result',
|
||||
'UI:Datatables:Language:Info' => 'of _TOTAL_ items',
|
||||
'UI:Datatables:Language:Info' => '_TOTAL_ items',
|
||||
'UI:Datatables:Language:InfoEmpty' => 'No information',
|
||||
'UI:Datatables:Language:InfoFiltered' => 'filtered out of _MAX_ items',
|
||||
'UI:Datatables:Language:EmptyTable' => 'No data available in this table',
|
||||
|
||||
@@ -164,6 +164,7 @@ return array(
|
||||
'Combodo\\iTop\\Application\\UI\\Component\\DataTable\\DataTableBlock' => $baseDir . '/sources/application/UI/Component/DataTable/DataTable.php',
|
||||
'Combodo\\iTop\\Application\\UI\\Component\\DataTable\\DataTableFactory' => $baseDir . '/sources/application/UI/Component/DataTable/DataTableFactory.php',
|
||||
'Combodo\\iTop\\Application\\UI\\Component\\DataTable\\DataTableSettings' => $baseDir . '/sources/application/UI/Component/DataTable/DataTableSettings.php',
|
||||
'Combodo\\iTop\\Application\\UI\\Component\\DataTable\\StaticTable\\StaticTable' => $baseDir . '/sources/application/UI/Component/DataTable/StaticTable/StaticTable.php',
|
||||
'Combodo\\iTop\\Application\\UI\\Component\\FieldSet\\FieldSet' => $baseDir . '/sources/application/UI/Component/FieldSet/FieldSet.php',
|
||||
'Combodo\\iTop\\Application\\UI\\Component\\Field\\Field' => $baseDir . '/sources/application/UI/Component/Field/Field.php',
|
||||
'Combodo\\iTop\\Application\\UI\\Component\\Form\\Form' => $baseDir . '/sources/application/UI/Component/Form/Form.php',
|
||||
|
||||
@@ -394,6 +394,7 @@ class ComposerStaticInit0018331147de7601e7552f7da8e3bb8b
|
||||
'Combodo\\iTop\\Application\\UI\\Component\\DataTable\\DataTableBlock' => __DIR__ . '/../..' . '/sources/application/UI/Component/DataTable/DataTable.php',
|
||||
'Combodo\\iTop\\Application\\UI\\Component\\DataTable\\DataTableFactory' => __DIR__ . '/../..' . '/sources/application/UI/Component/DataTable/DataTableFactory.php',
|
||||
'Combodo\\iTop\\Application\\UI\\Component\\DataTable\\DataTableSettings' => __DIR__ . '/../..' . '/sources/application/UI/Component/DataTable/DataTableSettings.php',
|
||||
'Combodo\\iTop\\Application\\UI\\Component\\DataTable\\StaticTable\\StaticTable' => __DIR__ . '/../..' . '/sources/application/UI/Component/DataTable/StaticTable/StaticTable.php',
|
||||
'Combodo\\iTop\\Application\\UI\\Component\\FieldSet\\FieldSet' => __DIR__ . '/../..' . '/sources/application/UI/Component/FieldSet/FieldSet.php',
|
||||
'Combodo\\iTop\\Application\\UI\\Component\\Field\\Field' => __DIR__ . '/../..' . '/sources/application/UI/Component/Field/Field.php',
|
||||
'Combodo\\iTop\\Application\\UI\\Component\\Form\\Form' => __DIR__ . '/../..' . '/sources/application/UI/Component/Form/Form.php',
|
||||
|
||||
@@ -10,7 +10,9 @@ use ApplicationException;
|
||||
use AttributeLinkedSet;
|
||||
use CMDBObjectSet;
|
||||
use cmdbAbstractObject;
|
||||
use Combodo\iTop\Application\UI\Component\DataTable\StaticTable\StaticTable;
|
||||
use Combodo\iTop\Application\UI\Component\Panel\PanelFactory;
|
||||
use Combodo\iTop\Application\UI\Component\Title\TitleFactory;
|
||||
use MetaModel;
|
||||
use appUserPreferences;
|
||||
use UserRights;
|
||||
@@ -639,7 +641,19 @@ class DataTableFactory
|
||||
} )'
|
||||
];
|
||||
|
||||
|
||||
return $aOptions;
|
||||
}
|
||||
|
||||
public static function MakeForStaticData(string $sTitle, array $aColumns, array $aData, ?string $sId = null)
|
||||
{
|
||||
$oBlock = new UIContentBlock();
|
||||
$oTitle = TitleFactory::MakeNeutral($sTitle, 3);
|
||||
$oBlock->AddSubBlock($oTitle);
|
||||
$oTable = new StaticTable($sId);
|
||||
$oTable->SetColumns($aColumns);
|
||||
$oTable->SetData($aData);
|
||||
$oBlock->AddSubBlock($oTable);
|
||||
|
||||
return $oBlock;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
namespace Combodo\iTop\Application\UI\Component\DataTable\StaticTable;
|
||||
|
||||
use Combodo\iTop\Application\UI\Layout\UIContentBlock;
|
||||
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2020 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* Tables with static data
|
||||
* Class StaticTable
|
||||
*/
|
||||
class StaticTable extends UIContentBlock
|
||||
{
|
||||
// Overloaded constants
|
||||
public const BLOCK_CODE = 'ibo-datatable';
|
||||
public const HTML_TEMPLATE_REL_PATH = 'components/datatable/static/layout';
|
||||
public const JS_TEMPLATE_REL_PATH = 'components/datatable/static/layout';
|
||||
|
||||
/**
|
||||
* @var array of 'entry name' => [
|
||||
* 'description' => tooltip,
|
||||
* 'label' => label to display,
|
||||
* 'class' => cell CSS class,
|
||||
* 'metadata' => [key => value] transformed into data-key="value"
|
||||
* ]
|
||||
*/
|
||||
private $aColumns;
|
||||
|
||||
/**
|
||||
* @var array of [
|
||||
* '@class' => css class of the row,
|
||||
* 'entry name' => [
|
||||
* 'value_html' => value to display in the cell,
|
||||
* 'value_raw' => real value put into data-value-raw
|
||||
* ], ...
|
||||
* ]
|
||||
*/
|
||||
private $aData;
|
||||
|
||||
public function __construct(string $sId = null, string $sContainerCSSClass = '')
|
||||
{
|
||||
parent::__construct($sId, $sContainerCSSClass);
|
||||
$this->aColumns = [];
|
||||
$this->aData = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function GetColumns(): array
|
||||
{
|
||||
return $this->aColumns;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $aColumns
|
||||
*/
|
||||
public function SetColumns(array $aColumns): void
|
||||
{
|
||||
$this->aColumns = $aColumns;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function GetData(): array
|
||||
{
|
||||
return $this->aData;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $aData
|
||||
*/
|
||||
public function SetData(array $aData): void
|
||||
{
|
||||
$this->aData = $aData;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -62,4 +62,9 @@ class TitleFactory
|
||||
|
||||
return $oTitle;
|
||||
}
|
||||
|
||||
public static function MakeNeutral(string $sTitle, int $iLevel = 1, ?string $sId = null)
|
||||
{
|
||||
return new Title($sTitle, $iLevel, $sId);
|
||||
}
|
||||
}
|
||||
48
templates/components/datatable/static/layout.html.twig
Normal file
48
templates/components/datatable/static/layout.html.twig
Normal file
@@ -0,0 +1,48 @@
|
||||
{# @copyright Copyright (C) 2010-2020 Combodo SARL #}
|
||||
{# @license http://opensource.org/licenses/AGPL-3.0 #}
|
||||
|
||||
{% set columns = oUIBlock.GetColumns() %}
|
||||
<table id="{{ oUIBlock.GetId() }}" class="ibo-datatable listResults" style="width:100%;">
|
||||
<thead>
|
||||
<tr>
|
||||
{% for column in columns %}
|
||||
<th class="ibo-datatable-header" title="{{ column.description }}">{{ column.label }}</th>
|
||||
{% endfor %}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for data in oUIBlock.GetData() %}
|
||||
{% if data['@class'] is not empty %}
|
||||
<tr role="row" class="{{ data['@class'] }}">
|
||||
{% else %}
|
||||
<tr>
|
||||
{% endif %}
|
||||
{% for name,column in columns %}
|
||||
<td {% if column.class is not empty %}class="{{ column.class }}" {% endif %}
|
||||
{% if column.metadata is not empty %}
|
||||
{% for prop,value in column.metadata %}
|
||||
data-{{ prop|replace({'_': '-'}) }}="{{ value }}"
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% set cellValueHtml = '' %}
|
||||
{% for cellName,cellValue in data %}
|
||||
{% if cellName == name %}
|
||||
{% if cellValue.value_raw is empty %}
|
||||
{% set cellValueHtml = cellValue %}
|
||||
{% else %}
|
||||
data-value-raw="{{ cellValue.value_raw }}"
|
||||
{% if cellValue.value_html is not empty %}
|
||||
{% set cellValueHtml = cellValue.value_html %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% if cellValueHtml is empty %}
|
||||
{% set cellValueHtml = ' ' %}
|
||||
{% endif %}
|
||||
>{{ cellValueHtml|raw }}</td>
|
||||
{% endfor %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
47
templates/components/datatable/static/layout.js.twig
Normal file
47
templates/components/datatable/static/layout.js.twig
Normal file
@@ -0,0 +1,47 @@
|
||||
{# @copyright Copyright (C) 2010-2020 Combodo SARL #}
|
||||
{# @license http://opensource.org/licenses/AGPL-3.0 #}
|
||||
|
||||
{% if oUIBlock.GetOptions() is not empty %}
|
||||
{% set iPageSize = oUIBlock.GetOptions()["iPageSize"] %}
|
||||
{% else %}
|
||||
{% set iPageSize = 10 %}
|
||||
{% endif %}
|
||||
|
||||
$('#{{ oUIBlock.GetId() }}').DataTable({
|
||||
language: {
|
||||
processing: "{{ 'UI:Datatables:Language:Processing'|dict_s }}",
|
||||
search: "{{ 'UI:Datatables:Language:Search'|dict_s }}",
|
||||
lengthMenu: "{{ 'UI:Datatables:Language:LengthMenu'|dict_s }}",
|
||||
zeroRecords: "{{ 'UI:Datatables:Language:ZeroRecords'|dict_s }}",
|
||||
info: "{{ 'UI:Datatables:Language:Info'|dict_s }}",
|
||||
infoEmpty: "",
|
||||
infoFiltered: "({{ 'UI:Datatables:Language:InfoFiltered'|dict_s }})",
|
||||
emptyTable: "{{ 'UI:Datatables:Language:EmptyTable'|dict_s }}",
|
||||
paginate: {
|
||||
first: "<<",
|
||||
previous: "<",
|
||||
next: ">",
|
||||
last: ">>"
|
||||
},
|
||||
aria: {
|
||||
sortAscending: ": {{ 'UI:Datatables:Language:Sort:Ascending'|dict_s }}",
|
||||
sortDescending: ": {{ 'UI:Datatables:Language:Sort:Descending'|dict_s }}"
|
||||
}
|
||||
},
|
||||
order: [],
|
||||
rowId: "id",
|
||||
filter: false,
|
||||
{% if oUIBlock.GetData()|length <= iPageSize %}
|
||||
paging: false,
|
||||
{% endif %}
|
||||
dom: "<'ibo-datatable-toolbar'pil>t<'ibo-datatable-toolbar'pil>",
|
||||
lengthMenu: [[ {{ iPageSize }}, {{ iPageSize*2 }}, {{ iPageSize*3 }}, {{ iPageSize*4 }}, -1], [ {{ iPageSize }}, {{ iPageSize*2 }}, {{ iPageSize*3 }}, {{ iPageSize*4 }}, "{{ 'Portal:Datatables:Language:DisplayLength:All'|dict_s }}"]],
|
||||
columns: [
|
||||
{% for column in oUIBlock.GetColumns() %}
|
||||
{
|
||||
width: "auto",
|
||||
sortable: true
|
||||
},
|
||||
{% endfor %}
|
||||
]
|
||||
});
|
||||
Reference in New Issue
Block a user