Compare commits

...

14 Commits

Author SHA1 Message Date
Eric
b0414748cb Typo 2019-06-13 11:55:10 +02:00
Molkobain
b6418d95e7 Add PHPDoc for type hinting as iTop replaces \DOMDocument with \MFDocument 2019-05-28 10:36:18 +02:00
Molkobain
2d6251e5df 💄 Add warning message CSS class (like error message) 2019-05-15 17:53:48 +02:00
Molkobain
91f410a85c 💄 Fix images being too large in icon selector (dashboards and Designer)
Note: The widget still needs a more aggressive refactoring to render nicely...
2019-05-02 16:42:21 +02:00
Eric
0a48696cd8 Carbon: N°1855 - Fix: Cannot remove last 'dependencies' with UI
Note that multi-select value when no entry is selected is "" and not []
in order to be posted, so multi-select values are not always arrays.
2019-04-30 15:46:44 +02:00
Eric
2f71570390 Carbon: N°1855 - fix "depends on" displaying fields from children 2019-04-30 12:02:13 +02:00
Molkobain
78b6c03af7 💡 Add some PHPDoc 2019-04-25 12:46:57 +02:00
Molkobain
22342cdc05 🐛 N°2184 Fix validation issue when several label fiels in a dashlet/designer form 2019-04-25 12:42:16 +02:00
Molkobain
dcf4963e0c N°2152 Fix bad XML generation when adding a dashboard attribute on a new class 2019-04-16 17:15:15 +02:00
Eric
9ec36a76f6 Carbon: N°1589 - Check migration 2019-04-10 12:12:31 +02:00
Eric
09b470e6c7 Better output 2019-04-09 10:43:39 +02:00
Molkobain
40151c7a43 N°2147 Fix non working impact relation when based on default value 2019-04-05 16:25:26 +02:00
Molkobain
34c030b501 N°2070 Extend ModelFactory implementations to optionally check meta classes (PHP) along with regular XML classes 2019-04-05 15:48:29 +02:00
Molkobain
c59d3cc624 Fix unreachable log message on exception 2019-04-01 16:52:22 +02:00
7 changed files with 206 additions and 40 deletions

View File

