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:
Molkobain
2020-10-15 15:51:50 +02:00
parent e7f01e7597
commit 9a47e3cf74
7 changed files with 221 additions and 95 deletions

View File

@@ -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\">&nbsp;</span>&nbsp;$sLabel</div>";
}
$sObjectIcon = $this->GetIcon();
$sClassName = MetaModel::GetName(get_class($this));
$sObjectName = $this->GetName();
if (count($aIcons) > 0) {
$sTags = '<div class="tags">'.implode('&nbsp;', $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);
}

View File

@@ -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";

View File

@@ -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;
}

View File

@@ -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;
}
}
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}