diff --git a/datamodels/2.x/itop-portal-base/portal/src/Controller/BrowseBrickController.php b/datamodels/2.x/itop-portal-base/portal/src/Controller/BrowseBrickController.php index 9811b2390c..cfb1e24916 100644 --- a/datamodels/2.x/itop-portal-base/portal/src/Controller/BrowseBrickController.php +++ b/datamodels/2.x/itop-portal-base/portal/src/Controller/BrowseBrickController.php @@ -359,9 +359,16 @@ class BrowseBrickController extends BrickController } $oSet->OptimizeColumnLoad($aColumnAttrs); - // Sorting objects through defined order (in DM) - $oSet->SetOrderByClasses(); - + // Setting specified column sort, setting default datamodel one otherwise + $aSortedParams = $this->ExtractSortParams(); + if (!empty($aSortedParams)) + { + $oSet->SetOrderBy($aSortedParams); + } + else + { + $oSet->SetOrderByClasses(); + } // Retrieving results and organizing them for templating $aItems = array(); while ($aCurrentRow = $oSet->FetchAssoc()) @@ -423,4 +430,28 @@ class BrowseBrickController extends BrickController return $oResponse; } + + /** + * Extract sort params from request and convert them to iTop OQL format + * + * @return array + * + * @since 2.7.0 + */ + protected function ExtractSortParams() + { + /** @var \Combodo\iTop\Portal\Helper\RequestManipulatorHelper $oRequestManipulator */ + $oRequestManipulator = $this->get('request_manipulator'); + + // Getting sort params + $aSortParams = $oRequestManipulator->ReadParam('aSortParams', array()); + + // Converting sort direction to proper format for DBObjectSet as it only accept real booleans + foreach ($aSortParams as $sAttributeAlias => $sDirection) + { + $aSortParams[$sAttributeAlias] = ($sDirection === 'true'); + } + + return $aSortParams; + } } diff --git a/datamodels/2.x/itop-portal-base/portal/src/Controller/ManageBrickController.php b/datamodels/2.x/itop-portal-base/portal/src/Controller/ManageBrickController.php index ff2998382c..468975449c 100644 --- a/datamodels/2.x/itop-portal-base/portal/src/Controller/ManageBrickController.php +++ b/datamodels/2.x/itop-portal-base/portal/src/Controller/ManageBrickController.php @@ -881,31 +881,25 @@ class ManageBrickController extends BrickController /** * Extract sort params from request and convert them to iTop OQL format * - * @param array $aColumnsAttrs - * * @return array * * @since 2.7.0 */ - protected function ExtractSortParams($aColumnsAttrs = array()) + protected function ExtractSortParams() { /** @var \Combodo\iTop\Portal\Helper\RequestManipulatorHelper $oRequestManipulator */ $oRequestManipulator = $this->get('request_manipulator'); // Getting sort params $aSortParams = $oRequestManipulator->ReadParam('aSortParams', array()); - $aFormattedSortParams = array(); - // - Adding possible multiple sort params on displayed columns - foreach ($aSortParams as $sKey => $aSortParam) + // Converting sort direction to proper format for DBObjectSet as it only accept real booleans + foreach ($aSortParams as $sAttributeAlias => $sDirection) { - if (array_key_exists($aSortParam['column'], $aColumnsAttrs)) - { - $aFormattedSortParams[$aColumnsAttrs[$aSortParam['column']]] = ($aSortParam['dir'] === 'asc'); - } + $aSortParams[$sAttributeAlias] = ($sDirection === 'true'); } - return $aFormattedSortParams; + return $aSortParams; } /** diff --git a/datamodels/2.x/itop-portal-base/portal/templates/bricks/browse/mode_list.html.twig b/datamodels/2.x/itop-portal-base/portal/templates/bricks/browse/mode_list.html.twig index 8e6beca2c8..e2b2f2d898 100644 --- a/datamodels/2.x/itop-portal-base/portal/templates/bricks/browse/mode_list.html.twig +++ b/datamodels/2.x/itop-portal-base/portal/templates/bricks/browse/mode_list.html.twig @@ -39,7 +39,7 @@ aColumnsDefinition.push({ "width": "auto", "searchable": true, - "sortable": (sDataLoading === '{{ constant('Combodo\\iTop\\Portal\\Brick\\AbstractBrick::ENUM_DATA_LOADING_FULL') }}'), + "sortable": true, "title": oLevelsProperties[sKey].title, "defaultContent": "", "type": "html", @@ -182,7 +182,7 @@ aColumnsDefinition.push({ "width": "auto", "searchable": true, - "sortable": false, + "sortable": true, "visible": !oLevelsProperties[sKey].fields[i].hidden, "title": oLevelsProperties[sKey].fields[i].label, "defaultContent": "", @@ -252,8 +252,28 @@ d.iPageNumber = Math.floor(d.start / d.length)+1; d.iListLength = d.length; d.sDataLoading = "{{ constant('Combodo\\iTop\\Portal\\Brick\\AbstractBrick::ENUM_DATA_LOADING_LAZY') }}"; - d.columns = null; - d.orders = null; + + // Prepare sort params (formatting them for direct use by DBObjectSet) + d.aSortParams = {}; + for (var iSortIdx in d.order) { + /* oSortedColumnData {column: index, dir: 'asc'|'desc'} */ + var oSortedColumnData = d.order[iSortIdx]; + /* sSortedColumnId (eg. 'L-1-1' for level's main column, or 'L-1-1.fields.ATTCODE' for other columns) */ + var sSortedColumnId = d.columns[oSortedColumnData.column].data; + + // Make proper attribute alias for OQL from column ID + // - Main level column (we have to retrieve the attcode from the level properties) + if (sSortedColumnId.indexOf('.fields') < 0) { + var sSortedAttributeAlias = sSortedColumnId+'.'+oLevelsProperties[sSortedColumnId].name_att; + } + // - Optional fields (attcode is already in the column ID, we just have to clean it) + else { + var sSortedAttributeAlias = sSortedColumnId.replace('.fields', ''); + } + + d.aSortParams[sSortedAttributeAlias] = (oSortedColumnData.dir === 'asc'); + } + if (d.search.value) { diff --git a/datamodels/2.x/itop-portal-base/portal/templates/bricks/manage/layout-table.html.twig b/datamodels/2.x/itop-portal-base/portal/templates/bricks/manage/layout-table.html.twig index e26983bef0..50ad411d07 100644 --- a/datamodels/2.x/itop-portal-base/portal/templates/bricks/manage/layout-table.html.twig +++ b/datamodels/2.x/itop-portal-base/portal/templates/bricks/manage/layout-table.html.twig @@ -294,7 +294,20 @@ "data": function (d) { d.iPageNumber = Math.floor(d.start / d.length) + 1; d.iListLength = d.length; - d.aSortParams = d.order; + + // Prepare sort params (formatting them for direct use by DBObjectSet) + d.aSortParams = {}; + for (var iSortIdx in d.order) { + /* oSortedColumnData {column: index, dir: 'asc'|'desc'} */ + var oSortedColumnData = d.order[iSortIdx]; + /* sSortedColumnId (eg. 'attributes.ATT_CODE.att_code') */ + var sSortedColumnId = d.columns[oSortedColumnData.column].data; + + // Make proper attribute alias for OQL from column ID + sSortedColumnId = sSortedColumnId.replace(/^attributes\./, '').replace(/\.att_code$/, ''); + + d.aSortParams[sSortedColumnId] = (oSortedColumnData.dir === 'asc'); + } {% if sSearchValue is not null %} // Sets default filter value