Skip to content

Commit cfdf850

Browse files
authored
* N°8955 Add UIBlocks markup in the setup
1 parent a3ecd25 commit cfdf850

File tree

14 files changed

+595
-96
lines changed

14 files changed

+595
-96
lines changed

css/backoffice/blocks-integrations/_all.scss

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,5 @@
2323
@import "field-badge-within-datatable";
2424
@import "jquery-blockui-within-dialog";
2525
@import "jquery-blockui-within-datatable";
26-
@import "badge-with-badge";
26+
@import "badge-with-badge";
27+
@import "extension-details-with-extension-details";

css/backoffice/blocks-integrations/_badge-with-badge.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* @copyright Copyright (C) 2010-2024 Combodo SAS
2+
* @copyright Copyright (C) 2010-2026 Combodo SAS
33
* @license http://opensource.org/licenses/AGPL-3.0
44
*/
55

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/*
2+
* @copyright Copyright (C) 2010-2026 Combodo SAS
3+
* @license http://opensource.org/licenses/AGPL-3.0
4+
*/
5+
6+
$ibo-extension-details--margin-top: $ibo-spacing-300 !default;
7+
8+
.ibo-extension-details + .ibo-extension-details,
9+
.ibo-extension-details--information--description .ibo-extension-details {
10+
margin-top: $ibo-extension-details--margin-top;
11+
}

css/backoffice/layout/extension/_extension-details.scss

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,21 @@ $ibo-extension-details--actions--button--padding-x: $ibo-button--padding-x !defa
4141
padding-right: $ibo-extension-details--information--metadata--padding;
4242
}
4343

