mirror of
https://github.com/Combodo/iTop.git
synced 2026-04-22 01:58:47 +02:00
N°2844 - Continue work on object details: Quick fixes for alpha, will need to be refactored
- Improve display of details in creation/modification/transition modes
This commit is contained in:
@@ -30,6 +30,7 @@ use Combodo\iTop\Application\UI\Layout\MultiColumn\Column\Column;
|
||||
use Combodo\iTop\Application\UI\Layout\MultiColumn\MultiColumn;
|
||||
use Combodo\iTop\Application\UI\Layout\UIContentBlock;
|
||||
use Combodo\iTop\Application\UI\Layout\Object\ObjectFactory;
|
||||
use Combodo\iTop\Application\UI\Component\Panel\Panel;
|
||||
|
||||
define('OBJECT_PROPERTIES_TAB', 'ObjectProperties');
|
||||
|
||||
@@ -388,9 +389,6 @@ EOF
|
||||
$aIcons[] = "<div class=\"tag\" title=\"$sTitle\"><span class=\"object-obsolete fas fa-eye-slash fa-1x\"> </span> $sLabel</div>";
|
||||
}
|
||||
|
||||
$sObjectIcon = $this->GetIcon();
|
||||
$sClassName = MetaModel::GetName(get_class($this));
|
||||
$sObjectName = $this->GetName();
|
||||
if (count($aIcons) > 0) {
|
||||
$sTags = '<div class="tags">'.implode(' ', $aIcons).'</div>';
|
||||
} else {
|
||||
@@ -450,7 +448,7 @@ EOF
|
||||
|
||||
// Special case to display the case log, if any...
|
||||
// WARNING: if you modify the loop below, also check the corresponding code in UpdateObject and DisplayModifyForm
|
||||
// TODO 2.8.0: Remove when sure everything has been migrated
|
||||
// TODO 3.0.0: Remove when sure everything has been migrated (CHECK THE WARNING ABOVE!)
|
||||
// foreach(MetaModel::ListAttributeDefs(get_class($this)) as $sAttCode => $oAttDef)
|
||||
// {
|
||||
// if ($oAttDef instanceof AttributeCaseLog)
|
||||
@@ -978,86 +976,26 @@ EOF
|
||||
$iKey = $this->GetKey();
|
||||
$sMode = static::ENUM_OBJECT_MODE_VIEW;
|
||||
|
||||
// Object's details
|
||||
// TODO 3.0.0: Complete the factory
|
||||
$oObjectDetails = ObjectFactory::MakeDetails($this);
|
||||
// $oPage->AddUiBlock($oObjectDetails);
|
||||
|
||||
|
||||
// TODO 2.8.0: Remove this when object details block completed, this is hardcoded for the demo
|
||||
$oPage->add_style(<<<CSS
|
||||
.object-details .ibo-title {
|
||||
z-index: 1;
|
||||
align-items: start;
|
||||
position: relative;
|
||||
padding-left: 32px;
|
||||
}
|
||||
.object-details .ibo-title .ibo-title--medallion {
|
||||
position: absolute;
|
||||
margin-top: 16px;
|
||||
}
|
||||
.object-details .ibo-title .ibo-title--content {
|
||||
margin-left: calc(90px + 32px);
|
||||
}
|
||||
.object-details .ibo-panel {
|
||||
z-index: 0;
|
||||
}
|
||||
.object-details .ibo-panel > .ibo-panel--body {
|
||||
padding: 8px 16px 0px;
|
||||
}
|
||||
.object-details .ibo-panel > .ibo-panel--body > .ibo-tab-container > .ibo-tab-container--tabs-list{
|
||||
margin-left: -16px;
|
||||
margin-right: -16px;
|
||||
padding-left: calc(32px + 90px + 32px - 24px);
|
||||
}
|
||||
.object-details .ibo-panel > .ibo-panel--body > .ibo-tab-container > .ibo-tab-container--tab-container{
|
||||
margin-left: -16px;
|
||||
margin-right: -16px;
|
||||
}
|
||||
.object-details .ibo-panel > .ibo-panel--body > .ibo-tab-container.ibo-is-vertical{
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
.object-details .ibo-panel > .ibo-panel--body > .ibo-tab-container.ibo-is-vertical > .ibo-tab-container--tabs-list{
|
||||
padding-top: 50px;
|
||||
flex-direction: column;
|
||||
height: auto;
|
||||
padding-left: unset;
|
||||
margin-right: unset;
|
||||
min-width: calc(32px + 90px + 32px);
|
||||
}
|
||||
.object-details .ibo-panel > .ibo-panel--body > .ibo-tab-container.ibo-is-vertical > .ibo-tab-container--tabs-list > .ibo-tab-container--tab-header{
|
||||
height: 50px;
|
||||
width: 100%;
|
||||
justify-content: left;
|
||||
}
|
||||
.object-details .ibo-panel > .ibo-panel--body > .ibo-tab-container.ibo-is-vertical > .ibo-tab-container--tabs-list > .ibo-tab-container--tab-header > .ibo-tab-container--tab-toggler{
|
||||
width: 100%;
|
||||
justify-content: left;
|
||||
}
|
||||
.object-details .ibo-panel > .ibo-panel--body > .ibo-tab-container.ibo-is-vertical > .ibo-tab-container--tab-container {
|
||||
flex-grow: 1;
|
||||
margin-left: unset;
|
||||
}
|
||||
CSS
|
||||
);
|
||||
|
||||
$oPage->add(<<<HTML
|
||||
<!-- Beginning of object-details -->
|
||||
<div id="search-widget-results-outer" class="object-details" data-object-class="$sClass" data-object-id="$iKey" data-object-mode="$sMode">
|
||||
HTML
|
||||
);
|
||||
$this->DisplayBareHeader($oPage, $bEditMode);
|
||||
|
||||
/** @var \iTopWebPage $oPage */
|
||||
$oPage->AddTabContainer(OBJECT_PROPERTIES_TAB);
|
||||
$this->DisplayBareHeader($oPage, $bEditMode);
|
||||
// Object's details
|
||||
// TODO 3.0.0: Complete the factory
|
||||
$oObjectDetails = ObjectFactory::MakeDetails($this);
|
||||
$oPage->AddUiBlock($oObjectDetails);
|
||||
|
||||
$oPage->AddTabContainer(OBJECT_PROPERTIES_TAB, '', $oObjectDetails);
|
||||
$oPage->SetCurrentTabContainer(OBJECT_PROPERTIES_TAB);
|
||||
$oPage->SetCurrentTab('UI:PropertiesTab');
|
||||
$this->DisplayBareProperties($oPage, $bEditMode);
|
||||
$this->DisplayBareRelations($oPage, $bEditMode);
|
||||
//$oPage->SetCurrentTab('UI:HistoryTab');
|
||||
//$this->DisplayBareHistory($oPage, $bEditMode);
|
||||
// TODO 3.0.0: What to do with this?
|
||||
//$oPage->AddAjaxTab('UI:HistoryTab', utils::GetAbsoluteUrlAppRoot().'pages/ajax.render.php?operation=history&class='.$sClass.'&id='.$iKey);
|
||||
//$this->DisplayBareHistory($oPage, $bEditMode);
|
||||
$oPage->add(<<<HTML
|
||||
</div><!-- End of object-details -->
|
||||
HTML
|
||||
@@ -2645,13 +2583,26 @@ JS
|
||||
->SetOnSubmitJsCode("return OnSubmit('form_{$this->m_iFormId}');");
|
||||
$oContentBlock->AddSubBlock($oForm);
|
||||
|
||||
// TODO 3.0.0: Dehardcode this after object details are refactored
|
||||
$oPage->add_style(<<<CSS
|
||||
.ibo-toolbar{
|
||||
margin: 6px 0;
|
||||
}
|
||||
.ibo-toolbar-top{
|
||||
padding-left: calc(90px + 64px);
|
||||
}
|
||||
CSS
|
||||
);
|
||||
$oToolbarTop = new Toolbar();
|
||||
$oToolbarTop->SetCSSClasses('ibo-toolbar ibo-toolbar-top');
|
||||
|
||||
|
||||
if ($sMode === static::ENUM_OBJECT_MODE_EDIT) {
|
||||
// The object already exists in the database, it's a modification
|
||||
$oForm->AddSubBlock(InputFactory::MakeForHidden('id', $iKey, "{$sPrefix}_id"));
|
||||
}
|
||||
$oForm->AddSubBlock(InputFactory::MakeForHidden('operation', $sOperation));
|
||||
|
||||
$oCancelButton = ButtonFactory::MakeForSecondaryAction(Dict::S('UI:Button:Cancel'));
|
||||
$oCancelButton->AddCSSClasses('action cancel');
|
||||
$oToolbarTop->AddSubBlock($oCancelButton);
|
||||
@@ -2739,7 +2690,11 @@ EOF
|
||||
$oForm->AddSubBlock($oToolbarTop);
|
||||
}
|
||||
|
||||
$oPage->AddTabContainer(OBJECT_PROPERTIES_TAB, $sPrefix, $oForm);
|
||||
|
||||
// TODO 3.0.0: Use ObjectDetails block when ready.
|
||||
$oPanel = new Panel;
|
||||
$oForm->AddSubBlock($oPanel);
|
||||
$oPage->AddTabContainer(OBJECT_PROPERTIES_TAB, $sPrefix, $oPanel);
|
||||
$oPage->SetCurrentTabContainer(OBJECT_PROPERTIES_TAB);
|
||||
$oPage->SetCurrentTab('UI:PropertiesTab');
|
||||
|
||||
@@ -2772,6 +2727,7 @@ EOF
|
||||
// bottom or both: display the buttons here
|
||||
$oPage->p($sStatesSelection);
|
||||
$oToolbarBottom = new Toolbar();
|
||||
$oToolbarBottom->SetCSSClasses('ibo-toolbar');
|
||||
foreach ($oToolbarTop->GetSubBlocks() as $oButton) {
|
||||
$oToolbarBottom->AddSubBlock($oButton);
|
||||
}
|
||||
|
||||
@@ -30,4 +30,5 @@
|
||||
@import "activity-panel/caselog-entry";
|
||||
@import "activity-panel/edits-entry";
|
||||
@import "activity-panel/transition-entry";
|
||||
@import "activity-panel/activity-new-entry-form";
|
||||
@import "activity-panel/activity-new-entry-form";
|
||||
@import "blocks-integrations/panel-with-tab-container";
|
||||
|
||||
@@ -3,24 +3,50 @@
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
$ibo-object-details--body--padding-top: $ibo-panel--highlight--height !default;
|
||||
$ibo-object-details--tabs-list--margin-x: -1 * $ibo-panel--body--padding-x !default;
|
||||
// TODO 3.0.0: This is temporary to make object forms work while it is being migrated to the blocks syste.
|
||||
// When there is a real ObjectDetails block, rework this to match the block conventions.
|
||||
|
||||
$ibo-object-details--tab-container--margin-x: -1 * $ibo-panel--body--padding-x !default;
|
||||
|
||||
.ibo-object-details.ibo-panel {
|
||||
> .ibo-panel--body {
|
||||
padding-top: $ibo-object-details--body--padding-top;
|
||||
|
||||
> .ibo-tab-container {
|
||||
> .ibo-tab-container--tabs-list{
|
||||
margin-left: $ibo-object-details--tabs-list--margin-x;
|
||||
margin-right: $ibo-object-details--tabs-list--margin-x;
|
||||
}
|
||||
> .ibo-tab-container--tab-container{
|
||||
margin-left: $ibo-object-details--tab-container--margin-x;
|
||||
margin-right: $ibo-object-details--tab-container--margin-x;
|
||||
}
|
||||
}
|
||||
}
|
||||
.object-details .ibo-title {
|
||||
z-index: 1;
|
||||
align-items: start;
|
||||
position: relative;
|
||||
padding-left: 32px;
|
||||
}
|
||||
.object-details .ibo-title .ibo-title--medallion {
|
||||
position: absolute;
|
||||
margin-top: 16px;
|
||||
}
|
||||
.object-details .ibo-title .ibo-title--content {
|
||||
margin-left: calc(90px + 32px);
|
||||
}
|
||||
.object-details .ibo-panel {
|
||||
z-index: 0;
|
||||
}
|
||||
.object-details .ibo-panel > .ibo-panel--body > .ibo-tab-container > .ibo-tab-container--tabs-list{
|
||||
padding-left: calc(32px + 90px + 32px - 24px);
|
||||
}
|
||||
.object-details .ibo-panel > .ibo-panel--body > .ibo-tab-container.ibo-is-vertical{
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
.object-details .ibo-panel > .ibo-panel--body > .ibo-tab-container.ibo-is-vertical > .ibo-tab-container--tabs-list{
|
||||
padding-top: 50px;
|
||||
flex-direction: column;
|
||||
height: auto;
|
||||
padding-left: unset;
|
||||
margin-right: unset;
|
||||
min-width: calc(32px + 90px + 32px);
|
||||
}
|
||||
.object-details .ibo-panel > .ibo-panel--body > .ibo-tab-container.ibo-is-vertical > .ibo-tab-container--tabs-list > .ibo-tab-container--tab-header{
|
||||
height: 50px;
|
||||
width: 100%;
|
||||
justify-content: left;
|
||||
}
|
||||
.object-details .ibo-panel > .ibo-panel--body > .ibo-tab-container.ibo-is-vertical > .ibo-tab-container--tabs-list > .ibo-tab-container--tab-header > .ibo-tab-container--tab-toggler{
|
||||
width: 100%;
|
||||
justify-content: left;
|
||||
}
|
||||
.object-details .ibo-panel > .ibo-panel--body > .ibo-tab-container.ibo-is-vertical > .ibo-tab-container--tab-container {
|
||||
flex-grow: 1;
|
||||
margin-left: unset;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/*!
|
||||
* @copyright Copyright (C) 2010-2020 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
$ibo-panel-with-tab-container--body--padding-top: $ibo-panel--highlight--height !default;
|
||||
$ibo-panel-with-tab-container--tabs-list--margin-x: -1 * $ibo-panel--body--padding-x !default;
|
||||
|
||||
$ibo-panel-with-tab-container--tab-container--margin-x: -1 * $ibo-panel--body--padding-x !default;
|
||||
|
||||
.ibo-panel {
|
||||
> .ibo-panel--body {
|
||||
padding-top: $ibo-panel-with-tab-container--body--padding-top;
|
||||
|
||||
> .ibo-tab-container {
|
||||
> .ibo-tab-container--tabs-list{
|
||||
margin-left: $ibo-panel-with-tab-container--tabs-list--margin-x;
|
||||
margin-right: $ibo-panel-with-tab-container--tabs-list--margin-x;
|
||||
}
|
||||
> .ibo-tab-container--tab-container{
|
||||
margin-left: $ibo-panel-with-tab-container--tab-container--margin-x;
|
||||
margin-right: $ibo-panel-with-tab-container--tab-container--margin-x;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,10 +8,126 @@ namespace Combodo\iTop\Application\UI\Layout\Object;
|
||||
|
||||
|
||||
use Combodo\iTop\Application\UI\Component\Panel\Panel;
|
||||
use DBObject;
|
||||
use MetaModel;
|
||||
|
||||
class ObjectDetails extends Panel
|
||||
{
|
||||
// Overloaded constants
|
||||
public const BLOCK_CODE = 'ibo-object-details';
|
||||
public const HTML_TEMPLATE_REL_PATH = 'layouts/object/object-details/layout';
|
||||
|
||||
/** @var string */
|
||||
protected $sClassName;
|
||||
/** @var string */
|
||||
protected $sClassLabel;
|
||||
/** @var string */
|
||||
protected $sName;
|
||||
/** @var string */
|
||||
protected $sIconUrl;
|
||||
/** @var string */
|
||||
protected $sStatusCode;
|
||||
/** @var string */
|
||||
protected $sStatusLabel;
|
||||
/** @var string */
|
||||
protected $sStatusColor;
|
||||
|
||||
/**
|
||||
* ObjectDetails constructor.
|
||||
*
|
||||
* @param \DBObject $oObject
|
||||
* @param string|null $sId
|
||||
*
|
||||
* @throws \CoreException
|
||||
*/
|
||||
public function __construct(DBObject $oObject, ?string $sId = null) {
|
||||
$this->sClassName = get_class($oObject);
|
||||
$this->sClassLabel = MetaModel::GetName($this->GetClassName());
|
||||
// Note: We get the raw name as only the front-end consumer knows when and how to encode it.
|
||||
$this->sName = $oObject->GetRawName();
|
||||
$this->sIconUrl = $oObject->GetIcon(false);
|
||||
|
||||
$sStatusAttCode = MetaModel::GetStateAttributeCode($this->sClassName);
|
||||
if(!empty($sStatusAttCode)) {
|
||||
$this->sStatusCode = $oObject->GetState();
|
||||
$this->sStatusLabel = $oObject->GetStateLabel();
|
||||
// TODO 3.0.0 : Dehardcode this
|
||||
switch ($this->sStatusCode) {
|
||||
case 'new':
|
||||
$this->sStatusColor = 'new';
|
||||
break;
|
||||
|
||||
case 'waiting_for_approval':
|
||||
case 'pending':
|
||||
$this->sStatusColor = 'waiting';
|
||||
break;
|
||||
|
||||
case 'escalated_tto':
|
||||
case 'escalated_ttr':
|
||||
case 'rejected':
|
||||
$this->sStatusColor = 'failure';
|
||||
break;
|
||||
|
||||
case 'resolved':
|
||||
$this->sStatusColor = 'success';
|
||||
break;
|
||||
|
||||
case 'closed':
|
||||
$this->sStatusColor = 'frozen';
|
||||
break;
|
||||
|
||||
case 'approved':
|
||||
case 'assigned':
|
||||
case 'dispatched':
|
||||
case 'redispatched':
|
||||
default:
|
||||
$this->sStatusColor = 'neutral';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
parent::__construct('', [], static::DEFAULT_COLOR, $sId);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function GetClassName(): string
|
||||
{
|
||||
return $this->sClassName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function GetObjectName(): string
|
||||
{
|
||||
return $this->sName;
|
||||
}
|
||||
|
||||
public function SetStatus($sCode, $sLabel, $sColor)
|
||||
{
|
||||
$this->sStatusCode = $sColor;
|
||||
$this->sStatusLabel = $sLabel;
|
||||
$this->sStatusColor = $sColor;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function GetStatusCode(): string
|
||||
{
|
||||
return $this->sStatusCode;
|
||||
}
|
||||
|
||||
public function GetStatusLabel(): string
|
||||
{
|
||||
return $this->sStatusLabel;
|
||||
}
|
||||
|
||||
public function GetStatusColor(): string
|
||||
{
|
||||
return $this->sStatusColor;
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,6 @@ class ObjectFactory {
|
||||
* @return \Combodo\iTop\Application\UI\Layout\Object\ObjectDetails
|
||||
*/
|
||||
public static function MakeDetails(DBObject $oObject) {
|
||||
return new ObjectDetails();
|
||||
return new ObjectDetails($oObject);
|
||||
}
|
||||
}
|
||||
@@ -317,6 +317,7 @@ class WebPage implements Page
|
||||
*/
|
||||
public function AddUiBlock(?iUIBlock $oBlock): ?iUIBlock
|
||||
{
|
||||
// TODO 3.0.0: Why make this parameter nullable?!
|
||||
if (is_null($oBlock)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user