N°2847 - Tranform old itop datatable to jquery DataTable
@@ -20,6 +20,7 @@
|
||||
use Combodo\iTop\Application\UI\Component\Alert\AlertFactory;
|
||||
use Combodo\iTop\Application\UI\Component\Button\Button;
|
||||
use Combodo\iTop\Application\UI\Component\Button\ButtonFactory;
|
||||
use Combodo\iTop\Application\UI\Component\DataContainer\DataContainerFactory;
|
||||
use Combodo\iTop\Application\UI\Component\Field\Field;
|
||||
use Combodo\iTop\Application\UI\Component\FieldSet\FieldSet;
|
||||
use Combodo\iTop\Application\UI\Component\Form\Form;
|
||||
@@ -57,6 +58,7 @@ require_once(APPROOT.'sources/application/search/criterionconversionabstract.cla
|
||||
require_once(APPROOT.'sources/application/search/criterionconversion/criteriontooql.class.inc.php');
|
||||
require_once(APPROOT.'sources/application/search/criterionconversion/criteriontosearchform.class.inc.php');
|
||||
|
||||
use Combodo\iTop\Application\UI\Component\DataTable\DataTableFactory;
|
||||
/**
|
||||
* Class cmdbAbstractObject
|
||||
*/
|
||||
@@ -1042,7 +1044,7 @@ HTML
|
||||
*/
|
||||
public static function DisplaySet(WebPage $oPage, CMDBObjectSet $oSet, $aExtraParams = array())
|
||||
{
|
||||
$oPage->add(self::GetDisplaySet($oPage, $oSet, $aExtraParams));
|
||||
$oPage->AddUiBlock(self::GetDisplaySetBlock($oPage, $oSet, $aExtraParams));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1100,14 +1102,16 @@ HTML
|
||||
*
|
||||
* @throws \CoreException*@throws \Exception
|
||||
* @throws \ApplicationException
|
||||
* @deprecated 3.0.0 use GetDisplaySetBlock
|
||||
*/
|
||||
public static function GetDisplaySet(WebPage $oPage, CMDBObjectSet $oSet, $aExtraParams = array())
|
||||
{
|
||||
if ($oPage->IsPrintableVersion() || $oPage->is_pdf())
|
||||
{
|
||||
return self::GetDisplaySetForPrinting($oPage, $oSet, $aExtraParams);
|
||||
$oPage->AddUiBlock(GetDisplaySetBlock( $oPage, $oSet, $aExtraParams ));
|
||||
return "";
|
||||
}
|
||||
|
||||
public static function GetDisplaySetBlock(WebPage $oPage, CMDBObjectSet $oSet, $aExtraParams = array())
|
||||
{
|
||||
if (empty($aExtraParams['currentId']))
|
||||
{
|
||||
$iListId = $oPage->GetUniqueId(); // Works only if not in an Ajax page !!
|
||||
@@ -1117,136 +1121,10 @@ HTML
|
||||
$iListId = $aExtraParams['currentId'];
|
||||
}
|
||||
|
||||
// Initialize and check the parameters
|
||||
$bViewLink = isset($aExtraParams['view_link']) ? $aExtraParams['view_link'] : true;
|
||||
$sLinkageAttribute = isset($aExtraParams['link_attr']) ? $aExtraParams['link_attr'] : '';
|
||||
$iLinkedObjectId = isset($aExtraParams['object_id']) ? $aExtraParams['object_id'] : 0;
|
||||
$sTargetAttr = isset($aExtraParams['target_attr']) ? $aExtraParams['target_attr'] : '';
|
||||
if (!empty($sLinkageAttribute))
|
||||
{
|
||||
if ($iLinkedObjectId == 0)
|
||||
{
|
||||
// if 'links' mode is requested the id of the object to link to must be specified
|
||||
throw new ApplicationException(Dict::S('UI:Error:MandatoryTemplateParameter_object_id'));
|
||||
}
|
||||
if ($sTargetAttr == '')
|
||||
{
|
||||
// if 'links' mode is requested the d of the object to link to must be specified
|
||||
throw new ApplicationException(Dict::S('UI:Error:MandatoryTemplateParameter_target_attr'));
|
||||
}
|
||||
}
|
||||
$bDisplayMenu = isset($aExtraParams['menu']) ? $aExtraParams['menu'] == true : true;
|
||||
$bSelectMode = isset($aExtraParams['selection_mode']) ? $aExtraParams['selection_mode'] == true : false;
|
||||
$bSingleSelectMode = isset($aExtraParams['selection_type']) ? ($aExtraParams['selection_type'] == 'single') : false;
|
||||
$oDataTable = DataTableFactory::MakeForResult($oPage, $iListId, $oSet, $aExtraParams);
|
||||
|
||||
$aExtraFieldsRaw = isset($aExtraParams['extra_fields']) ? explode(',',
|
||||
trim($aExtraParams['extra_fields'])) : array();
|
||||
$aExtraFields = array();
|
||||
foreach($aExtraFieldsRaw as $sFieldName)
|
||||
{
|
||||
// Ignore attributes not of the main queried class
|
||||
if (preg_match('/^(.*)\.(.*)$/', $sFieldName, $aMatches))
|
||||
{
|
||||
$sClassAlias = $aMatches[1];
|
||||
$sAttCode = $aMatches[2];
|
||||
if ($sClassAlias == $oSet->GetFilter()->GetClassAlias())
|
||||
{
|
||||
$aExtraFields[] = $sAttCode;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$aExtraFields[] = $sFieldName;
|
||||
}
|
||||
}
|
||||
$sClassName = $oSet->GetFilter()->GetClass();
|
||||
$sZListName = isset($aExtraParams['zlist']) ? ($aExtraParams['zlist']) : 'list';
|
||||
if ($sZListName !== false)
|
||||
{
|
||||
$aList = self::FlattenZList(MetaModel::GetZListItems($sClassName, $sZListName));
|
||||
$aList = array_merge($aList, $aExtraFields);
|
||||
}
|
||||
else
|
||||
{
|
||||
$aList = $aExtraFields;
|
||||
}
|
||||
|
||||
// Filter the list to removed linked set since we are not able to display them here
|
||||
foreach($aList as $index => $sAttCode)
|
||||
{
|
||||
$oAttDef = MetaModel::GetAttributeDef($sClassName, $sAttCode);
|
||||
if ($oAttDef instanceof AttributeLinkedSet)
|
||||
{
|
||||
// Removed from the display list
|
||||
unset($aList[$index]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!empty($sLinkageAttribute))
|
||||
{
|
||||
// The set to display is in fact a set of links between the object specified in the $sLinkageAttribute
|
||||
// and other objects...
|
||||
// The display will then group all the attributes related to the link itself:
|
||||
// | Link_attr1 | link_attr2 | ... || Object_attr1 | Object_attr2 | Object_attr3 | .. | Object_attr_n |
|
||||
$aDisplayList = array();
|
||||
$aAttDefs = MetaModel::ListAttributeDefs($sClassName);
|
||||
assert(isset($aAttDefs[$sLinkageAttribute]));
|
||||
$oAttDef = $aAttDefs[$sLinkageAttribute];
|
||||
assert($oAttDef->IsExternalKey());
|
||||
// First display all the attributes specific to the link record
|
||||
foreach($aList as $sLinkAttCode)
|
||||
{
|
||||
$oLinkAttDef = $aAttDefs[$sLinkAttCode];
|
||||
if ((!$oLinkAttDef->IsExternalKey()) && (!$oLinkAttDef->IsExternalField()))
|
||||
{
|
||||
$aDisplayList[] = $sLinkAttCode;
|
||||
}
|
||||
}
|
||||
// Then display all the attributes neither specific to the link record nor to the 'linkage' object (because the latter are constant)
|
||||
foreach($aList as $sLinkAttCode)
|
||||
{
|
||||
$oLinkAttDef = $aAttDefs[$sLinkAttCode];
|
||||
if (($oLinkAttDef->IsExternalKey() && ($sLinkAttCode != $sLinkageAttribute))
|
||||
|| ($oLinkAttDef->IsExternalField() && ($oLinkAttDef->GetKeyAttCode() != $sLinkageAttribute)))
|
||||
{
|
||||
$aDisplayList[] = $sLinkAttCode;
|
||||
}
|
||||
}
|
||||
// First display all the attributes specific to the link
|
||||
// Then display all the attributes linked to the other end of the relationship
|
||||
$aList = $aDisplayList;
|
||||
}
|
||||
|
||||
$sSelectMode = 'none';
|
||||
if ($bSelectMode)
|
||||
{
|
||||
$sSelectMode = $bSingleSelectMode ? 'single' : 'multiple';
|
||||
}
|
||||
|
||||
$sClassAlias = $oSet->GetClassAlias();
|
||||
$bDisplayLimit = isset($aExtraParams['display_limit']) ? $aExtraParams['display_limit'] : true;
|
||||
|
||||
$sTableId = isset($aExtraParams['table_id']) ? $aExtraParams['table_id'] : null;
|
||||
$aClassAliases = array($sClassAlias => $sClassName);
|
||||
$oDataTable = new DataTable($iListId, $oSet, $aClassAliases, $sTableId);
|
||||
$oSettings = DataTableSettings::GetDataModelSettings($aClassAliases, $bViewLink, array($sClassAlias => $aList));
|
||||
|
||||
if ($bDisplayLimit)
|
||||
{
|
||||
$iDefaultPageSize = appUserPreferences::GetPref('default_page_size',
|
||||
MetaModel::GetConfig()->GetMinDisplayLimit());
|
||||
$oSettings->iDefaultPageSize = $iDefaultPageSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
$oSettings->iDefaultPageSize = 0;
|
||||
}
|
||||
$oSettings->aSortOrder = MetaModel::GetOrderByDefault($sClassName);
|
||||
|
||||
return $oDataTable->Display($oPage, $oSettings, $bDisplayMenu, $sSelectMode, $bViewLink, $aExtraParams);
|
||||
return $oDataTable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \WebPage $oPage
|
||||
* @param \CMDBObjectSet $oSet
|
||||
@@ -1265,6 +1143,7 @@ HTML
|
||||
* @throws \MissingQueryArgument
|
||||
* @throws \MySQLException
|
||||
* @throws \MySQLHasGoneAwayException
|
||||
* @deprecated since 3.0.0
|
||||
*/
|
||||
public static function GetDisplayExtendedSet(WebPage $oPage, CMDBObjectSet $oSet, $aExtraParams = array())
|
||||
{
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
use Combodo\iTop\Application\UI\Component\Button\ButtonFactory;
|
||||
use Combodo\iTop\Application\UI\Component\Toolbar\Toolbar;
|
||||
|
||||
use Combodo\iTop\Application\UI\Component\DataTable\DataTableSettings;
|
||||
|
||||
require_once(APPROOT.'application/dashboardlayout.class.inc.php');
|
||||
require_once(APPROOT.'application/dashlet.class.inc.php');
|
||||
require_once(APPROOT.'core/modelreflection.class.inc.php');
|
||||
|
||||
@@ -28,7 +28,7 @@ class DataTable
|
||||
protected $sTableId; // identifier for saving the settings (combined with the class aliases)
|
||||
protected $oSet; // The set of objects to display
|
||||
protected $aClassAliases; // The aliases (alias => class) inside the set
|
||||
protected $iNbObjects; // Total number of objects inthe set
|
||||
protected $iNbObjects; // Total number of objects in the set
|
||||
protected $bUseCustomSettings; // Whether or not the current display uses custom settings
|
||||
protected $oDefaultSettings; // the default settings for displaying such a list
|
||||
protected $bShowObsoleteData;
|
||||
@@ -211,7 +211,7 @@ class DataTable
|
||||
|
||||
return $sHtml;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* When refreshing the body of a paginated table, get the rows of the table (inside the TBODY)
|
||||
* return string The HTML rows to insert inside the <tbody> node
|
||||
@@ -525,6 +525,7 @@ EOF;
|
||||
return $aAttribs;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $aColumns
|
||||
* @param $sSelectMode
|
||||
@@ -872,396 +873,3 @@ class PrintableDataTable extends DataTable
|
||||
return $sHtml;
|
||||
}
|
||||
}
|
||||
|
||||
class DataTableSettings implements Serializable
|
||||
{
|
||||
public $aClassAliases;
|
||||
public $sTableId;
|
||||
public $iDefaultPageSize;
|
||||
public $aColumns;
|
||||
|
||||
|
||||
/**
|
||||
* DataTableSettings constructor.
|
||||
*
|
||||
* @param $aClassAliases
|
||||
* @param null $sTableId
|
||||
*/
|
||||
public function __construct($aClassAliases, $sTableId = null)
|
||||
{
|
||||
$this->aClassAliases = $aClassAliases;
|
||||
$this->sTableId = $sTableId;
|
||||
$this->iDefaultPageSize = 10;
|
||||
$this->aColumns = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $iDefaultPageSize
|
||||
* @param $aSortOrder
|
||||
* @param $aColumns
|
||||
*/
|
||||
protected function Init($iDefaultPageSize, $aSortOrder, $aColumns)
|
||||
{
|
||||
$this->iDefaultPageSize = $iDefaultPageSize;
|
||||
$this->aColumns = $aColumns;
|
||||
$this->FixVisibleColumns();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function serialize()
|
||||
{
|
||||
// Save only the 'visible' columns
|
||||
$aColumns = array();
|
||||
foreach($this->aClassAliases as $sAlias => $sClass)
|
||||
{
|
||||
$aColumns[$sAlias] = array();
|
||||
foreach($this->aColumns[$sAlias] as $sAttCode => $aData)
|
||||
{
|
||||
unset($aData['label']); // Don't save the display name
|
||||
unset($aData['alias']); // Don't save the alias (redundant)
|
||||
unset($aData['code']); // Don't save the code (redundant)
|
||||
if ($aData['checked'])
|
||||
{
|
||||
$aColumns[$sAlias][$sAttCode] = $aData;
|
||||
}
|
||||
}
|
||||
}
|
||||
return serialize(
|
||||
array(
|
||||
'iDefaultPageSize' => $this->iDefaultPageSize,
|
||||
'aColumns' => $aColumns,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sData
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function unserialize($sData)
|
||||
{
|
||||
$aData = unserialize($sData);
|
||||
$this->iDefaultPageSize = $aData['iDefaultPageSize'];
|
||||
$this->aColumns = $aData['aColumns'];
|
||||
foreach($this->aClassAliases as $sAlias => $sClass)
|
||||
{
|
||||
foreach($this->aColumns[$sAlias] as $sAttCode => $aData)
|
||||
{
|
||||
$aFieldData = false;
|
||||
if ($sAttCode == '_key_')
|
||||
{
|
||||
$aFieldData = $this->GetFieldData($sAlias, $sAttCode, null, true /* bChecked */, $aData['sort']);
|
||||
}
|
||||
else if (MetaModel::isValidAttCode($sClass, $sAttCode))
|
||||
{
|
||||
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
|
||||
$aFieldData = $this->GetFieldData($sAlias, $sAttCode, $oAttDef, true /* bChecked */, $aData['sort']);
|
||||
}
|
||||
|
||||
if ($aFieldData)
|
||||
{
|
||||
$this->aColumns[$sAlias][$sAttCode] = $aFieldData;
|
||||
}
|
||||
else
|
||||
{
|
||||
unset($this->aColumns[$sAlias][$sAttCode]);
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->FixVisibleColumns();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $aClassAliases
|
||||
* @param $bViewLink
|
||||
* @param $aDefaultLists
|
||||
*
|
||||
* @return \DataTableSettings
|
||||
* @throws \CoreException
|
||||
* @throws \DictExceptionMissingString
|
||||
*/
|
||||
public static function GetDataModelSettings($aClassAliases, $bViewLink, $aDefaultLists)
|
||||
{
|
||||
$oSettings = new DataTableSettings($aClassAliases);
|
||||
// Retrieve the class specific settings for each class/alias based on the 'list' ZList
|
||||
//TODO let the caller pass some other default settings (another Zlist, extre fields...)
|
||||
$aColumns = array();
|
||||
foreach ($aClassAliases as $sAlias => $sClass)
|
||||
{
|
||||
if ($aDefaultLists == null)
|
||||
{
|
||||
$aList = cmdbAbstract::FlattenZList(MetaModel::GetZListItems($sClass, 'list'));
|
||||
}
|
||||
else
|
||||
{
|
||||
$aList = $aDefaultLists[$sAlias];
|
||||
}
|
||||
|
||||
$aSortOrder = MetaModel::GetOrderByDefault($sClass);
|
||||
if ($bViewLink)
|
||||
{
|
||||
$sSort = 'none';
|
||||
if(array_key_exists('friendlyname', $aSortOrder))
|
||||
{
|
||||
$sSort = $aSortOrder['friendlyname'] ? 'asc' : 'desc';
|
||||
}
|
||||
$sNormalizedFName = MetaModel::NormalizeFieldSpec($sClass, 'friendlyname');
|
||||
if(array_key_exists($sNormalizedFName, $aSortOrder))
|
||||
{
|
||||
$sSort = $aSortOrder[$sNormalizedFName] ? 'asc' : 'desc';
|
||||
}
|
||||
|
||||
$aColumns[$sAlias]['_key_'] = $oSettings->GetFieldData($sAlias, '_key_', null, true /* bChecked */, $sSort);
|
||||
}
|
||||
foreach($aList as $sAttCode)
|
||||
{
|
||||
$sSort = 'none';
|
||||
if(array_key_exists($sAttCode, $aSortOrder))
|
||||
{
|
||||
$sSort = $aSortOrder[$sAttCode] ? 'asc' : 'desc';
|
||||
}
|
||||
$oAttDef = Metamodel::GetAttributeDef($sClass, $sAttCode);
|
||||
$aFieldData = $oSettings->GetFieldData($sAlias, $sAttCode, $oAttDef, true /* bChecked */, $sSort);
|
||||
if ($aFieldData) $aColumns[$sAlias][$sAttCode] = $aFieldData;
|
||||
}
|
||||
}
|
||||
$iDefaultPageSize = appUserPreferences::GetPref('default_page_size', MetaModel::GetConfig()->GetMinDisplayLimit());
|
||||
$oSettings->Init($iDefaultPageSize, $aSortOrder, $aColumns);
|
||||
return $oSettings;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \CoreException
|
||||
*/
|
||||
protected function FixVisibleColumns()
|
||||
{
|
||||
foreach($this->aClassAliases as $sAlias => $sClass)
|
||||
{
|
||||
if (!isset($this->aColumns[$sAlias]))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
foreach($this->aColumns[$sAlias] as $sAttCode => $aData)
|
||||
{
|
||||
// Remove non-existent columns
|
||||
// TODO: check if the existing ones are still valid (in case their type changed)
|
||||
if (($sAttCode != '_key_') && (!MetaModel::IsValidAttCode($sClass, $sAttCode)))
|
||||
{
|
||||
unset($this->aColumns[$sAlias][$sAttCode]);
|
||||
}
|
||||
}
|
||||
$aList = MetaModel::ListAttributeDefs($sClass);
|
||||
|
||||
// Add the other (non visible ones), sorted in alphabetical order
|
||||
$aTempData = array();
|
||||
foreach($aList as $sAttCode => $oAttDef)
|
||||
{
|
||||
if ( (!array_key_exists($sAttCode, $this->aColumns[$sAlias])) && (!($oAttDef instanceof AttributeLinkedSet || $oAttDef instanceof AttributeDashboard)))
|
||||
{
|
||||
$aFieldData = $this->GetFieldData($sAlias, $sAttCode, $oAttDef, false /* bChecked */, 'none');
|
||||
if ($aFieldData) $aTempData[$aFieldData['label']] = $aFieldData;
|
||||
}
|
||||
}
|
||||
ksort($aTempData);
|
||||
foreach($aTempData as $sLabel => $aFieldData)
|
||||
{
|
||||
$this->aColumns[$sAlias][$aFieldData['code']] = $aFieldData;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $aClassAliases
|
||||
* @param null $sTableId
|
||||
* @param bool $bOnlyOnTable
|
||||
*
|
||||
* @return \DataTableSettings|null
|
||||
* @throws \Exception
|
||||
*/
|
||||
static public function GetTableSettings($aClassAliases, $sTableId = null, $bOnlyOnTable = false)
|
||||
{
|
||||
$pref = null;
|
||||
$oSettings = new DataTableSettings($aClassAliases, $sTableId);
|
||||
|
||||
if ($sTableId != null)
|
||||
{
|
||||
// An identified table, let's fetch its own settings (if any)
|
||||
$pref = appUserPreferences::GetPref($oSettings->GetPrefsKey($sTableId), null);
|
||||
}
|
||||
|
||||
if ($pref == null)
|
||||
{
|
||||
if (!$bOnlyOnTable)
|
||||
{
|
||||
// Try the global preferred values for this class / set of classes
|
||||
$pref = appUserPreferences::GetPref($oSettings->GetPrefsKey(null), null);
|
||||
}
|
||||
if ($pref == null)
|
||||
{
|
||||
// no such settings, use the default values provided by the data model
|
||||
return null;
|
||||
}
|
||||
}
|
||||
$oSettings->unserialize($pref);
|
||||
|
||||
return $oSettings;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function GetSortOrder()
|
||||
{
|
||||
$aSortOrder = array();
|
||||
foreach($this->aColumns as $sAlias => $aColumns)
|
||||
{
|
||||
foreach($aColumns as $aColumn)
|
||||
{
|
||||
if ($aColumn['sort'] != 'none')
|
||||
{
|
||||
$sCode = ($aColumn['code'] == '_key_') ? 'friendlyname' : $aColumn['code'];
|
||||
$aSortOrder[$sCode] = ($aColumn['sort']=='asc'); // true for ascending, false for descending
|
||||
}
|
||||
}
|
||||
break; // TODO: For now the Set object supports only sorting on the first class of the set
|
||||
}
|
||||
return $aSortOrder;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param null $sTargetTableId
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function Save($sTargetTableId = null)
|
||||
{
|
||||
$sSaveId = is_null($sTargetTableId) ? $this->sTableId : $sTargetTableId;
|
||||
if ($sSaveId == null) return false; // Cannot save, the table is not identified, use SaveAsDefault instead
|
||||
|
||||
$sSettings = $this->serialize();
|
||||
appUserPreferences::SetPref($this->GetPrefsKey($sSaveId), $sSettings);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function SaveAsDefault()
|
||||
{
|
||||
$sSettings = $this->serialize();
|
||||
appUserPreferences::SetPref($this->GetPrefsKey(null), $sSettings);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Clear the preferences for this particular table
|
||||
* @param $bResetAll boolean If true,the settings for all tables of the same class(es)/alias(es) are reset
|
||||
*/
|
||||
public function ResetToDefault($bResetAll)
|
||||
{
|
||||
if (($this->sTableId == null) && (!$bResetAll)) return false; // Cannot reset, the table is not identified, use force $bResetAll instead
|
||||
if ($bResetAll)
|
||||
{
|
||||
// Turn the key into a suitable PCRE pattern
|
||||
$sKey = $this->GetPrefsKey(null);
|
||||
$sPattern = str_replace(array('|'), array('\\|'), $sKey); // escape the | character
|
||||
$sPattern = '#^'.str_replace(array('*'), array('.*'), $sPattern).'$#'; // Don't use slash as the delimiter since it's used in our key to delimit aliases
|
||||
appUserPreferences::UnsetPref($sPattern, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
appUserPreferences::UnsetPref($this->GetPrefsKey($this->sTableId), false);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param null $sTableId
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function GetPrefsKey($sTableId = null)
|
||||
{
|
||||
return static::GetAppUserPreferenceKey($this->aClassAliases, $sTableId);
|
||||
}
|
||||
|
||||
public static function GetAppUserPreferenceKey($aClassAliases, $sTableId)
|
||||
{
|
||||
if ($sTableId === null)
|
||||
{
|
||||
$sTableId = '*';
|
||||
}
|
||||
|
||||
$aKeys = array();
|
||||
foreach($aClassAliases as $sAlias => $sClass)
|
||||
{
|
||||
$aKeys[] = $sAlias.'-'.$sClass;
|
||||
}
|
||||
return implode('/', $aKeys).'|'.$sTableId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $sAlias
|
||||
* @param $sAttCode
|
||||
* @param $oAttDef
|
||||
* @param $bChecked
|
||||
* @param $sSort
|
||||
*
|
||||
* @return array|bool
|
||||
* @throws \CoreException
|
||||
* @throws \DictExceptionMissingString
|
||||
*/
|
||||
protected function GetFieldData($sAlias, $sAttCode, $oAttDef, $bChecked, $sSort)
|
||||
{
|
||||
$ret = false;
|
||||
if ($sAttCode == '_key_')
|
||||
{
|
||||
$sLabel = Dict::Format('UI:ExtKey_AsLink', MetaModel::GetName($this->aClassAliases[$sAlias]));
|
||||
$ret = array(
|
||||
'label' => $sLabel,
|
||||
'checked' => true,
|
||||
'disabled' => true,
|
||||
'alias' => $sAlias,
|
||||
'code' => $sAttCode,
|
||||
'sort' => $sSort,
|
||||
);
|
||||
}
|
||||
else if (!$oAttDef->IsLinkSet())
|
||||
{
|
||||
$sLabel = $oAttDef->GetLabel();
|
||||
if ($oAttDef->IsExternalKey())
|
||||
{
|
||||
$sLabel = Dict::Format('UI:ExtKey_AsLink', $oAttDef->GetLabel());
|
||||
}
|
||||
else if ($oAttDef->IsExternalField())
|
||||
{
|
||||
if ($oAttDef->IsFriendlyName())
|
||||
{
|
||||
$sLabel = Dict::Format('UI:ExtKey_AsFriendlyName', $oAttDef->GetLabel());
|
||||
}
|
||||
else
|
||||
{
|
||||
$oExtAttDef = $oAttDef->GetExtAttDef();
|
||||
$sLabel = Dict::Format('UI:ExtField_AsRemoteField', $oAttDef->GetLabel(), $oExtAttDef->GetLabel());
|
||||
}
|
||||
}
|
||||
elseif ($oAttDef instanceof AttributeFriendlyName)
|
||||
{
|
||||
$sLabel = Dict::Format('UI:ExtKey_AsFriendlyName', $oAttDef->GetLabel());
|
||||
}
|
||||
$ret = array(
|
||||
'label' => $sLabel,
|
||||
'checked' => $bChecked,
|
||||
'disabled' => false,
|
||||
'alias' => $sAlias,
|
||||
'code' => $sAttCode,
|
||||
'sort' => $sSort,
|
||||
);
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
use Combodo\iTop\Application\UI\Component\Badge\BadgeFactory;
|
||||
use Combodo\iTop\Application\UI\Component\Button\ButtonFactory;
|
||||
use Combodo\iTop\Application\UI\Component\Dashlet\DashletFactory;
|
||||
use Combodo\iTop\Application\UI\Component\DataTable\DataTableFactory;
|
||||
use Combodo\iTop\Application\UI\Component\Html\Html;
|
||||
use Combodo\iTop\Application\UI\Component\Toolbar\Toolbar;
|
||||
use Combodo\iTop\Application\UI\iUIBlock;
|
||||
@@ -238,18 +239,15 @@ class DisplayBlock
|
||||
$sFilter = addslashes($this->m_oFilter->serialize(false, $aQueryParams)); // Used either for asynchronous or auto_reload
|
||||
if (!$this->m_bAsynchronous) {
|
||||
// render now
|
||||
$oHtml->AddHtml("<div id=\"$sId\" class=\"display_block\" >\n");
|
||||
try {
|
||||
$oHtml->AddSubBlock($this->GetRenderContent($oPage, $aExtraParams, $sId));
|
||||
} catch (Exception $e) {
|
||||
IssueLog::Error('Exception during GetDisplay: '.$e->getMessage());
|
||||
}
|
||||
$oHtml->AddHtml("</div>\n");
|
||||
} else {
|
||||
// render it as an Ajax (asynchronous) call
|
||||
$oHtml->AddHtml("<div id=\"$sId\" class=\"display_block loading\">\n");
|
||||
$oHtml->AddCSSClasses("display_block loading");
|
||||
$oHtml->AddHtml($oPage->GetP("<img src=\"../images/indicator_arrows.gif\"> ".Dict::S('UI:Loading')));
|
||||
$oHtml->AddHtml("</div>\n");
|
||||
$oPage->add_script('
|
||||
$.post("ajax.render.php?style='.$this->m_sStyle.'",
|
||||
{ operation: "ajax", filter: "'.$sFilter.'", extra_params: "'.$sExtraParams.'" },
|
||||
@@ -573,7 +571,16 @@ class DisplayBlock
|
||||
$index++;
|
||||
}
|
||||
$oSet = new CMDBObjectSet($oBlockFilter, array(), $aArgs);
|
||||
$sHtml .= "<tr><td>".cmdbAbstractObject::GetDisplayExtendedSet($oPage, $oSet, $aExtraParams)."</td></tr>\n";
|
||||
if (empty($aExtraParams['currentId']))
|
||||
{
|
||||
$iListId = $oPage->GetUniqueId(); // Works only if not in an Ajax page !!
|
||||
}
|
||||
else
|
||||
{
|
||||
$iListId = $aExtraParams['currentId'];
|
||||
}
|
||||
$oBlock = DataTableFactory::MakeForRendering( $iListId, $this->m_oSet, $aExtraParams);
|
||||
$sHtml .= "<tr><td>".render_block($oBlock)."</td></tr>\n";
|
||||
}
|
||||
}
|
||||
$sHtml .= "</table>\n";
|
||||
@@ -599,7 +606,15 @@ class DisplayBlock
|
||||
{
|
||||
if($this->m_oSet->CountWithLimit(1) > 0)
|
||||
{
|
||||
$sHtml .= cmdbAbstractObject::GetDisplayExtendedSet($oPage, $this->m_oSet, $aExtraParams);
|
||||
if (empty($aExtraParams['currentId']))
|
||||
{
|
||||
$iListId = $oPage->GetUniqueId(); // Works only if not in an Ajax page !!
|
||||
}
|
||||
else
|
||||
{
|
||||
$iListId = $aExtraParams['currentId'];
|
||||
}
|
||||
$oBlock = DataTableFactory::MakeForObject($oPage, $iListId, $this->m_oSet, $aExtraParams);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -618,7 +633,7 @@ class DisplayBlock
|
||||
// The list is made of only 1 class of objects, actions on the list are possible
|
||||
if ( ($this->m_oSet->CountWithLimit(1)> 0) && (UserRights::IsActionAllowed($this->m_oSet->GetClass(), UR_ACTION_READ, $this->m_oSet) == UR_ALLOWED_YES) )
|
||||
{
|
||||
$sHtml .= cmdbAbstractObject::GetDisplaySet($oPage, $this->m_oSet, $aExtraParams);
|
||||
$oBlock = cmdbAbstractObject::GetDisplaySetBlock($oPage, $this->m_oSet, $aExtraParams);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -784,10 +799,9 @@ class DisplayBlock
|
||||
case 'search':
|
||||
if (!$oPage->IsPrintableVersion())
|
||||
{
|
||||
$sHtml .= "<div id=\"ds_$sId\" class=\"search_box\">\n";
|
||||
$aExtraParams['currentId'] = $sId;
|
||||
$sHtml .= cmdbAbstractObject::GetSearchForm($oPage, $this->m_oSet, $aExtraParams);
|
||||
$sHtml .= "</div>\n";
|
||||
$oSearchForm = new \Combodo\iTop\Application\Search\SearchForm();
|
||||
$oBlock = $oSearchForm->GetSearchFormUIBlock($oPage, $this->m_oSet, $aExtraParams);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1800,7 +1814,7 @@ class MenuBlock extends DisplayBlock
|
||||
}
|
||||
if ($bToolkitMenu) {
|
||||
$sLabel = Dict::S('UI:ConfigureThisList');
|
||||
$aActions['iTop::ConfigureList'] = ['label' => $sLabel, 'url' => '#', 'onclick' => "$('#datatable_dlg_{$sId}').dialog('open');"];
|
||||
$aActions['iTop::ConfigureList'] = ['label' => $sLabel, 'url' => '#', 'onclick' => "$('#datatable_dlg_datatable_{$sId}').dialog('open');"];
|
||||
utils::GetPopupMenuItems($oPage, iPopupMenuExtension::MENU_OBJLIST_TOOLKIT, $param, $aActions);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
use Combodo\iTop\Application\UI\Component\DataTable\DataTableSettings;
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -184,7 +184,7 @@ class UILinksWidgetDirect
|
||||
// For security reasons: check that the "proposed" class is actually a subclass of the linked class
|
||||
// and that the current user is allowed to create objects of this class
|
||||
$sRealClass = '';
|
||||
$oPage->add('<div class="wizContainer" style="vertical-align:top;"><div>');
|
||||
//$oPage->add('<div class="wizContainer" style="vertical-align:top;"><div>');
|
||||
$aSubClasses = MetaModel::EnumChildClasses($this->sLinkedClass, ENUM_CHILD_CLASSES_ALL); // Including the specified class itself
|
||||
$aPossibleClasses = array();
|
||||
foreach($aSubClasses as $sCandidateClass)
|
||||
@@ -294,7 +294,7 @@ class UILinksWidgetDirect
|
||||
*/
|
||||
public function GetObjectsSelectionDlg($oPage, $oCurrentObj, $aAlreadyLinked, $aPrefillFormParam = array())
|
||||
{
|
||||
$oPage->add("<div class=\"wizContainer\" style=\"vertical-align:top;\">\n");
|
||||
//$oPage->add("<div class=\"wizContainer\" style=\"vertical-align:top;\">\n");
|
||||
|
||||
$oHiddenFilter = new DBObjectSearch($this->sLinkedClass);
|
||||
if (($oCurrentObj != null) && MetaModel::IsSameFamilyBranch($this->sLinkedClass, $this->sClass)) {
|
||||
@@ -355,7 +355,6 @@ class UILinksWidgetDirect
|
||||
<input type="hidden" id="count_{$this->sInputid}" value="0"/>
|
||||
<button type="button" class="cancel">{$sCancel}</button> <button type="button" class="ok" disabled="disabled">{$sAdd}</button>
|
||||
</form>
|
||||
</div>
|
||||
HTML
|
||||
);
|
||||
}
|
||||
|
||||
@@ -368,7 +368,8 @@ JS
|
||||
protected function DisplayFormTable(WebPage $oP, $aConfig, $aData)
|
||||
{
|
||||
$sHtml = "<input type=\"hidden\" name=\"attr_{$this->m_sAttCode}{$this->m_sNameSuffix}\" value=\"\">";
|
||||
$sHtml .= "<table class=\"listResults\">\n";
|
||||
$sHtml .= "<table class=\"listResults\" id='dt_{$this->m_sAttCode}{$this->m_sNameSuffix}' width='100%'>\n";
|
||||
$oP->add_ready_script("$('#dt_{$this->m_sAttCode}{$this->m_sNameSuffix}').DataTable({\"language\": {\"emptyTable\": \"".str_replace("\"","\\\"",Dict::S('UI:Message:EmptyList:UseAdd'))."\"},search:false});");
|
||||
// Header
|
||||
$sHtml .= "<thead>\n";
|
||||
$sHtml .= "<tr>\n";
|
||||
@@ -391,11 +392,11 @@ JS
|
||||
{
|
||||
$sHtml .= $this->DisplayFormRow($oP, $aConfig, $aRow, $iRowId);
|
||||
}
|
||||
$sHtml .= "<tr $sEmptyRowStyle id=\"{$this->m_sAttCode}{$this->m_sNameSuffix}_empty_row\"><td colspan=\"".count($aConfig)."\" style=\"text-align:center;\">".Dict::S('UI:Message:EmptyList:UseAdd')."</td></tr>";
|
||||
//$sHtml .= "<tr $sEmptyRowStyle id=\"{$this->m_sAttCode}{$this->m_sNameSuffix}_empty_row\"><td colspan=\"".count($aConfig)."\" style=\"text-align:center;\">".Dict::S('UI:Message:EmptyList:UseAdd')."</td></tr>";
|
||||
$sHtml .= "</tbody>\n";
|
||||
|
||||
// Footer
|
||||
$sHtml .= "</table>\n";
|
||||
$sHtml .= "</table></br>\n";
|
||||
|
||||
return $sHtml;
|
||||
}
|
||||
@@ -463,6 +464,7 @@ JS
|
||||
$aForm[$key] = $this->GetFormRow($oPage, $oLinkedObj, $oCurrentLink, $aArgs, $oCurrentObj, $key, $bReadOnly);
|
||||
}
|
||||
$sHtmlValue .= $this->DisplayFormTable($oPage, $this->m_aTableConfig, $aForm);
|
||||
// To prevent adding forms inside the main form
|
||||
|
||||
$sHtmlValue .= "<span style=\"float:left;\"> <img src=\"../images/tv-item-last.gif\"> <input id=\"{$this->m_sAttCode}{$this->m_sNameSuffix}_btnRemove\" type=\"button\" value=\"".Dict::S('UI:RemoveLinkedObjectsOf_Class')."\" onClick=\"oWidget{$this->m_iInputId}.RemoveSelected();\" >";
|
||||
$sHtmlValue .= " <input id=\"{$this->m_sAttCode}{$this->m_sNameSuffix}_btnAdd\" type=\"button\" value=\"".Dict::Format('UI:AddLinkedObjectsOf_Class', MetaModel::GetName($this->m_sRemoteClass))."\" onClick=\"oWidget{$this->m_iInputId}.AddObjects();\"><span id=\"{$this->m_sAttCode}{$this->m_sNameSuffix}_indicatorAdd\"></span></span>\n";
|
||||
@@ -513,7 +515,7 @@ JS
|
||||
*/
|
||||
public function GetObjectPickerDialog($oPage, $oCurrentObj, $sJson, $aAlreadyLinkedIds = array(), $aPrefillFormParam = array())
|
||||
{
|
||||
$oPage->add("<div class=\"wizContainer\" style=\"vertical-align:top;\">\n");
|
||||
//$oPage->add("<div class=\"wizContainer\" style=\"vertical-align:top;\">\n");
|
||||
|
||||
$oAlreadyLinkedFilter = new DBObjectSearch($this->m_sRemoteClass);
|
||||
if (!$this->m_bDuplicatesAllowed && count($aAlreadyLinkedIds) > 0) {
|
||||
@@ -555,14 +557,13 @@ JS
|
||||
<div style="background: #fff; border:0; text-align:center; vertical-align:middle;"><p>{$sEmptyList}</p></div>
|
||||
</div>
|
||||
<input type="hidden" id="count_{$this->m_sAttCode}{$this->m_sNameSuffix}" value="0"/>
|
||||
<input type="button" value="{$sCancel}" onClick="$('#dlg_{$this->m_sAttCode}{$this->m_sNameSuffix}').dialog('close');"> <input id="btn_ok_{$this->m_sAttCode}{$this->m_sNameSuffix}" disabled="disabled" type="button" onclick="return oWidget{$this->m_iInputId}.DoAddObjects(this.id);" value="{$sAdd}">
|
||||
<input type="button" value="{$sCancel}" onClick="$('#dlg_{$this->m_sAttCode}{$this->m_sNameSuffix}').dialog('close');">
|
||||
<input id="btn_ok_add_{$this->m_sAttCode}{$this->m_sNameSuffix}" disabled="disabled" type="button" onclick="return oWidget{$this->m_iInputId}.DoAddObjects(this.id);" value="{$sAdd}">
|
||||
</form>
|
||||
</div>
|
||||
HTML
|
||||
);
|
||||
|
||||
$oPage->add_ready_script("$('#dlg_{$this->m_sAttCode}{$this->m_sNameSuffix}').dialog({ width: $(window).width()*0.8, height: $(window).height()*0.8, autoOpen: false, modal: true, resizeStop: oWidget{$this->m_iInputId}.UpdateSizes });");
|
||||
$oPage->add_ready_script("$('#dlg_{$this->m_sAttCode}{$this->m_sNameSuffix}').dialog('option', {title:'".addslashes(Dict::Format('UI:AddObjectsOf_Class_LinkedWith_Class', MetaModel::GetName($this->m_sLinkedClass), MetaModel::GetName($this->m_sClass)))."'});");
|
||||
$oPage->add_ready_script("$('#dlg_{$this->m_sAttCode}{$this->m_sNameSuffix}').dialog({ width: $(window).width()*0.8, height: $(window).height()*0.8, title:'".addslashes(Dict::Format('UI:AddObjectsOf_Class_LinkedWith_Class', MetaModel::GetName($this->m_sLinkedClass), MetaModel::GetName($this->m_sClass)))."' , autoOpen: false, modal: true, resizeStop: oWidget{$this->m_iInputId}.UpdateSizes });");
|
||||
$oPage->add_ready_script("$('#SearchFormToAdd_{$this->m_sAttCode}{$this->m_sNameSuffix} form').bind('submit.uilinksWizard', oWidget{$this->m_iInputId}.SearchObjectsToAdd);");
|
||||
$oPage->add_ready_script("$('#SearchFormToAdd_{$this->m_sAttCode}{$this->m_sNameSuffix}').resize(oWidget{$this->m_iInputId}.UpdateSizes);");
|
||||
}
|
||||
|
||||
@@ -40,7 +40,6 @@ class UISearchFormForeignKeys
|
||||
*/
|
||||
public function ShowModalSearchForeignKeys($oPage, $sTitle)
|
||||
{
|
||||
$oPage->add("<div class=\"wizContainer\" style=\"vertical-align:top;\">\n");
|
||||
|
||||
$oFilter = new DBObjectSearch($this->m_sRemoteClass);
|
||||
|
||||
@@ -65,9 +64,9 @@ class UISearchFormForeignKeys
|
||||
<div style="background: #fff; border:0; text-align:center; vertical-align:middle;"><p>{$sEmptyList}</p></div>
|
||||
</div>
|
||||
<input type="hidden" id="count_{$this->m_iInputId}" value="0"/>
|
||||
<input type="button" value="{$sCancel}" onClick="$('#dlg_{$this->m_iInputId}').dialog('close');"> <input id="btn_ok_{$this->m_iInputId}" disabled="disabled" type="button" onclick="return oForeignKeysWidget{$this->m_iInputId}.DoAddObjects(this.id);" value="{$sAdd}">
|
||||
<input type="button" value="{$sCancel}" onClick="$('#dlg_{$this->m_iInputId}').dialog('close');">
|
||||
<input id="btn_ok_add_{$this->m_iInputId}" disabled="disabled" type="button" onclick="return oForeignKeysWidget{$this->m_iInputId}.DoAddObjects(this.id);" value="{$sAdd}">
|
||||
</form>
|
||||
</div>
|
||||
HTML
|
||||
);
|
||||
|
||||
|
||||
@@ -1273,6 +1273,15 @@ abstract class AttributeDefinition
|
||||
{
|
||||
return (string)$value;
|
||||
}
|
||||
|
||||
/*
|
||||
* return string
|
||||
*/
|
||||
public function GetRenderForDataTable(string $sClassAlias) :string
|
||||
{
|
||||
$sRenderFunction = "return data;";
|
||||
return $sRenderFunction;
|
||||
}
|
||||
}
|
||||
|
||||
class AttributeDashboard extends AttributeDefinition
|
||||
@@ -4906,6 +4915,11 @@ class AttributeEmailAddress extends AttributeString
|
||||
|
||||
return '<a class="mailto" href="mailto:'.$sValue.'"><span class="text_decoration '.$sUrlDecorationClass.'"></span>'.parent::GetAsHTML($sValue).'</a>';
|
||||
}
|
||||
public function GetRenderForDataTable(string $sClassAlias) :string
|
||||
{
|
||||
$sRenderFunction = "return '<a class=\'mailto\' href= \'mailto:'+data+'\'><span class=\'fas fa-envelope\'></span> '+data+'</a>' ;";
|
||||
return $sRenderFunction;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -4992,6 +5006,12 @@ class AttributePhoneNumber extends AttributeString
|
||||
|
||||
return '<a class="tel" href="'.$sUrl.'"><span class="text_decoration '.$sUrlDecorationClass.'"></span>'.parent::GetAsHTML($sValue).'</a>';
|
||||
}
|
||||
|
||||
public function GetRenderForDataTable(string $sClassAlias) :string
|
||||
{
|
||||
$sRenderFunction = "return '<a class=\'tel\' href= \'tel:'+data+'\'><span class=\'fas fa-phone\'></span> '+data+'</a>' ;";
|
||||
return $sRenderFunction;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -6781,6 +6801,12 @@ class AttributeExternalKey extends AttributeDBFieldVoid
|
||||
|
||||
return DBObject::MakeHyperLink($this->GetTargetClass(), $sValue);
|
||||
}
|
||||
|
||||
public function GetRenderForDataTable(string $sClassAlias) :string
|
||||
{
|
||||
$sRenderFunction = "return '<a class=\'object-ref-link\' href= \'UI.php?operation=details&class=".$this->m_aParams['targetclass']."&id='+data+'\'>'+row['".$sClassAlias."/".$this->m_sCode."_friendlyname']+'</a>' ;";
|
||||
return $sRenderFunction;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
@import "input/all";
|
||||
|
||||
@import "title";
|
||||
@import "datatable";
|
||||
@import "form";
|
||||
@import "fieldset";
|
||||
@import "field";
|
||||
|
||||
85
css/backoffice/components/_datatable.scss
Normal file
@@ -0,0 +1,85 @@
|
||||
.ibo-datatable {
|
||||
padding-bottom: 2em;
|
||||
padding-top: 2em;
|
||||
|
||||
thead tr th, tbody tr td {
|
||||
line-height: 30px;
|
||||
padding-right: 1em;
|
||||
padding-left: 1em;
|
||||
@extend %ibo-font-ral-nor-100;
|
||||
|
||||
a {
|
||||
color: $ibo-color-primary-600;
|
||||
}
|
||||
}
|
||||
|
||||
tbody tr:nth-child(odd) {
|
||||
background-color: $ibo-color-secondary-500;
|
||||
}
|
||||
}
|
||||
.dataTables_length
|
||||
{
|
||||
position: relative;
|
||||
float: right;
|
||||
padding-top: 0.755em;
|
||||
padding-right: 0.5em;
|
||||
}
|
||||
.dataTables_info
|
||||
{
|
||||
position: relative;
|
||||
float: right;
|
||||
padding-top: 0.755em;
|
||||
padding-right: 2em;
|
||||
padding-left: 0em;
|
||||
}
|
||||
.select-info{
|
||||
padding-left: 2em;
|
||||
}
|
||||
|
||||
.pagination
|
||||
{
|
||||
left: 1.21%;
|
||||
right: 1.21%;
|
||||
top: 91.58%;
|
||||
bottom: 4.85%;
|
||||
.paginate_button {
|
||||
margin-left: 1em;
|
||||
margin-right: 1em;
|
||||
}
|
||||
}
|
||||
.dataTables_paginate
|
||||
{
|
||||
/* position: relative;*/
|
||||
float: left;
|
||||
padding-top: 0.755em;
|
||||
padding-left: 2em;
|
||||
}
|
||||
.paginate_button {
|
||||
box-sizing: border-box;
|
||||
display: inline-block;
|
||||
}
|
||||
.paginate_button a{
|
||||
color: $ibo-color-grey-800;
|
||||
@extend %ibo-font-ral-nor-100;
|
||||
}
|
||||
.paginate_button a:hover {
|
||||
color: $ibo-color-blue-grey-200;
|
||||
}
|
||||
.paginate_button.active a {
|
||||
color: $ibo-color-grey-900;
|
||||
border: 2px solid var(--ibo-color-grey-300);
|
||||
background-color: $ibo-color-grey-200;
|
||||
}
|
||||
.ibo-datatable-toolbar {
|
||||
/*position: relative;*/
|
||||
height: 30px;
|
||||
}
|
||||
.ibo-criterion-area{
|
||||
font-size: $ibo-font-size-50 ;
|
||||
}
|
||||
.ibo-search-form{
|
||||
padding-top: $ibo-panel--spacing-top ;
|
||||
}
|
||||
.ibo-form-group{
|
||||
position: fixed;
|
||||
}
|
||||
@@ -79,4 +79,30 @@ $ibo-title--status-dot--border-radius: $ibo-border-radius-full !default;
|
||||
color: map-get($aColors, 'secondary-color');
|
||||
background-color: map-get($aColors, 'primary-color');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
.ibo-title-for-dashlet {
|
||||
padding-top: 2em;
|
||||
}
|
||||
.ibo-title-for-dashlet--title {
|
||||
@extend %ibo-font-ral-nor-350;
|
||||
}
|
||||
|
||||
.ibo-title-for-dashlet--content{
|
||||
background-color: $ibo-color-white-100;
|
||||
border-radius: 5px;
|
||||
border: 1px solid ;
|
||||
border-color:$ibo-color-grey-400;
|
||||
padding-bottom:1em;
|
||||
}
|
||||
.ibo-title-separator{
|
||||
border-radius: 5px 5px 0px 0px;
|
||||
border-color:$ibo-color-blue-600;
|
||||
color:$ibo-color-blue-600;
|
||||
background-color:$ibo-color-blue-600;
|
||||
border: 3px solid ;
|
||||
margin:0;
|
||||
padding:0;
|
||||
}
|
||||
@@ -93,66 +93,66 @@
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
table.datatable {
|
||||
width: 100%;
|
||||
border: 0;
|
||||
padding: 0;
|
||||
}
|
||||
//table.datatable {
|
||||
// width: 100%;
|
||||
// border: 0;
|
||||
// padding: 0;
|
||||
//}
|
||||
|
||||
td.menucontainer {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
table.listResults {
|
||||
padding: 0px;
|
||||
border-top: 3px solid $frame-background-color;
|
||||
border-left: 3px solid $frame-background-color;
|
||||
border-bottom: 3px solid #e6e6e1;
|
||||
border-right: 3px solid #e6e6e1;
|
||||
width: 100%;
|
||||
background-color: $white;
|
||||
}
|
||||
//table.listResults {
|
||||
// padding: 0px;
|
||||
// border-top: 3px solid $frame-background-color;
|
||||
// border-left: 3px solid $frame-background-color;
|
||||
// border-bottom: 3px solid #e6e6e1;
|
||||
// border-right: 3px solid #e6e6e1;
|
||||
// width: 100%;
|
||||
// background-color: $white;
|
||||
//}
|
||||
|
||||
table.listResults td {
|
||||
padding: 2px;
|
||||
}
|
||||
//table.listResults td {
|
||||
// padding: 2px;
|
||||
//}
|
||||
|
||||
table.listResults td .view-image {
|
||||
//table.listResults td .view-image {
|
||||
// Counteract the forced dimensions (usefull for displaying in the details view)
|
||||
width: inherit !important;
|
||||
height: inherit !important;
|
||||
// width: inherit !important;
|
||||
// height: inherit !important;
|
||||
|
||||
img {
|
||||
max-width: 48px !important;
|
||||
max-height: 48px !important;
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
}
|
||||
// img {
|
||||
// max-width: 48px !important;
|
||||
// max-height: 48px !important;
|
||||
// display: block;
|
||||
// margin-left: auto;
|
||||
// margin-right: auto;
|
||||
// }
|
||||
//}
|
||||
|
||||
table.listResults > tbody > tr.selected > * {
|
||||
}
|
||||
//table.listResults > tbody > tr.selected > * {
|
||||
//}
|
||||
|
||||
table.listResults > tbody > tr > * {
|
||||
transition: background-color 400ms linear;
|
||||
}
|
||||
//table.listResults > tbody > tr > * {
|
||||
// transition: background-color 400ms linear;
|
||||
//}
|
||||
|
||||
table.listResults > tbody > tr:hover > * {
|
||||
cursor: pointer;
|
||||
}
|
||||
//table.listResults > tbody > tr:hover > * {
|
||||
// cursor: pointer;
|
||||
//}
|
||||
|
||||
table.listResults > tbody > tr.selected:hover > * {
|
||||
//table.listResults > tbody > tr.selected:hover > * {
|
||||
/* hover on lines is currently done toggling td.hover, and having a rule for links */
|
||||
background-color: $brand-primary-lightest;
|
||||
color: $text-color;
|
||||
}
|
||||
// background-color: $brand-primary-lightest;
|
||||
// color: $text-color;
|
||||
//}
|
||||
|
||||
table.listResults > tbody > tr:hover > * {
|
||||
//table.listResults > tbody > tr:hover > * {
|
||||
/* hover on lines is currently done toggling td.hover, and having a rule for links */
|
||||
background-color: $table-hover-background;
|
||||
color: $text-color;
|
||||
}
|
||||
// background-color: $table-hover-background;
|
||||
// color: $text-color;
|
||||
//}
|
||||
|
||||
.edit-image {
|
||||
.view-image {
|
||||
@@ -278,13 +278,13 @@
|
||||
color: $text-color;
|
||||
}
|
||||
|
||||
th {
|
||||
font-family: Tahoma, Verdana, Arial, Helvetica;
|
||||
font-size: 8pt;
|
||||
color: $complement-color;
|
||||
height: 20px;
|
||||
background: $frame-background-color bottom repeat-x;
|
||||
}
|
||||
//th {
|
||||
// font-family: Tahoma, Verdana, Arial, Helvetica;
|
||||
// font-size: 8pt;
|
||||
// color: $complement-color;
|
||||
// height: 20px;
|
||||
// background: $frame-background-color bottom repeat-x;
|
||||
//}
|
||||
|
||||
th.header {
|
||||
cursor: pointer;
|
||||
@@ -986,14 +986,14 @@
|
||||
}
|
||||
|
||||
.search_form_handler {
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
width: 100%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
font-size: 12px;
|
||||
text-align: left; /* To compensate .search_box:text-align */
|
||||
border: 1px solid $search-form-container-bg-color;
|
||||
// position: relative;
|
||||
// z-index: 10;
|
||||
// width: 100%;
|
||||
// margin-left: auto;
|
||||
// margin-right: auto;
|
||||
// font-size: 12px;
|
||||
// text-align: left; /* To compensate .search_box:text-align */
|
||||
// border: 1px solid $search-form-container-bg-color;
|
||||
//transition: width 0.3s ease-in-out;
|
||||
|
||||
/* Sizing reset */
|
||||
@@ -1137,7 +1137,6 @@
|
||||
background-color: $white;
|
||||
|
||||
.sf_criterion_row {
|
||||
position: relative;;
|
||||
|
||||
&:not(:first-child) {
|
||||
margin-top: 20px;
|
||||
@@ -1165,6 +1164,11 @@
|
||||
|
||||
.sf_criterion_group {
|
||||
display: inline;
|
||||
.sfc_fg_button,
|
||||
.sfc_header {
|
||||
border: 1px solid #E1E7EC; /* Must be equal to .search_form_criteria:margin-bottom + this:padding-bottom */
|
||||
border-radius: 3px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1197,7 +1201,6 @@
|
||||
box-shadow: $box-shadow-regular;
|
||||
}
|
||||
|
||||
.sfc_form_group,
|
||||
.sfm_content {
|
||||
position: absolute;
|
||||
z-index: -1;
|
||||
|
||||
@@ -31,12 +31,12 @@
|
||||
{# - Bootstrap Datetime picker #}
|
||||
<link href="{{ app['combodo.portal.base.absolute_url'] ~ 'lib/bootstrap-datetimepicker/css/bootstrap-datetimepicker.min.css'|add_itop_version }}" rel="stylesheet">
|
||||
{# - Datatables #}
|
||||
<link href="{{ app['combodo.portal.base.absolute_url'] ~ 'lib/datatables/css/dataTables.bootstrap.min.css'|add_itop_version }}" rel="stylesheet">
|
||||
<link href="{{ app['combodo.portal.base.absolute_url'] ~ 'lib/datatables/css/fixedHeader.bootstrap.min.css'|add_itop_version }}" rel="stylesheet">
|
||||
<link href="{{ app['combodo.portal.base.absolute_url'] ~ 'lib/datatables/css/responsive.bootstrap.min.css'|add_itop_version }}" rel="stylesheet">
|
||||
<link href="{{ app['combodo.portal.base.absolute_url'] ~ 'lib/datatables/css/scroller.bootstrap.min.css'|add_itop_version }}" rel="stylesheet">
|
||||
<link href="{{ app['combodo.portal.base.absolute_url'] ~ 'lib/datatables/css/select.bootstrap.min.css'|add_itop_version }}" rel="stylesheet">
|
||||
<link href="{{ app['combodo.portal.base.absolute_url'] ~ 'lib/datatables/css/select.dataTables.min.css'|add_itop_version }}" rel="stylesheet">
|
||||
<link href="{{ app['combodo.absolute_url'] ~ 'lib/datatables/css/dataTables.bootstrap.min.css'|add_itop_version }}" rel="stylesheet">
|
||||
<link href="{{ app['combodo.absolute_url'] ~ 'lib/datatables/css/fixedHeader.bootstrap.min.css'|add_itop_version }}" rel="stylesheet">
|
||||
<link href="{{ app['combodo.absolute_url'] ~ 'lib/datatables/css/responsive.bootstrap.min.css'|add_itop_version }}" rel="stylesheet">
|
||||
<link href="{{ app['combodo.absolute_url'] ~ 'lib/datatables/css/scroller.bootstrap.min.css'|add_itop_version }}" rel="stylesheet">
|
||||
<link href="{{ app['combodo.absolute_url'] ~ 'lib/datatables/css/select.bootstrap.min.css'|add_itop_version }}" rel="stylesheet">
|
||||
<link href="{{ app['combodo.absolute_url'] ~ 'lib/datatables/css/select.dataTables.min.css'|add_itop_version }}" rel="stylesheet">
|
||||
{# - Font OpenSans #}
|
||||
<link href="{{ app['combodo.absolute_url'] ~ 'css/font-open-sans/font-open-sans.css'|add_itop_version }}" rel="stylesheet">
|
||||
{# - Font Combodo #}
|
||||
@@ -112,13 +112,13 @@
|
||||
{# Moment.js with locales#}
|
||||
<script type="text/javascript" src="{{ app['combodo.absolute_url'] ~ 'js/moment-with-locales.min.js'|add_itop_version }}"></script>
|
||||
{# Datatables #}
|
||||
<script type="text/javascript" src="{{ app['combodo.portal.base.absolute_url'] ~ 'lib/datatables/js/jquery.dataTables.min.js'|add_itop_version }}"></script>
|
||||
<script type="text/javascript" src="{{ app['combodo.portal.base.absolute_url'] ~ 'lib/datatables/js/dataTables.bootstrap.min.js'|add_itop_version }}"></script>
|
||||
<script type="text/javascript" src="{{ app['combodo.portal.base.absolute_url'] ~ 'lib/datatables/js/dataTables.fixedHeader.min.js'|add_itop_version }}"></script>
|
||||
<script type="text/javascript" src="{{ app['combodo.portal.base.absolute_url'] ~ 'lib/datatables/js/dataTables.responsive.min.js'|add_itop_version }}"></script>
|
||||
<script type="text/javascript" src="{{ app['combodo.portal.base.absolute_url'] ~ 'lib/datatables/js/dataTables.scroller.min.js'|add_itop_version }}"></script>
|
||||
<script type="text/javascript" src="{{ app['combodo.portal.base.absolute_url'] ~ 'lib/datatables/js/dataTables.select.min.js'|add_itop_version }}"></script>
|
||||
<script type="text/javascript" src="{{ app['combodo.portal.base.absolute_url'] ~ 'lib/datatables/js/datetime-moment.js'|add_itop_version }}"></script>
|
||||
<script type="text/javascript" src="{{ app['combodo.absolute_url'] ~ 'lib/datatables/js/jquery.dataTables.min.js'|add_itop_version }}"></script>
|
||||
<script type="text/javascript" src="{{ app['combodo.absolute_url'] ~ 'lib/datatables/js/dataTables.bootstrap.min.js'|add_itop_version }}"></script>
|
||||
<script type="text/javascript" src="{{ app['combodo.absolute_url'] ~ 'lib/datatables/js/dataTables.fixedHeader.min.js'|add_itop_version }}"></script>
|
||||
<script type="text/javascript" src="{{ app['combodo.absolute_url'] ~ 'lib/datatables/js/dataTables.responsive.min.js'|add_itop_version }}"></script>
|
||||
<script type="text/javascript" src="{{ app['combodo.absolute_url'] ~ 'lib/datatables/js/dataTables.scroller.min.js'|add_itop_version }}"></script>
|
||||
<script type="text/javascript" src="{{ app['combodo.absolute_url'] ~ 'lib/datatables/js/dataTables.select.min.js'|add_itop_version }}"></script>
|
||||
<script type="text/javascript" src="{{ app['combodo.absolute_url'] ~ 'lib/datatables/js/datetime-moment.js'|add_itop_version }}"></script>
|
||||
<script type="text/javascript" src="{{ app['combodo.portal.base.absolute_url'] ~ 'js/dataTables.accentNeutraliseForFilter.js'|add_itop_version }}"></script>
|
||||
{# Export for Datatables #}
|
||||
<script type="text/javascript" src="{{ app['combodo.portal.base.absolute_url'] ~ 'js/export.js'|add_itop_version }}"></script>
|
||||
|
||||
@@ -1167,7 +1167,8 @@ Dict::Add('CS CZ', 'Czech', 'Čeština', array(
|
||||
'UI:ColumnsAndSortOrder' => 'Sloupce a jejich řazení:',
|
||||
'UI:UseDefaultSettings' => 'Použít výchozí nastavení',
|
||||
'UI:UseSpecificSettings' => 'Použít následující nastavení:',
|
||||
'UI:Display_X_ItemsPerPage' => 'Zobrazit %1$s položek na stránku',
|
||||
'UI:Display_X_ItemsPerPage_prefix' => 'Zobrazit',
|
||||
'UI:Display_X_ItemsPerPage_suffix' => 'položek na stránku',
|
||||
'UI:UseSavetheSettings' => 'Uložit nastavení',
|
||||
'UI:OnlyForThisList' => 'Jen pro tento seznam',
|
||||
'UI:ForAllLists' => 'Pro všechny seznamy',
|
||||
|
||||
@@ -1156,7 +1156,8 @@ Ved tilknytningen til en trigger, bliver hver handling tildelt et "rækkefølge"
|
||||
'UI:ColumnsAndSortOrder' => 'Kolonner og sortering:',
|
||||
'UI:UseDefaultSettings' => 'Brug de anbefalede indstillinger',
|
||||
'UI:UseSpecificSettings' => 'Brug følgende indstillinger:',
|
||||
'UI:Display_X_ItemsPerPage' => 'Vis %1$s emner per side',
|
||||
'UI:Display_X_ItemsPerPage_prefix' => 'Vis',
|
||||
'UI:Display_X_ItemsPerPage_suffix' => 'emner per side',
|
||||
'UI:UseSavetheSettings' => 'Gem indstillinger',
|
||||
'UI:OnlyForThisList' => 'Kun for denne liste',
|
||||
'UI:ForAllLists' => 'For alle lister',
|
||||
|
||||
@@ -1154,7 +1154,8 @@ Wenn Aktionen mit Trigger verknüpft sind, bekommt jede Aktion eine Auftragsnumm
|
||||
'UI:ColumnsAndSortOrder' => 'Spalten und Sortierrheienfolge:',
|
||||
'UI:UseDefaultSettings' => 'Verwende Default-Einstellungen',
|
||||
'UI:UseSpecificSettings' => 'Verwende folgende Einstellungen:',
|
||||
'UI:Display_X_ItemsPerPage' => '%1$s Elemente pro Seite anzeigen',
|
||||
'UI:Display_X_ItemsPerPage_prefix' => '',
|
||||
'UI:Display_X_ItemsPerPage_suffix' => 'Elemente pro Seite anzeigen',
|
||||
'UI:UseSavetheSettings' => 'Einstellungen speichern',
|
||||
'UI:OnlyForThisList' => 'Nur für diese Liste',
|
||||
'UI:ForAllLists' => 'Standard für alle Listen',
|
||||
|
||||
@@ -1173,7 +1173,8 @@ When associated with a trigger, each action is given an "order" number, specifyi
|
||||
'UI:ColumnsAndSortOrder' => 'Columns and sort order:',
|
||||
'UI:UseDefaultSettings' => 'Use the Default Settings',
|
||||
'UI:UseSpecificSettings' => 'Use the Following Settings:',
|
||||
'UI:Display_X_ItemsPerPage' => 'Display %1$s items per page',
|
||||
'UI:Display_X_ItemsPerPage_prefix' => 'Display',
|
||||
'UI:Display_X_ItemsPerPage_suffix' => 'items per page',
|
||||
'UI:UseSavetheSettings' => 'Save the Settings',
|
||||
'UI:OnlyForThisList' => 'Only for this list',
|
||||
'UI:ForAllLists' => 'Default for all lists',
|
||||
|
||||
@@ -1169,7 +1169,8 @@ Cuando se asocien con un disparador, cada acción recibe un número de "orden",
|
||||
'UI:ColumnsAndSortOrder' => 'Columnas y Ordenamiento:',
|
||||
'UI:UseDefaultSettings' => 'Usar Configuración por Omisión',
|
||||
'UI:UseSpecificSettings' => 'Usar la Siguiente Configuración:',
|
||||
'UI:Display_X_ItemsPerPage' => 'Desplegar %1$s elementos por página',
|
||||
'UI:Display_X_ItemsPerPage_prefix' => 'Desplegar',
|
||||
'UI:Display_X_ItemsPerPage_suffix' => 'elementos por página',
|
||||
'UI:UseSavetheSettings' => 'Guardar Configuraciones',
|
||||
'UI:OnlyForThisList' => 'Sólo esta Lista',
|
||||
'UI:ForAllLists' => 'Defecto en todas las listas',
|
||||
|
||||
@@ -1153,7 +1153,8 @@ Lors de l\'association à un déclencheur, on attribue à chaque action un numé
|
||||
'UI:ColumnsAndSortOrder' => 'Colonnes et ordre de tri:',
|
||||
'UI:UseDefaultSettings' => 'Utiliser les réglages par défaut',
|
||||
'UI:UseSpecificSettings' => 'Utiliser les réglages suivants:',
|
||||
'UI:Display_X_ItemsPerPage' => 'Afficher %1$s éléments par page',
|
||||
'UI:Display_X_ItemsPerPage_prefix' => 'Afficher',
|
||||
'UI:Display_X_ItemsPerPage_suffix' => 'éléments par page',
|
||||
'UI:UseSavetheSettings' => 'Enregistrer ces réglages',
|
||||
'UI:OnlyForThisList' => 'Seulement pour cette liste',
|
||||
'UI:ForAllLists' => 'Défaut pour toutes les listes',
|
||||
|
||||
@@ -1154,7 +1154,8 @@ Dict::Add('JA JP', 'Japanese', '日本語', array(
|
||||
'UI:ColumnsAndSortOrder' => 'カラムと並び順:',
|
||||
'UI:UseDefaultSettings' => '既定のセッティングを使用',
|
||||
'UI:UseSpecificSettings' => '次のセッティングを使用:',
|
||||
'UI:Display_X_ItemsPerPage' => '1ページに %1$s アイテムを表示',
|
||||
'UI:Display_X_ItemsPerPage_prefix' => '1ページに',
|
||||
'UI:Display_X_ItemsPerPage_suffix' => 'アイテムを表示',
|
||||
'UI:UseSavetheSettings' => 'セッティングを保存',
|
||||
'UI:OnlyForThisList' => 'このリストのみ',
|
||||
'UI:ForAllLists' => 'すべてのリストのデフォルト',
|
||||
|
||||
@@ -1177,7 +1177,8 @@ Bij die koppeling wordt aan elke actie een volgorde-nummer gegeven. Dit bepaalt
|
||||
'UI:ColumnsAndSortOrder' => 'Kolommen en sorteervolgorde:',
|
||||
'UI:UseDefaultSettings' => 'Gebruik de standaard instellingen',
|
||||
'UI:UseSpecificSettings' => 'Gebruik de volgende instellingen:',
|
||||
'UI:Display_X_ItemsPerPage' => 'Geef %1$s items per pagina weer',
|
||||
'UI:Display_X_ItemsPerPage_prefix' => 'Geef',
|
||||
'UI:Display_X_ItemsPerPage_suffix' => 'items per pagina weer',
|
||||
'UI:UseSavetheSettings' => 'Sla de instellingen op',
|
||||
'UI:OnlyForThisList' => 'Alleen voor deze lijst',
|
||||
'UI:ForAllLists' => 'Standaard voor alle lijsten',
|
||||
|
||||
@@ -1167,7 +1167,8 @@ When associated with a trigger, each action is given an "order" number, specifyi
|
||||
'UI:ColumnsAndSortOrder' => 'Colunas e ordem de classificação:',
|
||||
'UI:UseDefaultSettings' => 'Use a configuração padrão',
|
||||
'UI:UseSpecificSettings' => 'Use as seguintes configurações:',
|
||||
'UI:Display_X_ItemsPerPage' => 'Mostrar %1$s itens por página',
|
||||
'UI:Display_X_ItemsPerPage_prefix' => 'Mostrar',
|
||||
'UI:Display_X_ItemsPerPage_suffix' => 'itens por página',
|
||||
'UI:UseSavetheSettings' => 'Salvar configurações',
|
||||
'UI:OnlyForThisList' => 'Somente para esta lista',
|
||||
'UI:ForAllLists' => 'Para todas as listas',
|
||||
|
||||
@@ -1145,7 +1145,8 @@ Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'UI:ColumnsAndSortOrder' => 'Колонки и порядок сортировки:',
|
||||
'UI:UseDefaultSettings' => 'Использовать настройки по умолчанию',
|
||||
'UI:UseSpecificSettings' => 'Использовать эти настройки:',
|
||||
'UI:Display_X_ItemsPerPage' => 'Показывать %1$s элементов на странице',
|
||||
'UI:Display_X_ItemsPerPage_prefix' => 'Показывать',
|
||||
'UI:Display_X_ItemsPerPage_suffix' => 'элементов на странице',
|
||||
'UI:UseSavetheSettings' => 'Сохранить настройки',
|
||||
'UI:OnlyForThisList' => 'Только для текущего списка',
|
||||
'UI:ForAllLists' => 'Для всех списков',
|
||||
|
||||
@@ -1156,7 +1156,8 @@ Keď sú priradené spúštačom, každej akcii je dané číslo "príkazu", šp
|
||||
'UI:ColumnsAndSortOrder' => 'Stĺpce a triediaci príkaz:',
|
||||
'UI:UseDefaultSettings' => 'Použite štandardné nastavenia',
|
||||
'UI:UseSpecificSettings' => 'Použite nasledovné nastavenia:',
|
||||
'UI:Display_X_ItemsPerPage' => 'Zobraziť %1$s položiek na stránku',
|
||||
'UI:Display_X_ItemsPerPage_prefix' => 'Zobraziť',
|
||||
'UI:Display_X_ItemsPerPage_suffix' => 'položiek na stránku',
|
||||
'UI:UseSavetheSettings' => 'Uložiť nastavenia',
|
||||
'UI:OnlyForThisList' => 'Iba pre tento zoznam',
|
||||
'UI:ForAllLists' => 'Pre všetky zoznamy',
|
||||
|
||||
33
dictionaries/ui/components/en.dictionary.itop.datatable.php
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2013-2020 Combodo SARL
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
*/
|
||||
|
||||
// Global search
|
||||
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:ZeroRecords' => 'No result',
|
||||
'UI:Datatables:Language:Info' => 'of _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',
|
||||
'UI:Datatables:Language:DisplayLength:All' => 'All',
|
||||
'UI:Datatables:Language:Sort:Ascending' => 'enable for an ascending sort',
|
||||
'UI:Datatables:Language:Sort:Descending' => 'enable for a descending sort',
|
||||
));
|
||||
@@ -1167,7 +1167,8 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', array(
|
||||
'UI:ColumnsAndSortOrder' => '列和排序顺序:',
|
||||
'UI:UseDefaultSettings' => '使用默认配置',
|
||||
'UI:UseSpecificSettings' => '使用下面的配置:',
|
||||
'UI:Display_X_ItemsPerPage' => '每页显示 %1$s 个项目',
|
||||
'UI:Display_X_ItemsPerPage_prefix' => '每页显示',
|
||||
'UI:Display_X_ItemsPerPage_suffix' => '个项目',
|
||||
'UI:UseSavetheSettings' => '保存设置',
|
||||
'UI:OnlyForThisList' => '仅这个列表',
|
||||
'UI:ForAllLists' => '默认所有列表',
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Deprecated in 2.8.0
|
||||
# Deprecated in 3.0.0
|
||||
|
||||
* TabManager::GetCurrentTabLength()
|
||||
* TabManager::TruncateTab()
|
||||
@@ -6,8 +6,9 @@
|
||||
* TabManager::RenderIntoContent()
|
||||
|
||||
* iTopWebPage::SelectTab()
|
||||
*cmdbabstract->GetDisplaySet
|
||||
*cmdbabstract->GetDisplayExtendedSet
|
||||
|
||||
|
||||
# Modified in 2.8.0
|
||||
# Modified in 3.0.0
|
||||
|
||||
* iTabbedPage::AddTabContainer -> one optional parameter added
|
||||
125
js/dataTables.pipeline.js
Normal file
@@ -0,0 +1,125 @@
|
||||
//
|
||||
// Pipelining function for DataTables. To be used to the `ajax` option of DataTables
|
||||
//
|
||||
$.fn.dataTable.pipeline = function ( opts ) {
|
||||
// Configuration options
|
||||
var conf = $.extend( {
|
||||
pages: 5, // number of pages to cache
|
||||
url: '', // script url
|
||||
data: null, // function or object with parameters to send to the server
|
||||
// matching how `ajax.data` works in DataTables
|
||||
method: 'GET' // Ajax HTTP method
|
||||
}, opts );
|
||||
|
||||
// Private variables for storing the cache
|
||||
var cacheLower = -1;
|
||||
var cacheUpper = null;
|
||||
var cacheLastRequest = null;
|
||||
var cacheLastJson = null;
|
||||
var draw_number = 1;
|
||||
|
||||
return function ( request, drawCallback, settings ) {
|
||||
var ajax = false;
|
||||
var requestStart = request.start;
|
||||
var drawStart = request.start;
|
||||
var requestLength = request.length;
|
||||
if(request.start=undefined)
|
||||
{
|
||||
requestStart = settings._iDisplayStart;
|
||||
drawStart = settings._iDisplayStart;
|
||||
requestLength = settings._iDisplayLength;
|
||||
}
|
||||
var requestEnd = requestStart + requestLength;
|
||||
|
||||
if ( settings.clearCache ) {
|
||||
// API requested that the cache be cleared
|
||||
ajax = true;
|
||||
settings.clearCache = false;
|
||||
}
|
||||
else if ( cacheLower < 0 || requestStart < cacheLower || requestEnd > cacheUpper ) {
|
||||
// outside cached data - need to make a request
|
||||
ajax = true;
|
||||
}
|
||||
else if ( JSON.stringify( request.order ) !== JSON.stringify( cacheLastRequest.order ) ||
|
||||
JSON.stringify( request.columns ) !== JSON.stringify( cacheLastRequest.columns ) ||
|
||||
JSON.stringify( request.search ) !== JSON.stringify( cacheLastRequest.search )
|
||||
) {
|
||||
// properties changed (ordering, columns, searching)
|
||||
ajax = true;
|
||||
}
|
||||
else if(cacheLastJson == undefined || cacheLastJson.length==0)
|
||||
{
|
||||
ajax = true;
|
||||
}
|
||||
|
||||
// Store the request for checking next time around
|
||||
cacheLastRequest = $.extend( true, {}, request );
|
||||
|
||||
if ( ajax ) {
|
||||
// Need data from the server
|
||||
if ( requestStart < cacheLower ) {
|
||||
requestStart = requestStart - (requestLength*(conf.pages-1));
|
||||
|
||||
if ( requestStart < 0 ) {
|
||||
requestStart = 0;
|
||||
}
|
||||
}
|
||||
|
||||
cacheLower = requestStart;
|
||||
cacheUpper = requestStart + (requestLength * conf.pages);
|
||||
|
||||
request.start = requestStart;
|
||||
request.length = requestLength*conf.pages;
|
||||
request.end = requestStart+ requestLength*conf.pages;
|
||||
|
||||
// Provide the same `data` options as DataTables.
|
||||
if ( typeof conf.data === 'function' ) {
|
||||
// As a function it is executed with the data object as an arg
|
||||
// for manipulation. If an object is returned, it is used as the
|
||||
// data object to submit
|
||||
var d = conf.data( request );
|
||||
if ( d ) {
|
||||
$.extend( request, d );
|
||||
}
|
||||
}
|
||||
else if ( $.isPlainObject( conf.data ) ) {
|
||||
// As an object, the data given extends the default
|
||||
$.extend( request, conf.data );
|
||||
}
|
||||
return $.ajax( {
|
||||
"type": conf.method,
|
||||
"url": conf.url,
|
||||
"data": request,
|
||||
"dataType": "json",
|
||||
"cache": false,
|
||||
"success": function ( json ) {
|
||||
cacheLastJson = $.extend(true, {}, json);
|
||||
|
||||
if ( cacheLower != drawStart ) {
|
||||
json.data.splice( 0, drawStart-cacheLower );
|
||||
}
|
||||
if ( requestLength >= -1 ) {
|
||||
json.data.splice( requestLength, json.data.length );
|
||||
}
|
||||
drawCallback( json );
|
||||
}
|
||||
} );
|
||||
}
|
||||
else {
|
||||
json = $.extend( true, {}, cacheLastJson );
|
||||
json.draw = request.draw; // Update the echo for each response
|
||||
json.data.splice( 0, requestStart-cacheLower );
|
||||
json.data.splice( requestLength, json.data.length );
|
||||
|
||||
drawCallback(json);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Register an API method that will empty the pipelined data, forcing an Ajax
|
||||
// fetch on the next draw (i.e. `table.clearPipeline().draw()`)
|
||||
$.fn.dataTable.Api.register( 'clearPipeline()', function () {
|
||||
return this.iterator( 'table', function ( settings ) {
|
||||
settings.clearCache = true;
|
||||
} );
|
||||
} );
|
||||
359
js/dataTables.settings.js
Normal file
@@ -0,0 +1,359 @@
|
||||
// jQuery UI style "widget" for selecting and sorting "fields"
|
||||
$(function()
|
||||
{
|
||||
// the widget definition, where "itop" is the namespace,
|
||||
// "datatable" the widget name
|
||||
$.widget( "itop.DataTableSettings",
|
||||
{
|
||||
// default options
|
||||
options:
|
||||
{
|
||||
sListId: '',
|
||||
oColumns: {},
|
||||
sSelectMode: '',
|
||||
sViewLink: 'true',
|
||||
iPageSize: -1,
|
||||
oClassAliases: {},
|
||||
sTableId : null,
|
||||
oExtraParams: {},
|
||||
sRenderUrl: 'index.php',
|
||||
oRenderParameters: {},
|
||||
oDefaultSettings: {},
|
||||
oLabels: { moveup: 'Move Up', movedown: 'Move Down' }
|
||||
},
|
||||
|
||||
// the constructor
|
||||
_create: function(mydatatable, options)
|
||||
{
|
||||
this.aDlgStateParams = ['iDefaultPageSize', 'oColumns'];
|
||||
console.warn('datatablesettings');
|
||||
this.element.addClass('itop-datatable');
|
||||
|
||||
var me = this;
|
||||
var bViewLink = (this.options.sViewLink == 'true');
|
||||
$('#sfl_'+me.options.sListId).fieldsorter({hasKeyColumn: bViewLink, labels: this.options.oLabels, fields: this.options.oColumns, onChange: function() { me._onSpecificSettings(); } });
|
||||
$('#datatable_dlg_'+me.options.sListId).find('input[name=page_size]').click(function() { me._onSpecificSettings(); });
|
||||
$('#datatable_dlg_'+me.options.sListId).find('input[name=save_settings]').click(function() { me._updateSaveScope(); });
|
||||
this.element.find('.itop_popup > ul li').popupmenu();
|
||||
this._updateSaveScope();
|
||||
this._saveDlgState();
|
||||
},
|
||||
|
||||
// called when created, and later when changing options
|
||||
_refresh: function()
|
||||
{
|
||||
oParams = this.options.oData;
|
||||
oParams.operation = 'search_and_refresh';
|
||||
|
||||
oParams.start = 0;
|
||||
oParams.end = this.options.iPageSize;
|
||||
oParams.select_mode = this.options.sSelectMode;
|
||||
oParams.display_key = this.options.sViewLink;
|
||||
oParams.class_aliases = this.options.oClassAliases;
|
||||
oParams.columns = this.options.oColumns;
|
||||
var iSortCol = 0;
|
||||
var aCurrentSort = [];
|
||||
for(var k1 in oParams.columns) //Aliases
|
||||
{
|
||||
for(var k2 in oParams.columns[k1]) //Attribute codes
|
||||
{
|
||||
if (oParams.columns[k1][k2].sort != 'none')
|
||||
{
|
||||
oParams.sort_col = iSortCol;
|
||||
oParams.sort_order = oParams.columns[k1][k2].sort;
|
||||
aCurrentSort.push([iSortCol, (oParams.columns[k1][k2].sort == 'asc') ? 0 : 1]);
|
||||
break; //TODO make this more generic, Sort on just one column for now
|
||||
}
|
||||
iSortCol++;
|
||||
}
|
||||
break; //TODO: DBObjectSet supports only sorting on the first alias of the set
|
||||
}
|
||||
oParams.list_id = this.options.sListId;
|
||||
var me = this;
|
||||
this.element.block();
|
||||
|
||||
$('#'+me.options.sListId).DataTable().ajax.reload();
|
||||
$.post(this.options.sRenderUrl, oParams, function(data) {
|
||||
// Nasty workaround to clear the pager's state for paginated lists !!!
|
||||
// See jquery.tablesorter.pager.js / saveParams / restoreParams
|
||||
if (window.pager_params)
|
||||
{
|
||||
window.pager_params['pager'+me.options.sListId] = undefined;
|
||||
}
|
||||
// End of workaround
|
||||
console.warn("update:");
|
||||
console.warn(data);
|
||||
|
||||
// try {
|
||||
var toto = $('#'+me.options.sListId).parent().parent();
|
||||
$('#'+me.options.sListId).DataTable().destroy(true);
|
||||
var entete="";
|
||||
var aOptions = JSON.parse(data);
|
||||
$.each(aOptions[0]['allColumns'], function(i, item) {
|
||||
$.each(item, function(j, champs) {
|
||||
if(champs.checked == 'true') {
|
||||
entete += "<th>"+champs.label+"</th>";
|
||||
}
|
||||
});
|
||||
});
|
||||
$.each(aOptions[0]['columns'], function(i, item) {
|
||||
aOptions[0]["columns"][i]["render"]["display"] = new Function ( "data, type, row" , aOptions[0]["columns"][i]["render"]["display"]);
|
||||
});
|
||||
|
||||
toto.append( "<table id=\""+me.options.sListId+"\" width=\"100%\" class=\"ibo-datatable\">" +
|
||||
"<thead><tr>"+entete+"</tr></thead></table>" );
|
||||
//$('#'+me.options.sListId).DataTable().clear();
|
||||
//$('#'+me.options.sListId).empty();
|
||||
aOptions[0]["lengthMenu"]= [[oParams.end, oParams.end*2, oParams.end*3, oParams.end*4, -1], [oParams.end, oParams.end*2, oParams.end*3, oParams.end*4, aOptions[0]["lengthMenu"]]];
|
||||
aOptions[0]["ajax"]=eval(aOptions[0]["ajax"]);
|
||||
$('#'+me.options.sListId).DataTable(aOptions[0]);
|
||||
//me.element.find('.datacontents').html(data);
|
||||
// restore the sort order on columns
|
||||
//me.element.find('table.listResults').trigger('fakesorton', [aCurrentSort]);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*} catch (e) {
|
||||
// ugly hacks for IE 8/9 first...
|
||||
if (!window.console) console.error = {};
|
||||
if (!window.console.error) {
|
||||
console.error = function () {
|
||||
};
|
||||
}
|
||||
console.error("Can not inject data : "+data);
|
||||
}*/
|
||||
me.element.unblock();
|
||||
|
||||
}, 'html' );
|
||||
|
||||
},
|
||||
_useDefaultSettings: function(bResetAll)
|
||||
{
|
||||
var oParams = this.options.oData;
|
||||
oParams.operation = 'datatable_reset_settings';
|
||||
|
||||
oParams.table_id = this.options.sTableId;
|
||||
oParams.defaults = bResetAll;
|
||||
oParams.class_aliases = this.options.oClassAliases;
|
||||
|
||||
var me = this;
|
||||
$.post(this.options.sRenderUrl, oParams, function(data) {
|
||||
// Do nothing...
|
||||
}, 'html' );
|
||||
},
|
||||
_saveSettings: function(bSaveAsDefaults)
|
||||
{
|
||||
var oParams = this.options.oData ;
|
||||
oParams.operation = 'datatable_save_settings';
|
||||
oParams.page_size = this.options.iPageSize;
|
||||
oParams.table_id = this.options.sTableId;
|
||||
oParams.defaults = bSaveAsDefaults;
|
||||
oParams.columns = this.options.oColumns;
|
||||
var iSortCol = 0;
|
||||
var sSortOrder = '';
|
||||
for(var i in this.options.oColumns)
|
||||
{
|
||||
if (this.options.oColumns[i].checked)
|
||||
{
|
||||
if (this.options.oColumns[i].sort != 'none')
|
||||
{
|
||||
sSortOrder = this.options.oColumns[i].sort;
|
||||
}
|
||||
else
|
||||
{
|
||||
iSortCol++;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*A voir, je ne sais pas à quoi ça sert
|
||||
if ((this.options.sSelectMode != '') && (this.options.sSelectMode != 'none'))
|
||||
{
|
||||
iSortCol++;
|
||||
}*/
|
||||
oParams.sort_col = iSortCol;
|
||||
oParams.sort_order = sSortOrder;
|
||||
var me = this;
|
||||
$.post(this.options.sRenderUrl, oParams, function(data) {
|
||||
// Do nothing...
|
||||
}, 'html' );
|
||||
},
|
||||
onDlgOk: function()
|
||||
{
|
||||
var oOptions = {};
|
||||
oSettings = $('#datatable_dlg_'+this.options.sListId).find('input[name=settings]:checked');
|
||||
if (oSettings.val() == 'defaults')
|
||||
{
|
||||
oOptions = { iPageSize: this.options.oDefaultSettings.iDefaultPageSize,
|
||||
oColumns: this.options.oDefaultSettings.oColumns
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
var oDisplayColumns = {};
|
||||
var iColIdx = 0;
|
||||
var iSortIdx = 0;
|
||||
var sSortDirection = 'asc';
|
||||
var oColumns = $('#datatable_dlg_'+this.options.sListId).find(':itop-fieldsorter').fieldsorter('get_params');
|
||||
var iPageSize = parseInt($('#datatable_dlg_'+this.options.sListId+' input[name=page_size]').val(), 10);
|
||||
|
||||
oOptions = {oColumns: oColumns, iPageSize: iPageSize, iDefaultPageSize: iPageSize };
|
||||
}
|
||||
this._setOptions(oOptions);
|
||||
|
||||
// Check if we need to save the settings or not...
|
||||
var oSaveCheck = $('#datatable_dlg_'+this.options.sListId).find('input[name=save_settings]');
|
||||
var oSaveScope = $('#datatable_dlg_'+this.options.sListId).find('input[name=scope]:checked');
|
||||
if (oSaveCheck.prop('checked'))
|
||||
{
|
||||
if (oSettings.val() == 'defaults')
|
||||
{
|
||||
this._useDefaultSettings((oSaveScope.val() == 'defaults'));
|
||||
}
|
||||
else
|
||||
{
|
||||
this._saveSettings((oSaveScope.val() == 'defaults'));
|
||||
}
|
||||
}
|
||||
this._saveDlgState();
|
||||
|
||||
},
|
||||
onDlgCancel: function()
|
||||
{
|
||||
this._restoreDlgState();
|
||||
},
|
||||
_onSpecificSettings: function()
|
||||
{
|
||||
$('#datatable_dlg_'+this.options.sListId).find('input.specific_settings').prop('checked', true);
|
||||
},
|
||||
_updateSaveScope: function()
|
||||
{
|
||||
var oSaveCheck = $('#datatable_dlg_'+this.options.sListId).find('input[name=save_settings]');
|
||||
if (oSaveCheck.prop('checked'))
|
||||
{
|
||||
$('#datatable_dlg_'+this.options.sListId).find('input[name=scope]').each(function() {
|
||||
if ($(this).attr('stay-disabled') != 'true')
|
||||
{
|
||||
$(this).prop('disabled', false);
|
||||
}
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
$('#datatable_dlg_'+this.options.sListId).find('input[name=scope]').prop('disabled', true);
|
||||
}
|
||||
},
|
||||
// events bound via _bind are removed automatically
|
||||
// revert other modifications here
|
||||
_destroy: function()
|
||||
{
|
||||
this.element.removeClass('itop-datatable');
|
||||
|
||||
$('#sfl_'+this.options.sListId).remove();
|
||||
$('#datatable_dlg_'+this.options.sListId).remove();
|
||||
},
|
||||
// _setOptions is called with a hash of all options that are changing
|
||||
_setOptions: function()
|
||||
{
|
||||
// in 1.9 would use _superApply
|
||||
this._superApply(arguments);
|
||||
this._refresh();
|
||||
},
|
||||
// _setOption is called for each individual option that is changing
|
||||
_setOption: function( key, value )
|
||||
{
|
||||
// in 1.9 would use _super
|
||||
this._superApply(arguments);
|
||||
},
|
||||
UpdateState: function( config )
|
||||
{
|
||||
console.warn('datatablesettings:UpdateState');
|
||||
var iPageSize = config.page_size;
|
||||
if (iPageSize == -1)
|
||||
{
|
||||
iPageSize = 0;
|
||||
}
|
||||
this.options.iPageSize = iPageSize;
|
||||
|
||||
var iPos = 0;
|
||||
for (alias in this.options.oColumns)
|
||||
{
|
||||
for (attcode in this.options.oColumns[alias])
|
||||
{
|
||||
this.options.oColumns[alias][attcode]['sort'] = 'none';
|
||||
if (this.options.oColumns[alias][attcode]['checked'])
|
||||
{
|
||||
if (iPos == config.sort_index)
|
||||
{
|
||||
this.options.oColumns[alias][attcode]['sort'] = config.sort_order;
|
||||
}
|
||||
iPos++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var dlgElement = $('#datatable_dlg_'+this.options.sListId);
|
||||
dlgElement.find('input[name=page_size]').val(iPageSize);
|
||||
dlgElement.find(':itop-fieldsorter').fieldsorter('option', { fields: this.options.oColumns });
|
||||
},
|
||||
_saveDlgState: function()
|
||||
{
|
||||
this.originalState = {};
|
||||
for(k in this.aDlgStateParams)
|
||||
{
|
||||
this.originalState[this.aDlgStateParams[k]] = this.options[this.aDlgStateParams[k]];
|
||||
}
|
||||
this.originalState.oFields = $('#datatable_dlg_'+this.options.sListId).find(':itop-fieldsorter').fieldsorter('get_params');
|
||||
},
|
||||
_restoreDlgState: function()
|
||||
{
|
||||
var dlgElement = $('#datatable_dlg_'+this.options.sListId);
|
||||
|
||||
for(k in this.aDlgStateParams)
|
||||
{
|
||||
this._setOption(this.aDlgStateParams[k], this.originalState[this.aDlgStateParams[k]]);
|
||||
}
|
||||
|
||||
dlgElement.find('input[name=page_size]').val(this.originalState.iDefaultPageSize);
|
||||
|
||||
dlgElement.find(':itop-fieldsorter').fieldsorter('option', { fields: this.originalState.oFields });
|
||||
|
||||
$('#datatable_dlg_'+this.options.sListId).unblock();
|
||||
|
||||
},
|
||||
IsDialogOpen: function()
|
||||
{
|
||||
var oDlgOpen = $('#datatable_dlg_'+this.options.sListId+' :visible');
|
||||
|
||||
return (oDlgOpen.length > 0);
|
||||
},
|
||||
DoRefresh: function()
|
||||
{
|
||||
this._refresh();
|
||||
},
|
||||
GetMultipleSelectionParams: function()
|
||||
{
|
||||
var oRes = {};
|
||||
|
||||
oRes.selectionMode = '';
|
||||
if (this.element.find(':input[name=selectionMode]').length > 0)
|
||||
{
|
||||
oRes.selectionMode = this.element.find(':input[name=selectionMode]').val();
|
||||
}
|
||||
|
||||
oRes.selectObject = [];
|
||||
this.element.find(':input[name^=selectObject]:checked').each(function() {
|
||||
oRes.selectObject.push($(this).val());
|
||||
});
|
||||
|
||||
oRes.storedSelection = [];
|
||||
this.element.find(':input[name^=storedSelection]').each(function() {
|
||||
oRes.storedSelection.push($(this).val());
|
||||
});
|
||||
|
||||
return oRes;
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -1,4 +1,5 @@
|
||||
// jQuery UI style "widget" for selecting and sorting "fields"
|
||||
//@deprecated
|
||||
$(function()
|
||||
{
|
||||
// the widget definition, where "itop" is the namespace,
|
||||
|
||||
@@ -193,7 +193,10 @@ function LinksWidget(id, sClass, sAttCode, iInputId, sSuffix, bDuplicates, oWizH
|
||||
theMap['selectionMode'] = sMode;
|
||||
$('#fs_SearchFormToAdd_'+me.id+' :input').each(
|
||||
function (i) {
|
||||
theMap[this.name] = this.value;
|
||||
if(this.name !="")
|
||||
{
|
||||
theMap[this.name] = this.value;
|
||||
}
|
||||
}
|
||||
);
|
||||
theMap['sRemoteClass'] = theMap['class']; // swap 'class' (defined in the form) and 'remoteClass'
|
||||
@@ -206,10 +209,11 @@ function LinksWidget(id, sClass, sAttCode, iInputId, sSuffix, bDuplicates, oWizH
|
||||
theMap[this.name].push(this.value);
|
||||
$(this).remove(); // Remove the selection for the next time the dialog re-opens
|
||||
});
|
||||
theMap["storedSelection[]"]=eval("oSelectedItemsadd_"+me.id);
|
||||
|
||||
// Retrieve the 'filter' definition
|
||||
var table = $('#ResultsToAdd_'+me.id).find('table.listResults')[0];
|
||||
theMap['filter'] = table.config.filter;
|
||||
theMap['extra_params'] = table.config.extra_params;
|
||||
theMap['filter'] = $(':input[name=filter]', context).val();
|
||||
theMap['extra_params'] = $(':input[name=extra_params]', context).val();
|
||||
}
|
||||
// else
|
||||
// {
|
||||
|
||||
@@ -380,7 +380,7 @@ $(function()
|
||||
// Prepare base DOM structure
|
||||
this.element
|
||||
.append('<div class="sfc_header"><div class="sfc_title"></div><span class="sfc_toggle"><a class="fas fa-caret-down"' + ' href="#"></a></span></div>')
|
||||
.append('<div class="sfc_form_group"><div class="sfc_fg_operators"></div><div class="sfc_fg_buttons"></div></div>');
|
||||
.append('<div class="sfc_form_group ibo-form-group"><div class="sfc_fg_operators"></div><div class="sfc_fg_buttons"></div></div>');
|
||||
|
||||
// Bind events
|
||||
// Note: No event to handle criteria closing when clicking outside of it as it is already handle by the form handler.
|
||||
|
||||
@@ -203,8 +203,8 @@ $(function()
|
||||
|
||||
|
||||
$('#ibo-breadcrumbs')
|
||||
.breadcrumb('destroy')
|
||||
.breadcrumb({
|
||||
.breadcrumbs('destroy')
|
||||
.breadcrumbs({
|
||||
itop_instance_id: oData['breadcrumb_instance_id'],
|
||||
max_count: oData['breadcrumb_max_count'],
|
||||
new_entry: {
|
||||
@@ -373,17 +373,17 @@ $(function()
|
||||
{
|
||||
oCriterionAreaElem = $('<div></div>').appendTo(this.element);
|
||||
}
|
||||
oCriterionAreaElem.addClass('sf_criterion_area');
|
||||
oCriterionAreaElem.addClass('sf_criterion_area ibo-criterion-area');
|
||||
this.elements.criterion_area = oCriterionAreaElem;
|
||||
|
||||
// Clean area
|
||||
oCriterionAreaElem
|
||||
.html('')
|
||||
.append('<div class="sf_criterion_row"></div>');
|
||||
.append('<div class="sf_criterion_row ibo-criterion-row"></div>');
|
||||
|
||||
// Prepare content
|
||||
this._prepareMoreCriterionMenu();
|
||||
this._prepareExistingCriterion();
|
||||
this._prepareMoreCriterionMenu();
|
||||
this._prepareSubmitButton();
|
||||
},
|
||||
// - Prepare "more" button
|
||||
@@ -398,7 +398,7 @@ $(function()
|
||||
|
||||
// Header part
|
||||
var oHeaderElem = $('<div class="sfm_header"></div>')
|
||||
.append('<a class="sfm_toggler" href="#"><span class="sfm_tg_title">' + Dict.S('UI:Search:Criterion:MoreMenu:AddCriteria') + '</span><span class="sfm_tg_icon fas fa-plus"></span></a>')
|
||||
.append('<a class="sfm_toggler" href="#"><span class="sfm_tg_icon fas fa-plus"></span></a>')
|
||||
.appendTo(this.elements.more_criterion);
|
||||
|
||||
// Content part
|
||||
@@ -695,7 +695,7 @@ $(function()
|
||||
else
|
||||
{
|
||||
var oCriterionRowElem = $('<div></div>')
|
||||
.addClass('sf_criterion_row')
|
||||
.addClass('sf_criterion_row ibo-criterion-row')
|
||||
.appendTo(this.elements.criterion_area);
|
||||
}
|
||||
|
||||
@@ -706,7 +706,7 @@ $(function()
|
||||
else
|
||||
{
|
||||
var oCriterionGroupElem = $('<div></div>')
|
||||
.addClass('sf_criterion_group')
|
||||
.addClass('sf_criterion_group ibo-criterion-group')
|
||||
.appendTo(oCriterionRowElem);
|
||||
}
|
||||
|
||||
@@ -754,7 +754,7 @@ $(function()
|
||||
oResultAreaElem = $('<div class="display_block"></div>').insertAfter(this.element.closest('.display_block'));
|
||||
}
|
||||
}
|
||||
oResultAreaElem.addClass('sf_results_area');
|
||||
//oResultAreaElem.addClass('display_block sf_results_area');
|
||||
|
||||
// Make placeholder if nothing yet
|
||||
if(oResultAreaElem.html() === '')
|
||||
|
||||
@@ -262,11 +262,11 @@ function UpdateFileName(id, sNewFileName) {
|
||||
* Reload a search form for the specified class
|
||||
*/
|
||||
function ReloadSearchForm(divId, sClassName, sBaseClass, sContext, sTableId, sExtraParams) {
|
||||
var oDiv = $('#ds_'+divId);
|
||||
var oDiv = $('#'+divId);
|
||||
oDiv.block();
|
||||
// deprecated in jQuery 1.8
|
||||
//var oFormEvents = $('#ds_'+divId+' form').data('events');
|
||||
var oForm = $('#ds_'+divId+' form');
|
||||
var oForm = $('#'+divId+' form');
|
||||
var oFormEvents = $._data(oForm[0], "events");
|
||||
|
||||
// Save the submit handlers
|
||||
@@ -276,11 +276,11 @@ function ReloadSearchForm(divId, sClassName, sBaseClass, sContext, sTableId, sEx
|
||||
aSubmit [index] = {data: oFormEvents.submit[index].data, namespace: oFormEvents.submit[index].namespace, handler: oFormEvents.submit[index].handler};
|
||||
}
|
||||
}
|
||||
sAction = $('#ds_'+divId+' form').attr('action');
|
||||
sAction = $('#'+divId+' form').attr('action');
|
||||
|
||||
// Save the current values in the form
|
||||
var oMap = {};
|
||||
$('#ds_'+divId+" form :input[name!='']").each(function () {
|
||||
$('#'+divId+" form :input[name!='']").each(function () {
|
||||
oMap[this.name] = this.value;
|
||||
});
|
||||
oMap.operation = 'search_form';
|
||||
|
||||
@@ -161,6 +161,9 @@ return array(
|
||||
'Combodo\\iTop\\Application\\UI\\Component\\Dashlet\\DashletContainer' => $baseDir . '/sources/application/UI/Component/Dashlet/DashletContainer.php',
|
||||
'Combodo\\iTop\\Application\\UI\\Component\\Dashlet\\DashletFactory' => $baseDir . '/sources/application/UI/Component/Dashlet/DashletFactory.php',
|
||||
'Combodo\\iTop\\Application\\UI\\Component\\Dashlet\\DashletHeaderStatic' => $baseDir . '/sources/application/UI/Component/Dashlet/DashletHeaderStatic.php',
|
||||
'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\\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',
|
||||
@@ -331,7 +334,6 @@ return array(
|
||||
'DashletProxy' => $baseDir . '/application/dashlet.class.inc.php',
|
||||
'DashletUnknown' => $baseDir . '/application/dashlet.class.inc.php',
|
||||
'DataTable' => $baseDir . '/application/datatable.class.inc.php',
|
||||
'DataTableSettings' => $baseDir . '/application/datatable.class.inc.php',
|
||||
'Datamatrix' => $vendorDir . '/combodo/tcpdf/include/barcodes/datamatrix.php',
|
||||
'DateTimeFormat' => $baseDir . '/core/datetimeformat.class.inc.php',
|
||||
'DeadLockLog' => $baseDir . '/core/log.class.inc.php',
|
||||
|
||||
@@ -391,6 +391,9 @@ class ComposerStaticInit0018331147de7601e7552f7da8e3bb8b
|
||||
'Combodo\\iTop\\Application\\UI\\Component\\Dashlet\\DashletContainer' => __DIR__ . '/../..' . '/sources/application/UI/Component/Dashlet/DashletContainer.php',
|
||||
'Combodo\\iTop\\Application\\UI\\Component\\Dashlet\\DashletFactory' => __DIR__ . '/../..' . '/sources/application/UI/Component/Dashlet/DashletFactory.php',
|
||||
'Combodo\\iTop\\Application\\UI\\Component\\Dashlet\\DashletHeaderStatic' => __DIR__ . '/../..' . '/sources/application/UI/Component/Dashlet/DashletHeaderStatic.php',
|
||||
'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\\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',
|
||||
@@ -561,7 +564,6 @@ class ComposerStaticInit0018331147de7601e7552f7da8e3bb8b
|
||||
'DashletProxy' => __DIR__ . '/../..' . '/application/dashlet.class.inc.php',
|
||||
'DashletUnknown' => __DIR__ . '/../..' . '/application/dashlet.class.inc.php',
|
||||
'DataTable' => __DIR__ . '/../..' . '/application/datatable.class.inc.php',
|
||||
'DataTableSettings' => __DIR__ . '/../..' . '/application/datatable.class.inc.php',
|
||||
'Datamatrix' => __DIR__ . '/..' . '/combodo/tcpdf/include/barcodes/datamatrix.php',
|
||||
'DateTimeFormat' => __DIR__ . '/../..' . '/core/datetimeformat.class.inc.php',
|
||||
'DeadLockLog' => __DIR__ . '/../..' . '/core/log.class.inc.php',
|
||||
|
||||
|
Before Width: | Height: | Size: 160 B After Width: | Height: | Size: 160 B |
|
Before Width: | Height: | Size: 148 B After Width: | Height: | Size: 148 B |
|
Before Width: | Height: | Size: 201 B After Width: | Height: | Size: 201 B |
|
Before Width: | Height: | Size: 158 B After Width: | Height: | Size: 158 B |
|
Before Width: | Height: | Size: 146 B After Width: | Height: | Size: 146 B |
27
pages/UI.php
@@ -208,6 +208,7 @@ function SetObjectBreadCrumbEntry(DBObject $oObj, WebPage $oPage)
|
||||
*/
|
||||
function DisplaySearchSet($oP, $oFilter, $bSearchForm = true, $sBaseClass = '', $sFormat = '', $bDoSearch = true, $bSearchFormOpen = true)
|
||||
{
|
||||
$oBlockForm=null;
|
||||
if ($bSearchForm)
|
||||
{
|
||||
$aParams = array('open' => $bSearchFormOpen, 'table_id' => '1');
|
||||
@@ -215,22 +216,24 @@ function DisplaySearchSet($oP, $oFilter, $bSearchForm = true, $sBaseClass = '',
|
||||
{
|
||||
$aParams['baseClass'] = $sBaseClass;
|
||||
}
|
||||
$oBlock = new DisplayBlock($oFilter, 'search', false /* Asynchronous */, $aParams);
|
||||
$oBlock->Display($oP, 0);
|
||||
$oBlockForm = new DisplayBlock($oFilter, 'search', false /* Asynchronous */, $aParams);
|
||||
|
||||
if (!$bDoSearch)
|
||||
{
|
||||
$oBlockForm->Display($oP, 0);
|
||||
}
|
||||
}
|
||||
if ($bDoSearch)
|
||||
{
|
||||
if (strtolower($sFormat) == 'csv')
|
||||
{
|
||||
$oBlock = new DisplayBlock($oFilter, 'csv', false);
|
||||
$oBlock->Display($oP, 1);
|
||||
// Adjust the size of the Textarea containing the CSV to fit almost all the remaining space
|
||||
$oP->add_ready_script(" $('#1>textarea').height($('#1').parent().height() - $('#0').outerHeight() - 30).width( $('#1').parent().width() - 20);"); // adjust the size of the block
|
||||
}
|
||||
else
|
||||
{
|
||||
$oBlock = new DisplayBlock($oFilter, 'list', false);
|
||||
$oBlock->Display($oP, 1);
|
||||
|
||||
// Breadcrumb
|
||||
//$iCount = $oBlock->GetDisplayedCount();
|
||||
@@ -238,6 +241,22 @@ function DisplaySearchSet($oP, $oFilter, $bSearchForm = true, $sBaseClass = '',
|
||||
$sLabel = MetaModel::GetName($oFilter->GetClass());
|
||||
$oP->SetBreadCrumbEntry($sPageId, $sLabel, '', '', 'fas fa-search', iTopWebPage::ENUM_BREADCRUMB_ENTRY_ICON_TYPE_CSS_CLASSES);
|
||||
}
|
||||
if ($bSearchForm) {
|
||||
$oUIBlockForm=$oBlockForm->GetDisplay($oP,'0');
|
||||
$sTableId = utils::ReadParam('_table_id_', null, false, 'raw_data');
|
||||
if($sTableId=='')
|
||||
{
|
||||
$sTableId = '1';
|
||||
}
|
||||
$oUIBlock=$oBlock->GetDisplay($oP, $sTableId);
|
||||
$oUIBlock->AddCSSClasses("display_block sf_results_area");
|
||||
//$oUIBlockForm->AddSubBlock($oUIBlock);
|
||||
$oP->AddUiBlock($oUIBlockForm);
|
||||
$oP->AddUiBlock($oUIBlock);
|
||||
}
|
||||
else {
|
||||
$oBlock->Display($oP, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,10 +17,12 @@
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
*/
|
||||
|
||||
use Combodo\iTop\Application\UI\Component\DataTable\DataTableSettings;
|
||||
use Combodo\iTop\Application\UI\Layout\ActivityPanel\ActivityEntry\ActivityEntryFactory;
|
||||
use Combodo\iTop\Controller\AjaxRenderController;
|
||||
use Combodo\iTop\Renderer\BlockRenderer;
|
||||
use Combodo\iTop\Renderer\Console\ConsoleFormRenderer;
|
||||
use Combodo\iTop\Application\UI\Component\DataTable\DataTableFactory;
|
||||
|
||||
require_once('../approot.inc.php');
|
||||
require_once(APPROOT.'application/application.inc.php');
|
||||
@@ -67,7 +69,7 @@ try
|
||||
}
|
||||
LoginWebPage::DoLoginEx($sRequestedPortalId, false);
|
||||
|
||||
$oPage = new ajax_page("");
|
||||
$oPage = new AjaxPage("");
|
||||
$oPage->no_cache();
|
||||
|
||||
|
||||
@@ -230,6 +232,190 @@ try
|
||||
$oKPI->ComputeAndReport('Data fetch and format');
|
||||
break;
|
||||
|
||||
case 'search_and_refresh':
|
||||
$oPage->SetContentType('application/json');
|
||||
$extraParams = utils::ReadParam('extra_param', '', false, 'raw_data');
|
||||
$aExtraParams = array();
|
||||
if (is_array($extraParams))
|
||||
{
|
||||
$aExtraParams = $extraParams;
|
||||
}
|
||||
else
|
||||
{
|
||||
$sExtraParams = stripslashes($extraParams);
|
||||
if (!empty($sExtraParams))
|
||||
{
|
||||
$val = json_decode(str_replace("'", '"', $sExtraParams), true /* associative array */);
|
||||
if ($val !== null)
|
||||
{
|
||||
$aExtraParams = $val;
|
||||
}
|
||||
}
|
||||
}
|
||||
$iLength = utils::ReadParam('end', 10);
|
||||
$aColumns = utils::ReadParam('columns', array(), false, 'raw_data');
|
||||
$sSelectMode = utils::ReadParam('select_mode', '');
|
||||
$aResult = DataTableFactory::GetOptionsForRendering( $aColumns, $sSelectMode, $sFilter, $iLength, $aExtraParams);
|
||||
$oPage->add(json_encode($aResult));
|
||||
break;
|
||||
|
||||
case 'search':
|
||||
$oPage->SetContentType('application/json');
|
||||
$extraParams = utils::ReadParam('extra_param', '', false, 'raw_data');
|
||||
$aExtraParams = array();
|
||||
if (is_array($extraParams))
|
||||
{
|
||||
$aExtraParams = $extraParams;
|
||||
}
|
||||
else
|
||||
{
|
||||
$sExtraParams = stripslashes($extraParams);
|
||||
if (!empty($sExtraParams))
|
||||
{
|
||||
$val = json_decode(str_replace("'", '"', $sExtraParams), true /* associative array */);
|
||||
if ($val !== null)
|
||||
{
|
||||
$aExtraParams = $val;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($sEncoding == 'oql')
|
||||
{
|
||||
$oFilter = DBSearch::FromOQL($sFilter);
|
||||
}
|
||||
else
|
||||
{
|
||||
$oFilter = DBSearch::unserialize($sFilter);
|
||||
}
|
||||
$iStart = utils::ReadParam('start', 0);
|
||||
$iEnd = utils::ReadParam('end', 1);
|
||||
$iDrawNumber= utils::ReadParam('draw', 1);
|
||||
|
||||
$iSortCol = utils::ReadParam('sort_col', 'null');
|
||||
$sSelectMode = utils::ReadParam('select_mode', '');
|
||||
if (!empty($sSelectMode) && ($sSelectMode != 'none'))
|
||||
{
|
||||
// The first column is used for the selection (radio / checkbox) and is not sortable
|
||||
$iSortCol--;
|
||||
}
|
||||
$bDisplayKey = utils::ReadParam('display_key', 'true') == 'true';
|
||||
$aColumns = utils::ReadParam('columns', array(), false, 'raw_data');
|
||||
$aClassAliases = utils::ReadParam('class_aliases', array());
|
||||
$iListId = utils::ReadParam('list_id', 0);
|
||||
|
||||
// Filter the list to removed linked set since we are not able to display them here
|
||||
$sIdName ="";
|
||||
$aOrderBy = array();
|
||||
$iSortIndex = 0;
|
||||
|
||||
$aColumnsLoad = array();
|
||||
foreach($aClassAliases as $sAlias => $sClassName)
|
||||
{
|
||||
$aColumnsLoad[$sAlias] = array();
|
||||
foreach($aColumns[$sAlias] as $sAttCode => $aData)
|
||||
{
|
||||
if ($aData['checked'] == 'true')
|
||||
{
|
||||
$aColumns[$sAlias][$sAttCode]['checked'] = true;
|
||||
if ($sAttCode == '_key_')
|
||||
{
|
||||
if($sIdName == ""){
|
||||
$sIdName = $sAlias."/_key_";
|
||||
}
|
||||
if ($iSortCol == $iSortIndex)
|
||||
{
|
||||
if (!MetaModel::HasChildrenClasses($oFilter->GetClass()))
|
||||
{
|
||||
$aNameSpec = MetaModel::GetNameSpec($oFilter->GetClass());
|
||||
if ($aNameSpec[0] == '%1$s')
|
||||
{
|
||||
// The name is made of a single column, let's sort according to the sort algorithm for this column
|
||||
$aOrderBy[$sAlias.'.'.$aNameSpec[1][0]] = (utils::ReadParam('sort_order', 'asc') == 'asc');
|
||||
}
|
||||
else
|
||||
{
|
||||
$aOrderBy[$sAlias.'.'.'friendlyname'] = (utils::ReadParam('sort_order', 'asc') == 'asc');
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$aOrderBy[$sAlias.'.'.'friendlyname'] = (utils::ReadParam('sort_order', 'asc') == 'asc');
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$oAttDef = MetaModel::GetAttributeDef($sClassName, $sAttCode);
|
||||
if ($oAttDef instanceof AttributeLinkedSet)
|
||||
{
|
||||
// Removed from the display list
|
||||
unset($aColumns[$sAlias][$sAttCode]);
|
||||
}
|
||||
else
|
||||
{
|
||||
$aColumnsLoad[$sAlias][] = $sAttCode;
|
||||
}
|
||||
if ($iSortCol == $iSortIndex)
|
||||
{
|
||||
if ($oAttDef->IsExternalKey())
|
||||
{
|
||||
$sSortCol = $sAttCode.'_friendlyname';
|
||||
}
|
||||
else
|
||||
{
|
||||
$sSortCol = $sAttCode;
|
||||
}
|
||||
$aOrderBy[$sAlias.'.'.$sSortCol] = (utils::ReadParam('sort_order', 'asc') == 'asc');
|
||||
}
|
||||
}
|
||||
$iSortIndex++;
|
||||
}
|
||||
else
|
||||
{
|
||||
$aColumns[$sAlias][$sAttCode]['checked'] = false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Load only the requested columns
|
||||
$oSet = new DBObjectSet($oFilter, $aOrderBy, $aExtraParams, null, $iEnd - $iStart, $iStart);
|
||||
$oSet->OptimizeColumnLoad($aColumnsLoad);
|
||||
|
||||
if (isset($aExtraParams['show_obsolete_data'])) {
|
||||
$bShowObsoleteData = $aExtraParams['show_obsolete_data'];
|
||||
}
|
||||
else {
|
||||
$bShowObsoleteData = utils::ShowObsoleteData();
|
||||
}
|
||||
$oSet->SetShowObsoleteData($bShowObsoleteData);
|
||||
$oKPI = new ExecutionKPI();
|
||||
$aResult["draw"] = $iDrawNumber;
|
||||
$aResult["recordsTotal"] = $oSet->Count() ;
|
||||
$aResult["recordsFiltered"] = $oSet->Count() ;
|
||||
$aResult["data"] = [];
|
||||
while ($aObject = $oSet->FetchAssoc()) {
|
||||
foreach($aClassAliases as $sAlias=>$sClass) {
|
||||
foreach($aColumns[$sAlias] as $sAttCode => $oAttDef) {
|
||||
if($sAttCode=="_key_") {
|
||||
$aObj[$sAlias."/".$sAttCode ] = $aObject[$sAlias]->GetKey();
|
||||
}
|
||||
else {
|
||||
$aObj[$sAlias."/".$sAttCode ] = $aObject[$sAlias]->Get($sAttCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
if($sIdName!="")
|
||||
{
|
||||
$aObj["id" ] = $aObj[$sIdName];
|
||||
}
|
||||
array_push($aResult["data"], $aObj);
|
||||
}
|
||||
|
||||
$oPage->add(json_encode($aResult));
|
||||
$oKPI->ComputeAndReport('Data fetch and format');
|
||||
break;
|
||||
|
||||
case 'datatable_save_settings':
|
||||
$oPage->SetContentType('text/plain');
|
||||
$iPageSize = utils::ReadParam('page_size', 10);
|
||||
|
||||
@@ -47,7 +47,7 @@ try
|
||||
throw new AjaxSearchException("Invalid query (empty filter)", 400);
|
||||
}
|
||||
|
||||
$oPage = new ajax_page("");
|
||||
$oPage = new AjaxPage("");
|
||||
$oPage->no_cache();
|
||||
$oPage->SetContentType('text/html');
|
||||
|
||||
|
||||
127
sources/application/UI/Component/DataTable/DataTable.php
Normal file
@@ -0,0 +1,127 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2020 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\Application\UI\Component\DataTable;
|
||||
|
||||
|
||||
use Combodo\iTop\Application\UI\Layout\UIContentBlock;
|
||||
|
||||
/**
|
||||
* Class DataTable
|
||||
*
|
||||
* @package Combodo\iTop\Application\UI\Component\DataTable
|
||||
* @since 3.0.0
|
||||
*/
|
||||
class DataTableBlock extends UIContentBlock
|
||||
{
|
||||
// Overloaded constants
|
||||
public const BLOCK_CODE = 'ibo-datatable';
|
||||
public const HTML_TEMPLATE_REL_PATH = 'components/datatable/layout';
|
||||
public const JS_TEMPLATE_REL_PATH = 'components/datatable/layout';
|
||||
|
||||
protected $aOptions;//list of specific options for display datatable
|
||||
protected $sAjaxUrl;
|
||||
protected $sAjaxData;
|
||||
protected $aDisplayColumns;
|
||||
protected $aResultColumns;
|
||||
|
||||
/**
|
||||
* Panel constructor.
|
||||
*
|
||||
*/
|
||||
public function __construct(?string $sId = null)
|
||||
{
|
||||
parent::__construct($sId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function GetAjaxUrl(): string
|
||||
{
|
||||
return $this->sAjaxUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $sAjaxUrl
|
||||
*/
|
||||
public function SetAjaxUrl(string $sAjaxUrl): void
|
||||
{
|
||||
$this->sAjaxUrl = $sAjaxUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function GetAjaxData(): string
|
||||
{
|
||||
return $this->sAjaxData;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $sAjaxData
|
||||
*/
|
||||
public function SetAjaxData(string $sAjaxData): void
|
||||
{
|
||||
$this->sAjaxData = $sAjaxData;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function GetDisplayColumns(): array
|
||||
{
|
||||
return $this->aDisplayColumns;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $aColumns
|
||||
*/
|
||||
public function SetDisplayColumns($aColumns): void
|
||||
{
|
||||
$this->aDisplayColumns = $aColumns;
|
||||
}
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function GetResultColumns(): array
|
||||
{
|
||||
return $this->aResultColumns;
|
||||
}
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function GetResultColumnsAsJson(): string
|
||||
{
|
||||
return json_encode($this->aResultColumns);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $aColumns
|
||||
*/
|
||||
public function SetResultColumns($aColumns): void
|
||||
{
|
||||
$this->aResultColumns = $aColumns;
|
||||
}
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function GetOptions(): array
|
||||
{
|
||||
return $this->aOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $aOptions
|
||||
*/
|
||||
public function SetOptions($aOptions): void
|
||||
{
|
||||
$this->aOptions = $aOptions;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
589
sources/application/UI/Component/DataTable/DataTableFactory.php
Normal file
@@ -0,0 +1,589 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2020 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\Application\UI\Component\DataTable;
|
||||
|
||||
use CMDBObjectSet;
|
||||
use cmdbAbstractObject;
|
||||
use Combodo\iTop\Application\UI\Component\Html\Html;
|
||||
use Combodo\iTop\Application\UI\Component\Panel\PanelFactory;
|
||||
use MetaModel;
|
||||
use appUserPreferences;
|
||||
use UserRights;
|
||||
use MenuBlock;
|
||||
use Combodo\iTop\Application\UI\Layout\UIContentBlock;
|
||||
use WebPage;
|
||||
use Dict;
|
||||
|
||||
/**
|
||||
* Class DataTableFactory
|
||||
*
|
||||
* @internal
|
||||
* @package Combodo\iTop\Application\UI\Component\DataTable
|
||||
* @since 3.0.0
|
||||
*/
|
||||
class DataTableFactory
|
||||
{
|
||||
public static function MakeForResult(WebPage $oPage, string $sListId, CMDBObjectSet $oSet, $aExtraParams = array())
|
||||
{
|
||||
$oPanel = PanelFactory::MakeForClass( $oSet->GetClass(), "Result");
|
||||
$oDataTable = DataTableFactory::MakeForRendering( $sListId, $oSet, $aExtraParams );
|
||||
$oPanel->AddMainBlock($oDataTable);
|
||||
|
||||
$oMenuBlock = new MenuBlock($oSet->GetFilter(), 'list');
|
||||
$oBlock = $oMenuBlock->GetRenderContent($oPage, $aExtraParams, $sListId);
|
||||
$oBlockMenu = new UIContentBlock();
|
||||
$oBlockMenu->AddSubBlock($oBlock);
|
||||
$oPanel->AddToolbarBlock($oBlockMenu);
|
||||
|
||||
return $oPanel;
|
||||
}
|
||||
public static function MakeForObject(WebPage $oPage, string $sListId, CMDBObjectSet $oSet, $aExtraParams = array())
|
||||
{
|
||||
$oPanel = PanelFactory::MakeForClass( $oSet->GetClass(), "Result");
|
||||
$oDataTable = DataTableFactory::MakeForRenderingObject( $sListId, $oSet, $aExtraParams );
|
||||
$oPanel->AddMainBlock($oDataTable);
|
||||
|
||||
$oMenuBlock = new MenuBlock($oSet->GetFilter(), 'list');
|
||||
$oBlock = $oMenuBlock->GetRenderContent($oPage, $aExtraParams, $sListId);
|
||||
$oBlockMenu = new UIContentBlock();
|
||||
$oBlockMenu->AddSubBlock($oBlock);
|
||||
$oPanel->AddToolbarBlock($oBlockMenu);
|
||||
|
||||
return $oPanel;
|
||||
}
|
||||
/**
|
||||
* Make a basis Panel component
|
||||
*
|
||||
* @param string $sTitle
|
||||
*
|
||||
* @return DataTableBlock
|
||||
*/
|
||||
public static function MakeForRendering(string $sListId, CMDBObjectSet $oSet, $aExtraParams = array())
|
||||
{
|
||||
$oDataTable = new DataTableBlock('datatable_'.$sListId);
|
||||
///////////////////////////////////////////////////
|
||||
/*TODO 3.0.0 PrintableVersion
|
||||
if ($oPage->IsPrintableVersion() || $oPage->is_pdf())
|
||||
{
|
||||
return self::GetDisplaySetForPrinting($oPage, $oSet, $aExtraParams);
|
||||
}
|
||||
*/
|
||||
|
||||
// Initialize and check the parameters
|
||||
$bViewLink = isset($aExtraParams['view_link']) ? $aExtraParams['view_link'] : true;
|
||||
$sLinkageAttribute = isset($aExtraParams['link_attr']) ? $aExtraParams['link_attr'] : '';
|
||||
$iLinkedObjectId = isset($aExtraParams['object_id']) ? $aExtraParams['object_id'] : 0;
|
||||
$sTargetAttr = isset($aExtraParams['target_attr']) ? $aExtraParams['target_attr'] : '';
|
||||
if (!empty($sLinkageAttribute)) {
|
||||
if ($iLinkedObjectId == 0) {
|
||||
// if 'links' mode is requested the id of the object to link to must be specified
|
||||
throw new ApplicationException(Dict::S('UI:Error:MandatoryTemplateParameter_object_id'));
|
||||
}
|
||||
if ($sTargetAttr == '') {
|
||||
// if 'links' mode is requested the d of the object to link to must be specified
|
||||
throw new ApplicationException(Dict::S('UI:Error:MandatoryTemplateParameter_target_attr'));
|
||||
}
|
||||
}
|
||||
$bSelectMode = isset($aExtraParams['selection_mode']) ? $aExtraParams['selection_mode'] == true : false;
|
||||
$bSingleSelectMode = isset($aExtraParams['selection_type']) ? ($aExtraParams['selection_type'] == 'single') : false;
|
||||
|
||||
$aExtraFieldsRaw = isset($aExtraParams['extra_fields']) ? explode(',',
|
||||
trim($aExtraParams['extra_fields'])) : array();
|
||||
$aExtraFields = array();
|
||||
foreach ($aExtraFieldsRaw as $sFieldName) {
|
||||
// Ignore attributes not of the main queried class
|
||||
if (preg_match('/^(.*)\.(.*)$/', $sFieldName, $aMatches)) {
|
||||
$sClassAlias = $aMatches[1];
|
||||
$sAttCode = $aMatches[2];
|
||||
if ($sClassAlias == $oSet->GetFilter()->GetClassAlias()) {//$oSet->GetFilter()->GetSelectedClasses()
|
||||
$aExtraFields[] = $sAttCode;
|
||||
}
|
||||
} else {
|
||||
$aExtraFields[] = $sFieldName;
|
||||
}
|
||||
}
|
||||
$sClassName = $oSet->GetFilter()->GetClass();
|
||||
$sZListName = isset($aExtraParams['zlist']) ? ($aExtraParams['zlist']) : 'list';
|
||||
if ($sZListName !== false) {
|
||||
$aList = cmdbAbstractObject::FlattenZList(MetaModel::GetZListItems($sClassName, $sZListName));
|
||||
$aList = array_merge($aList, $aExtraFields);
|
||||
} else {
|
||||
$aList = $aExtraFields;
|
||||
}
|
||||
|
||||
// Filter the list to removed linked set since we are not able to display them here
|
||||
foreach ($aList as $index => $sAttCode) {
|
||||
$oAttDef = MetaModel::GetAttributeDef($sClassName, $sAttCode);
|
||||
if ($oAttDef instanceof AttributeLinkedSet) {
|
||||
// Removed from the display list
|
||||
unset($aList[$index]);
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($sLinkageAttribute)) {
|
||||
// The set to display is in fact a set of links between the object specified in the $sLinkageAttribute
|
||||
// and other objects...
|
||||
// The display will then group all the attributes related to the link itself:
|
||||
// | Link_attr1 | link_attr2 | ... || Object_attr1 | Object_attr2 | Object_attr3 | .. | Object_attr_n |
|
||||
$aDisplayList = array();
|
||||
$aAttDefs = MetaModel::ListAttributeDefs($sClassName);
|
||||
assert(isset($aAttDefs[$sLinkageAttribute]));
|
||||
$oAttDef = $aAttDefs[$sLinkageAttribute];
|
||||
assert($oAttDef->IsExternalKey());
|
||||
// First display all the attributes specific to the link record
|
||||
foreach ($aList as $sLinkAttCode) {
|
||||
$oLinkAttDef = $aAttDefs[$sLinkAttCode];
|
||||
if ((!$oLinkAttDef->IsExternalKey()) && (!$oLinkAttDef->IsExternalField())) {
|
||||
$aDisplayList[] = $sLinkAttCode;
|
||||
}
|
||||
}
|
||||
// Then display all the attributes neither specific to the link record nor to the 'linkage' object (because the latter are constant)
|
||||
foreach ($aList as $sLinkAttCode) {
|
||||
$oLinkAttDef = $aAttDefs[$sLinkAttCode];
|
||||
if (($oLinkAttDef->IsExternalKey() && ($sLinkAttCode != $sLinkageAttribute))
|
||||
|| ($oLinkAttDef->IsExternalField() && ($oLinkAttDef->GetKeyAttCode() != $sLinkageAttribute))) {
|
||||
$aDisplayList[] = $sLinkAttCode;
|
||||
}
|
||||
}
|
||||
// First display all the attributes specific to the link
|
||||
// Then display all the attributes linked to the other end of the relationship
|
||||
$aList = $aDisplayList;
|
||||
}
|
||||
|
||||
$sSelectMode = 'none';
|
||||
if ($bSelectMode) {
|
||||
$sSelectMode = $bSingleSelectMode ? 'single' : 'multiple';
|
||||
}
|
||||
|
||||
$sClassAlias = $oSet->GetClassAlias();
|
||||
$bDisplayLimit = isset($aExtraParams['display_limit']) ? $aExtraParams['display_limit'] : true;
|
||||
|
||||
$sTableId = isset($aExtraParams['table_id']) ? $aExtraParams['table_id'] : null;
|
||||
$aClassAliases = array($sClassAlias => $sClassName);
|
||||
$oDefaultSettings = DataTableSettings::GetDataModelSettings($aClassAliases, $bViewLink, array($sClassAlias => $aList));
|
||||
|
||||
if ($bDisplayLimit) {
|
||||
$iDefaultPageSize = appUserPreferences::GetPref('default_page_size', MetaModel::GetConfig()->GetMinDisplayLimit());
|
||||
$oDefaultSettings->iDefaultPageSize = $iDefaultPageSize;
|
||||
} else {
|
||||
$oDefaultSettings->iDefaultPageSize = 0;
|
||||
}
|
||||
$oDefaultSettings->aSortOrder = MetaModel::GetOrderByDefault($sClassName);
|
||||
|
||||
$bUseCustomSettings = false;
|
||||
// Identified tables can have their own specific settings
|
||||
$oCustomSettings = DataTableSettings::GetTableSettings($aClassAliases, $sTableId);
|
||||
|
||||
if ($oCustomSettings != null) {
|
||||
// Custom settings overload the default ones
|
||||
$bUseCustomSettings = true;
|
||||
if ($oDefaultSettings->iDefaultPageSize == 0) {
|
||||
$oCustomSettings->iDefaultPageSize = 0;
|
||||
}
|
||||
} else {
|
||||
$oCustomSettings = $oDefaultSettings;
|
||||
}
|
||||
|
||||
if ($oCustomSettings->iDefaultPageSize > 0) {
|
||||
$oSet->SetLimit($oCustomSettings->iDefaultPageSize);
|
||||
}
|
||||
$oSet->SetOrderBy($oCustomSettings->GetSortOrder());
|
||||
|
||||
// Load only the requested columns
|
||||
$aColumnsToLoad = array();
|
||||
foreach ($oCustomSettings->aColumns as $sAlias => $aColumnsInfo) {
|
||||
foreach ($aColumnsInfo as $sAttCode => $aData) {
|
||||
if ($sAttCode != '_key_') {
|
||||
if ($aData['checked']) {
|
||||
$aColumnsToLoad[$sAlias][] = $sAttCode;
|
||||
} else {
|
||||
// See if this column is a must to load
|
||||
$sClass = $aClassAliases[$sAlias];
|
||||
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
|
||||
if ($oAttDef->alwaysLoadInTables()) {
|
||||
$aColumnsToLoad[$sAlias][] = $sAttCode;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$oSet->OptimizeColumnLoad($aColumnsToLoad);
|
||||
|
||||
$aColumnDefinition = [];
|
||||
foreach ($aClassAliases as $sClassAlias => $sClassName) {
|
||||
foreach ($oCustomSettings->aColumns[$sClassAlias] as $sAttCode => $aData) {
|
||||
if ($aData['checked']) {
|
||||
if ($sAttCode == '_key_') {
|
||||
$aColumnDefinition[] = [
|
||||
'description' => $aData['label'],
|
||||
'object_class' => $sClassName,
|
||||
'class_alias' => $sClassAlias,
|
||||
'attribute_code' => $sAttCode,
|
||||
'attribute_type' => '_key_',
|
||||
'attribute_label' => $aData['alias'],
|
||||
"render" => "return '<a class=\'object-ref-link\' href= \'UI.php?operation=details&class=".$sClassName."&id='+data+'\'>'+row['".$sClassAlias."/friendlyname']+'</a>' ;",
|
||||
];
|
||||
} else {
|
||||
$oAttDef = MetaModel::GetAttributeDef($sClassName, $sAttCode);
|
||||
$sAttDefClass = get_class($oAttDef);
|
||||
$sAttLabel = MetaModel::GetLabel($sClassName, $sAttCode);
|
||||
$aColumnDefinition[] = [
|
||||
'description' => $oAttDef->GetOrderByHint(),
|
||||
'object_class' => $sClassName,
|
||||
'class_alias' => $sClassAlias,
|
||||
'attribute_code' => $sAttCode,
|
||||
'attribute_type' => $sAttDefClass,
|
||||
'attribute_label' => $sAttLabel,
|
||||
"render" => $oAttDef->GetRenderForDataTable($sClassAlias),
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$aOptions = [];
|
||||
if($oDefaultSettings != null)
|
||||
{
|
||||
$aOptions['oDefaultSettings'] = json_encode(array('iDefaultPageSize' => $oDefaultSettings->iDefaultPageSize, 'oColumns' => $oDefaultSettings->aColumns));
|
||||
}
|
||||
|
||||
if ($sSelectMode == 'multiple') {
|
||||
$aOptions['select'] = "multi";
|
||||
} else if ($sSelectMode == 'single') {
|
||||
$aOptions['select'] = "single";
|
||||
}
|
||||
|
||||
$aOptions['iPageSize'] = 10;
|
||||
if ($oCustomSettings->iDefaultPageSize > 0) {
|
||||
$aOptions['iPageSize'] = $oCustomSettings->iDefaultPageSize;
|
||||
}
|
||||
|
||||
$aOptions['sTableId'] =$sTableId;
|
||||
$aOptions['bUseCustomSettings'] =$bUseCustomSettings;
|
||||
$aOptions['bViewLink'] =$bViewLink;
|
||||
|
||||
$oDataTable->SetOptions($aOptions);
|
||||
$oDataTable->SetAjaxUrl("ajax.render.php");
|
||||
$oDataTable->SetAjaxData(json_encode([
|
||||
"operation" => 'search',
|
||||
"filter" => $oSet->GetFilter()->serialize(),
|
||||
"columns" => $oCustomSettings->aColumns,
|
||||
"extra_params" => $aExtraParams,
|
||||
"class_aliases" => $aClassAliases,
|
||||
]));
|
||||
$oDataTable->SetDisplayColumns($aColumnDefinition);
|
||||
$oDataTable->SetResultColumns($oCustomSettings->aColumns);
|
||||
|
||||
return $oDataTable;
|
||||
}
|
||||
public static function MakeForRenderingObject(string $sListId, CMDBObjectSet $oSet, $aExtraParams = array())
|
||||
{
|
||||
$oDataTable = new DataTableBlock('datatable_'.$sListId);
|
||||
$aList = array();
|
||||
|
||||
// Initialize and check the parameters
|
||||
$bViewLink = isset($aExtraParams['view_link']) ? $aExtraParams['view_link'] : true;
|
||||
// Check if there is a list of aliases to limit the display to...
|
||||
$aDisplayAliases = isset($aExtraParams['display_aliases']) ? explode(',',
|
||||
$aExtraParams['display_aliases']) : array();
|
||||
$sZListName = isset($aExtraParams['zlist']) ? ($aExtraParams['zlist']) : 'list';
|
||||
|
||||
$aExtraFieldsRaw = isset($aExtraParams['extra_fields']) ? explode(',',
|
||||
trim($aExtraParams['extra_fields'])) : array();
|
||||
$aExtraFields = array();
|
||||
$sAttCode = '';
|
||||
foreach($aExtraFieldsRaw as $sFieldName)
|
||||
{
|
||||
// Ignore attributes not of the main queried class
|
||||
if (preg_match('/^(.*)\.(.*)$/', $sFieldName, $aMatches))
|
||||
{
|
||||
$sClassAlias = $aMatches[1];
|
||||
$sAttCode = $aMatches[2];
|
||||
if (array_key_exists($sClassAlias, $oSet->GetSelectedClasses()))
|
||||
{
|
||||
$aExtraFields[$sClassAlias][] = $sAttCode;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$aExtraFields['*'] = $sAttCode;
|
||||
}
|
||||
}
|
||||
|
||||
$aClassAliases = $oSet->GetFilter()->GetSelectedClasses();
|
||||
$aAuthorizedClasses = array();
|
||||
foreach($aClassAliases as $sAlias => $sClassName)
|
||||
{
|
||||
if ((UserRights::IsActionAllowed($sClassName, UR_ACTION_READ, $oSet) != UR_ALLOWED_NO) &&
|
||||
((count($aDisplayAliases) == 0) || (in_array($sAlias, $aDisplayAliases))))
|
||||
{
|
||||
$aAuthorizedClasses[$sAlias] = $sClassName;
|
||||
}
|
||||
}
|
||||
foreach($aAuthorizedClasses as $sAlias => $sClassName)
|
||||
{
|
||||
if (array_key_exists($sAlias, $aExtraFields))
|
||||
{
|
||||
$aList[$sAlias] = $aExtraFields[$sAlias];
|
||||
}
|
||||
else
|
||||
{
|
||||
$aList[$sAlias] = array();
|
||||
}
|
||||
if ($sZListName !== false)
|
||||
{
|
||||
$aDefaultList = self::FlattenZList(MetaModel::GetZListItems($sClassName, $sZListName));
|
||||
|
||||
$aList[$sAlias] = array_merge($aDefaultList, $aList[$sAlias]);
|
||||
}
|
||||
|
||||
// Filter the list to removed linked set since we are not able to display them here
|
||||
foreach ($aList[$sAlias] as $index => $sAttCode)
|
||||
{
|
||||
$oAttDef = MetaModel::GetAttributeDef($sClassName, $sAttCode);
|
||||
if ($oAttDef instanceof AttributeLinkedSet)
|
||||
{
|
||||
// Removed from the display list
|
||||
unset($aList[$sAlias][$index]);
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($aList[$sAlias]))
|
||||
{
|
||||
unset($aList[$sAlias], $aAuthorizedClasses[$sAlias]);
|
||||
}
|
||||
}
|
||||
|
||||
$sSelectMode = 'none';
|
||||
|
||||
$oDefaultSettings = DataTableSettings::GetDataModelSettings($aAuthorizedClasses, $bViewLink, $aList);
|
||||
|
||||
$bDisplayLimit = isset($aExtraParams['display_limit']) ? $aExtraParams['display_limit'] : true;
|
||||
if ($bDisplayLimit)
|
||||
{
|
||||
$iDefaultPageSize = appUserPreferences::GetPref('default_page_size',
|
||||
MetaModel::GetConfig()->GetMinDisplayLimit());
|
||||
$oDefaultSettings->iDefaultPageSize = $iDefaultPageSize;
|
||||
}
|
||||
|
||||
$sTableId = isset($aExtraParams['table_id']) ? $aExtraParams['table_id'] : null;
|
||||
$oDefaultSettings->aSortOrder = MetaModel::GetOrderByDefault($sClassName);
|
||||
|
||||
$bUseCustomSettings = false;
|
||||
// Identified tables can have their own specific settings
|
||||
$oCustomSettings = DataTableSettings::GetTableSettings($aClassAliases, $sTableId);
|
||||
|
||||
if ($oCustomSettings != null) {
|
||||
// Custom settings overload the default ones
|
||||
$bUseCustomSettings = true;
|
||||
if ($oDefaultSettings->iDefaultPageSize == 0) {
|
||||
$oCustomSettings->iDefaultPageSize = 0;
|
||||
}
|
||||
} else {
|
||||
$oCustomSettings = $oDefaultSettings;
|
||||
}
|
||||
|
||||
if ($oCustomSettings->iDefaultPageSize > 0) {
|
||||
$oSet->SetLimit($oCustomSettings->iDefaultPageSize);
|
||||
}
|
||||
$oSet->SetOrderBy($oCustomSettings->GetSortOrder());
|
||||
|
||||
// Load only the requested columns
|
||||
$aColumnsToLoad = array();
|
||||
foreach ($oCustomSettings->aColumns as $sAlias => $aColumnsInfo) {
|
||||
foreach ($aColumnsInfo as $sAttCode => $aData) {
|
||||
if ($sAttCode != '_key_') {
|
||||
if ($aData['checked']) {
|
||||
$aColumnsToLoad[$sAlias][] = $sAttCode;
|
||||
} else {
|
||||
// See if this column is a must to load
|
||||
$sClass = $aClassAliases[$sAlias];
|
||||
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
|
||||
if ($oAttDef->alwaysLoadInTables()) {
|
||||
$aColumnsToLoad[$sAlias][] = $sAttCode;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$oSet->OptimizeColumnLoad($aColumnsToLoad);
|
||||
|
||||
$aColumnDefinition = [];
|
||||
foreach ($aClassAliases as $sClassAlias => $sClassName) {
|
||||
foreach ($oCustomSettings->aColumns[$sClassAlias] as $sAttCode => $aData) {
|
||||
if ($aData['checked']) {
|
||||
if ($sAttCode == '_key_') {
|
||||
$aColumnDefinition[] = [
|
||||
'description' => $aData['label'],
|
||||
'object_class' => $sClassName,
|
||||
'class_alias' => $sClassAlias,
|
||||
'attribute_code' => $sAttCode,
|
||||
'attribute_type' => '_key_',
|
||||
'attribute_label' => $aData['alias'],
|
||||
"render" => "return '<a class=\'object-ref-link\' href= \'UI.php?operation=details&class=".$sClassName."&id='+data+'\'>'+row['".$sClassAlias."/friendlyname']+'</a>' ;",
|
||||
];
|
||||
} else {
|
||||
$oAttDef = MetaModel::GetAttributeDef($sClassName, $sAttCode);
|
||||
$sAttDefClass = get_class($oAttDef);
|
||||
$sAttLabel = MetaModel::GetLabel($sClassName, $sAttCode);
|
||||
$aColumnDefinition[] = [
|
||||
'description' => $oAttDef->GetOrderByHint(),
|
||||
'object_class' => $sClassName,
|
||||
'class_alias' => $sClassAlias,
|
||||
'attribute_code' => $sAttCode,
|
||||
'attribute_type' => $sAttDefClass,
|
||||
'attribute_label' => $sAttLabel,
|
||||
"render" => $oAttDef->GetRenderForDataTable($sClassAlias),
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$aOptions = [];
|
||||
if($oDefaultSettings != null)
|
||||
{
|
||||
$aOptions['oDefaultSettings'] = json_encode(array('iDefaultPageSize' => $oDefaultSettings->iDefaultPageSize, 'oColumns' => $oDefaultSettings->aColumns));
|
||||
}
|
||||
|
||||
if ($sSelectMode == 'multiple') {
|
||||
$aOptions['select'] = "multi";
|
||||
} else if ($sSelectMode == 'single') {
|
||||
$aOptions['select'] = "single";
|
||||
}
|
||||
|
||||
$aOptions['iPageSize'] = 10;
|
||||
if ($oCustomSettings->iDefaultPageSize > 0) {
|
||||
$aOptions['iPageSize'] = $oCustomSettings->iDefaultPageSize;
|
||||
}
|
||||
|
||||
$aOptions['sTableId'] =$sTableId;
|
||||
$aOptions['bUseCustomSettings'] =$bUseCustomSettings;
|
||||
$aOptions['bViewLink'] =$bViewLink;
|
||||
|
||||
$oDataTable->SetOptions($aOptions);
|
||||
$oDataTable->SetAjaxUrl("ajax.render.php");
|
||||
$oDataTable->SetAjaxData(json_encode([
|
||||
"operation" => 'search',
|
||||
"filter" => $oSet->GetFilter()->serialize(),
|
||||
"columns" => $oCustomSettings->aColumns,
|
||||
"extra_params" => $aExtraParams,
|
||||
"class_aliases" => $aClassAliases,
|
||||
]));
|
||||
$oDataTable->SetDisplayColumns($aColumnDefinition);
|
||||
$oDataTable->SetResultColumns($oCustomSettings->aColumns);
|
||||
|
||||
return $oDataTable;
|
||||
}
|
||||
public static function GetOptionsForRendering(array $aColumns,string $sSelectMode, string $sFilter, int $iLength, array $aExtraParams)
|
||||
{
|
||||
$aOptions = [];
|
||||
|
||||
$aColumnsDefinitions = [];
|
||||
$aColumnDefinition = [];
|
||||
$aClassAliases = [];
|
||||
|
||||
foreach ($aColumns as $sClassName => $aClassColumns) {
|
||||
$aClassAliases[$sClassName]=$sClassName;
|
||||
foreach ($aClassColumns as $sAttCode => $aData) {
|
||||
if ($aData['checked'] == "true") {
|
||||
$aColumnDefinition["width"] = "auto";
|
||||
$aColumnDefinition["searchable"]= false;
|
||||
$aColumnDefinition["sortable"]= true;
|
||||
$aColumnDefinition["defaultContent"]= "";
|
||||
$aColumnDefinition["type"]= "html";
|
||||
|
||||
if ($sAttCode == '_key_') {
|
||||
$aColumnDefinition["title"] =$aData['alias'];
|
||||
$aColumnDefinition['metadata'] =[
|
||||
'object_class'=> $sClassName,
|
||||
'attribute_code'=> $sAttCode,
|
||||
'attribute_type'=> '_key_',
|
||||
'attribute_label'=> $aData['alias'],
|
||||
];
|
||||
$aColumnDefinition["data"] = $sClassName."/".$sAttCode;
|
||||
$aColumnDefinition["render"] =[
|
||||
"display"=> "return '<a class=\'object-ref-link\' href=\'UI.php?operation=details&class=".$sClassName."&id='+data+'\'>'+row['".$sClassName."/friendlyname']+'</a>' ;",
|
||||
"_"=>$sClassName."/".$sAttCode,
|
||||
];
|
||||
} else {
|
||||
$oAttDef = MetaModel::GetAttributeDef($sClassName, $sAttCode);
|
||||
$sAttDefClass = get_class($oAttDef);
|
||||
$sAttLabel = MetaModel::GetLabel($sClassName, $sAttCode);
|
||||
|
||||
$aColumnDefinition["title"] =$sAttLabel;
|
||||
$aColumnDefinition['metadata'] =[
|
||||
'object_class'=> $sClassName,
|
||||
'attribute_code'=> $sAttCode,
|
||||
'attribute_type'=> $sAttDefClass,
|
||||
'attribute_label'=> $sAttLabel,
|
||||
];
|
||||
$aColumnDefinition["data"] = $sClassName."/".$sAttCode;
|
||||
$aColumnDefinition["render"] =[
|
||||
"display"=> $oAttDef->GetRenderForDataTable($sClassName),
|
||||
"_"=>$sClassName."/".$sAttCode,
|
||||
];
|
||||
}
|
||||
array_push($aColumnsDefinitions,$aColumnDefinition);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$aOptions['select'] =$sSelectMode;
|
||||
|
||||
$aOptions['pageLength'] = $iLength;
|
||||
|
||||
$sAjaxData=json_encode([
|
||||
"operation" => 'search',
|
||||
"filter" => $sFilter,
|
||||
"columns" => $aColumns,
|
||||
"extra_params" => $aExtraParams,
|
||||
"class_aliases" => $aClassAliases,
|
||||
]);
|
||||
|
||||
|
||||
$aOptions[] = [
|
||||
"language" =>
|
||||
["processing"=> Dict::Format('UI:Datatables:Language:Processing'),
|
||||
"search"=> Dict::Format('UI:Datatables:Language:Search'),
|
||||
"lengthMenu"=> Dict::Format('UI:Datatables:Language:LengthMenu'),
|
||||
"zeroRecords"=> Dict::Format('UI:Datatables:Language:ZeroRecords'),
|
||||
"info"=> Dict::Format('UI:Datatables:Language:Info'),
|
||||
"infoEmpty"=> Dict::Format('UI:Datatables:Language:InfoEmpty'),
|
||||
"infoFiltered"=> Dict::Format('UI:Datatables:Language:InfoFiltered'),
|
||||
"emptyTable"=> Dict::Format('UI:Datatables:Language:EmptyTable'),
|
||||
"paginate"=> [
|
||||
"first"=> "<<",
|
||||
"previous"=> "<",
|
||||
"next"=> ">",
|
||||
"last"=> ">>"
|
||||
],
|
||||
"aria"=> [
|
||||
"sortAscending"=> Dict::Format( 'UI:Datatables:Language:Sort:Ascending'),
|
||||
"sortDescending"=> Dict::Format('UI:Datatables:Language:Sort:Descending')
|
||||
],
|
||||
],
|
||||
"lengthMenu" => Dict::Format( 'Portal:Datatables:Language:DisplayLength:All'),
|
||||
"dom"=> "<'ibo-datatable-toolbar'pil>t<'ibo-datatable-toolbar'pil>",
|
||||
"order"=> [],
|
||||
"filter"=> false,
|
||||
"processing"=> true,
|
||||
"serverSide"=> true,
|
||||
"columns"=> $aColumnsDefinitions,
|
||||
"allColumns"=> $aColumns,
|
||||
'ajax' => '$.fn.dataTable.pipeline( {
|
||||
"url": "ajax.render.php",
|
||||
"data": '.$sAjaxData.',
|
||||
"method": "post",
|
||||
"pages": 5 // number of pages to cache
|
||||
} )'
|
||||
];
|
||||
|
||||
|
||||
return $aOptions;
|
||||
}
|
||||
}
|
||||
355
sources/application/UI/Component/DataTable/DataTableSettings.php
Normal file
@@ -0,0 +1,355 @@
|
||||
<?php
|
||||
|
||||
namespace Combodo\iTop\Application\UI\Component\DataTable;
|
||||
|
||||
use appUserPreferences;
|
||||
use AttributeDashboard;
|
||||
use AttributeFriendlyName;
|
||||
use AttributeLinkedSet;
|
||||
use cmdbAbstract;
|
||||
use Dict;
|
||||
use Metamodel;
|
||||
use Serializable;
|
||||
|
||||
class DataTableSettings implements Serializable
|
||||
{
|
||||
public $aClassAliases;
|
||||
public $sTableId;
|
||||
public $iDefaultPageSize;
|
||||
public $aColumns;
|
||||
|
||||
|
||||
/**
|
||||
* DataTableSettings constructor.
|
||||
*
|
||||
* @param $aClassAliases
|
||||
* @param null $sTableId
|
||||
*/
|
||||
public function __construct($aClassAliases, $sTableId = null)
|
||||
{
|
||||
$this->aClassAliases = $aClassAliases;
|
||||
$this->sTableId = $sTableId;
|
||||
$this->iDefaultPageSize = 10;
|
||||
$this->aColumns = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $iDefaultPageSize
|
||||
* @param $aSortOrder
|
||||
* @param $aColumns
|
||||
*/
|
||||
protected function Init($iDefaultPageSize, $aSortOrder, $aColumns)
|
||||
{
|
||||
$this->iDefaultPageSize = $iDefaultPageSize;
|
||||
$this->aColumns = $aColumns;
|
||||
$this->FixVisibleColumns();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function serialize()
|
||||
{
|
||||
// Save only the 'visible' columns
|
||||
$aColumns = array();
|
||||
foreach ($this->aClassAliases as $sAlias => $sClass) {
|
||||
$aColumns[$sAlias] = array();
|
||||
foreach ($this->aColumns[$sAlias] as $sAttCode => $aData) {
|
||||
unset($aData['label']); // Don't save the display name
|
||||
unset($aData['alias']); // Don't save the alias (redundant)
|
||||
unset($aData['code']); // Don't save the code (redundant)
|
||||
if ($aData['checked']) {
|
||||
$aColumns[$sAlias][$sAttCode] = $aData;
|
||||
}
|
||||
}
|
||||
}
|
||||
return serialize(
|
||||
array(
|
||||
'iDefaultPageSize' => $this->iDefaultPageSize,
|
||||
'aColumns' => $aColumns,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sData
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function unserialize($sData)
|
||||
{
|
||||
$aData = unserialize($sData);
|
||||
$this->iDefaultPageSize = $aData['iDefaultPageSize'];
|
||||
$this->aColumns = $aData['aColumns'];
|
||||
foreach ($this->aClassAliases as $sAlias => $sClass) {
|
||||
foreach ($this->aColumns[$sAlias] as $sAttCode => $aData) {
|
||||
$aFieldData = false;
|
||||
if ($sAttCode == '_key_') {
|
||||
$aFieldData = $this->GetFieldData($sAlias, $sAttCode, null, true /* bChecked */, $aData['sort']);
|
||||
} else if (MetaModel::isValidAttCode($sClass, $sAttCode)) {
|
||||
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
|
||||
$aFieldData = $this->GetFieldData($sAlias, $sAttCode, $oAttDef, true /* bChecked */, $aData['sort']);
|
||||
}
|
||||
|
||||
if ($aFieldData) {
|
||||
$this->aColumns[$sAlias][$sAttCode] = $aFieldData;
|
||||
} else {
|
||||
unset($this->aColumns[$sAlias][$sAttCode]);
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->FixVisibleColumns();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $aClassAliases
|
||||
* @param $bViewLink
|
||||
* @param $aDefaultLists
|
||||
*
|
||||
* @return \DataTableSettings
|
||||
* @throws \CoreException
|
||||
* @throws \DictExceptionMissingString
|
||||
*/
|
||||
public static function GetDataModelSettings($aClassAliases, $bViewLink, $aDefaultLists)
|
||||
{
|
||||
$oSettings = new DataTableSettings($aClassAliases);
|
||||
// Retrieve the class specific settings for each class/alias based on the 'list' ZList
|
||||
//TODO let the caller pass some other default settings (another Zlist, extre fields...)
|
||||
$aColumns = array();
|
||||
foreach ($aClassAliases as $sAlias => $sClass) {
|
||||
if ($aDefaultLists == null) {
|
||||
$aList = cmdbAbstract::FlattenZList(MetaModel::GetZListItems($sClass, 'list'));
|
||||
} else {
|
||||
$aList = $aDefaultLists[$sAlias];
|
||||
}
|
||||
|
||||
$aSortOrder = MetaModel::GetOrderByDefault($sClass);
|
||||
if ($bViewLink) {
|
||||
$sSort = 'none';
|
||||
if (array_key_exists('friendlyname', $aSortOrder)) {
|
||||
$sSort = $aSortOrder['friendlyname'] ? 'asc' : 'desc';
|
||||
}
|
||||
$sNormalizedFName = MetaModel::NormalizeFieldSpec($sClass, 'friendlyname');
|
||||
if (array_key_exists($sNormalizedFName, $aSortOrder)) {
|
||||
$sSort = $aSortOrder[$sNormalizedFName] ? 'asc' : 'desc';
|
||||
}
|
||||
|
||||
$aColumns[$sAlias]['_key_'] = $oSettings->GetFieldData($sAlias, '_key_', null, true /* bChecked */, $sSort);
|
||||
}
|
||||
foreach ($aList as $sAttCode) {
|
||||
$sSort = 'none';
|
||||
if (array_key_exists($sAttCode, $aSortOrder)) {
|
||||
$sSort = $aSortOrder[$sAttCode] ? 'asc' : 'desc';
|
||||
}
|
||||
$oAttDef = Metamodel::GetAttributeDef($sClass, $sAttCode);
|
||||
$aFieldData = $oSettings->GetFieldData($sAlias, $sAttCode, $oAttDef, true /* bChecked */, $sSort);
|
||||
if ($aFieldData) $aColumns[$sAlias][$sAttCode] = $aFieldData;
|
||||
}
|
||||
}
|
||||
$iDefaultPageSize = appUserPreferences::GetPref('default_page_size', MetaModel::GetConfig()->GetMinDisplayLimit());
|
||||
$oSettings->Init($iDefaultPageSize, $aSortOrder, $aColumns);
|
||||
return $oSettings;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \CoreException
|
||||
*/
|
||||
protected function FixVisibleColumns()
|
||||
{
|
||||
foreach ($this->aClassAliases as $sAlias => $sClass) {
|
||||
if (!isset($this->aColumns[$sAlias])) {
|
||||
continue;
|
||||
}
|
||||
foreach ($this->aColumns[$sAlias] as $sAttCode => $aData) {
|
||||
// Remove non-existent columns
|
||||
// TODO: check if the existing ones are still valid (in case their type changed)
|
||||
if (($sAttCode != '_key_') && (!MetaModel::IsValidAttCode($sClass, $sAttCode))) {
|
||||
unset($this->aColumns[$sAlias][$sAttCode]);
|
||||
}
|
||||
}
|
||||
$aList = MetaModel::ListAttributeDefs($sClass);
|
||||
|
||||
// Add the other (non visible ones), sorted in alphabetical order
|
||||
$aTempData = array();
|
||||
foreach ($aList as $sAttCode => $oAttDef) {
|
||||
if ((!array_key_exists($sAttCode, $this->aColumns[$sAlias])) && (!($oAttDef instanceof AttributeLinkedSet || $oAttDef instanceof AttributeDashboard))) {
|
||||
$aFieldData = $this->GetFieldData($sAlias, $sAttCode, $oAttDef, false /* bChecked */, 'none');
|
||||
if ($aFieldData) $aTempData[$aFieldData['label']] = $aFieldData;
|
||||
}
|
||||
}
|
||||
ksort($aTempData);
|
||||
foreach ($aTempData as $sLabel => $aFieldData) {
|
||||
$this->aColumns[$sAlias][$aFieldData['code']] = $aFieldData;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $aClassAliases
|
||||
* @param null $sTableId
|
||||
* @param bool $bOnlyOnTable
|
||||
*
|
||||
* @return \DataTableSettings|null
|
||||
* @throws \Exception
|
||||
*/
|
||||
static public function GetTableSettings($aClassAliases, $sTableId = null, $bOnlyOnTable = false)
|
||||
{
|
||||
$pref = null;
|
||||
$oSettings = new DataTableSettings($aClassAliases, $sTableId);
|
||||
|
||||
if ($sTableId != null) {
|
||||
// An identified table, let's fetch its own settings (if any)
|
||||
$pref = appUserPreferences::GetPref($oSettings->GetPrefsKey($sTableId), null);
|
||||
}
|
||||
|
||||
if ($pref == null) {
|
||||
if (!$bOnlyOnTable) {
|
||||
// Try the global preferred values for this class / set of classes
|
||||
$pref = appUserPreferences::GetPref($oSettings->GetPrefsKey(null), null);
|
||||
}
|
||||
if ($pref == null) {
|
||||
// no such settings, use the default values provided by the data model
|
||||
return null;
|
||||
}
|
||||
}
|
||||
$oSettings->unserialize($pref);
|
||||
|
||||
return $oSettings;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function GetSortOrder()
|
||||
{
|
||||
$aSortOrder = array();
|
||||
foreach ($this->aColumns as $sAlias => $aColumns) {
|
||||
foreach ($aColumns as $aColumn) {
|
||||
if ($aColumn['sort'] != 'none') {
|
||||
$sCode = ($aColumn['code'] == '_key_') ? 'friendlyname' : $aColumn['code'];
|
||||
$aSortOrder[$sCode] = ($aColumn['sort'] == 'asc'); // true for ascending, false for descending
|
||||
}
|
||||
}
|
||||
break; // TODO: For now the Set object supports only sorting on the first class of the set
|
||||
}
|
||||
return $aSortOrder;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param null $sTargetTableId
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function Save($sTargetTableId = null)
|
||||
{
|
||||
$sSaveId = is_null($sTargetTableId) ? $this->sTableId : $sTargetTableId;
|
||||
if ($sSaveId == null) return false; // Cannot save, the table is not identified, use SaveAsDefault instead
|
||||
|
||||
$sSettings = $this->serialize();
|
||||
appUserPreferences::SetPref($this->GetPrefsKey($sSaveId), $sSettings);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function SaveAsDefault()
|
||||
{
|
||||
$sSettings = $this->serialize();
|
||||
appUserPreferences::SetPref($this->GetPrefsKey(null), $sSettings);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Clear the preferences for this particular table
|
||||
* @param $bResetAll boolean If true,the settings for all tables of the same class(es)/alias(es) are reset
|
||||
*/
|
||||
public function ResetToDefault($bResetAll)
|
||||
{
|
||||
if (($this->sTableId == null) && (!$bResetAll)) return false; // Cannot reset, the table is not identified, use force $bResetAll instead
|
||||
if ($bResetAll) {
|
||||
// Turn the key into a suitable PCRE pattern
|
||||
$sKey = $this->GetPrefsKey(null);
|
||||
$sPattern = str_replace(array('|'), array('\\|'), $sKey); // escape the | character
|
||||
$sPattern = '#^' . str_replace(array('*'), array('.*'), $sPattern) . '$#'; // Don't use slash as the delimiter since it's used in our key to delimit aliases
|
||||
appUserPreferences::UnsetPref($sPattern, true);
|
||||
} else {
|
||||
appUserPreferences::UnsetPref($this->GetPrefsKey($this->sTableId), false);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param null $sTableId
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function GetPrefsKey($sTableId = null)
|
||||
{
|
||||
return static::GetAppUserPreferenceKey($this->aClassAliases, $sTableId);
|
||||
}
|
||||
|
||||
public static function GetAppUserPreferenceKey($aClassAliases, $sTableId)
|
||||
{
|
||||
if ($sTableId === null) {
|
||||
$sTableId = '*';
|
||||
}
|
||||
|
||||
$aKeys = array();
|
||||
foreach ($aClassAliases as $sAlias => $sClass) {
|
||||
$aKeys[] = $sAlias . '-' . $sClass;
|
||||
}
|
||||
return implode('/', $aKeys) . '|' . $sTableId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $sAlias
|
||||
* @param $sAttCode
|
||||
* @param $oAttDef
|
||||
* @param $bChecked
|
||||
* @param $sSort
|
||||
*
|
||||
* @return array|bool
|
||||
* @throws \CoreException
|
||||
* @throws \DictExceptionMissingString
|
||||
*/
|
||||
protected function GetFieldData($sAlias, $sAttCode, $oAttDef, $bChecked, $sSort)
|
||||
{
|
||||
$ret = false;
|
||||
if ($sAttCode == '_key_') {
|
||||
$sLabel = Dict::Format('UI:ExtKey_AsLink', MetaModel::GetName($this->aClassAliases[$sAlias]));
|
||||
$ret = array(
|
||||
'label' => $sLabel,
|
||||
'checked' => true,
|
||||
'disabled' => true,
|
||||
'alias' => $sAlias,
|
||||
'code' => $sAttCode,
|
||||
'sort' => $sSort,
|
||||
);
|
||||
} else if (!$oAttDef->IsLinkSet()) {
|
||||
$sLabel = $oAttDef->GetLabel();
|
||||
if ($oAttDef->IsExternalKey()) {
|
||||
$sLabel = Dict::Format('UI:ExtKey_AsLink', $oAttDef->GetLabel());
|
||||
} else if ($oAttDef->IsExternalField()) {
|
||||
if ($oAttDef->IsFriendlyName()) {
|
||||
$sLabel = Dict::Format('UI:ExtKey_AsFriendlyName', $oAttDef->GetLabel());
|
||||
} else {
|
||||
$oExtAttDef = $oAttDef->GetExtAttDef();
|
||||
$sLabel = Dict::Format('UI:ExtField_AsRemoteField', $oAttDef->GetLabel(), $oExtAttDef->GetLabel());
|
||||
}
|
||||
} elseif ($oAttDef instanceof AttributeFriendlyName) {
|
||||
$sLabel = Dict::Format('UI:ExtKey_AsFriendlyName', $oAttDef->GetLabel());
|
||||
}
|
||||
$ret = array(
|
||||
'label' => $sLabel,
|
||||
'checked' => $bChecked,
|
||||
'disabled' => false,
|
||||
'alias' => $sAlias,
|
||||
'code' => $sAttCode,
|
||||
'sort' => $sSort,
|
||||
);
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
}
|
||||
@@ -40,13 +40,31 @@ class NiceWebPage extends WebPage
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery-ui.custom.min.js');
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/utils.js');
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/hovertip.js');
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/table-selectable-lines.js');
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/field_sorter.js');
|
||||
//TODO deprecated in 3.0.0
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/datatable.js');
|
||||
// table sorting
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.tablesorter.js');
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.tablesorter.pager.js');
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.tablehover.js');
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/table-selectable-lines.js');
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/field_sorter.js');
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/datatable.js');
|
||||
//TODO end deprecated in 3.0.0
|
||||
// Datatables added in 3.0.0
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'lib/datatables/js/jquery.dataTables.min.js');
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'lib/datatables/js/dataTables.bootstrap.min.js');
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'lib/datatables/js/dataTables.fixedHeader.min.js');
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'lib/datatables/js/dataTables.responsive.min.js');
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'lib/datatables/js/dataTables.scroller.min.js');
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'lib/datatables/js/dataTables.select.min.js');
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/dataTables.settings.js');
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/dataTables.pipeline.js');
|
||||
/*$this->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'lib/datatables/css/dataTables.bootstrap.min.css');
|
||||
$this->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'lib/datatables/css/fixedHeader.bootstrap.min.css');
|
||||
$this->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'lib/datatables/css/responsive.bootstrap.min.css');
|
||||
$this->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'lib/datatables/css/scroller.bootstrap.min.css');
|
||||
$this->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'lib/datatables/css/select.bootstrap.min.css');
|
||||
$this->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'lib/datatables/css/select.dataTables.min.css');*/
|
||||
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.positionBy.js');
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.popupmenu.js');
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/searchformforeignkeys.js');
|
||||
@@ -69,52 +87,7 @@ class NiceWebPage extends WebPage
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/clipboardwidget.js');
|
||||
|
||||
$this->add_dict_entries('UI:Combo');
|
||||
|
||||
$this->add_ready_script(
|
||||
<<< EOF
|
||||
//add new widget called TruncatedList to properly display truncated lists when they are sorted
|
||||
$.tablesorter.addWidget({
|
||||
// give the widget a id
|
||||
id: "truncatedList",
|
||||
// format is called when the on init and when a sorting has finished
|
||||
format: function(table)
|
||||
{
|
||||
// Check if there is a "truncated" line
|
||||
this.truncatedList = false;
|
||||
if ($("tr td.truncated",table).length > 0)
|
||||
{
|
||||
this.truncatedList = true;
|
||||
}
|
||||
if (this.truncatedList)
|
||||
{
|
||||
$("tr td",table).removeClass('truncated');
|
||||
$("tr:last td",table).addClass('truncated');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$.tablesorter.addWidget({
|
||||
// give the widget a id
|
||||
id: "myZebra",
|
||||
// format is called when the on init and when a sorting has finished
|
||||
format: function(table)
|
||||
{
|
||||
// Replace the 'red even' lines by 'red_even' since most browser do not support 2 classes selector in CSS, etc..
|
||||
$("tbody tr:even",table).addClass('even');
|
||||
$("tbody tr.red:even",table).removeClass('red').removeClass('even').addClass('red_even');
|
||||
$("tbody tr.orange:even",table).removeClass('orange').removeClass('even').addClass('orange_even');
|
||||
$("tbody tr.green:even",table).removeClass('green').removeClass('even').addClass('green_even');
|
||||
// In case we sort again the table, we need to remove the added 'even' classes on odd rows
|
||||
$("tbody tr:odd",table).removeClass('even');
|
||||
$("tbody tr.red_even:odd",table).removeClass('even').removeClass('red_even').addClass('red');
|
||||
$("tbody tr.orange_even:odd",table).removeClass('even').removeClass('orange_even').addClass('orange');
|
||||
$("tbody tr.green_even:odd",table).removeClass('even').removeClass('green_even').addClass('green');
|
||||
}
|
||||
});
|
||||
$("table.listResults").tableHover(); // hover tables
|
||||
EOF
|
||||
);
|
||||
$this->LoadTheme();
|
||||
$this->LoadTheme();
|
||||
|
||||
$this->m_sRootUrl = $this->GetAbsoluteUrlAppRoot();
|
||||
$sAbsURLAppRoot = addslashes($this->m_sRootUrl);
|
||||
|
||||
@@ -31,6 +31,14 @@ use AttributeFriendlyName;
|
||||
use AttributeTagSet;
|
||||
use CMDBObjectSet;
|
||||
use Combodo\iTop\Application\Search\CriterionConversion\CriterionToSearchForm;
|
||||
use Combodo\iTop\Application\UI\Component\Form\Form;
|
||||
use Combodo\iTop\Application\UI\Component\DataContainer\DataContainer;
|
||||
use Combodo\iTop\Application\UI\Component\Html\Html;
|
||||
use Combodo\iTop\Application\UI\Component\Input\InputFactory;
|
||||
use Combodo\iTop\Application\UI\Component\Panel\Panel;
|
||||
use Combodo\iTop\Application\UI\Component\Panel\PanelFactory;
|
||||
use Combodo\iTop\Application\UI\Layout\UIContentBlock;
|
||||
use Combodo\iTop\Renderer\BlockRenderer;
|
||||
use CoreException;
|
||||
use DBObjectSearch;
|
||||
use DBObjectSet;
|
||||
@@ -41,6 +49,7 @@ use FieldExpression;
|
||||
use IssueLog;
|
||||
use MetaModel;
|
||||
use MissingQueryArgument;
|
||||
use ScssPhp\ScssPhp\Block;
|
||||
use TrueExpression;
|
||||
use utils;
|
||||
use WebPage;
|
||||
@@ -60,7 +69,12 @@ class SearchForm
|
||||
*/
|
||||
public function GetSearchForm(WebPage $oPage, CMDBObjectSet $oSet, $aExtraParams = array())
|
||||
{
|
||||
$sHtml = '';
|
||||
$oPage->AddUiBlock($this->GetSearchFormUIBlock($oPage, $oSet, $aExtraParams));
|
||||
return '';
|
||||
}
|
||||
public function GetSearchFormUIBlock(WebPage $oPage, CMDBObjectSet $oSet, $aExtraParams = array())
|
||||
{
|
||||
$oUiBlock = new UIContentBlock();
|
||||
$oAppContext = new ApplicationContext();
|
||||
$sClassName = $oSet->GetFilter()->GetClass();
|
||||
$aListParams = array();
|
||||
@@ -79,7 +93,7 @@ class SearchForm
|
||||
{
|
||||
$iSearchFormId = $oPage->GetUniqueId();
|
||||
$sSearchFormId = 'SimpleSearchForm'.$iSearchFormId;
|
||||
$sHtml .= "<div id=\"ds_$sSearchFormId\" class=\"mini_tab{$iSearchFormId}\">\n";
|
||||
$oUiBlock->AddHtml("<div id=\"ds_$sSearchFormId\" class=\"mini_tab{$iSearchFormId}\">");
|
||||
$aListParams['currentId'] = "$iSearchFormId";
|
||||
}
|
||||
// Check if the current class has some sub-classes
|
||||
@@ -109,7 +123,7 @@ class SearchForm
|
||||
|
||||
if (!isset($aExtraParams['result_list_outer_selector']))
|
||||
{
|
||||
if (isset($aExtraParams['table_id']))
|
||||
if (isset($aExtraParams['table_id']) )
|
||||
{
|
||||
$aExtraParams['result_list_outer_selector'] = $aExtraParams['table_id'];
|
||||
}
|
||||
@@ -170,21 +184,34 @@ class SearchForm
|
||||
}
|
||||
|
||||
$sAction = (isset($aExtraParams['action'])) ? $aExtraParams['action'] : utils::GetAbsoluteUrlAppRoot().'pages/UI.php';
|
||||
$sStyle = ($bOpen == 'true') ? '' : 'closed';
|
||||
$sStyle = "ibo-search-form";
|
||||
$sStyle .= ($bOpen == 'true') ? '' : ' closed';
|
||||
$sStyle .= ($bAutoSubmit === true) ? '' : ' no_auto_submit';
|
||||
$sHtml .= "<form id=\"fs_{$sSearchFormId}\" action=\"{$sAction}\" class=\"{$sStyle}\">\n"; // Don't use $_SERVER['SCRIPT_NAME'] since the form may be called asynchronously (from ajax.php)
|
||||
$sHtml .= "<h2 class=\"sf_title\"><span class=\"sft_long\">" . Dict::Format('UI:SearchFor_Class_Objects', $sClassesCombo) . "</span><span class=\"sft_short\">" . Dict::S('UI:SearchToggle') . "</span>";
|
||||
$sHtml .= "<a class=\"sft_toggler fas fa-caret-down pull-right\" href=\"#\" title=\"" . Dict::S('UI:Search:Toggle') . "\"></a>";
|
||||
//(string $sTitle = '', array $aSubBlocks = [], string $sColor = self::DEFAULT_COLOR, ?string $sId = null)
|
||||
$oUiSearchBlock = new Panel(Dict::Format('UI:SearchFor_Class_Objects', $sClassesCombo), [],Panel::DEFAULT_COLOR, $sSearchFormId);
|
||||
$oUiSearchBlock->SetCSSClasses("display_block");
|
||||
$oUiBlock->AddSubBlock($oUiSearchBlock);
|
||||
|
||||
$sHtml = "<a class=\"sft_toggler fas fa-caret-down pull-right\" href=\"#\" title=\"" . Dict::S('UI:Search:Toggle') . "\"></a>";
|
||||
$sHtml .= "<span class=\"pull-right\">";
|
||||
$sHtml .= "<span class=\"sfobs_hint pull-right\">" . Dict::S('UI:Search:Obsolescence:DisabledHint') . "</span>";
|
||||
$sHtml .= "<br class='clearboth' />";
|
||||
$sHtml .= "<span class=\"sft_hint pull-right\">" . Dict::S('UI:Search:AutoSubmit:DisabledHint') . "</span>";
|
||||
$sHtml .= "</span>";
|
||||
$sHtml .= "<br class='clearboth' />";
|
||||
$sHtml .= "</h2>\n";
|
||||
$sHtml .= "<div id=\"fs_{$sSearchFormId}_message\" class=\"sf_message header_message\"></div>\n";
|
||||
$sHtml .= "<div id=\"fs_{$sSearchFormId}_criterion_outer\">\n</div>\n";
|
||||
$sHtml .= "</form>\n";
|
||||
$oUiSearchBlock->AddToolbarBlock(new Html($sHtml));
|
||||
|
||||
|
||||
|
||||
$oFormSearch=new Form("fs_".$sSearchFormId);
|
||||
$oFormSearch->SetAction($sAction)
|
||||
->AddCSSClasses($sStyle);
|
||||
$oUiSearchBlock->AddSubBlock($oFormSearch);
|
||||
$oFormSearch->AddSubBlock(InputFactory::MakeForHidden("class", $sClassName));
|
||||
$oFormSearch->AddHtml( "<div id=\"fs_{$sSearchFormId}_message\" class=\"sf_message header_message\"></div>");//class sf_message header_message
|
||||
|
||||
$oCriterionBlock = new UIContentBlock("fs_{$sSearchFormId}_criterion_outer","sf_criterion_area ibo-criterion-area");
|
||||
$oFormSearch->AddSubBlock($oCriterionBlock);
|
||||
|
||||
if (isset($aExtraParams['query_params']))
|
||||
{
|
||||
@@ -289,9 +316,8 @@ class SearchForm
|
||||
|
||||
$oPage->add_ready_script('$("#fs_'.$sSearchFormId.'").search_form_handler('.json_encode($aSearchParams).');');
|
||||
|
||||
return $sHtml;
|
||||
return $oUiBlock;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \DBObjectSet $oSet
|
||||
*
|
||||
|
||||
61
templates/components/datatable/layout.html.twig
Normal file
@@ -0,0 +1,61 @@
|
||||
{% for oSubBlock in oUIBlock.GetSubBlocks() %}{{ render_block(oSubBlock, {aPage: aPage}) }}{% endfor %}
|
||||
{% if oUIBlock.GetOptions()["select"] is defined %}
|
||||
<input type="hidden" name="selectionMode" value="positive"/>
|
||||
<input type="hidden" name="extra_params" value="{{ oUIBlock.GetAjaxData()["extra_params"]}}"/>
|
||||
<input type="hidden" name="filter" value="{{ oUIBlock.GetAjaxData()["filter"]}}"/>
|
||||
{% endif %}
|
||||
|
||||
<table id="{{ oUIBlock.GetId() }}" width="100%" class="ibo-datatable">
|
||||
<thead>
|
||||
{% if oUIBlock.GetOptions()["select"] is defined %}
|
||||
<th></th>
|
||||
{% endif %}
|
||||
{% for aColumn in oUIBlock.GetDisplayColumns() %}
|
||||
<th class="ibo-datatable-header" title="{{ aColumn["description"] }}\">{{ aColumn["attribute_label"] }} </th>
|
||||
{% endfor %}
|
||||
</thead>
|
||||
</table>
|
||||
|
||||
<div id="datatable_dlg_{{ oUIBlock.GetId() }}" style="display: none; background : white;" class="">
|
||||
<form id="form_{{ oUIBlock.GetId() }}" onsubmit="return false">
|
||||
<p>
|
||||
<input id="dtbl_dlg_settings_{{ oUIBlock.GetId() }}" type="radio" name="settings" {% if (oUIBlock.GetOptions()['bUseCustomSettings'] == false) %} checked {% endif %} value="defaults">
|
||||
<label for="dtbl_dlg_settings_{{ oUIBlock.GetId() }}"> {{ 'UI:UseDefaultSettings'|dict_s }}</label>
|
||||
</p>
|
||||
<fieldset>
|
||||
<legend class="transparent">
|
||||
<input id="dtbl_dlg_specific_{{ oUIBlock.GetId() }}" type="radio" class="specific_settings" name="settings" {% if oUIBlock.GetOptions()["bUseCustomSettings"] %} checked {% endif %} value="specific">
|
||||
<label for="dtbl_dlg_specific_{{ oUIBlock.GetId() }}"> {{ 'UI:UseSpecificSettings'|dict_s }}</label>
|
||||
</legend>
|
||||
{{'UI:ColumnsAndSortOrder'|dict_s}}<br/>
|
||||
<ul class="sortable_field_list" id="sfl_{{ oUIBlock.GetId() }}">
|
||||
|
||||
</ul>
|
||||
|
||||
<p> {{ 'UI:Display_X_ItemsPerPage_prefix'|dict_s }}<input type="text" size="4" name="page_size" value="{{ oUIBlock.GetOptions()["iPageSize"]}}">{{ 'UI:Display_X_ItemsPerPage_suffix'|dict_s }}</p>
|
||||
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<legend class="transparent">
|
||||
<input id="dtbl_dlg_save_{{ oUIBlock.GetId() }}" type="checkbox" {% if oUIBlock.GetOptions()["sTableId"] != null %}checked{% endif %} name="save_settings">
|
||||
<label for="dtbl_dlg_save_{{ oUIBlock.GetId() }}"> {{ 'UI:UseSavetheSettings'|dict_s }}</label>
|
||||
</legend>
|
||||
<p>
|
||||
<input id="dtbl_dlg_this_list_{{ oUIBlock.GetId() }}" type="radio" name="scope" {% if oUIBlock.GetOptions()["sTableId"] != null %} checked {% else %} disabled="disabled" stay-disabled="true"{% endif %} value="this_list">
|
||||
<label for="dtbl_dlg_this_list_{{ oUIBlock.GetId() }}"> {{ 'UI:OnlyForThisList'|dict_s }}</label>
|
||||
<input id="dtbl_dlg_all_{{ oUIBlock.GetId() }}" type="radio" name="scope" {% if oUIBlock.GetOptions()["sTableId"] == null %} checked {% endif %} value="defaults">
|
||||
<label for="dtbl_dlg_all_{{ oUIBlock.GetId() }}"> {{ 'UI:ForAllLists'|dict_s }}</label>
|
||||
</p>
|
||||
</fieldset>
|
||||
<table style="width:100%">
|
||||
<tr>
|
||||
<td style="text-align:center;">
|
||||
<button type="button" onclick="$('#datatable_dlg_{{ oUIBlock.GetId() }}').DataTableSettings('onDlgCancel'); $('#datatable_dlg_{{ oUIBlock.GetId() }}').dialog('close')"> {{ 'UI:Button:Cancel'|dict_s }}</button>
|
||||
</td>
|
||||
<td style="text-align:center;">
|
||||
<button type="submit" onclick="$('#datatable_dlg_{{ oUIBlock.GetId() }}').DataTableSettings('onDlgOk'); $('#datatable_dlg_{{ oUIBlock.GetId() }}').dialog('close');"> {{ 'UI:Button:Ok'|dict_s }}</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
</div>
|
||||
256
templates/components/datatable/layout.js.twig
Normal file
@@ -0,0 +1,256 @@
|
||||
function checkAllDataTable(table, value)
|
||||
{
|
||||
if (value) {
|
||||
$(table).DataTable().rows().select();
|
||||
}
|
||||
else {
|
||||
$(table).DataTable().rows({ page: 'current' }).deselect();
|
||||
}
|
||||
// Mark all the displayed items as check or unchecked depending on the value
|
||||
$(table).find(':checkbox[name^=selectObj]:not([disabled])').each(function (index, element) {
|
||||
var $currentCheckbox = $(this);
|
||||
$currentCheckbox.prop('checked', value);
|
||||
$currentLine = $currentCheckbox.closest("tr");
|
||||
(value) ? $currentLine.addClass("selected") : $currentLine.removeClass("selected");
|
||||
});
|
||||
// Set the 'selectionMode' for the future objects to load
|
||||
var selectionMode = 'positive';
|
||||
if (value)
|
||||
{
|
||||
selectionMode = 'negative';
|
||||
}
|
||||
$(table).parent().parent().find(':input[name=selectionMode]').val(selectionMode);
|
||||
// Reset the list of saved selection...
|
||||
$(':input[name^=storedSelection]').remove();
|
||||
$(table).parent().find(':checkbox[name^=selectObj]').trigger("change");
|
||||
//updateCounter(table);
|
||||
return true;
|
||||
}
|
||||
|
||||
$('#{{ oUIBlock.GetId() }}').closest( "[role=dialog]" ).on( "dialogbeforeclose", function( event, ui ) {
|
||||
console.warn("destroy on close");
|
||||
$('#{{ oUIBlock.GetId() }}').DataTable().clear();
|
||||
// $('#{{ oUIBlock.GetId() }}').DataTable().destroy(false);
|
||||
} );
|
||||
|
||||
{% if oUIBlock.GetOptions()["select"] is defined %}
|
||||
var oSelectedItems{{ oUIBlock.GetOptions()['sTableId'] }} = [];
|
||||
{% endif %}
|
||||
|
||||
if ( $.fn.dataTable.isDataTable( '#{{ oUIBlock.GetId() }}' ) ) {
|
||||
console.warn("destroy on load");
|
||||
$('#{{ oUIBlock.GetId() }}').DataTable().destroy(false);
|
||||
}
|
||||
|
||||
var oTable{{ oUIBlock.GetId() }} = $('#{{ oUIBlock.GetId() }}').DataTable({
|
||||
"language": {
|
||||
"processing": "{{ 'UI:Datatables:Language:Processing'|dict_s }}",
|
||||
"search": "{{ 'UI:Datatables:Language:Search'|dict_s }}",
|
||||
"lengthMenu": " Showing _MENU_ out",// "{{ 'UI:Datatables:Language:LengthMenu'|dict_s }}",
|
||||
"zeroRecords": "{{ 'UI:Datatables:Language:ZeroRecords'|dict_s }}",
|
||||
"info": "of _TOTAL_ items",//"{{ 'UI:Datatables:Language:Info'|dict_s }}",
|
||||
"infoEmpty": "{{ 'UI:Datatables:Language:InfoEmpty'|dict_s }}",
|
||||
"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 }}"
|
||||
}
|
||||
},
|
||||
"lengthMenu": [[ {{ oUIBlock.GetOptions()["iPageSize"] }}, {{ oUIBlock.GetOptions()["iPageSize"]*2 }}, {{ oUIBlock.GetOptions()["iPageSize"]*3 }}, {{ oUIBlock.GetOptions()["iPageSize"]*4 }}, -1], [ {{ oUIBlock.GetOptions()["iPageSize"] }}, {{ oUIBlock.GetOptions()["iPageSize"]*2 }}, {{ oUIBlock.GetOptions()["iPageSize"]*3 }}, {{ oUIBlock.GetOptions()["iPageSize"]*4 }}, "{{ 'Portal:Datatables:Language:DisplayLength:All'|dict_s }}"]],
|
||||
"dom": "<'ibo-datatable-toolbar'pil>t<'ibo-datatable-toolbar'pil>",
|
||||
"order": [[1, "asc"]],
|
||||
{% if oUIBlock.GetOptions()["select"] is defined %}
|
||||
"select": {
|
||||
"style": "{{ oUIBlock.GetOptions()["select"] }}"
|
||||
},
|
||||
"rowCallback": function(oRow, oData){
|
||||
// Hiding pagination if only one page
|
||||
if ($(this).closest('.ibo-panel--body').find('[name=selectionMode]')=="negative") {
|
||||
if(! oData.id in oSelectedItems{{ oUIBlock.GetOptions()['sTableId'] }})
|
||||
{
|
||||
$(oRow).select();
|
||||
$(oRow).find('td:first-child input').prop('checked', true);
|
||||
}
|
||||
//$(table).DataTable().rows({ page: 'current' }).select();
|
||||
}
|
||||
else {
|
||||
if(oData.id in oSelectedItems{{ oUIBlock.GetOptions()['sTableId'] }})
|
||||
{
|
||||
$(oRow).select();
|
||||
$(oRow).find('td:first-child input').prop('checked', true);
|
||||
}
|
||||
}
|
||||
},
|
||||
"drawCallback": function (settings) {
|
||||
// Hiding pagination if only one page
|
||||
if ($(this).closest('.ibo-panel--body').find('[name=selectionMode]')=="negative") {
|
||||
$(this).find('[name=selectAll]').checked();
|
||||
$(table).DataTable().rows({ page: 'current' }).select();
|
||||
}
|
||||
else {
|
||||
$(this).closest('.dataTables_wrapper').find('.dataTables_paginate, .dataTables_info').show();
|
||||
}
|
||||
},
|
||||
{% endif %}
|
||||
"rowId": "id",
|
||||
"filter":false,
|
||||
"retrieve": true,
|
||||
"destroy": true,
|
||||
"processing": true,
|
||||
"serverSide": true,
|
||||
"columns":[
|
||||
{% if oUIBlock.GetOptions()["select"] is defined %}
|
||||
{"width": "auto",
|
||||
"searchable": false,
|
||||
"sortable": false,
|
||||
"title": '<span class="row_input"><input type="checkbox" onclick="checkAllDataTable(\'#{{ oUIBlock.GetId() }}\',this.checked);" class="checkAll" id="field_{{ oUIBlock.GetId() }}_check_all" name="field_{{ oUIBlock.GetId() }}_check_all" title="{{'UI:SearchValue:CheckAll'|dict_s}} / {{'UI:SearchValue:UncheckAll'|dict_s}}" /></span>',
|
||||
"type": "html",
|
||||
"data": "",
|
||||
"render": function(data, type, row)
|
||||
{
|
||||
var oCheckboxElem = $('<span class="row_input"><input type="checkbox" class="selectList{{ oUIBlock.GetId() }}" name="selectObject[]" /></span>');
|
||||
if(row.limited_access)
|
||||
{
|
||||
oCheckboxElem.html('-');
|
||||
}
|
||||
else
|
||||
{
|
||||
oCheckboxElem.find(':input').attr('data-object-id', row.id).attr('data-target-object-id', row.target_id);
|
||||
}
|
||||
return oCheckboxElem.prop('outerHTML');
|
||||
}
|
||||
},
|
||||
{% endif %}
|
||||
{% for aColumn in oUIBlock.GetDisplayColumns() %}
|
||||
{
|
||||
"width": "auto",
|
||||
"searchable": false,
|
||||
"sortable": true,
|
||||
"title":"{{ aColumn["attribute_label"] }}",
|
||||
"defaultContent": "",
|
||||
"type": "html",
|
||||
'metadata': {
|
||||
'object_class': "{{ aColumn["object_class"] }}",
|
||||
'attribute_code': "{{ aColumn["attribute_code"] }}",
|
||||
'attribute_type': "{{ aColumn["attribute_type"] }}",
|
||||
'attribute_label': "{{ aColumn["attribute_label"] }}",
|
||||
},
|
||||
"data": "{{ aColumn["class_alias"] }}/{{ aColumn["attribute_code"] }}",
|
||||
"render": {
|
||||
"display": function ( data, type, row ) { {{ aColumn["render"]|raw }}},
|
||||
"_":"{{ aColumn["class_alias"] }}/{{ aColumn["attribute_code"] }}",
|
||||
},
|
||||
},
|
||||
{% endfor %}
|
||||
],
|
||||
"ajax": $.fn.dataTable.pipeline( {
|
||||
"url": "{{ oUIBlock.GetAjaxUrl() }}",
|
||||
"data": {{ oUIBlock.GetAjaxData() |raw}},
|
||||
"method": "post",
|
||||
"pages": 5 // number of pages to cache
|
||||
} )
|
||||
});
|
||||
|
||||
oTable{{ oUIBlock.GetId() }}.off('select').on('select', function(oEvent, dt, type, indexes){
|
||||
var aData = oTable{{ oUIBlock.GetId() }}.rows(indexes).data().toArray();
|
||||
|
||||
// Checking input
|
||||
$('#{{ oUIBlock.GetId() }} tr[role="row"].selected td:first-child input').prop('checked', true);
|
||||
// Saving values in temp array
|
||||
for(var i in aData)
|
||||
{
|
||||
var iItemId = aData[i].id;
|
||||
if(!(iItemId in oSelectedItems{{ oUIBlock.GetOptions()['sTableId'] }}))
|
||||
{
|
||||
oSelectedItems{{ oUIBlock.GetOptions()['sTableId'] }}.push(iItemId);
|
||||
}
|
||||
}
|
||||
if ((oSelectedItems{{ oUIBlock.GetOptions()['sTableId'] }}.length == oTable{{ oUIBlock.GetId() }}.page.info()["recordsTotal"] && $(this).closest('.ibo-panel--body').find('[name=selectionMode]').val()=="negative"))
|
||||
{
|
||||
$('#btn_ok_{{ oUIBlock.GetOptions()['sTableId'] }}').prop('disabled', true);
|
||||
}
|
||||
else{
|
||||
$('#btn_ok_{{ oUIBlock.GetOptions()['sTableId'] }}').prop('disabled', false);
|
||||
}
|
||||
});
|
||||
oTable{{ oUIBlock.GetId() }}.off('deselect').on('deselect', function(oEvent, dt, type, indexes){
|
||||
var aData = oTable{{ oUIBlock.GetId() }}.rows(indexes).data().toArray();
|
||||
|
||||
// Checking input
|
||||
$('#{{ oUIBlock.GetId() }} tr[role="row"]:not(.selected) td:first-child input').prop('checked', false);
|
||||
// Saving values in temp array
|
||||
for(var i in aData)
|
||||
{
|
||||
var iItemId = aData[i].id;
|
||||
if(iItemId in oSelectedItems{{ oUIBlock.GetOptions()['sTableId'] }})
|
||||
{
|
||||
oSelectedItems{{ oUIBlock.GetOptions()['sTableId'] }}.splice( $.inArray(removeItem, oSelectedItems{{ oUIBlock.GetOptions()['sTableId'] }}), 1 );
|
||||
}
|
||||
}
|
||||
if ((oSelectedItems{{ oUIBlock.GetOptions()['sTableId'] }}.length == 0 && $(this).closest('.ibo-panel--body').find('[name=selectionMode]').val()=="positive"))
|
||||
{
|
||||
$('#btn_ok_{{ oUIBlock.GetOptions()['sTableId'] }}').prop('disabled', true);
|
||||
}
|
||||
else{
|
||||
$('#btn_ok_{{ oUIBlock.GetOptions()['sTableId'] }}').prop('disabled', false);
|
||||
}
|
||||
});
|
||||
|
||||
// Handles submit button
|
||||
//$('#form_{{ oUIBlock.GetId() }} .form_buttons .form_btn_submit').off('click').on('click', function(oEvent){
|
||||
// Extracting value(s) to be send back to the source form
|
||||
{% if bMultipleSelect %}
|
||||
//var oData = {values: oSelectedItems};
|
||||
{% else %}
|
||||
/*var oData = {value: {}};
|
||||
var sItemId = Object.keys(oSelectedItems)[0];
|
||||
var sItemName = oSelectedItems[sItemId];
|
||||
|
||||
oData.value[sItemId] = sItemName;*/
|
||||
{% endif %}
|
||||
|
||||
// Triggering value setting on the source field
|
||||
//$('[data-form-path="{{aSource.sFormPath}}"][data-field-id="{{aSource.sFieldId}}"]').triggerHandler('set_current_value', oData);
|
||||
|
||||
// Closing the modal
|
||||
{% if tIsModal is defined and tIsModal == true %}
|
||||
//$('#{{ sFormId }}').closest('.modal').modal('hide');
|
||||
{% endif %}
|
||||
//});
|
||||
|
||||
$('#datatable_dlg_{{ oUIBlock.GetId() }}').dialog(
|
||||
{
|
||||
autoOpen: false,
|
||||
title: "{{ 'UI:ListConfigurationTitle'|dict_s }}",
|
||||
width: 500,
|
||||
close: function() { //save data and refresh
|
||||
$('#datatable_dlg_{{ oUIBlock.GetId() }}').DataTableSettings('onDlgCancel');
|
||||
}
|
||||
});
|
||||
|
||||
$aOptions = {
|
||||
'sListId' : '{{ oUIBlock.GetId() }}',
|
||||
'oColumns' : {{ oUIBlock.GetResultColumnsAsJson()|raw }},
|
||||
'sViewLink': '{{ oUIBlock.GetOptions()["bViewLink"] }}' ,
|
||||
'iPageSize' : '{{ oUIBlock.GetOptions()["iPageSize"]}}',
|
||||
'sTableId' :'{{ oUIBlock.GetOptions()["sTableId"]}}',
|
||||
"sRenderUrl": "{{ oUIBlock.GetAjaxUrl() }}",
|
||||
"sSelectMode": "{{ oUIBlock.GetOptions()["select"] }}",
|
||||
"oData": {{ oUIBlock.GetAjaxData() |raw}},
|
||||
'oLabels' : {"moveup": "{{'UI:Button:MoveUp'|dict_s}}", "movedown": "{{'UI:Button:MoveDown'|dict_s}}"},
|
||||
'oDefaultSettings' : {{ oUIBlock.GetOptions()["oDefaultSettings"]|raw}},
|
||||
};
|
||||
console.warn($aOptions);
|
||||
//if (!typeof $('#datatable_dlg_{{ oUIBlock.GetId() }}').DataTableSettings() !== "undefined")
|
||||
if ($('#datatable_dlg_{{ oUIBlock.GetId() }}').DataTableSettings())
|
||||
{
|
||||
$('#datatable_dlg_{{ oUIBlock.GetId() }}').DataTableSettings( "destroy");
|
||||
}
|
||||
$('#datatable_dlg_{{ oUIBlock.GetId() }}').DataTableSettings( $aOptions);
|
||||
@@ -1,10 +1,9 @@
|
||||
{# @copyright Copyright (C) 2010-2020 Combodo SARL #}
|
||||
{# @license http://opensource.org/licenses/AGPL-3.0 #}
|
||||
{% apply spaceless %}
|
||||
<div id="{{ oUIBlock.GetId() }}" class="ibo-panel ibo-is-{{ oUIBlock.GetColor() }}">
|
||||
<div id="{{ oUIBlock.GetId() }}" class="ibo-panel ibo-is-{{ oUIBlock.GetColor() }} {{ oUIBlock.GetCSSClasses() }}">
|
||||
<div class="ibo-panel--header">
|
||||
{% block iboPanelHeader %}
|
||||
<div class="ibo-panel--title">{% block iboPanelTitle %}{{ oUIBlock.GetTitle() }}{% endblock %}</div>
|
||||
<div class="ibo-panel--toolbar">
|
||||
{% block iboPanelToolbar %}
|
||||
{% for oToolbarBlock in oUIBlock.GetToolbarBlocks() %}
|
||||
@@ -12,6 +11,7 @@
|
||||
{% endfor %}
|
||||
{% endblock %}
|
||||
</div>
|
||||
<div class="ibo-panel--title">{% block iboPanelTitle %}{{ oUIBlock.GetTitle()|raw }}{% endblock %}</div>
|
||||
{% endblock %}
|
||||
</div>
|
||||
<div class="ibo-panel--body">
|
||||
|
||||
@@ -1093,7 +1093,6 @@ input.dp-applied {
|
||||
border-radius: $search-criteria-box-radius;
|
||||
box-shadow: $box-shadow-regular;
|
||||
}
|
||||
.sfc_form_group,
|
||||
.sfm_content{
|
||||
position: absolute;
|
||||
z-index: -1;
|
||||
|
||||