44-
.ibo-extension-details:has(input:checked) .ibo-badge.unchecked, .ibo-extension-details:has(input:not(:checked)) .ibo-badge.checked {
45-
display: none;
44+
//ibo-extension-details can have other ibo-extension-details inside its ibo-extension-details--information--description in the setup. We need to only affect direct children
45+
.ibo-extension-details:has(>.ibo-extension-details--actions input:is([type="checkbox"], [type="radio"]):checked){
46+
&>.ibo-extension-details--information>.ibo-extension-details--information--label .ibo-badge.unchecked {
47+
display: none;
48+
}
49+
}
50+
//Merging the two lines below with :is([type="checkbox"], [type="radio"]) will generate a warning in scss compiler
51+
.ibo-extension-details:has(>.ibo-extension-details--actions input[type="checkbox"]:not(:checked)),
52+
.ibo-extension-details:has(>.ibo-extension-details--actions input[type="radio"]:not(:checked)) {
53+
&>.ibo-extension-details--information>.ibo-extension-details--information--label .ibo-badge.checked {
54+
display: none;
55+
}
4656
}
4757

58+
4859
.ibo-extension-details--actions > button {
4960
padding: $ibo-extension-details--actions--button--padding-y $ibo-extension-details--actions--button--padding-x;
5061
}

css/setup.css

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

css/setup.scss

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -316,29 +316,34 @@ fieldset {
316316
background-color: #F7FAFC;
317317
padding: 10px;
318318
.wiz-choice{
319-
&:checked ~ .description {
320-
#itop-ticket-mgmt-simple-ticket-enhanced-portal:not(:checked),
321-
#itop-ticket-mgmt-itil-enhanced-portal:not(:checked) {
322-
~ .description::after {
323-
content: "Legacy portal is no longer part of iTop, by leaving this option unchecked your portal users won't be able to access iTop anymore.";
324-
display: block;
325-
margin-top: 0.5em;
326-
font-weight: bold;
327-
color: $legacy-portal-removal-text-color;
328-
}
329-
}
330-
}
331-
&:not(:checked) ~ label .setup-extension-tag.checked{
319+
&:not(:checked) ~ label .checked{
332320
display:none;
333321
}
334-
&:checked ~ label .setup-extension-tag.unchecked{
322+
&:checked ~ label .unchecked{
335323
display:none;
336324
}
337325
}
338326
}
339327

328+
.ibo-extension-details:has(>.ibo-extension-details--actions>input:checked) {
329+
.ibo-extension-details:has(#itop-ticket-mgmt-simple-ticket-enhanced-portal:not(:checked), #itop-ticket-mgmt-itil-enhanced-portal:not(:checked)) {
330+
.ibo-extension-details--information--description::after {
331+
content: "Legacy portal is no longer part of iTop, by leaving this option unchecked your portal users won't be able to access iTop anymore.";
332+
display: block;
333+
margin-top: 0.5em;
334+
font-weight: bold;
335+
color: $legacy-portal-removal-text-color;
336+
}
337+
}
338+
}
340339

340+
.ibo-extension-details--information--metadata{
341+
color: $ibo-color-grey-800;
342+
}
341343

344+
.choice-disabled {
345+
color: $ibo-color-grey-700;
346+
}
342347

343348
body {
344349
font-size: 1.17rem;
@@ -633,6 +638,21 @@ body {
633638
}
634639
}
635640

641+
.ibo-extension-details {
642+
align-items: flex-start;
643+
}
644+
.ibo-extension-details--actions input{
645+
margin:0.2em 0.5em;
646+
width: 12px;
647+
}
648+
:not(.ibo-badge) ~ .ibo-badge{
649+
margin-left:0.5em;
650+
}
651+
.ibo-extension-details--information--label i{
652+
font-size : 0.9em;
653+
margin-left:0.3em;
654+
}
655+
636656
.setup--wizard-choice--label + .setup--wizard-choice--more-info {
637657
margin-left: 0.5rem;
638658
}

datamodels/2.x/installation.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@
219219
<choice>
220220
<extension_code>itop-problem-mgmt</extension_code>
221221
<title>Problem Management</title>
222-
<description>Select this option track "Problems" in iTop.</description>
222+
<description>Select this option to track "Problems" in iTop.</description>
223223
<modules type="array">
224224
<module>itop-problem-mgmt</module>
225225
</modules>

setup/extensionsmap.class.inc.php

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,7 @@ public function GetAllExtensionsOptionInfo(bool $bRemoteExtensionsShouldBeMandat
409409
'source_label' => $this->GetExtensionSourceLabel($oExtension->sSource),
410410
'uninstallable' => $oExtension->CanBeUninstalled(),
411411
'missing' => $oExtension->bRemovedFromDisk,
412+
'version' => $oExtension->sVersion,
412413
];
413414
}
414415

@@ -417,26 +418,18 @@ public function GetAllExtensionsOptionInfo(bool $bRemoteExtensionsShouldBeMandat
417418

418419
protected function GetExtensionSourceLabel($sSource)
419420
{
420-
$sDecorationClass = '';
421+
$sResult = '';
421422
switch ($sSource) {
422423
case iTopExtension::SOURCE_MANUAL:
423424
$sResult = 'Local extensions folder';
424-
$sDecorationClass = 'fas fa-folder';
425425
break;
426426

427427
case iTopExtension::SOURCE_REMOTE:
428428
$sResult = (ITOP_APPLICATION == 'iTop') ? 'iTop Hub' : 'ITSM Designer';
429-
$sDecorationClass = (ITOP_APPLICATION == 'iTop') ? 'fc fc-chameleon-icon' : 'fa pencil-ruler';
430429
break;
431430

432-
default:
433-
$sResult = '';
434431
}
435-
if ($sResult == '') {
436-
return '';
437-
}
438-
439-
return '<i class="setup-extension--icon '.$sDecorationClass.'" data-tooltip-content="'.$sResult.'"></i>';
432+
return $sResult;
440433
}
441434

442435
/**

setup/wizardsteps/WizStepModulesChoice.php

Lines changed: 77 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,6 @@ protected function DisplayStep($oPage)
202202
$oPage->add_style("div.choice { margin: 0.5em;}");
203203
$oPage->add_style("div.choice a { text-decoration:none; font-weight: bold; color: #1C94C4 }");
204204
$oPage->add_style("div.description { margin-left: 2em; }");
205-
$oPage->add_style(".choice-disabled { color: #999; }");
206205
$oPage->add_style("input.unremovable { accent-color: orangered;}");
207206

208207
$sManualInstallError = SetupUtils::CheckManualInstallDirEmpty(
@@ -638,7 +637,6 @@ protected function GetStepInfo($idx = null)
638637
if ($index + 1 >= count($this->aSteps)) {
639638
//make sure we also cache next step as well
640639
$aOptions = $this->oExtensionsMap->GetAllExtensionsOptionInfo($bRemoteExtensionsShouldBeMandatory);
641-
642640
// Display this step of the wizard only if there is something to display
643641
if (count($aOptions) > 0) {
644642
$this->aSteps[] = [
@@ -672,7 +670,7 @@ public function ComputeChoiceFlags(array $aChoice, string $sChoiceId, array $aSe
672670
$oITopExtension = $this->oExtensionsMap->GetFromExtensionCode($aChoice['extension_code']);
673671
//If the extension is missing from disk, it won't exist in the ExtensionsMap, thus returning null
674672
$bCanBeUninstalled = isset($aChoice['uninstallable']) ? $aChoice['uninstallable'] === true || $aChoice['uninstallable'] === 'yes' : $oITopExtension->CanBeUninstalled();
675-
$bSelected = isset($aSelectedComponents[$sChoiceId]) && ($aSelectedComponents[$sChoiceId] == $sChoiceId);
673+
$bSelected = isset($aSelectedComponents[$sChoiceId]) && ($aSelectedComponents[$sChoiceId] === $sChoiceId);
676674
$bMissingFromDisk = isset($aChoice['missing']) && $aChoice['missing'] === true;
677675
$bMandatory = (isset($aChoice['mandatory']) && $aChoice['mandatory']);
678676
$bInstalled = $bMissingFromDisk || $oITopExtension->bInstalled;
@@ -719,7 +717,7 @@ public function ComputeChoiceFlags(array $aChoice, string $sChoiceId, array $aSe
719717
];
720718
}
721719

722-
protected function DisplayOptions($oPage, $aStepInfo, $aSelectedComponents, $aDefaults, $sParentId = '', $bAllDisabled = false)
720+
public function DisplayOptions($oPage, $aStepInfo, $aSelectedComponents, $aDefaults, $sParentId = '', $bAllDisabled = false)
723721
{
724722
$aOptions = $aStepInfo['options'] ?? [];
725723
$aAlternatives = $aStepInfo['alternatives'] ?? [];
@@ -728,107 +726,124 @@ protected function DisplayOptions($oPage, $aStepInfo, $aSelectedComponents, $aDe
728726

729727
foreach ($aOptions as $index => $aChoice) {
730728
$sChoiceId = $sParentId.self::$SEP.$index;
731-
$sDataId = 'data-id="'.utils::EscapeHtml($aChoice['extension_code']).'"';
732-
$sId = utils::EscapeHtml($aChoice['extension_code']);
733729
$aFlags = $this->ComputeChoiceFlags($aChoice, $sChoiceId, $aSelectedComponents, $bAllDisabled, $bDisableUninstallCheck, $this->bUpgrade);
734730

735-
$sTooltip = '';
736-
$sUnremovable = '';
737-
if ($aFlags['missing']) {
738-
$sTooltip .= '<div class="setup-extension-tag removed">source removed</div>';
739-
}
740-
if ($aFlags['installed']) {
741-
$sTooltip .= '<div class="setup-extension-tag checked installed">installed</div>';
742-
$sTooltip .= '<div class="setup-extension-tag unchecked tobeuninstalled">to be uninstalled</div>';
743-
} else {
744-
$sTooltip .= '<div class="setup-extension-tag checked tobeinstalled">to be installed</div>';
745-
$sTooltip .= '<div class="setup-extension-tag unchecked notinstalled">not installed</div>';
746-
}
747-
if (!$aFlags['uninstallable']) {
748-
$sTooltip .= '<div class="setup-extension-tag notuninstallable">cannot be uninstalled</div>';
749-
}
750731
if ($aFlags['disabled'] && !$aFlags['checked'] && !$aFlags['uninstallable'] && !$bDisableUninstallCheck) {
751732
$this->bCanMoveForward = false;//Disable "Next"
752733
}
753-
$sChecked = $aFlags['checked'] ? ' checked ' : '';
754-
$sDisabled = $aFlags['disabled'] ? ' disabled data-disabled="disabled" ' : '';
755-
$sMissingModule = $aFlags['missing'] ? 'setup-extension--missing' : '';
756734

757-
$sHiddenInput = $aFlags['disabled'] && $aFlags['checked'] ? '<input type="hidden" name="choice['.$sChoiceId.']" value="'.$sChoiceId.'"/>' : '';
758-
$oPage->add('<div class="choice '.$sMissingModule.'" '.$sDataId.'><input class="wiz-choice '.$sUnremovable.'" id="'.$sId.'" name="choice['.$sChoiceId.']" type="checkbox" value="'.$sChoiceId.'" '.$sDisabled.$sChecked.'/>'.$sHiddenInput.'&nbsp;');
759-
$this->DisplayChoice($oPage, $aChoice, $aSelectedComponents, $aDefaults, $sChoiceId, $aFlags['disabled'], $sTooltip);
760-
$oPage->add('</div>');
735+
$this->DisplayChoice($oPage, $aChoice, $aSelectedComponents, $aDefaults, $sChoiceId, $sChoiceId, $aFlags);
761736
}
737+
762738
$sChoiceName = null;
763-
$sDisabled = '';
764739
$bDisabled = false;
765740
$sChoiceIdNone = null;
766741
foreach ($aAlternatives as $index => $aChoice) {
767742
$sChoiceId = $sParentId.self::$SEP.$index;
768743
if ($sChoiceName == null) {
769744
$sChoiceName = $sChoiceId; // All radios share the same name
770745
}
771-
$bIsDefault = array_key_exists($sChoiceName, $aDefaults) && ($aDefaults[$sChoiceName] == $sChoiceId);
746+
//Defaults contains previous installation choices during upgrade
747+
$bIsDefault = array_key_exists($sChoiceName, $aDefaults) && ($aDefaults[$sChoiceName] === $sChoiceId);
772748
$bMandatory = (isset($aChoice['mandatory']) && $aChoice['mandatory']) || ($this->bUpgrade && $bIsDefault);
773749
if ($bMandatory || $bAllDisabled) {
774750
// One choice is mandatory, all alternatives are disabled
775-
$sDisabled = ' disabled data-disabled="disabled"';
776751
$bDisabled = true;
777752
}
778-
if ((!isset($aChoice['sub_options']) || (count($aChoice['sub_options']) == 0)) && (!isset($aChoice['modules']) || (count($aChoice['modules']) == 0))) {
753+
if ((!isset($aChoice['sub_options']) || (count($aChoice['sub_options']) === 0)) && (!isset($aChoice['modules']) || (count($aChoice['modules']) === 0))) {
754+
//If there is no modules in the choice AND it has no sub choices, it is an empty choice.
779755
$sChoiceIdNone = $sChoiceId; // the "None" / empty choice
780756
}
781757
}
782758

783-
if (!array_key_exists($sChoiceName, $aDefaults) || ($aDefaults[$sChoiceName] == $sChoiceIdNone)) {
759+
if (!array_key_exists($sChoiceName, $aDefaults) || ($aDefaults[$sChoiceName] === $sChoiceIdNone)) {
784760
// The "none" choice does not disable the selection !!
785-
$sDisabled = '';
786761
$bDisabled = false;
787762
}
788763

789764
foreach ($aAlternatives as $index => $aChoice) {
790-
$sAttributes = '';
791765
$sChoiceId = $sParentId.self::$SEP.$index;
792-
$sDataId = 'data-id="'.utils::EscapeHtml($aChoice['extension_code']).'"';
793-
$sId = utils::EscapeHtml($aChoice['extension_code']);
794-
if ($sChoiceName == null) {
766+
if ($sChoiceName === null) {
795767
$sChoiceName = $sChoiceId; // All radios share the same name
796768
}
797-
$bIsDefault = array_key_exists($sChoiceName, $aDefaults) && ($aDefaults[$sChoiceName] == $sChoiceId);
798-
$bSelected = isset($aSelectedComponents[$sChoiceName]) && ($aSelectedComponents[$sChoiceName] == $sChoiceId);
799-
if (!isset($aSelectedComponents[$sChoiceName]) && ($sChoiceIdNone != null)) {
769+
$bSelected = isset($aSelectedComponents[$sChoiceName]) && ($aSelectedComponents[$sChoiceName] === $sChoiceId);
770+
if (!isset($aSelectedComponents[$sChoiceName]) && ($sChoiceIdNone !== null)) {
800771
// No choice selected, select the "None" option
801-
$bSelected = ($sChoiceId == $sChoiceIdNone);
772+
$bSelected = ($sChoiceId === $sChoiceIdNone);
802773
}
803-
$bMandatory = (isset($aChoice['mandatory']) && $aChoice['mandatory']) || ($this->bUpgrade && $bIsDefault);
804774

805-
if ($bSelected) {
806-
$sAttributes = ' checked ';
807-
}
808-
$sHidden = '';
809-
if ($bMandatory && $bDisabled) {
810-
$sAttributes = ' checked ';
811-
$sHidden = '<input type="hidden" name="choice['.$sChoiceName.']" value="'.$sChoiceId.'"/>';
812-
}
813-
$oPage->add('<div class="choice" '.$sDataId.'><input class="wiz-choice" id="'.$sId.'" name="choice['.$sChoiceName.']" type="radio"'.$sAttributes.' value="'.$sChoiceId.'"'.$sDisabled.'/>'.$sHidden.'&nbsp;');
814-
$this->DisplayChoice($oPage, $aChoice, $aSelectedComponents, $aDefaults, $sChoiceId, $bDisabled && !$bSelected);
815-
$oPage->add('</div>');
775+
$aFlags = $this->ComputeChoiceFlags($aChoice, $sChoiceId, $aSelectedComponents, $bAllDisabled, $bDisableUninstallCheck, $this->bUpgrade);
776+
//ComputeChoiceFlags does not completely compute alternative flags
777+
$aFlags['disabled'] = $bDisabled;
778+
$aFlags['checked'] = $bSelected;
779+
$this->DisplayChoice($oPage, $aChoice, $aSelectedComponents, $aDefaults, $sChoiceName, $sChoiceId, $aFlags, 'radio');
816780
}
817781
}
818782

819-
protected function DisplayChoice($oPage, $aChoice, $aSelectedComponents, $aDefaults, $sChoiceId, $bDisabled = false, $sTooltip = '')
783+
protected function DisplayChoice($oPage, $aChoice, $aSelectedComponents, $aDefaults, $sChoiceName, $sChoiceId, $aFlags, $sInputType = 'checkbox')
820784
{
821-
$sMoreInfo = (isset($aChoice['more_info']) && ($aChoice['more_info'] != '')) ? '<a class="setup--wizard-choice--more-info" target="_blank" href="'.$aChoice['more_info'].'">More information</a>' : '';
822-
$sSourceLabel = $aChoice['source_label'] ?? '';
785+
$sMoreInfo = (isset($aChoice['more_info']) && ($aChoice['more_info'] != '')) ? '
786+
<a class="setup--wizard-choice--more-info" target="_blank" href="'.$aChoice['more_info'].'">
787+
<i class="setup-extension--icon fas fa-external-link-alt" title="More information"></i>
788+
</a>' : '';
789+
$sDescription = isset($aChoice['description']) ? utils::EscapeHtml($aChoice['description']) : '';
823790
$sId = utils::EscapeHtml($aChoice['extension_code']);
791+
$sDataId = 'data-id="'.utils::EscapeHtml($aChoice['extension_code']).'"';
792+
$sDisabled = $aFlags['disabled'] ? ' disabled data-disabled="disabled"' : '';
793+
$sChecked = $aFlags['checked'] ? ' checked ' : '';
794+
$sHiddenInput = $aFlags['disabled'] && $aFlags['checked'] ? '<input type="hidden" name="choice['.$sChoiceName.']" value="'.$sChoiceId.'"/>' : '';
824795

825-
$oPage->add('<label class="setup--wizard-choice--label" for="'.$sId.'">'.$sSourceLabel.'<b>'.utils::EscapeHtml($aChoice['title']).'</b>'.'&nbsp;'.$sTooltip.'</label> '.$sMoreInfo.'');
826-
$sDescription = isset($aChoice['description']) ? utils::EscapeHtml($aChoice['description']) : '';
827-
$oPage->add('<div class="setup--wizard-choice--description description">'.$sDescription.'<span id="sub_choices'.$sId.'">');
796+
$sTooltip = '';
797+
if ($aFlags['missing']) {
798+
$sTooltip .= '<span class="ibo-badge ibo-block ibo-is-red" title="The local extension folder has been removed from the disk. This will force the uninstallation of this extension." >source removed</span>';
799+
}
800+
if ($aFlags['installed']) {
801+
$sTooltip .= '<span class="ibo-badge ibo-block checked ibo-is-green" title="This extension is part of the current installation." >installed</span>';
802+
803+
$sTooltip .= '<span class="ibo-badge ibo-block unchecked ibo-is-red" title="This extension will be uninstalled during the setup." >to be uninstalled</span>';
804+
} else {
805+
$sTooltip .= '<span class="ibo-badge ibo-block checked ibo-is-cyan" title="This extension will be installed during the setup." >to be installed</span>';
806+
$sTooltip .= '<span class="ibo-badge ibo-block unchecked ibo-is-blue-grey" title="This extension is not part of the current installation." >not installed</span>';
807+
}
808+
if (!$aFlags['uninstallable']) {
809+
$sTooltip .= '<span class="ibo-badge ibo-block ibo-is-orange" title="Once this extension has been installed, it should not be uninstalled." >cannot be uninstalled</span>';
810+
}
811+
812+
$sMetadata = '';
813+
if (isset($aChoice['version']) && isset($aChoice['source_label'])) {
814+
$sMetadata = '<span>v'.$aChoice['version'].'</span><span>'.$aChoice['source_label'].'</span>';
815+
}
816+
$sChoiceDisabled = $aFlags['disabled'] && !$aFlags['checked'] ? 'choice-disabled' : '';
817+
818+
$oPage->add('
819+
<div class="ibo-extension-details ibo-content-block ibo-block '.$sChoiceDisabled.'" '.$sDataId.'>
820+
<div class="ibo-extension-details--actions">
821+
<input class="wiz-choice" id="'.$sId.'" name="choice['.$sChoiceName.']" type="'.$sInputType.'" value="'.$sChoiceId.'" '.$sDisabled.$sChecked.'/>
822+
'.$sHiddenInput.'
823+
</div>
824+
<div class="ibo-extension-details--information">
825+
<div class="ibo-extension-details--information--label">
826+
<label for="'.$sId.'"><b>'.utils::EscapeHtml($aChoice['title']).'</b></label>
827+
'.$sMoreInfo.'
828+
'.$sTooltip.'
829+
</div>
830+
<div class="ibo-extension-details--information--metadata">
831+
'.$sMetadata.'
832+
</div>
833+
<div class="ibo-extension-details--information--description">
834+
'.$sDescription.'
835+
');
836+
$bSubOptionsDisabled = $aFlags['disabled'] && (!$aFlags['installed'] || $sInputType === 'checkbox');
828837
if (isset($aChoice['sub_options'])) {
829-
$this->DisplayOptions($oPage, $aChoice['sub_options'], $aSelectedComponents, $aDefaults, $sChoiceId, $bDisabled);
838+
$oPage->add('<div id="sub_choices'.$sId.'">');
839+
$this->DisplayOptions($oPage, $aChoice['sub_options'], $aSelectedComponents, $aDefaults, $sChoiceId, $bSubOptionsDisabled);
840+
$oPage->add('</div>');
830841
}
831-
$oPage->add('</span></div>');
842+
$oPage->add('
843+
</div>
844+
</div>
845+
</div>
846+
');
832847
}
833848

834849
protected function GetSourceFilePath()

0 commit comments

Comments
 (0)