diff --git a/application/cmdbabstract.class.inc.php b/application/cmdbabstract.class.inc.php index 5f692fcdf..6980f630e 100644 --- a/application/cmdbabstract.class.inc.php +++ b/application/cmdbabstract.class.inc.php @@ -3196,7 +3196,22 @@ EOF $oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode); if ((!$oAttDef->IsLinkSet()) && (($iFlags & OPT_ATT_HIDDEN) == 0) && !($oAttDef instanceof AttributeDashboard)) { - // The field is visible in the current state of the object + // First prepare the label + // - Attribute description + $sDescription = $oAttDef->GetDescription(); + $sDescriptionForHTMLAttributes = utils::HtmlEntities($sDescription); + $sDescriptionHTMLAttributes = (empty($sDescriptionForHTMLAttributes)) ? '' : 'class="ibo-has-description" data-tooltip-content="'.$sDescriptionForHTMLAttributes.'"'; + + // - Fullscreen toggler for large fields + $sFullscreenTogglerTooltip = Dict::S('UI:ToggleFullScreen'); + $sFullscreenTogglerHTML = (false === in_array($oAttDef->GetEditClass(), static::GetAttEditClassesToRenderAsLargeField())) ? '' : << +HTML; + + $sLabelAsHtml = ''.MetaModel::GetLabel($sClass, $sAttCode).''.$sFullscreenTogglerHTML; + + // Then prepare the value + // - The field is visible in the current state of the object if ($sStateAttCode == $sAttCode) { // Special display for the 'state' attribute itself @@ -3229,16 +3244,12 @@ EOF $sDisplayValue = $this->GetAsHTML($sAttCode); } } + $sValueAsHtml = $sDisplayValue; - // Attribute description - $sDescription = $oAttDef->GetDescription(); - $sDescriptionForHTMLTag = utils::HtmlEntities($sDescription); - $sDescriptionHTMLTag = (empty($sDescriptionForHTMLTag)) ? '' : 'class="ibo-has-description" data-tooltip-content="'.$sDescriptionForHTMLTag.'"'; - - $retVal = array( - 'label' => ''.MetaModel::GetLabel($sClass, $sAttCode).'', - 'value' => $sDisplayValue, - ); + $retVal = [ + 'label' => $sLabelAsHtml, + 'value' => $sValueAsHtml, + ]; } return $retVal; diff --git a/css/backoffice/components/_field.scss b/css/backoffice/components/_field.scss index 0e9767c00..3f992c29c 100644 --- a/css/backoffice/components/_field.scss +++ b/css/backoffice/components/_field.scss @@ -3,6 +3,7 @@ * license http://opensource.org/licenses/AGPL-3.0 */ +/* SCSS variables */ $ibo-field--sibling-spacing: 16px !default; $ibo-field--value--color: $ibo-color-grey-700 !default; @@ -10,6 +11,23 @@ $ibo-field--label--description--content: "?" !default; $ibo-field--label--description--padding-left: 4px !default; $ibo-field--label--description--color: $ibo-color-grey-600 !default; +$ibo-field--background-color--is-fullscreen: $ibo-color-white-100 !default; + +$ibo-field--label--width--is-fullscreen: 100% !default; +$ibo-field--label--padding-x--is-fullscreen: 8px !default; +$ibo-field--label--padding-y--is-fullscreen: 4px !default; +$ibo-field--label--background-color--is-fullscreen: $ibo-color-grey-100 !default; +$ibo-field--label--border-bottom--is-fullscreen: 1px solid $ibo-color-grey-400 !default; + +$ibo-field--fullscreen-toggler--size: 20px !default; +$ibo-field--fullscreen-toggler--border-radius: $ibo-border-radius-500 !default; +$ibo-field--fullscreen-toggler--background-color--on-hover: $ibo-color-white-200 !default; + +$ibo-field--value--padding-x--is-fullscreen: $ibo-field--label--padding-x--is-fullscreen !default; +$ibo-field--value--padding-top--is-fullscreen: $ibo-field--label--padding-y--is-fullscreen + 32px !default; +$ibo-field--value--padding-bottom--is-fullscreen: $ibo-field--label--padding-y--is-fullscreen !default; + +/* SCSS rules */ .ibo-field { @extend %ibo-font-ral-nor-150; @@ -22,11 +40,14 @@ $ibo-field--label--description--color: $ibo-color-grey-600 !default; display: inherit; .ibo-field--label { - display: inherit; - max-width: none; + position: relative; /* Necessary for fullscreen toggler */ + display: flex; + justify-content: space-between; + align-items: center; + max-width: initial; + width: 100%; } } - .ibo-field-small { display: table; width: 100%; @@ -34,6 +55,7 @@ $ibo-field--label--description--color: $ibo-color-grey-600 !default; .ibo-field--label { display: table-cell; vertical-align: top; + padding-right: 10px; } } @@ -41,7 +63,6 @@ $ibo-field--label--description--color: $ibo-color-grey-600 !default; min-width: 100px; max-width: 145px; width: 30%; - padding-right: 10px; > .ibo-has-description { &::after { @@ -55,9 +76,51 @@ $ibo-field--label--description--color: $ibo-color-grey-600 !default; } } } +.ibo-field--fullscreen-toggler { + width: $ibo-field--fullscreen-toggler--size; + height: $ibo-field--fullscreen-toggler--size; + border-radius: $ibo-field--fullscreen-toggler--border-radius; + cursor: pointer; + @extend %ibo-hyperlink-inherited-colors; + @extend %ibo-fully-centered-content; + @extend %ibo-font-ral-nor-100; + + &:hover { + background-color: $ibo-field--fullscreen-toggler--background-color--on-hover; + } +} .ibo-field--value { display: table; width: 100%; color: $ibo-field--value--color; + + /* Hack to force a table to fit its container without overflow (see N°2127) */ + /* Note that along with with, we now display a "expand" icon on large fields so we can have a better view of its content */ + .HTML { + table { + table-layout: fixed; + width: 100%; + } + } +} + +/* Fullscreen mode */ +.ibo-field-large { + &.ibo-is-fullscreen { + background-color: $ibo-field--background-color--is-fullscreen; + + .ibo-field--label { + position: fixed; + width: $ibo-field--label--width--is-fullscreen; + min-width: initial; + max-width: initial; + padding: $ibo-field--label--padding-y--is-fullscreen $ibo-field--label--padding-x--is-fullscreen; + background-color: $ibo-field--label--background-color--is-fullscreen; + border-bottom: $ibo-field--label--border-bottom--is-fullscreen; + } + .ibo-field--value { + padding: $ibo-field--value--padding-top--is-fullscreen $ibo-field--value--padding-x--is-fullscreen $ibo-field--value--padding-bottom--is-fullscreen $ibo-field--value--padding-x--is-fullscreen; + } + } } \ No newline at end of file diff --git a/css/backoffice/layout/activity-panel/_activity-entry.scss b/css/backoffice/layout/activity-panel/_activity-entry.scss index f267a8e5b..754b52998 100644 --- a/css/backoffice/layout/activity-panel/_activity-entry.scss +++ b/css/backoffice/layout/activity-panel/_activity-entry.scss @@ -183,6 +183,11 @@ $ibo-activity-entry--sub-information--text-color: $ibo-color-grey-700 !default; pre{ white-space: pre-wrap; } + /* Avoid table to overflow outside the entry (see N°2127) */ + table{ + table-layout: fixed; + width: 100%; + } /* Specific hyperlink color */ a{ diff --git a/css/backoffice/utils/helpers/_misc.scss b/css/backoffice/utils/helpers/_misc.scss index a7e44bf18..d510ec3f0 100644 --- a/css/backoffice/utils/helpers/_misc.scss +++ b/css/backoffice/utils/helpers/_misc.scss @@ -20,6 +20,34 @@ display: none !important; /* Note: !important is necessary as it needs to overload any standard rules */ } +/* Used on all ancestors when an element needs to be fullscreen (see .ibo-is-fullscreen) */ +html.ibo-has-fullscreen-descendant{ + position: fixed !important; + width: 0 !important; + height: 0 !important; +} +body.ibo-has-fullscreen-descendant{ + width: 0 !important; + height: 0 !important; + overflow: hidden !important; +} +.ibo-has-fullscreen-descendant{ + position: static !important; + overflow: visible !important; + z-index: 9000 !important; +} +/* Used on a fullscreen element (see .ibo-has-fullscreen-descendant) */ +.ibo-is-fullscreen{ + position: absolute; + top: 0 !important; + left: 0 !important; + margin: 0 !important; + padding: 0 !important; + width: 100vw; + height: 100vh; + overflow: auto; +} + %ibo-fully-centered-content{ display: flex; justify-content: center; diff --git a/js/pages/backoffice/toolbox.js b/js/pages/backoffice/toolbox.js index 9a822516a..572e60845 100644 --- a/js/pages/backoffice/toolbox.js +++ b/js/pages/backoffice/toolbox.js @@ -65,23 +65,23 @@ function SwitchTabMode() */ const CombodoBackofficeToolbox = { /** - * Set the oElem in fullscreen mode, meaning that it will take all the screen and be above everything else. + * Make the oElem enter the fullscreen mode, meaning that it will take all the screen and be above everything else. * * @param {object} oElem The jQuery object of the element * @constructor */ - SetElementToFullscreenMode: function(oElem) { + EnterFullscreenForElement: function(oElem) { oElem.parents().addClass('ibo-has-fullscreen-descendant'); oElem.addClass('ibo-is-fullscreen'); }, /** - * Remove the oElem from fullscreen mode. + * Make the oElem exit the fullscreen mode. * If none passed, all fullscreen elements will be removed from it * * @param {object|null} oElem The jQuery object of the element * @constructor */ - RemoveElementFromFullscreenMode: function(oElem = null) { + ExitFullscreenForElement: function(oElem = null) { // If no element passed, remove any element from fullscreen mode if(oElem === null) { $(document).find('.ibo-has-fullscreen-descendant').removeClass('ibo-has-fullscreen-descendant'); @@ -91,6 +91,20 @@ const CombodoBackofficeToolbox = { oElem.parents().removeClass('ibo-has-fullscreen-descendant'); oElem.removeClass('ibo-is-fullscreen'); } + }, + /** + * Make the oElem enter or exit the fullscreen mode depending on it's current state. + * + * @param {object} oElem The jQuery object of the element + * @constructor + */ + ToggleFullscreenForElement: function(oElem) { + if(oElem.hasClass('ibo-is-fullscreen')) { + this.ExitFullscreenForElement(oElem); + } + else { + this.EnterFullscreenForElement(oElem); + } } }; @@ -100,4 +114,32 @@ $(document).ready(function(){ $('[data-tooltip-content]:not([data-tooltip-instanciated="true"])').each(function(){ CombodoGlobalToolbox.InitTooltipFromMarkup($(this)); }); + + // Enable fullscreen togglers based on existing HTML markup, won't work on markup added dynamically after DOM ready (AJAX, ...) + $('[data-fullscreen-toggler-target]:not([data-fullscreen-toggler-instanciated="true"])').each(function(){ + const sTargetSelector = $(this).attr('data-fullscreen-toggler-target'); + let oTargetElem = null; + + // Check if target selector is a jQuery expression, meaning that it needs to be evaluated (eg. $(this).closest('[data-role="ibo-xxx"]')) + if(sTargetSelector.indexOf('$') !== -1) { + oTargetElem = eval(sTargetSelector); + } + // Otherwise it should be a simple selector (eg. #abc, .def) + else { + oTargetElem = $(document).find(sTargetSelector); + } + + // Still no target element found, abort + if((oTargetElem === null) || (oTargetElem.length === 0)) { + return false; + } + + // If target selector return one element, it's the good target + oTargetElem.on('click', function(oEvent){ + // Prevent anchor default behavior + oEvent.preventDefault(); + + CombodoBackofficeToolbox.ToggleFullscreenForElement(oTargetElem); + }); + }); }); \ No newline at end of file diff --git a/templates/base/components/field/layout.html.twig b/templates/base/components/field/layout.html.twig index db517c5d5..f26688a75 100644 --- a/templates/base/components/field/layout.html.twig +++ b/templates/base/components/field/layout.html.twig @@ -1,5 +1,6 @@ {% set aParams = oUIBlock.GetParams() %}