mirror of
https://github.com/Combodo/iTop.git
synced 2026-05-17 22:39:03 +02:00
N°3191 - Introduce summary cards for objects hyperlinks (#476)
This commit is contained in:
@@ -20,6 +20,7 @@
|
||||
use Combodo\iTop\Application\Helper\Session;
|
||||
use Combodo\iTop\Application\UI\Base\iUIBlock;
|
||||
use Combodo\iTop\Application\UI\Base\Layout\UIContentBlock;
|
||||
use Combodo\iTop\Core\MetaModel\FriendlyNameType;
|
||||
use ScssPhp\ScssPhp\Compiler;
|
||||
use ScssPhp\ScssPhp\OutputStyle;
|
||||
use ScssPhp\ScssPhp\ValueConverter;
|
||||
@@ -3362,4 +3363,5 @@ HTML;
|
||||
{
|
||||
return in_array($sTrait, self::TraitsUsedByClass($sClass, true));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1315,7 +1315,7 @@ abstract class DBObject implements iDisplay
|
||||
* @throws \CoreException
|
||||
* @throws \DictExceptionMissingString
|
||||
*/
|
||||
public static function MakeHyperLink($sObjClass, $sObjKey, $sHtmlLabel = '', $sUrlMakerClass = null, $bWithNavigationContext = true, $bArchived = false, $bObsolete = false)
|
||||
public static function MakeHyperLink($sObjClass, $sObjKey, $sHtmlLabel = '', $sUrlMakerClass = null, $bWithNavigationContext = true, $bArchived = false, $bObsolete = false, $bIgnorePreview = false)
|
||||
{
|
||||
if ($sObjKey <= 0) return '<em>'.Dict::S('UI:UndefinedObject').'</em>'; // Objects built in memory have negative IDs
|
||||
|
||||
@@ -1385,7 +1385,11 @@ abstract class DBObject implements iDisplay
|
||||
{
|
||||
$sHLink = $sIcon.$sHtmlLabel;
|
||||
}
|
||||
$sRet = "<span class=\"object-ref $sSpanClass\" title=\"$sHint\">$sHLink</span>";
|
||||
$sPreview = '';
|
||||
if(SummaryCardService::IsAllowedForClass($sObjClass) && $bIgnorePreview === false){
|
||||
$sPreview = SummaryCardService::GetHyperlinkMarkup($sObjClass, $sObjKey);
|
||||
}
|
||||
$sRet = "<span class=\"object-ref $sSpanClass\" $sPreview title=\"$sHint\">$sHLink</span>";
|
||||
return $sRet;
|
||||
}
|
||||
|
||||
@@ -1404,7 +1408,7 @@ abstract class DBObject implements iDisplay
|
||||
* @throws CoreException
|
||||
* @throws DictExceptionMissingString
|
||||
*/
|
||||
public function GetHyperlink($sUrlMakerClass = null, $bWithNavigationContext = true, $sLabel = null)
|
||||
public function GetHyperlink($sUrlMakerClass = null, $bWithNavigationContext = true, $sLabel = null, $bIgnorePreview = false)
|
||||
{
|
||||
if($sLabel === null)
|
||||
{
|
||||
@@ -1412,7 +1416,7 @@ abstract class DBObject implements iDisplay
|
||||
}
|
||||
$bArchived = $this->IsArchived();
|
||||
$bObsolete = $this->IsObsolete();
|
||||
return self::MakeHyperLink(get_class($this), $this->GetKey(), $sLabel, $sUrlMakerClass, $bWithNavigationContext, $bArchived, $bObsolete);
|
||||
return self::MakeHyperLink(get_class($this), $this->GetKey(), $sLabel, $sUrlMakerClass, $bWithNavigationContext, $bArchived, $bObsolete, $bIgnorePreview);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -7664,6 +7664,7 @@ abstract class MetaModel
|
||||
MetaModel::RegisterZList("noneditable", array("description" => "non editable fields", "type" => "attributes"));
|
||||
|
||||
MetaModel::RegisterZList("details", array("description" => "All attributes to be displayed for the 'details' of an object", "type" => "attributes"));
|
||||
MetaModel::RegisterZList("summary", array("description" => "All attributes to be displayed for shorter 'details' of an object", "type" => "attributes"));
|
||||
MetaModel::RegisterZList("list", array("description" => "All attributes to be displayed for a list of objects", "type" => "attributes"));
|
||||
MetaModel::RegisterZList("preview", array("description" => "All attributes visible in preview mode", "type" => "attributes"));
|
||||
|
||||
|
||||
@@ -12,13 +12,13 @@
|
||||
@import "fieldset/all";
|
||||
@import "form/all";
|
||||
@import "input/all";
|
||||
@import "object/all";
|
||||
@import "panel/all";
|
||||
@import "pill/all";
|
||||
@import "dashlet/all";
|
||||
@import "add-to-dashboard";
|
||||
@import "caselog-entry-form-within-activity-panel";
|
||||
@import "tab-container-within-panel";
|
||||
@import "object-details-with-tab-container";
|
||||
@import "medallion-with-blocklist";
|
||||
@import "field-badge-within-datatable";
|
||||
@import "jquery-blockui-within-dialog";
|
||||
|
||||
7
css/backoffice/blocks-integrations/object/_all.scss
Normal file
7
css/backoffice/blocks-integrations/object/_all.scss
Normal file
@@ -0,0 +1,7 @@
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2023 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
@import "object-details-with-tab-container";
|
||||
@import "object-summary-within-tippy";
|
||||
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2023 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
$ibo-vendors-tippy--object-summary--background-color: $ibo-color-transparent !default;
|
||||
$ibo-vendors-tippy--object-summary--color: $ibo-body-text-color !default;
|
||||
|
||||
.tippy-box[data-theme~='object-summary'] {
|
||||
background-color: $ibo-vendors-tippy--object-summary--background-color;
|
||||
color: $ibo-vendors-tippy--object-summary--color;
|
||||
.tippy-arrow {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
@@ -12,5 +12,5 @@
|
||||
@import "multi-column/column";
|
||||
@import "dashboard/all";
|
||||
@import "wizard-container/wizard-container";
|
||||
@import "object/object-details";
|
||||
@import "object/all";
|
||||
@import "activity-panel/all";
|
||||
|
||||
@@ -4,3 +4,4 @@
|
||||
*/
|
||||
|
||||
@import "object-details";
|
||||
@import "object-summary";
|
||||
|
||||
78
css/backoffice/layout/object/_object-summary.scss
Normal file
78
css/backoffice/layout/object/_object-summary.scss
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2023 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
$ibo-object-summary--header--margin-y: $ibo-panel--highlight--height!default;
|
||||
$ibo-object-summary--header--margin-x: (-$ibo-panel--body--padding-x) !default;
|
||||
|
||||
$ibo-object-summary--header--padding-y: $ibo-spacing-300 !default;
|
||||
$ibo-object-summary--header--padding-x: $ibo-spacing-0 !default;
|
||||
|
||||
$ibo-object-summary--header--background-color: $ibo-tab-container--tabs-list--background-color !default;
|
||||
$ibo-object-summary--header--border: solid 1px $ibo-color-grey-400 !default;
|
||||
|
||||
$ibo-object-summary--icon--background-color--as-medallion: $ibo-panel--icon--background-color--as-medallion !default;
|
||||
$ibo-object-summary--icon--border--as-medallion: 1px solid $ibo-color-blue-grey-300;
|
||||
$ibo-object-summary--icon--border-radius--as-medallion: $ibo-panel--icon--border-radius--as-medallion !default;
|
||||
|
||||
$ibo-object-summary--titles--padding-left: $ibo-panel--icon--spacing !default;
|
||||
|
||||
$ibo-object-summary--header-left--margin-left: $ibo-panel--icon--spacing--as-medallion !default;
|
||||
|
||||
$ibo-object-summary--header-right--margin-right: $ibo-panel--icon--spacing--as-medallion !default;
|
||||
$ibo-object-summary--header-right--margin-left: $ibo-spacing-300 !default;
|
||||
|
||||
$ibo-object-summary--panel--padding-top: $ibo-spacing-0 !default;
|
||||
$ibo-object-summary--panel--padding-box-shadow: $ibo-elevation-300 !default;
|
||||
|
||||
$ibo-object-summary--content--attributes--width: 100% !default;
|
||||
$ibo-object-summary--content--attributes--margin-top: $ibo-spacing-500 !default;
|
||||
|
||||
$ibo-object-summary--content--attributes--code--padding-right: $ibo-spacing-500 !default;
|
||||
|
||||
.ibo-object-summary--header{
|
||||
margin: $ibo-object-summary--header--margin-y $ibo-object-summary--header--margin-x;
|
||||
padding: $ibo-object-summary--header--padding-y $ibo-object-summary--header--padding-x;
|
||||
background-color: $ibo-object-summary--header--background-color;
|
||||
border-bottom: $ibo-object-summary--header--border;
|
||||
@extend .ibo-panel--header;
|
||||
.ibo-panel--icon {
|
||||
overflow: hidden;
|
||||
background-color: $ibo-panel--icon--background-color--as-medallion;
|
||||
border: $ibo-object-summary--icon--border--as-medallion;
|
||||
border-radius: $ibo-panel--icon--border-radius--as-medallion;
|
||||
}
|
||||
// We duplicate this rule from _panel.scss as a protection was added and disallow titles and header that are not direct child of panel
|
||||
.ibo-panel--titles {
|
||||
padding-left: $ibo-object-summary--titles--padding-left;
|
||||
}
|
||||
// We duplicate this rule from _panel.scss as a protection was added and disallow titles and header that are not direct child of panel
|
||||
.ibo-panel--header-left{
|
||||
margin-left: $ibo-object-summary--header-left--margin-left;
|
||||
}
|
||||
.ibo-panel--header-right{
|
||||
align-self: start;
|
||||
margin-right: $ibo-object-summary--header-right--margin-right;
|
||||
margin-left: $ibo-object-summary--header-right--margin-left;
|
||||
}
|
||||
}
|
||||
|
||||
.ibo-object-summary > .ibo-panel--body{
|
||||
padding-top: $ibo-object-summary--panel--padding-top;
|
||||
box-shadow: $ibo-object-summary--panel--padding-box-shadow;
|
||||
}
|
||||
|
||||
.ibo-object-summary--content--attributes {
|
||||
display: table;
|
||||
width: 100%;
|
||||
margin-top: $ibo-object-summary--content--attributes--margin-top;
|
||||
}
|
||||
|
||||
.ibo-object-summary--content--attributes--code, .ibo-object-summary--content--attributes--value {
|
||||
display: table-cell;
|
||||
}
|
||||
|
||||
.ibo-object-summary--content--attributes--code{
|
||||
@extend .ibo-font-ral-bol-150;
|
||||
}
|
||||
@@ -558,6 +558,7 @@ We hope you’ll enjoy this version as much as we enjoyed imagining and creating
|
||||
'UI:Menu:OtherActions' => 'Other Actions',
|
||||
'UI:Menu:Transitions' => 'Transitions',
|
||||
'UI:Menu:OtherTransitions' => 'Other Transitions',
|
||||
'UI:Menu:View' => 'View this object',
|
||||
'UI:Menu:New' => 'New...',
|
||||
'UI:Menu:Add' => 'Add...',
|
||||
'UI:Menu:Manage' => 'Manage...',
|
||||
|
||||
@@ -502,6 +502,7 @@ Nous espérons que vous aimerez cette version autant que nous avons eu du plaisi
|
||||
'UI:Menu:OtherActions' => 'Autres Actions',
|
||||
'UI:Menu:Transitions' => 'Transitions',
|
||||
'UI:Menu:OtherTransitions' => 'Autres Transitions',
|
||||
'UI:Menu:View' => 'Voir cet objet',
|
||||
'UI:Menu:New' => 'Créer...',
|
||||
'UI:Menu:Add' => 'Ajouter...',
|
||||
'UI:Menu:Manage' => 'Gérer...',
|
||||
|
||||
@@ -24,6 +24,8 @@ Dict::Add('EN US', 'English', 'English', array(
|
||||
'UI:Preferences:General:Title' => 'General',
|
||||
'UI:Preferences:General:Theme' => 'Theme',
|
||||
'UI:Preferences:General:Theme:DefaultThemeLabel' => '%1$s (default)',
|
||||
'UI:Favorites:General:ShowSummaryCards' => 'Show summary cards',
|
||||
'UI:Favorites:General:ShowSummaryCards+' => 'When hovering an hyperlink targeting an object, display a short summary of the object',
|
||||
'UI:Preferences:Lists:Title' => 'Lists',
|
||||
'UI:Preferences:RichText:Title' => 'Rich text editor',
|
||||
'UI:Preferences:RichText:ToolbarState' => 'Toolbar default state',
|
||||
|
||||
51
js/utils.js
51
js/utils.js
@@ -870,6 +870,15 @@ const CombodoGlobalToolbox = {
|
||||
* @since 3.0.0
|
||||
*/
|
||||
const CombodoTooltip = {
|
||||
|
||||
/**
|
||||
* Tooltips remote content once fetched from the server will be cached in this array
|
||||
* associated to their URL to avoid fetching the same content multiple times
|
||||
* @var aTooltipsRemoteContent {Object}
|
||||
* @since 3.1.0
|
||||
*/
|
||||
aTooltipsRemoteContent: {},
|
||||
|
||||
/**
|
||||
* Instantiate a tooltip on oElem from its data attributes
|
||||
*
|
||||
@@ -968,6 +977,48 @@ const CombodoTooltip = {
|
||||
(typeof sShowDelay === 'undefined') ? 200 : parseInt(sShowDelay),
|
||||
(typeof sHideDelay === 'undefined') ? null : parseInt(sHideDelay),
|
||||
];
|
||||
|
||||
// - If the content is asynchronous, bind methods to retrieve its content and cache it
|
||||
const bRemoteContent = oElem.attr('data-tooltip-is-async') === 'true'
|
||||
if(bRemoteContent) {
|
||||
oOptions['onCreate'] = function(instance) {
|
||||
instance._isFetching = false;
|
||||
instance._isLoaded = null;
|
||||
};
|
||||
oOptions['onShow'] = function(instance) {
|
||||
if (instance._isFetching || instance._isLoaded || instance._error) {
|
||||
return;
|
||||
}
|
||||
instance._isFetching = true;
|
||||
let sRemoteUrl = oOptions['content'];
|
||||
if(CombodoTooltip.aTooltipsRemoteContent[sRemoteUrl] !== undefined){
|
||||
instance.setContent(CombodoTooltip.aTooltipsRemoteContent[sRemoteUrl]);
|
||||
}
|
||||
else {
|
||||
instance.setContent('Loading...');
|
||||
$.ajax(sRemoteUrl)
|
||||
.done(function (html) {
|
||||
instance.setContent(html);
|
||||
|
||||
// - Ugly hack to include JS scripts as it doesn't work with tippy when adding multiple nodes
|
||||
$(html).each(function( index ) {
|
||||
if($(this).is('script')){
|
||||
$('body').append($(this));
|
||||
}
|
||||
});
|
||||
|
||||
CombodoTooltip.aTooltipsRemoteContent[sRemoteUrl] = html;
|
||||
instance._isLoaded = true;
|
||||
})
|
||||
.fail(function () {
|
||||
instance.setContent(`Request failed.`);
|
||||
})
|
||||
.always(function () {
|
||||
instance._isFetching = false;
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
oOptions['theme'] = oElem.attr('data-tooltip-theme') ?? '';
|
||||
|
||||
|
||||
@@ -2,6 +2,24 @@
|
||||
|
||||
// autoload.php @generated by Composer
|
||||
|
||||
if (PHP_VERSION_ID < 50600) {
|
||||
if (!headers_sent()) {
|
||||
header('HTTP/1.1 500 Internal Server Error');
|
||||
}
|
||||
$err = 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
|
||||
if (!ini_get('display_errors')) {
|
||||
if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
|
||||
fwrite(STDERR, $err);
|
||||
} elseif (!headers_sent()) {
|
||||
echo $err;
|
||||
}
|
||||
}
|
||||
trigger_error(
|
||||
$err,
|
||||
E_USER_ERROR
|
||||
);
|
||||
}
|
||||
|
||||
require_once __DIR__ . '/composer/autoload_real.php';
|
||||
|
||||
return ComposerAutoloaderInit7f81b4a2a468a061c306af5e447a9a9f::getLoader();
|
||||
|
||||
@@ -42,6 +42,9 @@ namespace Composer\Autoload;
|
||||
*/
|
||||
class ClassLoader
|
||||
{
|
||||
/** @var \Closure(string):void */
|
||||
private static $includeFile;
|
||||
|
||||
/** @var ?string */
|
||||
private $vendorDir;
|
||||
|
||||
@@ -106,6 +109,7 @@ class ClassLoader
|
||||
public function __construct($vendorDir = null)
|
||||
{
|
||||
$this->vendorDir = $vendorDir;
|
||||
self::initializeIncludeClosure();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -149,7 +153,7 @@ class ClassLoader
|
||||
|
||||
/**
|
||||
* @return string[] Array of classname => path
|
||||
* @psalm-var array<string, string>
|
||||
* @psalm-return array<string, string>
|
||||
*/
|
||||
public function getClassMap()
|
||||
{
|
||||
@@ -425,7 +429,8 @@ class ClassLoader
|
||||
public function loadClass($class)
|
||||
{
|
||||
if ($file = $this->findFile($class)) {
|
||||
includeFile($file);
|
||||
$includeFile = self::$includeFile;
|
||||
$includeFile($file);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -555,18 +560,26 @@ class ClassLoader
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scope isolated include.
|
||||
*
|
||||
* Prevents access to $this/self from included files.
|
||||
*
|
||||
* @param string $file
|
||||
* @return void
|
||||
* @private
|
||||
*/
|
||||
function includeFile($file)
|
||||
{
|
||||
include $file;
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
private static function initializeIncludeClosure()
|
||||
{
|
||||
if (self::$includeFile !== null) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scope isolated include.
|
||||
*
|
||||
* Prevents access to $this/self from included files.
|
||||
*
|
||||
* @param string $file
|
||||
* @return void
|
||||
*/
|
||||
self::$includeFile = \Closure::bind(static function($file) {
|
||||
include $file;
|
||||
}, null, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
// autoload_classmap.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(dirname(__FILE__));
|
||||
$vendorDir = dirname(__DIR__);
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
@@ -327,6 +327,7 @@ return array(
|
||||
'Combodo\\iTop\\Application\\UI\\Base\\Layout\\NavigationMenu\\NavigationMenuFactory' => $baseDir . '/sources/Application/UI/Base/Layout/NavigationMenu/NavigationMenuFactory.php',
|
||||
'Combodo\\iTop\\Application\\UI\\Base\\Layout\\Object\\ObjectDetails' => $baseDir . '/sources/Application/UI/Base/Layout/Object/ObjectDetails.php',
|
||||
'Combodo\\iTop\\Application\\UI\\Base\\Layout\\Object\\ObjectFactory' => $baseDir . '/sources/Application/UI/Base/Layout/Object/ObjectFactory.php',
|
||||
'Combodo\\iTop\\Application\\UI\\Base\\Layout\\Object\\ObjectSummary' => $baseDir . '/sources/Application/UI/Base/Layout/Object/ObjectSummary.php',
|
||||
'Combodo\\iTop\\Application\\UI\\Base\\Layout\\PageContent\\PageContent' => $baseDir . '/sources/Application/UI/Base/Layout/PageContent/PageContent.php',
|
||||
'Combodo\\iTop\\Application\\UI\\Base\\Layout\\PageContent\\PageContentFactory' => $baseDir . '/sources/Application/UI/Base/Layout/PageContent/PageContentFactory.php',
|
||||
'Combodo\\iTop\\Application\\UI\\Base\\Layout\\PageContent\\PageContentWithSideContent' => $baseDir . '/sources/Application/UI/Base/Layout/PageContent/PageContentWithSideContent.php',
|
||||
@@ -1553,6 +1554,7 @@ return array(
|
||||
'StimulusUserAction' => $baseDir . '/core/stimulus.class.inc.php',
|
||||
'Str' => $baseDir . '/core/MyHelpers.class.inc.php',
|
||||
'Stringable' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Stringable.php',
|
||||
'SummaryCardService' => $baseDir . '/sources/Service/SummaryCard/SummaryCardService.php',
|
||||
'Symfony\\Bridge\\Twig\\AppVariable' => $vendorDir . '/symfony/twig-bridge/AppVariable.php',
|
||||
'Symfony\\Bridge\\Twig\\Command\\DebugCommand' => $vendorDir . '/symfony/twig-bridge/Command/DebugCommand.php',
|
||||
'Symfony\\Bridge\\Twig\\Command\\LintCommand' => $vendorDir . '/symfony/twig-bridge/Command/LintCommand.php',
|
||||
|
||||
@@ -2,24 +2,24 @@
|
||||
|
||||
// autoload_files.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(dirname(__FILE__));
|
||||
$vendorDir = dirname(__DIR__);
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
'6e3fae29631ef280660b3cdad06f25a8' => $vendorDir . '/symfony/deprecation-contracts/function.php',
|
||||
'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php',
|
||||
'6e3fae29631ef280660b3cdad06f25a8' => $vendorDir . '/symfony/deprecation-contracts/function.php',
|
||||
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
|
||||
'320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php',
|
||||
'0d59ee240a4cd96ddbb4ff164fccea4d' => $vendorDir . '/symfony/polyfill-php73/bootstrap.php',
|
||||
'23c18046f52bef3eea034657bafda50f' => $vendorDir . '/symfony/polyfill-php81/bootstrap.php',
|
||||
'0d59ee240a4cd96ddbb4ff164fccea4d' => $vendorDir . '/symfony/polyfill-php73/bootstrap.php',
|
||||
'667aeda72477189d0494fecd327c3641' => $vendorDir . '/symfony/var-dumper/Resources/functions/dump.php',
|
||||
'e69f7f6ee287b969198c3c9d6777bd38' => $vendorDir . '/symfony/polyfill-intl-normalizer/bootstrap.php',
|
||||
'c9d07b32a2e02bc0fc582d4f0c1b56cc' => $vendorDir . '/laminas/laminas-servicemanager/src/autoload.php',
|
||||
'7b11c4dc42b3b3023073cb14e519683c' => $vendorDir . '/ralouphie/getallheaders/src/getallheaders.php',
|
||||
'8825ede83f2f289127722d4e842cf7e8' => $vendorDir . '/symfony/polyfill-intl-grapheme/bootstrap.php',
|
||||
'c964ee0ededf28c96ebd9db5099ef910' => $vendorDir . '/guzzlehttp/promises/src/functions_include.php',
|
||||
'b6b991a57620e2fb6b2f66f03fe9ddc2' => $vendorDir . '/symfony/string/Resources/functions.php',
|
||||
'e69f7f6ee287b969198c3c9d6777bd38' => $vendorDir . '/symfony/polyfill-intl-normalizer/bootstrap.php',
|
||||
'37a3dc5111fe8f707ab4c132ef1dbc62' => $vendorDir . '/guzzlehttp/guzzle/src/functions_include.php',
|
||||
'c9d07b32a2e02bc0fc582d4f0c1b56cc' => $vendorDir . '/laminas/laminas-servicemanager/src/autoload.php',
|
||||
'8825ede83f2f289127722d4e842cf7e8' => $vendorDir . '/symfony/polyfill-intl-grapheme/bootstrap.php',
|
||||
'25072dd6e2470089de65ae7bf11d3109' => $vendorDir . '/symfony/polyfill-php72/bootstrap.php',
|
||||
'f598d06aa772fa33d905e87be6398fb1' => $vendorDir . '/symfony/polyfill-intl-idn/bootstrap.php',
|
||||
'b6b991a57620e2fb6b2f66f03fe9ddc2' => $vendorDir . '/symfony/string/Resources/functions.php',
|
||||
);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
// autoload_namespaces.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(dirname(__FILE__));
|
||||
$vendorDir = dirname(__DIR__);
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
// autoload_psr4.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(dirname(__FILE__));
|
||||
$vendorDir = dirname(__DIR__);
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
|
||||
@@ -25,46 +25,31 @@ class ComposerAutoloaderInit7f81b4a2a468a061c306af5e447a9a9f
|
||||
require __DIR__ . '/platform_check.php';
|
||||
|
||||
spl_autoload_register(array('ComposerAutoloaderInit7f81b4a2a468a061c306af5e447a9a9f', 'loadClassLoader'), true, true);
|
||||
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(\dirname(__FILE__)));
|
||||
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
|
||||
spl_autoload_unregister(array('ComposerAutoloaderInit7f81b4a2a468a061c306af5e447a9a9f', 'loadClassLoader'));
|
||||
|
||||
$includePaths = require __DIR__ . '/include_paths.php';
|
||||
$includePaths[] = get_include_path();
|
||||
set_include_path(implode(PATH_SEPARATOR, $includePaths));
|
||||
|
||||
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
|
||||
if ($useStaticLoader) {
|
||||
require __DIR__ . '/autoload_static.php';
|
||||
|
||||
call_user_func(\Composer\Autoload\ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f::getInitializer($loader));
|
||||
} else {
|
||||
$classMap = require __DIR__ . '/autoload_classmap.php';
|
||||
if ($classMap) {
|
||||
$loader->addClassMap($classMap);
|
||||
}
|
||||
}
|
||||
require __DIR__ . '/autoload_static.php';
|
||||
call_user_func(\Composer\Autoload\ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f::getInitializer($loader));
|
||||
|
||||
$loader->setClassMapAuthoritative(true);
|
||||
$loader->register(true);
|
||||
|
||||
if ($useStaticLoader) {
|
||||
$includeFiles = Composer\Autoload\ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f::$files;
|
||||
} else {
|
||||
$includeFiles = require __DIR__ . '/autoload_files.php';
|
||||
}
|
||||
foreach ($includeFiles as $fileIdentifier => $file) {
|
||||
composerRequire7f81b4a2a468a061c306af5e447a9a9f($fileIdentifier, $file);
|
||||
$filesToLoad = \Composer\Autoload\ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f::$files;
|
||||
$requireFile = \Closure::bind(static function ($fileIdentifier, $file) {
|
||||
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
|
||||
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
|
||||
|
||||
require $file;
|
||||
}
|
||||
}, null, null);
|
||||
foreach ($filesToLoad as $fileIdentifier => $file) {
|
||||
$requireFile($fileIdentifier, $file);
|
||||
}
|
||||
|
||||
return $loader;
|
||||
}
|
||||
}
|
||||
|
||||
function composerRequire7f81b4a2a468a061c306af5e447a9a9f($fileIdentifier, $file)
|
||||
{
|
||||
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
|
||||
require $file;
|
||||
|
||||
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,22 +7,22 @@ namespace Composer\Autoload;
|
||||
class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f
|
||||
{
|
||||
public static $files = array (
|
||||
'6e3fae29631ef280660b3cdad06f25a8' => __DIR__ . '/..' . '/symfony/deprecation-contracts/function.php',
|
||||
'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php',
|
||||
'6e3fae29631ef280660b3cdad06f25a8' => __DIR__ . '/..' . '/symfony/deprecation-contracts/function.php',
|
||||
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
|
||||
'320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php',
|
||||
'0d59ee240a4cd96ddbb4ff164fccea4d' => __DIR__ . '/..' . '/symfony/polyfill-php73/bootstrap.php',
|
||||
'23c18046f52bef3eea034657bafda50f' => __DIR__ . '/..' . '/symfony/polyfill-php81/bootstrap.php',
|
||||
'0d59ee240a4cd96ddbb4ff164fccea4d' => __DIR__ . '/..' . '/symfony/polyfill-php73/bootstrap.php',
|
||||
'667aeda72477189d0494fecd327c3641' => __DIR__ . '/..' . '/symfony/var-dumper/Resources/functions/dump.php',
|
||||
'e69f7f6ee287b969198c3c9d6777bd38' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/bootstrap.php',
|
||||
'c9d07b32a2e02bc0fc582d4f0c1b56cc' => __DIR__ . '/..' . '/laminas/laminas-servicemanager/src/autoload.php',
|
||||
'7b11c4dc42b3b3023073cb14e519683c' => __DIR__ . '/..' . '/ralouphie/getallheaders/src/getallheaders.php',
|
||||
'8825ede83f2f289127722d4e842cf7e8' => __DIR__ . '/..' . '/symfony/polyfill-intl-grapheme/bootstrap.php',
|
||||
'c964ee0ededf28c96ebd9db5099ef910' => __DIR__ . '/..' . '/guzzlehttp/promises/src/functions_include.php',
|
||||
'b6b991a57620e2fb6b2f66f03fe9ddc2' => __DIR__ . '/..' . '/symfony/string/Resources/functions.php',
|
||||
'e69f7f6ee287b969198c3c9d6777bd38' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/bootstrap.php',
|
||||
'37a3dc5111fe8f707ab4c132ef1dbc62' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/functions_include.php',
|
||||
'c9d07b32a2e02bc0fc582d4f0c1b56cc' => __DIR__ . '/..' . '/laminas/laminas-servicemanager/src/autoload.php',
|
||||
'8825ede83f2f289127722d4e842cf7e8' => __DIR__ . '/..' . '/symfony/polyfill-intl-grapheme/bootstrap.php',
|
||||
'25072dd6e2470089de65ae7bf11d3109' => __DIR__ . '/..' . '/symfony/polyfill-php72/bootstrap.php',
|
||||
'f598d06aa772fa33d905e87be6398fb1' => __DIR__ . '/..' . '/symfony/polyfill-intl-idn/bootstrap.php',
|
||||
'b6b991a57620e2fb6b2f66f03fe9ddc2' => __DIR__ . '/..' . '/symfony/string/Resources/functions.php',
|
||||
);
|
||||
|
||||
public static $prefixLengthsPsr4 = array (
|
||||
@@ -692,6 +692,7 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f
|
||||
'Combodo\\iTop\\Application\\UI\\Base\\Layout\\NavigationMenu\\NavigationMenuFactory' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Layout/NavigationMenu/NavigationMenuFactory.php',
|
||||
'Combodo\\iTop\\Application\\UI\\Base\\Layout\\Object\\ObjectDetails' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Layout/Object/ObjectDetails.php',
|
||||
'Combodo\\iTop\\Application\\UI\\Base\\Layout\\Object\\ObjectFactory' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Layout/Object/ObjectFactory.php',
|
||||
'Combodo\\iTop\\Application\\UI\\Base\\Layout\\Object\\ObjectSummary' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Layout/Object/ObjectSummary.php',
|
||||
'Combodo\\iTop\\Application\\UI\\Base\\Layout\\PageContent\\PageContent' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Layout/PageContent/PageContent.php',
|
||||
'Combodo\\iTop\\Application\\UI\\Base\\Layout\\PageContent\\PageContentFactory' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Layout/PageContent/PageContentFactory.php',
|
||||
'Combodo\\iTop\\Application\\UI\\Base\\Layout\\PageContent\\PageContentWithSideContent' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Layout/PageContent/PageContentWithSideContent.php',
|
||||
@@ -1918,6 +1919,7 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f
|
||||
'StimulusUserAction' => __DIR__ . '/../..' . '/core/stimulus.class.inc.php',
|
||||
'Str' => __DIR__ . '/../..' . '/core/MyHelpers.class.inc.php',
|
||||
'Stringable' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Stringable.php',
|
||||
'SummaryCardService' => __DIR__ . '/../..' . '/sources/Service/SummaryCard/SummaryCardService.php',
|
||||
'Symfony\\Bridge\\Twig\\AppVariable' => __DIR__ . '/..' . '/symfony/twig-bridge/AppVariable.php',
|
||||
'Symfony\\Bridge\\Twig\\Command\\DebugCommand' => __DIR__ . '/..' . '/symfony/twig-bridge/Command/DebugCommand.php',
|
||||
'Symfony\\Bridge\\Twig\\Command\\LintCommand' => __DIR__ . '/..' . '/symfony/twig-bridge/Command/LintCommand.php',
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
// include_paths.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(dirname(__FILE__));
|
||||
$vendorDir = dirname(__DIR__);
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
|
||||
@@ -1064,7 +1064,7 @@ EOF
|
||||
$aParams = utils::ReadParam('params', '', false, 'raw_data');
|
||||
$sDashletClass = $aParams['attr_dashlet_class'];
|
||||
$sDashletType = $aParams['attr_dashlet_type'];
|
||||
$sDashletId = utils::HtmlEntities($aParams['attr_dashlet_id']);
|
||||
$sDashletId = utils::HtmlEntities($aParams['attr_dashlet_id']);
|
||||
$aUpdatedProperties = $aParams['updated']; // Code of the changed properties as an array: 'attr_xxx', 'attr_xxy', etc...
|
||||
$aPreviousValues = $aParams['previous_values']; // hash array: 'attr_xxx' => 'old_value'
|
||||
if (is_subclass_of($sDashletClass, 'Dashlet')) {
|
||||
|
||||
@@ -110,6 +110,7 @@ function DisplayPreferences($oP)
|
||||
$oMiscOptionsFieldset = FieldSetUIBlockFactory::MakeStandard(Dict::S('UI:FavoriteOtherSettings'), 'ibo-fieldset-for-misc-options');
|
||||
$oSecondColumn->AddSubBlock($oMiscOptionsFieldset);
|
||||
$oMiscOptionsFieldset->AddSubBlock(GetObsoleteDataFieldBlock());
|
||||
$oMiscOptionsFieldset->AddSubBlock(GetSummaryCardsFieldBlock());
|
||||
|
||||
$oP->add_script(
|
||||
<<<JS
|
||||
@@ -674,6 +675,33 @@ HTML;
|
||||
return new Html($sHtml);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return \Combodo\iTop\Application\UI\Base\iUIBlock
|
||||
* @throws \CoreException
|
||||
* @throws \CoreUnexpectedValue
|
||||
* @throws \MySQLException
|
||||
* @since 3.1.0
|
||||
*/
|
||||
function GetSummaryCardsFieldBlock(): iUIBlock
|
||||
{
|
||||
$bShow = appUserPreferences::GetPref('show_summary_cards', true);
|
||||
$sSelectedForHtmlAttribute = $bShow ? 'checked="checked"' : '';
|
||||
|
||||
$sLabel = Dict::S('UI:Favorites:General:ShowSummaryCards');
|
||||
$sLabelDescription = Dict::S('UI:Favorites:General:ShowSummaryCards+');
|
||||
$sHtml = <<<HTML
|
||||
<p>
|
||||
<label data-tooltip-content="{$sLabelDescription}">
|
||||
<span>{$sLabel}</span>
|
||||
<input type="checkbox" name="show_summary_cards" value="1" {$sSelectedForHtmlAttribute}>
|
||||
</label>
|
||||
</p>
|
||||
HTML;
|
||||
|
||||
return new Html($sHtml);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Main program
|
||||
@@ -766,6 +794,10 @@ try {
|
||||
// - Obsolete data
|
||||
$bShowObsoleteData = (bool)utils::ReadParam('show_obsolete_data', 0);
|
||||
appUserPreferences::SetPref('show_obsolete_data', $bShowObsoleteData);
|
||||
|
||||
// - Summary cards
|
||||
$bShowSummaryCards = (bool)utils::ReadParam('show_summary_cards', 0);
|
||||
appUserPreferences::SetPref('show_summary_cards', $bShowSummaryCards);
|
||||
|
||||
// Redirect to force a reload/display of the page in case language has been changed
|
||||
$oAppContext = new ApplicationContext();
|
||||
|
||||
@@ -1812,6 +1812,7 @@ EOF;
|
||||
// - Standard zlists
|
||||
$aListRef = [
|
||||
'details' => 'details',
|
||||
'summary' => 'summary',
|
||||
'standard_search' => 'search',
|
||||
'default_search' => 'default_search',
|
||||
'list' => 'list',
|
||||
|
||||
143
sources/Application/UI/Base/Layout/Object/ObjectSummary.php
Normal file
143
sources/Application/UI/Base/Layout/Object/ObjectSummary.php
Normal file
@@ -0,0 +1,143 @@
|
||||
<?php
|
||||
namespace Combodo\iTop\Application\UI\Base\Layout\Object;
|
||||
|
||||
|
||||
use ApplicationContext;
|
||||
use cmdbAbstractObject;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Button\ButtonUIBlockFactory;
|
||||
use Combodo\iTop\Application\UI\Base\tUIContentAreas;
|
||||
use Combodo\iTop\Application\UI\Base\UIBlock;
|
||||
use Combodo\iTop\Core\MetaModel\FriendlyNameType;
|
||||
use DBObject;
|
||||
use Dict;
|
||||
use MetaModel;
|
||||
|
||||
/**
|
||||
* Class ObjectSummary
|
||||
*
|
||||
* @package Combodo\iTop\Application\UI\Base\Layout\Object
|
||||
* @since 3.1.0
|
||||
*/
|
||||
class ObjectSummary extends ObjectDetails
|
||||
{
|
||||
use tUIContentAreas;
|
||||
|
||||
|
||||
// Overloaded constants
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public const BLOCK_CODE = 'ibo-object-summary';
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public const DEFAULT_HTML_TEMPLATE_REL_PATH = 'base/layouts/object/object-summary/layout';
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public const REQUIRES_ANCESTORS_DEFAULT_JS_FILES = true;
|
||||
/** @var \DBObject Object that will be displayed as summary */
|
||||
protected $oObject;
|
||||
|
||||
/** @var array Map of fields that will be displayed for the current object */
|
||||
protected $aObjectDisplayValues;
|
||||
/** @var \Combodo\iTop\Application\UI\Base\UIBlock Actions that will be displayed in the header */
|
||||
protected $oActions;
|
||||
|
||||
public function __construct(DBObject $oObject, ?string $sId = null)
|
||||
{
|
||||
parent::__construct($oObject,cmdbAbstractObject::ENUM_DISPLAY_MODE_VIEW, $sId);
|
||||
$this->oObject = $oObject;
|
||||
|
||||
$this->ComputeDetails();
|
||||
$this->SetToolBlocks([]);
|
||||
$this->ComputeActions();
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute object zlists and build the Field map that will be displayed
|
||||
*
|
||||
* @return void
|
||||
* @throws \ArchivedObjectException
|
||||
* @throws \CoreException
|
||||
* @throws \DictExceptionMissingString
|
||||
*/
|
||||
public function ComputeDetails(){
|
||||
$sClass = $this->sClassName;
|
||||
|
||||
$aDetailsList = MetaModel::GetZListItems($sClass, 'summary');
|
||||
|
||||
if(empty($aDetailsList)){
|
||||
$aComplementAttributeSpec = MetaModel::GetNameSpec($sClass, FriendlyNameType::COMPLEMENTARY);
|
||||
$aAdditionalField = $aComplementAttributeSpec[1];
|
||||
if (!empty($aAdditionalField)) {
|
||||
$aDetailsList = $aAdditionalField;
|
||||
}
|
||||
}
|
||||
|
||||
$aFieldsMap = [];
|
||||
foreach ($aDetailsList as $sAttCode) {
|
||||
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
|
||||
$sAttLabel = MetaModel::GetLabel($sClass, $sAttCode);
|
||||
$aFieldsMap[$sAttLabel] = $this->oObject->GetAsHTML($sAttCode);
|
||||
}
|
||||
$this->aObjectDisplayValues = $aFieldsMap;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Build the Actions that will be displayed in the summary header
|
||||
*
|
||||
* @return void
|
||||
* @throws \Exception
|
||||
*/
|
||||
private function ComputeActions()
|
||||
{
|
||||
$oDetailsButton = ButtonUIBlockFactory::MakeLinkNeutral(
|
||||
ApplicationContext::MakeObjectUrl($this->sClassName, $this->sObjectId),
|
||||
Dict::S('UI:Menu:View'),
|
||||
'fas fa-external-link-alt',
|
||||
'_blank',
|
||||
);
|
||||
|
||||
$this->oActions = $oDetailsButton;
|
||||
$this->AddToolbarBlock($oDetailsButton);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Combodo\iTop\Application\UI\Base\UIBlock
|
||||
*/
|
||||
public function GetActions(): UIBlock
|
||||
{
|
||||
return $this->oActions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Combodo\iTop\Application\UI\Base\UIBlock $oActions
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function SetActions(UIBlock $oActions)
|
||||
{
|
||||
$this->oActions = $oActions;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function GetDisplayValues() {
|
||||
return $this->aObjectDisplayValues;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $aObjectDisplayValues
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function SetObjectDisplayValues(array $aObjectDisplayValues)
|
||||
{
|
||||
$this->aObjectDisplayValues = $aObjectDisplayValues;
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
@@ -20,6 +20,7 @@ use CMDBObjectSet;
|
||||
use CMDBSource;
|
||||
use Combodo\iTop\Application\UI\Base\Component\DataTable\DataTableSettings;
|
||||
use Combodo\iTop\Application\UI\Base\Component\DataTable\DataTableUIBlockFactory;
|
||||
use Combodo\iTop\Application\UI\Base\Layout\Object\ObjectSummary;
|
||||
use DBObjectSearch;
|
||||
use DBObjectSet;
|
||||
use DBSearch;
|
||||
@@ -247,7 +248,7 @@ class AjaxRenderController
|
||||
$oPage->SetData($aResult);
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* @param string $sFilter
|
||||
*
|
||||
* @return array
|
||||
|
||||
@@ -14,6 +14,7 @@ use CMDBObjectSet;
|
||||
use Combodo\iTop\Application\Helper\Session;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Alert\AlertUIBlockFactory;
|
||||
use Combodo\iTop\Application\UI\Base\Component\QuickCreate\QuickCreateHelper;
|
||||
use Combodo\iTop\Application\UI\Base\Layout\Object\ObjectSummary;
|
||||
use Combodo\iTop\Application\UI\Base\Layout\PageContent\PageContentFactory;
|
||||
use Combodo\iTop\Controller\AbstractController;
|
||||
use Combodo\iTop\Service\Base\ObjectRepository;
|
||||
@@ -27,6 +28,7 @@ use iTopWebPage;
|
||||
use JsonPage;
|
||||
use MetaModel;
|
||||
use SecurityException;
|
||||
use SummaryCardService;
|
||||
use UserRights;
|
||||
use utils;
|
||||
|
||||
@@ -678,6 +680,37 @@ JS;
|
||||
return $oPage;
|
||||
}
|
||||
|
||||
public function OperationSummary() {
|
||||
$oPage = new AjaxPage('');
|
||||
|
||||
$sClass = utils::ReadParam('obj_class', '', false, utils::ENUM_SANITIZATION_FILTER_CLASS);
|
||||
$sObjectKey = utils::ReadParam('obj_key', 0, false);
|
||||
|
||||
// - Check if we are allowed to see/make summary for this class
|
||||
if(SummaryCardService::IsAllowedForClass($sClass)){
|
||||
if (is_numeric($sObjectKey))
|
||||
{
|
||||
$oObj = MetaModel::GetObject($sClass, $sObjectKey, false /* MustBeFound */);
|
||||
}
|
||||
else
|
||||
{
|
||||
$oObj = MetaModel::GetObjectByName($sClass, $sObjectKey, false /* MustBeFound */);
|
||||
}
|
||||
|
||||
if($oObj !== null) {
|
||||
$oPage->AddUiBlock(new ObjectSummary($oObj));
|
||||
}
|
||||
}
|
||||
else {
|
||||
$oPage->AddUiBlock(
|
||||
AlertUIBlockFactory::MakeForFailure(Dict::S('UI:Error:ActionNotAllowed'))
|
||||
->SetIsCollapsible(false)
|
||||
->SetIsClosable(false)
|
||||
);
|
||||
}
|
||||
return $oPage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add some JS files that are required during the modification of an object
|
||||
*
|
||||
|
||||
84
sources/Service/SummaryCard/SummaryCardService.php
Normal file
84
sources/Service/SummaryCard/SummaryCardService.php
Normal file
@@ -0,0 +1,84 @@
|
||||
<?php
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2022 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
use Combodo\iTop\Controller\AbstractController;
|
||||
use Combodo\iTop\Core\MetaModel\FriendlyNameType;
|
||||
|
||||
/**
|
||||
* Class SummaryCardService
|
||||
*
|
||||
* Service containing methods to call SummaryCards functionalities
|
||||
*
|
||||
* @since 3.1.0
|
||||
*/
|
||||
class SummaryCardService {
|
||||
|
||||
/**
|
||||
* @param $sObjClass
|
||||
* @param $sObjKey
|
||||
*
|
||||
* @return string
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function GetHyperlinkMarkup(string $sObjClass, $sObjKey): string
|
||||
{
|
||||
$sRoute = utils::GetAbsoluteUrlAppRoot()."/pages/ajax.render.php?route=object.summary&obj_key=$sObjKey&obj_class=$sObjClass";
|
||||
return
|
||||
<<<HTML
|
||||
data-tooltip-content="$sRoute"
|
||||
data-tooltip-interaction-enabled="true"
|
||||
data-tooltip-is-async="true"
|
||||
data-tooltip-html-enabled="true"
|
||||
data-tooltip-sanitizer-skipped="false"
|
||||
data-tooltip-show-delay="800"
|
||||
data-tooltip-hide-delay="500"
|
||||
data-tooltip-max-width="600"
|
||||
data-tooltip-theme="object-summary"
|
||||
data-tooltip-append-to="body"
|
||||
HTML;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the user is allowed to see this class and if the class is allowed to display its summary
|
||||
*
|
||||
* @param string $sClass
|
||||
*
|
||||
* @return bool
|
||||
* @throws \CoreException
|
||||
* @throws \CoreUnexpectedValue
|
||||
* @throws \DictExceptionMissingString
|
||||
* @throws \MySQLException
|
||||
* @throws \OQLException
|
||||
*/
|
||||
public static function IsAllowedForClass(string $sClass): bool
|
||||
{
|
||||
// - User can read this object, otherwise end here
|
||||
if (UserRights::IsActionAllowed($sClass, UR_ACTION_READ) === UR_ALLOWED_NO) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// - User doesn't want to see summary cards
|
||||
if (appUserPreferences::GetPref('show_summary_cards', true) === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// - This class has a summary zlist
|
||||
$aDetailsList = MetaModel::GetZListItems($sClass, 'summary');
|
||||
if(count($aDetailsList) > 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// - Then maybe this class has complementary attributes
|
||||
$aComplementAttributeSpec = MetaModel::GetNameSpec($sClass, FriendlyNameType::COMPLEMENTARY);
|
||||
$aAdditionalField = $aComplementAttributeSpec[1];
|
||||
if (count($aAdditionalField) > 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@
|
||||
class="{{ oUIBlock.GetBlocksInheritanceCSSClassesAsString() }} {{ oUIBlock.GetAdditionalCSSClassesAsString() }} {{ oUIBlock.GetCSSColorClass() }} {% if oUIBlock.HasIcon() %}ibo-has-icon{% endif %} {% if oUIBlock.IsIconAsMedallion() %}ibo-has-medallion-icon{% endif %} {% if oUIBlock.IsHidden() %}ibo-is-hidden{% endif %} ibo-is-opened"
|
||||
{% block iboPanelMetaData %}{% endblock %}
|
||||
data-role="ibo-panel">
|
||||
{% block iboPanelHeaderOuter %}
|
||||
<div class="ibo-panel--header" data-role="ibo-panel--header">
|
||||
{% block iboPanelHeader %}
|
||||
<div class="ibo-panel--header-left" data-role="ibo-panel--header-left">
|
||||
@@ -48,6 +49,8 @@
|
||||
</div>
|
||||
{% endblock %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% block iboPanelBodyOuter %}
|
||||
<div class="ibo-panel--body" data-role="ibo-panel--body">
|
||||
{% block iboPanelBody %}
|
||||
{% for oMainBlock in oUIBlock.GetMainBlocks() %}
|
||||
@@ -55,4 +58,5 @@
|
||||
{% endfor %}
|
||||
{% endblock %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
</div>
|
||||
@@ -7,7 +7,7 @@
|
||||
data-object-id="{{ oUIBlock.GetObjectId() }}"
|
||||
data-object-mode="{{ oUIBlock.GetObjectMode() }}"
|
||||
{% if oUIBlock.HasStatus() %}data-object-state="{{ oUIBlock.GetStatusCode() }}"{% endif %}
|
||||
data-role="ibo-object-details"
|
||||
data-role="{{ oUIBlock.GetBlockCode() }}"
|
||||
{% endblock %}
|
||||
|
||||
{% block iboPanelSubTitle %}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
{# @copyright Copyright (C) 2010-2021 Combodo SARL #}
|
||||
{# @license http://opensource.org/licenses/AGPL-3.0 #}
|
||||
{% extends 'base/layouts/object/object-details/layout.html.twig' %}
|
||||
|
||||
{% block iboPanelHeaderOuter %}
|
||||
{% endblock %}
|
||||
|
||||
{% block iboPanelBody %}
|
||||
<div class="ibo-object-summary--header">
|
||||
{% block iboPanelHeader %}
|
||||
{{ parent() }}
|
||||
{% endblock %}
|
||||
</div>
|
||||
<div class="ibo-object-summary--content--attributes">
|
||||
|
||||
{% for attcode,attval in oUIBlock.GetDisplayValues() %}
|
||||
<div class="ibo-object-summary--content--attribute ibo-field ibo-field-small">
|
||||
<span class="ibo-object-summary--content--attributes--code ibo-field--label">{{ attcode|raw }}</span>
|
||||
<span class="ibo-object-summary--content--attributes--value ibo-field--value">{{ attval|raw }}</span>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user