mirror of
https://github.com/Combodo/iTop.git
synced 2026-05-17 06:18:44 +02:00
N°3203 - Datamodel: Add semantic for image & state attributes Part. I
This commit is contained in:
@@ -853,12 +853,28 @@ abstract class MetaModel
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the $sClass has a state attribute defined
|
||||
*
|
||||
* @param string $sClass Datamodel class to check
|
||||
*
|
||||
* @return bool
|
||||
* @throws \CoreException
|
||||
* @since 3.0.0
|
||||
*/
|
||||
final public static function HasStateAttributeCode(string $sClass)
|
||||
{
|
||||
return !empty(self::GetStateAttributeCode($sClass));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the code of the attribute carrying the state of the instance of the class
|
||||
*
|
||||
* @param string $sClass
|
||||
*
|
||||
* @return string
|
||||
* @throws \CoreException
|
||||
*/
|
||||
final public static function GetStateAttributeCode($sClass)
|
||||
final public static function GetStateAttributeCode(string $sClass)
|
||||
{
|
||||
self::_check_subclass($sClass);
|
||||
|
||||
@@ -872,7 +888,7 @@ abstract class MetaModel
|
||||
* @throws \CoreException
|
||||
* @throws \Exception
|
||||
*/
|
||||
final public static function GetDefaultState($sClass)
|
||||
final public static function GetDefaultState(string $sClass)
|
||||
{
|
||||
$sDefaultState = '';
|
||||
$sStateAttrCode = self::GetStateAttributeCode($sClass);
|
||||
@@ -884,6 +900,36 @@ abstract class MetaModel
|
||||
return $sDefaultState;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the $sClass has an image attribute defined
|
||||
*
|
||||
* @param string $sClass
|
||||
*
|
||||
* @return bool
|
||||
* @throws \CoreException
|
||||
* @since 3.0.0
|
||||
*/
|
||||
final public static function HasImageAttributeCode(string $sClass)
|
||||
{
|
||||
return !empty(self::GetImageAttributeCode($sClass));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the code of the attribute carrying the image representing an instance of the class
|
||||
*
|
||||
* @param string $sClass Datamodel class to get the image attribute code for
|
||||
*
|
||||
* @return mixed
|
||||
* @throws \CoreException
|
||||
* @since 3.0.0
|
||||
*/
|
||||
final public static function GetImageAttributeCode(string $sClass)
|
||||
{
|
||||
self::_check_subclass($sClass);
|
||||
|
||||
return self::$m_aClassParams[$sClass]["image_attcode"];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sClass
|
||||
*
|
||||
@@ -3245,11 +3291,12 @@ abstract class MetaModel
|
||||
public static function Init_Params($aParams)
|
||||
{
|
||||
// Check mandatory params
|
||||
// Warning: Do not put image_attcode as a mandatory attribute or it will break all PHP datamodel classes
|
||||
$aMandatParams = array(
|
||||
"category" => "group classes by modules defining their visibility in the UI",
|
||||
"key_type" => "autoincrement | string",
|
||||
"name_attcode" => "define wich attribute is the class name, may be an array of attributes (format specified in the dictionary as 'Class:myclass/Name' => '%1\$s %2\$s...'",
|
||||
"state_attcode" => "define wich attribute is representing the state (object lifecycle)",
|
||||
"name_attcode" => "define which attribute is the class name, may be an array of attributes (format specified in the dictionary as 'Class:myclass/Name' => '%1\$s %2\$s...'",
|
||||
"state_attcode" => "define which attribute is representing the state (object lifecycle)",
|
||||
"reconc_keys" => "define the attributes that will 'almost uniquely' identify an object in batch processes",
|
||||
"db_table" => "database table",
|
||||
"db_key_field" => "database field which is the key",
|
||||
|
||||
@@ -10,7 +10,8 @@ $ibo-title--medallion--background-color: $ibo-color-grey-100 !default;
|
||||
$ibo-title--medallion--border: 2px solid $ibo-color-blue-grey-300 !default;
|
||||
$ibo-title--medallion--border-radius: $ibo-border-radius-full !default;
|
||||
|
||||
$ibo-title--icon--size: 66.67% !default;
|
||||
$ibo-title--icon--size--must-cover: 100% !default;
|
||||
$ibo-title--icon--size--must-zoomout: 66.67% !default;
|
||||
|
||||
$ibo-title--status-dot--size: 10px !default;
|
||||
$ibo-title--status-dot--spacing: 8px !default;
|
||||
@@ -26,6 +27,8 @@ $ibo-title--status-dot--border-radius: $ibo-border-radius-full !default;
|
||||
@extend %ibo-fully-centered-content;
|
||||
width: $ibo-title--medallion--size;
|
||||
height: $ibo-title--medallion--size;
|
||||
min-width: $ibo-title--medallion--size;
|
||||
min-height: $ibo-title--medallion--size;
|
||||
overflow: hidden;
|
||||
|
||||
background-color: $ibo-title--medallion--background-color;
|
||||
@@ -33,11 +36,14 @@ $ibo-title--status-dot--border-radius: $ibo-border-radius-full !default;
|
||||
border-radius: $ibo-title--medallion--border-radius;
|
||||
}
|
||||
.ibo-title--icon {
|
||||
width: $ibo-title--icon--size;
|
||||
width: $ibo-title--icon--size--must-cover;
|
||||
height: auto;
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
}
|
||||
.ibo-title--icon--must-zoomout {
|
||||
width: $ibo-title--icon--size--must-zoomout;
|
||||
}
|
||||
|
||||
.ibo-title--emphasis {
|
||||
|
||||
|
||||
@@ -1040,8 +1040,7 @@ class ObjectController extends BrickController
|
||||
$sHostId = $sObjectId;
|
||||
|
||||
// Security bypass for the image attribute of a class
|
||||
// Note: This will be changed with a proper DM check when corresponding bug is being worked on
|
||||
if(is_a($sObjectClass, 'Contact', true) && ($sObjectField === 'picture')){
|
||||
if(MetaModel::GetImageAttributeCode($sObjectClass) === $sObjectField) {
|
||||
$bCheckSecurity = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -984,6 +984,9 @@ public function PrefillSearchForm(&$aContextParam)
|
||||
<attribute id="name"/>
|
||||
</attributes>
|
||||
</naming>
|
||||
<semantic>
|
||||
<image_attribute>icon</image_attribute>
|
||||
</semantic>
|
||||
<icon>images/service.png</icon>
|
||||
<reconciliation>
|
||||
<attributes>
|
||||
@@ -1066,6 +1069,9 @@ public function PrefillSearchForm(&$aContextParam)
|
||||
<attribute id="name"/>
|
||||
</attributes>
|
||||
</naming>
|
||||
<semantic>
|
||||
<image_attribute>icon</image_attribute>
|
||||
</semantic>
|
||||
<icon>images/service.png</icon>
|
||||
<reconciliation>
|
||||
<attributes>
|
||||
|
||||
@@ -876,6 +876,9 @@ public function PrefillSearchForm(&$aContextParam)
|
||||
<attribute id="name"/>
|
||||
</attributes>
|
||||
</naming>
|
||||
<semantic>
|
||||
<image_attribute>icon</image_attribute>
|
||||
</semantic>
|
||||
<icon>images/service.png</icon>
|
||||
<reconciliation>
|
||||
<attributes>
|
||||
@@ -958,6 +961,9 @@ public function PrefillSearchForm(&$aContextParam)
|
||||
<attribute id="name"/>
|
||||
</attributes>
|
||||
</naming>
|
||||
<semantic>
|
||||
<image_attribute>icon</image_attribute>
|
||||
</semantic>
|
||||
<icon>images/service.png</icon>
|
||||
<reconciliation>
|
||||
<attributes>
|
||||
|
||||
@@ -514,6 +514,9 @@
|
||||
<attribute id="name"/>
|
||||
</attributes>
|
||||
</naming>
|
||||
<semantic>
|
||||
<image_attribute>picture</image_attribute>
|
||||
</semantic>
|
||||
<icon>images/person.png</icon>
|
||||
<reconciliation>
|
||||
<attributes>
|
||||
|
||||
@@ -997,6 +997,7 @@ EOF
|
||||
$aClassParams['is_link'] = 'true';
|
||||
}
|
||||
|
||||
// Naming
|
||||
if ($oNaming = $oProperties->GetOptionalElement('naming'))
|
||||
{
|
||||
$oNameAttributes = $oNaming->GetUniqueElement('attributes');
|
||||
@@ -1023,18 +1024,37 @@ EOF
|
||||
$sNameAttCode = "''";
|
||||
}
|
||||
$aClassParams['name_attcode'] = $sNameAttCode;
|
||||
|
||||
$oLifecycle = $oClass->GetOptionalElement('lifecycle');
|
||||
if ($oLifecycle)
|
||||
{
|
||||
$sStateAttCode = $oLifecycle->GetChildText('attribute');
|
||||
}
|
||||
else
|
||||
{
|
||||
$sStateAttCode = "";
|
||||
|
||||
// Semantic
|
||||
// - Default attributes code
|
||||
$sImageAttCode = "";
|
||||
$sStateAttCode = "";
|
||||
// - Parse optional semantic node
|
||||
$oSemantic = $oProperties->GetOptionalElement('semantic');
|
||||
if ($oSemantic) {
|
||||
// Image attribute
|
||||
$oImageAttribute = $oSemantic->GetOptionalElement('image_attribute');
|
||||
if ($oImageAttribute) {
|
||||
$sImageAttCode = $oImageAttribute->GetText();
|
||||
}
|
||||
|
||||
// State attribute, only if not already found from lifecycle
|
||||
// $oStateAttribute = $oSemantic->GetOptionalElement('state_attribute');
|
||||
// if(empty($sStateAttCode) && $oStateAttribute) {
|
||||
// $sStateAttCode = $oStateAttribute->GetText();
|
||||
// }
|
||||
}
|
||||
$aClassParams['image_attcode'] = "'$sImageAttCode'";
|
||||
$aClassParams['state_attcode'] = "'$sStateAttCode'";
|
||||
|
||||
|
||||
// Lifecycle (overload any state attribute defined in the semantic node)
|
||||
$oLifecycle = $oClass->GetOptionalElement('lifecycle');
|
||||
if ($oLifecycle) {
|
||||
$sStateAttCode = $oLifecycle->GetChildText('attribute');
|
||||
$aClassParams['state_attcode'] = "'$sStateAttCode'";
|
||||
}
|
||||
|
||||
// Reconcialiation
|
||||
if ($oReconciliation = $oProperties->GetOptionalElement('reconciliation'))
|
||||
{
|
||||
$oReconcAttributes = $oReconciliation->getElementsByTagName('attribute');
|
||||
|
||||
@@ -17,22 +17,37 @@ use Combodo\iTop\Application\UI\UIBlock;
|
||||
class Title extends UIBlock
|
||||
{
|
||||
// Overloaded constants
|
||||
/** @inheritDoc */
|
||||
public const BLOCK_CODE = 'ibo-title';
|
||||
/** @inheritDoc */
|
||||
public const HTML_TEMPLATE_REL_PATH = 'components/title/layout';
|
||||
|
||||
/** @var string Icon should cover all the space, best for icons with filled background */
|
||||
public const ENUM_ICON_COVER_METHOD_COVER = 'cover';
|
||||
/** @var string Icon should be a litte zoomed out to cover almost all space, best for icons with transparent background and no margin around (eg. class icons) */
|
||||
public const ENUM_ICON_COVER_METHOD_ZOOMOUT = 'zoomout';
|
||||
/** @var string */
|
||||
public const DEFAULT_ICON_COVER_METHOD = self::ENUM_ICON_COVER_METHOD_COVER;
|
||||
|
||||
/** @var string */
|
||||
protected $sTitle;
|
||||
/** @var int */
|
||||
protected $iLevel;
|
||||
/** @var string */
|
||||
protected $sIconHtml;
|
||||
protected $sIconUrl;
|
||||
/** @var string How the icon should cover the medallion, see static::ENUM_ICON_COVER_METHOD_COVER, static::ENUM_ICON_COVER_METHOD_ZOOMOUT */
|
||||
protected $sIconCoverMethod;
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function __construct(string $sTitle = '', int $iLevel = 1, ?string $sId = null)
|
||||
{
|
||||
parent::__construct($sId);
|
||||
$this->sTitle = $sTitle;
|
||||
$this->iLevel = $iLevel;
|
||||
$this->sIconHtml = null;
|
||||
$this->sIconUrl = null;
|
||||
$this->sIconCoverMethod = static::DEFAULT_ICON_COVER_METHOD;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -51,20 +66,26 @@ class Title extends UIBlock
|
||||
return $this->iLevel;
|
||||
}
|
||||
|
||||
public function SetIcon(string $sIconHtml): self
|
||||
public function SetIcon(string $sIconUrl, string $sIconCoverMethod = self::DEFAULT_ICON_COVER_METHOD)
|
||||
{
|
||||
$this->sIconHtml = $sIconHtml;
|
||||
$this->sIconUrl = $sIconUrl;
|
||||
$this->sIconCoverMethod = $sIconCoverMethod;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function GetIcon(): string
|
||||
public function GetIconUrl(): string
|
||||
{
|
||||
return $this->sIconHtml;
|
||||
return $this->sIconUrl;
|
||||
}
|
||||
|
||||
public function GetIconCoverMethod(): string
|
||||
{
|
||||
return $this->sIconCoverMethod;
|
||||
}
|
||||
|
||||
public function HasIcon(): string
|
||||
{
|
||||
return !is_null($this->sIconHtml);
|
||||
return !is_null($this->sIconUrl);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -23,13 +23,31 @@ class TitleFactory
|
||||
public static function MakeForObjectDetails(DBObject $oObject, ?string $sId = null)
|
||||
{
|
||||
// TODO 3.0.0: Refactor all of this
|
||||
$sObjIconUrl = $oObject->GetIcon(false);
|
||||
$sObjClass = get_class($oObject);
|
||||
$sObjClassName = MetaModel::GetName($sObjClass);
|
||||
$sObjName = $oObject->GetName();
|
||||
|
||||
// Object icon
|
||||
// - Default icon is the class icon
|
||||
$sObjIconUrl = $oObject->GetIcon(false);
|
||||
// Note: Class icons are a square image with no margin around, so they need to be zoomed out in the medallion
|
||||
$sIconCoverMethod = Title::ENUM_ICON_COVER_METHOD_ZOOMOUT;
|
||||
// - Use object image from seantic attribute only if it's not the default image
|
||||
if(!$oObject->IsNew()){
|
||||
$sImageAttCode = MetaModel::GetImageAttributeCode($sObjClass);
|
||||
if(!empty($sImageAttCode)){
|
||||
/** @var \ormDocument $oImage */
|
||||
$oImage = $oObject->Get($sImageAttCode);
|
||||
if(!$oImage->IsEmpty()){
|
||||
$sObjIconUrl = $oImage->GetDisplayURL($sObjClass, $oObject->GetKey(), $sImageAttCode);
|
||||
$sIconCoverMethod = Title::ENUM_ICON_COVER_METHOD_COVER;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$oTitle = new TitleForObjectDetails($sObjClassName, $sObjName, $sId);
|
||||
$oTitle->SetIcon($sObjIconUrl);
|
||||
$oTitle->SetIcon($sObjIconUrl, $sIconCoverMethod);
|
||||
|
||||
$sStatusAttCode = MetaModel::GetStateAttributeCode($sObjClass);
|
||||
if (!empty($sStatusAttCode)) {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<div class="ibo-title">
|
||||
{% if oUIBlock.HasIcon() %}
|
||||
<div class="ibo-title--medallion">
|
||||
<img class="ibo-title--icon" src="{{ oUIBlock.GetIcon() }}" />
|
||||
<img class="ibo-title--icon ibo-title--icon--must-{{ oUIBlock.GetIconCoverMethod() }}" src="{{ oUIBlock.GetIconUrl() }}" />
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="ibo-title--content">
|
||||
|
||||
Reference in New Issue
Block a user