From f718b26b7bacf28af7411d4b50d2bfc7eec9e1a0 Mon Sep 17 00:00:00 2001 From: acognet Date: Wed, 4 Nov 2020 13:36:20 +0100 Subject: [PATCH 01/16] =?UTF-8?q?N=C2=B02847=20-=20Tranform=20old=20itop?= =?UTF-8?q?=20datatable=20to=20jquery=20DataTable?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- application/cmdbabstract.class.inc.php | 143 +---- application/dashboard.class.inc.php | 2 + application/datatable.class.inc.php | 398 +----------- application/displayblock.class.inc.php | 36 +- application/shortcut.class.inc.php | 1 + .../ui.linksdirectwidget.class.inc.php | 5 +- application/ui.linkswidget.class.inc.php | 17 +- .../ui.searchformforeignkeys.class.inc.php | 5 +- core/attributedef.class.inc.php | 26 + css/backoffice/components/_all.scss | 1 + css/backoffice/components/_datatable.scss | 85 +++ css/backoffice/components/_title.scss | 26 + css/light-grey.scss | 125 ++-- .../portal/templates/layout.html.twig | 26 +- dictionaries/cs.dictionary.itop.ui.php | 3 +- dictionaries/da.dictionary.itop.ui.php | 3 +- dictionaries/de.dictionary.itop.ui.php | 3 +- dictionaries/en.dictionary.itop.ui.php | 3 +- dictionaries/es_cr.dictionary.itop.ui.php | 3 +- dictionaries/fr.dictionary.itop.ui.php | 3 +- dictionaries/ja.dictionary.itop.ui.php | 3 +- dictionaries/nl.dictionary.itop.ui.php | 3 +- dictionaries/pt_br.dictionary.itop.ui.php | 3 +- dictionaries/ru.dictionary.itop.ui.php | 3 +- dictionaries/sk.dictionary.itop.ui.php | 3 +- .../en.dictionary.itop.datatable.php | 33 + dictionaries/zh_cn.dictionary.itop.ui.php | 3 +- documentation/deprecations.md | 7 +- js/dataTables.pipeline.js | 125 ++++ js/dataTables.settings.js | 359 +++++++++++ js/datatable.js | 1 + js/linkswidget.js | 12 +- js/search/search_form_criteria.js | 2 +- js/search/search_form_handler.js | 18 +- js/utils.js | 8 +- lib/composer/autoload_classmap.php | 4 +- lib/composer/autoload_static.php | 4 +- .../css/dataTables.bootstrap.min.css | 0 .../css/fixedHeader.bootstrap.min.css | 0 .../css/responsive.bootstrap.min.css | 0 .../datatables/css/scroller.bootstrap.min.css | 0 .../datatables/css/select.bootstrap.min.css | 0 .../datatables/css/select.dataTables.min.css | 0 .../datatables/images/sort_asc.png | Bin .../datatables/images/sort_asc_disabled.png | Bin .../datatables/images/sort_both.png | Bin .../datatables/images/sort_desc.png | Bin .../datatables/images/sort_desc_disabled.png | Bin .../datatables/js/dataTables.bootstrap.min.js | 0 .../js/dataTables.fixedHeader.min.js | 0 .../js/dataTables.responsive.min.js | 0 .../datatables/js/dataTables.scroller.min.js | 0 .../datatables/js/dataTables.select.min.js | 0 .../datatables/js/datetime-moment.js | 0 .../datatables/js/jquery.dataTables.min.js | 0 pages/UI.php | 27 +- pages/ajax.render.php | 188 +++++- pages/ajax.searchform.php | 2 +- .../UI/Component/DataTable/DataTable.php | 127 ++++ .../Component/DataTable/DataTableFactory.php | 589 ++++++++++++++++++ .../Component/DataTable/DataTableSettings.php | 355 +++++++++++ sources/application/WebPage/NiceWebPage.php | 71 +-- .../search/searchform.class.inc.php | 52 +- .../components/datatable/layout.html.twig | 61 ++ templates/components/datatable/layout.js.twig | 256 ++++++++ templates/components/panel/layout.html.twig | 4 +- .../expected/css/light-grey.scss | 1 - 67 files changed, 2506 insertions(+), 732 deletions(-) create mode 100644 css/backoffice/components/_datatable.scss create mode 100644 dictionaries/ui/components/en.dictionary.itop.datatable.php create mode 100644 js/dataTables.pipeline.js create mode 100644 js/dataTables.settings.js rename {datamodels/2.x/itop-portal-base/portal/public/lib => lib}/datatables/css/dataTables.bootstrap.min.css (100%) rename {datamodels/2.x/itop-portal-base/portal/public/lib => lib}/datatables/css/fixedHeader.bootstrap.min.css (100%) rename {datamodels/2.x/itop-portal-base/portal/public/lib => lib}/datatables/css/responsive.bootstrap.min.css (100%) rename {datamodels/2.x/itop-portal-base/portal/public/lib => lib}/datatables/css/scroller.bootstrap.min.css (100%) rename {datamodels/2.x/itop-portal-base/portal/public/lib => lib}/datatables/css/select.bootstrap.min.css (100%) rename {datamodels/2.x/itop-portal-base/portal/public/lib => lib}/datatables/css/select.dataTables.min.css (100%) rename {datamodels/2.x/itop-portal-base/portal/public/lib => lib}/datatables/images/sort_asc.png (100%) rename {datamodels/2.x/itop-portal-base/portal/public/lib => lib}/datatables/images/sort_asc_disabled.png (100%) rename {datamodels/2.x/itop-portal-base/portal/public/lib => lib}/datatables/images/sort_both.png (100%) rename {datamodels/2.x/itop-portal-base/portal/public/lib => lib}/datatables/images/sort_desc.png (100%) rename {datamodels/2.x/itop-portal-base/portal/public/lib => lib}/datatables/images/sort_desc_disabled.png (100%) rename {datamodels/2.x/itop-portal-base/portal/public/lib => lib}/datatables/js/dataTables.bootstrap.min.js (100%) rename {datamodels/2.x/itop-portal-base/portal/public/lib => lib}/datatables/js/dataTables.fixedHeader.min.js (100%) rename {datamodels/2.x/itop-portal-base/portal/public/lib => lib}/datatables/js/dataTables.responsive.min.js (100%) rename {datamodels/2.x/itop-portal-base/portal/public/lib => lib}/datatables/js/dataTables.scroller.min.js (100%) rename {datamodels/2.x/itop-portal-base/portal/public/lib => lib}/datatables/js/dataTables.select.min.js (100%) rename {datamodels/2.x/itop-portal-base/portal/public/lib => lib}/datatables/js/datetime-moment.js (100%) rename {datamodels/2.x/itop-portal-base/portal/public/lib => lib}/datatables/js/jquery.dataTables.min.js (100%) create mode 100644 sources/application/UI/Component/DataTable/DataTable.php create mode 100644 sources/application/UI/Component/DataTable/DataTableFactory.php create mode 100644 sources/application/UI/Component/DataTable/DataTableSettings.php create mode 100644 templates/components/datatable/layout.html.twig create mode 100644 templates/components/datatable/layout.js.twig diff --git a/application/cmdbabstract.class.inc.php b/application/cmdbabstract.class.inc.php index 71b3e2040..05e69376e 100644 --- a/application/cmdbabstract.class.inc.php +++ b/application/cmdbabstract.class.inc.php @@ -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()) { diff --git a/application/dashboard.class.inc.php b/application/dashboard.class.inc.php index 3a0428054..3539baa8d 100644 --- a/application/dashboard.class.inc.php +++ b/application/dashboard.class.inc.php @@ -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'); diff --git a/application/datatable.class.inc.php b/application/datatable.class.inc.php index a975e3ad3..0765c4190 100644 --- a/application/datatable.class.inc.php +++ b/application/datatable.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 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; - } -} diff --git a/application/displayblock.class.inc.php b/application/displayblock.class.inc.php index 12b0ec042..0e75a5662 100644 --- a/application/displayblock.class.inc.php +++ b/application/displayblock.class.inc.php @@ -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("
\n"); try { $oHtml->AddSubBlock($this->GetRenderContent($oPage, $aExtraParams, $sId)); } catch (Exception $e) { IssueLog::Error('Exception during GetDisplay: '.$e->getMessage()); } - $oHtml->AddHtml("
\n"); } else { // render it as an Ajax (asynchronous) call - $oHtml->AddHtml("
\n"); + $oHtml->AddCSSClasses("display_block loading"); $oHtml->AddHtml($oPage->GetP(" ".Dict::S('UI:Loading'))); - $oHtml->AddHtml("
\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 .= "".cmdbAbstractObject::GetDisplayExtendedSet($oPage, $oSet, $aExtraParams)."\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 .= "".render_block($oBlock)."\n"; } } $sHtml .= "\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 .= "
\n"; $aExtraParams['currentId'] = $sId; - $sHtml .= cmdbAbstractObject::GetSearchForm($oPage, $this->m_oSet, $aExtraParams); - $sHtml .= "
\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; diff --git a/application/shortcut.class.inc.php b/application/shortcut.class.inc.php index 42d220053..1453966c9 100644 --- a/application/shortcut.class.inc.php +++ b/application/shortcut.class.inc.php @@ -15,6 +15,7 @@ // // You should have received a copy of the GNU Affero General Public License // along with iTop. If not, see +use Combodo\iTop\Application\UI\Component\DataTable\DataTableSettings; /** diff --git a/application/ui.linksdirectwidget.class.inc.php b/application/ui.linksdirectwidget.class.inc.php index de4803312..b11e353e2 100644 --- a/application/ui.linksdirectwidget.class.inc.php +++ b/application/ui.linksdirectwidget.class.inc.php @@ -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('
'); + //$oPage->add('
'); $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("
\n"); + //$oPage->add("
\n"); $oHiddenFilter = new DBObjectSearch($this->sLinkedClass); if (($oCurrentObj != null) && MetaModel::IsSameFamilyBranch($this->sLinkedClass, $this->sClass)) { @@ -355,7 +355,6 @@ class UILinksWidgetDirect    -
HTML ); } diff --git a/application/ui.linkswidget.class.inc.php b/application/ui.linkswidget.class.inc.php index cdf9a86e4..54048e9ac 100644 --- a/application/ui.linkswidget.class.inc.php +++ b/application/ui.linkswidget.class.inc.php @@ -368,7 +368,8 @@ JS protected function DisplayFormTable(WebPage $oP, $aConfig, $aData) { $sHtml = "m_sAttCode}{$this->m_sNameSuffix}\" value=\"\">"; - $sHtml .= "\n"; + $sHtml .= "
\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 .= "\n"; $sHtml .= "\n"; @@ -391,11 +392,11 @@ JS { $sHtml .= $this->DisplayFormRow($oP, $aConfig, $aRow, $iRowId); } - $sHtml .= "m_sAttCode}{$this->m_sNameSuffix}_empty_row\">"; + //$sHtml .= "m_sAttCode}{$this->m_sNameSuffix}_empty_row\">"; $sHtml .= "\n"; // Footer - $sHtml .= "
".Dict::S('UI:Message:EmptyList:UseAdd')."
".Dict::S('UI:Message:EmptyList:UseAdd')."
\n"; + $sHtml .= "
\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 .= "     m_sAttCode}{$this->m_sNameSuffix}_btnRemove\" type=\"button\" value=\"".Dict::S('UI:RemoveLinkedObjectsOf_Class')."\" onClick=\"oWidget{$this->m_iInputId}.RemoveSelected();\" >"; $sHtmlValue .= "   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();\">m_sAttCode}{$this->m_sNameSuffix}_indicatorAdd\">\n"; @@ -513,7 +515,7 @@ JS */ public function GetObjectPickerDialog($oPage, $oCurrentObj, $sJson, $aAlreadyLinkedIds = array(), $aPrefillFormParam = array()) { - $oPage->add("
\n"); + //$oPage->add("
\n"); $oAlreadyLinkedFilter = new DBObjectSearch($this->m_sRemoteClass); if (!$this->m_bDuplicatesAllowed && count($aAlreadyLinkedIds) > 0) { @@ -555,14 +557,13 @@ JS

{$sEmptyList}

-    +    + -
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);"); } diff --git a/application/ui.searchformforeignkeys.class.inc.php b/application/ui.searchformforeignkeys.class.inc.php index 80fdb0cb2..8fd25a329 100644 --- a/application/ui.searchformforeignkeys.class.inc.php +++ b/application/ui.searchformforeignkeys.class.inc.php @@ -40,7 +40,6 @@ class UISearchFormForeignKeys */ public function ShowModalSearchForeignKeys($oPage, $sTitle) { - $oPage->add("
\n"); $oFilter = new DBObjectSearch($this->m_sRemoteClass); @@ -65,9 +64,9 @@ class UISearchFormForeignKeys

{$sEmptyList}

-    +    + -
HTML ); diff --git a/core/attributedef.class.inc.php b/core/attributedef.class.inc.php index e3e8cb04c..f7f46ff03 100644 --- a/core/attributedef.class.inc.php +++ b/core/attributedef.class.inc.php @@ -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 ''.parent::GetAsHTML($sValue).''; } + public function GetRenderForDataTable(string $sClassAlias) :string + { + $sRenderFunction = "return ' '+data+'' ;"; + return $sRenderFunction; + } } /** @@ -4992,6 +5006,12 @@ class AttributePhoneNumber extends AttributeString return ''.parent::GetAsHTML($sValue).''; } + + public function GetRenderForDataTable(string $sClassAlias) :string + { + $sRenderFunction = "return ' '+data+'' ;"; + return $sRenderFunction; + } } /** @@ -6781,6 +6801,12 @@ class AttributeExternalKey extends AttributeDBFieldVoid return DBObject::MakeHyperLink($this->GetTargetClass(), $sValue); } + + public function GetRenderForDataTable(string $sClassAlias) :string + { + $sRenderFunction = "return 'm_aParams['targetclass']."&id='+data+'\'>'+row['".$sClassAlias."/".$this->m_sCode."_friendlyname']+'' ;"; + return $sRenderFunction; + } } /** diff --git a/css/backoffice/components/_all.scss b/css/backoffice/components/_all.scss index 8998ff7ed..6d066080f 100644 --- a/css/backoffice/components/_all.scss +++ b/css/backoffice/components/_all.scss @@ -18,6 +18,7 @@ @import "input/all"; @import "title"; +@import "datatable"; @import "form"; @import "fieldset"; @import "field"; diff --git a/css/backoffice/components/_datatable.scss b/css/backoffice/components/_datatable.scss new file mode 100644 index 000000000..6ad6b0644 --- /dev/null +++ b/css/backoffice/components/_datatable.scss @@ -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; +} \ No newline at end of file diff --git a/css/backoffice/components/_title.scss b/css/backoffice/components/_title.scss index de0b60378..64f4402e7 100644 --- a/css/backoffice/components/_title.scss +++ b/css/backoffice/components/_title.scss @@ -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; } \ No newline at end of file diff --git a/css/light-grey.scss b/css/light-grey.scss index 0669cdc17..d5dfb3658 100644 --- a/css/light-grey.scss +++ b/css/light-grey.scss @@ -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; diff --git a/datamodels/2.x/itop-portal-base/portal/templates/layout.html.twig b/datamodels/2.x/itop-portal-base/portal/templates/layout.html.twig index f1c429f4d..e6123d6dc 100644 --- a/datamodels/2.x/itop-portal-base/portal/templates/layout.html.twig +++ b/datamodels/2.x/itop-portal-base/portal/templates/layout.html.twig @@ -31,12 +31,12 @@ {# - Bootstrap Datetime picker #} {# - Datatables #} - - - - - - + + + + + + {# - Font OpenSans #} {# - Font Combodo #} @@ -112,13 +112,13 @@ {# Moment.js with locales#} {# Datatables #} - - - - - - - + + + + + + + {# Export for Datatables #} diff --git a/dictionaries/cs.dictionary.itop.ui.php b/dictionaries/cs.dictionary.itop.ui.php index a876cb021..45946c3e7 100755 --- a/dictionaries/cs.dictionary.itop.ui.php +++ b/dictionaries/cs.dictionary.itop.ui.php @@ -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', diff --git a/dictionaries/da.dictionary.itop.ui.php b/dictionaries/da.dictionary.itop.ui.php index a9580962e..ad527e31c 100644 --- a/dictionaries/da.dictionary.itop.ui.php +++ b/dictionaries/da.dictionary.itop.ui.php @@ -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', diff --git a/dictionaries/de.dictionary.itop.ui.php b/dictionaries/de.dictionary.itop.ui.php index 65e9ef506..c4bccd924 100644 --- a/dictionaries/de.dictionary.itop.ui.php +++ b/dictionaries/de.dictionary.itop.ui.php @@ -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', diff --git a/dictionaries/en.dictionary.itop.ui.php b/dictionaries/en.dictionary.itop.ui.php index 05746117c..58c61c314 100644 --- a/dictionaries/en.dictionary.itop.ui.php +++ b/dictionaries/en.dictionary.itop.ui.php @@ -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', diff --git a/dictionaries/es_cr.dictionary.itop.ui.php b/dictionaries/es_cr.dictionary.itop.ui.php index 0e5699ad1..d5c1ab9c7 100644 --- a/dictionaries/es_cr.dictionary.itop.ui.php +++ b/dictionaries/es_cr.dictionary.itop.ui.php @@ -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', diff --git a/dictionaries/fr.dictionary.itop.ui.php b/dictionaries/fr.dictionary.itop.ui.php index 296d3ab2e..6bd6b5e0d 100644 --- a/dictionaries/fr.dictionary.itop.ui.php +++ b/dictionaries/fr.dictionary.itop.ui.php @@ -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', diff --git a/dictionaries/ja.dictionary.itop.ui.php b/dictionaries/ja.dictionary.itop.ui.php index 39644c3ab..a2b90f9c6 100644 --- a/dictionaries/ja.dictionary.itop.ui.php +++ b/dictionaries/ja.dictionary.itop.ui.php @@ -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' => 'すべてのリストのデフォルト', diff --git a/dictionaries/nl.dictionary.itop.ui.php b/dictionaries/nl.dictionary.itop.ui.php index 0991e5bf0..f134d8442 100644 --- a/dictionaries/nl.dictionary.itop.ui.php +++ b/dictionaries/nl.dictionary.itop.ui.php @@ -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', diff --git a/dictionaries/pt_br.dictionary.itop.ui.php b/dictionaries/pt_br.dictionary.itop.ui.php index f435f7944..2d03baa08 100644 --- a/dictionaries/pt_br.dictionary.itop.ui.php +++ b/dictionaries/pt_br.dictionary.itop.ui.php @@ -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', diff --git a/dictionaries/ru.dictionary.itop.ui.php b/dictionaries/ru.dictionary.itop.ui.php index c95697a79..a0d6ba9ff 100644 --- a/dictionaries/ru.dictionary.itop.ui.php +++ b/dictionaries/ru.dictionary.itop.ui.php @@ -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' => 'Для всех списков', diff --git a/dictionaries/sk.dictionary.itop.ui.php b/dictionaries/sk.dictionary.itop.ui.php index d2b164b05..8505aeac6 100644 --- a/dictionaries/sk.dictionary.itop.ui.php +++ b/dictionaries/sk.dictionary.itop.ui.php @@ -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', diff --git a/dictionaries/ui/components/en.dictionary.itop.datatable.php b/dictionaries/ui/components/en.dictionary.itop.datatable.php new file mode 100644 index 000000000..9268242d4 --- /dev/null +++ b/dictionaries/ui/components/en.dictionary.itop.datatable.php @@ -0,0 +1,33 @@ + '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', +)); \ No newline at end of file diff --git a/dictionaries/zh_cn.dictionary.itop.ui.php b/dictionaries/zh_cn.dictionary.itop.ui.php index 52bca2ff4..32335cd68 100644 --- a/dictionaries/zh_cn.dictionary.itop.ui.php +++ b/dictionaries/zh_cn.dictionary.itop.ui.php @@ -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' => '默认所有列表', diff --git a/documentation/deprecations.md b/documentation/deprecations.md index fcc1d19b9..4ab9c91e3 100644 --- a/documentation/deprecations.md +++ b/documentation/deprecations.md @@ -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 \ No newline at end of file diff --git a/js/dataTables.pipeline.js b/js/dataTables.pipeline.js new file mode 100644 index 000000000..eb4e8398e --- /dev/null +++ b/js/dataTables.pipeline.js @@ -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; + } ); +} ); \ No newline at end of file diff --git a/js/dataTables.settings.js b/js/dataTables.settings.js new file mode 100644 index 000000000..53ff1647c --- /dev/null +++ b/js/dataTables.settings.js @@ -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 += ""+champs.label+""; + } + }); + }); + $.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( "" + + ""+entete+"
" ); + //$('#'+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; + } + }); +}); \ No newline at end of file diff --git a/js/datatable.js b/js/datatable.js index 37c0efd27..d57f7c129 100644 --- a/js/datatable.js +++ b/js/datatable.js @@ -1,4 +1,5 @@ // jQuery UI style "widget" for selecting and sorting "fields" +//@deprecated $(function() { // the widget definition, where "itop" is the namespace, diff --git a/js/linkswidget.js b/js/linkswidget.js index baee7f95b..40d7d8e62 100644 --- a/js/linkswidget.js +++ b/js/linkswidget.js @@ -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 // { diff --git a/js/search/search_form_criteria.js b/js/search/search_form_criteria.js index 2dd528ef0..40baf7f12 100644 --- a/js/search/search_form_criteria.js +++ b/js/search/search_form_criteria.js @@ -380,7 +380,7 @@ $(function() // Prepare base DOM structure this.element .append('
') - .append('
'); + .append('
'); // Bind events // Note: No event to handle criteria closing when clicking outside of it as it is already handle by the form handler. diff --git a/js/search/search_form_handler.js b/js/search/search_form_handler.js index 3e68900e3..368ea5fdf 100644 --- a/js/search/search_form_handler.js +++ b/js/search/search_form_handler.js @@ -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 = $('
').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('
'); + .append('
'); // Prepare content - this._prepareMoreCriterionMenu(); this._prepareExistingCriterion(); + this._prepareMoreCriterionMenu(); this._prepareSubmitButton(); }, // - Prepare "more" button @@ -398,7 +398,7 @@ $(function() // Header part var oHeaderElem = $('
') - .append('' + Dict.S('UI:Search:Criterion:MoreMenu:AddCriteria') + '') + .append('') .appendTo(this.elements.more_criterion); // Content part @@ -695,7 +695,7 @@ $(function() else { var oCriterionRowElem = $('
') - .addClass('sf_criterion_row') + .addClass('sf_criterion_row ibo-criterion-row') .appendTo(this.elements.criterion_area); } @@ -706,7 +706,7 @@ $(function() else { var oCriterionGroupElem = $('
') - .addClass('sf_criterion_group') + .addClass('sf_criterion_group ibo-criterion-group') .appendTo(oCriterionRowElem); } @@ -754,7 +754,7 @@ $(function() oResultAreaElem = $('
').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() === '') diff --git a/js/utils.js b/js/utils.js index b08a39cab..eb708930a 100644 --- a/js/utils.js +++ b/js/utils.js @@ -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'; diff --git a/lib/composer/autoload_classmap.php b/lib/composer/autoload_classmap.php index c1d33ded2..757f2dc5a 100644 --- a/lib/composer/autoload_classmap.php +++ b/lib/composer/autoload_classmap.php @@ -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', diff --git a/lib/composer/autoload_static.php b/lib/composer/autoload_static.php index c65c884fc..a88877f24 100644 --- a/lib/composer/autoload_static.php +++ b/lib/composer/autoload_static.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', diff --git a/datamodels/2.x/itop-portal-base/portal/public/lib/datatables/css/dataTables.bootstrap.min.css b/lib/datatables/css/dataTables.bootstrap.min.css similarity index 100% rename from datamodels/2.x/itop-portal-base/portal/public/lib/datatables/css/dataTables.bootstrap.min.css rename to lib/datatables/css/dataTables.bootstrap.min.css diff --git a/datamodels/2.x/itop-portal-base/portal/public/lib/datatables/css/fixedHeader.bootstrap.min.css b/lib/datatables/css/fixedHeader.bootstrap.min.css similarity index 100% rename from datamodels/2.x/itop-portal-base/portal/public/lib/datatables/css/fixedHeader.bootstrap.min.css rename to lib/datatables/css/fixedHeader.bootstrap.min.css diff --git a/datamodels/2.x/itop-portal-base/portal/public/lib/datatables/css/responsive.bootstrap.min.css b/lib/datatables/css/responsive.bootstrap.min.css similarity index 100% rename from datamodels/2.x/itop-portal-base/portal/public/lib/datatables/css/responsive.bootstrap.min.css rename to lib/datatables/css/responsive.bootstrap.min.css diff --git a/datamodels/2.x/itop-portal-base/portal/public/lib/datatables/css/scroller.bootstrap.min.css b/lib/datatables/css/scroller.bootstrap.min.css similarity index 100% rename from datamodels/2.x/itop-portal-base/portal/public/lib/datatables/css/scroller.bootstrap.min.css rename to lib/datatables/css/scroller.bootstrap.min.css diff --git a/datamodels/2.x/itop-portal-base/portal/public/lib/datatables/css/select.bootstrap.min.css b/lib/datatables/css/select.bootstrap.min.css similarity index 100% rename from datamodels/2.x/itop-portal-base/portal/public/lib/datatables/css/select.bootstrap.min.css rename to lib/datatables/css/select.bootstrap.min.css diff --git a/datamodels/2.x/itop-portal-base/portal/public/lib/datatables/css/select.dataTables.min.css b/lib/datatables/css/select.dataTables.min.css similarity index 100% rename from datamodels/2.x/itop-portal-base/portal/public/lib/datatables/css/select.dataTables.min.css rename to lib/datatables/css/select.dataTables.min.css diff --git a/datamodels/2.x/itop-portal-base/portal/public/lib/datatables/images/sort_asc.png b/lib/datatables/images/sort_asc.png similarity index 100% rename from datamodels/2.x/itop-portal-base/portal/public/lib/datatables/images/sort_asc.png rename to lib/datatables/images/sort_asc.png diff --git a/datamodels/2.x/itop-portal-base/portal/public/lib/datatables/images/sort_asc_disabled.png b/lib/datatables/images/sort_asc_disabled.png similarity index 100% rename from datamodels/2.x/itop-portal-base/portal/public/lib/datatables/images/sort_asc_disabled.png rename to lib/datatables/images/sort_asc_disabled.png diff --git a/datamodels/2.x/itop-portal-base/portal/public/lib/datatables/images/sort_both.png b/lib/datatables/images/sort_both.png similarity index 100% rename from datamodels/2.x/itop-portal-base/portal/public/lib/datatables/images/sort_both.png rename to lib/datatables/images/sort_both.png diff --git a/datamodels/2.x/itop-portal-base/portal/public/lib/datatables/images/sort_desc.png b/lib/datatables/images/sort_desc.png similarity index 100% rename from datamodels/2.x/itop-portal-base/portal/public/lib/datatables/images/sort_desc.png rename to lib/datatables/images/sort_desc.png diff --git a/datamodels/2.x/itop-portal-base/portal/public/lib/datatables/images/sort_desc_disabled.png b/lib/datatables/images/sort_desc_disabled.png similarity index 100% rename from datamodels/2.x/itop-portal-base/portal/public/lib/datatables/images/sort_desc_disabled.png rename to lib/datatables/images/sort_desc_disabled.png diff --git a/datamodels/2.x/itop-portal-base/portal/public/lib/datatables/js/dataTables.bootstrap.min.js b/lib/datatables/js/dataTables.bootstrap.min.js similarity index 100% rename from datamodels/2.x/itop-portal-base/portal/public/lib/datatables/js/dataTables.bootstrap.min.js rename to lib/datatables/js/dataTables.bootstrap.min.js diff --git a/datamodels/2.x/itop-portal-base/portal/public/lib/datatables/js/dataTables.fixedHeader.min.js b/lib/datatables/js/dataTables.fixedHeader.min.js similarity index 100% rename from datamodels/2.x/itop-portal-base/portal/public/lib/datatables/js/dataTables.fixedHeader.min.js rename to lib/datatables/js/dataTables.fixedHeader.min.js diff --git a/datamodels/2.x/itop-portal-base/portal/public/lib/datatables/js/dataTables.responsive.min.js b/lib/datatables/js/dataTables.responsive.min.js similarity index 100% rename from datamodels/2.x/itop-portal-base/portal/public/lib/datatables/js/dataTables.responsive.min.js rename to lib/datatables/js/dataTables.responsive.min.js diff --git a/datamodels/2.x/itop-portal-base/portal/public/lib/datatables/js/dataTables.scroller.min.js b/lib/datatables/js/dataTables.scroller.min.js similarity index 100% rename from datamodels/2.x/itop-portal-base/portal/public/lib/datatables/js/dataTables.scroller.min.js rename to lib/datatables/js/dataTables.scroller.min.js diff --git a/datamodels/2.x/itop-portal-base/portal/public/lib/datatables/js/dataTables.select.min.js b/lib/datatables/js/dataTables.select.min.js similarity index 100% rename from datamodels/2.x/itop-portal-base/portal/public/lib/datatables/js/dataTables.select.min.js rename to lib/datatables/js/dataTables.select.min.js diff --git a/datamodels/2.x/itop-portal-base/portal/public/lib/datatables/js/datetime-moment.js b/lib/datatables/js/datetime-moment.js similarity index 100% rename from datamodels/2.x/itop-portal-base/portal/public/lib/datatables/js/datetime-moment.js rename to lib/datatables/js/datetime-moment.js diff --git a/datamodels/2.x/itop-portal-base/portal/public/lib/datatables/js/jquery.dataTables.min.js b/lib/datatables/js/jquery.dataTables.min.js similarity index 100% rename from datamodels/2.x/itop-portal-base/portal/public/lib/datatables/js/jquery.dataTables.min.js rename to lib/datatables/js/jquery.dataTables.min.js diff --git a/pages/UI.php b/pages/UI.php index 856f2b0ed..f9fb91d28 100644 --- a/pages/UI.php +++ b/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); + } } } diff --git a/pages/ajax.render.php b/pages/ajax.render.php index 9ca402b9f..283498030 100644 --- a/pages/ajax.render.php +++ b/pages/ajax.render.php @@ -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); diff --git a/pages/ajax.searchform.php b/pages/ajax.searchform.php index b55bea343..a58e664dc 100644 --- a/pages/ajax.searchform.php +++ b/pages/ajax.searchform.php @@ -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'); diff --git a/sources/application/UI/Component/DataTable/DataTable.php b/sources/application/UI/Component/DataTable/DataTable.php new file mode 100644 index 000000000..d12d4ba2f --- /dev/null +++ b/sources/application/UI/Component/DataTable/DataTable.php @@ -0,0 +1,127 @@ +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; + } + + + +} diff --git a/sources/application/UI/Component/DataTable/DataTableFactory.php b/sources/application/UI/Component/DataTable/DataTableFactory.php new file mode 100644 index 000000000..e32fec712 --- /dev/null +++ b/sources/application/UI/Component/DataTable/DataTableFactory.php @@ -0,0 +1,589 @@ +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 ''+row['".$sClassAlias."/friendlyname']+'' ;", + ]; + } 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 ''+row['".$sClassAlias."/friendlyname']+'' ;", + ]; + } 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 ''+row['".$sClassName."/friendlyname']+'' ;", + "_"=>$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; + } +} \ No newline at end of file diff --git a/sources/application/UI/Component/DataTable/DataTableSettings.php b/sources/application/UI/Component/DataTable/DataTableSettings.php new file mode 100644 index 000000000..6b5f5a2f0 --- /dev/null +++ b/sources/application/UI/Component/DataTable/DataTableSettings.php @@ -0,0 +1,355 @@ +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; + } +} \ No newline at end of file diff --git a/sources/application/WebPage/NiceWebPage.php b/sources/application/WebPage/NiceWebPage.php index da9896b11..a3c9931c7 100644 --- a/sources/application/WebPage/NiceWebPage.php +++ b/sources/application/WebPage/NiceWebPage.php @@ -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); diff --git a/sources/application/search/searchform.class.inc.php b/sources/application/search/searchform.class.inc.php index 86da53990..b2a96b089 100644 --- a/sources/application/search/searchform.class.inc.php +++ b/sources/application/search/searchform.class.inc.php @@ -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 .= "
\n"; + $oUiBlock->AddHtml("
"); $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 .= "
\n"; // Don't use $_SERVER['SCRIPT_NAME'] since the form may be called asynchronously (from ajax.php) - $sHtml .= "

" . Dict::Format('UI:SearchFor_Class_Objects', $sClassesCombo) . "" . Dict::S('UI:SearchToggle') . ""; - $sHtml .= ""; +//(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 = ""; $sHtml .= ""; $sHtml .= "" . Dict::S('UI:Search:Obsolescence:DisabledHint') . ""; $sHtml .= "
"; $sHtml .= "" . Dict::S('UI:Search:AutoSubmit:DisabledHint') . ""; $sHtml .= "
"; $sHtml .= "
"; - $sHtml .= "

\n"; - $sHtml .= "
\n"; - $sHtml .= "
\n
\n"; - $sHtml .= "
\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( "
");//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 * diff --git a/templates/components/datatable/layout.html.twig b/templates/components/datatable/layout.html.twig new file mode 100644 index 000000000..98d60cd11 --- /dev/null +++ b/templates/components/datatable/layout.html.twig @@ -0,0 +1,61 @@ +{% for oSubBlock in oUIBlock.GetSubBlocks() %}{{ render_block(oSubBlock, {aPage: aPage}) }}{% endfor %} +{% if oUIBlock.GetOptions()["select"] is defined %} + + + +{% endif %} + + + + {% if oUIBlock.GetOptions()["select"] is defined %} + + {% endif %} + {% for aColumn in oUIBlock.GetDisplayColumns() %} + + {% endfor %} + +
{{ aColumn["attribute_label"] }}
+ + \ No newline at end of file diff --git a/templates/components/datatable/layout.js.twig b/templates/components/datatable/layout.js.twig new file mode 100644 index 000000000..106dac842 --- /dev/null +++ b/templates/components/datatable/layout.js.twig @@ -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": '', + "type": "html", + "data": "", + "render": function(data, type, row) + { + var oCheckboxElem = $(''); + 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); \ No newline at end of file diff --git a/templates/components/panel/layout.html.twig b/templates/components/panel/layout.html.twig index a7336b6e9..5a87ad589 100644 --- a/templates/components/panel/layout.html.twig +++ b/templates/components/panel/layout.html.twig @@ -1,10 +1,9 @@ {# @copyright Copyright (C) 2010-2020 Combodo SARL #} {# @license http://opensource.org/licenses/AGPL-3.0 #} {% apply spaceless %} -
+
{% block iboPanelHeader %} -
{% block iboPanelTitle %}{{ oUIBlock.GetTitle() }}{% endblock %}
{% block iboPanelToolbar %} {% for oToolbarBlock in oUIBlock.GetToolbarBlocks() %} @@ -12,6 +11,7 @@ {% endfor %} {% endblock %}
+
{% block iboPanelTitle %}{{ oUIBlock.GetTitle()|raw }}{% endblock %}
{% endblock %}
diff --git a/test/application/theme-handler/expected/css/light-grey.scss b/test/application/theme-handler/expected/css/light-grey.scss index 864323835..fe6bacc77 100644 --- a/test/application/theme-handler/expected/css/light-grey.scss +++ b/test/application/theme-handler/expected/css/light-grey.scss @@ -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; From 6237b5565c99b3d8bcf77ea3de2128dc614de496 Mon Sep 17 00:00:00 2001 From: Eric Date: Fri, 6 Nov 2020 09:08:12 +0100 Subject: [PATCH 02/16] =?UTF-8?q?N=C2=B02847=20-=20Fix=20panel=20toolbars?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- css/backoffice/components/_panel.scss | 1 + templates/components/panel/layout.html.twig | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/css/backoffice/components/_panel.scss b/css/backoffice/components/_panel.scss index b8a9fc852..119d0f300 100644 --- a/css/backoffice/components/_panel.scss +++ b/css/backoffice/components/_panel.scss @@ -77,6 +77,7 @@ $ibo-panel-colors: ( .ibo-panel--header { display: flex; + align-items: stretch; } .ibo-panel--title { diff --git a/templates/components/panel/layout.html.twig b/templates/components/panel/layout.html.twig index 5a87ad589..cf2071ddb 100644 --- a/templates/components/panel/layout.html.twig +++ b/templates/components/panel/layout.html.twig @@ -4,6 +4,7 @@
{% block iboPanelHeader %} +
{% block iboPanelTitle %}{{ oUIBlock.GetTitle()|raw }}{% endblock %}
{% block iboPanelToolbar %} {% for oToolbarBlock in oUIBlock.GetToolbarBlocks() %} @@ -11,7 +12,6 @@ {% endfor %} {% endblock %}
-
{% block iboPanelTitle %}{{ oUIBlock.GetTitle()|raw }}{% endblock %}
{% endblock %}
From bc809b0f3bf5a01062031a6d3c7860de87398fe9 Mon Sep 17 00:00:00 2001 From: Eric Date: Mon, 9 Nov 2020 08:00:26 +0100 Subject: [PATCH 03/16] =?UTF-8?q?N=C2=B02847=20-=20cleanup=20code?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Component/DataTable/DataTableFactory.php | 276 +++++++++++------- 1 file changed, 166 insertions(+), 110 deletions(-) diff --git a/sources/application/UI/Component/DataTable/DataTableFactory.php b/sources/application/UI/Component/DataTable/DataTableFactory.php index e32fec712..70bb2b3e6 100644 --- a/sources/application/UI/Component/DataTable/DataTableFactory.php +++ b/sources/application/UI/Component/DataTable/DataTableFactory.php @@ -6,9 +6,10 @@ namespace Combodo\iTop\Application\UI\Component\DataTable; +use ApplicationException; +use AttributeLinkedSet; use CMDBObjectSet; use cmdbAbstractObject; -use Combodo\iTop\Application\UI\Component\Html\Html; use Combodo\iTop\Application\UI\Component\Panel\PanelFactory; use MetaModel; use appUserPreferences; @@ -27,10 +28,28 @@ use Dict; */ class DataTableFactory { + /** + * @param \WebPage $oPage + * @param string $sListId + * @param \CMDBObjectSet $oSet + * @param array $aExtraParams + * + * @return \Combodo\iTop\Application\UI\Component\Panel\Panel + * @throws \ApplicationException + * @throws \ArchivedObjectException + * @throws \CoreException + * @throws \CoreUnexpectedValue + * @throws \DictExceptionMissingString + * @throws \MissingQueryArgument + * @throws \MySQLException + * @throws \MySQLHasGoneAwayException + * @throws \OQLException + * @throws \ReflectionException + */ 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 = PanelFactory::MakeForClass($oSet->GetClass(), "Result"); + $oDataTable = DataTableFactory::MakeForRendering($sListId, $oSet, $aExtraParams); $oPanel->AddMainBlock($oDataTable); $oMenuBlock = new MenuBlock($oSet->GetFilter(), 'list'); @@ -41,10 +60,28 @@ class DataTableFactory return $oPanel; } + + /** + * @param \WebPage $oPage + * @param string $sListId + * @param \CMDBObjectSet $oSet + * @param array $aExtraParams + * + * @return \Combodo\iTop\Application\UI\Component\Panel\Panel + * @throws \ArchivedObjectException + * @throws \CoreException + * @throws \CoreUnexpectedValue + * @throws \DictExceptionMissingString + * @throws \MissingQueryArgument + * @throws \MySQLException + * @throws \MySQLHasGoneAwayException + * @throws \OQLException + * @throws \ReflectionException + */ 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 = PanelFactory::MakeForClass($oSet->GetClass(), "Result"); + $oDataTable = DataTableFactory::MakeForRenderingObject($sListId, $oSet, $aExtraParams); $oPanel->AddMainBlock($oDataTable); $oMenuBlock = new MenuBlock($oSet->GetFilter(), 'list'); @@ -55,12 +92,21 @@ class DataTableFactory return $oPanel; } + /** * Make a basis Panel component * - * @param string $sTitle + * @param string $sListId + * @param \CMDBObjectSet $oSet + * @param array $aExtraParams * * @return DataTableBlock + * @throws \ApplicationException + * @throws \ArchivedObjectException + * @throws \CoreException + * @throws \CoreUnexpectedValue + * @throws \DictExceptionMissingString + * @throws \MySQLException */ public static function MakeForRendering(string $sListId, CMDBObjectSet $oSet, $aExtraParams = array()) { @@ -246,15 +292,16 @@ class DataTableFactory } $aOptions = []; - if($oDefaultSettings != null) - { + 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"; + } else { + if ($sSelectMode == 'single') { + $aOptions['select'] = "single"; + } } $aOptions['iPageSize'] = 10; @@ -262,9 +309,9 @@ class DataTableFactory $aOptions['iPageSize'] = $oCustomSettings->iDefaultPageSize; } - $aOptions['sTableId'] =$sTableId; - $aOptions['bUseCustomSettings'] =$bUseCustomSettings; - $aOptions['bViewLink'] =$bViewLink; + $aOptions['sTableId'] = $sTableId; + $aOptions['bUseCustomSettings'] = $bUseCustomSettings; + $aOptions['bViewLink'] = $bViewLink; $oDataTable->SetOptions($aOptions); $oDataTable->SetAjaxUrl("ajax.render.php"); @@ -280,6 +327,19 @@ class DataTableFactory return $oDataTable; } + + /** + * @param string $sListId + * @param \CMDBObjectSet $oSet + * @param array $aExtraParams + * + * @return \Combodo\iTop\Application\UI\Component\DataTable\DataTableBlock + * @throws \ArchivedObjectException + * @throws \CoreException + * @throws \CoreUnexpectedValue + * @throws \DictExceptionMissingString + * @throws \MySQLException + */ public static function MakeForRenderingObject(string $sListId, CMDBObjectSet $oSet, $aExtraParams = array()) { $oDataTable = new DataTableBlock('datatable_'.$sListId); @@ -296,64 +356,48 @@ class DataTableFactory trim($aExtraParams['extra_fields'])) : array(); $aExtraFields = array(); $sAttCode = ''; - foreach($aExtraFieldsRaw as $sFieldName) - { + foreach ($aExtraFieldsRaw as $sFieldName) { // Ignore attributes not of the main queried class - if (preg_match('/^(.*)\.(.*)$/', $sFieldName, $aMatches)) - { + if (preg_match('/^(.*)\.(.*)$/', $sFieldName, $aMatches)) { $sClassAlias = $aMatches[1]; $sAttCode = $aMatches[2]; - if (array_key_exists($sClassAlias, $oSet->GetSelectedClasses())) - { + if (array_key_exists($sClassAlias, $oSet->GetSelectedClasses())) { $aExtraFields[$sClassAlias][] = $sAttCode; } - } - else - { + } else { $aExtraFields['*'] = $sAttCode; } } $aClassAliases = $oSet->GetFilter()->GetSelectedClasses(); $aAuthorizedClasses = array(); - foreach($aClassAliases as $sAlias => $sClassName) - { + foreach ($aClassAliases as $sAlias => $sClassName) { if ((UserRights::IsActionAllowed($sClassName, UR_ACTION_READ, $oSet) != UR_ALLOWED_NO) && - ((count($aDisplayAliases) == 0) || (in_array($sAlias, $aDisplayAliases)))) - { + ((count($aDisplayAliases) == 0) || (in_array($sAlias, $aDisplayAliases)))) { $aAuthorizedClasses[$sAlias] = $sClassName; } } - foreach($aAuthorizedClasses as $sAlias => $sClassName) - { - if (array_key_exists($sAlias, $aExtraFields)) - { + foreach ($aAuthorizedClasses as $sAlias => $sClassName) { + if (array_key_exists($sAlias, $aExtraFields)) { $aList[$sAlias] = $aExtraFields[$sAlias]; - } - else - { + } else { $aList[$sAlias] = array(); } - if ($sZListName !== false) - { - $aDefaultList = self::FlattenZList(MetaModel::GetZListItems($sClassName, $sZListName)); - + if ($sZListName !== false) { + $aDefaultList = MetaModel::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) - { + foreach ($aList[$sAlias] as $index => $sAttCode) { $oAttDef = MetaModel::GetAttributeDef($sClassName, $sAttCode); - if ($oAttDef instanceof AttributeLinkedSet) - { + if ($oAttDef instanceof AttributeLinkedSet) { // Removed from the display list unset($aList[$sAlias][$index]); } } - if (empty($aList[$sAlias])) - { + if (empty($aList[$sAlias])) { unset($aList[$sAlias], $aAuthorizedClasses[$sAlias]); } } @@ -363,8 +407,7 @@ class DataTableFactory $oDefaultSettings = DataTableSettings::GetDataModelSettings($aAuthorizedClasses, $bViewLink, $aList); $bDisplayLimit = isset($aExtraParams['display_limit']) ? $aExtraParams['display_limit'] : true; - if ($bDisplayLimit) - { + if ($bDisplayLimit) { $iDefaultPageSize = appUserPreferences::GetPref('default_page_size', MetaModel::GetConfig()->GetMinDisplayLimit()); $oDefaultSettings->iDefaultPageSize = $iDefaultPageSize; @@ -445,15 +488,16 @@ class DataTableFactory } $aOptions = []; - if($oDefaultSettings != null) - { + 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"; + } else { + if ($sSelectMode == 'single') { + $aOptions['select'] = "single"; + } } $aOptions['iPageSize'] = 10; @@ -461,9 +505,9 @@ class DataTableFactory $aOptions['iPageSize'] = $oCustomSettings->iDefaultPageSize; } - $aOptions['sTableId'] =$sTableId; - $aOptions['bUseCustomSettings'] =$bUseCustomSettings; - $aOptions['bViewLink'] =$bViewLink; + $aOptions['sTableId'] = $sTableId; + $aOptions['bUseCustomSettings'] = $bUseCustomSettings; + $aOptions['bViewLink'] = $bViewLink; $oDataTable->SetOptions($aOptions); $oDataTable->SetAjaxUrl("ajax.render.php"); @@ -479,7 +523,18 @@ class DataTableFactory return $oDataTable; } - public static function GetOptionsForRendering(array $aColumns,string $sSelectMode, string $sFilter, int $iLength, array $aExtraParams) + + /** + * @param array $aColumns + * @param string $sSelectMode + * @param string $sFilter + * @param int $iLength + * @param array $aExtraParams + * + * @return array + * @throws \Exception + */ + public static function GetOptionsForRendering(array $aColumns, string $sSelectMode, string $sFilter, int $iLength, array $aExtraParams) { $aOptions = []; @@ -488,56 +543,56 @@ class DataTableFactory $aClassAliases = []; foreach ($aColumns as $sClassName => $aClassColumns) { - $aClassAliases[$sClassName]=$sClassName; + $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"; + $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["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 ''+row['".$sClassName."/friendlyname']+'' ;", - "_"=>$sClassName."/".$sAttCode, + $aColumnDefinition["render"] = [ + "display" => "return ''+row['".$sClassName."/friendlyname']+'' ;", + "_" => $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["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, + $aColumnDefinition["render"] = [ + "display" => $oAttDef->GetRenderForDataTable($sClassName), + "_" => $sClassName."/".$sAttCode, ]; } - array_push($aColumnsDefinitions,$aColumnDefinition); + array_push($aColumnsDefinitions, $aColumnDefinition); } } } - $aOptions['select'] =$sSelectMode; + $aOptions['select'] = $sSelectMode; $aOptions['pageLength'] = $iLength; - $sAjaxData=json_encode([ + $sAjaxData = json_encode([ "operation" => 'search', "filter" => $sFilter, "columns" => $aColumns, @@ -547,41 +602,42 @@ class DataTableFactory $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') - ], + "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" => ">>" ], - "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( { + "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; From 866a93c0c81ad11176c01d7ff20b2c097630a95f Mon Sep 17 00:00:00 2001 From: Eric Date: Mon, 9 Nov 2020 11:52:00 +0100 Subject: [PATCH 04/16] :white_check_mark: Fix unit tests --- .../precompiled-themes/light-grey/main.css | 184 ++++++------------ .../precompiled-themes/test-red/main.css | 184 ++++++------------ test/core/DBSearchTest.php | 21 +- 3 files changed, 139 insertions(+), 250 deletions(-) diff --git a/datamodels/2.x/itop-structure/precompiled-themes/light-grey/main.css b/datamodels/2.x/itop-structure/precompiled-themes/light-grey/main.css index 6551b1379..24a1b630d 100644 --- a/datamodels/2.x/itop-structure/precompiled-themes/light-grey/main.css +++ b/datamodels/2.x/itop-structure/precompiled-themes/light-grey/main.css @@ -1,6 +1,6 @@ /* === SIGNATURE BEGIN === -{"variables":"d751713988987e9331980363e24189ce","stylesheets":{"css-variables":"732f501302c538f594fb3c668d85b46c","jqueryui":"a887ad1c00f29132beba3bf729b981c7","main":"4da726efdbc7625538d988e1687f82ff"},"imports":[],"images":{"css\/ui-lightness\/images\/ui-icons_222222_256x240.png":"3a3c5468f484f07ac4a320d9e22acb8c","css\/ui-lightness\/images\/ui-bg_diagonals-thick_20_666666_40x40.png":"4429d568c67d8dfeb9040273ea0fb8c4","css\/ui-lightness\/images\/ui-icons_E87C1E_256x240.png":"7003dd36cb2aa032c8ec871ce4d4e03d","css\/ui-lightness\/images\/ui-icons_1c94c4_256x240.png":"dbd693dc8e0ef04e90a2f7ac7b390086","css\/ui-lightness\/images\/ui-icons_F26522_256x240.png":"16278ec0c07270be571f4c2e97fcc10c","css\/ui-lightness\/images\/ui-bg_diagonals-thick_18_b81900_40x40.png":"e460a66d4b3e093fc651e62a236267cb","css\/ui-lightness\/images\/ui-icons_ffffff_256x240.png":"41612b0f4a034424f8321c9f824a94da","css\/ui-lightness\/images\/ui-icons_ffd27a_256x240.png":"dda1b6f694b0d196aefc66a1d6d758f6","images\/actions_right.png":"31c8906bd25d27b83a0a2466bf903462","images\/ac-background.gif":"76135f3697b41a15aed787cfd77776c7","images\/green-square.gif":"16ea9a497d72f5e66e4e8ea9ae08024e","images\/tv-item.gif":"719fe2d4566108e73162fb8868d3778c","images\/tv-collapsable.gif":"63a3351ea0d580797c9b8c386aa4f48b","images\/tv-expandable.gif":"a2d1af4128e4a798a7f3390b12a28574","images\/tv-item-last.gif":"2ae7e1d9972ce71e5caa65a086bc5b7e","images\/tv-collapsable-last.gif":"71acaa9d7c2616e9e8b7131a75ca65da","images\/tv-expandable-last.gif":"9d51036b3a8102742709da66789fd0f7","images\/red-header.gif":"c73b8765f0c8c3c183cb6a0c2bb0ec69","images\/green-header.gif":"0e22a09bb8051b2a274b3427ede62e82","images\/orange-header.gif":"ce1f93f0af64431771b4cbd6c99c567b","images\/calendar.png":"ab56e59af3c96ca661821257d376465e","images\/truncated.png":"c6f91108afe8159d417b4dc556cd3b2a","images\/plus.gif":"f00e1e6e1161f48608bb2bbc79b9948c","images\/minus.gif":"6d77c0c0c2f86b6995d1cdf78274eaab","images\/full-screen.png":"b541fadd3f1563856a4b44aeebd9d563","images\/indicator.gif":"03ce3dcc84af110e9da8699a841e5200","images\/delete.png":"93c047549c31a270a037840277cf59d3","images\/info-mini.png":"445c090ed777c5e6a08ac390fa896193","images\/ok.png":"f6973773335fd83d8d2875f9a3c925af","images\/error.png":"1af8a1041016f67669c5fd22dc88c82e","images\/eye-open-555.png":"9940f4e5b1248042c238e1924359fd5e","images\/eye-closed-555.png":"6ad3b0bae791bf61addc9d8ca80a642d","images\/eye-open-fff.png":"b7db2402d4d5c72314c25790a66150d4","images\/eye-closed-fff.png":"f9be7454dbb47b0e0bca3aa370ae7db5"}} +{"variables":"d751713988987e9331980363e24189ce","stylesheets":{"css-variables":"732f501302c538f594fb3c668d85b46c","jqueryui":"a887ad1c00f29132beba3bf729b981c7","main":"0efa2620e936b99f9e2ad32088636b33"},"imports":[],"images":{"css\/ui-lightness\/images\/ui-icons_222222_256x240.png":"3a3c5468f484f07ac4a320d9e22acb8c","css\/ui-lightness\/images\/ui-bg_diagonals-thick_20_666666_40x40.png":"4429d568c67d8dfeb9040273ea0fb8c4","css\/ui-lightness\/images\/ui-icons_E87C1E_256x240.png":"7003dd36cb2aa032c8ec871ce4d4e03d","css\/ui-lightness\/images\/ui-icons_1c94c4_256x240.png":"dbd693dc8e0ef04e90a2f7ac7b390086","css\/ui-lightness\/images\/ui-icons_F26522_256x240.png":"16278ec0c07270be571f4c2e97fcc10c","css\/ui-lightness\/images\/ui-bg_diagonals-thick_18_b81900_40x40.png":"e460a66d4b3e093fc651e62a236267cb","css\/ui-lightness\/images\/ui-icons_ffffff_256x240.png":"41612b0f4a034424f8321c9f824a94da","css\/ui-lightness\/images\/ui-icons_ffd27a_256x240.png":"dda1b6f694b0d196aefc66a1d6d758f6","images\/actions_right.png":"31c8906bd25d27b83a0a2466bf903462","images\/ac-background.gif":"76135f3697b41a15aed787cfd77776c7","images\/green-square.gif":"16ea9a497d72f5e66e4e8ea9ae08024e","images\/tv-item.gif":"719fe2d4566108e73162fb8868d3778c","images\/tv-collapsable.gif":"63a3351ea0d580797c9b8c386aa4f48b","images\/tv-expandable.gif":"a2d1af4128e4a798a7f3390b12a28574","images\/tv-item-last.gif":"2ae7e1d9972ce71e5caa65a086bc5b7e","images\/tv-collapsable-last.gif":"71acaa9d7c2616e9e8b7131a75ca65da","images\/tv-expandable-last.gif":"9d51036b3a8102742709da66789fd0f7","images\/red-header.gif":"c73b8765f0c8c3c183cb6a0c2bb0ec69","images\/green-header.gif":"0e22a09bb8051b2a274b3427ede62e82","images\/orange-header.gif":"ce1f93f0af64431771b4cbd6c99c567b","images\/calendar.png":"ab56e59af3c96ca661821257d376465e","images\/truncated.png":"c6f91108afe8159d417b4dc556cd3b2a","images\/plus.gif":"f00e1e6e1161f48608bb2bbc79b9948c","images\/minus.gif":"6d77c0c0c2f86b6995d1cdf78274eaab","images\/full-screen.png":"b541fadd3f1563856a4b44aeebd9d563","images\/indicator.gif":"03ce3dcc84af110e9da8699a841e5200","images\/delete.png":"93c047549c31a270a037840277cf59d3","images\/info-mini.png":"445c090ed777c5e6a08ac390fa896193","images\/ok.png":"f6973773335fd83d8d2875f9a3c925af","images\/error.png":"1af8a1041016f67669c5fd22dc88c82e","images\/eye-open-555.png":"9940f4e5b1248042c238e1924359fd5e","images\/eye-closed-555.png":"6ad3b0bae791bf61addc9d8ca80a642d","images\/eye-open-fff.png":"b7db2402d4d5c72314c25790a66150d4","images\/eye-closed-fff.png":"f9be7454dbb47b0e0bca3aa370ae7db5"}} === SIGNATURE END === */ /*! @@ -99,7 +99,7 @@ background-repeat: no-repeat; width: 16px; height: 16px; - background-image: url("../../../../css/ui-lightness/images/ui-icons_222222_256x240.png?v=1604907799"); + background-image: url("../../../../css/ui-lightness/images/ui-icons_222222_256x240.png?v=1604919410"); filter: hue-rotate(0deg); } .ui-widget-icon-block { @@ -232,7 +232,7 @@ .ui-menu .ui-menu-item { margin: 0; cursor: pointer; - list-style-image: url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7?v=1604907799"); + list-style-image: url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7?v=1604919410"); } .ui-menu .ui-menu-item-wrapper { position: relative; @@ -298,7 +298,7 @@ color: #EA7D1E; } .ui-button:hover .ui-icon { - background-image: url("../../../../css/ui-lightness/images/ui-icons_E87C1E_256x240.png?v=1604907799"); + background-image: url("../../../../css/ui-lightness/images/ui-icons_E87C1E_256x240.png?v=1604919410"); } .ui-button:active { text-decoration: none; @@ -306,20 +306,20 @@ color: #EA7D1E; } .ui-button:active .ui-icon { - background-image: url("../../../../css/ui-lightness/images/ui-icons_E87C1E_256x240.png?v=1604907799"); + background-image: url("../../../../css/ui-lightness/images/ui-icons_E87C1E_256x240.png?v=1604919410"); } .ui-button:focus { font-weight: bold; color: #EA7D1E; } .ui-button:focus .ui-icon { - background-image: url("../../../../css/ui-lightness/images/ui-icons_E87C1E_256x240.png?v=1604907799"); + background-image: url("../../../../css/ui-lightness/images/ui-icons_E87C1E_256x240.png?v=1604919410"); } .ui-button .ui-state-highlight.ui-icon { - background-image: url("../../../../css/ui-lightness/images/ui-icons_1c94c4_256x240.png?v=1604907799"); + background-image: url("../../../../css/ui-lightness/images/ui-icons_1c94c4_256x240.png?v=1604919410"); } .ui-button .ui-icon { - background-image: url("../../../../css/ui-lightness/images/ui-icons_F26522_256x240.png?v=1604907799"); + background-image: url("../../../../css/ui-lightness/images/ui-icons_F26522_256x240.png?v=1604919410"); } .ui-button-icon-only { width: 2em; @@ -901,7 +901,7 @@ body .ui-tooltip { background-image: none; } .ui-widget-content .ui-icon { - background-image: url("../../../../css/ui-lightness/images/ui-icons_222222_256x240.png?v=1604907799"); + background-image: url("../../../../css/ui-lightness/images/ui-icons_222222_256x240.png?v=1604919410"); } .ui-widget-header .ui-priority-secondary { opacity: 0.7; @@ -913,7 +913,7 @@ body .ui-tooltip { background-image: none; } .ui-widget-header .ui-icon { - background-image: url("../../../../css/ui-lightness/images/ui-icons_ffffff_256x240.png?v=1604907799"); + background-image: url("../../../../css/ui-lightness/images/ui-icons_ffffff_256x240.png?v=1604919410"); } .ui-state-default a { text-decoration: none; @@ -925,7 +925,7 @@ body .ui-tooltip { text-decoration: none; } .ui-state-default .ui-icon { - background-image: url("../../../../css/ui-lightness/images/ui-icons_F26522_256x240.png?v=1604907799"); + background-image: url("../../../../css/ui-lightness/images/ui-icons_F26522_256x240.png?v=1604919410"); } a.ui-button { text-decoration: none; @@ -955,7 +955,7 @@ a:visited.ui-button { text-decoration: none; } .ui-state-hover .ui-icon { - background-image: url("../../../../css/ui-lightness/images/ui-icons_E87C1E_256x240.png?v=1604907799"); + background-image: url("../../../../css/ui-lightness/images/ui-icons_E87C1E_256x240.png?v=1604919410"); } .ui-state-focus a { text-decoration: none; @@ -970,7 +970,7 @@ a:visited.ui-button { text-decoration: none; } .ui-state-focus .ui-icon { - background-image: url("../../../../css/ui-lightness/images/ui-icons_E87C1E_256x240.png?v=1604907799"); + background-image: url("../../../../css/ui-lightness/images/ui-icons_E87C1E_256x240.png?v=1604919410"); } .ui-visual-focus { box-shadow: 0 0 3px 1px #5e9ed6; @@ -988,19 +988,19 @@ a:visited.ui-button { text-decoration: none; } .ui-state-active .ui-icon { - background-image: url("../../../../css/ui-lightness/images/ui-icons_E87C1E_256x240.png?v=1604907799"); + background-image: url("../../../../css/ui-lightness/images/ui-icons_E87C1E_256x240.png?v=1604919410"); } .ui-icon-background { background-color: #EA7D1E; } .ui-state-highlight .ui-icon { - background-image: url("../../../../css/ui-lightness/images/ui-icons_1c94c4_256x240.png?v=1604907799"); + background-image: url("../../../../css/ui-lightness/images/ui-icons_1c94c4_256x240.png?v=1604919410"); } .ui-state-error .ui-icon { - background-image: url("../../../../css/ui-lightness/images/ui-icons_ffd27a_256x240.png?v=1604907799"); + background-image: url("../../../../css/ui-lightness/images/ui-icons_ffd27a_256x240.png?v=1604919410"); } .ui-state-error-text .ui-icon { - background-image: url("../../../../css/ui-lightness/images/ui-icons_ffd27a_256x240.png?v=1604907799"); + background-image: url("../../../../css/ui-lightness/images/ui-icons_ffd27a_256x240.png?v=1604919410"); } .ui-priority-primary { font-weight: bold; @@ -1643,52 +1643,10 @@ a:visited.ui-button { color: #EA7D1E; text-decoration: none; } -#ibo-main-content table.datatable, .ui-dialog table.datatable { - width: 100%; - border: 0; - padding: 0; -} #ibo-main-content td.menucontainer, .ui-dialog td.menucontainer { text-align: right; -} -#ibo-main-content table.listResults, .ui-dialog table.listResults { - padding: 0px; - border-top: 3px solid #F1F1F1; - border-left: 3px solid #F1F1F1; - border-bottom: 3px solid #e6e6e1; - border-right: 3px solid #e6e6e1; - width: 100%; - background-color: #FFFFFF; -} -#ibo-main-content table.listResults td, .ui-dialog table.listResults td { - padding: 2px; -} -#ibo-main-content table.listResults td .view-image, .ui-dialog table.listResults td .view-image { - width: inherit !important; - height: inherit !important; -} -#ibo-main-content table.listResults td .view-image img, .ui-dialog table.listResults td .view-image img { - max-width: 48px !important; - max-height: 48px !important; - display: block; - margin-left: auto; - margin-right: auto; -} -#ibo-main-content table.listResults > tbody > tr > *, .ui-dialog table.listResults > tbody > tr > * { - transition: background-color 400ms linear; -} -#ibo-main-content table.listResults > tbody > tr:hover > *, .ui-dialog table.listResults > tbody > tr:hover > * { - cursor: pointer; -} -#ibo-main-content table.listResults > tbody > tr.selected:hover > *, .ui-dialog table.listResults > tbody > tr.selected:hover > * { /* hover on lines is currently done toggling td.hover, and having a rule for links */ - background-color: #f1a564; - color: #000; -} -#ibo-main-content table.listResults > tbody > tr:hover > *, .ui-dialog table.listResults > tbody > tr:hover > * { /* hover on lines is currently done toggling td.hover, and having a rule for links */ - background-color: #fdf5d0; - color: #000; } #ibo-main-content .edit-image .view-image, .ui-dialog .edit-image .view-image { display: inline-block; @@ -1697,7 +1655,7 @@ a:visited.ui-button { visibility: hidden; } #ibo-main-content .edit-image .view-image.dirty.compat, .ui-dialog .edit-image .view-image.dirty.compat { - background-image: url("../../../../css/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png?v=1604907799"); + background-image: url("../../../../css/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png?v=1604919410"); } #ibo-main-content .edit-image .view-image.dirty.compat img, .ui-dialog .edit-image .view-image.dirty.compat img { opacity: 0.3; @@ -1720,7 +1678,7 @@ a:visited.ui-button { opacity: 0.3; } #ibo-main-content .edit-image .edit-buttons .button .ui-icon, .ui-dialog .edit-image .edit-buttons .button .ui-icon { - background-image: url("../../../../css/ui-lightness/images/ui-icons_ffffff_256x240.png?v=1604907799"); + background-image: url("../../../../css/ui-lightness/images/ui-icons_ffffff_256x240.png?v=1604919410"); } #ibo-main-content .edit-image .file-input, .ui-dialog .edit-image .file-input { display: block; @@ -1781,13 +1739,6 @@ a:visited.ui-button { #ibo-main-content tr td.hover, .ui-dialog tr td.hover, #ibo-main-content tr.even td.hover, .ui-dialog tr.even td.hover, #ibo-main-content .hover a, .ui-dialog .hover a, #ibo-main-content .hover a:visited, .ui-dialog .hover a:visited, #ibo-main-content .hover a:hover, .ui-dialog .hover a:hover, #ibo-main-content .wizContainer tr.even td.hover, .ui-dialog .wizContainer tr.even td.hover, #ibo-main-content .wizContainer tr td.hover, .ui-dialog .wizContainer tr td.hover { color: #000; } -#ibo-main-content th, .ui-dialog th { - font-family: Tahoma, Verdana, Arial, Helvetica; - font-size: 8pt; - color: #1c94c4; - height: 20px; - background: #F1F1F1 bottom repeat-x; -} #ibo-main-content th.header, .ui-dialog th.header { cursor: pointer; background-repeat: no-repeat; @@ -1940,7 +1891,7 @@ a:visited.ui-button { background: #EA7D1E; } #ibo-main-content .actions_details span, .ui-dialog .actions_details span { - background: url("../../../../images/actions_right.png?v=1604907799") no-repeat right; + background: url("../../../../images/actions_right.png?v=1604919410") no-repeat right; color: #fff; font-weight: bold; padding-top: 2px; @@ -1963,7 +1914,7 @@ a:visited.ui-button { } #ibo-main-content .ac_input, .ui-dialog .ac_input { border: 1px solid #7f9db9; - background: #fff url("../../../../images/ac-background.gif?v=1604907799") no-repeat right; + background: #fff url("../../../../images/ac-background.gif?v=1604919410") no-repeat right; /* By Rom */ } #ibo-main-content .csvimport_createobj, .ui-dialog .csvimport_createobj { @@ -2018,7 +1969,7 @@ a:visited.ui-button { noborder-top: 1px solid #8b8b8b; padding: 4px 0px 0px 16px; font-size: 8pt; - background: url("../../../../images/green-square.gif?v=1604907799") no-repeat bottom left; + background: url("../../../../images/green-square.gif?v=1604919410") no-repeat bottom left; color: #83b217; font-weight: bold; text-decoration: none; @@ -2094,22 +2045,22 @@ a:visited.ui-button { margin-top: -8px; } #ibo-main-content .notreeview li, .ui-dialog .notreeview li { - background: url("../../../../images/tv-item.gif?v=1604907799") 0 0 no-repeat; + background: url("../../../../images/tv-item.gif?v=1604919410") 0 0 no-repeat; } #ibo-main-content .notreeview .collapsable, .ui-dialog .notreeview .collapsable { - background-image: url("../../../../images/tv-collapsable.gif?v=1604907799"); + background-image: url("../../../../images/tv-collapsable.gif?v=1604919410"); } #ibo-main-content .notreeview .expandable, .ui-dialog .notreeview .expandable { - background-image: url("../../../../images/tv-expandable.gif?v=1604907799"); + background-image: url("../../../../images/tv-expandable.gif?v=1604919410"); } #ibo-main-content .notreeview .last, .ui-dialog .notreeview .last { - background-image: url("../../../../images/tv-item-last.gif?v=1604907799"); + background-image: url("../../../../images/tv-item-last.gif?v=1604919410"); } #ibo-main-content .notreeview .lastCollapsable, .ui-dialog .notreeview .lastCollapsable { - background-image: url("../../../../images/tv-collapsable-last.gif?v=1604907799"); + background-image: url("../../../../images/tv-collapsable-last.gif?v=1604919410"); } #ibo-main-content .notreeview .lastExpandable, .ui-dialog .notreeview .lastExpandable { - background-image: url("../../../../images/tv-expandable-last.gif?v=1604907799"); + background-image: url("../../../../images/tv-expandable-last.gif?v=1604919410"); } #ibo-main-content #OrganizationSelection, .ui-dialog #OrganizationSelection { padding: 5px 0px 16px 20px; @@ -2284,7 +2235,7 @@ a:visited.ui-button { color: #000; } #ibo-main-content th.red, .ui-dialog th.red { - background: url("../../../../images/red-header.gif?v=1604907799") bottom left repeat-x; + background: url("../../../../images/red-header.gif?v=1604919410") bottom left repeat-x; color: #000; } #ibo-main-content .green, .ui-dialog .green { @@ -2292,7 +2243,7 @@ a:visited.ui-button { color: #000; } #ibo-main-content th.green, .ui-dialog th.green { - background: url("../../../../images/green-header.gif?v=1604907799") bottom left repeat-x; + background: url("../../../../images/green-header.gif?v=1604919410") bottom left repeat-x; color: #000; } #ibo-main-content .orange, .ui-dialog .orange { @@ -2300,7 +2251,7 @@ a:visited.ui-button { color: #000; } #ibo-main-content th.orange, .ui-dialog th.orange { - background: url("../../../../images/orange-header.gif?v=1604907799") bottom left repeat-x; + background: url("../../../../images/orange-header.gif?v=1604919410") bottom left repeat-x; color: #000; /* For Date Picker: Creates a little calendar icon * instead of a text link for "Choose date" @@ -2315,7 +2266,7 @@ a:visited.ui-button { display: block; text-indent: -2000px; overflow: hidden; - background: url("../../../../images/calendar.png?v=1604907799") no-repeat; + background: url("../../../../images/calendar.png?v=1604919410") no-repeat; } #ibo-main-content td a.dp-choose-date.dp-disabled, .ui-dialog td a.dp-choose-date.dp-disabled, #ibo-main-content a.dp-choose-date.dp-disabled, .ui-dialog a.dp-choose-date.dp-disabled { background-position: 0 -20px; @@ -2367,15 +2318,6 @@ a:visited.ui-button { box-sizing: border-box; } #ibo-main-content .search_form_handler, .ui-dialog .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 #1c94c4; /* Sizing reset */ } #ibo-main-content .search_form_handler *, .ui-dialog .search_form_handler * { @@ -2474,9 +2416,6 @@ a:visited.ui-button { /* padding-bottom must equals to padding-top - .search_form_criteria:margin-bottom */ background-color: #FFFFFF; } -#ibo-main-content .search_form_handler .sf_criterion_area .sf_criterion_row, .ui-dialog .search_form_handler .sf_criterion_area .sf_criterion_row { - position: relative; -} #ibo-main-content .search_form_handler .sf_criterion_area .sf_criterion_row:not(:first-child), .ui-dialog .search_form_handler .sf_criterion_area .sf_criterion_row:not(:first-child) { margin-top: 20px; } @@ -2502,6 +2441,11 @@ a:visited.ui-button { } #ibo-main-content .search_form_handler .sf_criterion_area .sf_criterion_row .sf_criterion_group, .ui-dialog .search_form_handler .sf_criterion_area .sf_criterion_row .sf_criterion_group { display: inline; +} +#ibo-main-content .search_form_handler .sf_criterion_area .sf_criterion_row .sf_criterion_group .sfc_fg_button, .ui-dialog .search_form_handler .sf_criterion_area .sf_criterion_row .sf_criterion_group .sfc_fg_button, #ibo-main-content .search_form_handler .sf_criterion_area .sf_criterion_row .sf_criterion_group .sfc_header, .ui-dialog .search_form_handler .sf_criterion_area .sf_criterion_row .sf_criterion_group .sfc_header { + border: 1px solid #E1E7EC; + /* Must be equal to .search_form_criteria:margin-bottom + this:padding-bottom */ + border-radius: 3px; /* Common style between criterion and more criterion */ } #ibo-main-content .search_form_handler .sf_criterion_area .search_form_criteria, .ui-dialog .search_form_handler .sf_criterion_area .search_form_criteria, #ibo-main-content .search_form_handler .sf_criterion_area .sf_more_criterion, .ui-dialog .search_form_handler .sf_criterion_area .sf_more_criterion, #ibo-main-content .search_form_handler .sf_criterion_area .sf_button, .ui-dialog .search_form_handler .sf_criterion_area .sf_button { @@ -2528,14 +2472,14 @@ a:visited.ui-button { border-radius: 1px; box-shadow: 0 1px 1px rgba(0, 0, 0, 0.15); } -#ibo-main-content .search_form_handler .sf_criterion_area .search_form_criteria .sfc_form_group, .ui-dialog .search_form_handler .sf_criterion_area .search_form_criteria .sfc_form_group, #ibo-main-content .search_form_handler .sf_criterion_area .sf_more_criterion .sfc_form_group, .ui-dialog .search_form_handler .sf_criterion_area .sf_more_criterion .sfc_form_group, #ibo-main-content .search_form_handler .sf_criterion_area .sf_button .sfc_form_group, .ui-dialog .search_form_handler .sf_criterion_area .sf_button .sfc_form_group, #ibo-main-content .search_form_handler .sf_criterion_area .search_form_criteria .sfm_content, .ui-dialog .search_form_handler .sf_criterion_area .search_form_criteria .sfm_content, #ibo-main-content .search_form_handler .sf_criterion_area .sf_more_criterion .sfm_content, .ui-dialog .search_form_handler .sf_criterion_area .sf_more_criterion .sfm_content, #ibo-main-content .search_form_handler .sf_criterion_area .sf_button .sfm_content, .ui-dialog .search_form_handler .sf_criterion_area .sf_button .sfm_content { +#ibo-main-content .search_form_handler .sf_criterion_area .search_form_criteria .sfm_content, .ui-dialog .search_form_handler .sf_criterion_area .search_form_criteria .sfm_content, #ibo-main-content .search_form_handler .sf_criterion_area .sf_more_criterion .sfm_content, .ui-dialog .search_form_handler .sf_criterion_area .sf_more_criterion .sfm_content, #ibo-main-content .search_form_handler .sf_criterion_area .sf_button .sfm_content, .ui-dialog .search_form_handler .sf_criterion_area .sf_button .sfm_content { position: absolute; z-index: -1; min-width: 100%; left: 0px; margin-top: -1px; } -#ibo-main-content .search_form_handler .sf_criterion_area .search_form_criteria .sfc_form_group .sfc_fg_buttons, .ui-dialog .search_form_handler .sf_criterion_area .search_form_criteria .sfc_form_group .sfc_fg_buttons, #ibo-main-content .search_form_handler .sf_criterion_area .sf_more_criterion .sfc_form_group .sfc_fg_buttons, .ui-dialog .search_form_handler .sf_criterion_area .sf_more_criterion .sfc_form_group .sfc_fg_buttons, #ibo-main-content .search_form_handler .sf_criterion_area .sf_button .sfc_form_group .sfc_fg_buttons, .ui-dialog .search_form_handler .sf_criterion_area .sf_button .sfc_form_group .sfc_fg_buttons, #ibo-main-content .search_form_handler .sf_criterion_area .search_form_criteria .sfm_content .sfc_fg_buttons, .ui-dialog .search_form_handler .sf_criterion_area .search_form_criteria .sfm_content .sfc_fg_buttons, #ibo-main-content .search_form_handler .sf_criterion_area .sf_more_criterion .sfm_content .sfc_fg_buttons, .ui-dialog .search_form_handler .sf_criterion_area .sf_more_criterion .sfm_content .sfc_fg_buttons, #ibo-main-content .search_form_handler .sf_criterion_area .sf_button .sfm_content .sfc_fg_buttons, .ui-dialog .search_form_handler .sf_criterion_area .sf_button .sfm_content .sfc_fg_buttons { +#ibo-main-content .search_form_handler .sf_criterion_area .search_form_criteria .sfm_content .sfc_fg_buttons, .ui-dialog .search_form_handler .sf_criterion_area .search_form_criteria .sfm_content .sfc_fg_buttons, #ibo-main-content .search_form_handler .sf_criterion_area .sf_more_criterion .sfm_content .sfc_fg_buttons, .ui-dialog .search_form_handler .sf_criterion_area .sf_more_criterion .sfm_content .sfc_fg_buttons, #ibo-main-content .search_form_handler .sf_criterion_area .sf_button .sfm_content .sfc_fg_buttons, .ui-dialog .search_form_handler .sf_criterion_area .sf_button .sfm_content .sfc_fg_buttons { white-space: nowrap; /* Criteria tags */ } @@ -2982,19 +2926,19 @@ a:visited.ui-button { /* Beware: IE6 does not support multiple selector with multiple classes, only the last class is used */ } #ibo-main-content table.listResults tr.odd td.truncated, .ui-dialog table.listResults tr.odd td.truncated, #ibo-main-content table.listResults tr td.truncated, .ui-dialog table.listResults tr td.truncated, #ibo-main-content .wizContainer table.listResults tr.odd td.truncated, .ui-dialog .wizContainer table.listResults tr.odd td.truncated, #ibo-main-content .wizContainer table.listResults tr td.truncated, .ui-dialog .wizContainer table.listResults tr td.truncated { - background: url("../../../../images/truncated.png?v=1604907799") bottom repeat-x; + background: url("../../../../images/truncated.png?v=1604919410") bottom repeat-x; /* Beware: IE6 does not support multiple selector with multiple classes, only the last class is used */ } #ibo-main-content table.listResults tr.even td.truncated, .ui-dialog table.listResults tr.even td.truncated, #ibo-main-content .wizContainer table.listResults tr.even td.truncated, .ui-dialog .wizContainer table.listResults tr.even td.truncated { - background: #f9f9f1 url("../../../../images/truncated.png?v=1604907799") bottom repeat-x; + background: #f9f9f1 url("../../../../images/truncated.png?v=1604919410") bottom repeat-x; /* Beware: IE6 does not support multiple selector with multiple classes, only the last class is used */ } #ibo-main-content table.listResults tr.even td.hover.truncated, .ui-dialog table.listResults tr.even td.hover.truncated, #ibo-main-content .wizContainer table.listResults tr.even td.hover.truncated, .ui-dialog .wizContainer table.listResults tr.even td.hover.truncated { - background: #fdf5d0 url("../../../../images/truncated.png?v=1604907799") bottom repeat-x; + background: #fdf5d0 url("../../../../images/truncated.png?v=1604919410") bottom repeat-x; /* Beware: IE6 does not support multiple selector with multiple classes, only the last class is used */ } #ibo-main-content table.listResults tr.odd td.hover.truncated, .ui-dialog table.listResults tr.odd td.hover.truncated, #ibo-main-content table.listResults tr td.hover.truncated, .ui-dialog table.listResults tr td.hover.truncated, #ibo-main-content .wizContainer table.listResults tr.odd td.hover.truncated, .ui-dialog .wizContainer table.listResults tr.odd td.hover.truncated, #ibo-main-content .wizContainer table.listResults tr td.hover.truncated, .ui-dialog .wizContainer table.listResults tr td.hover.truncated { - background: #fdf5d0 url("../../../../images/truncated.png?v=1604907799") bottom repeat-x; + background: #fdf5d0 url("../../../../images/truncated.png?v=1604919410") bottom repeat-x; } #ibo-main-content table.listResults.truncated, .ui-dialog table.listResults.truncated { border-bottom: 0; @@ -3096,7 +3040,7 @@ a:visited.ui-button { #ibo-main-content div#logo div, .ui-dialog div#logo div { height: 88px; width: 244px; - background: url("../../../../images/itop-logo-2.png?v=1604907799") left no-repeat; + background: url("../../../../images/itop-logo-2.png?v=1604919410") left no-repeat; } #ibo-main-content #left-pane .ui-layout-north, .ui-dialog #left-pane .ui-layout-north { overflow: hidden; @@ -3245,7 +3189,7 @@ a:visited.ui-button { margin: 0 2px; } #ibo-main-content .ui-layout-button-pin-down, .ui-dialog .ui-layout-button-pin-down { - background: url("../../../../images/splitter-bkg.png?v=1604907799") transparent; + background: url("../../../../images/splitter-bkg.png?v=1604919410") transparent; width: 16px; background-position: -144px -144px; } @@ -3382,13 +3326,13 @@ a:visited.ui-button { #ibo-main-content .caselog_header, .ui-dialog .caselog_header { padding: 3px; border-top: 1px solid #fff; - background: #ddd url("../../../../images/plus.gif?v=1604907799") left no-repeat; + background: #ddd url("../../../../images/plus.gif?v=1604919410") left no-repeat; padding-left: 16px; cursor: pointer; width: 100%; } #ibo-main-content .caselog_header.open, .ui-dialog .caselog_header.open { - background: #ddd url("../../../../images/minus.gif?v=1604907799") left no-repeat; + background: #ddd url("../../../../images/minus.gif?v=1604919410") left no-repeat; } #ibo-main-content .caselog_entry, .ui-dialog .caselog_entry, #ibo-main-content .caselog_entry_html, .ui-dialog .caselog_entry_html { overflow-x: auto; @@ -3564,7 +3508,7 @@ a:visited.ui-button { height: 15px; border: 1px #A6A6A6 solid; cursor: pointer; - background-image: url("../../../../images/full-screen.png?v=1604907799"); + background-image: url("../../../../images/full-screen.png?v=1604919410"); background-repeat: no-repeat; background-position: center center; background-size: 98%; @@ -3611,7 +3555,7 @@ a:visited.ui-button { padding: 2px; } #ibo-main-content .field_container > div > div.field_value .attribute-edit .field_input_zone.field_input_document .button .ui-icon, .ui-dialog .field_container > div > div.field_value .attribute-edit .field_input_zone.field_input_document .button .ui-icon { - background-image: url("../../../../css/ui-lightness/images/ui-icons_ffffff_256x240.png?v=1604907799"); + background-image: url("../../../../css/ui-lightness/images/ui-icons_ffffff_256x240.png?v=1604919410"); background-color: #EA7D1E; } #ibo-main-content .field_container > div > div.field_value .attribute-edit .field_input_zone.field_input_image input, .ui-dialog .field_container > div > div.field_value .attribute-edit .field_input_zone.field_input_image input { @@ -3678,7 +3622,7 @@ a:visited.ui-button { height: 15px; border: 1px #A6A6A6 solid; cursor: pointer; - background-image: url("../../../../images/full-screen.png?v=1604907799"); + background-image: url("../../../../images/full-screen.png?v=1604919410"); background-repeat: no-repeat; background-position: center center; background-size: 98%; @@ -3743,7 +3687,7 @@ a:visited.ui-button { padding-left: 0.4em; } #ibo-main-content .ac_dlg_loading, .ui-dialog .ac_dlg_loading { - background: white url("../../../../images/indicator.gif?v=1604907799") right center no-repeat; + background: white url("../../../../images/indicator.gif?v=1604919410") right center no-repeat; } #ibo-main-content table.pagination, .ui-dialog table.pagination { display: inline-block; @@ -3810,10 +3754,10 @@ a:visited.ui-button { cursor: not-allowed; } #ibo-main-content .dragHover, .ui-dialog .dragHover { - background: url("../../../../css/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png?v=1604907799"); + background: url("../../../../css/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png?v=1604919410"); } #ibo-main-content .edit_mode .dashlet, .ui-dialog .edit_mode .dashlet { - background: url("../../../../css/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png?v=1604907799"); + background: url("../../../../css/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png?v=1604919410"); padding: 5px; margin: 0; position: relative; @@ -3858,7 +3802,7 @@ a:visited.ui-button { top: 0; right: 0; z-index: 10; - background: transparent url("../../../../images/delete.png?v=1604907799") no-repeat center; + background: transparent url("../../../../images/delete.png?v=1604919410") no-repeat center; } #ibo-main-content td.prop_value, .ui-dialog td.prop_value { text-align: left; @@ -4087,23 +4031,23 @@ a:visited.ui-button { } #ibo-main-content .message_info, .ui-dialog .message_info { border: 1px solid #993; - background: url("../../../../images/info-mini.png?v=1604907799") 1em 1em no-repeat #ffc; + background: url("../../../../images/info-mini.png?v=1604919410") 1em 1em no-repeat #ffc; padding-left: 3em; } #ibo-main-content .message_ok, .ui-dialog .message_ok { border: 1px solid #393; - background: url("../../../../images/ok.png?v=1604907799") 1em 1em no-repeat #cfc; + background: url("../../../../images/ok.png?v=1604919410") 1em 1em no-repeat #cfc; padding-left: 3em; } #ibo-main-content .message_warning, .ui-dialog .message_warning { border: 1px solid #ec9800; - background: url("../../../../images/error.png?v=1604907799") 1em 1em no-repeat #ffd78d; + background: url("../../../../images/error.png?v=1604919410") 1em 1em no-repeat #ffd78d; color: #000; padding-left: 3em; } #ibo-main-content .message_error, .ui-dialog .message_error { border: 1px solid #933; - background: url("../../../../images/error.png?v=1604907799") 1em 1em no-repeat #fcc; + background: url("../../../../images/error.png?v=1604919410") 1em 1em no-repeat #fcc; padding-left: 3em; } #ibo-main-content .fg-menu a img, .ui-dialog .fg-menu a img { @@ -4234,18 +4178,18 @@ a:visited.ui-button { } #ibo-main-content #hiddeable_chapters .ui-tabs .ui-tabs-nav li.hideable-chapter span, .ui-dialog #hiddeable_chapters .ui-tabs .ui-tabs-nav li.hideable-chapter span { padding-left: 20px; - background: url("../../../../images/eye-open-555.png?v=1604907799") 2px center no-repeat; + background: url("../../../../images/eye-open-555.png?v=1604919410") 2px center no-repeat; } #ibo-main-content #hiddeable_chapters .ui-tabs .ui-tabs-nav li.hideable-chapter.strikethrough span, .ui-dialog #hiddeable_chapters .ui-tabs .ui-tabs-nav li.hideable-chapter.strikethrough span { text-decoration: line-through; - background: url("../../../../images/eye-closed-555.png?v=1604907799") 2px center no-repeat; + background: url("../../../../images/eye-closed-555.png?v=1604919410") 2px center no-repeat; } #ibo-main-content .printable-version legend, .ui-dialog .printable-version legend { padding-left: 26px; - background: #1c94c4 url("../../../../images/eye-open-fff.png?v=1604907799") 8px center no-repeat; + background: #1c94c4 url("../../../../images/eye-open-fff.png?v=1604919410") 8px center no-repeat; } #ibo-main-content .printable-version .strikethrough legend, .ui-dialog .printable-version .strikethrough legend { - background: #1c94c4 url("../../../../images/eye-closed-fff.png?v=1604907799") 8px center no-repeat; + background: #1c94c4 url("../../../../images/eye-closed-fff.png?v=1604919410") 8px center no-repeat; } #ibo-main-content .printable-version fieldset.strikethrough span, .ui-dialog .printable-version fieldset.strikethrough span { display: none; @@ -4318,7 +4262,7 @@ a:visited.ui-button { cursor: pointer; width: 16px; height: 16px; - background-image: url("../../../../css/ui-lightness/images/ui-icons_222222_256x240.png?v=1604907799"); + background-image: url("../../../../css/ui-lightness/images/ui-icons_222222_256x240.png?v=1604919410"); background-position: -16px -192px; } #ibo-main-content .history_entry_truncated .history_truncated_toggler, .ui-dialog .history_entry_truncated .history_truncated_toggler { @@ -4403,7 +4347,7 @@ a:visited.ui-button { #ibo-main-content #itop-breadcrumb .breadcrumb-item a::after, .ui-dialog #itop-breadcrumb .breadcrumb-item a::after { content: ''; position: absolute; - background-image: url("../../../../images/breadcrumb-separator.png?v=1604907799"); + background-image: url("../../../../images/breadcrumb-separator.png?v=1604919410"); background-repeat: no-repeat; width: 8px; height: 16px; diff --git a/datamodels/2.x/itop-structure/precompiled-themes/test-red/main.css b/datamodels/2.x/itop-structure/precompiled-themes/test-red/main.css index e2107a7d2..cbdd0c6de 100644 --- a/datamodels/2.x/itop-structure/precompiled-themes/test-red/main.css +++ b/datamodels/2.x/itop-structure/precompiled-themes/test-red/main.css @@ -1,6 +1,6 @@ /* === SIGNATURE BEGIN === -{"variables":"8cfe86f2c55d8eff36d57eb4e83d89f1","stylesheets":{"css-variables":"732f501302c538f594fb3c668d85b46c","jqueryui":"a887ad1c00f29132beba3bf729b981c7","main":"4da726efdbc7625538d988e1687f82ff","environment-banner":"3de3ffb8232b9a649e912b570a64bf5d"},"imports":[],"images":{"css\/ui-lightness\/images\/ui-icons_222222_256x240.png":"3a3c5468f484f07ac4a320d9e22acb8c","css\/ui-lightness\/images\/ui-bg_diagonals-thick_20_666666_40x40.png":"4429d568c67d8dfeb9040273ea0fb8c4","css\/ui-lightness\/images\/ui-icons_E87C1E_256x240.png":"7003dd36cb2aa032c8ec871ce4d4e03d","css\/ui-lightness\/images\/ui-icons_1c94c4_256x240.png":"dbd693dc8e0ef04e90a2f7ac7b390086","css\/ui-lightness\/images\/ui-icons_F26522_256x240.png":"16278ec0c07270be571f4c2e97fcc10c","css\/ui-lightness\/images\/ui-bg_diagonals-thick_18_b81900_40x40.png":"e460a66d4b3e093fc651e62a236267cb","css\/ui-lightness\/images\/ui-icons_ffffff_256x240.png":"41612b0f4a034424f8321c9f824a94da","css\/ui-lightness\/images\/ui-icons_ffd27a_256x240.png":"dda1b6f694b0d196aefc66a1d6d758f6","images\/actions_right.png":"31c8906bd25d27b83a0a2466bf903462","images\/ac-background.gif":"76135f3697b41a15aed787cfd77776c7","images\/green-square.gif":"16ea9a497d72f5e66e4e8ea9ae08024e","images\/tv-item.gif":"719fe2d4566108e73162fb8868d3778c","images\/tv-collapsable.gif":"63a3351ea0d580797c9b8c386aa4f48b","images\/tv-expandable.gif":"a2d1af4128e4a798a7f3390b12a28574","images\/tv-item-last.gif":"2ae7e1d9972ce71e5caa65a086bc5b7e","images\/tv-collapsable-last.gif":"71acaa9d7c2616e9e8b7131a75ca65da","images\/tv-expandable-last.gif":"9d51036b3a8102742709da66789fd0f7","images\/red-header.gif":"c73b8765f0c8c3c183cb6a0c2bb0ec69","images\/green-header.gif":"0e22a09bb8051b2a274b3427ede62e82","images\/orange-header.gif":"ce1f93f0af64431771b4cbd6c99c567b","images\/calendar.png":"ab56e59af3c96ca661821257d376465e","images\/truncated.png":"c6f91108afe8159d417b4dc556cd3b2a","images\/plus.gif":"f00e1e6e1161f48608bb2bbc79b9948c","images\/minus.gif":"6d77c0c0c2f86b6995d1cdf78274eaab","images\/full-screen.png":"b541fadd3f1563856a4b44aeebd9d563","images\/indicator.gif":"03ce3dcc84af110e9da8699a841e5200","images\/delete.png":"93c047549c31a270a037840277cf59d3","images\/info-mini.png":"445c090ed777c5e6a08ac390fa896193","images\/ok.png":"f6973773335fd83d8d2875f9a3c925af","images\/error.png":"1af8a1041016f67669c5fd22dc88c82e","images\/eye-open-555.png":"9940f4e5b1248042c238e1924359fd5e","images\/eye-closed-555.png":"6ad3b0bae791bf61addc9d8ca80a642d","images\/eye-open-fff.png":"b7db2402d4d5c72314c25790a66150d4","images\/eye-closed-fff.png":"f9be7454dbb47b0e0bca3aa370ae7db5"}} +{"variables":"8cfe86f2c55d8eff36d57eb4e83d89f1","stylesheets":{"css-variables":"732f501302c538f594fb3c668d85b46c","jqueryui":"a887ad1c00f29132beba3bf729b981c7","main":"0efa2620e936b99f9e2ad32088636b33","environment-banner":"3de3ffb8232b9a649e912b570a64bf5d"},"imports":[],"images":{"css\/ui-lightness\/images\/ui-icons_222222_256x240.png":"3a3c5468f484f07ac4a320d9e22acb8c","css\/ui-lightness\/images\/ui-bg_diagonals-thick_20_666666_40x40.png":"4429d568c67d8dfeb9040273ea0fb8c4","css\/ui-lightness\/images\/ui-icons_E87C1E_256x240.png":"7003dd36cb2aa032c8ec871ce4d4e03d","css\/ui-lightness\/images\/ui-icons_1c94c4_256x240.png":"dbd693dc8e0ef04e90a2f7ac7b390086","css\/ui-lightness\/images\/ui-icons_F26522_256x240.png":"16278ec0c07270be571f4c2e97fcc10c","css\/ui-lightness\/images\/ui-bg_diagonals-thick_18_b81900_40x40.png":"e460a66d4b3e093fc651e62a236267cb","css\/ui-lightness\/images\/ui-icons_ffffff_256x240.png":"41612b0f4a034424f8321c9f824a94da","css\/ui-lightness\/images\/ui-icons_ffd27a_256x240.png":"dda1b6f694b0d196aefc66a1d6d758f6","images\/actions_right.png":"31c8906bd25d27b83a0a2466bf903462","images\/ac-background.gif":"76135f3697b41a15aed787cfd77776c7","images\/green-square.gif":"16ea9a497d72f5e66e4e8ea9ae08024e","images\/tv-item.gif":"719fe2d4566108e73162fb8868d3778c","images\/tv-collapsable.gif":"63a3351ea0d580797c9b8c386aa4f48b","images\/tv-expandable.gif":"a2d1af4128e4a798a7f3390b12a28574","images\/tv-item-last.gif":"2ae7e1d9972ce71e5caa65a086bc5b7e","images\/tv-collapsable-last.gif":"71acaa9d7c2616e9e8b7131a75ca65da","images\/tv-expandable-last.gif":"9d51036b3a8102742709da66789fd0f7","images\/red-header.gif":"c73b8765f0c8c3c183cb6a0c2bb0ec69","images\/green-header.gif":"0e22a09bb8051b2a274b3427ede62e82","images\/orange-header.gif":"ce1f93f0af64431771b4cbd6c99c567b","images\/calendar.png":"ab56e59af3c96ca661821257d376465e","images\/truncated.png":"c6f91108afe8159d417b4dc556cd3b2a","images\/plus.gif":"f00e1e6e1161f48608bb2bbc79b9948c","images\/minus.gif":"6d77c0c0c2f86b6995d1cdf78274eaab","images\/full-screen.png":"b541fadd3f1563856a4b44aeebd9d563","images\/indicator.gif":"03ce3dcc84af110e9da8699a841e5200","images\/delete.png":"93c047549c31a270a037840277cf59d3","images\/info-mini.png":"445c090ed777c5e6a08ac390fa896193","images\/ok.png":"f6973773335fd83d8d2875f9a3c925af","images\/error.png":"1af8a1041016f67669c5fd22dc88c82e","images\/eye-open-555.png":"9940f4e5b1248042c238e1924359fd5e","images\/eye-closed-555.png":"6ad3b0bae791bf61addc9d8ca80a642d","images\/eye-open-fff.png":"b7db2402d4d5c72314c25790a66150d4","images\/eye-closed-fff.png":"f9be7454dbb47b0e0bca3aa370ae7db5"}} === SIGNATURE END === */ /*! @@ -99,7 +99,7 @@ background-repeat: no-repeat; width: 16px; height: 16px; - background-image: url("../../../../css/ui-lightness/images/ui-icons_222222_256x240.png?v=1604907799"); + background-image: url("../../../../css/ui-lightness/images/ui-icons_222222_256x240.png?v=1604919410"); filter: hue-rotate(0deg); } .ui-widget-icon-block { @@ -232,7 +232,7 @@ .ui-menu .ui-menu-item { margin: 0; cursor: pointer; - list-style-image: url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7?v=1604907799"); + list-style-image: url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7?v=1604919410"); } .ui-menu .ui-menu-item-wrapper { position: relative; @@ -298,7 +298,7 @@ color: #EA7D1E; } .ui-button:hover .ui-icon { - background-image: url("../../../../css/ui-lightness/images/ui-icons_E87C1E_256x240.png?v=1604907799"); + background-image: url("../../../../css/ui-lightness/images/ui-icons_E87C1E_256x240.png?v=1604919410"); } .ui-button:active { text-decoration: none; @@ -306,20 +306,20 @@ color: #EA7D1E; } .ui-button:active .ui-icon { - background-image: url("../../../../css/ui-lightness/images/ui-icons_E87C1E_256x240.png?v=1604907799"); + background-image: url("../../../../css/ui-lightness/images/ui-icons_E87C1E_256x240.png?v=1604919410"); } .ui-button:focus { font-weight: bold; color: #EA7D1E; } .ui-button:focus .ui-icon { - background-image: url("../../../../css/ui-lightness/images/ui-icons_E87C1E_256x240.png?v=1604907799"); + background-image: url("../../../../css/ui-lightness/images/ui-icons_E87C1E_256x240.png?v=1604919410"); } .ui-button .ui-state-highlight.ui-icon { - background-image: url("../../../../css/ui-lightness/images/ui-icons_1c94c4_256x240.png?v=1604907799"); + background-image: url("../../../../css/ui-lightness/images/ui-icons_1c94c4_256x240.png?v=1604919410"); } .ui-button .ui-icon { - background-image: url("../../../../css/ui-lightness/images/ui-icons_F26522_256x240.png?v=1604907799"); + background-image: url("../../../../css/ui-lightness/images/ui-icons_F26522_256x240.png?v=1604919410"); } .ui-button-icon-only { width: 2em; @@ -901,7 +901,7 @@ body .ui-tooltip { background-image: none; } .ui-widget-content .ui-icon { - background-image: url("../../../../css/ui-lightness/images/ui-icons_222222_256x240.png?v=1604907799"); + background-image: url("../../../../css/ui-lightness/images/ui-icons_222222_256x240.png?v=1604919410"); } .ui-widget-header .ui-priority-secondary { opacity: 0.7; @@ -913,7 +913,7 @@ body .ui-tooltip { background-image: none; } .ui-widget-header .ui-icon { - background-image: url("../../../../css/ui-lightness/images/ui-icons_ffffff_256x240.png?v=1604907799"); + background-image: url("../../../../css/ui-lightness/images/ui-icons_ffffff_256x240.png?v=1604919410"); } .ui-state-default a { text-decoration: none; @@ -925,7 +925,7 @@ body .ui-tooltip { text-decoration: none; } .ui-state-default .ui-icon { - background-image: url("../../../../css/ui-lightness/images/ui-icons_F26522_256x240.png?v=1604907799"); + background-image: url("../../../../css/ui-lightness/images/ui-icons_F26522_256x240.png?v=1604919410"); } a.ui-button { text-decoration: none; @@ -955,7 +955,7 @@ a:visited.ui-button { text-decoration: none; } .ui-state-hover .ui-icon { - background-image: url("../../../../css/ui-lightness/images/ui-icons_E87C1E_256x240.png?v=1604907799"); + background-image: url("../../../../css/ui-lightness/images/ui-icons_E87C1E_256x240.png?v=1604919410"); } .ui-state-focus a { text-decoration: none; @@ -970,7 +970,7 @@ a:visited.ui-button { text-decoration: none; } .ui-state-focus .ui-icon { - background-image: url("../../../../css/ui-lightness/images/ui-icons_E87C1E_256x240.png?v=1604907799"); + background-image: url("../../../../css/ui-lightness/images/ui-icons_E87C1E_256x240.png?v=1604919410"); } .ui-visual-focus { box-shadow: 0 0 3px 1px #5e9ed6; @@ -988,19 +988,19 @@ a:visited.ui-button { text-decoration: none; } .ui-state-active .ui-icon { - background-image: url("../../../../css/ui-lightness/images/ui-icons_E87C1E_256x240.png?v=1604907799"); + background-image: url("../../../../css/ui-lightness/images/ui-icons_E87C1E_256x240.png?v=1604919410"); } .ui-icon-background { background-color: #EA7D1E; } .ui-state-highlight .ui-icon { - background-image: url("../../../../css/ui-lightness/images/ui-icons_1c94c4_256x240.png?v=1604907799"); + background-image: url("../../../../css/ui-lightness/images/ui-icons_1c94c4_256x240.png?v=1604919410"); } .ui-state-error .ui-icon { - background-image: url("../../../../css/ui-lightness/images/ui-icons_ffd27a_256x240.png?v=1604907799"); + background-image: url("../../../../css/ui-lightness/images/ui-icons_ffd27a_256x240.png?v=1604919410"); } .ui-state-error-text .ui-icon { - background-image: url("../../../../css/ui-lightness/images/ui-icons_ffd27a_256x240.png?v=1604907799"); + background-image: url("../../../../css/ui-lightness/images/ui-icons_ffd27a_256x240.png?v=1604919410"); } .ui-priority-primary { font-weight: bold; @@ -1643,52 +1643,10 @@ a:visited.ui-button { color: #EA7D1E; text-decoration: none; } -#ibo-main-content table.datatable, .ui-dialog table.datatable { - width: 100%; - border: 0; - padding: 0; -} #ibo-main-content td.menucontainer, .ui-dialog td.menucontainer { text-align: right; -} -#ibo-main-content table.listResults, .ui-dialog table.listResults { - padding: 0px; - border-top: 3px solid #F1F1F1; - border-left: 3px solid #F1F1F1; - border-bottom: 3px solid #e6e6e1; - border-right: 3px solid #e6e6e1; - width: 100%; - background-color: #FFFFFF; -} -#ibo-main-content table.listResults td, .ui-dialog table.listResults td { - padding: 2px; -} -#ibo-main-content table.listResults td .view-image, .ui-dialog table.listResults td .view-image { - width: inherit !important; - height: inherit !important; -} -#ibo-main-content table.listResults td .view-image img, .ui-dialog table.listResults td .view-image img { - max-width: 48px !important; - max-height: 48px !important; - display: block; - margin-left: auto; - margin-right: auto; -} -#ibo-main-content table.listResults > tbody > tr > *, .ui-dialog table.listResults > tbody > tr > * { - transition: background-color 400ms linear; -} -#ibo-main-content table.listResults > tbody > tr:hover > *, .ui-dialog table.listResults > tbody > tr:hover > * { - cursor: pointer; -} -#ibo-main-content table.listResults > tbody > tr.selected:hover > *, .ui-dialog table.listResults > tbody > tr.selected:hover > * { /* hover on lines is currently done toggling td.hover, and having a rule for links */ - background-color: #f1a564; - color: #000; -} -#ibo-main-content table.listResults > tbody > tr:hover > *, .ui-dialog table.listResults > tbody > tr:hover > * { /* hover on lines is currently done toggling td.hover, and having a rule for links */ - background-color: #fdf5d0; - color: #000; } #ibo-main-content .edit-image .view-image, .ui-dialog .edit-image .view-image { display: inline-block; @@ -1697,7 +1655,7 @@ a:visited.ui-button { visibility: hidden; } #ibo-main-content .edit-image .view-image.dirty.compat, .ui-dialog .edit-image .view-image.dirty.compat { - background-image: url("../../../../css/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png?v=1604907799"); + background-image: url("../../../../css/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png?v=1604919410"); } #ibo-main-content .edit-image .view-image.dirty.compat img, .ui-dialog .edit-image .view-image.dirty.compat img { opacity: 0.3; @@ -1720,7 +1678,7 @@ a:visited.ui-button { opacity: 0.3; } #ibo-main-content .edit-image .edit-buttons .button .ui-icon, .ui-dialog .edit-image .edit-buttons .button .ui-icon { - background-image: url("../../../../css/ui-lightness/images/ui-icons_ffffff_256x240.png?v=1604907799"); + background-image: url("../../../../css/ui-lightness/images/ui-icons_ffffff_256x240.png?v=1604919410"); } #ibo-main-content .edit-image .file-input, .ui-dialog .edit-image .file-input { display: block; @@ -1781,13 +1739,6 @@ a:visited.ui-button { #ibo-main-content tr td.hover, .ui-dialog tr td.hover, #ibo-main-content tr.even td.hover, .ui-dialog tr.even td.hover, #ibo-main-content .hover a, .ui-dialog .hover a, #ibo-main-content .hover a:visited, .ui-dialog .hover a:visited, #ibo-main-content .hover a:hover, .ui-dialog .hover a:hover, #ibo-main-content .wizContainer tr.even td.hover, .ui-dialog .wizContainer tr.even td.hover, #ibo-main-content .wizContainer tr td.hover, .ui-dialog .wizContainer tr td.hover { color: #000; } -#ibo-main-content th, .ui-dialog th { - font-family: Tahoma, Verdana, Arial, Helvetica; - font-size: 8pt; - color: #1c94c4; - height: 20px; - background: #F1F1F1 bottom repeat-x; -} #ibo-main-content th.header, .ui-dialog th.header { cursor: pointer; background-repeat: no-repeat; @@ -1940,7 +1891,7 @@ a:visited.ui-button { background: #EA7D1E; } #ibo-main-content .actions_details span, .ui-dialog .actions_details span { - background: url("../../../../images/actions_right.png?v=1604907799") no-repeat right; + background: url("../../../../images/actions_right.png?v=1604919410") no-repeat right; color: #fff; font-weight: bold; padding-top: 2px; @@ -1963,7 +1914,7 @@ a:visited.ui-button { } #ibo-main-content .ac_input, .ui-dialog .ac_input { border: 1px solid #7f9db9; - background: #fff url("../../../../images/ac-background.gif?v=1604907799") no-repeat right; + background: #fff url("../../../../images/ac-background.gif?v=1604919410") no-repeat right; /* By Rom */ } #ibo-main-content .csvimport_createobj, .ui-dialog .csvimport_createobj { @@ -2018,7 +1969,7 @@ a:visited.ui-button { noborder-top: 1px solid #8b8b8b; padding: 4px 0px 0px 16px; font-size: 8pt; - background: url("../../../../images/green-square.gif?v=1604907799") no-repeat bottom left; + background: url("../../../../images/green-square.gif?v=1604919410") no-repeat bottom left; color: #83b217; font-weight: bold; text-decoration: none; @@ -2094,22 +2045,22 @@ a:visited.ui-button { margin-top: -8px; } #ibo-main-content .notreeview li, .ui-dialog .notreeview li { - background: url("../../../../images/tv-item.gif?v=1604907799") 0 0 no-repeat; + background: url("../../../../images/tv-item.gif?v=1604919410") 0 0 no-repeat; } #ibo-main-content .notreeview .collapsable, .ui-dialog .notreeview .collapsable { - background-image: url("../../../../images/tv-collapsable.gif?v=1604907799"); + background-image: url("../../../../images/tv-collapsable.gif?v=1604919410"); } #ibo-main-content .notreeview .expandable, .ui-dialog .notreeview .expandable { - background-image: url("../../../../images/tv-expandable.gif?v=1604907799"); + background-image: url("../../../../images/tv-expandable.gif?v=1604919410"); } #ibo-main-content .notreeview .last, .ui-dialog .notreeview .last { - background-image: url("../../../../images/tv-item-last.gif?v=1604907799"); + background-image: url("../../../../images/tv-item-last.gif?v=1604919410"); } #ibo-main-content .notreeview .lastCollapsable, .ui-dialog .notreeview .lastCollapsable { - background-image: url("../../../../images/tv-collapsable-last.gif?v=1604907799"); + background-image: url("../../../../images/tv-collapsable-last.gif?v=1604919410"); } #ibo-main-content .notreeview .lastExpandable, .ui-dialog .notreeview .lastExpandable { - background-image: url("../../../../images/tv-expandable-last.gif?v=1604907799"); + background-image: url("../../../../images/tv-expandable-last.gif?v=1604919410"); } #ibo-main-content #OrganizationSelection, .ui-dialog #OrganizationSelection { padding: 5px 0px 16px 20px; @@ -2284,7 +2235,7 @@ a:visited.ui-button { color: #000; } #ibo-main-content th.red, .ui-dialog th.red { - background: url("../../../../images/red-header.gif?v=1604907799") bottom left repeat-x; + background: url("../../../../images/red-header.gif?v=1604919410") bottom left repeat-x; color: #000; } #ibo-main-content .green, .ui-dialog .green { @@ -2292,7 +2243,7 @@ a:visited.ui-button { color: #000; } #ibo-main-content th.green, .ui-dialog th.green { - background: url("../../../../images/green-header.gif?v=1604907799") bottom left repeat-x; + background: url("../../../../images/green-header.gif?v=1604919410") bottom left repeat-x; color: #000; } #ibo-main-content .orange, .ui-dialog .orange { @@ -2300,7 +2251,7 @@ a:visited.ui-button { color: #000; } #ibo-main-content th.orange, .ui-dialog th.orange { - background: url("../../../../images/orange-header.gif?v=1604907799") bottom left repeat-x; + background: url("../../../../images/orange-header.gif?v=1604919410") bottom left repeat-x; color: #000; /* For Date Picker: Creates a little calendar icon * instead of a text link for "Choose date" @@ -2315,7 +2266,7 @@ a:visited.ui-button { display: block; text-indent: -2000px; overflow: hidden; - background: url("../../../../images/calendar.png?v=1604907799") no-repeat; + background: url("../../../../images/calendar.png?v=1604919410") no-repeat; } #ibo-main-content td a.dp-choose-date.dp-disabled, .ui-dialog td a.dp-choose-date.dp-disabled, #ibo-main-content a.dp-choose-date.dp-disabled, .ui-dialog a.dp-choose-date.dp-disabled { background-position: 0 -20px; @@ -2367,15 +2318,6 @@ a:visited.ui-button { box-sizing: border-box; } #ibo-main-content .search_form_handler, .ui-dialog .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 #1c94c4; /* Sizing reset */ } #ibo-main-content .search_form_handler *, .ui-dialog .search_form_handler * { @@ -2474,9 +2416,6 @@ a:visited.ui-button { /* padding-bottom must equals to padding-top - .search_form_criteria:margin-bottom */ background-color: #FFFFFF; } -#ibo-main-content .search_form_handler .sf_criterion_area .sf_criterion_row, .ui-dialog .search_form_handler .sf_criterion_area .sf_criterion_row { - position: relative; -} #ibo-main-content .search_form_handler .sf_criterion_area .sf_criterion_row:not(:first-child), .ui-dialog .search_form_handler .sf_criterion_area .sf_criterion_row:not(:first-child) { margin-top: 20px; } @@ -2502,6 +2441,11 @@ a:visited.ui-button { } #ibo-main-content .search_form_handler .sf_criterion_area .sf_criterion_row .sf_criterion_group, .ui-dialog .search_form_handler .sf_criterion_area .sf_criterion_row .sf_criterion_group { display: inline; +} +#ibo-main-content .search_form_handler .sf_criterion_area .sf_criterion_row .sf_criterion_group .sfc_fg_button, .ui-dialog .search_form_handler .sf_criterion_area .sf_criterion_row .sf_criterion_group .sfc_fg_button, #ibo-main-content .search_form_handler .sf_criterion_area .sf_criterion_row .sf_criterion_group .sfc_header, .ui-dialog .search_form_handler .sf_criterion_area .sf_criterion_row .sf_criterion_group .sfc_header { + border: 1px solid #E1E7EC; + /* Must be equal to .search_form_criteria:margin-bottom + this:padding-bottom */ + border-radius: 3px; /* Common style between criterion and more criterion */ } #ibo-main-content .search_form_handler .sf_criterion_area .search_form_criteria, .ui-dialog .search_form_handler .sf_criterion_area .search_form_criteria, #ibo-main-content .search_form_handler .sf_criterion_area .sf_more_criterion, .ui-dialog .search_form_handler .sf_criterion_area .sf_more_criterion, #ibo-main-content .search_form_handler .sf_criterion_area .sf_button, .ui-dialog .search_form_handler .sf_criterion_area .sf_button { @@ -2528,14 +2472,14 @@ a:visited.ui-button { border-radius: 1px; box-shadow: 0 1px 1px rgba(0, 0, 0, 0.15); } -#ibo-main-content .search_form_handler .sf_criterion_area .search_form_criteria .sfc_form_group, .ui-dialog .search_form_handler .sf_criterion_area .search_form_criteria .sfc_form_group, #ibo-main-content .search_form_handler .sf_criterion_area .sf_more_criterion .sfc_form_group, .ui-dialog .search_form_handler .sf_criterion_area .sf_more_criterion .sfc_form_group, #ibo-main-content .search_form_handler .sf_criterion_area .sf_button .sfc_form_group, .ui-dialog .search_form_handler .sf_criterion_area .sf_button .sfc_form_group, #ibo-main-content .search_form_handler .sf_criterion_area .search_form_criteria .sfm_content, .ui-dialog .search_form_handler .sf_criterion_area .search_form_criteria .sfm_content, #ibo-main-content .search_form_handler .sf_criterion_area .sf_more_criterion .sfm_content, .ui-dialog .search_form_handler .sf_criterion_area .sf_more_criterion .sfm_content, #ibo-main-content .search_form_handler .sf_criterion_area .sf_button .sfm_content, .ui-dialog .search_form_handler .sf_criterion_area .sf_button .sfm_content { +#ibo-main-content .search_form_handler .sf_criterion_area .search_form_criteria .sfm_content, .ui-dialog .search_form_handler .sf_criterion_area .search_form_criteria .sfm_content, #ibo-main-content .search_form_handler .sf_criterion_area .sf_more_criterion .sfm_content, .ui-dialog .search_form_handler .sf_criterion_area .sf_more_criterion .sfm_content, #ibo-main-content .search_form_handler .sf_criterion_area .sf_button .sfm_content, .ui-dialog .search_form_handler .sf_criterion_area .sf_button .sfm_content { position: absolute; z-index: -1; min-width: 100%; left: 0px; margin-top: -1px; } -#ibo-main-content .search_form_handler .sf_criterion_area .search_form_criteria .sfc_form_group .sfc_fg_buttons, .ui-dialog .search_form_handler .sf_criterion_area .search_form_criteria .sfc_form_group .sfc_fg_buttons, #ibo-main-content .search_form_handler .sf_criterion_area .sf_more_criterion .sfc_form_group .sfc_fg_buttons, .ui-dialog .search_form_handler .sf_criterion_area .sf_more_criterion .sfc_form_group .sfc_fg_buttons, #ibo-main-content .search_form_handler .sf_criterion_area .sf_button .sfc_form_group .sfc_fg_buttons, .ui-dialog .search_form_handler .sf_criterion_area .sf_button .sfc_form_group .sfc_fg_buttons, #ibo-main-content .search_form_handler .sf_criterion_area .search_form_criteria .sfm_content .sfc_fg_buttons, .ui-dialog .search_form_handler .sf_criterion_area .search_form_criteria .sfm_content .sfc_fg_buttons, #ibo-main-content .search_form_handler .sf_criterion_area .sf_more_criterion .sfm_content .sfc_fg_buttons, .ui-dialog .search_form_handler .sf_criterion_area .sf_more_criterion .sfm_content .sfc_fg_buttons, #ibo-main-content .search_form_handler .sf_criterion_area .sf_button .sfm_content .sfc_fg_buttons, .ui-dialog .search_form_handler .sf_criterion_area .sf_button .sfm_content .sfc_fg_buttons { +#ibo-main-content .search_form_handler .sf_criterion_area .search_form_criteria .sfm_content .sfc_fg_buttons, .ui-dialog .search_form_handler .sf_criterion_area .search_form_criteria .sfm_content .sfc_fg_buttons, #ibo-main-content .search_form_handler .sf_criterion_area .sf_more_criterion .sfm_content .sfc_fg_buttons, .ui-dialog .search_form_handler .sf_criterion_area .sf_more_criterion .sfm_content .sfc_fg_buttons, #ibo-main-content .search_form_handler .sf_criterion_area .sf_button .sfm_content .sfc_fg_buttons, .ui-dialog .search_form_handler .sf_criterion_area .sf_button .sfm_content .sfc_fg_buttons { white-space: nowrap; /* Criteria tags */ } @@ -2982,19 +2926,19 @@ a:visited.ui-button { /* Beware: IE6 does not support multiple selector with multiple classes, only the last class is used */ } #ibo-main-content table.listResults tr.odd td.truncated, .ui-dialog table.listResults tr.odd td.truncated, #ibo-main-content table.listResults tr td.truncated, .ui-dialog table.listResults tr td.truncated, #ibo-main-content .wizContainer table.listResults tr.odd td.truncated, .ui-dialog .wizContainer table.listResults tr.odd td.truncated, #ibo-main-content .wizContainer table.listResults tr td.truncated, .ui-dialog .wizContainer table.listResults tr td.truncated { - background: url("../../../../images/truncated.png?v=1604907799") bottom repeat-x; + background: url("../../../../images/truncated.png?v=1604919410") bottom repeat-x; /* Beware: IE6 does not support multiple selector with multiple classes, only the last class is used */ } #ibo-main-content table.listResults tr.even td.truncated, .ui-dialog table.listResults tr.even td.truncated, #ibo-main-content .wizContainer table.listResults tr.even td.truncated, .ui-dialog .wizContainer table.listResults tr.even td.truncated { - background: #f9f9f1 url("../../../../images/truncated.png?v=1604907799") bottom repeat-x; + background: #f9f9f1 url("../../../../images/truncated.png?v=1604919410") bottom repeat-x; /* Beware: IE6 does not support multiple selector with multiple classes, only the last class is used */ } #ibo-main-content table.listResults tr.even td.hover.truncated, .ui-dialog table.listResults tr.even td.hover.truncated, #ibo-main-content .wizContainer table.listResults tr.even td.hover.truncated, .ui-dialog .wizContainer table.listResults tr.even td.hover.truncated { - background: #fdf5d0 url("../../../../images/truncated.png?v=1604907799") bottom repeat-x; + background: #fdf5d0 url("../../../../images/truncated.png?v=1604919410") bottom repeat-x; /* Beware: IE6 does not support multiple selector with multiple classes, only the last class is used */ } #ibo-main-content table.listResults tr.odd td.hover.truncated, .ui-dialog table.listResults tr.odd td.hover.truncated, #ibo-main-content table.listResults tr td.hover.truncated, .ui-dialog table.listResults tr td.hover.truncated, #ibo-main-content .wizContainer table.listResults tr.odd td.hover.truncated, .ui-dialog .wizContainer table.listResults tr.odd td.hover.truncated, #ibo-main-content .wizContainer table.listResults tr td.hover.truncated, .ui-dialog .wizContainer table.listResults tr td.hover.truncated { - background: #fdf5d0 url("../../../../images/truncated.png?v=1604907799") bottom repeat-x; + background: #fdf5d0 url("../../../../images/truncated.png?v=1604919410") bottom repeat-x; } #ibo-main-content table.listResults.truncated, .ui-dialog table.listResults.truncated { border-bottom: 0; @@ -3096,7 +3040,7 @@ a:visited.ui-button { #ibo-main-content div#logo div, .ui-dialog div#logo div { height: 88px; width: 244px; - background: url("../../../../images/itop-logo-2.png?v=1604907799") left no-repeat; + background: url("../../../../images/itop-logo-2.png?v=1604919410") left no-repeat; } #ibo-main-content #left-pane .ui-layout-north, .ui-dialog #left-pane .ui-layout-north { overflow: hidden; @@ -3245,7 +3189,7 @@ a:visited.ui-button { margin: 0 2px; } #ibo-main-content .ui-layout-button-pin-down, .ui-dialog .ui-layout-button-pin-down { - background: url("../../../../images/splitter-bkg.png?v=1604907799") transparent; + background: url("../../../../images/splitter-bkg.png?v=1604919410") transparent; width: 16px; background-position: -144px -144px; } @@ -3382,13 +3326,13 @@ a:visited.ui-button { #ibo-main-content .caselog_header, .ui-dialog .caselog_header { padding: 3px; border-top: 1px solid #fff; - background: #ddd url("../../../../images/plus.gif?v=1604907799") left no-repeat; + background: #ddd url("../../../../images/plus.gif?v=1604919410") left no-repeat; padding-left: 16px; cursor: pointer; width: 100%; } #ibo-main-content .caselog_header.open, .ui-dialog .caselog_header.open { - background: #ddd url("../../../../images/minus.gif?v=1604907799") left no-repeat; + background: #ddd url("../../../../images/minus.gif?v=1604919410") left no-repeat; } #ibo-main-content .caselog_entry, .ui-dialog .caselog_entry, #ibo-main-content .caselog_entry_html, .ui-dialog .caselog_entry_html { overflow-x: auto; @@ -3564,7 +3508,7 @@ a:visited.ui-button { height: 15px; border: 1px #A6A6A6 solid; cursor: pointer; - background-image: url("../../../../images/full-screen.png?v=1604907799"); + background-image: url("../../../../images/full-screen.png?v=1604919410"); background-repeat: no-repeat; background-position: center center; background-size: 98%; @@ -3611,7 +3555,7 @@ a:visited.ui-button { padding: 2px; } #ibo-main-content .field_container > div > div.field_value .attribute-edit .field_input_zone.field_input_document .button .ui-icon, .ui-dialog .field_container > div > div.field_value .attribute-edit .field_input_zone.field_input_document .button .ui-icon { - background-image: url("../../../../css/ui-lightness/images/ui-icons_ffffff_256x240.png?v=1604907799"); + background-image: url("../../../../css/ui-lightness/images/ui-icons_ffffff_256x240.png?v=1604919410"); background-color: #EA7D1E; } #ibo-main-content .field_container > div > div.field_value .attribute-edit .field_input_zone.field_input_image input, .ui-dialog .field_container > div > div.field_value .attribute-edit .field_input_zone.field_input_image input { @@ -3678,7 +3622,7 @@ a:visited.ui-button { height: 15px; border: 1px #A6A6A6 solid; cursor: pointer; - background-image: url("../../../../images/full-screen.png?v=1604907799"); + background-image: url("../../../../images/full-screen.png?v=1604919410"); background-repeat: no-repeat; background-position: center center; background-size: 98%; @@ -3743,7 +3687,7 @@ a:visited.ui-button { padding-left: 0.4em; } #ibo-main-content .ac_dlg_loading, .ui-dialog .ac_dlg_loading { - background: white url("../../../../images/indicator.gif?v=1604907799") right center no-repeat; + background: white url("../../../../images/indicator.gif?v=1604919410") right center no-repeat; } #ibo-main-content table.pagination, .ui-dialog table.pagination { display: inline-block; @@ -3810,10 +3754,10 @@ a:visited.ui-button { cursor: not-allowed; } #ibo-main-content .dragHover, .ui-dialog .dragHover { - background: url("../../../../css/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png?v=1604907799"); + background: url("../../../../css/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png?v=1604919410"); } #ibo-main-content .edit_mode .dashlet, .ui-dialog .edit_mode .dashlet { - background: url("../../../../css/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png?v=1604907799"); + background: url("../../../../css/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png?v=1604919410"); padding: 5px; margin: 0; position: relative; @@ -3858,7 +3802,7 @@ a:visited.ui-button { top: 0; right: 0; z-index: 10; - background: transparent url("../../../../images/delete.png?v=1604907799") no-repeat center; + background: transparent url("../../../../images/delete.png?v=1604919410") no-repeat center; } #ibo-main-content td.prop_value, .ui-dialog td.prop_value { text-align: left; @@ -4087,23 +4031,23 @@ a:visited.ui-button { } #ibo-main-content .message_info, .ui-dialog .message_info { border: 1px solid #993; - background: url("../../../../images/info-mini.png?v=1604907799") 1em 1em no-repeat #ffc; + background: url("../../../../images/info-mini.png?v=1604919410") 1em 1em no-repeat #ffc; padding-left: 3em; } #ibo-main-content .message_ok, .ui-dialog .message_ok { border: 1px solid #393; - background: url("../../../../images/ok.png?v=1604907799") 1em 1em no-repeat #cfc; + background: url("../../../../images/ok.png?v=1604919410") 1em 1em no-repeat #cfc; padding-left: 3em; } #ibo-main-content .message_warning, .ui-dialog .message_warning { border: 1px solid #ec9800; - background: url("../../../../images/error.png?v=1604907799") 1em 1em no-repeat #ffd78d; + background: url("../../../../images/error.png?v=1604919410") 1em 1em no-repeat #ffd78d; color: #000; padding-left: 3em; } #ibo-main-content .message_error, .ui-dialog .message_error { border: 1px solid #933; - background: url("../../../../images/error.png?v=1604907799") 1em 1em no-repeat #fcc; + background: url("../../../../images/error.png?v=1604919410") 1em 1em no-repeat #fcc; padding-left: 3em; } #ibo-main-content .fg-menu a img, .ui-dialog .fg-menu a img { @@ -4234,18 +4178,18 @@ a:visited.ui-button { } #ibo-main-content #hiddeable_chapters .ui-tabs .ui-tabs-nav li.hideable-chapter span, .ui-dialog #hiddeable_chapters .ui-tabs .ui-tabs-nav li.hideable-chapter span { padding-left: 20px; - background: url("../../../../images/eye-open-555.png?v=1604907799") 2px center no-repeat; + background: url("../../../../images/eye-open-555.png?v=1604919410") 2px center no-repeat; } #ibo-main-content #hiddeable_chapters .ui-tabs .ui-tabs-nav li.hideable-chapter.strikethrough span, .ui-dialog #hiddeable_chapters .ui-tabs .ui-tabs-nav li.hideable-chapter.strikethrough span { text-decoration: line-through; - background: url("../../../../images/eye-closed-555.png?v=1604907799") 2px center no-repeat; + background: url("../../../../images/eye-closed-555.png?v=1604919410") 2px center no-repeat; } #ibo-main-content .printable-version legend, .ui-dialog .printable-version legend { padding-left: 26px; - background: #1c94c4 url("../../../../images/eye-open-fff.png?v=1604907799") 8px center no-repeat; + background: #1c94c4 url("../../../../images/eye-open-fff.png?v=1604919410") 8px center no-repeat; } #ibo-main-content .printable-version .strikethrough legend, .ui-dialog .printable-version .strikethrough legend { - background: #1c94c4 url("../../../../images/eye-closed-fff.png?v=1604907799") 8px center no-repeat; + background: #1c94c4 url("../../../../images/eye-closed-fff.png?v=1604919410") 8px center no-repeat; } #ibo-main-content .printable-version fieldset.strikethrough span, .ui-dialog .printable-version fieldset.strikethrough span { display: none; @@ -4318,7 +4262,7 @@ a:visited.ui-button { cursor: pointer; width: 16px; height: 16px; - background-image: url("../../../../css/ui-lightness/images/ui-icons_222222_256x240.png?v=1604907799"); + background-image: url("../../../../css/ui-lightness/images/ui-icons_222222_256x240.png?v=1604919410"); background-position: -16px -192px; } #ibo-main-content .history_entry_truncated .history_truncated_toggler, .ui-dialog .history_entry_truncated .history_truncated_toggler { @@ -4403,7 +4347,7 @@ a:visited.ui-button { #ibo-main-content #itop-breadcrumb .breadcrumb-item a::after, .ui-dialog #itop-breadcrumb .breadcrumb-item a::after { content: ''; position: absolute; - background-image: url("../../../../images/breadcrumb-separator.png?v=1604907799"); + background-image: url("../../../../images/breadcrumb-separator.png?v=1604919410"); background-repeat: no-repeat; width: 8px; height: 16px; diff --git a/test/core/DBSearchTest.php b/test/core/DBSearchTest.php index 9127fe89f..52661517d 100644 --- a/test/core/DBSearchTest.php +++ b/test/core/DBSearchTest.php @@ -679,20 +679,21 @@ class DBSearchTest extends ItopDataTestCase $oSet = new \CMDBObjectSet($oSearch, array(), array('org_ids' => $TwoOrgIdsOnly)); static::assertEquals(4, $oSet->Count()); - $_SERVER['REQUEST_URI'] = 'FAKE_REQUEST_URI'; - $_SERVER['REQUEST_METHOD'] = 'FAKE_REQUEST_METHOD'; - $oP = new \iTopWebPage("test"); - $oBlock = new \DisplayBlock($oSet->GetFilter(), 'list', false); - $oHtml = $oBlock->GetDisplay($oP, 'package_table', array('menu' => true, 'display_limit' => false)); - $sHtml = BlockRenderer::RenderBlockTemplates($oHtml); - - $iHtmlUserRequestLineCount = substr_count($sHtml, 'GetFilter(), 'list', false); + // $oHtml = $oBlock->GetDisplay($oP, 'package_table', array('menu' => true, 'display_limit' => false)); + // $sHtml = BlockRenderer::RenderBlockTemplates($oHtml); + // + // $iHtmlUserRequestLineCount = substr_count($sHtml, ' Date: Mon, 9 Nov 2020 15:15:12 +0100 Subject: [PATCH 05/16] :white_check_mark: Fix ThemeHandlerTest Regression introduced by f718b26b : the test expected SCSS file was modified in sync with modifications done in iTop SCSS files. No need to do that as this file is only used in this test. --- test/application/theme-handler/expected/css/light-grey.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/test/application/theme-handler/expected/css/light-grey.scss b/test/application/theme-handler/expected/css/light-grey.scss index fe6bacc77..864323835 100644 --- a/test/application/theme-handler/expected/css/light-grey.scss +++ b/test/application/theme-handler/expected/css/light-grey.scss @@ -1093,6 +1093,7 @@ input.dp-applied { border-radius: $search-criteria-box-radius; box-shadow: $box-shadow-regular; } + .sfc_form_group, .sfm_content{ position: absolute; z-index: -1; From 23452804aa8d0bcd737cfc94358aa22ec096c7ca Mon Sep 17 00:00:00 2001 From: Eric Date: Tue, 10 Nov 2020 17:30:53 +0100 Subject: [PATCH 06/16] =?UTF-8?q?N=C2=B02847=20-=20Datatables=20for=20stat?= =?UTF-8?q?ic=20data?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- application/displayblock.class.inc.php | 148 ++++++++++-------- css/backoffice/components/_datatable.scss | 2 +- .../en.dictionary.itop.datatable.php | 4 +- lib/composer/autoload_classmap.php | 1 + lib/composer/autoload_static.php | 1 + .../Component/DataTable/DataTableFactory.php | 16 +- .../DataTable/StaticTable/StaticTable.php | 83 ++++++++++ .../UI/Component/Title/TitleFactory.php | 5 + .../datatable/static/layout.html.twig | 48 ++++++ .../datatable/static/layout.js.twig | 47 ++++++ 10 files changed, 282 insertions(+), 73 deletions(-) create mode 100644 sources/application/UI/Component/DataTable/StaticTable/StaticTable.php create mode 100644 templates/components/datatable/static/layout.html.twig create mode 100644 templates/components/datatable/static/layout.js.twig diff --git a/application/displayblock.class.inc.php b/application/displayblock.class.inc.php index 0e75a5662..f1e5a6f15 100644 --- a/application/displayblock.class.inc.php +++ b/application/displayblock.class.inc.php @@ -415,75 +415,8 @@ class DisplayBlock switch($this->m_sStyle) { case 'count': - if (isset($aExtraParams['group_by'])) - { - $this->MakeGroupByQuery($aExtraParams, $oGroupByExp, $sGroupByLabel, $aGroupBy, $sAggregationFunction, $sFctVar, $sAggregationAttr, $sSql); - - $aRes = CMDBSource::QueryToArray($sSql); - - $aGroupBy = array(); - $aLabels = array(); - $aValues = array(); - $iTotalCount = 0; - foreach ($aRes as $iRow => $aRow) - { - $sValue = $aRow['grouped_by_1']; - $aValues[$iRow] = $sValue; - $sHtmlValue = $oGroupByExp->MakeValueLabel($this->m_oFilter, $sValue, $sValue); - $aLabels[$iRow] = $sHtmlValue; - $aGroupBy[$iRow] = (int) $aRow[$sFctVar]; - $iTotalCount += $aRow['_itop_count_']; - } - - - $aData = array(); - $oAppContext = new ApplicationContext(); - $sParams = $oAppContext->GetForLink(); - foreach($aGroupBy as $iRow => $iCount) - { - // Build the search for this subset - $oSubsetSearch = $this->m_oFilter->DeepClone(); - $oCondition = new BinaryExpression($oGroupByExp, '=', new ScalarExpression($aValues[$iRow])); - $oSubsetSearch->AddConditionExpression($oCondition); - if (isset($aExtraParams['query_params'])) - { - $aQueryParams = $aExtraParams['query_params']; - } - else - { - $aQueryParams = array(); - } - $sFilter = rawurlencode($oSubsetSearch->serialize(false, $aQueryParams)); - - $aData[] = array ('group' => $aLabels[$iRow], - 'value' => "$iCount"); // TO DO: add the context information - } - $aAttribs =array( - 'group' => array('label' => $sGroupByLabel, 'description' => ''), - 'value' => array( - 'label' => Dict::S('UI:GroupBy:'.$sAggregationFunction), - 'description' => Dict::Format('UI:GroupBy:'.$sAggregationFunction.'+', $sAggregationAttr), - ), - ); - $sFormat = isset($aExtraParams['format']) ? $aExtraParams['format'] : 'UI:Pagination:HeaderNoSelection'; - $sHtml .= $oPage->GetP(Dict::Format($sFormat, $iTotalCount)); - $sHtml .= $oPage->GetTable($aAttribs, $aData); - - $oPage->add_ready_script("LoadGroupBySortOrder('$sId');\n$('#{$sId} table.listResults').unbind('sortEnd.group_by').bind('sortEnd.group_by', function() { SaveGroupBySortOrder('$sId', $(this)[0].config.sortList); })"); - } - else - { - // Simply count the number of elements in the set - $iCount = $this->m_oSet->Count(); - $sFormat = 'UI:CountOfObjects'; - if (isset($aExtraParams['format'])) - { - $sFormat = $aExtraParams['format']; - } - $sHtml .= $oPage->GetP(Dict::Format($sFormat, $iCount)); - } - - break; + $oBlock = $this->RenderCount($aExtraParams, $oPage, $sId); + break; case 'join': $aDisplayAliases = isset($aExtraParams['display_aliases']) ? explode(',', $aExtraParams['display_aliases']): array(); @@ -1382,6 +1315,83 @@ JS return $oBlock; } + + /** + * @param array $aExtraParams + * @param \WebPage $oPage + * @param string|null $sId + * + * @return \Combodo\iTop\Application\UI\iUIBlock + * @throws \ArchivedObjectException + * @throws \CoreException + * @throws \MissingQueryArgument + * @throws \MySQLException + * @throws \MySQLHasGoneAwayException + * @throws \Exception + */ + protected function RenderCount(array $aExtraParams, WebPage $oPage, ?string $sId): iUIBlock + { + if (isset($aExtraParams['group_by'])) { + $this->MakeGroupByQuery($aExtraParams, $oGroupByExp, $sGroupByLabel, $aGroupBy, $sAggregationFunction, $sFctVar, $sAggregationAttr, $sSql); + + $aRes = CMDBSource::QueryToArray($sSql); + + $aGroupBy = array(); + $aLabels = array(); + $aValues = array(); + $iTotalCount = 0; + foreach ($aRes as $iRow => $aRow) { + $sValue = $aRow['grouped_by_1']; + $aValues[$iRow] = $sValue; + $sHtmlValue = $oGroupByExp->MakeValueLabel($this->m_oFilter, $sValue, $sValue); + $aLabels[$iRow] = $sHtmlValue; + $aGroupBy[$iRow] = (int)$aRow[$sFctVar]; + $iTotalCount += $aRow['_itop_count_']; + } + + $aData = array(); + $oAppContext = new ApplicationContext(); + $sParams = $oAppContext->GetForLink(); + foreach ($aGroupBy as $iRow => $iCount) { + // Build the search for this subset + $oSubsetSearch = $this->m_oFilter->DeepClone(); + $oCondition = new BinaryExpression($oGroupByExp, '=', new ScalarExpression($aValues[$iRow])); + $oSubsetSearch->AddConditionExpression($oCondition); + if (isset($aExtraParams['query_params'])) { + $aQueryParams = $aExtraParams['query_params']; + } else { + $aQueryParams = array(); + } + $sFilter = rawurlencode($oSubsetSearch->serialize(false, $aQueryParams)); + + $aData[] = array( + 'group' => $aLabels[$iRow], + 'value' => "$iCount" + ); // TO DO: add the context information + } + $aAttribs = array( + 'group' => array('label' => $sGroupByLabel, 'description' => ''), + 'value' => array( + 'label' => Dict::S('UI:GroupBy:'.$sAggregationFunction), + 'description' => Dict::Format('UI:GroupBy:'.$sAggregationFunction.'+', $sAggregationAttr), + ), + ); + $sFormat = isset($aExtraParams['format']) ? $aExtraParams['format'] : 'UI:Pagination:HeaderNoSelection'; + $sTitle = Dict::Format($sFormat, $iTotalCount); + $oBlock = DataTableFactory::MakeForStaticData($sTitle, $aAttribs, $aData); + + // $oPage->add_ready_script("LoadGroupBySortOrder('$sId');\n$('#{$sId} table.listResults').unbind('sortEnd.group_by').bind('sortEnd.group_by', function() { SaveGroupBySortOrder('$sId', $(this)[0].config.sortList); })"); + } else { + // Simply count the number of elements in the set + $iCount = $this->m_oSet->Count(); + $sFormat = 'UI:CountOfObjects'; + if (isset($aExtraParams['format'])) { + $sFormat = $aExtraParams['format']; + } + $oBlock = new Html($oPage->GetP(Dict::Format($sFormat, $iCount))); + } + return $oBlock; +} } /** diff --git a/css/backoffice/components/_datatable.scss b/css/backoffice/components/_datatable.scss index 6ad6b0644..93c645fba 100644 --- a/css/backoffice/components/_datatable.scss +++ b/css/backoffice/components/_datatable.scss @@ -72,7 +72,7 @@ } .ibo-datatable-toolbar { /*position: relative;*/ - height: 30px; + //height: 30px; } .ibo-criterion-area{ font-size: $ibo-font-size-50 ; diff --git a/dictionaries/ui/components/en.dictionary.itop.datatable.php b/dictionaries/ui/components/en.dictionary.itop.datatable.php index 9268242d4..281bed56f 100644 --- a/dictionaries/ui/components/en.dictionary.itop.datatable.php +++ b/dictionaries/ui/components/en.dictionary.itop.datatable.php @@ -21,9 +21,9 @@ Dict::Add('EN US', 'English', 'English', array( 'UI:Datatables:Language:Processing' => 'Please wait...', 'UI:Datatables:Language:Search' => 'Filter:', - 'UI:Datatables:Language:LengthMenu' => 'Showing _MENU_ out', + 'UI:Datatables:Language:LengthMenu' => 'Showing _MENU_ out of', 'UI:Datatables:Language:ZeroRecords' => 'No result', - 'UI:Datatables:Language:Info' => 'of _TOTAL_ items', + 'UI:Datatables:Language:Info' => '_TOTAL_ items', 'UI:Datatables:Language:InfoEmpty' => 'No information', 'UI:Datatables:Language:InfoFiltered' => 'filtered out of _MAX_ items', 'UI:Datatables:Language:EmptyTable' => 'No data available in this table', diff --git a/lib/composer/autoload_classmap.php b/lib/composer/autoload_classmap.php index 757f2dc5a..bedd4f246 100644 --- a/lib/composer/autoload_classmap.php +++ b/lib/composer/autoload_classmap.php @@ -164,6 +164,7 @@ return array( 'Combodo\\iTop\\Application\\UI\\Component\\DataTable\\DataTableBlock' => $baseDir . '/sources/application/UI/Component/DataTable/DataTable.php', 'Combodo\\iTop\\Application\\UI\\Component\\DataTable\\DataTableFactory' => $baseDir . '/sources/application/UI/Component/DataTable/DataTableFactory.php', 'Combodo\\iTop\\Application\\UI\\Component\\DataTable\\DataTableSettings' => $baseDir . '/sources/application/UI/Component/DataTable/DataTableSettings.php', + 'Combodo\\iTop\\Application\\UI\\Component\\DataTable\\StaticTable\\StaticTable' => $baseDir . '/sources/application/UI/Component/DataTable/StaticTable/StaticTable.php', 'Combodo\\iTop\\Application\\UI\\Component\\FieldSet\\FieldSet' => $baseDir . '/sources/application/UI/Component/FieldSet/FieldSet.php', 'Combodo\\iTop\\Application\\UI\\Component\\Field\\Field' => $baseDir . '/sources/application/UI/Component/Field/Field.php', 'Combodo\\iTop\\Application\\UI\\Component\\Form\\Form' => $baseDir . '/sources/application/UI/Component/Form/Form.php', diff --git a/lib/composer/autoload_static.php b/lib/composer/autoload_static.php index a88877f24..a892eca86 100644 --- a/lib/composer/autoload_static.php +++ b/lib/composer/autoload_static.php @@ -394,6 +394,7 @@ class ComposerStaticInit0018331147de7601e7552f7da8e3bb8b 'Combodo\\iTop\\Application\\UI\\Component\\DataTable\\DataTableBlock' => __DIR__ . '/../..' . '/sources/application/UI/Component/DataTable/DataTable.php', 'Combodo\\iTop\\Application\\UI\\Component\\DataTable\\DataTableFactory' => __DIR__ . '/../..' . '/sources/application/UI/Component/DataTable/DataTableFactory.php', 'Combodo\\iTop\\Application\\UI\\Component\\DataTable\\DataTableSettings' => __DIR__ . '/../..' . '/sources/application/UI/Component/DataTable/DataTableSettings.php', + 'Combodo\\iTop\\Application\\UI\\Component\\DataTable\\StaticTable\\StaticTable' => __DIR__ . '/../..' . '/sources/application/UI/Component/DataTable/StaticTable/StaticTable.php', 'Combodo\\iTop\\Application\\UI\\Component\\FieldSet\\FieldSet' => __DIR__ . '/../..' . '/sources/application/UI/Component/FieldSet/FieldSet.php', 'Combodo\\iTop\\Application\\UI\\Component\\Field\\Field' => __DIR__ . '/../..' . '/sources/application/UI/Component/Field/Field.php', 'Combodo\\iTop\\Application\\UI\\Component\\Form\\Form' => __DIR__ . '/../..' . '/sources/application/UI/Component/Form/Form.php', diff --git a/sources/application/UI/Component/DataTable/DataTableFactory.php b/sources/application/UI/Component/DataTable/DataTableFactory.php index 70bb2b3e6..8544d93aa 100644 --- a/sources/application/UI/Component/DataTable/DataTableFactory.php +++ b/sources/application/UI/Component/DataTable/DataTableFactory.php @@ -10,7 +10,9 @@ use ApplicationException; use AttributeLinkedSet; use CMDBObjectSet; use cmdbAbstractObject; +use Combodo\iTop\Application\UI\Component\DataTable\StaticTable\StaticTable; use Combodo\iTop\Application\UI\Component\Panel\PanelFactory; +use Combodo\iTop\Application\UI\Component\Title\TitleFactory; use MetaModel; use appUserPreferences; use UserRights; @@ -639,7 +641,19 @@ class DataTableFactory } )' ]; - return $aOptions; } + + public static function MakeForStaticData(string $sTitle, array $aColumns, array $aData, ?string $sId = null) + { + $oBlock = new UIContentBlock(); + $oTitle = TitleFactory::MakeNeutral($sTitle, 3); + $oBlock->AddSubBlock($oTitle); + $oTable = new StaticTable($sId); + $oTable->SetColumns($aColumns); + $oTable->SetData($aData); + $oBlock->AddSubBlock($oTable); + + return $oBlock; + } } \ No newline at end of file diff --git a/sources/application/UI/Component/DataTable/StaticTable/StaticTable.php b/sources/application/UI/Component/DataTable/StaticTable/StaticTable.php new file mode 100644 index 000000000..64aaa5a55 --- /dev/null +++ b/sources/application/UI/Component/DataTable/StaticTable/StaticTable.php @@ -0,0 +1,83 @@ + [ + * 'description' => tooltip, + * 'label' => label to display, + * 'class' => cell CSS class, + * 'metadata' => [key => value] transformed into data-key="value" + * ] + */ + private $aColumns; + + /** + * @var array of [ + * '@class' => css class of the row, + * 'entry name' => [ + * 'value_html' => value to display in the cell, + * 'value_raw' => real value put into data-value-raw + * ], ... + * ] + */ + private $aData; + + public function __construct(string $sId = null, string $sContainerCSSClass = '') + { + parent::__construct($sId, $sContainerCSSClass); + $this->aColumns = []; + $this->aData = []; + } + + /** + * @return array + */ + public function GetColumns(): array + { + return $this->aColumns; + } + + /** + * @param array $aColumns + */ + public function SetColumns(array $aColumns): void + { + $this->aColumns = $aColumns; + } + + /** + * @return array + */ + public function GetData(): array + { + return $this->aData; + } + + /** + * @param array $aData + */ + public function SetData(array $aData): void + { + $this->aData = $aData; + } + +} \ No newline at end of file diff --git a/sources/application/UI/Component/Title/TitleFactory.php b/sources/application/UI/Component/Title/TitleFactory.php index 37123bca1..5e4fbcc00 100644 --- a/sources/application/UI/Component/Title/TitleFactory.php +++ b/sources/application/UI/Component/Title/TitleFactory.php @@ -62,4 +62,9 @@ class TitleFactory return $oTitle; } + + public static function MakeNeutral(string $sTitle, int $iLevel = 1, ?string $sId = null) + { + return new Title($sTitle, $iLevel, $sId); + } } \ No newline at end of file diff --git a/templates/components/datatable/static/layout.html.twig b/templates/components/datatable/static/layout.html.twig new file mode 100644 index 000000000..3527d1ad4 --- /dev/null +++ b/templates/components/datatable/static/layout.html.twig @@ -0,0 +1,48 @@ +{# @copyright Copyright (C) 2010-2020 Combodo SARL #} +{# @license http://opensource.org/licenses/AGPL-3.0 #} + +{% set columns = oUIBlock.GetColumns() %} + + + + {% for column in columns %} + + {% endfor %} + + + + {% for data in oUIBlock.GetData() %} + {% if data['@class'] is not empty %} + + {% else %} + + {% endif %} + {% for name,column in columns %} + + {% endfor %} + + {% endfor %} + +
{{ column.label }}
{{ cellValueHtml|raw }}
\ No newline at end of file diff --git a/templates/components/datatable/static/layout.js.twig b/templates/components/datatable/static/layout.js.twig new file mode 100644 index 000000000..b7fba48d5 --- /dev/null +++ b/templates/components/datatable/static/layout.js.twig @@ -0,0 +1,47 @@ +{# @copyright Copyright (C) 2010-2020 Combodo SARL #} +{# @license http://opensource.org/licenses/AGPL-3.0 #} + +{% if oUIBlock.GetOptions() is not empty %} +{% set iPageSize = oUIBlock.GetOptions()["iPageSize"] %} +{% else %} +{% set iPageSize = 10 %} +{% endif %} + +$('#{{ oUIBlock.GetId() }}').DataTable({ + language: { + processing: "{{ 'UI:Datatables:Language:Processing'|dict_s }}", + search: "{{ 'UI:Datatables:Language:Search'|dict_s }}", + lengthMenu: "{{ 'UI:Datatables:Language:LengthMenu'|dict_s }}", + zeroRecords: "{{ 'UI:Datatables:Language:ZeroRecords'|dict_s }}", + info: "{{ 'UI:Datatables:Language:Info'|dict_s }}", + infoEmpty: "", + infoFiltered: "({{ 'UI:Datatables:Language:InfoFiltered'|dict_s }})", + emptyTable: "{{ 'UI:Datatables:Language:EmptyTable'|dict_s }}", + paginate: { + first: "<<", + previous: "<", + next: ">", + last: ">>" + }, + aria: { + sortAscending: ": {{ 'UI:Datatables:Language:Sort:Ascending'|dict_s }}", + sortDescending: ": {{ 'UI:Datatables:Language:Sort:Descending'|dict_s }}" + } + }, + order: [], + rowId: "id", + filter: false, + {% if oUIBlock.GetData()|length <= iPageSize %} + paging: false, + {% endif %} + dom: "<'ibo-datatable-toolbar'pil>t<'ibo-datatable-toolbar'pil>", + lengthMenu: [[ {{ iPageSize }}, {{ iPageSize*2 }}, {{ iPageSize*3 }}, {{ iPageSize*4 }}, -1], [ {{ iPageSize }}, {{ iPageSize*2 }}, {{ iPageSize*3 }}, {{ iPageSize*4 }}, "{{ 'Portal:Datatables:Language:DisplayLength:All'|dict_s }}"]], + columns: [ + {% for column in oUIBlock.GetColumns() %} + { + width: "auto", + sortable: true + }, + {% endfor %} + ] +}); \ No newline at end of file From 291041610bb040dd21bb7abce830bf67cb48050c Mon Sep 17 00:00:00 2001 From: Eric Date: Thu, 12 Nov 2020 10:57:13 +0100 Subject: [PATCH 07/16] set_time_limit accept only int in PHP7.4 --- application/cmdbabstract.class.inc.php | 4 ++-- application/utils.inc.php | 2 +- core/bulkchange.class.inc.php | 6 +++--- core/csvbulkexport.class.inc.php | 4 ++-- core/csvparser.class.inc.php | 6 +++--- core/dbobject.class.php | 10 +++++----- core/deletionplan.class.inc.php | 4 ++-- core/displayablegraph.class.inc.php | 18 +++++++++--------- core/excelbulkexport.class.inc.php | 4 ++-- core/htmlbulkexport.class.inc.php | 4 ++-- core/relationgraph.class.inc.php | 4 ++-- core/spreadsheetbulkexport.class.inc.php | 4 ++-- core/xmlbulkexport.class.inc.php | 4 ++-- .../combodo-db-tools/db_analyzer.class.inc.php | 2 +- synchro/synchro_import.php | 4 ++-- synchro/synchrodatasource.class.inc.php | 6 +++--- 16 files changed, 43 insertions(+), 43 deletions(-) diff --git a/application/cmdbabstract.class.inc.php b/application/cmdbabstract.class.inc.php index 05e69376e..817bd21ec 100644 --- a/application/cmdbabstract.class.inc.php +++ b/application/cmdbabstract.class.inc.php @@ -4623,7 +4623,7 @@ EOF $iLoopTimeLimit = MetaModel::GetConfig()->Get('max_execution_time_per_loop'); foreach($aSelectedObj as $iId) { - set_time_limit($iLoopTimeLimit); + set_time_limit(intval($iLoopTimeLimit)); /** @var \cmdbAbstractObject $oObj */ $oObj = MetaModel::GetObject($sClass, $iId); $aErrors = $oObj->UpdateObjectFromPostedForm(''); @@ -4655,7 +4655,7 @@ EOF $oObj->DBUpdate(); } } - set_time_limit($iPreviousTimeLimit); + set_time_limit(intval($iPreviousTimeLimit)); $oP->Table($aHeaders, $aRows); if ($bPreview) { diff --git a/application/utils.inc.php b/application/utils.inc.php index 372731f99..f8e06f8c8 100644 --- a/application/utils.inc.php +++ b/application/utils.inc.php @@ -1697,7 +1697,7 @@ class utils set_time_limit(0); // Compiling SASS $sCss = $oSass->compile($sSassContent); - set_time_limit($iCurrentMaxExecTime); + set_time_limit(intval($iCurrentMaxExecTime)); return $sCss; } diff --git a/core/bulkchange.class.inc.php b/core/bulkchange.class.inc.php index 976d894d5..0af44ae97 100644 --- a/core/bulkchange.class.inc.php +++ b/core/bulkchange.class.inc.php @@ -948,7 +948,7 @@ class BulkChange $iLoopTimeLimit = MetaModel::GetConfig()->Get('max_execution_time_per_loop'); foreach($this->m_aData as $iRow => $aRowData) { - set_time_limit($iLoopTimeLimit); + set_time_limit(intval($iLoopTimeLimit)); if (isset($aResult[$iRow]["__STATUS__"])) { // An issue at the earlier steps - skip the rest @@ -1067,13 +1067,13 @@ class BulkChange $iObj = $oObj->GetKey(); if (!in_array($iObj, $aVisited)) { - set_time_limit($iLoopTimeLimit); + set_time_limit(intval($iLoopTimeLimit)); $iRow++; $this->UpdateMissingObject($aResult, $iRow, $oObj, $oChange); } } } - set_time_limit($iPreviousTimeLimit); + set_time_limit(itval($iPreviousTimeLimit)); // Fill in the blanks - the result matrix is expected to be 100% complete // diff --git a/core/csvbulkexport.class.inc.php b/core/csvbulkexport.class.inc.php index bfb22cfcf..fad0c38f0 100644 --- a/core/csvbulkexport.class.inc.php +++ b/core/csvbulkexport.class.inc.php @@ -301,7 +301,7 @@ EOF } while($aRow = $oSet->FetchAssoc()) { - set_time_limit($iLoopTimeLimit); + set_time_limit(intval($iLoopTimeLimit)); $aData = array(); foreach($this->aStatusInfo['fields'] as $iCol => $aFieldSpec) { @@ -339,7 +339,7 @@ EOF // Restore original date & time formats AttributeDateTime::SetFormat($oPrevDateTimeFormat); AttributeDate::SetFormat($oPrevDateFormat); - set_time_limit($iPreviousTimeLimit); + set_time_limit(intval($iPreviousTimeLimit)); $this->aStatusInfo['position'] += $this->iChunkSize; if ($this->aStatusInfo['total'] == 0) { diff --git a/core/csvparser.class.inc.php b/core/csvparser.class.inc.php index fae9af6d1..86df52b52 100644 --- a/core/csvparser.class.inc.php +++ b/core/csvparser.class.inc.php @@ -135,7 +135,7 @@ class CSVParser // More time for the next row if ($this->m_iTimeLimitPerRow !== null) { - set_time_limit($this->m_iTimeLimitPerRow); + set_time_limit(intval($this->m_iTimeLimitPerRow)); } } protected function __AddCellTrimmed($c = null, $aFieldMap = null) @@ -194,7 +194,7 @@ class CSVParser { // Give some time for the first row $iTimeLimit = ini_get('max_execution_time'); - set_time_limit($this->m_iTimeLimitPerRow); + set_time_limit(intval($this->m_iTimeLimitPerRow)); } for($i = 0; $i <= $iDataLength ; $i++) { @@ -255,7 +255,7 @@ class CSVParser if ($iTimeLimit !== null) { // Restore the previous time limit - set_time_limit($iTimeLimit); + set_time_limit(intval($iTimeLimit)); } return $this->m_aDataSet; } diff --git a/core/dbobject.class.php b/core/dbobject.class.php index f6eb94566..5b69898c1 100644 --- a/core/dbobject.class.php +++ b/core/dbobject.class.php @@ -3595,7 +3595,7 @@ abstract class DBObject implements iDisplay // As a temporary fix: delete only the objects that are still to be deleted... if ($oToDelete->m_bIsInDB) { - set_time_limit($iLoopTimeLimit); + set_time_limit(intval($iLoopTimeLimit)); $oToDelete->DBDeleteSingleObject(); } } @@ -3610,13 +3610,13 @@ abstract class DBObject implements iDisplay foreach ($aData['attributes'] as $sRemoteExtKey => $aRemoteAttDef) { $oToUpdate->Set($sRemoteExtKey, $aData['values'][$sRemoteExtKey]); - set_time_limit($iLoopTimeLimit); + set_time_limit(intval($iLoopTimeLimit)); $oToUpdate->DBUpdate(); } } } - set_time_limit($iPreviousTimeLimit); + set_time_limit(intval($iPreviousTimeLimit)); return $oDeletionPlan; } @@ -4560,7 +4560,7 @@ abstract class DBObject implements iDisplay { foreach ($aPotentialDeletes as $sRemoteExtKey => $aData) { - set_time_limit($iLoopTimeLimit); + set_time_limit(intval($iLoopTimeLimit)); /** @var \AttributeExternalKey $oAttDef */ $oAttDef = $aData['attribute']; @@ -4592,7 +4592,7 @@ abstract class DBObject implements iDisplay } } } - set_time_limit($iPreviousTimeLimit); + set_time_limit(intval($iPreviousTimeLimit)); } /** diff --git a/core/deletionplan.class.inc.php b/core/deletionplan.class.inc.php index 447b458f1..9cae22135 100644 --- a/core/deletionplan.class.inc.php +++ b/core/deletionplan.class.inc.php @@ -116,7 +116,7 @@ class DeletionPlan { foreach($aToUpdate as $iId => $aData) { - set_time_limit($iLoopTimeLimit); + set_time_limit(intval($iLoopTimeLimit)); $this->m_iToUpdate++; $oObject = $aData['to_reset']; @@ -142,7 +142,7 @@ class DeletionPlan } } } - set_time_limit($iPreviousTimeLimit); + set_time_limit(intval($iPreviousTimeLimit)); } public function GetIssues() diff --git a/core/displayablegraph.class.inc.php b/core/displayablegraph.class.inc.php index 06b405543..559fd0c02 100644 --- a/core/displayablegraph.class.inc.php +++ b/core/displayablegraph.class.inc.php @@ -874,7 +874,7 @@ class DisplayableGraph extends SimpleGraph $oNodesIter = new RelationTypeIterator($oGraph, 'Node'); foreach($oNodesIter as $oNode) { - set_time_limit($iLoopTimeLimit); + set_time_limit(intval($iLoopTimeLimit)); switch(get_class($oNode)) { case 'RelationObjectNode': @@ -921,7 +921,7 @@ class DisplayableGraph extends SimpleGraph $oEdgesIter = new RelationTypeIterator($oGraph, 'Edge'); foreach($oEdgesIter as $oEdge) { - set_time_limit($iLoopTimeLimit); + set_time_limit(intval($iLoopTimeLimit)); $oSourceNode = $oNewGraph->GetNode($oEdge->GetSourceNode()->GetId()); $oSinkNode = $oNewGraph->GetNode($oEdge->GetSinkNode()->GetId()); $oNewEdge = new DisplayableEdge($oNewGraph, $oEdge->GetId(), $oSourceNode, $oSinkNode); @@ -932,7 +932,7 @@ class DisplayableGraph extends SimpleGraph $aEdgeKeys = array(); foreach($oEdgesIter as $oEdge) { - set_time_limit($iLoopTimeLimit); + set_time_limit(intval($iLoopTimeLimit)); $sSourceId = $oEdge->GetSourceNode()->GetId(); $sSinkId = $oEdge->GetSinkNode()->GetId(); if ($sSourceId == $sSinkId) @@ -958,7 +958,7 @@ class DisplayableGraph extends SimpleGraph $oNodesIter = new RelationTypeIterator($oNewGraph, 'Node'); foreach($oNodesIter as $oNode) { - set_time_limit($iLoopTimeLimit); + set_time_limit(intval($iLoopTimeLimit)); if ($bDirectionDown && $oNode->GetProperty('source')) { $oNode->GroupSimilarNeighbours($oNewGraph, $iGroupingThreshold, true, $bDirectionDown); @@ -973,7 +973,7 @@ class DisplayableGraph extends SimpleGraph $iGroupIdx = 0; foreach($oIterator as $oNode) { - set_time_limit($iLoopTimeLimit); + set_time_limit(intval($iLoopTimeLimit)); if ($oNode instanceof DisplayableGroupNode) { if ($oNode->GetObjectCount() == 0) @@ -995,7 +995,7 @@ class DisplayableGraph extends SimpleGraph $aEdgeKeys = array(); foreach($oEdgesIter as $oEdge) { - set_time_limit($iLoopTimeLimit); + set_time_limit(intval($iLoopTimeLimit)); $sSourceId = $oEdge->GetSourceNode()->GetId(); $sSinkId = $oEdge->GetSinkNode()->GetId(); if ($sSourceId == $sSinkId) @@ -1017,7 +1017,7 @@ class DisplayableGraph extends SimpleGraph } } } - set_time_limit($iPreviousTimeLimit); + set_time_limit(intval($iPreviousTimeLimit)); return $oNewGraph; } @@ -1257,14 +1257,14 @@ class DisplayableGraph extends SimpleGraph $iLoopTimeLimit = MetaModel::GetConfig()->Get('max_execution_time_per_loop'); foreach($oIterator as $sId => $oEdge) { - set_time_limit($iLoopTimeLimit); + set_time_limit(intval($iLoopTimeLimit)); $oEdge->RenderAsPDF($oPdf, $this, $fScale, $aContextDefs); } $oIterator = new RelationTypeIterator($this, 'Node'); foreach($oIterator as $sId => $oNode) { - set_time_limit($iLoopTimeLimit); + set_time_limit(intval($iLoopTimeLimit)); $oNode->RenderAsPDF($oPdf, $this, $fScale, $aContextDefs); } diff --git a/core/excelbulkexport.class.inc.php b/core/excelbulkexport.class.inc.php index 1d4569397..c4998cd92 100644 --- a/core/excelbulkexport.class.inc.php +++ b/core/excelbulkexport.class.inc.php @@ -296,7 +296,7 @@ EOF $iLoopTimeLimit = MetaModel::GetConfig()->Get('max_execution_time_per_loop'); while($aRow = $oSet->FetchAssoc()) { - set_time_limit($iLoopTimeLimit); + set_time_limit(intval($iLoopTimeLimit)); $aData = array(); foreach($this->aStatusInfo['fields'] as $iCol => $aFieldSpec) { @@ -314,7 +314,7 @@ EOF fwrite($hFile, json_encode($aData)."\n"); $iCount++; } - set_time_limit($iPreviousTimeLimit); + set_time_limit(intval($iPreviousTimeLimit)); $this->aStatusInfo['position'] += $this->iChunkSize; if ($this->aStatusInfo['total'] == 0) { diff --git a/core/htmlbulkexport.class.inc.php b/core/htmlbulkexport.class.inc.php index 8f811bb14..aea53bf88 100644 --- a/core/htmlbulkexport.class.inc.php +++ b/core/htmlbulkexport.class.inc.php @@ -128,7 +128,7 @@ class HTMLBulkExport extends TabularBulkExport $iLoopTimeLimit = MetaModel::GetConfig()->Get('max_execution_time_per_loop'); while($aRow = $oSet->FetchAssoc()) { - set_time_limit($iLoopTimeLimit); + set_time_limit(intval($iLoopTimeLimit)); $oMainObj = $aRow[$sFirstAlias]; $sHilightClass = ''; if ($oMainObj) @@ -160,7 +160,7 @@ class HTMLBulkExport extends TabularBulkExport $sData .= ""; $iCount++; } - set_time_limit($iPreviousTimeLimit); + set_time_limit(intval($iPreviousTimeLimit)); $this->aStatusInfo['position'] += $this->iChunkSize; if ($this->aStatusInfo['total'] == 0) { diff --git a/core/relationgraph.class.inc.php b/core/relationgraph.class.inc.php index 3e3521767..4dde465f8 100644 --- a/core/relationgraph.class.inc.php +++ b/core/relationgraph.class.inc.php @@ -472,7 +472,7 @@ class RelationGraph extends SimpleGraph { do { - set_time_limit($iLoopTimeLimit); + set_time_limit(intval($iLoopTimeLimit)); $sObjectRef = RelationObjectNode::MakeId($oRelatedObj); $oRelatedNode = $this->GetNode($sObjectRef); @@ -501,7 +501,7 @@ class RelationGraph extends SimpleGraph while ($oRelatedObj = $oObjSet->Fetch()); } } - set_time_limit($iPreviousTimeLimit); + set_time_limit(intval($iPreviousTimeLimit)); } } } diff --git a/core/spreadsheetbulkexport.class.inc.php b/core/spreadsheetbulkexport.class.inc.php index a742bc780..8a31453a6 100644 --- a/core/spreadsheetbulkexport.class.inc.php +++ b/core/spreadsheetbulkexport.class.inc.php @@ -266,7 +266,7 @@ EOF $iLoopTimeLimit = MetaModel::GetConfig()->Get('max_execution_time_per_loop'); while($aRow = $oSet->FetchAssoc()) { - set_time_limit($iLoopTimeLimit); + set_time_limit(intval($iLoopTimeLimit)); $sData .= ""; foreach($this->aStatusInfo['fields'] as $iCol => $aFieldSpec) @@ -362,7 +362,7 @@ EOF $sData .= ""; $iCount++; } - set_time_limit($iPreviousTimeLimit); + set_time_limit(intval($iPreviousTimeLimit)); $this->aStatusInfo['position'] += $this->iChunkSize; if ($this->aStatusInfo['total'] == 0) { diff --git a/core/xmlbulkexport.class.inc.php b/core/xmlbulkexport.class.inc.php index a94ecef1e..6c5d6bdb6 100644 --- a/core/xmlbulkexport.class.inc.php +++ b/core/xmlbulkexport.class.inc.php @@ -144,7 +144,7 @@ class XMLBulkExport extends BulkExport while ($aObjects = $oSet->FetchAssoc()) { - set_time_limit($iLoopTimeLimit); + set_time_limit(intval($iLoopTimeLimit)); if (count($aAuthorizedClasses) > 1) { $sData .= "\n"; @@ -182,7 +182,7 @@ class XMLBulkExport extends BulkExport $iCount++; } - set_time_limit($iPreviousTimeLimit); + set_time_limit(intval($iPreviousTimeLimit)); $this->aStatusInfo['position'] += $this->iChunkSize; if ($this->aStatusInfo['total'] == 0) { diff --git a/datamodels/2.x/combodo-db-tools/db_analyzer.class.inc.php b/datamodels/2.x/combodo-db-tools/db_analyzer.class.inc.php index 29772994e..c41c83219 100644 --- a/datamodels/2.x/combodo-db-tools/db_analyzer.class.inc.php +++ b/datamodels/2.x/combodo-db-tools/db_analyzer.class.inc.php @@ -40,7 +40,7 @@ class DatabaseAnalyzer { if (!is_null($this->iTimeLimitPerOperation)) { - set_time_limit($this->iTimeLimitPerOperation); + set_time_limit(intval($this->iTimeLimitPerOperation)); } $aWrongRecords = CMDBSource::QueryToArray($sSelWrongRecs); diff --git a/synchro/synchro_import.php b/synchro/synchro_import.php index d15b7be3e..613622414 100644 --- a/synchro/synchro_import.php +++ b/synchro/synchro_import.php @@ -491,7 +491,7 @@ try $iLoopTimeLimit = MetaModel::GetConfig()->Get('max_execution_time_per_loop'); $oMutex = new iTopMutex('synchro_import_'.$oDataSource->GetKey()); $oMutex->Lock(); - set_time_limit($iLoopTimeLimit); + set_time_limit(intval($iLoopTimeLimit)); foreach ($aData as $iRow => $aRow) { $sReconciliationCondition = '`primary_key` = '.CMDBSource::Quote($aRow[$iPrimaryKeyCol]); @@ -633,7 +633,7 @@ try } } $oMutex->Unlock(); - set_time_limit($iPreviousTimeLimit); + set_time_limit(intval($iPreviousTimeLimit)); if (($sOutput === 'summary') || ($sOutput === 'details')) { diff --git a/synchro/synchrodatasource.class.inc.php b/synchro/synchrodatasource.class.inc.php index eac1c4048..3c4678492 100644 --- a/synchro/synchrodatasource.class.inc.php +++ b/synchro/synchrodatasource.class.inc.php @@ -3466,7 +3466,7 @@ class SynchroExecution /** @var SynchroReplica $oReplica */ while($oReplica = $oSetToProcess->Fetch()) { - set_time_limit($iLoopTimeLimit); + set_time_limit(intval($iLoopTimeLimit)); $iLastReplicaProcessed = $oReplica->GetKey(); switch ($sDeletePolicy) { @@ -3595,7 +3595,7 @@ class SynchroExecution /** @var \SynchroReplica $oReplica */ while ($oReplica = $oSetToProcess->Fetch()) { - set_time_limit($iLoopTimeLimit); + set_time_limit(intval($iLoopTimeLimit)); $iLastReplicaProcessed = $oReplica->GetKey(); $this->m_oStatLog->AddTrace("Synchronizing replica id=$iLastReplicaProcessed."); $oReplica->Synchro($this->m_oDataSource, $this->m_aReconciliationKeys, $this->m_aAttributes, $this->m_oChange, @@ -3697,7 +3697,7 @@ class SynchroExecution /** @var SynchroReplica $oReplica */ while($oReplica = $oSetToProcess->Fetch()) { - set_time_limit($iLoopTimeLimit); + set_time_limit(intval($iLoopTimeLimit)); $iLastReplicaProcessed = $oReplica->GetKey(); $this->m_oStatLog->AddTrace('Destination object to be DELETED', $oReplica); $oReplica->DeleteDestObject($this->m_oChange, $this->m_oStatLog); From 6d82a85b12b905576f740a8cf342f90b3b1c9e2c Mon Sep 17 00:00:00 2001 From: Eric Date: Thu, 12 Nov 2020 11:44:06 +0100 Subject: [PATCH 08/16] =?UTF-8?q?N=C2=B02847=20-=20Datatables=20for=20form?= =?UTF-8?q?s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- application/ui.linkswidget.class.inc.php | 63 +-- css/backoffice/components/_all.scss | 3 +- css/backoffice/components/_formtable.scss | 4 + css/light-grey.scss | 1 - lib/composer/autoload_classmap.php | 1 + lib/composer/autoload_static.php | 1 + .../Component/DataTable/DataTableFactory.php | 10 + .../StaticTable/FormTable/FormTable.php | 48 ++ templates/components/datatable/layout.js.twig | 437 +++++++++--------- .../static/formtable/layout.html.twig | 35 ++ .../datatable/static/formtable/layout.js.twig | 6 + 11 files changed, 330 insertions(+), 279 deletions(-) create mode 100644 css/backoffice/components/_formtable.scss create mode 100644 sources/application/UI/Component/DataTable/StaticTable/FormTable/FormTable.php create mode 100644 templates/components/datatable/static/formtable/layout.html.twig create mode 100644 templates/components/datatable/static/formtable/layout.js.twig diff --git a/application/ui.linkswidget.class.inc.php b/application/ui.linkswidget.class.inc.php index 54048e9ac..5e2869369 100644 --- a/application/ui.linkswidget.class.inc.php +++ b/application/ui.linkswidget.class.inc.php @@ -24,6 +24,9 @@ * @license http://opensource.org/licenses/AGPL-3.0 */ +use Combodo\iTop\Application\UI\Component\DataTable\DataTableFactory; +use Combodo\iTop\Renderer\BlockRenderer; + require_once(APPROOT.'application/displayblock.class.inc.php'); class UILinksWidget @@ -335,68 +338,24 @@ JS ); } - /** - * Display one row of the whole form - * - * @param WebPage $oP - * @param array $aConfig - * @param array $aRow - * @param int $iRowId - * - * @return string - */ - protected function DisplayFormRow(WebPage $oP, $aConfig, $aRow, $iRowId) - { - $sHtml = ''; - $sHtml .= "m_sAttCode}{$this->m_sNameSuffix}_row_$iRowId\">\n"; - foreach($aConfig as $sName=>$void) - { - $sHtml .= "".$aRow[$sName]."\n"; - } - $sHtml .= "\n"; - - return $sHtml; - } - /** * Display the table with the form for editing all the links at once + * * @param WebPage $oP The web page used for the output * @param array $aConfig The table's header configuration * @param array $aData The tabular data to be displayed + * * @return string Html fragment representing the form table + * @throws \ReflectionException + * @throws \Twig\Error\LoaderError + * @throws \Twig\Error\RuntimeError + * @throws \Twig\Error\SyntaxError */ protected function DisplayFormTable(WebPage $oP, $aConfig, $aData) { - $sHtml = "m_sAttCode}{$this->m_sNameSuffix}\" value=\"\">"; - $sHtml .= "\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 .= "\n"; - $sHtml .= "\n"; - foreach($aConfig as $sName=>$aDef) - { - $sHtml .= "\n"; - } - $sHtml .= "\n"; - $sHtml .= "\n"; + $oTable = DataTableFactory::MakeForForm("{$this->m_sAttCode}{$this->m_sNameSuffix}", $aConfig, $aData); - // Content - $sHtml .= "\n"; - $sEmptyRowStyle = ''; - if (count($aData) != 0) - { - $sEmptyRowStyle = 'style="display:none;"'; - } - - foreach ($aData as $iRowId => $aRow) - { - $sHtml .= $this->DisplayFormRow($oP, $aConfig, $aRow, $iRowId); - } - //$sHtml .= "m_sAttCode}{$this->m_sNameSuffix}_empty_row\">"; - $sHtml .= "\n"; - - // Footer - $sHtml .= "
".$aDef['label']."
".Dict::S('UI:Message:EmptyList:UseAdd')."

\n"; + $sHtml = BlockRenderer::RenderBlockTemplates($oTable); return $sHtml; } diff --git a/css/backoffice/components/_all.scss b/css/backoffice/components/_all.scss index f81bd1372..b4732ec98 100644 --- a/css/backoffice/components/_all.scss +++ b/css/backoffice/components/_all.scss @@ -23,4 +23,5 @@ @import "fieldset"; @import "field"; @import "toolbar"; -@import "richtext"; \ No newline at end of file +@import "richtext"; +@import "formtable"; \ No newline at end of file diff --git a/css/backoffice/components/_formtable.scss b/css/backoffice/components/_formtable.scss new file mode 100644 index 000000000..2b1c120e8 --- /dev/null +++ b/css/backoffice/components/_formtable.scss @@ -0,0 +1,4 @@ +/*! + * copyright Copyright (C) 2010-2020 Combodo SARL + * license http://opensource.org/licenses/AGPL-3.0 + */ diff --git a/css/light-grey.scss b/css/light-grey.scss index 9bc0a7908..c202a5ab8 100644 --- a/css/light-grey.scss +++ b/css/light-grey.scss @@ -2645,7 +2645,6 @@ } > .field_input_btn { - display: table-cell; width: 25px; padding-left: 0.4em; diff --git a/lib/composer/autoload_classmap.php b/lib/composer/autoload_classmap.php index bedd4f246..e66f84566 100644 --- a/lib/composer/autoload_classmap.php +++ b/lib/composer/autoload_classmap.php @@ -164,6 +164,7 @@ return array( 'Combodo\\iTop\\Application\\UI\\Component\\DataTable\\DataTableBlock' => $baseDir . '/sources/application/UI/Component/DataTable/DataTable.php', 'Combodo\\iTop\\Application\\UI\\Component\\DataTable\\DataTableFactory' => $baseDir . '/sources/application/UI/Component/DataTable/DataTableFactory.php', 'Combodo\\iTop\\Application\\UI\\Component\\DataTable\\DataTableSettings' => $baseDir . '/sources/application/UI/Component/DataTable/DataTableSettings.php', + 'Combodo\\iTop\\Application\\UI\\Component\\DataTable\\StaticTable\\FormTable\\FormTable' => $baseDir . '/sources/application/UI/Component/DataTable/StaticTable/FormTable/FormTable.php', 'Combodo\\iTop\\Application\\UI\\Component\\DataTable\\StaticTable\\StaticTable' => $baseDir . '/sources/application/UI/Component/DataTable/StaticTable/StaticTable.php', 'Combodo\\iTop\\Application\\UI\\Component\\FieldSet\\FieldSet' => $baseDir . '/sources/application/UI/Component/FieldSet/FieldSet.php', 'Combodo\\iTop\\Application\\UI\\Component\\Field\\Field' => $baseDir . '/sources/application/UI/Component/Field/Field.php', diff --git a/lib/composer/autoload_static.php b/lib/composer/autoload_static.php index a892eca86..fa7e97290 100644 --- a/lib/composer/autoload_static.php +++ b/lib/composer/autoload_static.php @@ -394,6 +394,7 @@ class ComposerStaticInit0018331147de7601e7552f7da8e3bb8b 'Combodo\\iTop\\Application\\UI\\Component\\DataTable\\DataTableBlock' => __DIR__ . '/../..' . '/sources/application/UI/Component/DataTable/DataTable.php', 'Combodo\\iTop\\Application\\UI\\Component\\DataTable\\DataTableFactory' => __DIR__ . '/../..' . '/sources/application/UI/Component/DataTable/DataTableFactory.php', 'Combodo\\iTop\\Application\\UI\\Component\\DataTable\\DataTableSettings' => __DIR__ . '/../..' . '/sources/application/UI/Component/DataTable/DataTableSettings.php', + 'Combodo\\iTop\\Application\\UI\\Component\\DataTable\\StaticTable\\FormTable\\FormTable' => __DIR__ . '/../..' . '/sources/application/UI/Component/DataTable/StaticTable/FormTable/FormTable.php', 'Combodo\\iTop\\Application\\UI\\Component\\DataTable\\StaticTable\\StaticTable' => __DIR__ . '/../..' . '/sources/application/UI/Component/DataTable/StaticTable/StaticTable.php', 'Combodo\\iTop\\Application\\UI\\Component\\FieldSet\\FieldSet' => __DIR__ . '/../..' . '/sources/application/UI/Component/FieldSet/FieldSet.php', 'Combodo\\iTop\\Application\\UI\\Component\\Field\\Field' => __DIR__ . '/../..' . '/sources/application/UI/Component/Field/Field.php', diff --git a/sources/application/UI/Component/DataTable/DataTableFactory.php b/sources/application/UI/Component/DataTable/DataTableFactory.php index 8544d93aa..de64d3026 100644 --- a/sources/application/UI/Component/DataTable/DataTableFactory.php +++ b/sources/application/UI/Component/DataTable/DataTableFactory.php @@ -10,6 +10,7 @@ use ApplicationException; use AttributeLinkedSet; use CMDBObjectSet; use cmdbAbstractObject; +use Combodo\iTop\Application\UI\Component\DataTable\StaticTable\FormTable\FormTable; use Combodo\iTop\Application\UI\Component\DataTable\StaticTable\StaticTable; use Combodo\iTop\Application\UI\Component\Panel\PanelFactory; use Combodo\iTop\Application\UI\Component\Title\TitleFactory; @@ -656,4 +657,13 @@ class DataTableFactory return $oBlock; } + + public Static function MakeForForm(string $sRef, array $aColumns, array $aData) + { + $oTable = new FormTable($sRef); + $oTable->SetColumns($aColumns); + $oTable->SetData($aData); + + return $oTable; + } } \ No newline at end of file diff --git a/sources/application/UI/Component/DataTable/StaticTable/FormTable/FormTable.php b/sources/application/UI/Component/DataTable/StaticTable/FormTable/FormTable.php new file mode 100644 index 000000000..619771a4b --- /dev/null +++ b/sources/application/UI/Component/DataTable/StaticTable/FormTable/FormTable.php @@ -0,0 +1,48 @@ +SetRef($sRef); + } + + /** + * @return string + */ + public function GetRef(): string + { + return $this->sRef; + } + + /** + * @param string $sRef + */ + public function SetRef(string $sRef): void + { + $this->sRef = $sRef; + } +} \ No newline at end of file diff --git a/templates/components/datatable/layout.js.twig b/templates/components/datatable/layout.js.twig index 106dac842..9183520e3 100644 --- a/templates/components/datatable/layout.js.twig +++ b/templates/components/datatable/layout.js.twig @@ -1,256 +1,243 @@ -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; +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 () { + 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() }}').closest("[role=dialog]").on("dialogbeforeclose", function () { + 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'] }} = []; +var oSelectedItems{{ oUIBlock.GetOptions()['sTableId'] }} = []; {% endif %} -if ( $.fn.dataTable.isDataTable( '#{{ oUIBlock.GetId() }}' ) ) { - console.warn("destroy on load"); - $('#{{ oUIBlock.GetId() }}').DataTable().destroy(false); +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": '', - "type": "html", - "data": "", - "render": function(data, type, row) - { - var oCheckboxElem = $(''); - 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 - } ) + "language": { + "processing": "{{ 'UI:Datatables:Language:Processing'|dict_s }}", + "search": "{{ 'UI:Datatables:Language:Search'|dict_s }}", + "lengthMenu": "{{ 'UI:Datatables:Language:LengthMenu'|dict_s }}", + "zeroRecords": "{{ 'UI:Datatables:Language:ZeroRecords'|dict_s }}", + "info": "{{ 'UI:Datatables:Language:Info'|dict_s }}", + "infoEmpty": "{{ '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": [], + {% 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 () { + // 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": '', + "type": "html", + "data": "", + "render": function (data, type, row) { + var oCheckboxElem = $(''); + 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 + }), + "initComplete": function() { + if (this.api().page.info().pages === 1) { + $('.dataTables_paginate').hide(); + $('.dataTables_length').hide(); + } + } }); -oTable{{ oUIBlock.GetId() }}.off('select').on('select', function(oEvent, dt, type, indexes){ - var aData = oTable{{ oUIBlock.GetId() }}.rows(indexes).data().toArray(); +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); - } + // 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(); +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); - } + // 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]; +// 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 %} +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); +// 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 %} +// 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'); - } -}); + { + 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}}, + '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"); +if ($('#datatable_dlg_{{ oUIBlock.GetId() }}').DataTableSettings()) { + $('#datatable_dlg_{{ oUIBlock.GetId() }}').DataTableSettings("destroy"); } -$('#datatable_dlg_{{ oUIBlock.GetId() }}').DataTableSettings( $aOptions); \ No newline at end of file +$('#datatable_dlg_{{ oUIBlock.GetId() }}').DataTableSettings($aOptions); \ No newline at end of file diff --git a/templates/components/datatable/static/formtable/layout.html.twig b/templates/components/datatable/static/formtable/layout.html.twig new file mode 100644 index 000000000..2f20c1dd5 --- /dev/null +++ b/templates/components/datatable/static/formtable/layout.html.twig @@ -0,0 +1,35 @@ +{# @copyright Copyright (C) 2010-2020 Combodo SARL #} +{# @license http://opensource.org/licenses/AGPL-3.0 #} + + + +{% set columns = oUIBlock.GetColumns() %} + + + + {% for column in columns %} + + {% endfor %} + + + + {% for rowId,data in oUIBlock.GetData() %} + + {% for name,column in columns %} + + {% endfor %} + + {% endfor %} + +
{{ column.label|raw }}
+ {% set cellValueHtml = '' %} + {% for cellName,cellValue in data %} + {% if cellName == name %} + {% set cellValueHtml = cellValue %} + {% endif %} + {% endfor %} + {% if cellValueHtml is empty %} + {% set cellValueHtml = ' ' %} + {% endif %} + {{ cellValueHtml|raw }} +
\ No newline at end of file diff --git a/templates/components/datatable/static/formtable/layout.js.twig b/templates/components/datatable/static/formtable/layout.js.twig new file mode 100644 index 000000000..8868623b2 --- /dev/null +++ b/templates/components/datatable/static/formtable/layout.js.twig @@ -0,0 +1,6 @@ +$('#{{ oUIBlock.GetId() }}').DataTable({ + language: { + emptyTable: {{ 'UI:Message:EmptyList:UseAdd'|dict_s }} + }, + search:false +}); \ No newline at end of file From 62880b04eb23ca0e4d3c9a629229bb4d9fa8d16e Mon Sep 17 00:00:00 2001 From: Eric Date: Thu, 12 Nov 2020 11:59:56 +0100 Subject: [PATCH 09/16] =?UTF-8?q?N=C2=B02847=20-=20Datatables=20pagination?= =?UTF-8?q?=20CSS?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- css/backoffice/components/_datatable.scss | 8 ++ .../precompiled-themes/light-grey/main.css | 115 +++++++++--------- .../precompiled-themes/test-red/main.css | 115 +++++++++--------- templates/components/datatable/layout.js.twig | 4 +- .../datatable/static/layout.js.twig | 4 +- 5 files changed, 126 insertions(+), 120 deletions(-) diff --git a/css/backoffice/components/_datatable.scss b/css/backoffice/components/_datatable.scss index 93c645fba..7e07eb52d 100644 --- a/css/backoffice/components/_datatable.scss +++ b/css/backoffice/components/_datatable.scss @@ -19,6 +19,9 @@ } .dataTables_length { + @extend %ibo-font-ral-med-100; + color: $ibo-color-grey-700; + position: relative; float: right; padding-top: 0.755em; @@ -26,6 +29,9 @@ } .dataTables_info { + @extend %ibo-font-ral-med-100; + color: $ibo-color-grey-700; + position: relative; float: right; padding-top: 0.755em; @@ -38,6 +44,8 @@ .pagination { + color: $ibo-color-grey-800; + left: 1.21%; right: 1.21%; top: 91.58%; diff --git a/datamodels/2.x/itop-structure/precompiled-themes/light-grey/main.css b/datamodels/2.x/itop-structure/precompiled-themes/light-grey/main.css index 24a1b630d..b6604273b 100644 --- a/datamodels/2.x/itop-structure/precompiled-themes/light-grey/main.css +++ b/datamodels/2.x/itop-structure/precompiled-themes/light-grey/main.css @@ -1,6 +1,6 @@ /* === SIGNATURE BEGIN === -{"variables":"d751713988987e9331980363e24189ce","stylesheets":{"css-variables":"732f501302c538f594fb3c668d85b46c","jqueryui":"a887ad1c00f29132beba3bf729b981c7","main":"0efa2620e936b99f9e2ad32088636b33"},"imports":[],"images":{"css\/ui-lightness\/images\/ui-icons_222222_256x240.png":"3a3c5468f484f07ac4a320d9e22acb8c","css\/ui-lightness\/images\/ui-bg_diagonals-thick_20_666666_40x40.png":"4429d568c67d8dfeb9040273ea0fb8c4","css\/ui-lightness\/images\/ui-icons_E87C1E_256x240.png":"7003dd36cb2aa032c8ec871ce4d4e03d","css\/ui-lightness\/images\/ui-icons_1c94c4_256x240.png":"dbd693dc8e0ef04e90a2f7ac7b390086","css\/ui-lightness\/images\/ui-icons_F26522_256x240.png":"16278ec0c07270be571f4c2e97fcc10c","css\/ui-lightness\/images\/ui-bg_diagonals-thick_18_b81900_40x40.png":"e460a66d4b3e093fc651e62a236267cb","css\/ui-lightness\/images\/ui-icons_ffffff_256x240.png":"41612b0f4a034424f8321c9f824a94da","css\/ui-lightness\/images\/ui-icons_ffd27a_256x240.png":"dda1b6f694b0d196aefc66a1d6d758f6","images\/actions_right.png":"31c8906bd25d27b83a0a2466bf903462","images\/ac-background.gif":"76135f3697b41a15aed787cfd77776c7","images\/green-square.gif":"16ea9a497d72f5e66e4e8ea9ae08024e","images\/tv-item.gif":"719fe2d4566108e73162fb8868d3778c","images\/tv-collapsable.gif":"63a3351ea0d580797c9b8c386aa4f48b","images\/tv-expandable.gif":"a2d1af4128e4a798a7f3390b12a28574","images\/tv-item-last.gif":"2ae7e1d9972ce71e5caa65a086bc5b7e","images\/tv-collapsable-last.gif":"71acaa9d7c2616e9e8b7131a75ca65da","images\/tv-expandable-last.gif":"9d51036b3a8102742709da66789fd0f7","images\/red-header.gif":"c73b8765f0c8c3c183cb6a0c2bb0ec69","images\/green-header.gif":"0e22a09bb8051b2a274b3427ede62e82","images\/orange-header.gif":"ce1f93f0af64431771b4cbd6c99c567b","images\/calendar.png":"ab56e59af3c96ca661821257d376465e","images\/truncated.png":"c6f91108afe8159d417b4dc556cd3b2a","images\/plus.gif":"f00e1e6e1161f48608bb2bbc79b9948c","images\/minus.gif":"6d77c0c0c2f86b6995d1cdf78274eaab","images\/full-screen.png":"b541fadd3f1563856a4b44aeebd9d563","images\/indicator.gif":"03ce3dcc84af110e9da8699a841e5200","images\/delete.png":"93c047549c31a270a037840277cf59d3","images\/info-mini.png":"445c090ed777c5e6a08ac390fa896193","images\/ok.png":"f6973773335fd83d8d2875f9a3c925af","images\/error.png":"1af8a1041016f67669c5fd22dc88c82e","images\/eye-open-555.png":"9940f4e5b1248042c238e1924359fd5e","images\/eye-closed-555.png":"6ad3b0bae791bf61addc9d8ca80a642d","images\/eye-open-fff.png":"b7db2402d4d5c72314c25790a66150d4","images\/eye-closed-fff.png":"f9be7454dbb47b0e0bca3aa370ae7db5"}} +{"variables":"d751713988987e9331980363e24189ce","stylesheets":{"css-variables":"732f501302c538f594fb3c668d85b46c","jqueryui":"a887ad1c00f29132beba3bf729b981c7","main":"eede8e230764022095bf042e5fed5fec"},"imports":[],"images":{"css\/ui-lightness\/images\/ui-icons_222222_256x240.png":"3a3c5468f484f07ac4a320d9e22acb8c","css\/ui-lightness\/images\/ui-bg_diagonals-thick_20_666666_40x40.png":"4429d568c67d8dfeb9040273ea0fb8c4","css\/ui-lightness\/images\/ui-icons_E87C1E_256x240.png":"7003dd36cb2aa032c8ec871ce4d4e03d","css\/ui-lightness\/images\/ui-icons_1c94c4_256x240.png":"dbd693dc8e0ef04e90a2f7ac7b390086","css\/ui-lightness\/images\/ui-icons_F26522_256x240.png":"16278ec0c07270be571f4c2e97fcc10c","css\/ui-lightness\/images\/ui-bg_diagonals-thick_18_b81900_40x40.png":"e460a66d4b3e093fc651e62a236267cb","css\/ui-lightness\/images\/ui-icons_ffffff_256x240.png":"41612b0f4a034424f8321c9f824a94da","css\/ui-lightness\/images\/ui-icons_ffd27a_256x240.png":"dda1b6f694b0d196aefc66a1d6d758f6","images\/actions_right.png":"31c8906bd25d27b83a0a2466bf903462","images\/ac-background.gif":"76135f3697b41a15aed787cfd77776c7","images\/green-square.gif":"16ea9a497d72f5e66e4e8ea9ae08024e","images\/tv-item.gif":"719fe2d4566108e73162fb8868d3778c","images\/tv-collapsable.gif":"63a3351ea0d580797c9b8c386aa4f48b","images\/tv-expandable.gif":"a2d1af4128e4a798a7f3390b12a28574","images\/tv-item-last.gif":"2ae7e1d9972ce71e5caa65a086bc5b7e","images\/tv-collapsable-last.gif":"71acaa9d7c2616e9e8b7131a75ca65da","images\/tv-expandable-last.gif":"9d51036b3a8102742709da66789fd0f7","images\/red-header.gif":"c73b8765f0c8c3c183cb6a0c2bb0ec69","images\/green-header.gif":"0e22a09bb8051b2a274b3427ede62e82","images\/orange-header.gif":"ce1f93f0af64431771b4cbd6c99c567b","images\/calendar.png":"ab56e59af3c96ca661821257d376465e","images\/truncated.png":"c6f91108afe8159d417b4dc556cd3b2a","images\/plus.gif":"f00e1e6e1161f48608bb2bbc79b9948c","images\/minus.gif":"6d77c0c0c2f86b6995d1cdf78274eaab","images\/full-screen.png":"b541fadd3f1563856a4b44aeebd9d563","images\/indicator.gif":"03ce3dcc84af110e9da8699a841e5200","images\/delete.png":"93c047549c31a270a037840277cf59d3","images\/info-mini.png":"445c090ed777c5e6a08ac390fa896193","images\/ok.png":"f6973773335fd83d8d2875f9a3c925af","images\/error.png":"1af8a1041016f67669c5fd22dc88c82e","images\/eye-open-555.png":"9940f4e5b1248042c238e1924359fd5e","images\/eye-closed-555.png":"6ad3b0bae791bf61addc9d8ca80a642d","images\/eye-open-fff.png":"b7db2402d4d5c72314c25790a66150d4","images\/eye-closed-fff.png":"f9be7454dbb47b0e0bca3aa370ae7db5"}} === SIGNATURE END === */ /*! @@ -99,7 +99,7 @@ background-repeat: no-repeat; width: 16px; height: 16px; - background-image: url("../../../../css/ui-lightness/images/ui-icons_222222_256x240.png?v=1604919410"); + background-image: url("../../../../css/ui-lightness/images/ui-icons_222222_256x240.png?v=1605178543"); filter: hue-rotate(0deg); } .ui-widget-icon-block { @@ -232,7 +232,7 @@ .ui-menu .ui-menu-item { margin: 0; cursor: pointer; - list-style-image: url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7?v=1604919410"); + list-style-image: url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7?v=1605178543"); } .ui-menu .ui-menu-item-wrapper { position: relative; @@ -298,7 +298,7 @@ color: #EA7D1E; } .ui-button:hover .ui-icon { - background-image: url("../../../../css/ui-lightness/images/ui-icons_E87C1E_256x240.png?v=1604919410"); + background-image: url("../../../../css/ui-lightness/images/ui-icons_E87C1E_256x240.png?v=1605178543"); } .ui-button:active { text-decoration: none; @@ -306,20 +306,20 @@ color: #EA7D1E; } .ui-button:active .ui-icon { - background-image: url("../../../../css/ui-lightness/images/ui-icons_E87C1E_256x240.png?v=1604919410"); + background-image: url("../../../../css/ui-lightness/images/ui-icons_E87C1E_256x240.png?v=1605178543"); } .ui-button:focus { font-weight: bold; color: #EA7D1E; } .ui-button:focus .ui-icon { - background-image: url("../../../../css/ui-lightness/images/ui-icons_E87C1E_256x240.png?v=1604919410"); + background-image: url("../../../../css/ui-lightness/images/ui-icons_E87C1E_256x240.png?v=1605178543"); } .ui-button .ui-state-highlight.ui-icon { - background-image: url("../../../../css/ui-lightness/images/ui-icons_1c94c4_256x240.png?v=1604919410"); + background-image: url("../../../../css/ui-lightness/images/ui-icons_1c94c4_256x240.png?v=1605178543"); } .ui-button .ui-icon { - background-image: url("../../../../css/ui-lightness/images/ui-icons_F26522_256x240.png?v=1604919410"); + background-image: url("../../../../css/ui-lightness/images/ui-icons_F26522_256x240.png?v=1605178543"); } .ui-button-icon-only { width: 2em; @@ -901,7 +901,7 @@ body .ui-tooltip { background-image: none; } .ui-widget-content .ui-icon { - background-image: url("../../../../css/ui-lightness/images/ui-icons_222222_256x240.png?v=1604919410"); + background-image: url("../../../../css/ui-lightness/images/ui-icons_222222_256x240.png?v=1605178543"); } .ui-widget-header .ui-priority-secondary { opacity: 0.7; @@ -913,7 +913,7 @@ body .ui-tooltip { background-image: none; } .ui-widget-header .ui-icon { - background-image: url("../../../../css/ui-lightness/images/ui-icons_ffffff_256x240.png?v=1604919410"); + background-image: url("../../../../css/ui-lightness/images/ui-icons_ffffff_256x240.png?v=1605178543"); } .ui-state-default a { text-decoration: none; @@ -925,7 +925,7 @@ body .ui-tooltip { text-decoration: none; } .ui-state-default .ui-icon { - background-image: url("../../../../css/ui-lightness/images/ui-icons_F26522_256x240.png?v=1604919410"); + background-image: url("../../../../css/ui-lightness/images/ui-icons_F26522_256x240.png?v=1605178543"); } a.ui-button { text-decoration: none; @@ -955,7 +955,7 @@ a:visited.ui-button { text-decoration: none; } .ui-state-hover .ui-icon { - background-image: url("../../../../css/ui-lightness/images/ui-icons_E87C1E_256x240.png?v=1604919410"); + background-image: url("../../../../css/ui-lightness/images/ui-icons_E87C1E_256x240.png?v=1605178543"); } .ui-state-focus a { text-decoration: none; @@ -970,7 +970,7 @@ a:visited.ui-button { text-decoration: none; } .ui-state-focus .ui-icon { - background-image: url("../../../../css/ui-lightness/images/ui-icons_E87C1E_256x240.png?v=1604919410"); + background-image: url("../../../../css/ui-lightness/images/ui-icons_E87C1E_256x240.png?v=1605178543"); } .ui-visual-focus { box-shadow: 0 0 3px 1px #5e9ed6; @@ -988,19 +988,19 @@ a:visited.ui-button { text-decoration: none; } .ui-state-active .ui-icon { - background-image: url("../../../../css/ui-lightness/images/ui-icons_E87C1E_256x240.png?v=1604919410"); + background-image: url("../../../../css/ui-lightness/images/ui-icons_E87C1E_256x240.png?v=1605178543"); } .ui-icon-background { background-color: #EA7D1E; } .ui-state-highlight .ui-icon { - background-image: url("../../../../css/ui-lightness/images/ui-icons_1c94c4_256x240.png?v=1604919410"); + background-image: url("../../../../css/ui-lightness/images/ui-icons_1c94c4_256x240.png?v=1605178543"); } .ui-state-error .ui-icon { - background-image: url("../../../../css/ui-lightness/images/ui-icons_ffd27a_256x240.png?v=1604919410"); + background-image: url("../../../../css/ui-lightness/images/ui-icons_ffd27a_256x240.png?v=1605178543"); } .ui-state-error-text .ui-icon { - background-image: url("../../../../css/ui-lightness/images/ui-icons_ffd27a_256x240.png?v=1604919410"); + background-image: url("../../../../css/ui-lightness/images/ui-icons_ffd27a_256x240.png?v=1605178543"); } .ui-priority-primary { font-weight: bold; @@ -1655,7 +1655,7 @@ a:visited.ui-button { visibility: hidden; } #ibo-main-content .edit-image .view-image.dirty.compat, .ui-dialog .edit-image .view-image.dirty.compat { - background-image: url("../../../../css/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png?v=1604919410"); + background-image: url("../../../../css/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png?v=1605178543"); } #ibo-main-content .edit-image .view-image.dirty.compat img, .ui-dialog .edit-image .view-image.dirty.compat img { opacity: 0.3; @@ -1678,7 +1678,7 @@ a:visited.ui-button { opacity: 0.3; } #ibo-main-content .edit-image .edit-buttons .button .ui-icon, .ui-dialog .edit-image .edit-buttons .button .ui-icon { - background-image: url("../../../../css/ui-lightness/images/ui-icons_ffffff_256x240.png?v=1604919410"); + background-image: url("../../../../css/ui-lightness/images/ui-icons_ffffff_256x240.png?v=1605178543"); } #ibo-main-content .edit-image .file-input, .ui-dialog .edit-image .file-input { display: block; @@ -1891,7 +1891,7 @@ a:visited.ui-button { background: #EA7D1E; } #ibo-main-content .actions_details span, .ui-dialog .actions_details span { - background: url("../../../../images/actions_right.png?v=1604919410") no-repeat right; + background: url("../../../../images/actions_right.png?v=1605178543") no-repeat right; color: #fff; font-weight: bold; padding-top: 2px; @@ -1914,7 +1914,7 @@ a:visited.ui-button { } #ibo-main-content .ac_input, .ui-dialog .ac_input { border: 1px solid #7f9db9; - background: #fff url("../../../../images/ac-background.gif?v=1604919410") no-repeat right; + background: #fff url("../../../../images/ac-background.gif?v=1605178543") no-repeat right; /* By Rom */ } #ibo-main-content .csvimport_createobj, .ui-dialog .csvimport_createobj { @@ -1969,7 +1969,7 @@ a:visited.ui-button { noborder-top: 1px solid #8b8b8b; padding: 4px 0px 0px 16px; font-size: 8pt; - background: url("../../../../images/green-square.gif?v=1604919410") no-repeat bottom left; + background: url("../../../../images/green-square.gif?v=1605178543") no-repeat bottom left; color: #83b217; font-weight: bold; text-decoration: none; @@ -2045,22 +2045,22 @@ a:visited.ui-button { margin-top: -8px; } #ibo-main-content .notreeview li, .ui-dialog .notreeview li { - background: url("../../../../images/tv-item.gif?v=1604919410") 0 0 no-repeat; + background: url("../../../../images/tv-item.gif?v=1605178543") 0 0 no-repeat; } #ibo-main-content .notreeview .collapsable, .ui-dialog .notreeview .collapsable { - background-image: url("../../../../images/tv-collapsable.gif?v=1604919410"); + background-image: url("../../../../images/tv-collapsable.gif?v=1605178543"); } #ibo-main-content .notreeview .expandable, .ui-dialog .notreeview .expandable { - background-image: url("../../../../images/tv-expandable.gif?v=1604919410"); + background-image: url("../../../../images/tv-expandable.gif?v=1605178543"); } #ibo-main-content .notreeview .last, .ui-dialog .notreeview .last { - background-image: url("../../../../images/tv-item-last.gif?v=1604919410"); + background-image: url("../../../../images/tv-item-last.gif?v=1605178543"); } #ibo-main-content .notreeview .lastCollapsable, .ui-dialog .notreeview .lastCollapsable { - background-image: url("../../../../images/tv-collapsable-last.gif?v=1604919410"); + background-image: url("../../../../images/tv-collapsable-last.gif?v=1605178543"); } #ibo-main-content .notreeview .lastExpandable, .ui-dialog .notreeview .lastExpandable { - background-image: url("../../../../images/tv-expandable-last.gif?v=1604919410"); + background-image: url("../../../../images/tv-expandable-last.gif?v=1605178543"); } #ibo-main-content #OrganizationSelection, .ui-dialog #OrganizationSelection { padding: 5px 0px 16px 20px; @@ -2235,7 +2235,7 @@ a:visited.ui-button { color: #000; } #ibo-main-content th.red, .ui-dialog th.red { - background: url("../../../../images/red-header.gif?v=1604919410") bottom left repeat-x; + background: url("../../../../images/red-header.gif?v=1605178543") bottom left repeat-x; color: #000; } #ibo-main-content .green, .ui-dialog .green { @@ -2243,7 +2243,7 @@ a:visited.ui-button { color: #000; } #ibo-main-content th.green, .ui-dialog th.green { - background: url("../../../../images/green-header.gif?v=1604919410") bottom left repeat-x; + background: url("../../../../images/green-header.gif?v=1605178543") bottom left repeat-x; color: #000; } #ibo-main-content .orange, .ui-dialog .orange { @@ -2251,7 +2251,7 @@ a:visited.ui-button { color: #000; } #ibo-main-content th.orange, .ui-dialog th.orange { - background: url("../../../../images/orange-header.gif?v=1604919410") bottom left repeat-x; + background: url("../../../../images/orange-header.gif?v=1605178543") bottom left repeat-x; color: #000; /* For Date Picker: Creates a little calendar icon * instead of a text link for "Choose date" @@ -2266,7 +2266,7 @@ a:visited.ui-button { display: block; text-indent: -2000px; overflow: hidden; - background: url("../../../../images/calendar.png?v=1604919410") no-repeat; + background: url("../../../../images/calendar.png?v=1605178543") no-repeat; } #ibo-main-content td a.dp-choose-date.dp-disabled, .ui-dialog td a.dp-choose-date.dp-disabled, #ibo-main-content a.dp-choose-date.dp-disabled, .ui-dialog a.dp-choose-date.dp-disabled { background-position: 0 -20px; @@ -2926,19 +2926,19 @@ a:visited.ui-button { /* Beware: IE6 does not support multiple selector with multiple classes, only the last class is used */ } #ibo-main-content table.listResults tr.odd td.truncated, .ui-dialog table.listResults tr.odd td.truncated, #ibo-main-content table.listResults tr td.truncated, .ui-dialog table.listResults tr td.truncated, #ibo-main-content .wizContainer table.listResults tr.odd td.truncated, .ui-dialog .wizContainer table.listResults tr.odd td.truncated, #ibo-main-content .wizContainer table.listResults tr td.truncated, .ui-dialog .wizContainer table.listResults tr td.truncated { - background: url("../../../../images/truncated.png?v=1604919410") bottom repeat-x; + background: url("../../../../images/truncated.png?v=1605178543") bottom repeat-x; /* Beware: IE6 does not support multiple selector with multiple classes, only the last class is used */ } #ibo-main-content table.listResults tr.even td.truncated, .ui-dialog table.listResults tr.even td.truncated, #ibo-main-content .wizContainer table.listResults tr.even td.truncated, .ui-dialog .wizContainer table.listResults tr.even td.truncated { - background: #f9f9f1 url("../../../../images/truncated.png?v=1604919410") bottom repeat-x; + background: #f9f9f1 url("../../../../images/truncated.png?v=1605178543") bottom repeat-x; /* Beware: IE6 does not support multiple selector with multiple classes, only the last class is used */ } #ibo-main-content table.listResults tr.even td.hover.truncated, .ui-dialog table.listResults tr.even td.hover.truncated, #ibo-main-content .wizContainer table.listResults tr.even td.hover.truncated, .ui-dialog .wizContainer table.listResults tr.even td.hover.truncated { - background: #fdf5d0 url("../../../../images/truncated.png?v=1604919410") bottom repeat-x; + background: #fdf5d0 url("../../../../images/truncated.png?v=1605178543") bottom repeat-x; /* Beware: IE6 does not support multiple selector with multiple classes, only the last class is used */ } #ibo-main-content table.listResults tr.odd td.hover.truncated, .ui-dialog table.listResults tr.odd td.hover.truncated, #ibo-main-content table.listResults tr td.hover.truncated, .ui-dialog table.listResults tr td.hover.truncated, #ibo-main-content .wizContainer table.listResults tr.odd td.hover.truncated, .ui-dialog .wizContainer table.listResults tr.odd td.hover.truncated, #ibo-main-content .wizContainer table.listResults tr td.hover.truncated, .ui-dialog .wizContainer table.listResults tr td.hover.truncated { - background: #fdf5d0 url("../../../../images/truncated.png?v=1604919410") bottom repeat-x; + background: #fdf5d0 url("../../../../images/truncated.png?v=1605178543") bottom repeat-x; } #ibo-main-content table.listResults.truncated, .ui-dialog table.listResults.truncated { border-bottom: 0; @@ -3040,7 +3040,7 @@ a:visited.ui-button { #ibo-main-content div#logo div, .ui-dialog div#logo div { height: 88px; width: 244px; - background: url("../../../../images/itop-logo-2.png?v=1604919410") left no-repeat; + background: url("../../../../images/itop-logo-2.png?v=1605178543") left no-repeat; } #ibo-main-content #left-pane .ui-layout-north, .ui-dialog #left-pane .ui-layout-north { overflow: hidden; @@ -3189,7 +3189,7 @@ a:visited.ui-button { margin: 0 2px; } #ibo-main-content .ui-layout-button-pin-down, .ui-dialog .ui-layout-button-pin-down { - background: url("../../../../images/splitter-bkg.png?v=1604919410") transparent; + background: url("../../../../images/splitter-bkg.png?v=1605178543") transparent; width: 16px; background-position: -144px -144px; } @@ -3326,13 +3326,13 @@ a:visited.ui-button { #ibo-main-content .caselog_header, .ui-dialog .caselog_header { padding: 3px; border-top: 1px solid #fff; - background: #ddd url("../../../../images/plus.gif?v=1604919410") left no-repeat; + background: #ddd url("../../../../images/plus.gif?v=1605178543") left no-repeat; padding-left: 16px; cursor: pointer; width: 100%; } #ibo-main-content .caselog_header.open, .ui-dialog .caselog_header.open { - background: #ddd url("../../../../images/minus.gif?v=1604919410") left no-repeat; + background: #ddd url("../../../../images/minus.gif?v=1605178543") left no-repeat; } #ibo-main-content .caselog_entry, .ui-dialog .caselog_entry, #ibo-main-content .caselog_entry_html, .ui-dialog .caselog_entry_html { overflow-x: auto; @@ -3508,7 +3508,7 @@ a:visited.ui-button { height: 15px; border: 1px #A6A6A6 solid; cursor: pointer; - background-image: url("../../../../images/full-screen.png?v=1604919410"); + background-image: url("../../../../images/full-screen.png?v=1605178543"); background-repeat: no-repeat; background-position: center center; background-size: 98%; @@ -3555,7 +3555,7 @@ a:visited.ui-button { padding: 2px; } #ibo-main-content .field_container > div > div.field_value .attribute-edit .field_input_zone.field_input_document .button .ui-icon, .ui-dialog .field_container > div > div.field_value .attribute-edit .field_input_zone.field_input_document .button .ui-icon { - background-image: url("../../../../css/ui-lightness/images/ui-icons_ffffff_256x240.png?v=1604919410"); + background-image: url("../../../../css/ui-lightness/images/ui-icons_ffffff_256x240.png?v=1605178543"); background-color: #EA7D1E; } #ibo-main-content .field_container > div > div.field_value .attribute-edit .field_input_zone.field_input_image input, .ui-dialog .field_container > div > div.field_value .attribute-edit .field_input_zone.field_input_image input { @@ -3577,7 +3577,6 @@ a:visited.ui-button { width: 100%; } #ibo-main-content .field_container > div > div.field_value .attribute-edit .field_input_zone.field_input_extkey > .field_input_btn, .ui-dialog .field_container > div > div.field_value .attribute-edit .field_input_zone.field_input_extkey > .field_input_btn { - display: table-cell; width: 25px; padding-left: 0.4em; } @@ -3622,7 +3621,7 @@ a:visited.ui-button { height: 15px; border: 1px #A6A6A6 solid; cursor: pointer; - background-image: url("../../../../images/full-screen.png?v=1604919410"); + background-image: url("../../../../images/full-screen.png?v=1605178543"); background-repeat: no-repeat; background-position: center center; background-size: 98%; @@ -3687,7 +3686,7 @@ a:visited.ui-button { padding-left: 0.4em; } #ibo-main-content .ac_dlg_loading, .ui-dialog .ac_dlg_loading { - background: white url("../../../../images/indicator.gif?v=1604919410") right center no-repeat; + background: white url("../../../../images/indicator.gif?v=1605178543") right center no-repeat; } #ibo-main-content table.pagination, .ui-dialog table.pagination { display: inline-block; @@ -3754,10 +3753,10 @@ a:visited.ui-button { cursor: not-allowed; } #ibo-main-content .dragHover, .ui-dialog .dragHover { - background: url("../../../../css/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png?v=1604919410"); + background: url("../../../../css/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png?v=1605178543"); } #ibo-main-content .edit_mode .dashlet, .ui-dialog .edit_mode .dashlet { - background: url("../../../../css/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png?v=1604919410"); + background: url("../../../../css/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png?v=1605178543"); padding: 5px; margin: 0; position: relative; @@ -3802,7 +3801,7 @@ a:visited.ui-button { top: 0; right: 0; z-index: 10; - background: transparent url("../../../../images/delete.png?v=1604919410") no-repeat center; + background: transparent url("../../../../images/delete.png?v=1605178543") no-repeat center; } #ibo-main-content td.prop_value, .ui-dialog td.prop_value { text-align: left; @@ -4031,23 +4030,23 @@ a:visited.ui-button { } #ibo-main-content .message_info, .ui-dialog .message_info { border: 1px solid #993; - background: url("../../../../images/info-mini.png?v=1604919410") 1em 1em no-repeat #ffc; + background: url("../../../../images/info-mini.png?v=1605178543") 1em 1em no-repeat #ffc; padding-left: 3em; } #ibo-main-content .message_ok, .ui-dialog .message_ok { border: 1px solid #393; - background: url("../../../../images/ok.png?v=1604919410") 1em 1em no-repeat #cfc; + background: url("../../../../images/ok.png?v=1605178543") 1em 1em no-repeat #cfc; padding-left: 3em; } #ibo-main-content .message_warning, .ui-dialog .message_warning { border: 1px solid #ec9800; - background: url("../../../../images/error.png?v=1604919410") 1em 1em no-repeat #ffd78d; + background: url("../../../../images/error.png?v=1605178543") 1em 1em no-repeat #ffd78d; color: #000; padding-left: 3em; } #ibo-main-content .message_error, .ui-dialog .message_error { border: 1px solid #933; - background: url("../../../../images/error.png?v=1604919410") 1em 1em no-repeat #fcc; + background: url("../../../../images/error.png?v=1605178543") 1em 1em no-repeat #fcc; padding-left: 3em; } #ibo-main-content .fg-menu a img, .ui-dialog .fg-menu a img { @@ -4178,18 +4177,18 @@ a:visited.ui-button { } #ibo-main-content #hiddeable_chapters .ui-tabs .ui-tabs-nav li.hideable-chapter span, .ui-dialog #hiddeable_chapters .ui-tabs .ui-tabs-nav li.hideable-chapter span { padding-left: 20px; - background: url("../../../../images/eye-open-555.png?v=1604919410") 2px center no-repeat; + background: url("../../../../images/eye-open-555.png?v=1605178543") 2px center no-repeat; } #ibo-main-content #hiddeable_chapters .ui-tabs .ui-tabs-nav li.hideable-chapter.strikethrough span, .ui-dialog #hiddeable_chapters .ui-tabs .ui-tabs-nav li.hideable-chapter.strikethrough span { text-decoration: line-through; - background: url("../../../../images/eye-closed-555.png?v=1604919410") 2px center no-repeat; + background: url("../../../../images/eye-closed-555.png?v=1605178543") 2px center no-repeat; } #ibo-main-content .printable-version legend, .ui-dialog .printable-version legend { padding-left: 26px; - background: #1c94c4 url("../../../../images/eye-open-fff.png?v=1604919410") 8px center no-repeat; + background: #1c94c4 url("../../../../images/eye-open-fff.png?v=1605178543") 8px center no-repeat; } #ibo-main-content .printable-version .strikethrough legend, .ui-dialog .printable-version .strikethrough legend { - background: #1c94c4 url("../../../../images/eye-closed-fff.png?v=1604919410") 8px center no-repeat; + background: #1c94c4 url("../../../../images/eye-closed-fff.png?v=1605178543") 8px center no-repeat; } #ibo-main-content .printable-version fieldset.strikethrough span, .ui-dialog .printable-version fieldset.strikethrough span { display: none; @@ -4262,7 +4261,7 @@ a:visited.ui-button { cursor: pointer; width: 16px; height: 16px; - background-image: url("../../../../css/ui-lightness/images/ui-icons_222222_256x240.png?v=1604919410"); + background-image: url("../../../../css/ui-lightness/images/ui-icons_222222_256x240.png?v=1605178543"); background-position: -16px -192px; } #ibo-main-content .history_entry_truncated .history_truncated_toggler, .ui-dialog .history_entry_truncated .history_truncated_toggler { @@ -4347,7 +4346,7 @@ a:visited.ui-button { #ibo-main-content #itop-breadcrumb .breadcrumb-item a::after, .ui-dialog #itop-breadcrumb .breadcrumb-item a::after { content: ''; position: absolute; - background-image: url("../../../../images/breadcrumb-separator.png?v=1604919410"); + background-image: url("../../../../images/breadcrumb-separator.png?v=1605178543"); background-repeat: no-repeat; width: 8px; height: 16px; diff --git a/datamodels/2.x/itop-structure/precompiled-themes/test-red/main.css b/datamodels/2.x/itop-structure/precompiled-themes/test-red/main.css index cbdd0c6de..db4913781 100644 --- a/datamodels/2.x/itop-structure/precompiled-themes/test-red/main.css +++ b/datamodels/2.x/itop-structure/precompiled-themes/test-red/main.css @@ -1,6 +1,6 @@ /* === SIGNATURE BEGIN === -{"variables":"8cfe86f2c55d8eff36d57eb4e83d89f1","stylesheets":{"css-variables":"732f501302c538f594fb3c668d85b46c","jqueryui":"a887ad1c00f29132beba3bf729b981c7","main":"0efa2620e936b99f9e2ad32088636b33","environment-banner":"3de3ffb8232b9a649e912b570a64bf5d"},"imports":[],"images":{"css\/ui-lightness\/images\/ui-icons_222222_256x240.png":"3a3c5468f484f07ac4a320d9e22acb8c","css\/ui-lightness\/images\/ui-bg_diagonals-thick_20_666666_40x40.png":"4429d568c67d8dfeb9040273ea0fb8c4","css\/ui-lightness\/images\/ui-icons_E87C1E_256x240.png":"7003dd36cb2aa032c8ec871ce4d4e03d","css\/ui-lightness\/images\/ui-icons_1c94c4_256x240.png":"dbd693dc8e0ef04e90a2f7ac7b390086","css\/ui-lightness\/images\/ui-icons_F26522_256x240.png":"16278ec0c07270be571f4c2e97fcc10c","css\/ui-lightness\/images\/ui-bg_diagonals-thick_18_b81900_40x40.png":"e460a66d4b3e093fc651e62a236267cb","css\/ui-lightness\/images\/ui-icons_ffffff_256x240.png":"41612b0f4a034424f8321c9f824a94da","css\/ui-lightness\/images\/ui-icons_ffd27a_256x240.png":"dda1b6f694b0d196aefc66a1d6d758f6","images\/actions_right.png":"31c8906bd25d27b83a0a2466bf903462","images\/ac-background.gif":"76135f3697b41a15aed787cfd77776c7","images\/green-square.gif":"16ea9a497d72f5e66e4e8ea9ae08024e","images\/tv-item.gif":"719fe2d4566108e73162fb8868d3778c","images\/tv-collapsable.gif":"63a3351ea0d580797c9b8c386aa4f48b","images\/tv-expandable.gif":"a2d1af4128e4a798a7f3390b12a28574","images\/tv-item-last.gif":"2ae7e1d9972ce71e5caa65a086bc5b7e","images\/tv-collapsable-last.gif":"71acaa9d7c2616e9e8b7131a75ca65da","images\/tv-expandable-last.gif":"9d51036b3a8102742709da66789fd0f7","images\/red-header.gif":"c73b8765f0c8c3c183cb6a0c2bb0ec69","images\/green-header.gif":"0e22a09bb8051b2a274b3427ede62e82","images\/orange-header.gif":"ce1f93f0af64431771b4cbd6c99c567b","images\/calendar.png":"ab56e59af3c96ca661821257d376465e","images\/truncated.png":"c6f91108afe8159d417b4dc556cd3b2a","images\/plus.gif":"f00e1e6e1161f48608bb2bbc79b9948c","images\/minus.gif":"6d77c0c0c2f86b6995d1cdf78274eaab","images\/full-screen.png":"b541fadd3f1563856a4b44aeebd9d563","images\/indicator.gif":"03ce3dcc84af110e9da8699a841e5200","images\/delete.png":"93c047549c31a270a037840277cf59d3","images\/info-mini.png":"445c090ed777c5e6a08ac390fa896193","images\/ok.png":"f6973773335fd83d8d2875f9a3c925af","images\/error.png":"1af8a1041016f67669c5fd22dc88c82e","images\/eye-open-555.png":"9940f4e5b1248042c238e1924359fd5e","images\/eye-closed-555.png":"6ad3b0bae791bf61addc9d8ca80a642d","images\/eye-open-fff.png":"b7db2402d4d5c72314c25790a66150d4","images\/eye-closed-fff.png":"f9be7454dbb47b0e0bca3aa370ae7db5"}} +{"variables":"8cfe86f2c55d8eff36d57eb4e83d89f1","stylesheets":{"css-variables":"732f501302c538f594fb3c668d85b46c","jqueryui":"a887ad1c00f29132beba3bf729b981c7","main":"eede8e230764022095bf042e5fed5fec","environment-banner":"3de3ffb8232b9a649e912b570a64bf5d"},"imports":[],"images":{"css\/ui-lightness\/images\/ui-icons_222222_256x240.png":"3a3c5468f484f07ac4a320d9e22acb8c","css\/ui-lightness\/images\/ui-bg_diagonals-thick_20_666666_40x40.png":"4429d568c67d8dfeb9040273ea0fb8c4","css\/ui-lightness\/images\/ui-icons_E87C1E_256x240.png":"7003dd36cb2aa032c8ec871ce4d4e03d","css\/ui-lightness\/images\/ui-icons_1c94c4_256x240.png":"dbd693dc8e0ef04e90a2f7ac7b390086","css\/ui-lightness\/images\/ui-icons_F26522_256x240.png":"16278ec0c07270be571f4c2e97fcc10c","css\/ui-lightness\/images\/ui-bg_diagonals-thick_18_b81900_40x40.png":"e460a66d4b3e093fc651e62a236267cb","css\/ui-lightness\/images\/ui-icons_ffffff_256x240.png":"41612b0f4a034424f8321c9f824a94da","css\/ui-lightness\/images\/ui-icons_ffd27a_256x240.png":"dda1b6f694b0d196aefc66a1d6d758f6","images\/actions_right.png":"31c8906bd25d27b83a0a2466bf903462","images\/ac-background.gif":"76135f3697b41a15aed787cfd77776c7","images\/green-square.gif":"16ea9a497d72f5e66e4e8ea9ae08024e","images\/tv-item.gif":"719fe2d4566108e73162fb8868d3778c","images\/tv-collapsable.gif":"63a3351ea0d580797c9b8c386aa4f48b","images\/tv-expandable.gif":"a2d1af4128e4a798a7f3390b12a28574","images\/tv-item-last.gif":"2ae7e1d9972ce71e5caa65a086bc5b7e","images\/tv-collapsable-last.gif":"71acaa9d7c2616e9e8b7131a75ca65da","images\/tv-expandable-last.gif":"9d51036b3a8102742709da66789fd0f7","images\/red-header.gif":"c73b8765f0c8c3c183cb6a0c2bb0ec69","images\/green-header.gif":"0e22a09bb8051b2a274b3427ede62e82","images\/orange-header.gif":"ce1f93f0af64431771b4cbd6c99c567b","images\/calendar.png":"ab56e59af3c96ca661821257d376465e","images\/truncated.png":"c6f91108afe8159d417b4dc556cd3b2a","images\/plus.gif":"f00e1e6e1161f48608bb2bbc79b9948c","images\/minus.gif":"6d77c0c0c2f86b6995d1cdf78274eaab","images\/full-screen.png":"b541fadd3f1563856a4b44aeebd9d563","images\/indicator.gif":"03ce3dcc84af110e9da8699a841e5200","images\/delete.png":"93c047549c31a270a037840277cf59d3","images\/info-mini.png":"445c090ed777c5e6a08ac390fa896193","images\/ok.png":"f6973773335fd83d8d2875f9a3c925af","images\/error.png":"1af8a1041016f67669c5fd22dc88c82e","images\/eye-open-555.png":"9940f4e5b1248042c238e1924359fd5e","images\/eye-closed-555.png":"6ad3b0bae791bf61addc9d8ca80a642d","images\/eye-open-fff.png":"b7db2402d4d5c72314c25790a66150d4","images\/eye-closed-fff.png":"f9be7454dbb47b0e0bca3aa370ae7db5"}} === SIGNATURE END === */ /*! @@ -99,7 +99,7 @@ background-repeat: no-repeat; width: 16px; height: 16px; - background-image: url("../../../../css/ui-lightness/images/ui-icons_222222_256x240.png?v=1604919410"); + background-image: url("../../../../css/ui-lightness/images/ui-icons_222222_256x240.png?v=1605178543"); filter: hue-rotate(0deg); } .ui-widget-icon-block { @@ -232,7 +232,7 @@ .ui-menu .ui-menu-item { margin: 0; cursor: pointer; - list-style-image: url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7?v=1604919410"); + list-style-image: url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7?v=1605178543"); } .ui-menu .ui-menu-item-wrapper { position: relative; @@ -298,7 +298,7 @@ color: #EA7D1E; } .ui-button:hover .ui-icon { - background-image: url("../../../../css/ui-lightness/images/ui-icons_E87C1E_256x240.png?v=1604919410"); + background-image: url("../../../../css/ui-lightness/images/ui-icons_E87C1E_256x240.png?v=1605178543"); } .ui-button:active { text-decoration: none; @@ -306,20 +306,20 @@ color: #EA7D1E; } .ui-button:active .ui-icon { - background-image: url("../../../../css/ui-lightness/images/ui-icons_E87C1E_256x240.png?v=1604919410"); + background-image: url("../../../../css/ui-lightness/images/ui-icons_E87C1E_256x240.png?v=1605178543"); } .ui-button:focus { font-weight: bold; color: #EA7D1E; } .ui-button:focus .ui-icon { - background-image: url("../../../../css/ui-lightness/images/ui-icons_E87C1E_256x240.png?v=1604919410"); + background-image: url("../../../../css/ui-lightness/images/ui-icons_E87C1E_256x240.png?v=1605178543"); } .ui-button .ui-state-highlight.ui-icon { - background-image: url("../../../../css/ui-lightness/images/ui-icons_1c94c4_256x240.png?v=1604919410"); + background-image: url("../../../../css/ui-lightness/images/ui-icons_1c94c4_256x240.png?v=1605178543"); } .ui-button .ui-icon { - background-image: url("../../../../css/ui-lightness/images/ui-icons_F26522_256x240.png?v=1604919410"); + background-image: url("../../../../css/ui-lightness/images/ui-icons_F26522_256x240.png?v=1605178543"); } .ui-button-icon-only { width: 2em; @@ -901,7 +901,7 @@ body .ui-tooltip { background-image: none; } .ui-widget-content .ui-icon { - background-image: url("../../../../css/ui-lightness/images/ui-icons_222222_256x240.png?v=1604919410"); + background-image: url("../../../../css/ui-lightness/images/ui-icons_222222_256x240.png?v=1605178543"); } .ui-widget-header .ui-priority-secondary { opacity: 0.7; @@ -913,7 +913,7 @@ body .ui-tooltip { background-image: none; } .ui-widget-header .ui-icon { - background-image: url("../../../../css/ui-lightness/images/ui-icons_ffffff_256x240.png?v=1604919410"); + background-image: url("../../../../css/ui-lightness/images/ui-icons_ffffff_256x240.png?v=1605178543"); } .ui-state-default a { text-decoration: none; @@ -925,7 +925,7 @@ body .ui-tooltip { text-decoration: none; } .ui-state-default .ui-icon { - background-image: url("../../../../css/ui-lightness/images/ui-icons_F26522_256x240.png?v=1604919410"); + background-image: url("../../../../css/ui-lightness/images/ui-icons_F26522_256x240.png?v=1605178543"); } a.ui-button { text-decoration: none; @@ -955,7 +955,7 @@ a:visited.ui-button { text-decoration: none; } .ui-state-hover .ui-icon { - background-image: url("../../../../css/ui-lightness/images/ui-icons_E87C1E_256x240.png?v=1604919410"); + background-image: url("../../../../css/ui-lightness/images/ui-icons_E87C1E_256x240.png?v=1605178543"); } .ui-state-focus a { text-decoration: none; @@ -970,7 +970,7 @@ a:visited.ui-button { text-decoration: none; } .ui-state-focus .ui-icon { - background-image: url("../../../../css/ui-lightness/images/ui-icons_E87C1E_256x240.png?v=1604919410"); + background-image: url("../../../../css/ui-lightness/images/ui-icons_E87C1E_256x240.png?v=1605178543"); } .ui-visual-focus { box-shadow: 0 0 3px 1px #5e9ed6; @@ -988,19 +988,19 @@ a:visited.ui-button { text-decoration: none; } .ui-state-active .ui-icon { - background-image: url("../../../../css/ui-lightness/images/ui-icons_E87C1E_256x240.png?v=1604919410"); + background-image: url("../../../../css/ui-lightness/images/ui-icons_E87C1E_256x240.png?v=1605178543"); } .ui-icon-background { background-color: #EA7D1E; } .ui-state-highlight .ui-icon { - background-image: url("../../../../css/ui-lightness/images/ui-icons_1c94c4_256x240.png?v=1604919410"); + background-image: url("../../../../css/ui-lightness/images/ui-icons_1c94c4_256x240.png?v=1605178543"); } .ui-state-error .ui-icon { - background-image: url("../../../../css/ui-lightness/images/ui-icons_ffd27a_256x240.png?v=1604919410"); + background-image: url("../../../../css/ui-lightness/images/ui-icons_ffd27a_256x240.png?v=1605178543"); } .ui-state-error-text .ui-icon { - background-image: url("../../../../css/ui-lightness/images/ui-icons_ffd27a_256x240.png?v=1604919410"); + background-image: url("../../../../css/ui-lightness/images/ui-icons_ffd27a_256x240.png?v=1605178543"); } .ui-priority-primary { font-weight: bold; @@ -1655,7 +1655,7 @@ a:visited.ui-button { visibility: hidden; } #ibo-main-content .edit-image .view-image.dirty.compat, .ui-dialog .edit-image .view-image.dirty.compat { - background-image: url("../../../../css/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png?v=1604919410"); + background-image: url("../../../../css/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png?v=1605178543"); } #ibo-main-content .edit-image .view-image.dirty.compat img, .ui-dialog .edit-image .view-image.dirty.compat img { opacity: 0.3; @@ -1678,7 +1678,7 @@ a:visited.ui-button { opacity: 0.3; } #ibo-main-content .edit-image .edit-buttons .button .ui-icon, .ui-dialog .edit-image .edit-buttons .button .ui-icon { - background-image: url("../../../../css/ui-lightness/images/ui-icons_ffffff_256x240.png?v=1604919410"); + background-image: url("../../../../css/ui-lightness/images/ui-icons_ffffff_256x240.png?v=1605178543"); } #ibo-main-content .edit-image .file-input, .ui-dialog .edit-image .file-input { display: block; @@ -1891,7 +1891,7 @@ a:visited.ui-button { background: #EA7D1E; } #ibo-main-content .actions_details span, .ui-dialog .actions_details span { - background: url("../../../../images/actions_right.png?v=1604919410") no-repeat right; + background: url("../../../../images/actions_right.png?v=1605178543") no-repeat right; color: #fff; font-weight: bold; padding-top: 2px; @@ -1914,7 +1914,7 @@ a:visited.ui-button { } #ibo-main-content .ac_input, .ui-dialog .ac_input { border: 1px solid #7f9db9; - background: #fff url("../../../../images/ac-background.gif?v=1604919410") no-repeat right; + background: #fff url("../../../../images/ac-background.gif?v=1605178543") no-repeat right; /* By Rom */ } #ibo-main-content .csvimport_createobj, .ui-dialog .csvimport_createobj { @@ -1969,7 +1969,7 @@ a:visited.ui-button { noborder-top: 1px solid #8b8b8b; padding: 4px 0px 0px 16px; font-size: 8pt; - background: url("../../../../images/green-square.gif?v=1604919410") no-repeat bottom left; + background: url("../../../../images/green-square.gif?v=1605178543") no-repeat bottom left; color: #83b217; font-weight: bold; text-decoration: none; @@ -2045,22 +2045,22 @@ a:visited.ui-button { margin-top: -8px; } #ibo-main-content .notreeview li, .ui-dialog .notreeview li { - background: url("../../../../images/tv-item.gif?v=1604919410") 0 0 no-repeat; + background: url("../../../../images/tv-item.gif?v=1605178543") 0 0 no-repeat; } #ibo-main-content .notreeview .collapsable, .ui-dialog .notreeview .collapsable { - background-image: url("../../../../images/tv-collapsable.gif?v=1604919410"); + background-image: url("../../../../images/tv-collapsable.gif?v=1605178543"); } #ibo-main-content .notreeview .expandable, .ui-dialog .notreeview .expandable { - background-image: url("../../../../images/tv-expandable.gif?v=1604919410"); + background-image: url("../../../../images/tv-expandable.gif?v=1605178543"); } #ibo-main-content .notreeview .last, .ui-dialog .notreeview .last { - background-image: url("../../../../images/tv-item-last.gif?v=1604919410"); + background-image: url("../../../../images/tv-item-last.gif?v=1605178543"); } #ibo-main-content .notreeview .lastCollapsable, .ui-dialog .notreeview .lastCollapsable { - background-image: url("../../../../images/tv-collapsable-last.gif?v=1604919410"); + background-image: url("../../../../images/tv-collapsable-last.gif?v=1605178543"); } #ibo-main-content .notreeview .lastExpandable, .ui-dialog .notreeview .lastExpandable { - background-image: url("../../../../images/tv-expandable-last.gif?v=1604919410"); + background-image: url("../../../../images/tv-expandable-last.gif?v=1605178543"); } #ibo-main-content #OrganizationSelection, .ui-dialog #OrganizationSelection { padding: 5px 0px 16px 20px; @@ -2235,7 +2235,7 @@ a:visited.ui-button { color: #000; } #ibo-main-content th.red, .ui-dialog th.red { - background: url("../../../../images/red-header.gif?v=1604919410") bottom left repeat-x; + background: url("../../../../images/red-header.gif?v=1605178543") bottom left repeat-x; color: #000; } #ibo-main-content .green, .ui-dialog .green { @@ -2243,7 +2243,7 @@ a:visited.ui-button { color: #000; } #ibo-main-content th.green, .ui-dialog th.green { - background: url("../../../../images/green-header.gif?v=1604919410") bottom left repeat-x; + background: url("../../../../images/green-header.gif?v=1605178543") bottom left repeat-x; color: #000; } #ibo-main-content .orange, .ui-dialog .orange { @@ -2251,7 +2251,7 @@ a:visited.ui-button { color: #000; } #ibo-main-content th.orange, .ui-dialog th.orange { - background: url("../../../../images/orange-header.gif?v=1604919410") bottom left repeat-x; + background: url("../../../../images/orange-header.gif?v=1605178543") bottom left repeat-x; color: #000; /* For Date Picker: Creates a little calendar icon * instead of a text link for "Choose date" @@ -2266,7 +2266,7 @@ a:visited.ui-button { display: block; text-indent: -2000px; overflow: hidden; - background: url("../../../../images/calendar.png?v=1604919410") no-repeat; + background: url("../../../../images/calendar.png?v=1605178543") no-repeat; } #ibo-main-content td a.dp-choose-date.dp-disabled, .ui-dialog td a.dp-choose-date.dp-disabled, #ibo-main-content a.dp-choose-date.dp-disabled, .ui-dialog a.dp-choose-date.dp-disabled { background-position: 0 -20px; @@ -2926,19 +2926,19 @@ a:visited.ui-button { /* Beware: IE6 does not support multiple selector with multiple classes, only the last class is used */ } #ibo-main-content table.listResults tr.odd td.truncated, .ui-dialog table.listResults tr.odd td.truncated, #ibo-main-content table.listResults tr td.truncated, .ui-dialog table.listResults tr td.truncated, #ibo-main-content .wizContainer table.listResults tr.odd td.truncated, .ui-dialog .wizContainer table.listResults tr.odd td.truncated, #ibo-main-content .wizContainer table.listResults tr td.truncated, .ui-dialog .wizContainer table.listResults tr td.truncated { - background: url("../../../../images/truncated.png?v=1604919410") bottom repeat-x; + background: url("../../../../images/truncated.png?v=1605178543") bottom repeat-x; /* Beware: IE6 does not support multiple selector with multiple classes, only the last class is used */ } #ibo-main-content table.listResults tr.even td.truncated, .ui-dialog table.listResults tr.even td.truncated, #ibo-main-content .wizContainer table.listResults tr.even td.truncated, .ui-dialog .wizContainer table.listResults tr.even td.truncated { - background: #f9f9f1 url("../../../../images/truncated.png?v=1604919410") bottom repeat-x; + background: #f9f9f1 url("../../../../images/truncated.png?v=1605178543") bottom repeat-x; /* Beware: IE6 does not support multiple selector with multiple classes, only the last class is used */ } #ibo-main-content table.listResults tr.even td.hover.truncated, .ui-dialog table.listResults tr.even td.hover.truncated, #ibo-main-content .wizContainer table.listResults tr.even td.hover.truncated, .ui-dialog .wizContainer table.listResults tr.even td.hover.truncated { - background: #fdf5d0 url("../../../../images/truncated.png?v=1604919410") bottom repeat-x; + background: #fdf5d0 url("../../../../images/truncated.png?v=1605178543") bottom repeat-x; /* Beware: IE6 does not support multiple selector with multiple classes, only the last class is used */ } #ibo-main-content table.listResults tr.odd td.hover.truncated, .ui-dialog table.listResults tr.odd td.hover.truncated, #ibo-main-content table.listResults tr td.hover.truncated, .ui-dialog table.listResults tr td.hover.truncated, #ibo-main-content .wizContainer table.listResults tr.odd td.hover.truncated, .ui-dialog .wizContainer table.listResults tr.odd td.hover.truncated, #ibo-main-content .wizContainer table.listResults tr td.hover.truncated, .ui-dialog .wizContainer table.listResults tr td.hover.truncated { - background: #fdf5d0 url("../../../../images/truncated.png?v=1604919410") bottom repeat-x; + background: #fdf5d0 url("../../../../images/truncated.png?v=1605178543") bottom repeat-x; } #ibo-main-content table.listResults.truncated, .ui-dialog table.listResults.truncated { border-bottom: 0; @@ -3040,7 +3040,7 @@ a:visited.ui-button { #ibo-main-content div#logo div, .ui-dialog div#logo div { height: 88px; width: 244px; - background: url("../../../../images/itop-logo-2.png?v=1604919410") left no-repeat; + background: url("../../../../images/itop-logo-2.png?v=1605178543") left no-repeat; } #ibo-main-content #left-pane .ui-layout-north, .ui-dialog #left-pane .ui-layout-north { overflow: hidden; @@ -3189,7 +3189,7 @@ a:visited.ui-button { margin: 0 2px; } #ibo-main-content .ui-layout-button-pin-down, .ui-dialog .ui-layout-button-pin-down { - background: url("../../../../images/splitter-bkg.png?v=1604919410") transparent; + background: url("../../../../images/splitter-bkg.png?v=1605178543") transparent; width: 16px; background-position: -144px -144px; } @@ -3326,13 +3326,13 @@ a:visited.ui-button { #ibo-main-content .caselog_header, .ui-dialog .caselog_header { padding: 3px; border-top: 1px solid #fff; - background: #ddd url("../../../../images/plus.gif?v=1604919410") left no-repeat; + background: #ddd url("../../../../images/plus.gif?v=1605178543") left no-repeat; padding-left: 16px; cursor: pointer; width: 100%; } #ibo-main-content .caselog_header.open, .ui-dialog .caselog_header.open { - background: #ddd url("../../../../images/minus.gif?v=1604919410") left no-repeat; + background: #ddd url("../../../../images/minus.gif?v=1605178543") left no-repeat; } #ibo-main-content .caselog_entry, .ui-dialog .caselog_entry, #ibo-main-content .caselog_entry_html, .ui-dialog .caselog_entry_html { overflow-x: auto; @@ -3508,7 +3508,7 @@ a:visited.ui-button { height: 15px; border: 1px #A6A6A6 solid; cursor: pointer; - background-image: url("../../../../images/full-screen.png?v=1604919410"); + background-image: url("../../../../images/full-screen.png?v=1605178543"); background-repeat: no-repeat; background-position: center center; background-size: 98%; @@ -3555,7 +3555,7 @@ a:visited.ui-button { padding: 2px; } #ibo-main-content .field_container > div > div.field_value .attribute-edit .field_input_zone.field_input_document .button .ui-icon, .ui-dialog .field_container > div > div.field_value .attribute-edit .field_input_zone.field_input_document .button .ui-icon { - background-image: url("../../../../css/ui-lightness/images/ui-icons_ffffff_256x240.png?v=1604919410"); + background-image: url("../../../../css/ui-lightness/images/ui-icons_ffffff_256x240.png?v=1605178543"); background-color: #EA7D1E; } #ibo-main-content .field_container > div > div.field_value .attribute-edit .field_input_zone.field_input_image input, .ui-dialog .field_container > div > div.field_value .attribute-edit .field_input_zone.field_input_image input { @@ -3577,7 +3577,6 @@ a:visited.ui-button { width: 100%; } #ibo-main-content .field_container > div > div.field_value .attribute-edit .field_input_zone.field_input_extkey > .field_input_btn, .ui-dialog .field_container > div > div.field_value .attribute-edit .field_input_zone.field_input_extkey > .field_input_btn { - display: table-cell; width: 25px; padding-left: 0.4em; } @@ -3622,7 +3621,7 @@ a:visited.ui-button { height: 15px; border: 1px #A6A6A6 solid; cursor: pointer; - background-image: url("../../../../images/full-screen.png?v=1604919410"); + background-image: url("../../../../images/full-screen.png?v=1605178543"); background-repeat: no-repeat; background-position: center center; background-size: 98%; @@ -3687,7 +3686,7 @@ a:visited.ui-button { padding-left: 0.4em; } #ibo-main-content .ac_dlg_loading, .ui-dialog .ac_dlg_loading { - background: white url("../../../../images/indicator.gif?v=1604919410") right center no-repeat; + background: white url("../../../../images/indicator.gif?v=1605178543") right center no-repeat; } #ibo-main-content table.pagination, .ui-dialog table.pagination { display: inline-block; @@ -3754,10 +3753,10 @@ a:visited.ui-button { cursor: not-allowed; } #ibo-main-content .dragHover, .ui-dialog .dragHover { - background: url("../../../../css/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png?v=1604919410"); + background: url("../../../../css/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png?v=1605178543"); } #ibo-main-content .edit_mode .dashlet, .ui-dialog .edit_mode .dashlet { - background: url("../../../../css/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png?v=1604919410"); + background: url("../../../../css/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png?v=1605178543"); padding: 5px; margin: 0; position: relative; @@ -3802,7 +3801,7 @@ a:visited.ui-button { top: 0; right: 0; z-index: 10; - background: transparent url("../../../../images/delete.png?v=1604919410") no-repeat center; + background: transparent url("../../../../images/delete.png?v=1605178543") no-repeat center; } #ibo-main-content td.prop_value, .ui-dialog td.prop_value { text-align: left; @@ -4031,23 +4030,23 @@ a:visited.ui-button { } #ibo-main-content .message_info, .ui-dialog .message_info { border: 1px solid #993; - background: url("../../../../images/info-mini.png?v=1604919410") 1em 1em no-repeat #ffc; + background: url("../../../../images/info-mini.png?v=1605178543") 1em 1em no-repeat #ffc; padding-left: 3em; } #ibo-main-content .message_ok, .ui-dialog .message_ok { border: 1px solid #393; - background: url("../../../../images/ok.png?v=1604919410") 1em 1em no-repeat #cfc; + background: url("../../../../images/ok.png?v=1605178543") 1em 1em no-repeat #cfc; padding-left: 3em; } #ibo-main-content .message_warning, .ui-dialog .message_warning { border: 1px solid #ec9800; - background: url("../../../../images/error.png?v=1604919410") 1em 1em no-repeat #ffd78d; + background: url("../../../../images/error.png?v=1605178543") 1em 1em no-repeat #ffd78d; color: #000; padding-left: 3em; } #ibo-main-content .message_error, .ui-dialog .message_error { border: 1px solid #933; - background: url("../../../../images/error.png?v=1604919410") 1em 1em no-repeat #fcc; + background: url("../../../../images/error.png?v=1605178543") 1em 1em no-repeat #fcc; padding-left: 3em; } #ibo-main-content .fg-menu a img, .ui-dialog .fg-menu a img { @@ -4178,18 +4177,18 @@ a:visited.ui-button { } #ibo-main-content #hiddeable_chapters .ui-tabs .ui-tabs-nav li.hideable-chapter span, .ui-dialog #hiddeable_chapters .ui-tabs .ui-tabs-nav li.hideable-chapter span { padding-left: 20px; - background: url("../../../../images/eye-open-555.png?v=1604919410") 2px center no-repeat; + background: url("../../../../images/eye-open-555.png?v=1605178543") 2px center no-repeat; } #ibo-main-content #hiddeable_chapters .ui-tabs .ui-tabs-nav li.hideable-chapter.strikethrough span, .ui-dialog #hiddeable_chapters .ui-tabs .ui-tabs-nav li.hideable-chapter.strikethrough span { text-decoration: line-through; - background: url("../../../../images/eye-closed-555.png?v=1604919410") 2px center no-repeat; + background: url("../../../../images/eye-closed-555.png?v=1605178543") 2px center no-repeat; } #ibo-main-content .printable-version legend, .ui-dialog .printable-version legend { padding-left: 26px; - background: #1c94c4 url("../../../../images/eye-open-fff.png?v=1604919410") 8px center no-repeat; + background: #1c94c4 url("../../../../images/eye-open-fff.png?v=1605178543") 8px center no-repeat; } #ibo-main-content .printable-version .strikethrough legend, .ui-dialog .printable-version .strikethrough legend { - background: #1c94c4 url("../../../../images/eye-closed-fff.png?v=1604919410") 8px center no-repeat; + background: #1c94c4 url("../../../../images/eye-closed-fff.png?v=1605178543") 8px center no-repeat; } #ibo-main-content .printable-version fieldset.strikethrough span, .ui-dialog .printable-version fieldset.strikethrough span { display: none; @@ -4262,7 +4261,7 @@ a:visited.ui-button { cursor: pointer; width: 16px; height: 16px; - background-image: url("../../../../css/ui-lightness/images/ui-icons_222222_256x240.png?v=1604919410"); + background-image: url("../../../../css/ui-lightness/images/ui-icons_222222_256x240.png?v=1605178543"); background-position: -16px -192px; } #ibo-main-content .history_entry_truncated .history_truncated_toggler, .ui-dialog .history_entry_truncated .history_truncated_toggler { @@ -4347,7 +4346,7 @@ a:visited.ui-button { #ibo-main-content #itop-breadcrumb .breadcrumb-item a::after, .ui-dialog #itop-breadcrumb .breadcrumb-item a::after { content: ''; position: absolute; - background-image: url("../../../../images/breadcrumb-separator.png?v=1604919410"); + background-image: url("../../../../images/breadcrumb-separator.png?v=1605178543"); background-repeat: no-repeat; width: 8px; height: 16px; diff --git a/templates/components/datatable/layout.js.twig b/templates/components/datatable/layout.js.twig index 9183520e3..db37aedd6 100644 --- a/templates/components/datatable/layout.js.twig +++ b/templates/components/datatable/layout.js.twig @@ -51,8 +51,8 @@ var oTable{{ oUIBlock.GetId() }} = $('#{{ oUIBlock.GetId() }}').DataTable({ "emptyTable": "{{ 'UI:Datatables:Language:EmptyTable'|dict_s }}", "paginate": { "first": "<<", - "previous": "<", - "next": ">", + previous: "", + next: "", "last": ">>" }, "aria": { diff --git a/templates/components/datatable/static/layout.js.twig b/templates/components/datatable/static/layout.js.twig index b7fba48d5..8cafad35f 100644 --- a/templates/components/datatable/static/layout.js.twig +++ b/templates/components/datatable/static/layout.js.twig @@ -19,8 +19,8 @@ $('#{{ oUIBlock.GetId() }}').DataTable({ emptyTable: "{{ 'UI:Datatables:Language:EmptyTable'|dict_s }}", paginate: { first: "<<", - previous: "<", - next: ">", + previous: "", + next: "", last: ">>" }, aria: { From 6835ebd11daf11b1634d26313d37b3114fdf9f23 Mon Sep 17 00:00:00 2001 From: acognet Date: Thu, 12 Nov 2020 12:34:52 +0100 Subject: [PATCH 10/16] =?UTF-8?q?N=C2=B02847=20-=20Tranform=20old=20itop?= =?UTF-8?q?=20datatable=20to=20jquery=20DataTable=20-=20show=20+=20button?= =?UTF-8?q?=20in=20search=20box?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- css/backoffice/components/_datatable.scss | 27 ++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/css/backoffice/components/_datatable.scss b/css/backoffice/components/_datatable.scss index 7e07eb52d..518acf74d 100644 --- a/css/backoffice/components/_datatable.scss +++ b/css/backoffice/components/_datatable.scss @@ -78,6 +78,25 @@ border: 2px solid var(--ibo-color-grey-300); background-color: $ibo-color-grey-200; } +.ibo-datatable thead tr th{ + position: relative; +} +.ibo-datatable thead tr th.sorting::after{ + font-family: "Font Awesome 5 Free"; font-weight: 900; content: "\f0dc"; + opacity: 0.3; + right: 1em; + position: absolute; +} +.ibo-datatable thead tr th.sorting_desc:after{ + font-family: "Font Awesome 5 Free"; font-weight: 900; content: "\f0d7"; + right: 1em; + position: absolute; +} +.ibo-datatable thead tr th.sorting_asc:after{ + font-family: "Font Awesome 5 Free"; font-weight: 900; content: "\f0d8"; + right: 1em; + position: absolute; +} .ibo-datatable-toolbar { /*position: relative;*/ //height: 30px; @@ -88,6 +107,12 @@ .ibo-search-form{ padding-top: $ibo-panel--spacing-top ; } + .ibo-form-group{ position: fixed; -} \ No newline at end of file +} + +.sf_more_criterion.opened > .sfm_content{ + position: fixed !important; + left: auto !important; +} From 0046834b2c908b720232bc683693044936bb1a19 Mon Sep 17 00:00:00 2001 From: acognet Date: Thu, 12 Nov 2020 18:30:20 +0100 Subject: [PATCH 11/16] =?UTF-8?q?N=C2=B02847=20-=20Tranform=20old=20itop?= =?UTF-8?q?=20datatable=20to=20jquery=20DataTable=20-=20add=20sort?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- application/cmdbabstract.class.inc.php | 1 - js/dataTables.settings.js | 59 +++++----------- pages/ajax.render.php | 18 +++-- pages/ajax.searchform.php | 8 --- .../Component/DataTable/DataTableFactory.php | 68 ++++++++++++++++--- .../components/datatable/layout.html.twig | 4 +- templates/components/datatable/layout.js.twig | 22 +++--- 7 files changed, 100 insertions(+), 80 deletions(-) diff --git a/application/cmdbabstract.class.inc.php b/application/cmdbabstract.class.inc.php index 817bd21ec..5edd3b5c0 100644 --- a/application/cmdbabstract.class.inc.php +++ b/application/cmdbabstract.class.inc.php @@ -51,7 +51,6 @@ require_once(APPROOT.'application/ui.linksdirectwidget.class.inc.php'); require_once(APPROOT.'application/ui.passwordwidget.class.inc.php'); require_once(APPROOT.'application/ui.extkeywidget.class.inc.php'); require_once(APPROOT.'application/ui.htmleditorwidget.class.inc.php'); -require_once(APPROOT.'application/datatable.class.inc.php'); require_once(APPROOT.'sources/application/search/searchform.class.inc.php'); require_once(APPROOT.'sources/application/search/criterionparser.class.inc.php'); require_once(APPROOT.'sources/application/search/criterionconversionabstract.class.inc.php'); diff --git a/js/dataTables.settings.js b/js/dataTables.settings.js index 53ff1647c..48a20a30f 100644 --- a/js/dataTables.settings.js +++ b/js/dataTables.settings.js @@ -2,7 +2,7 @@ $(function() { // the widget definition, where "itop" is the namespace, - // "datatable" the widget name + // "DataTableSettings" the widget name $.widget( "itop.DataTableSettings", { // default options @@ -26,7 +26,6 @@ $(function() _create: function(mydatatable, options) { this.aDlgStateParams = ['iDefaultPageSize', 'oColumns']; - console.warn('datatablesettings'); this.element.addClass('itop-datatable'); var me = this; @@ -80,51 +79,32 @@ $(function() { 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(); + var parentElt = $('#'+me.options.sListId).parent().parent(); $('#'+me.options.sListId).DataTable().destroy(true); - var entete=""; + var sThead=""; + if(me.options.sSelectMode !=""){ + sThead += ""; + } var aOptions = JSON.parse(data); - $.each(aOptions[0]['allColumns'], function(i, item) { + $.each(aOptions['allColumns'], function(i, item) { $.each(item, function(j, champs) { if(champs.checked == 'true') { - entete += ""+champs.label+""; + sThead += ""+champs.label+""; } }); }); - $.each(aOptions[0]['columns'], function(i, item) { - aOptions[0]["columns"][i]["render"]["display"] = new Function ( "data, type, row" , aOptions[0]["columns"][i]["render"]["display"]); + $.each(aOptions['columns'], function(i, item) { + aOptions["columns"][i]["render"]["display"] = new Function ( "data, type, row" , aOptions["columns"][i]["render"]["display"]); }); - toto.append( "" + - ""+entete+"
" ); - //$('#'+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]); + parentElt.append( "" + + ""+sThead+"
" ); + aOptions["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["lengthMenu"]]]; + aOptions["ajax"]=eval(aOptions["ajax"]); + $('#'+me.options.sListId).DataTable(aOptions); - - - - - - /*} 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' ); @@ -168,11 +148,6 @@ $(function() } } } - /*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; @@ -202,6 +177,7 @@ $(function() oOptions = {oColumns: oColumns, iPageSize: iPageSize, iDefaultPageSize: iPageSize }; } this._setOptions(oOptions); + this._refresh(); // Check if we need to save the settings or not... var oSaveCheck = $('#datatable_dlg_'+this.options.sListId).find('input[name=save_settings]'); @@ -259,7 +235,6 @@ $(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 ) @@ -269,7 +244,6 @@ $(function() }, UpdateState: function( config ) { - console.warn('datatablesettings:UpdateState'); var iPageSize = config.page_size; if (iPageSize == -1) { @@ -314,6 +288,7 @@ $(function() for(k in this.aDlgStateParams) { this._setOption(this.aDlgStateParams[k], this.originalState[this.aDlgStateParams[k]]); + this._refresh(); } dlgElement.find('input[name=page_size]').val(this.originalState.iDefaultPageSize); diff --git a/pages/ajax.render.php b/pages/ajax.render.php index 283498030..4dd47ee05 100644 --- a/pages/ajax.render.php +++ b/pages/ajax.render.php @@ -291,7 +291,15 @@ try $iEnd = utils::ReadParam('end', 1); $iDrawNumber= utils::ReadParam('draw', 1); - $iSortCol = utils::ReadParam('sort_col', 'null'); + $aSort = utils::ReadParam('order', [], false, 'array'); + if(count($aSort)>0){ + $iSortCol = $aSort[0]["column"]; + $sSortOrder = $aSort[0]["dir"]; + } + else{ + $iSortCol = 0; + $sSortOrder = "asc"; + } $sSelectMode = utils::ReadParam('select_mode', ''); if (!empty($sSelectMode) && ($sSelectMode != 'none')) { @@ -330,16 +338,16 @@ try 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'); + $aOrderBy[$sAlias.'.'.$aNameSpec[1][0]] = ($sSortOrder == 'asc'); } else { - $aOrderBy[$sAlias.'.'.'friendlyname'] = (utils::ReadParam('sort_order', 'asc') == 'asc'); + $aOrderBy[$sAlias.'.'.'friendlyname'] = ($sSortOrder == 'asc'); } } else { - $aOrderBy[$sAlias.'.'.'friendlyname'] = (utils::ReadParam('sort_order', 'asc') == 'asc'); + $aOrderBy[$sAlias.'.'.'friendlyname'] = ($sSortOrder == 'asc'); } } } @@ -365,7 +373,7 @@ try { $sSortCol = $sAttCode; } - $aOrderBy[$sAlias.'.'.$sSortCol] = (utils::ReadParam('sort_order', 'asc') == 'asc'); + $aOrderBy[$sAlias.'.'.$sSortCol] = ($sSortOrder == 'asc'); } } $iSortIndex++; diff --git a/pages/ajax.searchform.php b/pages/ajax.searchform.php index a58e664dc..ec55101e9 100644 --- a/pages/ajax.searchform.php +++ b/pages/ajax.searchform.php @@ -64,8 +64,6 @@ try $sHiddenCriteria = ''; } $oFilter = CriterionParser::Parse($aParams['base_oql'], $aParams['criterion'], $sHiddenCriteria); - - //IssueLog::Info('Search OQL: "'.$oFilter->ToOQL().'"'); $oDisplayBlock = new DisplayBlock($oFilter, 'list_search', false); foreach($aListParams as $key => $value) @@ -92,11 +90,6 @@ try { $aExtraParams['query_params'] = array('this->object()' => $oObj); } - -// // Current extkey value, so we can display event if it is not available anymore (eg. archived). -// $iCurrentExtKeyId = (is_null($oObj)) ? 0 : $oObj->Get($this->sAttCode); -// $aExtraParams['current_extkey_id'] = $iCurrentExtKeyId; - } if (!isset($aExtraParams['update_history'])) @@ -116,7 +109,6 @@ try $oDisplayBlock->RenderContent($oPage, $aExtraParams); } - if (isset($aListParams['debug']) || UserRights::IsAdministrator()) { $oPage->StartCollapsibleSection(Dict::S('UI:RunQuery:MoreInfo'), false, 'SearchQuery'); diff --git a/sources/application/UI/Component/DataTable/DataTableFactory.php b/sources/application/UI/Component/DataTable/DataTableFactory.php index de64d3026..3bf441f97 100644 --- a/sources/application/UI/Component/DataTable/DataTableFactory.php +++ b/sources/application/UI/Component/DataTable/DataTableFactory.php @@ -240,7 +240,6 @@ class DataTableFactory if ($oCustomSettings->iDefaultPageSize > 0) { $oSet->SetLimit($oCustomSettings->iDefaultPageSize); } - $oSet->SetOrderBy($oCustomSettings->GetSortOrder()); // Load only the requested columns $aColumnsToLoad = array(); @@ -261,10 +260,20 @@ class DataTableFactory } } $oSet->OptimizeColumnLoad($aColumnsToLoad); - + $aSortOrder=[]; + $aSortDatable=[]; $aColumnDefinition = []; + $iIndexColumn=0; + if($sSelectMode!="") { + $iIndexColumn++; + } foreach ($aClassAliases as $sClassAlias => $sClassName) { foreach ($oCustomSettings->aColumns[$sClassAlias] as $sAttCode => $aData) { + if ($aData['sort'] != 'none') { + $sCode = ($aData['code'] == '_key_') ? 'friendlyname' : $aData['code']; + $aSortOrder[$sAlias.$sCode] = ($aData['sort'] == 'asc'); // true for ascending, false for descending + $aSortDatable=[$iIndexColumn,$aData['sort']]; + } if ($aData['checked']) { if ($sAttCode == '_key_') { $aColumnDefinition[] = [ @@ -290,20 +299,22 @@ class DataTableFactory "render" => $oAttDef->GetRenderForDataTable($sClassAlias), ]; } + $iIndexColumn++; } } } + $oSet->SetOrderBy($aSortOrder); $aOptions = []; if ($oDefaultSettings != null) { $aOptions['oDefaultSettings'] = json_encode(array('iDefaultPageSize' => $oDefaultSettings->iDefaultPageSize, 'oColumns' => $oDefaultSettings->aColumns)); } - + $aOptions['sort'] = $aSortDatable; if ($sSelectMode == 'multiple') { - $aOptions['select'] = "multi"; + $aOptions['select_mode'] = "multiple"; } else { if ($sSelectMode == 'single') { - $aOptions['select'] = "single"; + $aOptions['select_mode'] = "single"; } } @@ -324,6 +335,7 @@ class DataTableFactory "columns" => $oCustomSettings->aColumns, "extra_params" => $aExtraParams, "class_aliases" => $aClassAliases, + "select_mode" => $sSelectMode, ])); $oDataTable->SetDisplayColumns($aColumnDefinition); $oDataTable->SetResultColumns($oCustomSettings->aColumns); @@ -436,7 +448,6 @@ class DataTableFactory if ($oCustomSettings->iDefaultPageSize > 0) { $oSet->SetLimit($oCustomSettings->iDefaultPageSize); } - $oSet->SetOrderBy($oCustomSettings->GetSortOrder()); // Load only the requested columns $aColumnsToLoad = array(); @@ -459,8 +470,17 @@ class DataTableFactory $oSet->OptimizeColumnLoad($aColumnsToLoad); $aColumnDefinition = []; + $iIndexColumn=0; + if($sSelectMode!="") { + $iIndexColumn++; + } foreach ($aClassAliases as $sClassAlias => $sClassName) { foreach ($oCustomSettings->aColumns[$sClassAlias] as $sAttCode => $aData) { + if ($aData['sort'] != 'none') { + $sCode = ($aData['code'] == '_key_') ? 'friendlyname' : $aData['code']; + $aSortOrder[$sAlias.$sCode] = ($aData['sort'] == 'asc'); // true for ascending, false for descending + $aSortDatable=[$iIndexColumn,$aData['sort']]; + } if ($aData['checked']) { if ($sAttCode == '_key_') { $aColumnDefinition[] = [ @@ -486,9 +506,11 @@ class DataTableFactory "render" => $oAttDef->GetRenderForDataTable($sClassAlias), ]; } + $iIndexColumn++; } } } + $oSet->SetOrderBy($oCustomSettings->GetSortOrder()); $aOptions = []; if ($oDefaultSettings != null) { @@ -496,13 +518,15 @@ class DataTableFactory } if ($sSelectMode == 'multiple') { - $aOptions['select'] = "multi"; + $aOptions['select_mode'] = "multiple"; } else { if ($sSelectMode == 'single') { - $aOptions['select'] = "single"; + $aOptions['select_mode'] = "single"; } } + $aOptions['sort'] = $aSortDatable; + $aOptions['iPageSize'] = 10; if ($oCustomSettings->iDefaultPageSize > 0) { $aOptions['iPageSize'] = $oCustomSettings->iDefaultPageSize; @@ -520,6 +544,7 @@ class DataTableFactory "columns" => $oCustomSettings->aColumns, "extra_params" => $aExtraParams, "class_aliases" => $aClassAliases, + "select_mode" => $sSelectMode, ])); $oDataTable->SetDisplayColumns($aColumnDefinition); $oDataTable->SetResultColumns($oCustomSettings->aColumns); @@ -545,6 +570,25 @@ class DataTableFactory $aColumnDefinition = []; $aClassAliases = []; + if ($sSelectMode!=""){ + $aColumnDefinition["width"] = "auto"; + $aColumnDefinition["searchable"] = false; + $aColumnDefinition["sortable"] = false; + $aColumnDefinition["title"] = ""; + $aColumnDefinition["type"] = "html"; + $aColumnDefinition["data"] = ""; + $aColumnDefinition["render"] = "function (data, type, row) { + var oCheckboxElem = $(''); + 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'); + }"; + array_push($aColumnsDefinitions, $aColumnDefinition); + } + foreach ($aColumns as $sClassName => $aClassColumns) { $aClassAliases[$sClassName] = $sClassName; foreach ($aClassColumns as $sAttCode => $aData) { @@ -591,7 +635,7 @@ class DataTableFactory } } - $aOptions['select'] = $sSelectMode; + $aOptions['select'] = ["style"=>$sSelectMode]; $aOptions['pageLength'] = $iLength; @@ -601,10 +645,11 @@ class DataTableFactory "columns" => $aColumns, "extra_params" => $aExtraParams, "class_aliases" => $aClassAliases, + "select_mode" => $sSelectMode, ]); - $aOptions[] = [ + $aOptions =array_merge ($aOptions, [ "language" => [ "processing" => Dict::Format('UI:Datatables:Language:Processing'), @@ -628,6 +673,7 @@ class DataTableFactory ], "lengthMenu" => Dict::Format('Portal:Datatables:Language:DisplayLength:All'), "dom" => "<'ibo-datatable-toolbar'pil>t<'ibo-datatable-toolbar'pil>", + "ordering"=>true, "order" => [], "filter" => false, "processing" => true, @@ -640,7 +686,7 @@ class DataTableFactory "method": "post", "pages": 5 // number of pages to cache } )' - ]; + ]); return $aOptions; } diff --git a/templates/components/datatable/layout.html.twig b/templates/components/datatable/layout.html.twig index 98d60cd11..b45e9a70b 100644 --- a/templates/components/datatable/layout.html.twig +++ b/templates/components/datatable/layout.html.twig @@ -1,5 +1,5 @@ {% for oSubBlock in oUIBlock.GetSubBlocks() %}{{ render_block(oSubBlock, {aPage: aPage}) }}{% endfor %} -{% if oUIBlock.GetOptions()["select"] is defined %} +{% if oUIBlock.GetOptions()["select_mode"] is defined %} @@ -7,7 +7,7 @@ - {% if oUIBlock.GetOptions()["select"] is defined %} + {% if oUIBlock.GetOptions()["select_mode"] is defined %} {% endif %} {% for aColumn in oUIBlock.GetDisplayColumns() %} diff --git a/templates/components/datatable/layout.js.twig b/templates/components/datatable/layout.js.twig index db37aedd6..ac9060fb7 100644 --- a/templates/components/datatable/layout.js.twig +++ b/templates/components/datatable/layout.js.twig @@ -20,22 +20,18 @@ function checkAllDataTable(table, value) { // 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 () { - console.warn("destroy on close"); - $('#{{ oUIBlock.GetId() }}').DataTable().clear(); -// $('#{{ oUIBlock.GetId() }}').DataTable().destroy(false); + $('#{{ oUIBlock.GetId() }}').DataTable().clear(); }); -{% if oUIBlock.GetOptions()["select"] is defined %} +{% if oUIBlock.GetOptions()["select_mode"] is defined %} var oSelectedItems{{ oUIBlock.GetOptions()['sTableId'] }} = []; {% endif %} if ($.fn.dataTable.isDataTable('#{{ oUIBlock.GetId() }}')) { - console.warn("destroy on load"); $('#{{ oUIBlock.GetId() }}').DataTable().destroy(false); } @@ -62,7 +58,12 @@ var oTable{{ oUIBlock.GetId() }} = $('#{{ oUIBlock.GetId() }}').DataTable({ }, "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": [], + {% if( oUIBlock.GetOptions()["sort"][0] is defined ) %} + "order": [[{{ oUIBlock.GetOptions()["sort"][0]}},'{{ oUIBlock.GetOptions()["sort"][1]}}']], + {% else %} + "order":[], + {% endif %} + "ordering": true, {% if oUIBlock.GetOptions()["select"] is defined %} "select": { "style": "{{ oUIBlock.GetOptions()["select"] }}" @@ -74,7 +75,6 @@ var oTable{{ oUIBlock.GetId() }} = $('#{{ oUIBlock.GetId() }}').DataTable({ $(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(); @@ -99,7 +99,7 @@ var oTable{{ oUIBlock.GetId() }} = $('#{{ oUIBlock.GetId() }}').DataTable({ "processing": true, "serverSide": true, "columns": [ - {% if oUIBlock.GetOptions()["select"] is defined %} + {% if oUIBlock.GetOptions()["select_mode"] is defined %} { "width": "auto", "searchable": false, @@ -230,12 +230,12 @@ $aOptions = { 'iPageSize': '{{ oUIBlock.GetOptions()["iPageSize"] }}', 'sTableId': '{{ oUIBlock.GetOptions()["sTableId"] }}', "sRenderUrl": "{{ oUIBlock.GetAjaxUrl() }}", - "sSelectMode": "{{ oUIBlock.GetOptions()["select"] }}", + "sSelectMode": "{{ oUIBlock.GetOptions()["select_mode"] }}", "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"); From 0a02c1028745c001cb3d9d9940b047de9e220a6a Mon Sep 17 00:00:00 2001 From: acognet Date: Mon, 16 Nov 2020 10:40:35 +0100 Subject: [PATCH 12/16] =?UTF-8?q?N=C2=B02847=20-=20Tranform=20old=20itop?= =?UTF-8?q?=20datatable=20to=20jquery=20DataTable=20-=20fix=20diplay?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- application/displayblock.class.inc.php | 500 ++++++++++-------- application/ui.linkswidget.class.inc.php | 20 + js/search/search_form_handler.js | 4 +- .../Component/DataTable/DataTableFactory.php | 2 + .../search/searchform.class.inc.php | 20 +- templates/components/datatable/layout.js.twig | 7 +- 6 files changed, 319 insertions(+), 234 deletions(-) diff --git a/application/displayblock.class.inc.php b/application/displayblock.class.inc.php index f1e5a6f15..ff0d4af0a 100644 --- a/application/displayblock.class.inc.php +++ b/application/displayblock.class.inc.php @@ -1567,244 +1567,308 @@ class MenuBlock extends DisplayBlock { $this->m_sStyle = 'list'; } - $oAppContext = new ApplicationContext(); - $sContext = $oAppContext->GetForLink(); - if (!empty($sContext)) { - $sContext = '&'.$sContext; - } $sClass = $this->m_oFilter->GetClass(); - $oReflectionClass = new ReflectionClass($sClass); $oSet = new CMDBObjectSet($this->m_oFilter); - $sFilter = $this->m_oFilter->serialize(); - $aActions = []; - $sUIPage = cmdbAbstractObject::ComputeStandardUIPage($sClass); - $sRootUrl = utils::GetAbsoluteUrlAppRoot(); - // Common params that will be applied to actions - $aActionParams = array(); - if (isset($aExtraParams['menu_actions_target'])) { - $aActionParams['target'] = $aExtraParams['menu_actions_target']; - } - // 1:n links, populate the target object as a default value when creating a new linked object - if (isset($aExtraParams['target_attr'])) { - $aExtraParams['default'][$aExtraParams['target_attr']] = $aExtraParams['object_id']; - } - $sDefault = ''; - if (!empty($aExtraParams['default'])) { - foreach ($aExtraParams['default'] as $sKey => $sValue) { - $sDefault .= "&default[$sKey]=$sValue"; - } - } - $bIsCreationAllowed = (UserRights::IsActionAllowed($sClass, UR_ACTION_CREATE) == UR_ALLOWED_YES) && ($oReflectionClass->IsSubclassOf('cmdbAbstractObject')); $sRefreshAction = ''; - switch ($oSet->Count()) { - case 0: - // No object in the set, the only possible action is "new" - if ($bIsCreationAllowed) { - $aActions['UI:Menu:New'] = array('label' => Dict::S('UI:Menu:New'), 'url' => "{$sRootUrl}pages/$sUIPage?operation=new&class=$sClass{$sContext}{$sDefault}") + $aActionParams; + if (!isset($aExtraParams['selection_mode']) || $aExtraParams['selection_mode'] == "") { + $oAppContext = new ApplicationContext(); + $sContext = $oAppContext->GetForLink(); + if (!empty($sContext)) { + $sContext = '&'.$sContext; + } + $oReflectionClass = new ReflectionClass($sClass); + $sFilter = $this->m_oFilter->serialize(); + $aActions = []; + $sUIPage = cmdbAbstractObject::ComputeStandardUIPage($sClass); + $sRootUrl = utils::GetAbsoluteUrlAppRoot(); + // Common params that will be applied to actions + $aActionParams = array(); + if (isset($aExtraParams['menu_actions_target'])) { + $aActionParams['target'] = $aExtraParams['menu_actions_target']; + } + // 1:n links, populate the target object as a default value when creating a new linked object + if (isset($aExtraParams['target_attr'])) { + $aExtraParams['default'][$aExtraParams['target_attr']] = $aExtraParams['object_id']; + } + $sDefault = ''; + if (!empty($aExtraParams['default'])) { + foreach ($aExtraParams['default'] as $sKey => $sValue) { + $sDefault .= "&default[$sKey]=$sValue"; } - break; + } + $bIsCreationAllowed = (UserRights::IsActionAllowed($sClass, + UR_ACTION_CREATE) == UR_ALLOWED_YES) && ($oReflectionClass->IsSubclassOf('cmdbAbstractObject')); + switch ($oSet->Count()) { + case 0: + // No object in the set, the only possible action is "new" + if ($bIsCreationAllowed) { + $aActions['UI:Menu:New'] = array( + 'label' => Dict::S('UI:Menu:New'), + 'url' => "{$sRootUrl}pages/$sUIPage?operation=new&class=$sClass{$sContext}{$sDefault}" + ) + $aActionParams; + } + break; - case 1: - $oObj = $oSet->Fetch(); - if (is_null($oObj)) { - if (!isset($aExtraParams['link_attr'])) { - if ($bIsCreationAllowed) { - $aActions['UI:Menu:New'] = array('label' => Dict::S('UI:Menu:New'), 'url' => "{$sRootUrl}pages/$sUIPage?operation=new&class=$sClass{$sContext}{$sDefault}") + $aActionParams; + case 1: + $oObj = $oSet->Fetch(); + if (is_null($oObj)) { + if (!isset($aExtraParams['link_attr'])) { + if ($bIsCreationAllowed) { + $aActions['UI:Menu:New'] = array( + 'label' => Dict::S('UI:Menu:New'), + 'url' => "{$sRootUrl}pages/$sUIPage?operation=new&class=$sClass{$sContext}{$sDefault}" + ) + $aActionParams; + } } - } - } else { - $id = $oObj->GetKey(); - if (utils::ReadParam('operation') == 'details') { - if ($_SERVER['REQUEST_METHOD'] == 'GET') { - $sRefreshAction = "window.location.reload();"; - } else { - $sRefreshAction = "window.location.href='".ApplicationContext::MakeObjectUrl(get_class($oObj), $id)."';"; + } else { + $id = $oObj->GetKey(); + if (utils::ReadParam('operation') == 'details') { + if ($_SERVER['REQUEST_METHOD'] == 'GET') { + $sRefreshAction = "window.location.reload();"; + } else { + $sRefreshAction = "window.location.href='".ApplicationContext::MakeObjectUrl(get_class($oObj), $id)."';"; + } } - } - $bLocked = false; - if (MetaModel::GetConfig()->Get('concurrent_lock_enabled')) { - $aLockInfo = iTopOwnershipLock::IsLocked(get_class($oObj), $id); - if ($aLockInfo['locked']) { - $bLocked = true; - //$this->AddMenuSeparator($aActions); - //$aActions['concurrent_lock_unlock'] = array ('label' => Dict::S('UI:Menu:ReleaseConcurrentLock'), 'url' => "{$sRootUrl}pages/$sUIPage?operation=kill_lock&class=$sClass&id=$id{$sContext}"); + $bLocked = false; + if (MetaModel::GetConfig()->Get('concurrent_lock_enabled')) { + $aLockInfo = iTopOwnershipLock::IsLocked(get_class($oObj), $id); + if ($aLockInfo['locked']) { + $bLocked = true; + //$this->AddMenuSeparator($aActions); + //$aActions['concurrent_lock_unlock'] = array ('label' => Dict::S('UI:Menu:ReleaseConcurrentLock'), 'url' => "{$sRootUrl}pages/$sUIPage?operation=kill_lock&class=$sClass&id=$id{$sContext}"); + } } - } - $bRawModifiedAllowed = (UserRights::IsActionAllowed($sClass, UR_ACTION_MODIFY, $oSet) == UR_ALLOWED_YES) && ($oReflectionClass->IsSubclassOf('cmdbAbstractObject')); - $bIsModifyAllowed = !$bLocked && $bRawModifiedAllowed; - $bIsDeleteAllowed = !$bLocked && UserRights::IsActionAllowed($sClass, UR_ACTION_DELETE, $oSet); - // Just one object in the set, possible actions are "new / clone / modify and delete" - if (!isset($aExtraParams['link_attr'])) { - if ($bIsModifyAllowed) { - $aActions['UI:Menu:Modify'] = array('label' => Dict::S('UI:Menu:Modify'), 'url' => "{$sRootUrl}pages/$sUIPage?operation=modify&class=$sClass&id=$id{$sContext}#") + $aActionParams; - } - if ($bIsCreationAllowed) { - $aActions['UI:Menu:New'] = array('label' => Dict::S('UI:Menu:New'), 'url' => "{$sRootUrl}pages/$sUIPage?operation=new&class=$sClass{$sContext}{$sDefault}") + $aActionParams; - } - if ($bIsDeleteAllowed) { - $aActions['UI:Menu:Delete'] = array('label' => Dict::S('UI:Menu:Delete'), 'url' => "{$sRootUrl}pages/$sUIPage?operation=delete&class=$sClass&id=$id{$sContext}") + $aActionParams; - } - // Transitions / Stimuli - if (!$bLocked) { - $aTransitions = $oObj->EnumTransitions(); - if (count($aTransitions)) { + $bRawModifiedAllowed = (UserRights::IsActionAllowed($sClass, UR_ACTION_MODIFY, + $oSet) == UR_ALLOWED_YES) && ($oReflectionClass->IsSubclassOf('cmdbAbstractObject')); + $bIsModifyAllowed = !$bLocked && $bRawModifiedAllowed; + $bIsDeleteAllowed = !$bLocked && UserRights::IsActionAllowed($sClass, UR_ACTION_DELETE, $oSet); + // Just one object in the set, possible actions are "new / clone / modify and delete" + if (!isset($aExtraParams['link_attr'])) { + if ($bIsModifyAllowed) { + $aActions['UI:Menu:Modify'] = array( + 'label' => Dict::S('UI:Menu:Modify'), + 'url' => "{$sRootUrl}pages/$sUIPage?operation=modify&class=$sClass&id=$id{$sContext}#" + ) + $aActionParams; + } + if ($bIsCreationAllowed) { + $aActions['UI:Menu:New'] = array( + 'label' => Dict::S('UI:Menu:New'), + 'url' => "{$sRootUrl}pages/$sUIPage?operation=new&class=$sClass{$sContext}{$sDefault}" + ) + $aActionParams; + } + if ($bIsDeleteAllowed) { + $aActions['UI:Menu:Delete'] = array( + 'label' => Dict::S('UI:Menu:Delete'), + 'url' => "{$sRootUrl}pages/$sUIPage?operation=delete&class=$sClass&id=$id{$sContext}" + ) + $aActionParams; + } + // Transitions / Stimuli + if (!$bLocked) { + $aTransitions = $oObj->EnumTransitions(); + if (count($aTransitions)) { + $this->AddMenuSeparator($aActions); + $aStimuli = Metamodel::EnumStimuli(get_class($oObj)); + foreach ($aTransitions as $sStimulusCode => $aTransitionDef) { + $iActionAllowed = (get_class($aStimuli[$sStimulusCode]) == 'StimulusUserAction') ? UserRights::IsStimulusAllowed($sClass, + $sStimulusCode, $oSet) : UR_ALLOWED_NO; + switch ($iActionAllowed) { + case UR_ALLOWED_YES: + $aActions[$sStimulusCode] = array( + 'label' => $aStimuli[$sStimulusCode]->GetLabel(), + 'url' => "{$sRootUrl}pages/UI.php?operation=stimulus&stimulus=$sStimulusCode&class=$sClass&id=$id{$sContext}" + ) + $aActionParams; + break; + + default: + // Do nothing + } + } + } + } + // Relations... + $aRelations = MetaModel::EnumRelationsEx($sClass); + if (count($aRelations)) { $this->AddMenuSeparator($aActions); - $aStimuli = Metamodel::EnumStimuli(get_class($oObj)); - foreach ($aTransitions as $sStimulusCode => $aTransitionDef) { - $iActionAllowed = (get_class($aStimuli[$sStimulusCode]) == 'StimulusUserAction') ? UserRights::IsStimulusAllowed($sClass, $sStimulusCode, $oSet) : UR_ALLOWED_NO; - switch ($iActionAllowed) { - case UR_ALLOWED_YES: - $aActions[$sStimulusCode] = array('label' => $aStimuli[$sStimulusCode]->GetLabel(), 'url' => "{$sRootUrl}pages/UI.php?operation=stimulus&stimulus=$sStimulusCode&class=$sClass&id=$id{$sContext}") + $aActionParams; - break; + foreach ($aRelations as $sRelationCode => $aRelationInfo) { + if (array_key_exists('down', $aRelationInfo)) { + $aActions[$sRelationCode.'_down'] = array( + 'label' => $aRelationInfo['down'], + 'url' => "{$sRootUrl}pages/$sUIPage?operation=view_relations&relation=$sRelationCode&direction=down&class=$sClass&id=$id{$sContext}" + ) + $aActionParams; + } + if (array_key_exists('up', $aRelationInfo)) { + $aActions[$sRelationCode.'_up'] = array( + 'label' => $aRelationInfo['up'], + 'url' => "{$sRootUrl}pages/$sUIPage?operation=view_relations&relation=$sRelationCode&direction=up&class=$sClass&id=$id{$sContext}" + ) + $aActionParams; + } + } + } + if ($bLocked && $bRawModifiedAllowed) { + // Add a special menu to kill the lock, but only to allowed users who can also modify this object + /** @var array $aAllowedProfiles */ + $aAllowedProfiles = MetaModel::GetConfig()->Get('concurrent_lock_override_profiles'); + $bCanKill = false; - default: - // Do nothing + $oUser = UserRights::GetUserObject(); + $aUserProfiles = array(); + if (!is_null($oUser)) { + $oProfileSet = $oUser->Get('profile_list'); + while ($oProfile = $oProfileSet->Fetch()) { + $aUserProfiles[$oProfile->Get('profile')] = true; + } + } + + foreach ($aAllowedProfiles as $sProfile) { + if (array_key_exists($sProfile, $aUserProfiles)) { + $bCanKill = true; + break; + } + } + + if ($bCanKill) { + $this->AddMenuSeparator($aActions); + $aActions['concurrent_lock_unlock'] = array( + 'label' => Dict::S('UI:Menu:KillConcurrentLock'), + 'url' => "{$sRootUrl}pages/$sUIPage?operation=kill_lock&class=$sClass&id=$id{$sContext}" + ); + } + } + } + $this->AddMenuSeparator($aActions); + /** @var \iApplicationUIExtension $oExtensionInstance */ + foreach (MetaModel::EnumPlugins('iApplicationUIExtension') as $oExtensionInstance) { + $oSet->Rewind(); + foreach ($oExtensionInstance->EnumAllowedActions($oSet) as $sLabel => $sUrl) { + $aActions[$sLabel] = array('label' => $sLabel, 'url' => $sUrl) + $aActionParams; + } + } + } + break; + + default: + // Check rights + // New / Modify + $bIsModifyAllowed = UserRights::IsActionAllowed($sClass, UR_ACTION_MODIFY, + $oSet) && ($oReflectionClass->IsSubclassOf('cmdbAbstractObject')); + $bIsBulkModifyAllowed = (!MetaModel::IsAbstract($sClass)) && UserRights::IsActionAllowed($sClass, UR_ACTION_BULK_MODIFY, + $oSet) && ($oReflectionClass->IsSubclassOf('cmdbAbstractObject')); + $bIsBulkDeleteAllowed = UserRights::IsActionAllowed($sClass, UR_ACTION_BULK_DELETE, $oSet); + if (isset($aExtraParams['link_attr'])) { + $id = $aExtraParams['object_id']; + $sTargetAttr = $aExtraParams['target_attr']; + $oAttDef = MetaModel::GetAttributeDef($sClass, $sTargetAttr); + $sTargetClass = $oAttDef->GetTargetClass(); + if ($bIsModifyAllowed) { + $aActions['UI:Menu:Add'] = array( + 'label' => Dict::S('UI:Menu:Add'), + 'url' => "{$sRootUrl}pages/$sUIPage?operation=modify_links&class=$sClass&link_attr=".$aExtraParams['link_attr']."&target_class=$sTargetClass&id=$id&addObjects=true{$sContext}" + ) + $aActionParams; + } + if ($bIsBulkModifyAllowed) { + $aActions['UI:Menu:Manage'] = array( + 'label' => Dict::S('UI:Menu:Manage'), + 'url' => "{$sRootUrl}pages/$sUIPage?operation=modify_links&class=$sClass&link_attr=".$aExtraParams['link_attr']."&target_class=$sTargetClass&id=$id{$sContext}" + ) + $aActionParams; + } + //if ($bIsBulkDeleteAllowed) { $aActions[] = array ('label' => 'Remove All...', 'url' => "#") + $aActionParams; } + } else { + // many objects in the set, possible actions are: new / modify all / delete all + if ($bIsCreationAllowed) { + $aActions['UI:Menu:New'] = array( + 'label' => Dict::S('UI:Menu:New'), + 'url' => "{$sRootUrl}pages/$sUIPage?operation=new&class=$sClass{$sContext}{$sDefault}" + ) + $aActionParams; + } + if ($bIsBulkModifyAllowed) { + $aActions['UI:Menu:ModifyAll'] = array( + 'label' => Dict::S('UI:Menu:ModifyAll'), + 'url' => "{$sRootUrl}pages/$sUIPage?operation=select_for_modify_all&class=$sClass&filter=".urlencode($sFilter)."{$sContext}" + ) + $aActionParams; + } + if ($bIsBulkDeleteAllowed) { + $aActions['UI:Menu:BulkDelete'] = array( + 'label' => Dict::S('UI:Menu:BulkDelete'), + 'url' => "{$sRootUrl}pages/$sUIPage?operation=select_for_deletion&filter=".urlencode($sFilter)."{$sContext}" + ) + $aActionParams; + } + + // Stimuli + $aStates = MetaModel::EnumStates($sClass); + // Do not perform time consuming computations if there are too may objects in the list + $iLimit = MetaModel::GetConfig()->Get('complex_actions_limit'); + + if ((count($aStates) > 0) && (($iLimit == 0) || ($oSet->CountWithLimit($iLimit + 1) < $iLimit))) { + // Life cycle actions may be available... if all objects are in the same state + // + // Group by + $oGroupByExp = new FieldExpression(MetaModel::GetStateAttributeCode($sClass), $this->m_oFilter->GetClassAlias()); + $aGroupBy = array('__state__' => $oGroupByExp); + $aQueryParams = array(); + if (isset($aExtraParams['query_params'])) { + $aQueryParams = $aExtraParams['query_params']; + } + $sSql = $this->m_oFilter->MakeGroupByQuery($aQueryParams, $aGroupBy); + $aRes = CMDBSource::QueryToArray($sSql); + if (count($aRes) == 1) { + // All objects are in the same state... + $sState = $aRes[0]['__state__']; + $aTransitions = Metamodel::EnumTransitions($sClass, $sState); + if (count($aTransitions)) { + $this->AddMenuSeparator($aActions); + $aStimuli = Metamodel::EnumStimuli($sClass); + foreach ($aTransitions as $sStimulusCode => $aTransitionDef) { + $oSet->Rewind(); + // As soon as the user rights implementation will browse the object set, + // then we might consider using OptimizeColumnLoad() here + $iActionAllowed = UserRights::IsStimulusAllowed($sClass, $sStimulusCode, $oSet); + $iActionAllowed = (get_class($aStimuli[$sStimulusCode]) == 'StimulusUserAction') ? $iActionAllowed : UR_ALLOWED_NO; + switch ($iActionAllowed) { + case UR_ALLOWED_YES: + case UR_ALLOWED_DEPENDS: + $aActions[$sStimulusCode] = array( + 'label' => $aStimuli[$sStimulusCode]->GetLabel(), + 'url' => "{$sRootUrl}pages/UI.php?operation=select_bulk_stimulus&stimulus=$sStimulusCode&state=$sState&class=$sClass&filter=".urlencode($sFilter)."{$sContext}" + ) + $aActionParams; + break; + + default: + // Do nothing + } } } } } - // Relations... - $aRelations = MetaModel::EnumRelationsEx($sClass); - if (count($aRelations)) { - $this->AddMenuSeparator($aActions); - foreach ($aRelations as $sRelationCode => $aRelationInfo) { - if (array_key_exists('down', $aRelationInfo)) { - $aActions[$sRelationCode.'_down'] = array('label' => $aRelationInfo['down'], 'url' => "{$sRootUrl}pages/$sUIPage?operation=view_relations&relation=$sRelationCode&direction=down&class=$sClass&id=$id{$sContext}") + $aActionParams; - } - if (array_key_exists('up', $aRelationInfo)) { - $aActions[$sRelationCode.'_up'] = array('label' => $aRelationInfo['up'], 'url' => "{$sRootUrl}pages/$sUIPage?operation=view_relations&relation=$sRelationCode&direction=up&class=$sClass&id=$id{$sContext}") + $aActionParams; - } - } - } - if ($bLocked && $bRawModifiedAllowed) { - // Add a special menu to kill the lock, but only to allowed users who can also modify this object - /** @var array $aAllowedProfiles */ - $aAllowedProfiles = MetaModel::GetConfig()->Get('concurrent_lock_override_profiles'); - $bCanKill = false; - - $oUser = UserRights::GetUserObject(); - $aUserProfiles = array(); - if (!is_null($oUser)) { - $oProfileSet = $oUser->Get('profile_list'); - while ($oProfile = $oProfileSet->Fetch()) { - $aUserProfiles[$oProfile->Get('profile')] = true; - } - } - - foreach ($aAllowedProfiles as $sProfile) { - if (array_key_exists($sProfile, $aUserProfiles)) { - $bCanKill = true; - break; - } - } - - if ($bCanKill) { - $this->AddMenuSeparator($aActions); - $aActions['concurrent_lock_unlock'] = array('label' => Dict::S('UI:Menu:KillConcurrentLock'), 'url' => "{$sRootUrl}pages/$sUIPage?operation=kill_lock&class=$sClass&id=$id{$sContext}"); - } - } } - $this->AddMenuSeparator($aActions); - /** @var \iApplicationUIExtension $oExtensionInstance */ - foreach (MetaModel::EnumPlugins('iApplicationUIExtension') as $oExtensionInstance) { - $oSet->Rewind(); - foreach ($oExtensionInstance->EnumAllowedActions($oSet) as $sLabel => $sUrl) { - $aActions[$sLabel] = array('label' => $sLabel, 'url' => $sUrl) + $aActionParams; - } - } - } - break; - - default: - // Check rights - // New / Modify - $bIsModifyAllowed = UserRights::IsActionAllowed($sClass, UR_ACTION_MODIFY, $oSet) && ($oReflectionClass->IsSubclassOf('cmdbAbstractObject')); - $bIsBulkModifyAllowed = (!MetaModel::IsAbstract($sClass)) && UserRights::IsActionAllowed($sClass, UR_ACTION_BULK_MODIFY, $oSet) && ($oReflectionClass->IsSubclassOf('cmdbAbstractObject')); - $bIsBulkDeleteAllowed = UserRights::IsActionAllowed($sClass, UR_ACTION_BULK_DELETE, $oSet); - if (isset($aExtraParams['link_attr'])) - { - $id = $aExtraParams['object_id']; - $sTargetAttr = $aExtraParams['target_attr']; - $oAttDef = MetaModel::GetAttributeDef($sClass, $sTargetAttr); - $sTargetClass = $oAttDef->GetTargetClass(); - if ($bIsModifyAllowed) { $aActions['UI:Menu:Add'] = array ('label' => Dict::S('UI:Menu:Add'), 'url' => "{$sRootUrl}pages/$sUIPage?operation=modify_links&class=$sClass&link_attr=".$aExtraParams['link_attr']."&target_class=$sTargetClass&id=$id&addObjects=true{$sContext}") + $aActionParams; } - if ($bIsBulkModifyAllowed) { $aActions['UI:Menu:Manage'] = array ('label' => Dict::S('UI:Menu:Manage'), 'url' => "{$sRootUrl}pages/$sUIPage?operation=modify_links&class=$sClass&link_attr=".$aExtraParams['link_attr']."&target_class=$sTargetClass&id=$id{$sContext}") + $aActionParams; } - //if ($bIsBulkDeleteAllowed) { $aActions[] = array ('label' => 'Remove All...', 'url' => "#") + $aActionParams; } } - else - { - // many objects in the set, possible actions are: new / modify all / delete all - if ($bIsCreationAllowed) { $aActions['UI:Menu:New'] = array ('label' => Dict::S('UI:Menu:New'), 'url' => "{$sRootUrl}pages/$sUIPage?operation=new&class=$sClass{$sContext}{$sDefault}") + $aActionParams; } - if ($bIsBulkModifyAllowed) { $aActions['UI:Menu:ModifyAll'] = array ('label' => Dict::S('UI:Menu:ModifyAll'), 'url' => "{$sRootUrl}pages/$sUIPage?operation=select_for_modify_all&class=$sClass&filter=".urlencode($sFilter)."{$sContext}") + $aActionParams; } - if ($bIsBulkDeleteAllowed) { $aActions['UI:Menu:BulkDelete'] = array ('label' => Dict::S('UI:Menu:BulkDelete'), 'url' => "{$sRootUrl}pages/$sUIPage?operation=select_for_deletion&filter=".urlencode($sFilter)."{$sContext}") + $aActionParams; } - // Stimuli - $aStates = MetaModel::EnumStates($sClass); - // Do not perform time consuming computations if there are too may objects in the list - $iLimit = MetaModel::GetConfig()->Get('complex_actions_limit'); - - if ((count($aStates) > 0) && (($iLimit == 0) || ($oSet->CountWithLimit($iLimit + 1) < $iLimit))) - { - // Life cycle actions may be available... if all objects are in the same state - // - // Group by - $oGroupByExp = new FieldExpression(MetaModel::GetStateAttributeCode($sClass), $this->m_oFilter->GetClassAlias()); - $aGroupBy = array('__state__' => $oGroupByExp); - $aQueryParams = array(); - if (isset($aExtraParams['query_params'])) - { - $aQueryParams = $aExtraParams['query_params']; - } - $sSql = $this->m_oFilter->MakeGroupByQuery($aQueryParams, $aGroupBy); - $aRes = CMDBSource::QueryToArray($sSql); - if (count($aRes) == 1) - { - // All objects are in the same state... - $sState = $aRes[0]['__state__']; - $aTransitions = Metamodel::EnumTransitions($sClass, $sState); - if (count($aTransitions)) - { - $this->AddMenuSeparator($aActions); - $aStimuli = Metamodel::EnumStimuli($sClass); - foreach($aTransitions as $sStimulusCode => $aTransitionDef) - { - $oSet->Rewind(); - // As soon as the user rights implementation will browse the object set, - // then we might consider using OptimizeColumnLoad() here - $iActionAllowed = UserRights::IsStimulusAllowed($sClass, $sStimulusCode, $oSet); - $iActionAllowed = (get_class($aStimuli[$sStimulusCode]) == 'StimulusUserAction') ? $iActionAllowed : UR_ALLOWED_NO; - switch($iActionAllowed) - { - case UR_ALLOWED_YES: - case UR_ALLOWED_DEPENDS: - $aActions[$sStimulusCode] = array('label' => $aStimuli[$sStimulusCode]->GetLabel(), 'url' => "{$sRootUrl}pages/UI.php?operation=select_bulk_stimulus&stimulus=$sStimulusCode&state=$sState&class=$sClass&filter=".urlencode($sFilter)."{$sContext}") + $aActionParams; - break; - - default: - // Do nothing - } - } - } + $this->AddMenuSeparator($aActions); + /** @var \iApplicationUIExtension $oExtensionInstance */ + foreach (MetaModel::EnumPlugins('iApplicationUIExtension') as $oExtensionInstance) { + $oSet->Rewind(); + foreach ($oExtensionInstance->EnumAllowedActions($oSet) as $sLabel => $data) { + if (is_array($data)) { + // New plugins can provide javascript handlers via the 'onclick' property + //TODO: enable extension of different menus by checking the 'target' property ?? + $aActions[$sLabel] = [ + 'label' => $sLabel, + 'url' => isset($data['url']) ? $data['url'] : '#', + 'onclick' => isset($data['onclick']) ? $data['onclick'] : '' + ]; + } else { + // Backward compatibility with old plugins + $aActions[$sLabel] = ['label' => $sLabel, 'url' => $data] + $aActionParams; } } } - } - - $this->AddMenuSeparator($aActions); - /** @var \iApplicationUIExtension $oExtensionInstance */ - foreach (MetaModel::EnumPlugins('iApplicationUIExtension') as $oExtensionInstance) { - $oSet->Rewind(); - foreach ($oExtensionInstance->EnumAllowedActions($oSet) as $sLabel => $data) { - if (is_array($data)) { - // New plugins can provide javascript handlers via the 'onclick' property - //TODO: enable extension of different menus by checking the 'target' property ?? - $aActions[$sLabel] = ['label' => $sLabel, 'url' => isset($data['url']) ? $data['url'] : '#', 'onclick' => isset($data['onclick']) ? $data['onclick'] : '']; - } else { - // Backward compatibility with old plugins - $aActions[$sLabel] = ['label' => $sLabel, 'url' => $data] + $aActionParams; - } + if (empty($sRefreshAction) && $this->m_sStyle == 'list') { + //for the detail page this var is defined way beyond this line + $sRefreshAction = "window.location.reload();"; } + } else + { + //it's easier just display configure this list and MENU_OBJLIST_TOOLKIT } $param = null; $iMenuId = null; @@ -1891,10 +1955,6 @@ JS $oActionsBlock->AddSubBlock($oActionButton); } - if (empty($sRefreshAction) && $this->m_sStyle == 'list') { - //for the detail page this var is defined way beyond this line - $sRefreshAction = "window.location.reload();"; - } if (!$oPage->IsPrintableVersion() && ($sRefreshAction != '')) { $oActionButton = ButtonFactory::MakeAlternativeNeutral('', 'UI:Button:Refresh'); $oActionButton->SetIconClass('fas fa-sync') diff --git a/application/ui.linkswidget.class.inc.php b/application/ui.linkswidget.class.inc.php index 5e2869369..d283a89b7 100644 --- a/application/ui.linkswidget.class.inc.php +++ b/application/ui.linkswidget.class.inc.php @@ -559,7 +559,27 @@ HTML $oBlock = new DisplayBlock($oFilter, 'list', false); $oBlock->Display($oP, "ResultsToAdd_{$this->m_sAttCode}", array('menu' => false, 'cssCount'=> '#count_'.$this->m_sAttCode.$this->m_sNameSuffix , 'selection_mode' => true, 'table_id' => 'add_'.$this->m_sAttCode)); // Don't display the 'Actions' menu on the results } + /** + * Display one row of the whole form + * @param WebPage $oP + * @param array $aConfig + * @param array $aRow + * @param int $iRowId + * @return string + * @deprecated in 3.0 + */ + protected function DisplayFormRow(WebPage $oP, $aConfig, $aRow, $iRowId) + { + $sHtml = ''; + $sHtml .= "m_sAttCode}{$this->m_sNameSuffix}_row_$iRowId\">\n"; + foreach($aConfig as $sName=>$void) + { + $sHtml .= "\n"; + } + $sHtml .= "\n"; + return $sHtml; + } /** * @param WebPage $oP * @param int $iMaxAddedId diff --git a/js/search/search_form_handler.js b/js/search/search_form_handler.js index 368ea5fdf..dc0d4b581 100644 --- a/js/search/search_form_handler.js +++ b/js/search/search_form_handler.js @@ -348,14 +348,14 @@ $(function() me._submit(); }); // - Toggle icon - this.element.find('.sf_title').on('click', function(oEvent){ + this.element.find('.ibo-panel--header').on('click', function(oEvent){ // Prevent anchors oEvent.preventDefault(); // Prevent toggle on ', + title: + {% if oUIBlock.GetOption("select") == "multi" %} + '' + {% else %} + '' + {% endif %}, "type": "html", "data": "", "render": function (data, type, row) { - var oCheckboxElem = $(''); + var oCheckboxElem = + {% if oUIBlock.GetOption("select") == "multi" %} + $(''); + {% else %} + $(''); + {% endif %} if (row.limited_access) { oCheckboxElem.html('-'); } else { diff --git a/templates/components/datatable/static/formtable/layout.html.twig b/templates/components/datatable/static/formtable/layout.html.twig index 2f20c1dd5..16e443328 100644 --- a/templates/components/datatable/static/formtable/layout.html.twig +++ b/templates/components/datatable/static/formtable/layout.html.twig @@ -13,23 +13,8 @@ - {% for rowId,data in oUIBlock.GetData() %} - - {% for name,column in columns %} - - {% endfor %} - + {% for oSubBlock in oUIBlock.GetRows() %} + {{ render_block(oSubBlock, {aPage: aPage}) }} {% endfor %}
".$aRow[$sName]."
- {% set cellValueHtml = '' %} - {% for cellName,cellValue in data %} - {% if cellName == name %} - {% set cellValueHtml = cellValue %} - {% endif %} - {% endfor %} - {% if cellValueHtml is empty %} - {% set cellValueHtml = ' ' %} - {% endif %} - {{ cellValueHtml|raw }} -
\ No newline at end of file diff --git a/templates/components/datatable/static/formtablerow/layout.html.twig b/templates/components/datatable/static/formtablerow/layout.html.twig new file mode 100644 index 000000000..609a3e624 --- /dev/null +++ b/templates/components/datatable/static/formtablerow/layout.html.twig @@ -0,0 +1,19 @@ +{# @copyright Copyright (C) 2010-2020 Combodo SARL #} +{# @license http://opensource.org/licenses/AGPL-3.0 #} + + + {% for colName,column in oUIBlock.GetColumns() %} + + {% set cellValueHtml = '' %} + {% for cellName,cellValue in oUIBlock.GetData() %} + {% if cellName == colName %} + {% set cellValueHtml = cellValue %} + {% endif %} + {% endfor %} + {% if cellValueHtml is empty %} + {% set cellValueHtml = ' ' %} + {% endif %} + {{ cellValueHtml|raw }} + + {% endfor %} + diff --git a/templates/components/datatable/static/formtablerow/layout.js.twig b/templates/components/datatable/static/formtablerow/layout.js.twig new file mode 100644 index 000000000..e69de29bb From 434c829f7e0449357831769b2401ffacf9e7de89 Mon Sep 17 00:00:00 2001 From: Eric Date: Thu, 12 Nov 2020 18:13:57 +0100 Subject: [PATCH 14/16] Fix update objects --- application/cmdbabstract.class.inc.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/application/cmdbabstract.class.inc.php b/application/cmdbabstract.class.inc.php index 5edd3b5c0..05f4b0089 100644 --- a/application/cmdbabstract.class.inc.php +++ b/application/cmdbabstract.class.inc.php @@ -2493,6 +2493,7 @@ CSS $oForm->AddSubBlock(InputFactory::MakeForHidden('id', $iKey, "{$sPrefix}_id")); } $oForm->AddSubBlock(InputFactory::MakeForHidden('operation', $sOperation)); + $oForm->AddSubBlock(InputFactory::MakeForHidden('class', $sClass)); $oCancelButton = ButtonFactory::MakeForSecondaryAction(Dict::S('UI:Button:Cancel')); $oCancelButton->AddCSSClasses('action cancel'); @@ -2526,6 +2527,7 @@ CSS $sButtonsPosition = MetaModel::GetConfig()->Get('buttons_position'); $iTransactionId = isset($aExtraParams['transaction_id']) ? $aExtraParams['transaction_id'] : utils::GetNewTransactionId(); $oPage->SetTransactionId($iTransactionId); + $oForm->AddSubBlock(InputFactory::MakeForHidden('transaction_id', $iTransactionId)); $sStatesSelection = ''; if (!isset($aExtraParams['custom_operation']) && $this->IsNew()) { From 89c35f034545fe24e81b46aa6aa1934c498b7b72 Mon Sep 17 00:00:00 2001 From: Eric Date: Fri, 13 Nov 2020 09:56:23 +0100 Subject: [PATCH 15/16] =?UTF-8?q?N=C2=B02847=20-=20Datatables=20Fix=20exte?= =?UTF-8?q?rnal=20keys=20search?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- application/cmdbabstract.class.inc.php | 36 ++++++++----------- application/displayblock.class.inc.php | 6 ++-- core/attributedef.class.inc.php | 4 ++- .../search/searchform.class.inc.php | 9 +---- templates/components/datatable/layout.js.twig | 8 ++--- 5 files changed, 27 insertions(+), 36 deletions(-) diff --git a/application/cmdbabstract.class.inc.php b/application/cmdbabstract.class.inc.php index 05f4b0089..1824c44bb 100644 --- a/application/cmdbabstract.class.inc.php +++ b/application/cmdbabstract.class.inc.php @@ -17,10 +17,11 @@ * You should have received a copy of the GNU Affero General Public License */ +use Combodo\iTop\Application\Search\SearchForm; 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\DataTable\DataTableSettings; use Combodo\iTop\Application\UI\Component\Field\Field; use Combodo\iTop\Application\UI\Component\FieldSet\FieldSet; use Combodo\iTop\Application\UI\Component\Form\Form; @@ -58,6 +59,8 @@ require_once(APPROOT.'sources/application/search/criterionconversion/criterionto require_once(APPROOT.'sources/application/search/criterionconversion/criteriontosearchform.class.inc.php'); use Combodo\iTop\Application\UI\Component\DataTable\DataTableFactory; +use Combodo\iTop\Renderer\Console\ConsoleFormRenderer; + /** * Class cmdbAbstractObject */ @@ -390,11 +393,11 @@ EOF $aIcons[] = "
  $sLabel
"; } - if (count($aIcons) > 0) { - $sTags = '
'.implode(' ', $aIcons).'
'; - } else { - $sTags = ''; - } +// if (count($aIcons) > 0) { +// $sTags = '
'.implode(' ', $aIcons).'
'; +// } else { +// $sTags = ''; +// } $oPage->AddUiBlock(TitleFactory::MakeForObjectDetails($this)); } @@ -1105,7 +1108,7 @@ HTML */ public static function GetDisplaySet(WebPage $oPage, CMDBObjectSet $oSet, $aExtraParams = array()) { - $oPage->AddUiBlock(GetDisplaySetBlock( $oPage, $oSet, $aExtraParams )); + $oPage->AddUiBlock(static::GetDisplaySetBlock( $oPage, $oSet, $aExtraParams )); return ""; } @@ -1120,9 +1123,7 @@ HTML $iListId = $aExtraParams['currentId']; } - $oDataTable = DataTableFactory::MakeForResult($oPage, $iListId, $oSet, $aExtraParams); - - return $oDataTable; + return DataTableFactory::MakeForResult($oPage, $iListId, $oSet, $aExtraParams); } /** * @param \WebPage $oPage @@ -1722,7 +1723,7 @@ HTML */ public static function GetSearchForm(WebPage $oPage, CMDBObjectSet $oSet, $aExtraParams = array()) { - $oSearchForm = new \Combodo\iTop\Application\Search\SearchForm(); + $oSearchForm = new SearchForm(); return $oSearchForm->GetSearchForm($oPage, $oSet, $aExtraParams); } @@ -2144,7 +2145,7 @@ EOF $sHTMLValue .= "\n"; $oForm = $value->GetForm($sFormPrefix); - $oRenderer = new \Combodo\iTop\Renderer\Console\ConsoleFormRenderer($oForm); + $oRenderer = new ConsoleFormRenderer($oForm); $aRenderRes = $oRenderer->Render(); $aFieldSetOptions = array( @@ -2415,8 +2416,7 @@ JS if (isset($aExtraParams['wizard_container']) && $aExtraParams['wizard_container']) { $sClassLabel = MetaModel::GetName($sClass); - $sHeaderTitle = Dict::Format('UI:ModificationTitle_Class_Object', $sClassLabel, - $this->GetName()); + //$sHeaderTitle = Dict::Format('UI:ModificationTitle_Class_Object', $sClassLabel, $this->GetName()); $oPage->set_title(Dict::Format('UI:ModificationPageTitle_Object_Class', $this->GetRawName(), $sClassLabel)); // Set title will take care of the encoding @@ -4194,12 +4194,9 @@ EOF if ((!$bEditMode) || ($iFlags & (OPT_ATT_READONLY | OPT_ATT_SLAVE))) { // Check if the attribute is not read-only because of a synchro... - $sSynchroIcon = ''; if ($iFlags & OPT_ATT_SLAVE) { $aReasons = array(); - $iSynchroFlags = $this->GetSynchroReplicaFlags($sAttCode, $aReasons); - $sSynchroIcon = " "; $sTip = ''; foreach($aReasons as $aRow) { @@ -4218,7 +4215,6 @@ EOF $sHTMLValue .= ''; $aFieldsMap[$sAttCode] = $sInputId; - $sComment .= $sSynchroIcon; } else { @@ -4267,7 +4263,6 @@ HTML public function GetExpectedAttributes($sCurrentState, $sStimulus, $bOnlyNewOnes) { $aTransitions = $this->EnumTransitions(); - $aStimuli = MetaModel::EnumStimuli(get_class($this)); if (!isset($aTransitions[$sStimulus])) { // Invalid stimulus @@ -4588,6 +4583,7 @@ EOF */ public static function DoBulkModify($oP, $sClass, $aSelectedObj, $sCustomOperation, $bPreview, $sCancelUrl, $aContextData = array()) { + /** @var string[] $aHeaders */ $aHeaders = array( 'form::select' => array( 'label' => "", @@ -4663,7 +4659,6 @@ EOF $sFormAction = utils::GetAbsoluteUrlAppRoot().'pages/UI.php'; // No parameter in the URL, the only parameter will be the ones passed through the form // Form to submit: $oP->add("
\n"); - $aDefaults = utils::ReadParam('default', array()); $oAppContext = new ApplicationContext(); $oP->add($oAppContext->GetForForm()); foreach($aContextData as $sKey => $value) @@ -4879,7 +4874,6 @@ EOF if (count($aObjects) == 1) { $oObj = $aObjects[0]; - $id = $oObj->GetKey(); $oP->p('

'.Dict::Format('UI:Delect:Confirm_Object', $oObj->GetHyperLink()).'

'); } else diff --git a/application/displayblock.class.inc.php b/application/displayblock.class.inc.php index ff0d4af0a..511403ed8 100644 --- a/application/displayblock.class.inc.php +++ b/application/displayblock.class.inc.php @@ -17,6 +17,7 @@ * You should have received a copy of the GNU Affero General Public License */ +use Combodo\iTop\Application\Search\SearchForm; use Combodo\iTop\Application\UI\Component\Badge\BadgeFactory; use Combodo\iTop\Application\UI\Component\Button\ButtonFactory; use Combodo\iTop\Application\UI\Component\Dashlet\DashletFactory; @@ -25,6 +26,7 @@ use Combodo\iTop\Application\UI\Component\Html\Html; use Combodo\iTop\Application\UI\Component\Toolbar\Toolbar; use Combodo\iTop\Application\UI\iUIBlock; use Combodo\iTop\Application\UI\Layout\UIContentBlock; +use Combodo\iTop\Renderer\BlockRenderer; require_once(APPROOT.'/application/utils.inc.php'); @@ -513,7 +515,7 @@ class DisplayBlock $iListId = $aExtraParams['currentId']; } $oBlock = DataTableFactory::MakeForRendering( $iListId, $this->m_oSet, $aExtraParams); - $sHtml .= "".render_block($oBlock)."\n"; + $sHtml .= "".BlockRenderer::RenderBlockTemplates($oBlock)."\n"; } } $sHtml .= "\n"; @@ -733,7 +735,7 @@ class DisplayBlock if (!$oPage->IsPrintableVersion()) { $aExtraParams['currentId'] = $sId; - $oSearchForm = new \Combodo\iTop\Application\Search\SearchForm(); + $oSearchForm = new SearchForm(); $oBlock = $oSearchForm->GetSearchFormUIBlock($oPage, $this->m_oSet, $aExtraParams); } break; diff --git a/core/attributedef.class.inc.php b/core/attributedef.class.inc.php index f7f46ff03..a5a7e59ae 100644 --- a/core/attributedef.class.inc.php +++ b/core/attributedef.class.inc.php @@ -6804,7 +6804,9 @@ class AttributeExternalKey extends AttributeDBFieldVoid public function GetRenderForDataTable(string $sClassAlias) :string { - $sRenderFunction = "return 'm_aParams['targetclass']."&id='+data+'\'>'+row['".$sClassAlias."/".$this->m_sCode."_friendlyname']+'' ;"; + $oRemoteAtt = $this->GetFinalAttDef(); + $sTargetClass = $oRemoteAtt->GetTargetClass(); + $sRenderFunction = "return ''+row['".$sClassAlias."/".$this->GetCode()."_friendlyname']+'' ;"; return $sRenderFunction; } } diff --git a/sources/application/search/searchform.class.inc.php b/sources/application/search/searchform.class.inc.php index 3c8d1a105..acce218dd 100644 --- a/sources/application/search/searchform.class.inc.php +++ b/sources/application/search/searchform.class.inc.php @@ -32,13 +32,10 @@ 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; @@ -49,11 +46,10 @@ use FieldExpression; use IssueLog; use MetaModel; use MissingQueryArgument; -use ScssPhp\ScssPhp\Block; use TrueExpression; +use UserRights; use utils; use WebPage; -use UserRights; class SearchForm { @@ -63,9 +59,6 @@ class SearchForm * @param array $aExtraParams * * @return string - * @throws \CoreException - * @throws \DictExceptionMissingString - * @throws \Exception */ public function GetSearchForm(WebPage $oPage, CMDBObjectSet $oSet, $aExtraParams = array()) { diff --git a/templates/components/datatable/layout.js.twig b/templates/components/datatable/layout.js.twig index 51af1be8c..41c174e6d 100644 --- a/templates/components/datatable/layout.js.twig +++ b/templates/components/datatable/layout.js.twig @@ -99,13 +99,13 @@ var oTable{{ oUIBlock.GetId() }} = $('#{{ oUIBlock.GetId() }}').DataTable({ "processing": true, "serverSide": true, "columns": [ - {% if oUIBlock.GetOption("select") is not empty %} + {% if oUIBlock.GetOption("select_mode") is not empty %} { "width": "auto", "searchable": false, "sortable": false, - title: - {% if oUIBlock.GetOption("select") == "multi" %} + "title": + {% if oUIBlock.GetOption("select_mode") == "multi" %} '' {% else %} '' @@ -114,7 +114,7 @@ var oTable{{ oUIBlock.GetId() }} = $('#{{ oUIBlock.GetId() }}').DataTable({ "data": "", "render": function (data, type, row) { var oCheckboxElem = - {% if oUIBlock.GetOption("select") == "multi" %} + {% if oUIBlock.GetOption("select_mode") == "multi" %} $(''); {% else %} $(''); From 4c78ecab917e683f1e29c8c95eeb414371f1f468 Mon Sep 17 00:00:00 2001 From: Eric Date: Mon, 16 Nov 2020 15:02:02 +0100 Subject: [PATCH 16/16] =?UTF-8?q?N=C2=B02847=20-=20Datatables=20WIP?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- application/displayblock.class.inc.php | 234 ++++++++++-------- application/ui.linkswidget.class.inc.php | 25 +- .../Component/DataTable/DataTableFactory.php | 22 +- .../Component/DataTable/DataTableSettings.php | 7 +- .../search/searchform.class.inc.php | 3 +- templates/components/datatable/layout.js.twig | 57 +++-- 6 files changed, 181 insertions(+), 167 deletions(-) diff --git a/application/displayblock.class.inc.php b/application/displayblock.class.inc.php index 511403ed8..3b83e805e 100644 --- a/application/displayblock.class.inc.php +++ b/application/displayblock.class.inc.php @@ -45,6 +45,7 @@ class DisplayBlock protected $m_sStyle; protected $m_bAsynchronous; protected $m_aParams; + /** @var \DBObjectSet|null */ protected $m_oSet; protected $m_bShowObsoleteData = null; @@ -524,104 +525,11 @@ class DisplayBlock break; case 'list_search': + $oBlock = $this->RenderListSearch($aExtraParams, $oPage); + break; + case 'list': - $aClasses = $this->m_oSet->GetSelectedClasses(); - $aAuthorizedClasses = array(); - if (count($aClasses) > 1) - { - // Check the classes that can be read (i.e authorized) by this user... - foreach($aClasses as $sAlias => $sClassName) - { - if (UserRights::IsActionAllowed($sClassName, UR_ACTION_READ, $this->m_oSet) != UR_ALLOWED_NO) - { - $aAuthorizedClasses[$sAlias] = $sClassName; - } - } - if (count($aAuthorizedClasses) > 0) - { - if($this->m_oSet->CountWithLimit(1) > 0) - { - 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 - { - // Empty set - $sHtml .= $oPage->GetP(Dict::S('UI:NoObjectToDisplay')); - } - } - else - { - // Not authorized - $sHtml .= $oPage->GetP(Dict::S('UI:NoObjectToDisplay')); - } - } - else - { - // 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) ) - { - $oBlock = cmdbAbstractObject::GetDisplaySetBlock($oPage, $this->m_oSet, $aExtraParams); - } - else - { - $sHtml .= $oPage->GetP(Dict::S('UI:NoObjectToDisplay')); - $sClass = $this->m_oFilter->GetClass(); - $bDisplayMenu = isset($aExtraParams['menu']) ? $aExtraParams['menu'] == true : true; - if ($bDisplayMenu) - { - if ((UserRights::IsActionAllowed($sClass, UR_ACTION_MODIFY) == UR_ALLOWED_YES)) - { - $sLinkTarget = ''; - $oAppContext = new ApplicationContext(); - $sParams = $oAppContext->GetForLink(); - // 1:n links, populate the target object as a default value when creating a new linked object - if (isset($aExtraParams['target_attr'])) - { - $sLinkTarget = ' target="_blank" '; - $aExtraParams['default'][$aExtraParams['target_attr']] = $aExtraParams['object_id']; - } - $sDefault = ''; - if (!empty($aExtraParams['default'])) - { - foreach($aExtraParams['default'] as $sKey => $sValue) - { - $sDefault.= "&default[$sKey]=$sValue"; - } - } - - $sHtml .= $oPage->GetP("".Dict::Format('UI:ClickToCreateNew', Metamodel::GetName($sClass))."\n"); - } - } - } - - if (isset($aExtraParams['update_history']) && true == $aExtraParams['update_history']) - { - $sSearchFilter = $this->m_oSet->GetFilter()->serialize(); - // Limit the size of the URL (N°1585 - request uri too long) - if (strlen($sSearchFilter) < SERVER_MAX_URL_LENGTH) - { - $seventAttachedData = json_encode(array( - 'filter' => $sSearchFilter, - 'breadcrumb_id' => "ui-search-".$this->m_oSet->GetClass(), - 'breadcrumb_label' => MetaModel::GetName($this->m_oSet->GetClass()), - 'breadcrumb_max_count' => utils::GetConfig()->Get('breadcrumb.max_count'), - 'breadcrumb_instance_id' => MetaModel::GetConfig()->GetItopInstanceid(), - 'breadcrumb_icon' => 'fas fa-search', - 'breadcrumb_icon_type' => iTopWebPage::ENUM_BREADCRUMB_ENTRY_ICON_TYPE_CSS_CLASSES, - )); - - $oPage->add_ready_script("$('body').trigger('update_history.itop', [$seventAttachedData])"); - } - } - } + $oBlock = $this->RenderList($aExtraParams, $oPage); break; case 'links': @@ -732,13 +640,8 @@ class DisplayBlock break; case 'search': - if (!$oPage->IsPrintableVersion()) - { - $aExtraParams['currentId'] = $sId; - $oSearchForm = new SearchForm(); - $oBlock = $oSearchForm->GetSearchFormUIBlock($oPage, $this->m_oSet, $aExtraParams); - } - break; + $oBlock = $this->RenderSearch($oPage, $sId, $aExtraParams); + break; case 'chart': static $iChartCounter = 0; @@ -1394,6 +1297,129 @@ JS } return $oBlock; } + + /** + * @param \WebPage $oPage + * @param string|null $sId + * @param array $aExtraParams + * + * @return \Combodo\iTop\Application\UI\iUIBlock + */ + protected function RenderSearch(WebPage $oPage, ?string $sId, array $aExtraParams): iUIBlock + { + $oBlock = null; + + if (!$oPage->IsPrintableVersion()) { + $aExtraParams['currentId'] = $sId; + $oSearchForm = new SearchForm(); + $oBlock = $oSearchForm->GetSearchFormUIBlock($oPage, $this->m_oSet, $aExtraParams); + } + + return $oBlock; + } + + protected function RenderListSearch(array $aExtraParams, WebPage $oPage) + { + return $this->RenderList($aExtraParams, $oPage); + } + + /** + * @param array $aExtraParams + * @param \WebPage $oPage + * + * @throws \ArchivedObjectException + * @throws \ConfigException + * @throws \CoreException + * @throws \CoreUnexpectedValue + * @throws \DictExceptionMissingString + * @throws \MissingQueryArgument + * @throws \MySQLException + * @throws \MySQLHasGoneAwayException + * @throws \OQLException + * @throws \ReflectionException + */ + protected function RenderList(array $aExtraParams, WebPage $oPage) + { + $aClasses = $this->m_oSet->GetSelectedClasses(); + $aAuthorizedClasses = array(); + $oBlock = null; + $sHtml = ''; + if (count($aClasses) > 1) { + // Check the classes that can be read (i.e authorized) by this user... + foreach ($aClasses as $sAlias => $sClassName) { + if (UserRights::IsActionAllowed($sClassName, UR_ACTION_READ, $this->m_oSet) != UR_ALLOWED_NO) { + $aAuthorizedClasses[$sAlias] = $sClassName; + } + } + if (count($aAuthorizedClasses) > 0) { + if ($this->m_oSet->CountWithLimit(1) > 0) { + 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 { + // Empty set + $sHtml .= $oPage->GetP(Dict::S('UI:NoObjectToDisplay')); + } + } else { + // Not authorized + $sHtml .= $oPage->GetP(Dict::S('UI:NoObjectToDisplay')); + } + } else { + // 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)) { + $oBlock = cmdbAbstractObject::GetDisplaySetBlock($oPage, $this->m_oSet, $aExtraParams); + } else { + $sHtml .= $oPage->GetP(Dict::S('UI:NoObjectToDisplay')); + $sClass = $this->m_oFilter->GetClass(); + $bDisplayMenu = isset($aExtraParams['menu']) ? $aExtraParams['menu'] == true : true; + if ($bDisplayMenu) { + if ((UserRights::IsActionAllowed($sClass, UR_ACTION_MODIFY) == UR_ALLOWED_YES)) { + $sLinkTarget = ''; + $oAppContext = new ApplicationContext(); + $sParams = $oAppContext->GetForLink(); + // 1:n links, populate the target object as a default value when creating a new linked object + if (isset($aExtraParams['target_attr'])) { + $sLinkTarget = ' target="_blank" '; + $aExtraParams['default'][$aExtraParams['target_attr']] = $aExtraParams['object_id']; + } + $sDefault = ''; + if (!empty($aExtraParams['default'])) { + foreach ($aExtraParams['default'] as $sKey => $sValue) { + $sDefault .= "&default[$sKey]=$sValue"; + } + } + + $sHtml .= $oPage->GetP("".Dict::Format('UI:ClickToCreateNew', Metamodel::GetName($sClass))."\n"); + } + } + } + + if (isset($aExtraParams['update_history']) && true == $aExtraParams['update_history']) { + $sSearchFilter = $this->m_oSet->GetFilter()->serialize(); + // Limit the size of the URL (N°1585 - request uri too long) + if (strlen($sSearchFilter) < SERVER_MAX_URL_LENGTH) { + $seventAttachedData = json_encode(array( + 'filter' => $sSearchFilter, + 'breadcrumb_id' => "ui-search-".$this->m_oSet->GetClass(), + 'breadcrumb_label' => MetaModel::GetName($this->m_oSet->GetClass()), + 'breadcrumb_max_count' => utils::GetConfig()->Get('breadcrumb.max_count'), + 'breadcrumb_instance_id' => MetaModel::GetConfig()->GetItopInstanceid(), + 'breadcrumb_icon' => 'fas fa-search', + 'breadcrumb_icon_type' => iTopWebPage::ENUM_BREADCRUMB_ENTRY_ICON_TYPE_CSS_CLASSES, + )); + + $oPage->add_ready_script("$('body').trigger('update_history.itop', [$seventAttachedData])"); + } + } + } + if (is_null($oBlock)) { + $oBlock = new Html($sHtml); + } + return $oBlock; + } } /** diff --git a/application/ui.linkswidget.class.inc.php b/application/ui.linkswidget.class.inc.php index b10342ca6..aab215339 100644 --- a/application/ui.linkswidget.class.inc.php +++ b/application/ui.linkswidget.class.inc.php @@ -487,7 +487,7 @@ JS if (!$this->m_bDuplicatesAllowed && count($aAlreadyLinkedIds) > 0) { $oAlreadyLinkedFilter->AddCondition('id', $aAlreadyLinkedIds, 'NOTIN'); $oAlreadyLinkedExpression = $oAlreadyLinkedFilter->GetCriteria(); - $sAlreadyLinkedExpression = $oAlreadyLinkedExpression->Render(); + $sAlreadyLinkedExpression = $oAlreadyLinkedExpression->RenderExpression(); } else { $sAlreadyLinkedExpression = ''; } @@ -505,7 +505,7 @@ JS array( 'menu' => false, 'result_list_outer_selector' => "SearchResultsToAdd_{$this->m_sAttCode}{$this->m_sNameSuffix}", - 'table_id' => 'add_'.$this->m_sAttCode, + 'table_id' => "add_{$this->m_sAttCode}{$this->m_sNameSuffix}", 'table_inner_id' => "ResultsToAdd_{$this->m_sAttCode}{$this->m_sNameSuffix}", 'selection_mode' => true, 'json' => $sJson, @@ -566,27 +566,7 @@ HTML $oBlock = new DisplayBlock($oFilter, 'list', false); $oBlock->Display($oP, "ResultsToAdd_{$this->m_sAttCode}", array('menu' => false, 'cssCount'=> '#count_'.$this->m_sAttCode.$this->m_sNameSuffix , 'selection_mode' => true, 'table_id' => 'add_'.$this->m_sAttCode)); // Don't display the 'Actions' menu on the results } - /** - * Display one row of the whole form - * @param WebPage $oP - * @param array $aConfig - * @param array $aRow - * @param int $iRowId - * @return string - * @deprecated in 3.0 - */ - protected function DisplayFormRow(WebPage $oP, $aConfig, $aRow, $iRowId) - { - $sHtml = ''; - $sHtml .= "m_sAttCode}{$this->m_sNameSuffix}_row_$iRowId\">\n"; - foreach($aConfig as $sName=>$void) - { - $sHtml .= "".$aRow[$sName]."\n"; - } - $sHtml .= "\n"; - return $sHtml; - } /** * @param WebPage $oP * @param int $iMaxAddedId @@ -607,7 +587,6 @@ HTML if (is_object($oLinkedObj)) { $aRow = $this->GetFormRow($oP, $oLinkedObj, $iObjectId, array(), $oCurrentObj, $iAdditionId); // Not yet created link get negative Ids - //$oP->add($this->DisplayFormRow($oP, $this->m_aTableConfig, $aRow, -$iAdditionId)); $oRow = new FormTableRow("{$this->m_sAttCode}{$this->m_sNameSuffix}", $this->m_aTableConfig, $aRow, -$iAdditionId); $oP->AddUiBlock($oRow); $iAdditionId++; diff --git a/sources/application/UI/Component/DataTable/DataTableFactory.php b/sources/application/UI/Component/DataTable/DataTableFactory.php index 59bb3e30a..1d7841f64 100644 --- a/sources/application/UI/Component/DataTable/DataTableFactory.php +++ b/sources/application/UI/Component/DataTable/DataTableFactory.php @@ -7,20 +7,21 @@ namespace Combodo\iTop\Application\UI\Component\DataTable; use ApplicationException; +use appUserPreferences; use AttributeLinkedSet; -use CMDBObjectSet; use cmdbAbstractObject; +use CMDBObjectSet; use Combodo\iTop\Application\UI\Component\DataTable\StaticTable\FormTable\FormTable; use Combodo\iTop\Application\UI\Component\DataTable\StaticTable\StaticTable; use Combodo\iTop\Application\UI\Component\Panel\PanelFactory; use Combodo\iTop\Application\UI\Component\Title\TitleFactory; -use MetaModel; -use appUserPreferences; -use UserRights; -use MenuBlock; use Combodo\iTop\Application\UI\Layout\UIContentBlock; -use WebPage; +use DBObjectSet; use Dict; +use MenuBlock; +use MetaModel; +use UserRights; +use WebPage; /** * Class DataTableFactory @@ -67,7 +68,7 @@ class DataTableFactory /** * @param \WebPage $oPage * @param string $sListId - * @param \CMDBObjectSet $oSet + * @param DBObjectSet $oSet * @param array $aExtraParams * * @return \Combodo\iTop\Application\UI\Component\Panel\Panel @@ -81,7 +82,7 @@ class DataTableFactory * @throws \OQLException * @throws \ReflectionException */ - public static function MakeForObject(WebPage $oPage, string $sListId, CMDBObjectSet $oSet, $aExtraParams = array()) + public static function MakeForObject(WebPage $oPage, string $sListId, DBObjectSet $oSet, $aExtraParams = array()) { $oPanel = PanelFactory::MakeForClass($oSet->GetClass(), "Result"); $oDataTable = DataTableFactory::MakeForRenderingObject($sListId, $oSet, $aExtraParams); @@ -345,7 +346,7 @@ class DataTableFactory /** * @param string $sListId - * @param \CMDBObjectSet $oSet + * @param DBObjectSet $oSet * @param array $aExtraParams * * @return \Combodo\iTop\Application\UI\Component\DataTable\DataTableBlock @@ -355,7 +356,7 @@ class DataTableFactory * @throws \DictExceptionMissingString * @throws \MySQLException */ - public static function MakeForRenderingObject(string $sListId, CMDBObjectSet $oSet, $aExtraParams = array()) + public static function MakeForRenderingObject(string $sListId, DBObjectSet $oSet, $aExtraParams = array()) { $oDataTable = new DataTableBlock('datatable_'.$sListId); $aList = array(); @@ -476,6 +477,7 @@ class DataTableFactory if($sSelectMode!="") { $iIndexColumn++; } + $aSortDatable = []; foreach ($aClassAliases as $sClassAlias => $sClassName) { foreach ($oCustomSettings->aColumns[$sClassAlias] as $sAttCode => $aData) { if ($aData['sort'] != 'none') { diff --git a/sources/application/UI/Component/DataTable/DataTableSettings.php b/sources/application/UI/Component/DataTable/DataTableSettings.php index 6b5f5a2f0..d2f4ffa56 100644 --- a/sources/application/UI/Component/DataTable/DataTableSettings.php +++ b/sources/application/UI/Component/DataTable/DataTableSettings.php @@ -7,6 +7,7 @@ use AttributeDashboard; use AttributeFriendlyName; use AttributeLinkedSet; use cmdbAbstract; +use cmdbAbstractObject; use Dict; use Metamodel; use Serializable; @@ -106,7 +107,7 @@ class DataTableSettings implements Serializable * @param $bViewLink * @param $aDefaultLists * - * @return \DataTableSettings + * @return DataTableSettings * @throws \CoreException * @throws \DictExceptionMissingString */ @@ -118,7 +119,7 @@ class DataTableSettings implements Serializable $aColumns = array(); foreach ($aClassAliases as $sAlias => $sClass) { if ($aDefaultLists == null) { - $aList = cmdbAbstract::FlattenZList(MetaModel::GetZListItems($sClass, 'list')); + $aList = cmdbAbstractObject::FlattenZList(MetaModel::GetZListItems($sClass, 'list')); } else { $aList = $aDefaultLists[$sAlias]; } @@ -189,7 +190,7 @@ class DataTableSettings implements Serializable * @param null $sTableId * @param bool $bOnlyOnTable * - * @return \DataTableSettings|null + * @return DataTableSettings|null * @throws \Exception */ static public function GetTableSettings($aClassAliases, $sTableId = null, $bOnlyOnTable = false) diff --git a/sources/application/search/searchform.class.inc.php b/sources/application/search/searchform.class.inc.php index acce218dd..069059055 100644 --- a/sources/application/search/searchform.class.inc.php +++ b/sources/application/search/searchform.class.inc.php @@ -65,7 +65,8 @@ class SearchForm $oPage->AddUiBlock($this->GetSearchFormUIBlock($oPage, $oSet, $aExtraParams)); return ''; } - public function GetSearchFormUIBlock(WebPage $oPage, CMDBObjectSet $oSet, $aExtraParams = array()) + + public function GetSearchFormUIBlock(WebPage $oPage, DBObjectSet $oSet, $aExtraParams = array()) { $oUiBlock = new UIContentBlock(); $oAppContext = new ApplicationContext(); diff --git a/templates/components/datatable/layout.js.twig b/templates/components/datatable/layout.js.twig index 41c174e6d..3fa99d332 100644 --- a/templates/components/datatable/layout.js.twig +++ b/templates/components/datatable/layout.js.twig @@ -1,9 +1,10 @@ function checkAllDataTable(table, value) { + // Set the 'selectionMode' for the future objects to load + var selectionMode = 'positive'; if (value) { - $(table).DataTable().rows().select(); - } else { - $(table).DataTable().rows({page: 'current'}).deselect(); + selectionMode = 'negative'; } + // Mark all the displayed items as check or unchecked depending on the value $(table).find(':checkbox[name^=selectObj]:not([disabled])').each(function () { var $currentCheckbox = $(this); @@ -11,15 +12,18 @@ function checkAllDataTable(table, 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"); + + if (value) { + $(table).DataTable().rows().select(); + } else { + $(table).DataTable().rows({page: 'current'}).deselect(); + } + return true; } @@ -27,8 +31,8 @@ $('#{{ oUIBlock.GetId() }}').closest("[role=dialog]").on("dialogbeforeclose", fu $('#{{ oUIBlock.GetId() }}').DataTable().clear(); }); -{% if oUIBlock.GetOptions()["select_mode"] is defined %} -var oSelectedItems{{ oUIBlock.GetOptions()['sTableId'] }} = []; +{% if oUIBlock.GetOption("select_mode") is defined %} +var oSelectedItems{{ oUIBlock.GetOption('sTableId') }} = []; {% endif %} if ($.fn.dataTable.isDataTable('#{{ oUIBlock.GetId() }}')) { @@ -64,19 +68,19 @@ var oTable{{ oUIBlock.GetId() }} = $('#{{ oUIBlock.GetId() }}').DataTable({ "order":[], {% endif %} "ordering": true, - {% if oUIBlock.GetOptions()["select_mode"] is defined %} + {% if oUIBlock.GetOption("select_mode") is defined %} "select": { - "style": "{{ oUIBlock.GetOptions()["select_mode"] }}" + "style": "{{ oUIBlock.GetOption("select_mode") }}" }, "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'] }}) { + if (!oData.id in oSelectedItems{{ oUIBlock.GetOption('sTableId') }}) { $(oRow).select(); $(oRow).find('td:first-child input').prop('checked', true); } } else { - if (oData.id in oSelectedItems{{ oUIBlock.GetOptions()['sTableId'] }}) { + if (oData.id in oSelectedItems{{ oUIBlock.GetOption('sTableId') }}) { $(oRow).select(); $(oRow).find('td:first-child input').prop('checked', true); } @@ -105,7 +109,7 @@ var oTable{{ oUIBlock.GetId() }} = $('#{{ oUIBlock.GetId() }}').DataTable({ "searchable": false, "sortable": false, "title": - {% if oUIBlock.GetOption("select_mode") == "multi" %} + {% if oUIBlock.GetOption("select_mode") != "single" %} '' {% else %} '' @@ -114,7 +118,7 @@ var oTable{{ oUIBlock.GetId() }} = $('#{{ oUIBlock.GetId() }}').DataTable({ "data": "", "render": function (data, type, row) { var oCheckboxElem = - {% if oUIBlock.GetOption("select_mode") == "multi" %} + {% if oUIBlock.GetOption("select_mode") != "single" %} $(''); {% else %} $(''); @@ -171,16 +175,17 @@ oTable{{ oUIBlock.GetId() }}.off('select').on('select', function (oEvent, dt, ty // 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.GetOption('sTableId') }}.indexOf(iItemId) === -1) { + oSelectedItems{{ oUIBlock.GetOption('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); + if ((oSelectedItems{{ oUIBlock.GetOption('sTableId') }}.length === oTable{{ oUIBlock.GetId() }}.page.info()["recordsTotal"] && $(this).closest('.ibo-panel--body').find('[name=selectionMode]').val() === "negative")) { + $('#btn_ok_{{ oUIBlock.GetOption('sTableId') }}').prop('disabled', true); } else { - $('#btn_ok_{{ oUIBlock.GetOptions()['sTableId'] }}').prop('disabled', false); + $('#btn_ok_{{ oUIBlock.GetOption('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(); @@ -189,14 +194,14 @@ oTable{{ oUIBlock.GetId() }}.off('deselect').on('deselect', function (oEvent, dt // 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.GetOption('sTableId') }}.indexOf(iItemId) > -1) { + oSelectedItems{{ oUIBlock.GetOption('sTableId') }}.splice(oSelectedItems{{ oUIBlock.GetOption('sTableId') }}.indexOf(iItemId), 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); + if ((oSelectedItems{{ oUIBlock.GetOption('sTableId') }}.length === 0 && $(this).closest('.ibo-panel--body').find('[name=selectionMode]').val() === "positive")) { + $('#btn_ok_{{ oUIBlock.GetOption('sTableId') }}').prop('disabled', true); } else { - $('#btn_ok_{{ oUIBlock.GetOptions()['sTableId'] }}').prop('disabled', false); + $('#btn_ok_{{ oUIBlock.GetOption('sTableId') }}').prop('disabled', false); } });