@@ -395,6 +395,7 @@ EOF
{ {
foreach($aFields as $oField) foreach($aFields as $oField)
{ {
/** @var \DesignerFormField $oField */
$oField->ReadParam($aValues); $oField->ReadParam($aValues);
} }
} }
@@ -679,18 +680,34 @@ class DesignerTabularForm extends DesignerForm
class DesignerFormField class DesignerFormField
{ {
/** @var string $sLabel */
protected $sLabel; protected $sLabel;
/** @var string $sCode */
protected $sCode; protected $sCode;
/** @var mixed $defaultValue */
protected $defaultValue; protected $defaultValue;
/** @var \DesignerForm $oForm */ /** @var \DesignerForm $oForm */
protected $oForm; protected $oForm;
/** @var bool $bMandatory */
protected $bMandatory; protected $bMandatory;
/** @var bool $bReadOnly */
protected $bReadOnly; protected $bReadOnly;
/** @var bool $bAutoApply */
protected $bAutoApply; protected $bAutoApply;
/** @var array $aCSSClasses */
protected $aCSSClasses; protected $aCSSClasses;
/** @var bool $bDisplayed */
protected $bDisplayed; protected $bDisplayed;
/** @var array $aWidgetExtraParams */
protected $aWidgetExtraParams; protected $aWidgetExtraParams;
/**
* DesignerFormField constructor.
*
* @param string $sCode
* @param string $sLabel
* @param mixed $defaultValue
*/
public function __construct($sCode, $sLabel, $defaultValue) public function __construct($sCode, $sLabel, $defaultValue)
{ {
$this->sLabel = $sLabel; $this->sLabel = $sLabel;
@@ -703,7 +720,10 @@ class DesignerFormField
$this->bDisplayed = true; $this->bDisplayed = true;
$this->aWidgetExtraParams = array(); $this->aWidgetExtraParams = array();
} }
/**
* @return string
*/
public function GetCode() public function GetCode()
{ {
return $this->sCode; return $this->sCode;
@@ -712,69 +732,108 @@ class DesignerFormField
/** /**
* @param \DesignerForm $oForm * @param \DesignerForm $oForm
*/ */
public function SetForm(\DesignerForm $oForm) public function SetForm(DesignerForm $oForm)
{ {
$this->oForm = $oForm; $this->oForm = $oForm;
} }
/**
* @param bool $bMandatory
*/
public function SetMandatory($bMandatory = true) public function SetMandatory($bMandatory = true)
{ {
$this->bMandatory = $bMandatory; $this->bMandatory = $bMandatory;
} }
/**
* @param bool $bReadOnly
*/
public function SetReadOnly($bReadOnly = true) public function SetReadOnly($bReadOnly = true)
{ {
$this->bReadOnly = $bReadOnly; $this->bReadOnly = $bReadOnly;
} }
/**
* @return bool
*/
public function IsReadOnly() public function IsReadOnly()
{ {
return ($this->oForm->IsReadOnly() || $this->bReadOnly); return ($this->oForm->IsReadOnly() || $this->bReadOnly);
} }
/**
* @param bool $bAutoApply
*/
public function SetAutoApply($bAutoApply) public function SetAutoApply($bAutoApply)
{ {
$this->bAutoApply = $bAutoApply; $this->bAutoApply = $bAutoApply;
} }
/**
* @return bool
*/
public function IsAutoApply() public function IsAutoApply()
{ {
return $this->bAutoApply; return $this->bAutoApply;
} }
/**
* @param bool $bDisplayed
*/
public function SetDisplayed($bDisplayed) public function SetDisplayed($bDisplayed)
{ {
$this->bDisplayed = $bDisplayed; $this->bDisplayed = $bDisplayed;
} }
/**
* @return bool
*/
public function IsDisplayed() public function IsDisplayed()
{ {
return $this->bDisplayed; return $this->bDisplayed;
} }
/**
* @return string
*/
public function GetFieldId() public function GetFieldId()
{ {
return $this->oForm->GetFieldId($this->sCode); return $this->oForm->GetFieldId($this->sCode);
} }
/**
* @return string
*/
public function GetWidgetClass() public function GetWidgetClass()
{ {
return 'property_field'; return 'property_field';
} }
/**
* @return array
*/
public function GetWidgetExtraParams() public function GetWidgetExtraParams()
{ {
return $this->aWidgetExtraParams; return $this->aWidgetExtraParams;
} }
/**
* @param \WebPage $oP
* @param string $sFormId
* @param string $sRenderMode
*
* @return array
*/
public function Render(WebPage $oP, $sFormId, $sRenderMode='dialog') public function Render(WebPage $oP, $sFormId, $sRenderMode='dialog')
{ {
$sId = $this->oForm->GetFieldId($this->sCode); $sId = $this->oForm->GetFieldId($this->sCode);
$sName = $this->oForm->GetFieldName($this->sCode); $sName = $this->oForm->GetFieldName($this->sCode);
return array('label' => $this->sLabel, 'value' => "<input type=\"text\" id=\"$sId\" name=\"$sName\" value=\"".htmlentities($this->defaultValue, ENT_QUOTES, 'UTF-8')."\">"); return array('label' => $this->sLabel, 'value' => "<input type=\"text\" id=\"$sId\" name=\"$sName\" value=\"".htmlentities($this->defaultValue, ENT_QUOTES, 'UTF-8')."\">");
} }
/**
* @param array $aValues
*/
public function ReadParam(&$aValues) public function ReadParam(&$aValues)
{ {
if ($this->IsReadOnly()) if ($this->IsReadOnly())
@@ -801,12 +860,18 @@ class DesignerFormField
} }
} }
} }
/**
* @return bool
*/
public function IsVisible() public function IsVisible()
{ {
return true; return true;
} }
/**
* @param string $sCSSClass
*/
public function AddCSSClass($sCSSClass) public function AddCSSClass($sCSSClass)
{ {
$this->aCSSClasses[] = $sCSSClass; $this->aCSSClasses[] = $sCSSClass;
@@ -814,6 +879,8 @@ class DesignerFormField
/** /**
* A way to set/change the default value after constructing the field * A way to set/change the default value after constructing the field
*
* @param array $aAllDefaultValue
*/ */
public function SetDefaultValueFrom($aAllDefaultValue) public function SetDefaultValueFrom($aAllDefaultValue)
{ {
@@ -822,7 +889,12 @@ class DesignerFormField
$this->defaultValue = $aAllDefaultValue[$this->GetCode()]; $this->defaultValue = $aAllDefaultValue[$this->GetCode()];
} }
} }
/**
* @param $sFieldCode
*
* @return \DesignerFormField|false
*/
public function FindField($sFieldCode) public function FindField($sFieldCode)
{ {
if ($this->sCode == $sFieldCode) if ($this->sCode == $sFieldCode)
@@ -832,11 +904,17 @@ class DesignerFormField
return false; return false;
} }
/**
* @return string
*/
public function GetHandlerEquals() public function GetHandlerEquals()
{ {
return 'null'; return 'null';
} }
/**
* @return string
*/
public function GetHandlerGetValue() public function GetHandlerGetValue()
{ {
return 'null'; return 'null';
@@ -845,25 +923,43 @@ class DesignerFormField
class DesignerLabelField extends DesignerFormField class DesignerLabelField extends DesignerFormField
{ {
/** @var int $iCount A counter to automatically make the field code */
protected static $iCount = 0;
/** @var string $sDescription */
protected $sDescription; protected $sDescription;
/**
* @inheritdoc
*/
public function __construct($sLabel, $sDescription) public function __construct($sLabel, $sDescription)
{ {
parent::__construct('', $sLabel, ''); // Increase counter
static::$iCount++;
parent::__construct('label_number_' . static::$iCount, $sLabel, '');
$this->sDescription = $sDescription; $this->sDescription = $sDescription;
} }
/**
* @inheritdoc
*/
public function Render(WebPage $oP, $sFormId, $sRenderMode='dialog') public function Render(WebPage $oP, $sFormId, $sRenderMode='dialog')
{ {
$sId = $this->oForm->GetFieldId($this->sCode); $sId = $this->oForm->GetFieldId($this->sCode);
$sName = $this->oForm->GetFieldName($this->sCode); $sName = $this->oForm->GetFieldName($this->sCode);
return array('label' => $this->sLabel, 'value' => $this->sDescription); return array('label' => $this->sLabel, 'value' => $this->sDescription);
} }
/**
* @inheritdoc
*/
public function ReadParam(&$aValues) public function ReadParam(&$aValues)
{ {
} }
/**
* @inheritdoc
*/
public function IsVisible() public function IsVisible()
{ {
return true; return true;
@@ -1334,7 +1430,8 @@ class DesignerIconSelectionField extends DesignerFormField
$sPostUploadTo = ($this->sUploadUrl == null) ? 'null' : "'{$this->sUploadUrl}'"; $sPostUploadTo = ($this->sUploadUrl == null) ? 'null' : "'{$this->sUploadUrl}'";
if (!$this->IsReadOnly()) if (!$this->IsReadOnly())
{ {
$sValue = "<input type=\"hidden\" id=\"$sId\" name=\"$sName\" value=\"{$this->defaultValue}\"/>"; $sDefaultValue = ($this->defaultValue !== '') ? : $this->aAllowedValues[$idx]['value'];
$sValue = "<input type=\"hidden\" id=\"$sId\" name=\"$sName\" value=\"{$sDefaultValue}\"/>";
$oP->add_ready_script( $oP->add_ready_script(
<<<EOF <<<EOF
$('#$sId').icon_select({current_idx: $idx, items: $sJSItems, post_upload_to: $sPostUploadTo}); $('#$sId').icon_select({current_idx: $idx, items: $sJSItems, post_upload_to: $sPostUploadTo});

View File

@@ -602,17 +602,19 @@ class utils
/** /**
* Format a value into a more friendly format (KB, MB, GB, TB) instead a juste a Bytes amount. * Format a value into a more friendly format (KB, MB, GB, TB) instead a juste a Bytes amount.
* *
* @param type $value * @param int $value
* @return string * @return string
*/ */
public static function BytesToFriendlyFormat($value) public static function BytesToFriendlyFormat($value)
{ {
$sReturn = ''; $sReturn = '';
$iPrecision = 0;
// Kilobytes // Kilobytes
if ($value >= 1024) if ($value >= 1024)
{ {
$sReturn = 'K'; $sReturn = 'K';
$value = $value / 1024; $value = $value / 1024;
$iPrecision = 1;
} }
// Megabytes // Megabytes
if ($value >= 1024) if ($value >= 1024)
@@ -633,7 +635,7 @@ class utils
$value = $value / 1024; $value = $value / 1024;
} }
$value = round($value, 1); $value = round($value, $iPrecision);
return $value . '' . $sReturn . 'B'; return $value . '' . $sReturn . 'B';
} }

View File

@@ -2398,6 +2398,12 @@ a.summary, a.summary:hover {
background: url(../images/ok.png?v=v2.6.1) 1em 1em no-repeat #cfc; background: url(../images/ok.png?v=v2.6.1) 1em 1em no-repeat #cfc;
padding-left: 3em; padding-left: 3em;
} }
.message_warning {
border: 1px solid #ec9800;
background: url(../images/error.png?v=v2.6.1) 1em 1em no-repeat #ffd78d;
color: #000;
padding-left: 3em;
}
.message_error { .message_error {
border: 1px solid #933; border: 1px solid #933;
background: url(../images/error.png?v=v2.6.1) 1em 1em no-repeat #fcc; background: url(../images/error.png?v=v2.6.1) 1em 1em no-repeat #fcc;
@@ -2927,6 +2933,17 @@ table.listResults .originColor {
.menu-icon-select > .ui-menu-item { .menu-icon-select > .ui-menu-item {
padding: 0.3em 3%; padding: 0.3em 3%;
} }
.menu-icon-select > .ui-menu-item > * {
width: 100%;
white-space: nowrap;
overflow-x: hidden;
text-overflow: ellipsis;
}
.menu-icon-select > .ui-menu-item > * > img {
max-width: 80px;
max-height: 45px;
margin-right: 10px;
}
.attribute.attribute-set .attribute-set-item::after { .attribute.attribute-set .attribute-set-item::after {
content: ","; content: ",";
margin-right: 0.5em; margin-right: 0.5em;

View File

@@ -2762,6 +2762,12 @@ a.summary, a.summary:hover {
background: url(../images/ok.png?v=#{$version}) 1em 1em no-repeat #cfc; background: url(../images/ok.png?v=#{$version}) 1em 1em no-repeat #cfc;
padding-left: 3em; padding-left: 3em;
} }
.message_warning {
border: 1px solid #ec9800;
background: url(../images/error.png?v=#{$version}) 1em 1em no-repeat #ffd78d;
color: #000;
padding-left: 3em;
}
.message_error { .message_error {
border: 1px solid #933; border: 1px solid #933;
background: url(../images/error.png?v=#{$version}) 1em 1em no-repeat #fcc; background: url(../images/error.png?v=#{$version}) 1em 1em no-repeat #fcc;
@@ -3353,6 +3359,19 @@ table.listResults .originColor{
} }
.menu-icon-select > .ui-menu-item{ .menu-icon-select > .ui-menu-item{
padding: .3em 3%; padding: .3em 3%;
> *{
width: 100%;
white-space: nowrap;
overflow-x: hidden;
text-overflow: ellipsis;
> img{
max-width: 80px;
max-height: 45px;
margin-right: 10px;
}
}
} }
////////////////////// //////////////////////

View File

@@ -256,14 +256,14 @@ $(function()
if (oWidget && oWidget._is_visible()) if (oWidget && oWidget._is_visible())
{ {
var oVal = oWidget._get_committed_value(); var oVal = oWidget._get_committed_value();
oData[oVal.name] = oVal.value; oData[oVal.name] = me._get_value_for_post(oVal.value);
} }
}); });
oPostedData = this.options.submit_parameters; var oPostedData = this.options.submit_parameters;
oPostedData.params = oData; oPostedData.params = oData;
oPostedData.params.updated = [ $('#'+this.options.field_id, this.element).attr('name') ]; // only one field updated in this case oPostedData.params.updated = [ $('#'+this.options.field_id, this.element).attr('name') ]; // only one field updated in this case
oPostedData.params.previous_values = {}; oPostedData.params.previous_values = {};
oPostedData.params.previous_values[oPostedData.params.updated] = this.previous_value; // pass also the previous value(s) oPostedData.params.previous_values[$('#'+this.options.field_id, this.element).attr('name')] = me._get_value_for_post(this.previous_value); // pass also the previous value(s)
$.post(this.options.submit_to, oPostedData, function(data) $.post(this.options.submit_to, oPostedData, function(data)
{ {
$('#prop_submit_result').html(data); $('#prop_submit_result').html(data);
@@ -293,6 +293,14 @@ $(function()
oWidget = element.data('itopSelector_property_field'); oWidget = element.data('itopSelector_property_field');
} }
return oWidget; return oWidget;
},
_get_value_for_post: function(value)
{
if ((typeof value == "object") && (Object.keys(value).length === 0))
{
return "";
}
return value;
} }
}); });
}); });

View File

@@ -150,8 +150,8 @@ try
$sAuthent = utils::ReadParam('authent', '', false, 'raw_data'); $sAuthent = utils::ReadParam('authent', '', false, 'raw_data');
if (!file_exists(APPROOT.'data/setup/authent') || $sAuthent !== file_get_contents(APPROOT.'data/setup/authent')) if (!file_exists(APPROOT.'data/setup/authent') || $sAuthent !== file_get_contents(APPROOT.'data/setup/authent'))
{ {
throw new SecurityException('Setup operations are not allowed outside of the setup');
SetupPage::log_error("Setup operations are not allowed outside of the setup"); SetupPage::log_error("Setup operations are not allowed outside of the setup");
throw new SecurityException('Setup operations are not allowed outside of the setup');
} }
switch($sOperation) switch($sOperation)

View File

@@ -615,8 +615,8 @@ class ModelFactory
if (!$oTargetParentNode) if (!$oTargetParentNode)
{ {
echo "Dumping target doc - looking for '$sParentId'<br/>\n"; // echo "Dumping target doc - looking for '$sParentId'<br/>\n";
$this->oDOMDocument->firstChild->Dump(); // $this->oDOMDocument->firstChild->Dump();
$sPath = MFDocument::GetItopNodePath($oSourceNode); $sPath = MFDocument::GetItopNodePath($oSourceNode);
$iLine = $oSourceNode->getLineNo(); $iLine = $oSourceNode->getLineNo();
throw new MFException($sPath.' at line '.$iLine.": parent class '$sParentId' could not be found", MFException::PARENT_NOT_FOUND, $iLine, $sPath, $sParentId); throw new MFException($sPath.' at line '.$iLine.": parent class '$sParentId' could not be found", MFException::PARENT_NOT_FOUND, $iLine, $sPath, $sParentId);
@@ -633,8 +633,8 @@ class ModelFactory
} }
else else
{ {
echo "Dumping target doc - looking for '".$oSourceNode->getAttribute('id')."'<br/>\n"; // echo "Dumping target doc - looking for '".$oSourceNode->getAttribute('id')."'<br/>\n";
$this->oDOMDocument->firstChild->Dump(); // $this->oDOMDocument->firstChild->Dump();
$sPath = MFDocument::GetItopNodePath($oSourceNode); $sPath = MFDocument::GetItopNodePath($oSourceNode);
$iLine = $oSourceNode->getLineNo(); $iLine = $oSourceNode->getLineNo();
throw new MFException($sPath.' at line '.$iLine.": could not be found", MFException::NOT_FOUND, $iLine, $sPath); throw new MFException($sPath.' at line '.$iLine.": could not be found", MFException::NOT_FOUND, $iLine, $sPath);
@@ -1078,13 +1078,17 @@ class ModelFactory
/** /**
* Check if the class specified by the given name already exists in the loaded DOM * Check if the class specified by the given name already exists in the loaded DOM
*
* @param string $sClassName The node corresponding to the class to load * @param string $sClassName The node corresponding to the class to load
* @throws Exception * @param bool $bIncludeMetas Look for $sClassName also in meta declaration (PHP classes) if not found in XML classes
*
* @throws \Exception
*
* @return bool True if the class exists, false otherwise * @return bool True if the class exists, false otherwise
*/ */
protected function ClassNameExists($sClassName) protected function ClassNameExists($sClassName, $bIncludeMetas = false)
{ {
return !is_null($this->GetClass($sClassName)); return !is_null($this->GetClass($sClassName, $bIncludeMetas));
} }
/** /**
@@ -1190,14 +1194,22 @@ EOF
{ {
return $this->GetNodes("/itop_design/classes//class[@id][@_created_in='$sModuleName']"); return $this->GetNodes("/itop_design/classes//class[@id][@_created_in='$sModuleName']");
} }
/** /**
* List all classes from the DOM * List all classes from the DOM
* @throws Exception *
* @param bool $bIncludeMetas Also look for meta declaration (PHP classes) in addition to XML classes
*
* @return \DOMNodeList
*/ */
public function ListAllClasses() public function ListAllClasses($bIncludeMetas = false)
{ {
return $this->GetNodes("/itop_design/classes//class[@id]"); $sXPath = "/itop_design/classes//class[@id]";
if($bIncludeMetas === true)
{
$sXPath .= "|/itop_design/meta/classes/class[@id]";
}
return $this->GetNodes($sXPath);
} }
/** /**
@@ -1210,13 +1222,22 @@ EOF
} }
/** /**
* @param $sClassName * @param string $sClassName
* @param bool $bIncludeMetas Look for $sClassName also in meta declaration (PHP classes) if not found in XML classes
* *
* @return \DOMElement * @return null|\DOMElement
*/ */
public function GetClass($sClassName) public function GetClass($sClassName, $bIncludeMetas = false)
{ {
// Check if class among XML classes
$oClassNode = $this->GetNodes("/itop_design/classes//class[@id='$sClassName']")->item(0); $oClassNode = $this->GetNodes("/itop_design/classes//class[@id='$sClassName']")->item(0);
// If not, check if class among exposed meta classes (PHP classes)
if(is_null($oClassNode) && ($bIncludeMetas === true))
{
$oClassNode = $this->GetNodes("/itop_design/meta/classes/class[@id='$sClassName']")->item(0);
}
return $oClassNode; return $oClassNode;
} }
@@ -1764,6 +1785,7 @@ EOF;
/** /**
* MFElement: helper to read/change the DOM * MFElement: helper to read/change the DOM
* @package ModelFactory * @package ModelFactory
* @property \MFDocument $ownerDocument This is only here for type hinting as iTop replaces \DOMDocument with \MFDocument
*/ */
class MFElement extends Combodo\iTop\DesignElement class MFElement extends Combodo\iTop\DesignElement
{ {
@@ -2286,8 +2308,8 @@ class MFElement extends Combodo\iTop\DesignElement
{ {
if ($bMustExist) if ($bMustExist)
{ {
echo "Dumping parent node<br/>\n"; //echo "Dumping parent node<br/>\n";
$oContainer->Dump(); //$oContainer->Dump();
throw new Exception(MFDocument::GetItopNodePath($this).' at line '.$this->getLineNo().": could not be found"); throw new Exception(MFDocument::GetItopNodePath($this).' at line '.$this->getLineNo().": could not be found");
} }
if (!$bIfExists) if (!$bIfExists)
@@ -2358,6 +2380,7 @@ class MFElement extends Combodo\iTop\DesignElement
case 'added': case 'added':
case 'replaced': case 'replaced':
case 'needed': case 'needed':
case 'forced':
// marked as added or modified, just reset the flag // marked as added or modified, just reset the flag
$oNode->removeAttribute('_alteration'); $oNode->removeAttribute('_alteration');
break; break;