mirror of
https://github.com/Combodo/iTop.git
synced 2026-02-12 23:14:18 +01:00
Merge remote-tracking branch 'origin/support/3.2' into develop
This commit is contained in:
@@ -1330,7 +1330,8 @@ class DesignerComboField extends DesignerFormField
|
||||
{
|
||||
if ($this->bMultipleSelection)
|
||||
{
|
||||
$sHtml = "<span><select $sCSSClasses multiple size=\"8\"id=\"$sId\" name=\"$sName\">";
|
||||
$iSize = max(1, min(8, count($this->aAllowedValues)));
|
||||
$sHtml = "<span><select $sCSSClasses multiple size=\"$iSize\" id=\"$sId\" name=\"$sName\">";
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -4491,6 +4491,9 @@
|
||||
<attribute id="name"/>
|
||||
</attributes>
|
||||
</naming>
|
||||
<fields_semantic>
|
||||
<image_attribute>logo</image_attribute>
|
||||
</fields_semantic>
|
||||
<style>
|
||||
<icon/>
|
||||
</style>
|
||||
@@ -4509,6 +4512,13 @@
|
||||
</uniqueness_rules>
|
||||
</properties>
|
||||
<fields>
|
||||
<field id="logo" xsi:type="AttributeImage">
|
||||
<display_max_width>96</display_max_width>
|
||||
<display_max_height>96</display_max_height>
|
||||
<storage_max_width>128</storage_max_width>
|
||||
<storage_max_height>128</storage_max_height>
|
||||
<is_null_allowed>true</is_null_allowed>
|
||||
</field>
|
||||
<field id="physicaldevices_list" xsi:type="AttributeLinkedSet">
|
||||
<linked_class>PhysicalDevice</linked_class>
|
||||
<ext_key_to_me>brand_id</ext_key_to_me>
|
||||
@@ -4525,9 +4535,12 @@
|
||||
<item id="name">
|
||||
<rank>10</rank>
|
||||
</item>
|
||||
<item id="physicaldevices_list">
|
||||
<item id="logo">
|
||||
<rank>20</rank>
|
||||
</item>
|
||||
<item id="physicaldevices_list">
|
||||
<rank>30</rank>
|
||||
</item>
|
||||
</items>
|
||||
</details>
|
||||
<search>
|
||||
@@ -4544,6 +4557,13 @@
|
||||
</item>
|
||||
</items>
|
||||
</list>
|
||||
<summary>
|
||||
<items>
|
||||
<item id="name">
|
||||
<rank>10</rank>
|
||||
</item>
|
||||
</items>
|
||||
</summary>
|
||||
</presentation>
|
||||
</class>
|
||||
<class id="Model" _delta="define">
|
||||
@@ -4564,6 +4584,9 @@
|
||||
<attribute id="type"/>
|
||||
</complementary_attributes>
|
||||
</naming>
|
||||
<fields_semantic>
|
||||
<image_attribute>picture</image_attribute>
|
||||
</fields_semantic>
|
||||
<style>
|
||||
<icon/>
|
||||
</style>
|
||||
@@ -4596,6 +4619,13 @@
|
||||
<extkey_attcode>brand_id</extkey_attcode>
|
||||
<target_attcode>name</target_attcode>
|
||||
</field>
|
||||
<field id="picture" xsi:type="AttributeImage">
|
||||
<display_max_width>256</display_max_width>
|
||||
<display_max_height>256</display_max_height>
|
||||
<storage_max_width>512</storage_max_width>
|
||||
<storage_max_height>512</storage_max_height>
|
||||
<is_null_allowed>true</is_null_allowed>
|
||||
</field>
|
||||
<field id="type" xsi:type="AttributeEnum">
|
||||
<sort_type>label</sort_type>
|
||||
<values>
|
||||
@@ -4678,12 +4708,15 @@
|
||||
<item id="brand_id">
|
||||
<rank>20</rank>
|
||||
</item>
|
||||
<item id="type">
|
||||
<item id="picture">
|
||||
<rank>30</rank>
|
||||
</item>
|
||||
<item id="physicaldevices_list">
|
||||
<item id="type">
|
||||
<rank>40</rank>
|
||||
</item>
|
||||
<item id="physicaldevices_list">
|
||||
<rank>50</rank>
|
||||
</item>
|
||||
</items>
|
||||
</details>
|
||||
<search>
|
||||
@@ -4717,6 +4750,9 @@
|
||||
<item id="type">
|
||||
<rank>20</rank>
|
||||
</item>
|
||||
<item id="picture">
|
||||
<rank>30</rank>
|
||||
</item>
|
||||
</items>
|
||||
</summary>
|
||||
</presentation>
|
||||
|
||||
@@ -1092,6 +1092,8 @@ Dict::Add('EN US', 'English', 'English', array(
|
||||
Dict::Add('EN US', 'English', 'English', array(
|
||||
'Class:Brand' => 'Brand',
|
||||
'Class:Brand+' => '',
|
||||
'Class:Brand/Attribute:logo' => 'Logo',
|
||||
'Class:Brand/Attribute:logo+' => '',
|
||||
'Class:Brand/Attribute:physicaldevices_list' => 'Physical devices',
|
||||
'Class:Brand/Attribute:physicaldevices_list+' => 'All the physical devices corresponding to this brand',
|
||||
'Class:Brand/UniquenessRule:name+' => 'The name must be unique',
|
||||
@@ -1110,6 +1112,8 @@ Dict::Add('EN US', 'English', 'English', array(
|
||||
'Class:Model/Attribute:brand_id+' => '',
|
||||
'Class:Model/Attribute:brand_name' => 'Brand name',
|
||||
'Class:Model/Attribute:brand_name+' => '',
|
||||
'Class:Model/Attribute:picture' => 'Picture',
|
||||
'Class:Model/Attribute:picture+' => '',
|
||||
'Class:Model/Attribute:type' => 'Device type',
|
||||
'Class:Model/Attribute:type+' => '',
|
||||
'Class:Model/Attribute:type/Value:PowerSource' => 'Power Source',
|
||||
|
||||
@@ -28,6 +28,8 @@ Dict::Add('FR FR', 'French', 'Français', [
|
||||
'Class:ApplicationSolution/Attribute:status/Value:inactive+' => '',
|
||||
'Class:Brand' => 'Marque',
|
||||
'Class:Brand+' => '',
|
||||
'Class:Brand/Attribute:logo' => 'Logo',
|
||||
'Class:Brand/Attribute:logo+' => '',
|
||||
'Class:Brand/Attribute:physicaldevices_list' => 'Matériels',
|
||||
'Class:Brand/Attribute:physicaldevices_list+' => 'Tous les matériels correspondant à cette marque',
|
||||
'Class:Brand/Attribute:physicaldevices_list/UI:Links:Create:Button+' => 'Créer un %4$s',
|
||||
@@ -355,6 +357,8 @@ Dict::Add('FR FR', 'French', 'Français', [
|
||||
'Class:Model/Attribute:brand_id+' => '',
|
||||
'Class:Model/Attribute:brand_name' => 'Nom marque',
|
||||
'Class:Model/Attribute:brand_name+' => '',
|
||||
'Class:Model/Attribute:picture' => 'Image',
|
||||
'Class:Model/Attribute:picture+' => '',
|
||||
'Class:Model/Attribute:physicaldevices_list' => 'Matériels',
|
||||
'Class:Model/Attribute:physicaldevices_list+' => 'Tous les matériels correspondant à ce modèle',
|
||||
'Class:Model/Attribute:physicaldevices_list/UI:Links:Create:Button+' => 'Créer un %4$s',
|
||||
|
||||
2
js/ckeditor/build/ckeditor.js
vendored
2
js/ckeditor/build/ckeditor.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
33
js/ckeditor/package-lock.json
generated
33
js/ckeditor/package-lock.json
generated
@@ -33,7 +33,8 @@
|
||||
"@ckeditor/ckeditor5-table": "~41.4",
|
||||
"@ckeditor/ckeditor5-typing": "~41.4",
|
||||
"@ckeditor/ckeditor5-ui": "~41.4",
|
||||
"@ckeditor/ckeditor5-undo": "~41.4"
|
||||
"@ckeditor/ckeditor5-undo": "~41.4",
|
||||
"ws": ">=7.5.10"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@ckeditor/ckeditor5-core": "~41.4",
|
||||
@@ -3117,6 +3118,26 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/jsdom/node_modules/ws": {
|
||||
"version": "7.5.10",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz",
|
||||
"integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==",
|
||||
"engines": {
|
||||
"node": ">=8.3.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"bufferutil": "^4.0.1",
|
||||
"utf-8-validate": "^5.0.2"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"bufferutil": {
|
||||
"optional": true
|
||||
},
|
||||
"utf-8-validate": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/jsesc": {
|
||||
"version": "2.5.2",
|
||||
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
|
||||
@@ -5499,15 +5520,15 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/ws": {
|
||||
"version": "7.5.9",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz",
|
||||
"integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==",
|
||||
"version": "8.18.0",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz",
|
||||
"integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==",
|
||||
"engines": {
|
||||
"node": ">=8.3.0"
|
||||
"node": ">=10.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"bufferutil": "^4.0.1",
|
||||
"utf-8-validate": "^5.0.2"
|
||||
"utf-8-validate": ">=5.0.2"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"bufferutil": {
|
||||
|
||||
@@ -32,7 +32,8 @@
|
||||
"@ckeditor/ckeditor5-table": "~41.4",
|
||||
"@ckeditor/ckeditor5-typing": "~41.4",
|
||||
"@ckeditor/ckeditor5-ui": "~41.4",
|
||||
"@ckeditor/ckeditor5-undo": "~41.4"
|
||||
"@ckeditor/ckeditor5-undo": "~41.4",
|
||||
"ws": ">=7.5.10"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@ckeditor/ckeditor5-core": "~41.4",
|
||||
|
||||
@@ -95,20 +95,7 @@ $(function()
|
||||
value = $(oElem).val();
|
||||
}
|
||||
}
|
||||
else if( $(oElem).is(':radio'))
|
||||
{
|
||||
let nameRadioButton= $(oElem).prop('name');
|
||||
let radioCheckProp = $('[name='+nameRadioButton+']:checked');
|
||||
if(radioCheckProp.length === 1)
|
||||
{
|
||||
value = radioCheckProp.val();
|
||||
}
|
||||
else
|
||||
{
|
||||
value = "";
|
||||
}
|
||||
}
|
||||
else if($(oElem).is(':checkbox'))
|
||||
else if($(oElem).is(':checkbox') || $(oElem).is(':radio'))
|
||||
{
|
||||
if(value === null)
|
||||
{
|
||||
|
||||
@@ -57,6 +57,7 @@ $(function() {
|
||||
|
||||
// the constructor
|
||||
_create: function () {
|
||||
const me = this;
|
||||
const aMandatoryOptions = ['object_class', 'object_id', 'attribute_code'];
|
||||
for (let sOption of aMandatoryOptions) {
|
||||
if (null === this.options[sOption]) {
|
||||
@@ -66,19 +67,22 @@ $(function() {
|
||||
}
|
||||
}
|
||||
|
||||
this._UpdateState();
|
||||
if (this._IsSubmitAutonomous()) {
|
||||
this._ShowMainActions();
|
||||
} else {
|
||||
this._AddBridgeInput();
|
||||
this._HideMainActions();
|
||||
}
|
||||
// Ensure the CKEditor instance is ready before proceding
|
||||
this._GetCKEditorInstance(true).then((oCKEditorInstance) => {
|
||||
me._UpdateState();
|
||||
if (me._IsSubmitAutonomous()) {
|
||||
me._ShowMainActions();
|
||||
} else {
|
||||
me._AddBridgeInput();
|
||||
me._HideMainActions();
|
||||
}
|
||||
|
||||
this._bindEvents();
|
||||
me._bindEvents();
|
||||
|
||||
this.element.trigger('ready.caselog_entry_form.itop');
|
||||
me.element.trigger('ready.caselog_entry_form.itop');
|
||||
});
|
||||
},
|
||||
_bindEvents: async function () {
|
||||
_bindEvents: function () {
|
||||
let me = this;
|
||||
let CKEditorInstance = this._GetCKEditorInstance();
|
||||
// Handlers for the CKEditor itself
|
||||
@@ -198,8 +202,8 @@ $(function() {
|
||||
this.element.trigger('requested_submission.caselog_entry_form.itop', oData);
|
||||
},
|
||||
// - Form
|
||||
_GetCKEditorInstance: function () {
|
||||
return CombodoCKEditorHandler.GetInstanceSynchronous('#'+this.options.text_input_id);
|
||||
_GetCKEditorInstance: function (bAsync = false) {
|
||||
return bAsync ? CombodoCKEditorHandler.GetInstance('#'+this.options.text_input_id) : CombodoCKEditorHandler.GetInstanceSynchronous('#'+this.options.text_input_id);
|
||||
},
|
||||
_ShowEntryForm: function () {
|
||||
this.element.closest(this.js_selectors.activity_panel).find(this.js_selectors.form).removeClass(this.css_classes.is_closed);
|
||||
|
||||
@@ -39,7 +39,8 @@ $.widget( "itop.scrollabletabs", $.ui.tabs, {
|
||||
this._super(this.options);
|
||||
|
||||
// Initialize the vertical scroll offset
|
||||
this.scroll_offset_y = this.element.find('#' + this.tabs.eq(0).attr('data-tab-id')).offset().top;
|
||||
let oFirstPanel = this.element.find('#' + this.tabs.eq(0).attr('data-tab-id'));
|
||||
this.scroll_offset_y = oFirstPanel.length > 0 ? oFirstPanel.offset().top : this.element.find(this.js_selectors.tab_container_list).offset().top;
|
||||
|
||||
// Add every other tab to the controller
|
||||
$(this.js_selectors.tab_toggler).each(function(){
|
||||
@@ -53,14 +54,17 @@ $.widget( "itop.scrollabletabs", $.ui.tabs, {
|
||||
// Set active tab, tab-container gives us a tab based on url hash or 0
|
||||
this.setTab(this._findActive(this.options.active));
|
||||
// If not on the first tab, we scroll directly to it
|
||||
// Note: We don't want to scroll if we are on the first one, otherwise it will looks buggy because the page will be a bit scrolled and it doesn't feel right
|
||||
// Note: We don't want to scroll if we are on the first one, otherwise it will look buggy because the page will be a bit scrolled and it doesn't feel right
|
||||
if(this.options.active > 0) {
|
||||
const oActiveTab = this.tabs.eq(this.options.active);
|
||||
const oActivePanel = this.element.find('#' + oActiveTab.attr('data-tab-id'));
|
||||
|
||||
// Remove from scroll length the initial space between the top of the first panel and the top of the screen; this is to avoid scrolling too far
|
||||
// That being said, as lists are fetched / updated asynchroniously, once they got their responses, the layout will change/shift and the current tab won't be the good one anymore 😕
|
||||
this.controller.scrollTo(oActivePanel.offset().top - this.scroll_offset_y);
|
||||
// That being said, as lists are fetched / updated asynchronously, once they got their responses, the layout will change/shift and the current tab won't be the good one anymore 😕
|
||||
// We check if the active panel is loaded as we may try to scroll to it before it is loaded, and it doesn't exist yet
|
||||
if(oActivePanel.length > 0) {
|
||||
this.controller.scrollTo(oActivePanel.offset().top-this.scroll_offset_y);
|
||||
}
|
||||
}
|
||||
},
|
||||
// Create a new scene to be added to the controller
|
||||
|
||||
@@ -1167,6 +1167,7 @@ EOF
|
||||
*/
|
||||
protected function QuoteForPHP($sStr, $bSimpleQuotes = false)
|
||||
{
|
||||
$sStr = $sStr ?? '';
|
||||
if ($bSimpleQuotes)
|
||||
{
|
||||
$sEscaped = str_replace(array('\\', "'"), array('\\\\', "\\'"), $sStr);
|
||||
@@ -3230,10 +3231,11 @@ EOF;
|
||||
|
||||
$aEntriesPHP = array();
|
||||
$oEntries = $oDictionaryNode->GetUniqueElement('entries');
|
||||
/** @var MFElement $oEntry */
|
||||
foreach ($oEntries->getElementsByTagName('entry') as $oEntry)
|
||||
{
|
||||
$sStringCode = $oEntry->getAttribute('id');
|
||||
$sValue = $oEntry->GetText();
|
||||
$sValue = $oEntry->GetText('');
|
||||
$aEntriesPHP[] = "\t'$sStringCode' => ".self::QuoteForPHP(self::FilterDictString($sValue), true).",";
|
||||
}
|
||||
$sEntriesPHP = implode("\n", $aEntriesPHP);
|
||||
@@ -3268,7 +3270,7 @@ EOF;
|
||||
file_put_contents($sLanguagesFile, $sLanguagesFileContent);
|
||||
}
|
||||
|
||||
protected static function FilterDictString($s)
|
||||
protected static function FilterDictString(string $s): string
|
||||
{
|
||||
if (strpos($s, '~') !== false)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user