mirror of
https://github.com/Combodo/iTop.git
synced 2026-02-15 00:14:10 +01:00
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9f50a2714a | ||
|
|
33c5839273 | ||
|
|
9f92bc4b8a | ||
|
|
2af2fd0aea |
@@ -79,7 +79,7 @@ class Html2Text {
|
||||
// replace with spaces
|
||||
|
||||
$html = str_replace(" ", " ", $html);
|
||||
$html = mb_str_replace("\xc2\xa0", " ", $html); // DO NOT USE str_replace since it breaks the "à" character which is \xc3 \xa0 in UTF-8
|
||||
$html = mb_str_replace("\xa0", " ", $html); // DO NOT USE str_replace since it breaks the "à" character which is \xc3 \xa0 in UTF-8
|
||||
|
||||
$html = static::fixNewlines($html);
|
||||
|
||||
|
||||
@@ -202,16 +202,32 @@ EOF
|
||||
// Render the tabs in the page (if any)
|
||||
$this->s_content = $this->m_oTabs->RenderIntoContent($this->s_content, $this);
|
||||
|
||||
// Additional UI widgets to be activated inside the ajax fragment
|
||||
// Important: Testing the content type is not enough because some ajax handlers have not correctly positionned the flag (e.g json response corrupted by the script)
|
||||
if (($this->sContentType == 'text/html') && (preg_match('/class="date-pick"/', $this->s_content) || preg_match('/class="datetime-pick"/', $this->s_content)) )
|
||||
// Additional UI widgets to be activated inside the ajax fragment ??
|
||||
if (($this->sContentType == 'text/html') && (preg_match('/class="date-pick"/', $this->s_content) || preg_match('/class="datetime-pick"/', $this->s_content)) )
|
||||
{
|
||||
$this->add_ready_script(
|
||||
<<<EOF
|
||||
PrepareWidgets();
|
||||
$(".date-pick").datepicker({
|
||||
showOn: 'button',
|
||||
buttonImage: '../images/calendar.png',
|
||||
buttonImageOnly: true,
|
||||
dateFormat: 'yy-mm-dd',
|
||||
constrainInput: false,
|
||||
changeMonth: true,
|
||||
changeYear: true
|
||||
});
|
||||
$(".datetime-pick").datepicker({
|
||||
showOn: 'button',
|
||||
buttonImage: '../images/calendar.png',
|
||||
buttonImageOnly: true,
|
||||
dateFormat: 'yy-mm-dd 00:00:00',
|
||||
constrainInput: false,
|
||||
changeMonth: true,
|
||||
changeYear: true
|
||||
});
|
||||
EOF
|
||||
);
|
||||
}
|
||||
}
|
||||
$s_captured_output = $this->ob_get_clean_safe();
|
||||
if (($this->sContentType == 'text/html') && ($this->sContentDisposition == 'inline'))
|
||||
{
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
require_once(APPROOT.'/application/applicationcontext.class.inc.php');
|
||||
require_once(APPROOT.'/application/cmdbabstract.class.inc.php');
|
||||
require_once(APPROOT.'/application/displayblock.class.inc.php');
|
||||
require_once(APPROOT.'/application/sqlblock.class.inc.php');
|
||||
require_once(APPROOT.'/application/audit.category.class.inc.php');
|
||||
require_once(APPROOT.'/application/audit.rule.class.inc.php');
|
||||
require_once(APPROOT.'/application/query.class.inc.php');
|
||||
|
||||
@@ -688,7 +688,6 @@ EOF
|
||||
else
|
||||
{
|
||||
$val = array('label' => '<span title="'.$oAttDef->GetDescription().'">'.$oAttDef->GetLabel().'</span>', 'value' => "<span id=\"field_{$sInputId}\">".$this->GetAsHTML($sAttCode)."</span>", 'comments' => $sComments, 'infos' => $sInfos);
|
||||
$aFieldsMap[$sAttCode] = $sInputId;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1745,7 +1744,7 @@ EOF
|
||||
$aEventsList[] ='change';
|
||||
|
||||
$sPlaceholderValue = 'placeholder="'.htmlentities(AttributeDateTime::GetFormat()->ToPlaceholder(), ENT_QUOTES, 'UTF-8').'"';
|
||||
$sHTMLValue = "<input title=\"$sHelpText\" class=\"datetime-pick\" type=\"text\" size=\"19\" $sPlaceholderValue name=\"attr_{$sFieldPrefix}{$sAttCode}{$sNameSuffix}\" value=\"".htmlentities($sDisplayValue, ENT_QUOTES, 'UTF-8')."\" id=\"$iId\"/> {$sValidationSpan}{$sReloadSpan}";
|
||||
$sHTMLValue = "<input title=\"$sHelpText\" class=\"datetime-pick\" type=\"text\" size=\"15\" $sPlaceholderValue name=\"attr_{$sFieldPrefix}{$sAttCode}{$sNameSuffix}\" value=\"".htmlentities($sDisplayValue, ENT_QUOTES, 'UTF-8')."\" id=\"$iId\"/> {$sValidationSpan}{$sReloadSpan}";
|
||||
break;
|
||||
|
||||
case 'Duration':
|
||||
@@ -3543,6 +3542,7 @@ EOF
|
||||
// b) or override some of the configuration settings, using the second parameter of ckeditor()
|
||||
$aConfig = array();
|
||||
$sLanguage = strtolower(trim(UserRights::GetUserLanguage()));
|
||||
$aConfig['font_style'] = $sLanguage;
|
||||
$aConfig['language'] = $sLanguage;
|
||||
$aConfig['contentsLanguage'] = $sLanguage;
|
||||
$aConfig['extraPlugins'] = 'disabler';
|
||||
|
||||
@@ -795,17 +795,9 @@ class DisplayBlock
|
||||
$sCsvFile = strtolower($this->m_oFilter->GetClass()).'.csv';
|
||||
$sDownloadLink = utils::GetAbsoluteUrlAppRoot().'webservices/export.php?expression='.urlencode($this->m_oFilter->ToOQL(true)).'&format=csv&filename='.urlencode($sCsvFile);
|
||||
$sLinkToToggle = utils::GetAbsoluteUrlAppRoot().'pages/UI.php?operation=search&'.$oAppContext->GetForLink().'&filter='.urlencode($this->m_oFilter->serialize()).'&format=csv';
|
||||
// Pass the parameters via POST, since expression may be very long
|
||||
$aParamsToPost = array(
|
||||
'expression' => $this->m_oFilter->ToOQL(true),
|
||||
'format' => 'csv',
|
||||
'filename' => $sCsvFile,
|
||||
'charset' => 'UTF-8',
|
||||
);
|
||||
if ($bAdvancedMode)
|
||||
{
|
||||
$sDownloadLink .= '&fields_advanced=1';
|
||||
$aParamsToPost['fields_advance'] = 1;
|
||||
$sChecked = 'CHECKED';
|
||||
}
|
||||
else
|
||||
@@ -813,7 +805,7 @@ class DisplayBlock
|
||||
$sLinkToToggle = $sLinkToToggle.'&advanced=1';
|
||||
$sChecked = '';
|
||||
}
|
||||
$sAjaxLink = utils::GetAbsoluteUrlAppRoot().'webservices/export.php';
|
||||
$sAjaxLink = $sDownloadLink.'&charset=UTF-8'; // Includes &fields_advanced=1 if in advanced mode
|
||||
|
||||
/*
|
||||
$sCSVData = cmdbAbstractObject::GetSetAsCSV($this->m_oSet, array('fields_advanced' => $bAdvancedMode));
|
||||
@@ -864,8 +856,7 @@ class DisplayBlock
|
||||
$sHtml .= "<div id=\"csv_content_loading\"><div style=\"width: 250px; height: 20px; background: url(../setup/orange-progress.gif); border: 1px #999 solid; margin-left:auto; margin-right: auto; text-align: center;\">".Dict::S('UI:Loading')."</div></div><textarea id=\"csv_content\" style=\"display:none;\">\n";
|
||||
//$sHtml .= htmlentities($sCSVData, ENT_QUOTES, 'UTF-8');
|
||||
$sHtml .= "</textarea>\n";
|
||||
$sJsonParams = json_encode($aParamsToPost);
|
||||
$oPage->add_ready_script("$.post('$sAjaxLink', $sJsonParams, function(data) { $('#csv_content').html(data); $('#csv_content_loading').hide(); $('#csv_content').show();} );");
|
||||
$oPage->add_ready_script("$.post('$sAjaxLink', {}, function(data) { $('#csv_content').html(data); $('#csv_content_loading').hide(); $('#csv_content').show();} );");
|
||||
break;
|
||||
|
||||
case 'modify':
|
||||
@@ -1015,12 +1006,6 @@ var chart = c3.generate({
|
||||
},
|
||||
axis: {
|
||||
x: {
|
||||
tick: {
|
||||
culling: {max: 25}, // Maximum 24 labels on x axis (2 years).
|
||||
centered: true,
|
||||
rotate: 90,
|
||||
multiline: false
|
||||
},
|
||||
type: 'category' // this needed to load string x value
|
||||
}
|
||||
},
|
||||
@@ -1072,7 +1057,6 @@ var chart = c3.generate({
|
||||
},
|
||||
legend: {
|
||||
show: true,
|
||||
position: 'right',
|
||||
},
|
||||
tooltip: {
|
||||
format: {
|
||||
|
||||
@@ -881,7 +881,7 @@ class DesignerTextField extends DesignerFormField
|
||||
$this->sValidationPattern = $sValidationPattern;
|
||||
}
|
||||
|
||||
public function SetForbiddenValues($aValues, $sExplain, $bCaseSensitive = true)
|
||||
public function SetForbiddenValues($aValues, $sExplain)
|
||||
{
|
||||
$aForbiddenValues = $aValues;
|
||||
|
||||
@@ -893,7 +893,7 @@ class DesignerTextField extends DesignerFormField
|
||||
|
||||
}
|
||||
|
||||
$this->aForbiddenValues[] = array('values' => $aForbiddenValues, 'message' => $sExplain, 'case_sensitive' => $bCaseSensitive);
|
||||
$this->aForbiddenValues[] = array('values' => $aForbiddenValues, 'message' => $sExplain);
|
||||
}
|
||||
|
||||
public function Render(WebPage $oP, $sFormId, $sRenderMode='dialog')
|
||||
@@ -1367,36 +1367,6 @@ class RunTimeIconSelectionField extends DesignerIconSelectionField
|
||||
}
|
||||
|
||||
static protected function FindIconsOnDisk($sBaseDir, $sDir = '')
|
||||
{
|
||||
$aFiles = null;
|
||||
$sKey = $sBaseDir.'/'.$sDir;
|
||||
$sShortKey = abs(crc32($sKey));
|
||||
$sCacheFile = utils::GetCachePath().'available-icons-'.$sShortKey.'.php';
|
||||
$sCacheClass = 'AvailableIcons_'.$sShortKey;
|
||||
if (file_exists($sCacheFile))
|
||||
{
|
||||
require_once($sCacheFile);
|
||||
if ($sCacheClass::$sKey === $sKey) // crc32 collision detection
|
||||
{
|
||||
$aFiles = $sCacheClass::$aIconFiles;
|
||||
}
|
||||
}
|
||||
if ($aFiles === null)
|
||||
{
|
||||
$aFiles = self::_FindIconsOnDisk($sBaseDir, $sDir);
|
||||
$sAvailableIcons = '<?php'.PHP_EOL;
|
||||
$sAvailableIcons .= '// Generated and used by '.__METHOD__.PHP_EOL;
|
||||
$sAvailableIcons .= 'class '.$sCacheClass.PHP_EOL;
|
||||
$sAvailableIcons .= '{'.PHP_EOL;
|
||||
$sAvailableIcons .= ' static $sKey = '.var_export($sKey, true).';'.PHP_EOL;
|
||||
$sAvailableIcons .= ' static $aIconFiles = '.var_export($aFiles, true).';'.PHP_EOL;
|
||||
$sAvailableIcons .= '}'.PHP_EOL;
|
||||
file_put_contents($sCacheFile, $sAvailableIcons, LOCK_EX);
|
||||
}
|
||||
return $aFiles;
|
||||
}
|
||||
|
||||
static protected function _FindIconsOnDisk($sBaseDir, $sDir = '')
|
||||
{
|
||||
$aResult = array();
|
||||
// Populate automatically the list of icon files
|
||||
@@ -1408,7 +1378,7 @@ class RunTimeIconSelectionField extends DesignerIconSelectionField
|
||||
if (($sFile != '.') && ($sFile != '..') && ($sFile != 'lifecycle') && is_dir($sBaseDir.'/'.$sDir.'/'.$sFile))
|
||||
{
|
||||
$sDirSubPath = ($sDir == '') ? $sFile : $sDir.'/'.$sFile;
|
||||
$aResult = array_merge($aResult, self::_FindIconsOnDisk($sBaseDir, $sDirSubPath));
|
||||
$aResult = array_merge($aResult, self::FindIconsOnDisk($sBaseDir, $sDirSubPath));
|
||||
}
|
||||
if (preg_match("/\.(png|jpg|jpeg|gif)$/i", $sFile, $aMatches)) // png, jp(e)g and gif are considered valid
|
||||
{
|
||||
|
||||
@@ -191,8 +191,7 @@ EOF;
|
||||
$sJSDatePickerOptions = json_encode($aPickerOptions);
|
||||
|
||||
// Time picker additional options
|
||||
$aPickerOptions['showOn'] = '';
|
||||
$aPickerOptions['buttonImage'] = null;
|
||||
|
||||
$aPickerOptions['timeFormat'] = $oTimeFormat->ToDatePicker();
|
||||
$aPickerOptions['controlType'] = 'select';
|
||||
$aPickerOptions['closeText'] = Dict::S('UI:Button:Ok');
|
||||
@@ -209,39 +208,7 @@ EOF;
|
||||
}";
|
||||
$sJSDateTimePickerOptions = substr($sJSDateTimePickerOptions, 0, -1).$aMoreJSOptions;
|
||||
}
|
||||
$this->add_script(
|
||||
<<< EOF
|
||||
function PrepareWidgets()
|
||||
{
|
||||
// note: each action implemented here must be idempotent,
|
||||
// because this helper function might be called several times on a given page
|
||||
|
||||
$(".date-pick").datepicker($sJSDatePickerOptions);
|
||||
|
||||
// Hack for the date and time picker addon issue on Chrome (see #1305)
|
||||
// The workaround is to instantiate the widget on demand
|
||||
// It relies on the same markup, thus reverting to the original implementation should be straightforward
|
||||
$(".datetime-pick:not(.is-widget-ready)").each(function(){
|
||||
var oInput = this;
|
||||
$(oInput).addClass('is-widget-ready');
|
||||
$('<img class="datetime-pick-button" src="../images/calendar.png">')
|
||||
.insertAfter($(this))
|
||||
.on('click', function(){
|
||||
$(oInput)
|
||||
.datetimepicker($sJSDateTimePickerOptions)
|
||||
.datetimepicker('show')
|
||||
.datetimepicker('option', 'onClose', function(dateText,inst){
|
||||
$(oInput).datetimepicker('destroy');
|
||||
})
|
||||
.on('click keypress', function(){
|
||||
$(oInput).datetimepicker('hide');
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
EOF
|
||||
);
|
||||
|
||||
|
||||
$this->m_sInitScript =
|
||||
<<< EOF
|
||||
try
|
||||
@@ -477,7 +444,8 @@ EOF
|
||||
|
||||
// End of Tabs handling
|
||||
|
||||
PrepareWidgets();
|
||||
$(".date-pick").datepicker($sJSDatePickerOptions);
|
||||
$(".datetime-pick").datetimepicker($sJSDateTimePickerOptions);
|
||||
|
||||
// Make sortable, everything that claims to be sortable
|
||||
$('.sortable').sortable( {axis: 'y', cursor: 'move', handle: '.drag_handle', stop: function()
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
/**
|
||||
* Class PortalWebPage
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2016 Combodo SARL
|
||||
* @copyright Copyright (C) 2010-2013 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
@@ -96,88 +96,15 @@ class PortalWebPage extends NiceWebPage
|
||||
$this->add_linked_script("../js/ckeditor/ckeditor.js");
|
||||
$this->add_linked_script("../js/ckeditor/adapters/jquery.js");
|
||||
|
||||
$this->add_linked_script("../js/jquery-ui-timepicker-addon.js");
|
||||
$this->add_linked_script("../js/jquery-ui-timepicker-addon-i18n.min.js");
|
||||
$this->add_linked_stylesheet("../css/jquery-ui-timepicker-addon.css");
|
||||
|
||||
$sJSDisconnectedMessage = json_encode(Dict::S('UI:DisconnectedDlgMessage'));
|
||||
$sJSTitle = json_encode(Dict::S('UI:DisconnectedDlgTitle'));
|
||||
$sJSLoginAgain = json_encode(Dict::S('UI:LoginAgain'));
|
||||
$sJSStayOnThePage = json_encode(Dict::S('UI:StayOnThePage'));
|
||||
$aDaysMin = array(Dict::S('DayOfWeek-Sunday-Min'), Dict::S('DayOfWeek-Monday-Min'), Dict::S('DayOfWeek-Tuesday-Min'), Dict::S('DayOfWeek-Wednesday-Min'),
|
||||
Dict::S('DayOfWeek-Thursday-Min'), Dict::S('DayOfWeek-Friday-Min'), Dict::S('DayOfWeek-Saturday-Min'));
|
||||
$aMonthsShort = array(Dict::S('Month-01-Short'), Dict::S('Month-02-Short'), Dict::S('Month-03-Short'), Dict::S('Month-04-Short'), Dict::S('Month-05-Short'), Dict::S('Month-06-Short'),
|
||||
Dict::S('Month-07-Short'), Dict::S('Month-08-Short'), Dict::S('Month-09-Short'), Dict::S('Month-10-Short'), Dict::S('Month-11-Short'), Dict::S('Month-12-Short'));
|
||||
$sTimeFormat = AttributeDateTime::GetFormat()->ToTimeFormat();
|
||||
$oTimeFormat = new DateTimeFormat($sTimeFormat);
|
||||
$sJSLangShort = json_encode(strtolower(substr(Dict::GetUserLanguage(), 0, 2)));
|
||||
|
||||
// Date picker options
|
||||
$aPickerOptions = array(
|
||||
'showOn' => 'button',
|
||||
'buttonImage' => '../images/calendar.png',
|
||||
'buttonImageOnly' => true,
|
||||
'dateFormat' => AttributeDate::GetFormat()->ToDatePicker(),
|
||||
'constrainInput' => false,
|
||||
'changeMonth' => true,
|
||||
'changeYear' => true,
|
||||
'dayNamesMin' => $aDaysMin,
|
||||
'monthNamesShort' => $aMonthsShort,
|
||||
'firstDay' => (int) Dict::S('Calendar-FirstDayOfWeek'),
|
||||
);
|
||||
$sJSDatePickerOptions = json_encode($aPickerOptions);
|
||||
|
||||
// Time picker additional options
|
||||
$aPickerOptions['showOn'] = '';
|
||||
$aPickerOptions['buttonImage'] = null;
|
||||
$aPickerOptions['timeFormat'] = $oTimeFormat->ToDatePicker();
|
||||
$aPickerOptions['controlType'] = 'select';
|
||||
$aPickerOptions['closeText'] = Dict::S('UI:Button:Ok');
|
||||
$sJSDateTimePickerOptions = json_encode($aPickerOptions);
|
||||
if ($sJSLangShort != '"en"')
|
||||
{
|
||||
// More options that cannot be passed via json_encode since they must be evaluated client-side
|
||||
$aMoreJSOptions = ",
|
||||
'timeText': $.timepicker.regional[$sJSLangShort].timeText,
|
||||
'hourText': $.timepicker.regional[$sJSLangShort].hourText,
|
||||
'minuteText': $.timepicker.regional[$sJSLangShort].minuteText,
|
||||
'secondText': $.timepicker.regional[$sJSLangShort].secondText,
|
||||
'currentText': $.timepicker.regional[$sJSLangShort].currentText
|
||||
}";
|
||||
$sJSDateTimePickerOptions = substr($sJSDateTimePickerOptions, 0, -1).$aMoreJSOptions;
|
||||
}
|
||||
$this->add_script(
|
||||
<<< EOF
|
||||
function PrepareWidgets()
|
||||
{
|
||||
// note: each action implemented here must be idempotent,
|
||||
// because this helper function might be called several times on a given page
|
||||
|
||||
$(".date-pick").datepicker($sJSDatePickerOptions);
|
||||
|
||||
// Hack for the date and time picker addon issue on Chrome (see #1305)
|
||||
// The workaround is to instantiate the widget on demand
|
||||
// It relies on the same markup, thus reverting to the original implementation should be straightforward
|
||||
$(".datetime-pick:not(.is-widget-ready)").each(function(){
|
||||
var oInput = this;
|
||||
$(oInput).addClass('is-widget-ready');
|
||||
$('<img class="datetime-pick-button" src="../images/calendar.png">')
|
||||
.insertAfter($(this))
|
||||
.on('click', function(){
|
||||
$(oInput)
|
||||
.datetimepicker($sJSDateTimePickerOptions)
|
||||
.datetimepicker('show')
|
||||
.datetimepicker('option', 'onClose', function(dateText,inst){
|
||||
$(oInput).datetimepicker('destroy');
|
||||
})
|
||||
.on('click keypress', function(){
|
||||
$(oInput).datetimepicker('hide');
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
EOF
|
||||
);
|
||||
$sJSDaysMin = json_encode(array(Dict::S('DayOfWeek-Sunday-Min'), Dict::S('DayOfWeek-Monday-Min'), Dict::S('DayOfWeek-Tuesday-Min'), Dict::S('DayOfWeek-Wednesday-Min'),
|
||||
Dict::S('DayOfWeek-Thursday-Min'), Dict::S('DayOfWeek-Friday-Min'), Dict::S('DayOfWeek-Saturday-Min')));
|
||||
$sJSMonthsShort = json_encode(array(Dict::S('Month-01-Short'), Dict::S('Month-02-Short'), Dict::S('Month-03-Short'), Dict::S('Month-04-Short'), Dict::S('Month-05-Short'), Dict::S('Month-06-Short'),
|
||||
Dict::S('Month-07-Short'), Dict::S('Month-08-Short'), Dict::S('Month-09-Short'), Dict::S('Month-10-Short'), Dict::S('Month-11-Short'), Dict::S('Month-12-Short')));
|
||||
$iFirstDayOfWeek = (int) Dict::S('Calendar-FirstDayOfWeek');
|
||||
|
||||
$this->add_ready_script(
|
||||
<<<EOF
|
||||
@@ -219,10 +146,34 @@ try
|
||||
}
|
||||
});
|
||||
|
||||
PrepareWidgets();
|
||||
$(".date-pick").datepicker({
|
||||
showOn: 'button',
|
||||
buttonImage: '../images/calendar.png',
|
||||
buttonImageOnly: true,
|
||||
dateFormat: 'yy-mm-dd',
|
||||
constrainInput: false,
|
||||
changeMonth: true,
|
||||
changeYear: true,
|
||||
dayNamesMin: $sJSDaysMin,
|
||||
monthNamesShort: $sJSMonthsShort,
|
||||
firstDay: $iFirstDayOfWeek
|
||||
});
|
||||
|
||||
$(".datetime-pick").datepicker({
|
||||
showOn: 'button',
|
||||
buttonImage: '../images/calendar.png',
|
||||
buttonImageOnly: true,
|
||||
dateFormat: 'yy-mm-dd 00:00:00',
|
||||
constrainInput: false,
|
||||
changeMonth: true,
|
||||
changeYear: true,
|
||||
dayNamesMin: $sJSDaysMin,
|
||||
monthNamesShort: $sJSMonthsShort,
|
||||
firstDay: $iFirstDayOfWeek
|
||||
});
|
||||
|
||||
//$('.resizable').resizable(); // Make resizable everything that claims to be resizable !
|
||||
$('.caselog_header').click( function () { $(this).toggleClass('open').next('.caselog_entry,.caselog_entry_html').toggle(); });
|
||||
$('.caselog_header').click( function () { $(this).toggleClass('open').next('.caselog_entry_html').toggle(); });
|
||||
|
||||
$(document).ajaxSend(function(event, jqxhr, options) {
|
||||
jqxhr.setRequestHeader('X-Combodo-Ajax', 'true');
|
||||
|
||||
531
application/sqlblock.class.inc.php
Normal file
531
application/sqlblock.class.inc.php
Normal file
@@ -0,0 +1,531 @@
|
||||
<?php
|
||||
// Copyright (C) 2010-2012 Combodo SARL
|
||||
//
|
||||
// This file is part of iTop.
|
||||
//
|
||||
// iTop is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// iTop is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
/**
|
||||
* SqlBlock - display tables or charts, given an SQL query - use cautiously!
|
||||
*
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2012 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
|
||||
require_once(APPROOT.'/application/webpage.class.inc.php');
|
||||
require_once(APPROOT.'/application/utils.inc.php');
|
||||
|
||||
require_once(APPROOT.'/pages/php-ofc-library/open-flash-chart.php');
|
||||
|
||||
/**
|
||||
* Helper class to design optimized dashboards, based on an SQL query
|
||||
*
|
||||
*/
|
||||
class SqlBlock
|
||||
{
|
||||
protected $m_sQuery;
|
||||
protected $m_aColumns;
|
||||
protected $m_sTitle;
|
||||
protected $m_sType;
|
||||
protected $m_aParams;
|
||||
|
||||
public function __construct($sQuery, $aColumns, $sTitle, $sType, $aParams = array())
|
||||
{
|
||||
$this->m_sQuery = $sQuery;
|
||||
$this->m_aColumns = $aColumns;
|
||||
$this->m_sTitle = $sTitle;
|
||||
$this->m_sType = $sType;
|
||||
$this->m_aParams = $aParams;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a SqlBlock object from an XML template
|
||||
/*
|
||||
*
|
||||
* <sqlblock>
|
||||
* <sql>SELECT date_format(start_date, '%d') AS Date, count(*) AS Count FROM ticket WHERE DATE_SUB(NOW(), INTERVAL 15 DAY) < start_date AND finalclass = 'UserIssue' GROUP BY date_format(start_date, '%d') AND $CONDITION(param1, ticket.org_id)$</sql>
|
||||
* <type>table</type>
|
||||
* <title>UserRequest:Overview-Title</title>
|
||||
* <parameter>
|
||||
* <name>param1</name>
|
||||
* <type>context</type>
|
||||
* <mapping>org_id</mapping>
|
||||
* </parameter>
|
||||
* <column>
|
||||
* <name>Date</name>
|
||||
* <label>UserRequest:Overview-Date</label>
|
||||
* <drilldown></drilldown>
|
||||
* </column>
|
||||
* <column>
|
||||
* <name>Count</name>
|
||||
* <label>UserRequest:Overview-Count</label>
|
||||
* <drilldown>SELECT UserIssue WHERE date_format(start_date, '%d') = :Date</drilldown>
|
||||
* </column>
|
||||
* </sqlblock>
|
||||
*
|
||||
* Tags
|
||||
* - sql: a (My)SQL query. Do not forget to use html entities (e.g. < for <)
|
||||
* - type: table (default), bars or pie. If bars or pie is selected only the two first columns are taken into account.
|
||||
* - title: optional title, typed in clear or given as a dictionnary entry
|
||||
* - parameter: specifies how to map the context parameters (namely org_id) to a given named parameter in the query.
|
||||
* The expression $CONDITION(<param_name>, <sql_column_name>) will be automatically replaced by:
|
||||
* either the string "1" if there is no restriction on the organisation in iTop
|
||||
* or the string "(<sql_column_name>=<value_of_org_id>)" if there is a limitation to one organizations in iTop
|
||||
* or the string "(<sql_column_name> IN (<values_of_org_id>))" if there is a limitation to a given set of organizations in iTop
|
||||
* - column: specification of a column (not displayed if omitted)
|
||||
* - column / name: name of the column in the SQL query (use aliases)
|
||||
* - column / label: label, typed in clear or given as a dictionnary entry
|
||||
* - column / drilldown: NOT IMPLEMENTED YET - OQL with parameters corresponding to column names (in the query)
|
||||
*
|
||||
* @param $sTemplate string The XML template
|
||||
* @return DisplayBlock The DisplayBlock object, or null if the template is invalid
|
||||
*/
|
||||
public static function FromTemplate($sTemplate)
|
||||
{
|
||||
$oXml = simplexml_load_string('<root>'.$sTemplate.'</root>', 'SimpleXMLElement', LIBXML_NOCDATA);
|
||||
if (false)
|
||||
{
|
||||
// Debug
|
||||
echo "<pre>\n";
|
||||
print_r($oXml);
|
||||
echo "</pre>\n";
|
||||
}
|
||||
|
||||
if (isset($oXml->title))
|
||||
{
|
||||
$sTitle = (string)$oXml->title;
|
||||
}
|
||||
if (isset($oXml->type))
|
||||
{
|
||||
$sType = (string)$oXml->type;
|
||||
}
|
||||
else
|
||||
{
|
||||
$sType = 'table';
|
||||
}
|
||||
if (!isset($oXml->sql))
|
||||
{
|
||||
throw new Exception('Missing tag "sql" in sqlblock');
|
||||
}
|
||||
$sQuery = (string)$oXml->sql;
|
||||
|
||||
$aColumns = array();
|
||||
if (isset($oXml->column))
|
||||
{
|
||||
foreach ($oXml->column AS $oColumnData)
|
||||
{
|
||||
if (!isset($oColumnData->name))
|
||||
{
|
||||
throw new Exception("Missing tag 'name' in sqlblock/column");
|
||||
}
|
||||
$sName = (string) $oColumnData->name;
|
||||
if (strlen($sName) == 0)
|
||||
{
|
||||
throw new Exception("Empty tag 'name' in sqlblock/column");
|
||||
}
|
||||
|
||||
$aColumns[$sName] = array();
|
||||
if (isset($oColumnData->label))
|
||||
{
|
||||
$sLabel = (string)$oColumnData->label;
|
||||
if (strlen($sLabel) > 0)
|
||||
{
|
||||
$aColumns[$sName]['label'] = Dict::S($sLabel);
|
||||
}
|
||||
}
|
||||
if (isset($oColumnData->drilldown))
|
||||
{
|
||||
$sDrillDown = (string)$oColumnData->drilldown;
|
||||
if (strlen($sDrillDown) > 0)
|
||||
{
|
||||
$aColumns[$sName]['drilldown'] = $sDrillDown;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$aParams = array();
|
||||
if (isset($oXml->parameter))
|
||||
{
|
||||
foreach ($oXml->parameter AS $oParamData)
|
||||
{
|
||||
if (!isset($oParamData->name))
|
||||
{
|
||||
throw new Exception("Missing tag 'name' for parameter in sqlblock/column");
|
||||
}
|
||||
$sName = (string) $oParamData->name;
|
||||
if (strlen($sName) == 0)
|
||||
{
|
||||
throw new Exception("Empty tag 'name' for parameter in sqlblock/column");
|
||||
}
|
||||
if (!isset($oParamData->mapping))
|
||||
{
|
||||
throw new Exception("Missing tag 'mapping' for parameter in sqlblock/column");
|
||||
}
|
||||
$sMapping = (string) $oParamData->mapping;
|
||||
if (strlen($sMapping) == 0)
|
||||
{
|
||||
throw new Exception("Empty tag 'mapping' for parameter in sqlblock/column");
|
||||
}
|
||||
|
||||
if (isset($oParamData->type))
|
||||
{
|
||||
$sParamType = $oParamData->type;
|
||||
}
|
||||
else
|
||||
{
|
||||
$sParamType = 'context';
|
||||
}
|
||||
$aParams[$sName] = array('mapping' => $sMapping, 'type' => $sParamType);
|
||||
}
|
||||
}
|
||||
|
||||
return new SqlBlock($sQuery, $aColumns, $sTitle, $sType, $aParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the defined parameters into the SQL query
|
||||
* @return string the SQL query to execute
|
||||
*/
|
||||
public function BuildQuery()
|
||||
{
|
||||
$oAppContext = new ApplicationContext();
|
||||
$sQuery = $this->m_sQuery;
|
||||
$sQuery = str_replace('$DB_PREFIX$', MetaModel::GetConfig()->GetDBSubname(), $sQuery); // put the tables DB prefix (if any)
|
||||
foreach($this->m_aParams as $sName => $aParam)
|
||||
{
|
||||
if ($aParam['type'] == 'context')
|
||||
{
|
||||
$sSearchPattern = '/\$CONDITION\('.$sName.',([^\)]+)\)\$/';
|
||||
$value = $oAppContext->GetCurrentValue($aParam['mapping']);
|
||||
if (empty($value))
|
||||
{
|
||||
$sSQLExpr = '(1)';
|
||||
}
|
||||
else
|
||||
{
|
||||
// Special case for managing the hierarchy of organizations
|
||||
if (($aParam['mapping'] == 'org_id') && ( MetaModel::IsValidClass('Organization')))
|
||||
{
|
||||
$sHierarchicalKeyCode = MetaModel::IsHierarchicalClass('Organization');
|
||||
if ($sHierarchicalKeyCode != false)
|
||||
{
|
||||
// organizations are in hierarchy... gather all the orgs below the given one...
|
||||
$sOQL = "SELECT Organization AS node JOIN Organization AS root ON node.$sHierarchicalKeyCode BELOW root.id WHERE root.id = :value";
|
||||
$oSet = new DBObjectSet(DBObjectSearch::FromOQL($sOQL), array(), array('value' => $value));
|
||||
$aOrgIds = array();
|
||||
while($oOrg = $oSet->Fetch())
|
||||
{
|
||||
$aOrgIds[]= $oOrg->GetKey();
|
||||
}
|
||||
$sSQLExpr = '($1 IN('.implode(',', $aOrgIds).'))';
|
||||
}
|
||||
else
|
||||
{
|
||||
$sSQLExpr = '($1 = '.CMDBSource::Quote($value).')';
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$sSQLExpr = '($1 = '.CMDBSource::Quote($value).')';
|
||||
}
|
||||
}
|
||||
$sQuery = preg_replace($sSearchPattern, $sSQLExpr, $sQuery);
|
||||
}
|
||||
}
|
||||
return $sQuery;
|
||||
}
|
||||
|
||||
public function RenderContent(WebPage $oPage, $aExtraParams = array())
|
||||
{
|
||||
if (empty($aExtraParams['currentId']))
|
||||
{
|
||||
$sId = 'sqlblock_'.$oPage->GetUniqueId(); // Works only if the page is not an Ajax one !
|
||||
}
|
||||
else
|
||||
{
|
||||
$sId = $aExtraParams['currentId'];
|
||||
}
|
||||
// $oPage->add($this->GetRenderContent($oPage, $aExtraParams, $sId));
|
||||
|
||||
$sQuery = $this->BuildQuery();
|
||||
$res = CMDBSource::Query($sQuery);
|
||||
$aQueryCols = CMDBSource::GetColumns($res);
|
||||
|
||||
// Prepare column definitions (check + give default values)
|
||||
//
|
||||
foreach($this->m_aColumns as $sName => $aColumnData)
|
||||
{
|
||||
if (!in_array($sName, $aQueryCols))
|
||||
{
|
||||
throw new Exception("Unknown column name '$sName' in sqlblock column");
|
||||
}
|
||||
if (!isset($aColumnData['label']))
|
||||
{
|
||||
$this->m_aColumns[$sName]['label'] = $sName;
|
||||
}
|
||||
if (isset($aColumnData['drilldown']) && !empty($aColumnData['drilldown']))
|
||||
{
|
||||
// Check if the OQL is valid
|
||||
try
|
||||
{
|
||||
$this->m_aColumns[$sName]['filter'] = DBObjectSearch::FromOQL($aColumnData['drilldown']);
|
||||
}
|
||||
catch(OQLException $e)
|
||||
{
|
||||
unset($aColumnData['drilldown']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (strlen($this->m_sTitle) > 0)
|
||||
{
|
||||
$oPage->add("<h2>".Dict::S($this->m_sTitle)."</h2>\n");
|
||||
}
|
||||
|
||||
switch ($this->m_sType)
|
||||
{
|
||||
case 'bars':
|
||||
case 'pie':
|
||||
$aColNames = array_keys($this->m_aColumns);
|
||||
$sXColName = $aColNames[0];
|
||||
$sYColName = $aColNames[1];
|
||||
$aData = array();
|
||||
$aRows = array();
|
||||
while($aRow = CMDBSource::FetchArray($res))
|
||||
{
|
||||
$aData[$aRow[$sXColName]] = $aRow[$sYColName];
|
||||
$aRows[$aRow[$sXColName]] = $aRow;
|
||||
}
|
||||
$this->RenderChart($oPage, $sId, $aData, $this->m_aColumns[$sYColName]['drilldown'], $aRows);
|
||||
break;
|
||||
|
||||
default:
|
||||
case 'table':
|
||||
$oAppContext = new ApplicationContext();
|
||||
$sContext = $oAppContext->GetForLink();
|
||||
if (!empty($sContext))
|
||||
{
|
||||
$sContext = '&'.$sContext;
|
||||
}
|
||||
$aDisplayConfig = array();
|
||||
foreach($this->m_aColumns as $sName => $aColumnData)
|
||||
{
|
||||
$aDisplayConfig[$sName] = array('label' => $aColumnData['label'], 'description' => '');
|
||||
}
|
||||
|
||||
$aDisplayData = array();
|
||||
while($aRow = CMDBSource::FetchArray($res))
|
||||
{
|
||||
$aSQLColNames = array_keys($aRow);
|
||||
$aDisplayRow = array();
|
||||
foreach($this->m_aColumns as $sName => $aColumnData)
|
||||
{
|
||||
if (isset($aColumnData['filter']))
|
||||
{
|
||||
$sFilter = $aColumnData['drilldown'];
|
||||
$sClass = $aColumnData['filter']->GetClass();
|
||||
$sFilter = str_replace('SELECT '.$sClass, '', $sFilter);
|
||||
foreach($aSQLColNames as $sColName)
|
||||
{
|
||||
$sFilter = str_replace(':'.$sColName, "'".addslashes( $aRow[$sColName] )."'", $sFilter);
|
||||
}
|
||||
$sURL = utils::GetAbsoluteUrlAppRoot().'pages/UI.php?operation=search_oql&search_form=0&oql_class='.$sClass.'&oql_clause='.urlencode($sFilter).'&format=html'.$sContext;
|
||||
$aDisplayRow[$sName] = '<a href="'.$sURL.'">'.$aRow[$sName]."</a>";
|
||||
}
|
||||
else
|
||||
{
|
||||
$aDisplayRow[$sName] = $aRow[$sName];
|
||||
}
|
||||
}
|
||||
$aDisplayData[] = $aDisplayRow;
|
||||
}
|
||||
$oPage->table($aDisplayConfig, $aDisplayData);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public function GetRenderContent(WebPage $oPage, $aExtraParams = array(), $sId)
|
||||
{
|
||||
$sHtml = '';
|
||||
return $sHtml;
|
||||
}
|
||||
|
||||
protected function RenderChart($oPage, $sId, $aValues, $sDrillDown = '', $aRows = array())
|
||||
{
|
||||
// 1- Compute Open Flash Chart data
|
||||
//
|
||||
$aValueKeys = array();
|
||||
$index = 0;
|
||||
if ((count($aValues) > 0) && ($sDrillDown != ''))
|
||||
{
|
||||
$oFilter = DBObjectSearch::FromOQL($sDrillDown);
|
||||
$sClass = $oFilter->GetClass();
|
||||
$sOQLClause = str_replace('SELECT '.$sClass, '', $sDrillDown);
|
||||
$aSQLColNames = array_keys(current($aRows)); // Read the list of columns from the current (i.e. first) element of the array
|
||||
$oAppContext = new ApplicationContext();
|
||||
$sURL = utils::GetAbsoluteUrlAppRoot().'pages/UI.php?operation=search_oql&search_form=0&oql_class='.$sClass.'&format=html&'.$oAppContext->GetForLink().'&oql_clause=';
|
||||
}
|
||||
$aURLs = array();
|
||||
foreach($aValues as $key => $value)
|
||||
{
|
||||
// Make sure that values are integers (so that max() will work....)
|
||||
// and build an array of STRING with the keys (numeric keys are transformed into string by PHP :-(
|
||||
$aValues[$key] = (int)$value;
|
||||
$aValueKeys[] = (string)$key;
|
||||
|
||||
// Build the custom query for the 'drill down' on each element
|
||||
if ($sDrillDown != '')
|
||||
{
|
||||
$sFilter = $sOQLClause;
|
||||
foreach($aSQLColNames as $sColName)
|
||||
{
|
||||
$sFilter = str_replace(':'.$sColName, "'".addslashes( $aRows[$key][$sColName] )."'", $sFilter);
|
||||
$aURLs[$index] = $sURL.urlencode($sFilter);
|
||||
}
|
||||
}
|
||||
$index++;
|
||||
}
|
||||
|
||||
$oChart = new open_flash_chart();
|
||||
|
||||
if ($this->m_sType == 'bars')
|
||||
{
|
||||
$oChartElement = new bar_glass();
|
||||
|
||||
if (count($aValues) > 0)
|
||||
{
|
||||
$maxValue = max($aValues);
|
||||
}
|
||||
else
|
||||
{
|
||||
$maxValue = 1;
|
||||
}
|
||||
$oYAxis = new y_axis();
|
||||
$aMagicValues = array(1,2,5,10);
|
||||
$iMultiplier = 1;
|
||||
$index = 0;
|
||||
$iTop = $aMagicValues[$index % count($aMagicValues)]*$iMultiplier;
|
||||
while($maxValue > $iTop)
|
||||
{
|
||||
$index++;
|
||||
$iTop = $aMagicValues[$index % count($aMagicValues)]*$iMultiplier;
|
||||
if (($index % count($aMagicValues)) == 0)
|
||||
{
|
||||
$iMultiplier = $iMultiplier * 10;
|
||||
}
|
||||
}
|
||||
//echo "oYAxis->set_range(0, $iTop, $iMultiplier);\n";
|
||||
$oYAxis->set_range(0, $iTop, $iMultiplier);
|
||||
$oChart->set_y_axis( $oYAxis );
|
||||
$aBarValues = array();
|
||||
foreach($aValues as $iValue)
|
||||
{
|
||||
$oBarValue = new bar_value($iValue);
|
||||
$oBarValue->on_click("ofc_drilldown_{$sId}");
|
||||
$aBarValues[] = $oBarValue;
|
||||
}
|
||||
$oChartElement->set_values($aBarValues);
|
||||
//$oChartElement->set_values(array_values($aValues));
|
||||
$oXAxis = new x_axis();
|
||||
$oXLabels = new x_axis_labels();
|
||||
// set them vertical
|
||||
$oXLabels->set_vertical();
|
||||
// set the label text
|
||||
$oXLabels->set_labels($aValueKeys);
|
||||
// Add the X Axis Labels to the X Axis
|
||||
$oXAxis->set_labels( $oXLabels );
|
||||
$oChart->set_x_axis( $oXAxis );
|
||||
}
|
||||
else
|
||||
{
|
||||
$oChartElement = new pie();
|
||||
$oChartElement->set_start_angle( 35 );
|
||||
$oChartElement->set_animate( true );
|
||||
$oChartElement->set_tooltip( '#label# - #val# (#percent#)' );
|
||||
$oChartElement->set_colours( array('#FF8A00', '#909980', '#2C2B33', '#CCC08D', '#596664') );
|
||||
|
||||
$aData = array();
|
||||
foreach($aValues as $sValue => $iValue)
|
||||
{
|
||||
$oPieValue = new pie_value($iValue, $sValue); //@@ BUG: not passed via ajax !!!
|
||||
$oPieValue->on_click("ofc_drilldown_{$sId}");
|
||||
$aData[] = $oPieValue;
|
||||
}
|
||||
|
||||
$oChartElement->set_values( $aData );
|
||||
$oChart->x_axis = null;
|
||||
}
|
||||
|
||||
// Title given in HTML
|
||||
//$oTitle = new title($this->m_sTitle);
|
||||
//$oChart->set_title($oTitle);
|
||||
$oChart->set_bg_colour('#FFFFFF');
|
||||
$oChart->add_element( $oChartElement );
|
||||
|
||||
$sData = $oChart->toPrettyString();
|
||||
$sData = json_encode($sData);
|
||||
|
||||
// 2- Declare the Javascript function that will render the chart data\
|
||||
//
|
||||
$oPage->add_script(
|
||||
<<< EOF
|
||||
function ofc_get_data_{$sId}()
|
||||
{
|
||||
return $sData;
|
||||
}
|
||||
EOF
|
||||
);
|
||||
|
||||
if (count($aURLs) > 0)
|
||||
{
|
||||
$sURLList = '';
|
||||
foreach($aURLs as $index => $sURL)
|
||||
{
|
||||
$sURLList .= "\taURLs[$index] = '".addslashes($sURL)."';\n";
|
||||
}
|
||||
|
||||
$oPage->add_script(
|
||||
<<< EOF
|
||||
function ofc_drilldown_{$sId}(index)
|
||||
{
|
||||
var aURLs = new Array();
|
||||
{$sURLList}
|
||||
var sURL = aURLs[index];
|
||||
|
||||
window.location.href = sURL; // Navigate !
|
||||
}
|
||||
EOF
|
||||
);
|
||||
}
|
||||
|
||||
// 3- Insert the Open Flash chart
|
||||
//
|
||||
$oPage->add("<div id=\"$sId\"><div>\n");
|
||||
$oPage->add_ready_script(
|
||||
<<<EOF
|
||||
swfobject.embedSWF( "../images/open-flash-chart.swf",
|
||||
"{$sId}",
|
||||
"100%", "300","9.0.0",
|
||||
"expressInstall.swf",
|
||||
{"get-data":"ofc_get_data_{$sId}", "id":"{$sId}"},
|
||||
{'wmode': 'transparent'}
|
||||
);
|
||||
EOF
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -1,5 +1,5 @@
|
||||
<?php
|
||||
// Copyright (C) 2010-2016 Combodo SARL
|
||||
// Copyright (C) 2010-2015 Combodo SARL
|
||||
//
|
||||
// This file is part of iTop.
|
||||
//
|
||||
@@ -20,8 +20,9 @@
|
||||
* Class UIHTMLEditorWidget
|
||||
* UI wdiget for displaying and editing one-way encrypted passwords
|
||||
*
|
||||
* @author Phil Eddies
|
||||
* @author Romain Quetiez
|
||||
* @copyright Copyright (C) 2010-2016 Combodo SARL
|
||||
* @copyright Copyright (C) 2010-2015 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
@@ -98,26 +99,9 @@ class UIHTMLEditorWidget
|
||||
|
||||
// Could also be bound to 'instanceReady.ckeditor'
|
||||
$oPage->add_ready_script("$('#$iId').bind('validate', function(evt, sFormId) { return ValidateCKEditField('$iId', '', {$this->m_sMandatory}, sFormId, '') } );\n");
|
||||
$oPage->add_ready_script(
|
||||
<<<EOF
|
||||
$('#$iId').bind('update', function(evt){
|
||||
BlockField('cke_$iId', $('#$iId').attr('disabled'));
|
||||
//Delayed execution - ckeditor must be properly initialized before setting readonly
|
||||
var retryCount = 0;
|
||||
var oMe = $('#$iId');
|
||||
var delayedSetReadOnly = function () {
|
||||
if (oMe.data('ckeditorInstance').editable() == undefined && retryCount++ < 10) {
|
||||
setTimeout(delayedSetReadOnly, retryCount * 100); //Wait a while longer each iteration
|
||||
}
|
||||
else
|
||||
{
|
||||
oMe.data('ckeditorInstance').setReadOnly(oMe.prop('disabled'));
|
||||
}
|
||||
};
|
||||
setTimeout(delayedSetReadOnly, 50);
|
||||
});
|
||||
EOF
|
||||
);
|
||||
$oPage->add_ready_script("$('#$iId').bind('update', function() { BlockField('cke_$iId', $('#$iId').attr('disabled')); $(this).data('ckeditorInstance').setReadOnly($(this).prop('disabled')); } );\n");
|
||||
|
||||
return $sHtmlValue;
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -163,10 +163,38 @@ class UILinksWidget
|
||||
$aFieldsMap[$sFieldCode] = $sSafeId;
|
||||
}
|
||||
$sState = '';
|
||||
$sJSDaysMin = json_encode(array(Dict::S('DayOfWeek-Sunday-Min'), Dict::S('DayOfWeek-Monday-Min'), Dict::S('DayOfWeek-Tuesday-Min'), Dict::S('DayOfWeek-Wednesday-Min'),
|
||||
Dict::S('DayOfWeek-Thursday-Min'), Dict::S('DayOfWeek-Friday-Min'), Dict::S('DayOfWeek-Saturday-Min')));
|
||||
$sJSMonthsShort = json_encode(array(Dict::S('Month-01-Short'), Dict::S('Month-02-Short'), Dict::S('Month-03-Short'), Dict::S('Month-04-Short'), Dict::S('Month-05-Short'), Dict::S('Month-06-Short'),
|
||||
Dict::S('Month-07-Short'), Dict::S('Month-08-Short'), Dict::S('Month-09-Short'), Dict::S('Month-10-Short'), Dict::S('Month-11-Short'), Dict::S('Month-12-Short')));
|
||||
$iFirstDayOfWeek = (int) Dict::S('Calendar-FirstDayOfWeek');
|
||||
|
||||
$oP->add_script(
|
||||
<<<EOF
|
||||
PrepareWidgets();
|
||||
$(".date-pick").datepicker({
|
||||
showOn: 'button',
|
||||
buttonImage: '../images/calendar.png',
|
||||
buttonImageOnly: true,
|
||||
dateFormat: 'yy-mm-dd',
|
||||
constrainInput: false,
|
||||
changeMonth: true,
|
||||
changeYear: true,
|
||||
dayNamesMin: $sJSDaysMin,
|
||||
monthNamesShort: $sJSMonthsShort,
|
||||
firstDay: $iFirstDayOfWeek
|
||||
});
|
||||
$(".datetime-pick").datepicker({
|
||||
showOn: 'button',
|
||||
buttonImage: '../images/calendar.png',
|
||||
buttonImageOnly: true,
|
||||
dateFormat: 'yy-mm-dd 00:00:00',
|
||||
constrainInput: false,
|
||||
changeMonth: true,
|
||||
changeYear: true,
|
||||
dayNamesMin: $sJSDaysMin,
|
||||
monthNamesShort: $sJSMonthsShort,
|
||||
firstDay: $iFirstDayOfWeek
|
||||
});
|
||||
EOF
|
||||
);
|
||||
}
|
||||
|
||||
@@ -437,45 +437,6 @@ class utils
|
||||
return $iReturn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a value into a more friendly format (KB, MB, GB, TB) instead a juste a Bytes amount.
|
||||
*
|
||||
* @param type $value
|
||||
* @return string
|
||||
*/
|
||||
public static function BytesToFriendlyFormat($value)
|
||||
{
|
||||
$sReturn = '';
|
||||
// Kilobytes
|
||||
if ($value >= 1024)
|
||||
{
|
||||
$sReturn = 'K';
|
||||
$value = $value / 1024;
|
||||
}
|
||||
// Megabytes
|
||||
if ($value >= 1024)
|
||||
{
|
||||
$sReturn = 'M';
|
||||
$value = $value / 1024;
|
||||
}
|
||||
// Gigabytes
|
||||
if ($value >= 1024)
|
||||
{
|
||||
$sReturn = 'G';
|
||||
$value = $value / 1024;
|
||||
}
|
||||
// Terabytes
|
||||
if ($value >= 1024)
|
||||
{
|
||||
$sReturn = 'T';
|
||||
$value = $value / 1024;
|
||||
}
|
||||
|
||||
$value = round($value, 1);
|
||||
|
||||
return $value . '' . $sReturn . 'B';
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to convert a string to a date, given a format specification. It replaces strtotime which does not allow for specifying a date in a french format (for instance)
|
||||
* Example: StringToTime('01/05/11 12:03:45', '%d/%m/%y %H:%i:%s')
|
||||
@@ -887,11 +848,7 @@ class utils
|
||||
// Bulk export actions
|
||||
$aResult[] = new JSPopupMenuItem('UI:Menu:CSVExport', Dict::S('UI:Menu:CSVExport'), "ExportListDlg('$sOQL', '$sDataTableId', 'csv', ".json_encode(Dict::S('UI:Menu:CSVExport')).")");
|
||||
$aResult[] = new JSPopupMenuItem('UI:Menu:ExportXLSX', Dict::S('ExcelExporter:ExportMenu'), "ExportListDlg('$sOQL', '$sDataTableId', 'xlsx', ".json_encode(Dict::S('ExcelExporter:ExportMenu')).")");
|
||||
if (extension_loaded('gd'))
|
||||
{
|
||||
// PDF export requires GD
|
||||
$aResult[] = new JSPopupMenuItem('UI:Menu:ExportPDF', Dict::S('UI:Menu:ExportPDF'), "ExportListDlg('$sOQL', '$sDataTableId', 'pdf', ".json_encode(Dict::S('UI:Menu:ExportPDF')).")");
|
||||
}
|
||||
$aResult[] = new JSPopupMenuItem('UI:Menu:ExportPDF', Dict::S('UI:Menu:ExportPDF'), "ExportListDlg('$sOQL', '$sDataTableId', 'pdf', ".json_encode(Dict::S('UI:Menu:ExportPDF')).")");
|
||||
}
|
||||
$aResult[] = new JSPopupMenuItem('UI:Menu:AddToDashboard', Dict::S('UI:Menu:AddToDashboard'), "DashletCreationDlg('$sOQL')");
|
||||
$aResult[] = new JSPopupMenuItem('UI:Menu:ShortcutList', Dict::S('UI:Menu:ShortcutList'), "ShortcutListDlg('$sOQL', '$sDataTableId', '$sContext')");
|
||||
@@ -1318,21 +1275,10 @@ class utils
|
||||
*/
|
||||
public static function ResizeImageToFit(ormDocument $oImage, $iWidth, $iHeight, $iMaxImageWidth, $iMaxImageHeight)
|
||||
{
|
||||
// If image size smaller than maximums, we do nothing
|
||||
if (($iWidth <= $iMaxImageWidth) && ($iHeight <= $iMaxImageHeight))
|
||||
{
|
||||
return $oImage;
|
||||
}
|
||||
|
||||
|
||||
// If gd extension is not loaded, we put a warning in the log and return the image as is
|
||||
if (extension_loaded('gd') === false)
|
||||
{
|
||||
IssueLog::Warning('Image could not be resized as the "gd" extension does not seem to be loaded. It will remain as ' . $iWidth . 'x' . $iHeight . ' instead of ' . $iMaxImageWidth . 'x' . $iMaxImageHeight);
|
||||
return $oImage;
|
||||
}
|
||||
|
||||
|
||||
switch($oImage->GetMimeType())
|
||||
{
|
||||
case 'image/gif':
|
||||
|
||||
@@ -138,22 +138,6 @@ class WizardHelper
|
||||
$oObj->Set($sAttCode, $value);
|
||||
}
|
||||
}
|
||||
else if ($oAttDef instanceof AttributeDateTime) // AttributeDate is derived from AttributeDateTime
|
||||
{
|
||||
if ($value != null)
|
||||
{
|
||||
$oDate = $oAttDef->GetFormat()->Parse($value);
|
||||
if ($oDate instanceof DateTime)
|
||||
{
|
||||
$value = $oDate->format($oAttDef->GetInternalFormat());
|
||||
}
|
||||
else
|
||||
{
|
||||
$value = null;
|
||||
}
|
||||
}
|
||||
$oObj->Set($sAttCode, $value);
|
||||
}
|
||||
else
|
||||
{
|
||||
$oObj->Set($sAttCode, $value);
|
||||
|
||||
@@ -1,69 +0,0 @@
|
||||
<?php
|
||||
// Copyright (C) 2016 Combodo SARL
|
||||
//
|
||||
// This file is part of iTop.
|
||||
//
|
||||
// iTop is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// iTop is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
// Emulate the API of APC, over APCU
|
||||
// Note: for PHP < 7, this compatibility used to be provided by APCU itself (if compiled with some options)
|
||||
// for PHP 7+, it can be provided by the mean of apcu_bc, which is not so simple to install
|
||||
// The current emulation aims at skipping this complexity
|
||||
if (!function_exists('apc_store') && function_exists('apcu_store'))
|
||||
{
|
||||
function apc_add($key, $var, $ttl = 0)
|
||||
{
|
||||
return apcu_add($key, $var, $ttl);
|
||||
}
|
||||
function apc_cache_info($cache_type = '', $limited = false)
|
||||
{
|
||||
return apcu_cache_info($limited);
|
||||
}
|
||||
function apc_cas($key, $old, $new)
|
||||
{
|
||||
return apcu_cas($key, $old, $new);
|
||||
}
|
||||
function apc_clear_cache($cache_type = '')
|
||||
{
|
||||
return apcu_clear_cache();
|
||||
}
|
||||
function apc_dec($key, $step = 1, &$success = null)
|
||||
{
|
||||
apcu_dec($key, $step, $success);
|
||||
}
|
||||
function apc_delete($key)
|
||||
{
|
||||
return apcu_delete($key);
|
||||
}
|
||||
function apc_exists($keys)
|
||||
{
|
||||
return apcu_exists($keys);
|
||||
}
|
||||
function apc_fetch($key)
|
||||
{
|
||||
return apcu_fetch($key);
|
||||
}
|
||||
function apc_inc($key, $step = 1, &$success = null)
|
||||
{
|
||||
apcu_inc($key, $step, $success);
|
||||
}
|
||||
function apc_sma_info($limited = false)
|
||||
{
|
||||
return apcu_sma_info($limited);
|
||||
}
|
||||
function apc_store($key, $var, $ttl = 0)
|
||||
{
|
||||
return apcu_store($key, $var, $ttl);
|
||||
}
|
||||
}
|
||||
@@ -2116,41 +2116,6 @@ class AttributeFinalClass extends AttributeString
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An enum can be localized
|
||||
*/
|
||||
public function MakeValueFromString($sProposedValue, $bLocalizedValue = false, $sSepItem = null, $sSepAttribute = null, $sSepValue = null, $sAttributeQualifier = null)
|
||||
{
|
||||
if ($bLocalizedValue)
|
||||
{
|
||||
// Lookup for the value matching the input
|
||||
//
|
||||
$sFoundValue = null;
|
||||
$aRawValues = self::GetAllowedValues();
|
||||
if (!is_null($aRawValues))
|
||||
{
|
||||
foreach ($aRawValues as $sKey => $sValue)
|
||||
{
|
||||
if ($sProposedValue == $sValue)
|
||||
{
|
||||
$sFoundValue = $sKey;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (is_null($sFoundValue))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return $this->MakeRealValue($sFoundValue, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
return parent::MakeValueFromString($sProposedValue, $bLocalizedValue, $sSepItem, $sSepAttribute, $sSepValue, $sAttributeQualifier);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Because this is sometimes used to get a localized/string version of an attribute...
|
||||
public function GetEditValue($sValue, $oHostObj = null)
|
||||
{
|
||||
@@ -3811,17 +3776,6 @@ class AttributeDateTime extends AttributeDBField
|
||||
}
|
||||
if (!is_numeric($proposedValue))
|
||||
{
|
||||
// Check the format
|
||||
try
|
||||
{
|
||||
$oFormat = new DateTimeFormat($this->GetInternalFormat());
|
||||
$oTrash = $oFormat->Parse($proposedValue);
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
throw new Exception('Wrong format for date attribute '.$this->GetCode().', expecting "'.$this->GetInternalFormat().'" and got "'.$proposedValue.'"');
|
||||
}
|
||||
|
||||
return $proposedValue;
|
||||
}
|
||||
|
||||
@@ -4049,7 +4003,7 @@ class AttributeDuration extends AttributeInteger
|
||||
|
||||
static public function GetFormFieldClass()
|
||||
{
|
||||
return '\\Combodo\\iTop\\Form\\Field\\DurationField';
|
||||
return '\\Combodo\\iTop\\Form\\Field\\LabelField';
|
||||
}
|
||||
|
||||
public function MakeFormField(DBObject $oObject, $oFormField = null)
|
||||
@@ -4063,7 +4017,7 @@ class AttributeDuration extends AttributeInteger
|
||||
|
||||
// Note : As of today, this attribute is -by nature- only supported in readonly mode, not edition
|
||||
$sAttCode = $this->GetCode();
|
||||
$oFormField->SetCurrentValue($oObject->Get($sAttCode));
|
||||
$oFormField->SetCurrentValue(html_entity_decode($oObject->GetAsHTML($sAttCode), ENT_QUOTES, 'UTF-8'));
|
||||
$oFormField->SetReadOnly(true);
|
||||
|
||||
return $oFormField;
|
||||
@@ -4376,13 +4330,9 @@ class AttributeExternalKey extends AttributeDBFieldVoid
|
||||
$oTmpField = $oFormField;
|
||||
$oFormField->SetOnFinalizeCallback(function() use ($oTmpField, $oTmpAttDef, $oObject)
|
||||
{
|
||||
// We set search object only if it has not already been set (overrided)
|
||||
if ($oTmpField->GetSearch() === null)
|
||||
{
|
||||
$oSearch = DBSearch::FromOQL($oTmpAttDef->GetValuesDef()->GetFilterExpression());
|
||||
$oSearch->SetInternalParams(array('this' => $oObject));
|
||||
$oTmpField->SetSearch($oSearch);
|
||||
}
|
||||
$oSearch = DBSearch::FromOQL($oTmpAttDef->GetValuesDef()->GetFilterExpression());
|
||||
$oSearch->SetInternalParams(array('this' => $oObject));
|
||||
$oTmpField->SetSearch($oSearch);
|
||||
});
|
||||
}
|
||||
else
|
||||
@@ -5113,33 +5063,6 @@ class AttributeBlob extends AttributeDefinition
|
||||
}
|
||||
return $sFingerprint;
|
||||
}
|
||||
|
||||
static public function GetFormFieldClass()
|
||||
{
|
||||
return '\\Combodo\\iTop\\Form\\Field\\BlobField';
|
||||
}
|
||||
|
||||
public function MakeFormField(DBObject $oObject, $oFormField = null)
|
||||
{
|
||||
if ($oFormField === null)
|
||||
{
|
||||
$sFormFieldClass = static::GetFormFieldClass();
|
||||
$oFormField = new $sFormFieldClass($this->GetCode());
|
||||
}
|
||||
|
||||
// Note: As of today we want this field to always be read-only
|
||||
$oFormField->SetReadOnly(true);
|
||||
|
||||
// Generating urls
|
||||
$value = $oObject->Get($this->GetCode());
|
||||
$oFormField->SetDownloadUrl($value->GetDownloadURL(get_class($oObject), $oObject->GetKey(), $this->GetCode()));
|
||||
$oFormField->SetDisplayUrl($value->GetDisplayURL(get_class($oObject), $oObject->GetKey(), $this->GetCode()));
|
||||
|
||||
parent::MakeFormField($oObject, $oFormField);
|
||||
|
||||
return $oFormField;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -22,7 +22,6 @@ MetaModel::IncludeModule('application/user.preferences.class.inc.php');
|
||||
MetaModel::IncludeModule('application/user.dashboard.class.inc.php');
|
||||
MetaModel::IncludeModule('application/audit.rule.class.inc.php');
|
||||
MetaModel::IncludeModule('application/query.class.inc.php');
|
||||
MetaModel::IncludeModule('setup/moduleinstallation.class.inc.php');
|
||||
|
||||
MetaModel::IncludeModule('core/event.class.inc.php');
|
||||
MetaModel::IncludeModule('core/action.class.inc.php');
|
||||
|
||||
@@ -828,8 +828,8 @@ class BulkChange
|
||||
$sFormat = $sDateFormat;
|
||||
}
|
||||
$oFormat = new DateTimeFormat($sFormat);
|
||||
$sRegExp = $oFormat->ToRegExpr('/');
|
||||
if (!preg_match($sRegExp, $this->m_aData[$iRow][$iCol]))
|
||||
$sRegExp = $oFormat->ToRegExpr();
|
||||
if (!preg_match('/'.$sRegExp.'/', $this->m_aData[$iRow][$iCol]))
|
||||
{
|
||||
$aResult[$iRow]["__STATUS__"]= new RowStatus_Issue(Dict::S('UI:CSVReport-Row-Issue-DateFormat'));
|
||||
}
|
||||
|
||||
@@ -412,11 +412,7 @@ abstract class BulkExport
|
||||
// The built-in exports
|
||||
require_once(APPROOT.'core/tabularbulkexport.class.inc.php');
|
||||
require_once(APPROOT.'core/htmlbulkexport.class.inc.php');
|
||||
if (extension_loaded('gd'))
|
||||
{
|
||||
// PDF export - via TCPDF - requires GD
|
||||
require_once(APPROOT.'core/pdfbulkexport.class.inc.php');
|
||||
}
|
||||
require_once(APPROOT.'core/pdfbulkexport.class.inc.php');
|
||||
require_once(APPROOT.'core/csvbulkexport.class.inc.php');
|
||||
require_once(APPROOT.'core/excelbulkexport.class.inc.php');
|
||||
require_once(APPROOT.'core/spreadsheetbulkexport.class.inc.php');
|
||||
|
||||
@@ -246,7 +246,7 @@ class Config
|
||||
),
|
||||
'access_mode' => array(
|
||||
'type' => 'integer',
|
||||
'description' => 'Access mode: ACCESS_READONLY = 0, ACCESS_ADMIN_WRITE = 2, ACCESS_FULL = 3',
|
||||
'description' => 'Combination of flags (ACCESS_USER_WRITE | ACCESS_ADMIN_WRITE, or ACCESS_FULL)',
|
||||
'default' => ACCESS_FULL,
|
||||
'value' => ACCESS_FULL,
|
||||
'source_of_value' => '',
|
||||
|
||||
@@ -413,16 +413,10 @@ EOF
|
||||
/**
|
||||
* Get the regular expression to (approximately) validate a date/time for the current format
|
||||
* The validation does not take into account the number of days in a month (i.e. June 31st will pass, as well as Feb 30th!)
|
||||
* @param string $sDelimiter Surround the regexp (and escape) if needed
|
||||
* @return string The regular expression in PCRE syntax
|
||||
*/
|
||||
public function ToRegExpr($sDelimiter = null)
|
||||
public function ToRegExpr()
|
||||
{
|
||||
$sRet = '^'.$this->Transform('regexpr', "\\%s", false /* escape all */, '.?*$^()[]:').'$';
|
||||
if ($sDelimiter !== null)
|
||||
{
|
||||
$sRet = $sDelimiter.str_replace($sDelimiter, '\\'.$sDelimiter, $sRet).$sDelimiter;
|
||||
}
|
||||
return $sRet;
|
||||
return '^'.$this->Transform('regexpr', "\\%s", false /* escape all */, '.?*$^()[]/:').'$';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -192,14 +192,10 @@ abstract class DBObject implements iDisplay
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $bAllowAllData DEPRECATED: the reload must never fail!
|
||||
* @throws CoreException
|
||||
*/
|
||||
public function Reload($bAllowAllData = false)
|
||||
{
|
||||
assert($this->m_bIsInDB);
|
||||
$aRow = MetaModel::MakeSingleRow(get_class($this), $this->m_iKey, false /* must be found */, true /* AllowAllData */);
|
||||
$aRow = MetaModel::MakeSingleRow(get_class($this), $this->m_iKey, false /* must be found */, $bAllowAllData/* in the future $this->m_bAllowAllData ??*/);
|
||||
if (empty($aRow))
|
||||
{
|
||||
throw new CoreException("Failed to reload object of class '".get_class($this)."', id = ".$this->m_iKey);
|
||||
@@ -1935,7 +1931,6 @@ abstract class DBObject implements iDisplay
|
||||
{
|
||||
$oFilter = new DBObjectSearch(get_class($this));
|
||||
$oFilter->AddCondition('id', $this->m_iKey, '=');
|
||||
$oFilter->AllowAllData();
|
||||
|
||||
$sSQL = $oFilter->MakeUpdateQuery($aDBChanges);
|
||||
CMDBSource::Query($sSQL);
|
||||
|
||||
@@ -23,9 +23,7 @@
|
||||
* @copyright Copyright (C) 2010-2016 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
// Dev hack for disabling the some query build optimizations (Folding/Merging)
|
||||
define('ENABLE_OPT', true);
|
||||
|
||||
|
||||
class DBObjectSearch extends DBSearch
|
||||
{
|
||||
@@ -37,11 +35,6 @@ class DBObjectSearch extends DBSearch
|
||||
private $m_aPointingTo;
|
||||
private $m_aReferencedBy;
|
||||
|
||||
// By default, some information may be hidden to the current user
|
||||
// But it may happen that we need to disable that feature
|
||||
protected $m_bAllowAllData = false;
|
||||
protected $m_bDataFiltered = false;
|
||||
|
||||
public function __construct($sClass, $sClassAlias = null)
|
||||
{
|
||||
parent::__construct();
|
||||
@@ -59,11 +52,6 @@ class DBObjectSearch extends DBSearch
|
||||
$this->m_aReferencedBy = array();
|
||||
}
|
||||
|
||||
public function AllowAllData($bAllowAllData = true) {$this->m_bAllowAllData = $bAllowAllData;}
|
||||
public function IsAllDataAllowed() {return $this->m_bAllowAllData;}
|
||||
protected function IsDataFiltered() {return $this->m_bDataFiltered; }
|
||||
protected function SetDataFiltered() {$this->m_bDataFiltered = true;}
|
||||
|
||||
// Create a search definition that leads to 0 result, still a valid search object
|
||||
static public function FromEmptySet($sClass)
|
||||
{
|
||||
@@ -184,87 +172,12 @@ class DBObjectSearch extends DBSearch
|
||||
{
|
||||
if (!array_key_exists($sAlias, $this->m_aClasses))
|
||||
{
|
||||
throw new CoreException("SetSelectedClasses: Invalid class alias $sAlias");
|
||||
throw new CoreException("Invalid class alias $sAlias");
|
||||
}
|
||||
$this->m_aSelectedClasses[$sAlias] = $this->m_aClasses[$sAlias];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Change any alias of the query tree
|
||||
*
|
||||
* @param $sOldName
|
||||
* @param $sNewName
|
||||
* @return bool True if the alias has been found and changed
|
||||
*/
|
||||
public function RenameAlias($sOldName, $sNewName)
|
||||
{
|
||||
$bFound = false;
|
||||
if (array_key_exists($sOldName, $this->m_aClasses))
|
||||
{
|
||||
$bFound = true;
|
||||
}
|
||||
if (array_key_exists($sNewName, $this->m_aClasses))
|
||||
{
|
||||
throw new Exception("RenameAlias: alias '$sNewName' already used");
|
||||
}
|
||||
|
||||
$aClasses = array();
|
||||
foreach ($this->m_aClasses as $sAlias => $sClass)
|
||||
{
|
||||
if ($sAlias === $sOldName)
|
||||
{
|
||||
$aClasses[$sNewName] = $sClass;
|
||||
}
|
||||
else
|
||||
{
|
||||
$aClasses[$sAlias] = $sClass;
|
||||
}
|
||||
}
|
||||
$this->m_aClasses = $aClasses;
|
||||
|
||||
$aSelectedClasses = array();
|
||||
foreach ($this->m_aSelectedClasses as $sAlias => $sClass)
|
||||
{
|
||||
if ($sAlias === $sOldName)
|
||||
{
|
||||
$aSelectedClasses[$sNewName] = $sClass;
|
||||
}
|
||||
else
|
||||
{
|
||||
$aSelectedClasses[$sAlias] = $sClass;
|
||||
}
|
||||
}
|
||||
$this->m_aSelectedClasses = $aSelectedClasses;
|
||||
|
||||
$this->m_oSearchCondition->RenameAlias($sOldName, $sNewName);
|
||||
|
||||
foreach($this->m_aPointingTo as $sExtKeyAttCode=>$aPointingTo)
|
||||
{
|
||||
foreach($aPointingTo as $iOperatorCode => $aFilter)
|
||||
{
|
||||
foreach($aFilter as $oExtFilter)
|
||||
{
|
||||
$bFound = $oExtFilter->RenameAlias($sOldName, $sNewName) || $bFound;
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach($this->m_aReferencedBy as $sForeignClass => $aReferences)
|
||||
{
|
||||
foreach($aReferences as $sForeignExtKeyAttCode => $aFiltersByOperator)
|
||||
{
|
||||
foreach ($aFiltersByOperator as $iOperatorCode => $aFilters)
|
||||
{
|
||||
foreach ($aFilters as $oForeignFilter)
|
||||
{
|
||||
$bFound = $oForeignFilter->RenameAlias($sOldName, $sNewName) || $bFound;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return $bFound;
|
||||
}
|
||||
|
||||
public function SetModifierProperty($sPluginClass, $sProperty, $value)
|
||||
{
|
||||
$this->m_aModifierProperties[$sPluginClass][$sProperty] = $value;
|
||||
@@ -641,85 +554,8 @@ class DBObjectSearch extends DBSearch
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to
|
||||
* - convert a translation table (format optimized for the translation in an expression tree) into simple hash
|
||||
* - compile over an eventually existing map
|
||||
*
|
||||
* @param $aRealiasingMap Map to update
|
||||
* @param $aAliasTranslation Translation table resulting from calls to MergeWith_InNamespace
|
||||
* @return array of <old-alias> => <new-alias>
|
||||
*/
|
||||
protected function UpdateRealiasingMap(&$aRealiasingMap, $aAliasTranslation)
|
||||
{
|
||||
if ($aRealiasingMap !== null)
|
||||
{
|
||||
foreach ($aAliasTranslation as $sPrevAlias => $aRules)
|
||||
{
|
||||
if (isset($aRules['*']))
|
||||
{
|
||||
$sNewAlias = $aRules['*'];
|
||||
$sOriginalAlias = array_search($sPrevAlias, $aRealiasingMap);
|
||||
if ($sOriginalAlias !== false)
|
||||
{
|
||||
$aRealiasingMap[$sOriginalAlias] = $sNewAlias;
|
||||
}
|
||||
else
|
||||
{
|
||||
$aRealiasingMap[$sPrevAlias] = $sNewAlias;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Completes the list of alias=>class by browsing the whole structure recursively
|
||||
* This a workaround to handle some cases in which the list of classes is not correctly updated.
|
||||
* This code should disappear as soon as DBObjectSearch get split between a container search class and a Node class
|
||||
*
|
||||
* @param $aClasses List to be completed
|
||||
*/
|
||||
protected function RecomputeClassList(&$aClasses)
|
||||
{
|
||||
$aClasses[$this->GetFirstJoinedClassAlias()] = $this->GetFirstJoinedClass();
|
||||
|
||||
// Recurse in the query tree
|
||||
foreach($this->m_aPointingTo as $sExtKeyAttCode=>$aPointingTo)
|
||||
{
|
||||
foreach($aPointingTo as $iOperatorCode => $aFilter)
|
||||
{
|
||||
foreach($aFilter as $oFilter)
|
||||
{
|
||||
$oFilter->RecomputeClassList($aClasses);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach($this->m_aReferencedBy as $sForeignClass=>$aReferences)
|
||||
{
|
||||
foreach($aReferences as $sForeignExtKeyAttCode => $aFiltersByOperator)
|
||||
{
|
||||
foreach ($aFiltersByOperator as $iOperatorCode => $aFilters)
|
||||
{
|
||||
foreach ($aFilters as $oForeignFilter)
|
||||
{
|
||||
$oForeignFilter->RecomputeClassList($aClasses);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param DBObjectSearch $oFilter
|
||||
* @param $sExtKeyAttCode
|
||||
* @param int $iOperatorCode
|
||||
* @param null $aRealiasingMap array of <old-alias> => <new-alias>, for each alias that has changed
|
||||
* @throws CoreException
|
||||
* @throws CoreWarning
|
||||
*/
|
||||
public function AddCondition_PointingTo(DBObjectSearch $oFilter, $sExtKeyAttCode, $iOperatorCode = TREE_OPERATOR_EQUALS, &$aRealiasingMap = null)
|
||||
public function AddCondition_PointingTo(DBObjectSearch $oFilter, $sExtKeyAttCode, $iOperatorCode = TREE_OPERATOR_EQUALS)
|
||||
{
|
||||
if (!MetaModel::IsValidKeyAttCode($this->GetClass(), $sExtKeyAttCode))
|
||||
{
|
||||
@@ -743,22 +579,6 @@ class DBObjectSearch extends DBSearch
|
||||
$aAliasTranslation = array();
|
||||
$res = $this->AddCondition_PointingTo_InNameSpace($oFilter, $sExtKeyAttCode, $this->m_aClasses, $aAliasTranslation, $iOperatorCode);
|
||||
$this->TransferConditionExpression($oFilter, $aAliasTranslation);
|
||||
$this->UpdateRealiasingMap($aRealiasingMap, $aAliasTranslation);
|
||||
|
||||
if (ENABLE_OPT && ($oFilter->GetClass() == $oFilter->GetFirstJoinedClass()))
|
||||
{
|
||||
if (isset($oFilter->m_aReferencedBy[$this->GetClass()][$sExtKeyAttCode][$iOperatorCode]))
|
||||
{
|
||||
// Optimization - fold sibling query
|
||||
$oRemoteFilter = $oFilter->m_aReferencedBy[$this->GetClass()][$sExtKeyAttCode][$iOperatorCode][0];
|
||||
$aAliasTranslation = array();
|
||||
$this->MergeWith_InNamespace($oRemoteFilter, $this->m_aClasses, $aAliasTranslation);
|
||||
unset($oFilter->m_aReferencedBy[$this->GetClass()][$sExtKeyAttCode][$iOperatorCode]);
|
||||
$this->m_oSearchCondition = $this->m_oSearchCondition->Translate($aAliasTranslation, false, false);
|
||||
$this->UpdateRealiasingMap($aRealiasingMap, $aAliasTranslation);
|
||||
}
|
||||
}
|
||||
$this->RecomputeClassList($this->m_aClasses);
|
||||
return $res;
|
||||
}
|
||||
|
||||
@@ -767,25 +587,11 @@ class DBObjectSearch extends DBSearch
|
||||
// Find the node on which the new tree must be attached (most of the time it is "this")
|
||||
$oReceivingFilter = $this->GetNode($this->GetClassAlias());
|
||||
|
||||
if (ENABLE_OPT && isset($oReceivingFilter->m_aPointingTo[$sExtKeyAttCode][$iOperatorCode]))
|
||||
{
|
||||
$oExisting = $oReceivingFilter->m_aPointingTo[$sExtKeyAttCode][$iOperatorCode][0];
|
||||
$oExisting->MergeWith_InNamespace($oFilter, $oExisting->m_aClasses, $aAliasTranslation);
|
||||
}
|
||||
else
|
||||
{
|
||||
$oFilter->AddToNamespace($aClassAliases, $aAliasTranslation);
|
||||
$oReceivingFilter->m_aPointingTo[$sExtKeyAttCode][$iOperatorCode][] = $oFilter;
|
||||
}
|
||||
$oFilter->AddToNamespace($aClassAliases, $aAliasTranslation);
|
||||
$oReceivingFilter->m_aPointingTo[$sExtKeyAttCode][$iOperatorCode][] = $oFilter;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param DBObjectSearch $oFilter
|
||||
* @param $sForeignExtKeyAttCode
|
||||
* @param int $iOperatorCode
|
||||
* @param null $aRealiasingMap array of <old-alias> => <new-alias>, for each alias that has changed
|
||||
*/
|
||||
public function AddCondition_ReferencedBy(DBObjectSearch $oFilter, $sForeignExtKeyAttCode, $iOperatorCode = TREE_OPERATOR_EQUALS, &$aRealiasingMap = null)
|
||||
public function AddCondition_ReferencedBy(DBObjectSearch $oFilter, $sForeignExtKeyAttCode, $iOperatorCode = TREE_OPERATOR_EQUALS)
|
||||
{
|
||||
$sForeignClass = $oFilter->GetClass();
|
||||
if (!MetaModel::IsValidKeyAttCode($sForeignClass, $sForeignExtKeyAttCode))
|
||||
@@ -798,7 +604,6 @@ class DBObjectSearch extends DBSearch
|
||||
// à refaire en spécifique dans FromOQL
|
||||
throw new CoreException("The specified filter (objects referencing an object of class {$this->GetClass()}) is not compatible with the key '{$sForeignClass}::$sForeignExtKeyAttCode', which is pointing to {$oAttExtKey->GetTargetClass()}");
|
||||
}
|
||||
|
||||
// Note: though it seems to be a good practice to clone the given source filter
|
||||
// (as it was done and fixed an issue in Intersect())
|
||||
// this was not implemented here because it was causing a regression (login as admin, select an org, click on any badge)
|
||||
@@ -808,22 +613,6 @@ class DBObjectSearch extends DBSearch
|
||||
$aAliasTranslation = array();
|
||||
$res = $this->AddCondition_ReferencedBy_InNameSpace($oFilter, $sForeignExtKeyAttCode, $this->m_aClasses, $aAliasTranslation, $iOperatorCode);
|
||||
$this->TransferConditionExpression($oFilter, $aAliasTranslation);
|
||||
$this->UpdateRealiasingMap($aRealiasingMap, $aAliasTranslation);
|
||||
|
||||
if (ENABLE_OPT && ($oFilter->GetClass() == $oFilter->GetFirstJoinedClass()))
|
||||
{
|
||||
if (isset($oFilter->m_aPointingTo[$sForeignExtKeyAttCode][$iOperatorCode]))
|
||||
{
|
||||
// Optimization - fold sibling query
|
||||
$oRemoteFilter = $oFilter->m_aPointingTo[$sForeignExtKeyAttCode][$iOperatorCode][0];
|
||||
$aAliasTranslation = array();
|
||||
$this->MergeWith_InNamespace($oRemoteFilter, $this->m_aClasses, $aAliasTranslation);
|
||||
unset($oFilter->m_aPointingTo[$sForeignExtKeyAttCode][$iOperatorCode]);
|
||||
$this->m_oSearchCondition = $this->m_oSearchCondition->Translate($aAliasTranslation, false, false);
|
||||
$this->UpdateRealiasingMap($aRealiasingMap, $aAliasTranslation);
|
||||
}
|
||||
}
|
||||
$this->RecomputeClassList($this->m_aClasses);
|
||||
return $res;
|
||||
}
|
||||
|
||||
@@ -834,16 +623,8 @@ class DBObjectSearch extends DBSearch
|
||||
// Find the node on which the new tree must be attached (most of the time it is "this")
|
||||
$oReceivingFilter = $this->GetNode($this->GetClassAlias());
|
||||
|
||||
if (ENABLE_OPT && isset($oReceivingFilter->m_aReferencedBy[$sForeignClass][$sForeignExtKeyAttCode][$iOperatorCode]))
|
||||
{
|
||||
$oExisting = $oReceivingFilter->m_aReferencedBy[$sForeignClass][$sForeignExtKeyAttCode][$iOperatorCode][0];
|
||||
$oExisting->MergeWith_InNamespace($oFilter, $oExisting->m_aClasses, $aAliasTranslation);
|
||||
}
|
||||
else
|
||||
{
|
||||
$oFilter->AddToNamespace($aClassAliases, $aAliasTranslation);
|
||||
$oReceivingFilter->m_aReferencedBy[$sForeignClass][$sForeignExtKeyAttCode][$iOperatorCode][] = $oFilter;
|
||||
}
|
||||
$oFilter->AddToNamespace($aClassAliases, $aAliasTranslation);
|
||||
$oReceivingFilter->m_aReferencedBy[$sForeignClass][$sForeignExtKeyAttCode][$iOperatorCode][] = $oFilter;
|
||||
}
|
||||
|
||||
public function Intersect(DBSearch $oFilter)
|
||||
@@ -873,10 +654,7 @@ class DBObjectSearch extends DBSearch
|
||||
|
||||
$oLeftFilter = $this->DeepClone();
|
||||
$oRightFilter = $oRightFilter->DeepClone();
|
||||
|
||||
$bAllowAllData = ($oLeftFilter->IsAllDataAllowed() && $oRightFilter->IsAllDataAllowed());
|
||||
$oLeftFilter->AllowAllData($bAllowAllData);
|
||||
|
||||
|
||||
if ($oLeftFilter->GetClass() != $oRightFilter->GetClass())
|
||||
{
|
||||
if (MetaModel::IsParentClass($oLeftFilter->GetClass(), $oRightFilter->GetClass()))
|
||||
@@ -1032,7 +810,7 @@ class DBObjectSearch extends DBSearch
|
||||
return $this->m_oSearchCondition->ApplyParameters(array_merge($this->m_aParams, $aArgs));
|
||||
}
|
||||
|
||||
public function ToOQL($bDevelopParams = false, $aContextParams = null, $bWithAllowAllFlag = false)
|
||||
public function ToOQL($bDevelopParams = false, $aContextParams = null)
|
||||
{
|
||||
// Currently unused, but could be useful later
|
||||
$bRetrofitParams = false;
|
||||
@@ -1072,10 +850,6 @@ class DBObjectSearch extends DBSearch
|
||||
{
|
||||
$sRes .= " AND MATCHES '$sFullText'";
|
||||
}
|
||||
if ($bWithAllowAllFlag && $this->m_bAllowAllData)
|
||||
{
|
||||
$sRes .= " ALLOW ALL DATA";
|
||||
}
|
||||
return $sRes;
|
||||
}
|
||||
|
||||
@@ -1233,22 +1007,6 @@ class DBObjectSearch extends DBSearch
|
||||
|
||||
$aAliases = array($sClassAlias => $sClass);
|
||||
|
||||
// Note: the condition must be built here, it may be altered later on when optimizing some joins
|
||||
$oConditionTree = $oOqlQuery->GetCondition();
|
||||
if ($oConditionTree instanceof Expression)
|
||||
{
|
||||
$aRawAliases = array($sClassAlias => $sClass);
|
||||
$aJoinSpecs = $oOqlQuery->GetJoins();
|
||||
if (is_array($aJoinSpecs))
|
||||
{
|
||||
foreach ($aJoinSpecs as $oJoinSpec)
|
||||
{
|
||||
$aRawAliases[$oJoinSpec->GetClassAlias()] = $oJoinSpec->GetClass();
|
||||
}
|
||||
}
|
||||
$this->m_oSearchCondition = $this->OQLExpressionToCondition($sQuery, $oConditionTree, $aRawAliases);
|
||||
}
|
||||
|
||||
// Maintain an array of filters, because the flat list is in fact referring to a tree
|
||||
// And this will be an easy way to dispatch the conditions
|
||||
// $this will be referenced by the other filters, or the other way around...
|
||||
@@ -1257,32 +1015,19 @@ class DBObjectSearch extends DBSearch
|
||||
$aJoinSpecs = $oOqlQuery->GetJoins();
|
||||
if (is_array($aJoinSpecs))
|
||||
{
|
||||
$aAliasTranslation = array();
|
||||
foreach ($aJoinSpecs as $oJoinSpec)
|
||||
{
|
||||
$sJoinClass = $oJoinSpec->GetClass();
|
||||
$sJoinClassAlias = $oJoinSpec->GetClassAlias();
|
||||
if (isset($aAliasTranslation[$sJoinClassAlias]['*']))
|
||||
{
|
||||
$sJoinClassAlias = $aAliasTranslation[$sJoinClassAlias]['*'];
|
||||
}
|
||||
|
||||
// Assumption: ext key on the left only !!!
|
||||
// normalization should take care of this
|
||||
$oLeftField = $oJoinSpec->GetLeftField();
|
||||
$sFromClass = $oLeftField->GetParent();
|
||||
if (isset($aAliasTranslation[$sFromClass]['*']))
|
||||
{
|
||||
$sFromClass = $aAliasTranslation[$sFromClass]['*'];
|
||||
}
|
||||
$sExtKeyAttCode = $oLeftField->GetName();
|
||||
|
||||
$oRightField = $oJoinSpec->GetRightField();
|
||||
$sToClass = $oRightField->GetParent();
|
||||
if (isset($aAliasTranslation[$sToClass]['*']))
|
||||
{
|
||||
$sToClass = $aAliasTranslation[$sToClass]['*'];
|
||||
}
|
||||
|
||||
$aAliases[$sJoinClassAlias] = $sJoinClass;
|
||||
$aJoinItems[$sJoinClassAlias] = new DBObjectSearch($sJoinClass, $sJoinClassAlias);
|
||||
@@ -1324,16 +1069,19 @@ class DBObjectSearch extends DBSearch
|
||||
{
|
||||
$oReceiver = $aJoinItems[$sToClass];
|
||||
$oNewComer = $aJoinItems[$sFromClass];
|
||||
|
||||
$aAliasTranslation = array();
|
||||
$oReceiver->AddCondition_ReferencedBy_InNameSpace($oNewComer, $sExtKeyAttCode, $oReceiver->m_aClasses, $aAliasTranslation, $iOperatorCode);
|
||||
}
|
||||
else
|
||||
{
|
||||
$oReceiver = $aJoinItems[$sFromClass];
|
||||
$oNewComer = $aJoinItems[$sToClass];
|
||||
|
||||
$aAliasTranslation = array();
|
||||
$oReceiver->AddCondition_PointingTo_InNameSpace($oNewComer, $sExtKeyAttCode, $oReceiver->m_aClasses, $aAliasTranslation, $iOperatorCode);
|
||||
}
|
||||
}
|
||||
$this->m_oSearchCondition = $this->m_oSearchCondition->Translate($aAliasTranslation, false, false /* leave unresolved fields */);
|
||||
}
|
||||
|
||||
// Check and prepare the select information
|
||||
@@ -1344,6 +1092,12 @@ class DBObjectSearch extends DBSearch
|
||||
$this->m_aSelectedClasses[$sClassToSelect] = $aAliases[$sClassToSelect];
|
||||
}
|
||||
$this->m_aClasses = $aAliases;
|
||||
|
||||
$oConditionTree = $oOqlQuery->GetCondition();
|
||||
if ($oConditionTree instanceof Expression)
|
||||
{
|
||||
$this->m_oSearchCondition = $this->OQLExpressionToCondition($sQuery, $oConditionTree, $aAliases);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
@@ -1375,139 +1129,7 @@ class DBObjectSearch extends DBSearch
|
||||
return $oSQLQuery->RenderUpdate($aScalarArgs);
|
||||
}
|
||||
|
||||
public function GetSQLQueryStructure($aAttToLoad, $bGetCount, $aGroupByExpr = null, $aSelectedClasses = null)
|
||||
{
|
||||
// Hide objects that are not visible to the current user
|
||||
//
|
||||
$oSearch = $this;
|
||||
if (!$this->IsAllDataAllowed() && !$this->IsDataFiltered())
|
||||
{
|
||||
$oVisibleObjects = UserRights::GetSelectFilter($this->GetClass(), $this->GetModifierProperties('UserRightsGetSelectFilter'));
|
||||
if ($oVisibleObjects === false)
|
||||
{
|
||||
// Make sure this is a valid search object, saying NO for all
|
||||
$oVisibleObjects = DBObjectSearch::FromEmptySet($this->GetClass());
|
||||
}
|
||||
if (is_object($oVisibleObjects))
|
||||
{
|
||||
$oVisibleObjects->AllowAllData();
|
||||
$oSearch = $this->Intersect($oVisibleObjects);
|
||||
$oSearch->SetDataFiltered();
|
||||
}
|
||||
else
|
||||
{
|
||||
// should be true at this point, meaning that no additional filtering
|
||||
// is required
|
||||
}
|
||||
}
|
||||
|
||||
// Compute query modifiers properties (can be set in the search itself, by the context, etc.)
|
||||
//
|
||||
$aModifierProperties = MetaModel::MakeModifierProperties($oSearch);
|
||||
|
||||
// Create a unique cache id
|
||||
//
|
||||
if (self::$m_bQueryCacheEnabled || self::$m_bTraceQueries)
|
||||
{
|
||||
// Need to identify the query
|
||||
$sOqlQuery = $oSearch->ToOql(false, null, true);
|
||||
|
||||
if (count($aModifierProperties))
|
||||
{
|
||||
array_multisort($aModifierProperties);
|
||||
$sModifierProperties = json_encode($aModifierProperties);
|
||||
}
|
||||
else
|
||||
{
|
||||
$sModifierProperties = '';
|
||||
}
|
||||
|
||||
$sRawId = $sOqlQuery.$sModifierProperties;
|
||||
if (!is_null($aAttToLoad))
|
||||
{
|
||||
$sRawId .= json_encode($aAttToLoad);
|
||||
}
|
||||
if (!is_null($aGroupByExpr))
|
||||
{
|
||||
foreach($aGroupByExpr as $sAlias => $oExpr)
|
||||
{
|
||||
$sRawId .= 'g:'.$sAlias.'!'.$oExpr->Render();
|
||||
}
|
||||
}
|
||||
$sRawId .= $bGetCount;
|
||||
if (is_array($aSelectedClasses))
|
||||
{
|
||||
$sRawId .= implode(',', $aSelectedClasses); // Unions may alter the list of selected columns
|
||||
}
|
||||
$sOqlId = md5($sRawId);
|
||||
}
|
||||
else
|
||||
{
|
||||
$sOqlQuery = "SELECTING... ".$oSearch->GetClass();
|
||||
$sOqlId = "query id ? n/a";
|
||||
}
|
||||
|
||||
|
||||
// Query caching
|
||||
//
|
||||
if (self::$m_bQueryCacheEnabled)
|
||||
{
|
||||
// Warning: using directly the query string as the key to the hash array can FAIL if the string
|
||||
// is long and the differences are only near the end... so it's safer (but not bullet proof?)
|
||||
// to use a hash (like md5) of the string as the key !
|
||||
//
|
||||
// Example of two queries that were found as similar by the hash array:
|
||||
// SELECT SLT JOIN lnkSLTToSLA AS L1 ON L1.slt_id=SLT.id JOIN SLA ON L1.sla_id = SLA.id JOIN lnkContractToSLA AS L2 ON L2.sla_id = SLA.id JOIN CustomerContract ON L2.contract_id = CustomerContract.id WHERE SLT.ticket_priority = 1 AND SLA.service_id = 3 AND SLT.metric = 'TTO' AND CustomerContract.customer_id = 2
|
||||
// and
|
||||
// SELECT SLT JOIN lnkSLTToSLA AS L1 ON L1.slt_id=SLT.id JOIN SLA ON L1.sla_id = SLA.id JOIN lnkContractToSLA AS L2 ON L2.sla_id = SLA.id JOIN CustomerContract ON L2.contract_id = CustomerContract.id WHERE SLT.ticket_priority = 1 AND SLA.service_id = 3 AND SLT.metric = 'TTR' AND CustomerContract.customer_id = 2
|
||||
// the only difference is R instead or O at position 285 (TTR instead of TTO)...
|
||||
//
|
||||
if (array_key_exists($sOqlId, self::$m_aQueryStructCache))
|
||||
{
|
||||
// hit!
|
||||
|
||||
$oSQLQuery = unserialize(serialize(self::$m_aQueryStructCache[$sOqlId]));
|
||||
// Note: cloning is not enough because the subtree is made of objects
|
||||
}
|
||||
elseif (self::$m_bUseAPCCache)
|
||||
{
|
||||
// Note: For versions of APC older than 3.0.17, fetch() accepts only one parameter
|
||||
//
|
||||
$sOqlAPCCacheId = 'itop-'.MetaModel::GetEnvironmentId().'-query-cache-'.$sOqlId;
|
||||
$oKPI = new ExecutionKPI();
|
||||
$result = apc_fetch($sOqlAPCCacheId);
|
||||
$oKPI->ComputeStats('Query APC (fetch)', $sOqlQuery);
|
||||
|
||||
if (is_object($result))
|
||||
{
|
||||
$oSQLQuery = $result;
|
||||
self::$m_aQueryStructCache[$sOqlId] = $oSQLQuery;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!isset($oSQLQuery))
|
||||
{
|
||||
$oKPI = new ExecutionKPI();
|
||||
$oSQLQuery = $oSearch->BuildSQLQueryStruct($aAttToLoad, $bGetCount, $aModifierProperties, $aGroupByExpr, $aSelectedClasses);
|
||||
$oKPI->ComputeStats('BuildSQLQueryStruct', $sOqlQuery);
|
||||
|
||||
if (self::$m_bQueryCacheEnabled)
|
||||
{
|
||||
if (self::$m_bUseAPCCache)
|
||||
{
|
||||
$oKPI = new ExecutionKPI();
|
||||
apc_store($sOqlAPCCacheId, $oSQLQuery, self::$m_iQueryCacheTTL);
|
||||
$oKPI->ComputeStats('Query APC (store)', $sOqlQuery);
|
||||
}
|
||||
|
||||
self::$m_aQueryStructCache[$sOqlId] = $oSQLQuery->DeepClone();
|
||||
}
|
||||
}
|
||||
return $oSQLQuery;
|
||||
}
|
||||
|
||||
protected function BuildSQLQueryStruct($aAttToLoad, $bGetCount, $aModifierProperties, $aGroupByExpr = null, $aSelectedClasses = null)
|
||||
public function MakeSQLQuery($aAttToLoad, $bGetCount, $aModifierProperties, $aGroupByExpr = null, $aSelectedClasses = null)
|
||||
{
|
||||
$oBuild = new QueryBuilderContext($this, $aModifierProperties, $aGroupByExpr, $aSelectedClasses);
|
||||
|
||||
|
||||
@@ -445,8 +445,8 @@ class DBObjectSet
|
||||
|
||||
/**
|
||||
* Sets the sort order for loading the rows from the DB. Changing the order by causes a Reload.
|
||||
*
|
||||
* @param hash $aOrderBy Format: [alias.]attcode => boolean (true = ascending, false = descending)
|
||||
*
|
||||
* @param hash $aOrderBy Format: field_code => boolean (true = ascending, false = descending)
|
||||
*/
|
||||
public function SetOrderBy($aOrderBy)
|
||||
{
|
||||
@@ -461,34 +461,6 @@ class DBObjectSet
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the sort order for loading the rows from the DB. Changing the order by causes a Reload.
|
||||
*
|
||||
* @param hash $aAliases Format: alias => boolean (true = ascending, false = descending). If omitted, then it defaults to all the selected classes
|
||||
*/
|
||||
public function SetOrderByClasses($aAliases = null)
|
||||
{
|
||||
if ($aAliases === null)
|
||||
{
|
||||
$aAliases = array();
|
||||
foreach ($this->GetSelectedClasses() as $sAlias => $sClass)
|
||||
{
|
||||
$aAliases[$sAlias] = true;
|
||||
}
|
||||
}
|
||||
|
||||
$aAttributes = array();
|
||||
foreach ($aAliases as $sAlias => $bClassDirection)
|
||||
{
|
||||
foreach (MetaModel::GetOrderByDefault($this->m_oFilter->GetClass($sAlias)) as $sAttCode => $bAttributeDirection)
|
||||
{
|
||||
$bDirection = $bClassDirection ? $bAttributeDirection : !$bAttributeDirection;
|
||||
$aAttributes[$sAlias.'.'.$sAttCode] = $bDirection;
|
||||
}
|
||||
}
|
||||
$this->SetOrderBy($aAttributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the 'count' limit for loading the rows from the DB
|
||||
*
|
||||
|
||||
@@ -42,9 +42,14 @@ abstract class DBSearch
|
||||
const JOIN_POINTING_TO = 0;
|
||||
const JOIN_REFERENCED_BY = 1;
|
||||
|
||||
protected $m_bDataFiltered = false;
|
||||
protected $m_bNoContextParameters = false;
|
||||
protected $m_aModifierProperties = array();
|
||||
|
||||
// By default, some information may be hidden to the current user
|
||||
// But it may happen that we need to disable that feature
|
||||
protected $m_bAllowAllData = false;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
@@ -57,11 +62,12 @@ abstract class DBSearch
|
||||
return unserialize(serialize($this)); // Beware this serializes/unserializes the search and its parameters as well
|
||||
}
|
||||
|
||||
abstract public function AllowAllData();
|
||||
abstract public function IsAllDataAllowed();
|
||||
|
||||
public function AllowAllData() {$this->m_bAllowAllData = true;}
|
||||
public function IsAllDataAllowed() {return $this->m_bAllowAllData;}
|
||||
public function NoContextParameters() {$this->m_bNoContextParameters = true;}
|
||||
public function HasContextParameters() {return $this->m_bNoContextParameters;}
|
||||
public function IsDataFiltered() {return $this->m_bDataFiltered; }
|
||||
public function SetDataFiltered() {$this->m_bDataFiltered = true;}
|
||||
|
||||
public function SetModifierProperty($sPluginClass, $sProperty, $value)
|
||||
{
|
||||
@@ -97,15 +103,6 @@ abstract class DBSearch
|
||||
*/
|
||||
abstract public function SetSelectedClasses($aSelectedClasses);
|
||||
|
||||
/**
|
||||
* Change any alias of the query tree
|
||||
*
|
||||
* @param $sOldName
|
||||
* @param $sNewName
|
||||
* @return bool True if the alias has been found and changed
|
||||
*/
|
||||
abstract public function RenameAlias($sOldName, $sNewName);
|
||||
|
||||
abstract public function IsAny();
|
||||
|
||||
public function Describe(){return 'deprecated - use ToOQL() instead';}
|
||||
@@ -130,35 +127,19 @@ abstract class DBSearch
|
||||
abstract public function AddConditionAdvanced($sAttSpec, $value);
|
||||
abstract public function AddCondition_FullText($sFullText);
|
||||
|
||||
/**
|
||||
* @param DBObjectSearch $oFilter
|
||||
* @param $sExtKeyAttCode
|
||||
* @param int $iOperatorCode
|
||||
* @param null $aRealiasingMap array of <old-alias> => <new-alias>, for each alias that has changed
|
||||
* @throws CoreException
|
||||
* @throws CoreWarning
|
||||
*/
|
||||
abstract public function AddCondition_PointingTo(DBObjectSearch $oFilter, $sExtKeyAttCode, $iOperatorCode = TREE_OPERATOR_EQUALS, &$aRealiasingMap = null);
|
||||
|
||||
/**
|
||||
* @param DBObjectSearch $oFilter
|
||||
* @param $sForeignExtKeyAttCode
|
||||
* @param int $iOperatorCode
|
||||
* @param null $aRealiasingMap array of <old-alias> => <new-alias>, for each alias that has changed
|
||||
*/
|
||||
abstract public function AddCondition_ReferencedBy(DBObjectSearch $oFilter, $sForeignExtKeyAttCode, $iOperatorCode = TREE_OPERATOR_EQUALS, &$aRealiasingMap = null);
|
||||
|
||||
abstract public function AddCondition_PointingTo(DBObjectSearch $oFilter, $sExtKeyAttCode, $iOperatorCode = TREE_OPERATOR_EQUALS);
|
||||
abstract public function AddCondition_ReferencedBy(DBObjectSearch $oFilter, $sForeignExtKeyAttCode, $iOperatorCode = TREE_OPERATOR_EQUALS);
|
||||
abstract public function Intersect(DBSearch $oFilter);
|
||||
|
||||
/**
|
||||
*
|
||||
* @param DBSearch $oFilter
|
||||
* @param integer $iDirection
|
||||
* @param string $sExtKeyAttCode
|
||||
* @param integer $iOperatorCode
|
||||
* @param array &$RealisasingMap Map of aliases from the attached query, that could have been renamed by the optimization process
|
||||
* @return DBSearch
|
||||
*/
|
||||
public function Join(DBSearch $oFilter, $iDirection, $sExtKeyAttCode, $iOperatorCode = TREE_OPERATOR_EQUALS, &$aRealiasingMap = null)
|
||||
public function Join(DBSearch $oFilter, $iDirection, $sExtKeyAttCode, $iOperatorCode = TREE_OPERATOR_EQUALS)
|
||||
{
|
||||
$oSourceFilter = $this->DeepClone();
|
||||
$oRet = null;
|
||||
@@ -168,7 +149,7 @@ abstract class DBSearch
|
||||
$aSearches = array();
|
||||
foreach ($oFilter->GetSearches() as $oSearch)
|
||||
{
|
||||
$aSearches[] = $oSourceFilter->Join($oSearch, $iDirection, $sExtKeyAttCode, $iOperatorCode, $aRealiasingMap);
|
||||
$aSearches[] = $oSourceFilter->Join($oSearch, $iDirection, $sExtKeyAttCode, $iOperatorCode);
|
||||
}
|
||||
$oRet = new DBUnionSearch($aSearches);
|
||||
}
|
||||
@@ -176,7 +157,7 @@ abstract class DBSearch
|
||||
{
|
||||
if ($iDirection === static::JOIN_POINTING_TO)
|
||||
{
|
||||
$oSourceFilter->AddCondition_PointingTo($oFilter, $sExtKeyAttCode, $iOperatorCode, $aRealiasingMap);
|
||||
$oSourceFilter->AddCondition_PointingTo($oFilter, $sExtKeyAttCode, $iOperatorCode);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -184,7 +165,7 @@ abstract class DBSearch
|
||||
{
|
||||
throw new Exception('Only TREE_OPERATOR_EQUALS operator code is supported yet for AddCondition_ReferencedBy.');
|
||||
}
|
||||
$oSourceFilter->AddCondition_ReferencedBy($oFilter, $sExtKeyAttCode, TREE_OPERATOR_EQUALS, $aRealiasingMap);
|
||||
$oSourceFilter->AddCondition_ReferencedBy($oFilter, $sExtKeyAttCode);
|
||||
}
|
||||
$oRet = $oSourceFilter;
|
||||
}
|
||||
@@ -238,7 +219,7 @@ abstract class DBSearch
|
||||
return $oSearchWithAlias;
|
||||
}
|
||||
|
||||
abstract public function ToOQL($bDevelopParams = false, $aContextParams = null, $bWithAllowAllFlag = false);
|
||||
abstract public function ToOQL($bDevelopParams = false, $aContextParams = null);
|
||||
|
||||
static protected $m_aOQLQueries = array();
|
||||
|
||||
@@ -511,8 +492,129 @@ abstract class DBSearch
|
||||
|
||||
protected function GetSQLQuery($aOrderBy, $aArgs, $aAttToLoad, $aExtendedDataSpec, $iLimitCount, $iLimitStart, $bGetCount, $aGroupByExpr = null)
|
||||
{
|
||||
$oSQLQuery = $this->GetSQLQueryStructure($aAttToLoad, $bGetCount, $aGroupByExpr);
|
||||
$oSQLQuery->SetSourceOQL($this->ToOQL());
|
||||
// Hide objects that are not visible to the current user
|
||||
//
|
||||
$oSearch = $this;
|
||||
if (!$this->IsAllDataAllowed() && !$this->IsDataFiltered())
|
||||
{
|
||||
$oVisibleObjects = UserRights::GetSelectFilter($this->GetClass(), $this->GetModifierProperties('UserRightsGetSelectFilter'));
|
||||
if ($oVisibleObjects === false)
|
||||
{
|
||||
// Make sure this is a valid search object, saying NO for all
|
||||
$oVisibleObjects = DBObjectSearch::FromEmptySet($this->GetClass());
|
||||
}
|
||||
if (is_object($oVisibleObjects))
|
||||
{
|
||||
$oSearch = $this->Intersect($oVisibleObjects);
|
||||
$oSearch->SetDataFiltered();
|
||||
}
|
||||
else
|
||||
{
|
||||
// should be true at this point, meaning that no additional filtering
|
||||
// is required
|
||||
}
|
||||
}
|
||||
|
||||
// Compute query modifiers properties (can be set in the search itself, by the context, etc.)
|
||||
//
|
||||
$aModifierProperties = MetaModel::MakeModifierProperties($oSearch);
|
||||
|
||||
// Create a unique cache id
|
||||
//
|
||||
if (self::$m_bQueryCacheEnabled || self::$m_bTraceQueries)
|
||||
{
|
||||
// Need to identify the query
|
||||
$sOqlQuery = $oSearch->ToOql();
|
||||
|
||||
if (count($aModifierProperties))
|
||||
{
|
||||
array_multisort($aModifierProperties);
|
||||
$sModifierProperties = json_encode($aModifierProperties);
|
||||
}
|
||||
else
|
||||
{
|
||||
$sModifierProperties = '';
|
||||
}
|
||||
|
||||
$sRawId = $sOqlQuery.$sModifierProperties;
|
||||
if (!is_null($aAttToLoad))
|
||||
{
|
||||
$sRawId .= json_encode($aAttToLoad);
|
||||
}
|
||||
if (!is_null($aGroupByExpr))
|
||||
{
|
||||
foreach($aGroupByExpr as $sAlias => $oExpr)
|
||||
{
|
||||
$sRawId .= 'g:'.$sAlias.'!'.$oExpr->Render();
|
||||
}
|
||||
}
|
||||
$sRawId .= $bGetCount;
|
||||
$sOqlId = md5($sRawId);
|
||||
}
|
||||
else
|
||||
{
|
||||
$sOqlQuery = "SELECTING... ".$oSearch->GetClass();
|
||||
$sOqlId = "query id ? n/a";
|
||||
}
|
||||
|
||||
|
||||
// Query caching
|
||||
//
|
||||
if (self::$m_bQueryCacheEnabled)
|
||||
{
|
||||
// Warning: using directly the query string as the key to the hash array can FAIL if the string
|
||||
// is long and the differences are only near the end... so it's safer (but not bullet proof?)
|
||||
// to use a hash (like md5) of the string as the key !
|
||||
//
|
||||
// Example of two queries that were found as similar by the hash array:
|
||||
// SELECT SLT JOIN lnkSLTToSLA AS L1 ON L1.slt_id=SLT.id JOIN SLA ON L1.sla_id = SLA.id JOIN lnkContractToSLA AS L2 ON L2.sla_id = SLA.id JOIN CustomerContract ON L2.contract_id = CustomerContract.id WHERE SLT.ticket_priority = 1 AND SLA.service_id = 3 AND SLT.metric = 'TTO' AND CustomerContract.customer_id = 2
|
||||
// and
|
||||
// SELECT SLT JOIN lnkSLTToSLA AS L1 ON L1.slt_id=SLT.id JOIN SLA ON L1.sla_id = SLA.id JOIN lnkContractToSLA AS L2 ON L2.sla_id = SLA.id JOIN CustomerContract ON L2.contract_id = CustomerContract.id WHERE SLT.ticket_priority = 1 AND SLA.service_id = 3 AND SLT.metric = 'TTR' AND CustomerContract.customer_id = 2
|
||||
// the only difference is R instead or O at position 285 (TTR instead of TTO)...
|
||||
//
|
||||
if (array_key_exists($sOqlId, self::$m_aQueryStructCache))
|
||||
{
|
||||
// hit!
|
||||
|
||||
$oSQLQuery = unserialize(serialize(self::$m_aQueryStructCache[$sOqlId]));
|
||||
// Note: cloning is not enough because the subtree is made of objects
|
||||
}
|
||||
elseif (self::$m_bUseAPCCache)
|
||||
{
|
||||
// Note: For versions of APC older than 3.0.17, fetch() accepts only one parameter
|
||||
//
|
||||
$sOqlAPCCacheId = 'itop-'.MetaModel::GetEnvironmentId().'-query-cache-'.$sOqlId;
|
||||
$oKPI = new ExecutionKPI();
|
||||
$result = apc_fetch($sOqlAPCCacheId);
|
||||
$oKPI->ComputeStats('Query APC (fetch)', $sOqlQuery);
|
||||
|
||||
if (is_object($result))
|
||||
{
|
||||
$oSQLQuery = $result;
|
||||
self::$m_aQueryStructCache[$sOqlId] = $oSQLQuery;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!isset($oSQLQuery))
|
||||
{
|
||||
$oKPI = new ExecutionKPI();
|
||||
$oSQLQuery = $oSearch->MakeSQLQuery($aAttToLoad, $bGetCount, $aModifierProperties, $aGroupByExpr);
|
||||
$oSQLQuery->SetSourceOQL($sOqlQuery);
|
||||
$oKPI->ComputeStats('MakeSQLQuery', $sOqlQuery);
|
||||
|
||||
if (self::$m_bQueryCacheEnabled)
|
||||
{
|
||||
if (self::$m_bUseAPCCache)
|
||||
{
|
||||
$oKPI = new ExecutionKPI();
|
||||
apc_store($sOqlAPCCacheId, $oSQLQuery, self::$m_iQueryCacheTTL);
|
||||
$oKPI->ComputeStats('Query APC (store)', $sOqlQuery);
|
||||
}
|
||||
|
||||
self::$m_aQueryStructCache[$sOqlId] = $oSQLQuery->DeepClone();
|
||||
}
|
||||
}
|
||||
|
||||
// Join to an additional table, if required...
|
||||
//
|
||||
@@ -522,7 +624,7 @@ abstract class DBSearch
|
||||
$aExtendedFields = array();
|
||||
foreach($aExtendedDataSpec['fields'] as $sColumn)
|
||||
{
|
||||
$sColRef = $this->GetClassAlias().'_extdata_'.$sColumn;
|
||||
$sColRef = $oSearch->GetClassAlias().'_extdata_'.$sColumn;
|
||||
$aExtendedFields[$sColRef] = new FieldExpressionResolved($sColumn, $sTableAlias);
|
||||
}
|
||||
$oSQLQueryExt = new SQLObjectQuery($aExtendedDataSpec['table'], $sTableAlias, $aExtendedFields);
|
||||
|
||||
@@ -55,22 +55,6 @@ class DBUnionSearch extends DBSearch
|
||||
$this->ComputeSelectedClasses();
|
||||
}
|
||||
|
||||
public function AllowAllData()
|
||||
{
|
||||
foreach ($this->aSearches as $oSearch)
|
||||
{
|
||||
$oSearch->AllowAllData();
|
||||
}
|
||||
}
|
||||
public function IsAllDataAllowed()
|
||||
{
|
||||
foreach ($this->aSearches as $oSearch)
|
||||
{
|
||||
if ($oSearch->IsAllDataAllowed() === false) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the lowest common ancestor for each of the selected class
|
||||
*/
|
||||
@@ -203,23 +187,6 @@ class DBUnionSearch extends DBSearch
|
||||
$this->ComputeSelectedClasses();
|
||||
}
|
||||
|
||||
/**
|
||||
* Change any alias of the query tree
|
||||
*
|
||||
* @param $sOldName
|
||||
* @param $sNewName
|
||||
* @return bool True if the alias has been found and changed
|
||||
*/
|
||||
public function RenameAlias($sOldName, $sNewName)
|
||||
{
|
||||
$bRet = false;
|
||||
foreach ($this->aSearches as $oSearch)
|
||||
{
|
||||
$bRet = $oSearch->RenameAlias($sOldName, $sNewName) || $bRet;
|
||||
}
|
||||
return $bRet;
|
||||
}
|
||||
|
||||
public function IsAny()
|
||||
{
|
||||
$bIsAny = true;
|
||||
@@ -315,33 +282,19 @@ class DBUnionSearch extends DBSearch
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param DBObjectSearch $oFilter
|
||||
* @param $sExtKeyAttCode
|
||||
* @param int $iOperatorCode
|
||||
* @param null $aRealiasingMap array of <old-alias> => <new-alias>, for each alias that has changed
|
||||
* @throws CoreException
|
||||
* @throws CoreWarning
|
||||
*/
|
||||
public function AddCondition_PointingTo(DBObjectSearch $oFilter, $sExtKeyAttCode, $iOperatorCode = TREE_OPERATOR_EQUALS, &$aRealiasingMap = null)
|
||||
public function AddCondition_PointingTo(DBObjectSearch $oFilter, $sExtKeyAttCode, $iOperatorCode = TREE_OPERATOR_EQUALS)
|
||||
{
|
||||
foreach ($this->aSearches as $oSearch)
|
||||
{
|
||||
$oSearch->AddCondition_PointingTo($oFilter, $sExtKeyAttCode, $iOperatorCode, $aRealiasingMap);
|
||||
$oSearch->AddCondition_PointingTo($oFilter, $sExtKeyAttCode, $iOperatorCode);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param DBObjectSearch $oFilter
|
||||
* @param $sForeignExtKeyAttCode
|
||||
* @param int $iOperatorCode
|
||||
* @param null $aRealiasingMap array of <old-alias> => <new-alias>, for each alias that has changed
|
||||
*/
|
||||
public function AddCondition_ReferencedBy(DBObjectSearch $oFilter, $sForeignExtKeyAttCode, $iOperatorCode = TREE_OPERATOR_EQUALS, &$aRealiasingMap = null)
|
||||
public function AddCondition_ReferencedBy(DBObjectSearch $oFilter, $sForeignExtKeyAttCode, $iOperatorCode = TREE_OPERATOR_EQUALS)
|
||||
{
|
||||
foreach ($this->aSearches as $oSearch)
|
||||
{
|
||||
$oSearch->AddCondition_ReferencedBy($oFilter, $sForeignExtKeyAttCode, $iOperatorCode, $aRealiasingMap);
|
||||
$oSearch->AddCondition_ReferencedBy($oFilter, $sForeignExtKeyAttCode, $iOperatorCode);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -404,12 +357,12 @@ class DBUnionSearch extends DBSearch
|
||||
/**
|
||||
* Overloads for query building
|
||||
*/
|
||||
public function ToOQL($bDevelopParams = false, $aContextParams = null, $bWithAllowAllFlag = false)
|
||||
public function ToOQL($bDevelopParams = false, $aContextParams = null)
|
||||
{
|
||||
$aSubQueries = array();
|
||||
foreach ($this->aSearches as $oSearch)
|
||||
{
|
||||
$aSubQueries[] = $oSearch->ToOQL($bDevelopParams, $aContextParams, $bWithAllowAllFlag);
|
||||
$aSubQueries[] = $oSearch->ToOQL($bDevelopParams, $aContextParams);
|
||||
}
|
||||
$sRet = implode(' UNION ', $aSubQueries);
|
||||
return $sRet;
|
||||
@@ -456,11 +409,11 @@ class DBUnionSearch extends DBSearch
|
||||
throw new Exception('MakeUpdateQuery is not implemented for the unions!');
|
||||
}
|
||||
|
||||
protected function GetSQLQueryStructure($aAttToLoad, $bGetCount, $aGroupByExpr = null, $aSelectedClasses = null)
|
||||
protected function MakeSQLQuery($aAttToLoad, $bGetCount, $aModifierProperties, $aGroupByExpr = null, $aSelectedClasses = null)
|
||||
{
|
||||
if (count($this->aSearches) == 1)
|
||||
{
|
||||
return $this->aSearches[0]->GetSQLQueryStructure($aAttToLoad, $bGetCount, $aGroupByExpr);
|
||||
return $this->aSearches[0]->MakeSQLQuery($aAttToLoad, $bGetCount, $aModifierProperties, $aGroupByExpr);
|
||||
}
|
||||
|
||||
$aSQLQueries = array();
|
||||
@@ -515,7 +468,7 @@ class DBUnionSearch extends DBSearch
|
||||
$aQueryGroupByExpr[$sExpressionAlias] = $oExpression->Translate($aTranslationData, false, false);
|
||||
}
|
||||
}
|
||||
$oSubQuery = $oSearch->GetSQLQueryStructure($aQueryAttToLoad, false, $aQueryGroupByExpr, $aSearchSelectedClasses);
|
||||
$oSubQuery = $oSearch->MakeSQLQuery($aQueryAttToLoad, false, $aModifierProperties, $aQueryGroupByExpr, $aSearchSelectedClasses);
|
||||
$aSQLQueries[] = $oSubQuery;
|
||||
}
|
||||
|
||||
|
||||
@@ -195,6 +195,8 @@ class EMail
|
||||
|
||||
$aFailedRecipients = array();
|
||||
$this->m_oMessage->setMaxLineLength(0);
|
||||
IssueLog::Info(__METHOD__.' '.$this->m_oMessage->getMaxLineLength());
|
||||
IssueLog::Info(__METHOD__.' '.$this->m_oMessage->toString());
|
||||
$iSent = $oMailer->send($this->m_oMessage, $aFailedRecipients);
|
||||
if ($iSent === 0)
|
||||
{
|
||||
|
||||
@@ -138,7 +138,7 @@ class HTMLDOMSanitizer extends HTMLSanitizer
|
||||
protected static $aTagsWhiteList = array(
|
||||
'html' => array(),
|
||||
'body' => array(),
|
||||
'a' => array('href', 'name', 'style', 'target'),
|
||||
'a' => array('href', 'name', 'style'),
|
||||
'p' => array('style'),
|
||||
'br' => array(),
|
||||
'span' => array('style'),
|
||||
@@ -159,7 +159,7 @@ class HTMLDOMSanitizer extends HTMLSanitizer
|
||||
'nav' => array('style'),
|
||||
'section' => array('style'),
|
||||
'code' => array('style'),
|
||||
'table' => array('style', 'width', 'summary', 'align', 'border', 'cellpadding', 'cellspacing'),
|
||||
'table' => array('style', 'width'),
|
||||
'thead' => array('style'),
|
||||
'tbody' => array('style'),
|
||||
'tr' => array('style'),
|
||||
@@ -183,26 +183,17 @@ class HTMLDOMSanitizer extends HTMLSanitizer
|
||||
'hr' => array('style'),
|
||||
'pre' => array(),
|
||||
'center' => array(),
|
||||
'caption' => array(),
|
||||
);
|
||||
|
||||
protected static $aAttrsWhiteList = array(
|
||||
'href' => '/^(http:|https:)/i',
|
||||
'src' => '/^(http:|https:|data:)/i',
|
||||
);
|
||||
|
||||
protected static $aStylesWhiteList = array(
|
||||
'background-color', 'color', 'float', 'font', 'font-style', 'font-size', 'font-family', 'padding', 'margin', 'border', 'cellpadding', 'cellspacing', 'bordercolor', 'border-collapse', 'width', 'height', 'text-align',
|
||||
'background-color', 'color', 'float', 'font', 'font-style', 'font-size', 'font-family', 'padding', 'margin', 'border', 'cellpadding', 'cellspacing', 'bordercolor', 'border-collapse', 'width', 'height',
|
||||
);
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
if (!array_key_exists('href', self::$aAttrsWhiteList))
|
||||
{
|
||||
$sPattern = '/'.str_replace('/', '\/', utils::GetConfig()->Get('url_validation_pattern')).'/i';
|
||||
self::$aAttrsWhiteList['href'] = $sPattern;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function DoSanitize($sHTML)
|
||||
{
|
||||
$this->oDoc = new DOMDocument();
|
||||
|
||||
@@ -464,7 +464,7 @@ EOF
|
||||
oEditor.on( 'instanceReady', function() {
|
||||
if(!CKEDITOR.env.iOS && $('#'+oEditor.id+'_toolbox .editor_magnifier').length == 0)
|
||||
{
|
||||
$('#'+oEditor.id+'_toolbox').append('<span class="editor_magnifier" title="$sToggleFullScreen" style="display:block;width:12px;height:11px;border:1px #A6A6A6 solid;cursor:pointer; background-image:url(\\'$sAppRootUrl/images/full-screen.png\\')"> </span>');
|
||||
$('#'+oEditor.id+'_toolbox').append('<span class="editor_magnifier" title="$sToggleFullScreen" style="display:block;width:12px;height:11px;border:1px #A6A6A6 solid;cursor:pointer; background-image:url($sAppRootUrl/images/full-screen.png)"> </span>');
|
||||
$('#'+oEditor.id+'_toolbox .editor_magnifier').on('click', function() {
|
||||
oEditor.execCommand('maximize');
|
||||
if ($(this).closest('.cke_maximized').length != 0)
|
||||
@@ -473,15 +473,12 @@ EOF
|
||||
}
|
||||
});
|
||||
}
|
||||
if (oEditor.widgets.registered.uploadimage)
|
||||
{
|
||||
oEditor.widgets.registered.uploadimage.onUploaded = function( upload ) {
|
||||
var oData = JSON.parse(upload.xhr.responseText);
|
||||
this.replaceWith( '<img src="' + upload.url + '" ' +
|
||||
'width="' + oData.width + '" ' +
|
||||
'height="' + oData.height + '">' );
|
||||
}
|
||||
}
|
||||
oEditor.widgets.registered.uploadimage.onUploaded = function( upload ) {
|
||||
var oData = JSON.parse(upload.xhr.responseText);
|
||||
this.replaceWith( '<img src="' + upload.url + '" ' +
|
||||
'width="' + oData.width + '" ' +
|
||||
'height="' + oData.height + '">' );
|
||||
}
|
||||
});
|
||||
});
|
||||
EOF
|
||||
|
||||
@@ -22,7 +22,6 @@ require_once(APPROOT.'core/querymodifier.class.inc.php');
|
||||
require_once(APPROOT.'core/metamodelmodifier.inc.php');
|
||||
require_once(APPROOT.'core/computing.inc.php');
|
||||
require_once(APPROOT.'core/relationgraph.class.inc.php');
|
||||
require_once(APPROOT.'core/apc-compat.php');
|
||||
|
||||
/**
|
||||
* Metamodel
|
||||
@@ -1768,10 +1767,10 @@ abstract class MetaModel
|
||||
$oFriendlyName = new AttributeExternalField($sFriendlyNameAttCode, array("allowed_values"=>null, "extkey_attcode"=>$sKeyAttCode, "target_attcode"=>$sRemoteAttCode, "depends_on"=>array()));
|
||||
$oFriendlyName->SetHostClass($sClass);
|
||||
self::$m_aAttribDefs[$sClass][$sFriendlyNameAttCode] = $oFriendlyName;
|
||||
self::$m_aAttribOrigins[$sClass][$sFriendlyNameAttCode] = self::$m_aAttribOrigins[$sClass][$sKeyAttCode];
|
||||
self::$m_aAttribOrigins[$sClass][$sFriendlyNameAttCode] = $sRemoteClass;
|
||||
$oFriendlyNameFlt = new FilterFromAttribute($oFriendlyName);
|
||||
self::$m_aFilterDefs[$sClass][$sFriendlyNameAttCode] = $oFriendlyNameFlt;
|
||||
self::$m_aFilterOrigins[$sClass][$sFriendlyNameAttCode] = self::$m_aFilterOrigins[$sClass][$sKeyAttCode];
|
||||
self::$m_aFilterOrigins[$sClass][$sFriendlyNameAttCode] = $sRemoteClass;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1780,10 +1779,10 @@ abstract class MetaModel
|
||||
$oFriendlyName = new AttributeFriendlyName($sFriendlyNameAttCode, $sAttCode);
|
||||
$oFriendlyName->SetHostClass($sClass);
|
||||
self::$m_aAttribDefs[$sClass][$sFriendlyNameAttCode] = $oFriendlyName;
|
||||
self::$m_aAttribOrigins[$sClass][$sFriendlyNameAttCode] = self::$m_aAttribOrigins[$sClass][$sAttCode];
|
||||
self::$m_aAttribOrigins[$sClass][$sFriendlyNameAttCode] = $sRemoteClass;
|
||||
$oFriendlyNameFlt = new FilterFromAttribute($oFriendlyName);
|
||||
self::$m_aFilterDefs[$sClass][$sFriendlyNameAttCode] = $oFriendlyNameFlt;
|
||||
self::$m_aFilterOrigins[$sClass][$sFriendlyNameAttCode] = self::$m_aFilterOrigins[$sClass][$sAttCode];
|
||||
self::$m_aFilterOrigins[$sClass][$sFriendlyNameAttCode] = $sRemoteClass;
|
||||
|
||||
if (self::HasChildrenClasses($sRemoteClass))
|
||||
{
|
||||
@@ -1798,11 +1797,11 @@ abstract class MetaModel
|
||||
));
|
||||
$oClassRecall->SetHostClass($sClass);
|
||||
self::$m_aAttribDefs[$sClass][$sClassRecallAttCode] = $oClassRecall;
|
||||
self::$m_aAttribOrigins[$sClass][$sClassRecallAttCode] = self::$m_aAttribOrigins[$sClass][$sAttCode];
|
||||
self::$m_aAttribOrigins[$sClass][$sClassRecallAttCode] = $sRemoteClass;
|
||||
|
||||
$oClassFlt = new FilterFromAttribute($oClassRecall);
|
||||
self::$m_aFilterDefs[$sClass][$sClassRecallAttCode] = $oClassFlt;
|
||||
self::$m_aFilterOrigins[$sClass][$sClassRecallAttCode] = self::$m_aFilterOrigins[$sClass][$sAttCode];
|
||||
self::$m_aFilterOrigins[$sClass][$sClassRecallAttCode] = $sRemoteClass;
|
||||
|
||||
// Add it to the ZLists where the external key is present
|
||||
//foreach(self::$m_aListData[$sClass] as $sListCode => $aAttributes)
|
||||
|
||||
@@ -639,12 +639,12 @@ class ormCaseLog {
|
||||
}
|
||||
|
||||
|
||||
public function GetModifiedEntry($sFormat = 'text')
|
||||
public function GetModifiedEntry()
|
||||
{
|
||||
$sModifiedEntry = '';
|
||||
if ($this->m_bModified)
|
||||
{
|
||||
$sModifiedEntry = $this->GetLatestEntry($sFormat);
|
||||
$sModifiedEntry = $this->GetLatestEntry();
|
||||
}
|
||||
return $sModifiedEntry;
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ class ormCustomFieldsValue
|
||||
{
|
||||
$oAttDef = MetaModel::GetAttributeDef(get_class($this->oHostObject), $this->sAttCode);
|
||||
$oHandler = $oAttDef->GetHandler($this->GetValues());
|
||||
return $oHandler->GetForTemplate($this->aCurrentValues, $sVerb, $bLocalize);
|
||||
return 'template...verb='.$sVerb.' sur "'.json_encode($this->aCurrentValues).'"';
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -115,29 +115,21 @@ class ormDocument
|
||||
*/
|
||||
public function GetDownloadLink($sClass, $Id, $sAttCode)
|
||||
{
|
||||
return "<a href=\"".utils::GetAbsoluteUrlAppRoot()."pages/ajax.document.php?operation=download_document&class=$sClass&id=$Id&field=$sAttCode\">".htmlentities($this->GetFileName(), ENT_QUOTES, 'UTF-8')."</a>\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an URL to display a document like an image
|
||||
* @return string
|
||||
*/
|
||||
public function GetDisplayURL($sClass, $Id, $sAttCode)
|
||||
{
|
||||
return utils::GetAbsoluteUrlAppRoot() . "pages/ajax.render.php?operation=display_document&class=$sClass&id=$Id&field=$sAttCode";
|
||||
return "<a href=\"".utils::GetAbsoluteUrlAppRoot()."pages/ajax.render.php?operation=download_document&class=$sClass&id=$Id&field=$sAttCode\">".htmlentities($this->GetFileName(), ENT_QUOTES, 'UTF-8')."</a>\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an URL to download a document like an image (uses HTTP caching)
|
||||
* @return string
|
||||
*/
|
||||
*/
|
||||
public function GetDownloadURL($sClass, $Id, $sAttCode)
|
||||
{
|
||||
// Compute a signature to reset the cache anytime the data changes (this is acceptable if used only with icon files)
|
||||
$sSignature = md5($this->GetData());
|
||||
return utils::GetAbsoluteUrlAppRoot() . "pages/ajax.document.php?operation=download_document&class=$sClass&id=$Id&field=$sAttCode&s=$sSignature&cache=86400";
|
||||
return utils::GetAbsoluteUrlAppRoot()."pages/ajax.document.php?operation=download_document&class=$sClass&id=$Id&field=$sAttCode&s=$sSignature&cache=86400";
|
||||
}
|
||||
|
||||
|
||||
public function IsPreviewAvailable()
|
||||
{
|
||||
$bRet = false;
|
||||
@@ -184,7 +176,7 @@ class ormDocument
|
||||
{
|
||||
$oPage->TrashUnexpectedOutput();
|
||||
$oPage->SetContentType($oDocument->GetMimeType());
|
||||
$oPage->SetContentDisposition($sContentDisposition,$oDocument->GetFileName());
|
||||
//$oPage->SetContentDisposition($sContentDisposition,$oDocument->GetFileName());
|
||||
$oPage->add($oDocument->GetData());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -494,7 +494,6 @@ class CheckStopWatchThresholds implements iBackgroundProcess
|
||||
$sExpression = "SELECT $sClass WHERE {$sAttCode}_laststart AND {$sAttCode}_{$iThreshold}_triggered = 0 AND {$sAttCode}_{$iThreshold}_deadline < '$sNow'";
|
||||
$oFilter = DBObjectSearch::FromOQL($sExpression);
|
||||
$oSet = new DBObjectSet($oFilter);
|
||||
$oSet->OptimizeColumnLoad(array($sAttCode));
|
||||
while ((time() < $iTimeLimit) && ($oObj = $oSet->Fetch()))
|
||||
{
|
||||
$sClass = get_class($oObj);
|
||||
|
||||
@@ -1045,12 +1045,7 @@ class UserRights
|
||||
{
|
||||
$oUser = self::$m_oUser;
|
||||
}
|
||||
if ($oUser === null)
|
||||
{
|
||||
// Not logged in: no profile at all
|
||||
$aProfiles = array();
|
||||
}
|
||||
elseif ((self::$m_oUser !== null) && ($oUser->GetKey() == self::$m_oUser->GetKey()))
|
||||
if ($oUser->GetKey() == self::$m_oUser->GetKey())
|
||||
{
|
||||
// Data about the current user can be found into the session data
|
||||
if (array_key_exists('profile_list', $_SESSION))
|
||||
|
||||
@@ -2,19 +2,42 @@
|
||||
|
||||
/**
|
||||
* Локализация интерфейса Combodo iTop подготовлена сообществом iTop по-русски http://community.itop-itsm.ru.
|
||||
*
|
||||
* @author Vladimir Kunin <v.b.kunin@gmail.com>
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*
|
||||
* @author Vladimir Kunin <v.b.kunin@gmail.com>
|
||||
* @link http://community.itop-itsm.ru iTop Russian Community
|
||||
* @link https://github.com/itop-itsm-ru/itop-rus
|
||||
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
|
||||
*
|
||||
* Инструкция по установке
|
||||
*
|
||||
* Процесс установки заключается в замене имеющихся локализационных файлов полученными и последующем запуске процедуры обновления iTop для перекомпиляции кода.
|
||||
* 1. Скопируйте с заменой два полученных файла из "itop-rus/dictionaries" в "путь/до/вашего/itop/dictionaries".
|
||||
* 2. Скопируйте с заменой полученные файлы "itop-rus/datamodels/2.x/название-модуля/ru.dict.название-модуля.php" в "путь/до/вашего/itop/datamodels/2.x/название-модуля".
|
||||
* 3. Перейдите по адресу "http://адрес/вашего/itop/setup", при этом файл "путь/до/вашего/itop/conf/production/config-itop.php" должен быть доступен для записи.
|
||||
* 4. На второй странице установщика выберите "Upgrade an existing iTop instance" и следуйте дальнейшим инструкциям установщика.
|
||||
*
|
||||
* Ответы на вопросы по установке и использованию переводов, а также на любые другие вопросы по iTop всегда можно получить на сайте сообщества iTop по-русски http://community.itop-itsm.ru.
|
||||
*
|
||||
*/
|
||||
|
||||
// Dictionnay conventions
|
||||
// Class:<class_name>
|
||||
// Class:<class_name>+
|
||||
// Class:<class_name>/Attribute:<attribute_code>
|
||||
// Class:<class_name>/Attribute:<attribute_code>+
|
||||
// Class:<class_name>/Attribute:<attribute_code>/Value:<value>
|
||||
// Class:<class_name>/Attribute:<attribute_code>/Value:<value>+
|
||||
// Class:<class_name>/Stimulus:<stimulus_code>
|
||||
// Class:<class_name>/Stimulus:<stimulus_code>+
|
||||
|
||||
//
|
||||
// Class: UserExternal
|
||||
//
|
||||
|
||||
Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Class:UserExternal' => 'Внешний пользователь',
|
||||
'Class:UserExternal+' => 'Пользователь, аутентифицируемый вне iTop',
|
||||
'Class:UserExternal+' => 'Пользователь, аутентифицированный вне iTop',
|
||||
));
|
||||
|
||||
|
||||
|
||||
?>
|
||||
|
||||
@@ -2,21 +2,44 @@
|
||||
|
||||
/**
|
||||
* Локализация интерфейса Combodo iTop подготовлена сообществом iTop по-русски http://community.itop-itsm.ru.
|
||||
*
|
||||
* @author Vladimir Kunin <v.b.kunin@gmail.com>
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*
|
||||
* @author Vladimir Kunin <v.b.kunin@gmail.com>
|
||||
* @link http://community.itop-itsm.ru iTop Russian Community
|
||||
* @link https://github.com/itop-itsm-ru/itop-rus
|
||||
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
|
||||
*
|
||||
* Инструкция по установке
|
||||
*
|
||||
* Процесс установки заключается в замене имеющихся локализационных файлов полученными и последующем запуске процедуры обновления iTop для перекомпиляции кода.
|
||||
* 1. Скопируйте с заменой два полученных файла из "itop-rus/dictionaries" в "путь/до/вашего/itop/dictionaries".
|
||||
* 2. Скопируйте с заменой полученные файлы "itop-rus/datamodels/2.x/название-модуля/ru.dict.название-модуля.php" в "путь/до/вашего/itop/datamodels/2.x/название-модуля".
|
||||
* 3. Перейдите по адресу "http://адрес/вашего/itop/setup", при этом файл "путь/до/вашего/itop/conf/production/config-itop.php" должен быть доступен для записи.
|
||||
* 4. На второй странице установщика выберите "Upgrade an existing iTop instance" и следуйте дальнейшим инструкциям установщика.
|
||||
*
|
||||
* Ответы на вопросы по установке и использованию переводов, а также на любые другие вопросы по iTop всегда можно получить на сайте сообщества iTop по-русски http://community.itop-itsm.ru.
|
||||
*
|
||||
*/
|
||||
|
||||
// Dictionnay conventions
|
||||
// Class:<class_name>
|
||||
// Class:<class_name>+
|
||||
// Class:<class_name>/Attribute:<attribute_code>
|
||||
// Class:<class_name>/Attribute:<attribute_code>+
|
||||
// Class:<class_name>/Attribute:<attribute_code>/Value:<value>
|
||||
// Class:<class_name>/Attribute:<attribute_code>/Value:<value>+
|
||||
// Class:<class_name>/Stimulus:<stimulus_code>
|
||||
// Class:<class_name>/Stimulus:<stimulus_code>+
|
||||
|
||||
//
|
||||
// Class: UserLDAP
|
||||
//
|
||||
|
||||
Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Class:UserLDAP' => 'Пользователь LDAP',
|
||||
'Class:UserLDAP+' => 'Пользователь, аутентифицируемый через LDAP',
|
||||
'Class:UserLDAP+' => 'Пользователь, аутентифицированный в LDAP',
|
||||
'Class:UserLDAP/Attribute:password' => 'Пароль',
|
||||
'Class:UserLDAP/Attribute:password+' => 'Строка аутентификации пользователя',
|
||||
));
|
||||
));
|
||||
|
||||
|
||||
|
||||
?>
|
||||
|
||||
@@ -2,21 +2,44 @@
|
||||
|
||||
/**
|
||||
* Локализация интерфейса Combodo iTop подготовлена сообществом iTop по-русски http://community.itop-itsm.ru.
|
||||
*
|
||||
* @author Vladimir Kunin <v.b.kunin@gmail.com>
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*
|
||||
* @author Vladimir Kunin <v.b.kunin@gmail.com>
|
||||
* @link http://community.itop-itsm.ru iTop Russian Community
|
||||
* @link https://github.com/itop-itsm-ru/itop-rus
|
||||
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
|
||||
*
|
||||
* Инструкция по установке
|
||||
*
|
||||
* Процесс установки заключается в замене имеющихся локализационных файлов полученными и последующем запуске процедуры обновления iTop для перекомпиляции кода.
|
||||
* 1. Скопируйте с заменой два полученных файла из "itop-rus/dictionaries" в "путь/до/вашего/itop/dictionaries".
|
||||
* 2. Скопируйте с заменой полученные файлы "itop-rus/datamodels/2.x/название-модуля/ru.dict.название-модуля.php" в "путь/до/вашего/itop/datamodels/2.x/название-модуля".
|
||||
* 3. Перейдите по адресу "http://адрес/вашего/itop/setup", при этом файл "путь/до/вашего/itop/conf/production/config-itop.php" должен быть доступен для записи.
|
||||
* 4. На второй странице установщика выберите "Upgrade an existing iTop instance" и следуйте дальнейшим инструкциям установщика.
|
||||
*
|
||||
* Ответы на вопросы по установке и использованию переводов, а также на любые другие вопросы по iTop всегда можно получить на сайте сообщества iTop по-русски http://community.itop-itsm.ru.
|
||||
*
|
||||
*/
|
||||
|
||||
// Dictionnay conventions
|
||||
// Class:<class_name>
|
||||
// Class:<class_name>+
|
||||
// Class:<class_name>/Attribute:<attribute_code>
|
||||
// Class:<class_name>/Attribute:<attribute_code>+
|
||||
// Class:<class_name>/Attribute:<attribute_code>/Value:<value>
|
||||
// Class:<class_name>/Attribute:<attribute_code>/Value:<value>+
|
||||
// Class:<class_name>/Stimulus:<stimulus_code>
|
||||
// Class:<class_name>/Stimulus:<stimulus_code>+
|
||||
|
||||
//
|
||||
// Class: UserLocal
|
||||
//
|
||||
|
||||
Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Class:UserLocal' => 'Пользователь iTop',
|
||||
'Class:UserLocal+' => 'Пользователь, аутентифицируемый через iTop',
|
||||
'Class:UserLocal+' => 'Пользователь, аутентифицированный в iTop',
|
||||
'Class:UserLocal/Attribute:password' => 'Пароль',
|
||||
'Class:UserLocal/Attribute:password+' => 'Строка аутентификации пользователя',
|
||||
));
|
||||
));
|
||||
|
||||
|
||||
|
||||
?>
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Локализация интерфейса Combodo iTop подготовлена сообществом iTop по-русски http://community.itop-itsm.ru.
|
||||
*
|
||||
* @author Vladimir Kunin <v.b.kunin@gmail.com>
|
||||
* @link http://community.itop-itsm.ru iTop Russian Community
|
||||
* @link https://github.com/itop-itsm-ru/itop-rus
|
||||
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
|
||||
*
|
||||
*/
|
||||
|
||||
Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Attachments:TabTitle_Count' => 'Вложения (%1$d)',
|
||||
'Attachments:EmptyTabTitle' => 'Вложения',
|
||||
'Attachments:FieldsetTitle' => 'Вложения',
|
||||
'Attachments:DeleteBtn' => 'Удалить',
|
||||
'Attachments:History_File_Added' => 'Вложение %1$s добавлено.',
|
||||
'Attachments:History_File_Removed' => 'Вложение %1$s удалено.',
|
||||
'Attachments:AddAttachment' => 'Добавить вложение:',
|
||||
'Attachments:UploadNotAllowedOnThisSystem' => 'Загрузка файлов НЕ разрешена в этой системе. За подробностями обратитесь к администратору вашего iTop',
|
||||
'Attachment:Max_Go' => '(Максимальный размер файла: %1$s ГБ)',
|
||||
'Attachment:Max_Mo' => '(Максимальный размер файла: %1$s МБ)',
|
||||
'Attachment:Max_Ko' => '(Максимальный размер файла: %1$s кБ)',
|
||||
'Attachments:NoAttachment' => 'Нет вложений.',
|
||||
'Attachments:PreviewNotAvailable' => 'Предварительный просмотр не доступен для этого типа вложений.',
|
||||
));
|
||||
@@ -244,7 +244,6 @@ class BackupExec implements iScheduledProcess
|
||||
{
|
||||
break;
|
||||
}
|
||||
$iNextPos = false; // necessary on sundays
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Локализация интерфейса Combodo iTop подготовлена сообществом iTop по-русски http://community.itop-itsm.ru.
|
||||
*
|
||||
* @author Vladimir Kunin <v.b.kunin@gmail.com>
|
||||
* @link http://community.itop-itsm.ru iTop Russian Community
|
||||
* @link https://github.com/itop-itsm-ru/itop-rus
|
||||
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
|
||||
*
|
||||
*/
|
||||
|
||||
Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
|
||||
'bkp-backup-running' => 'Выполняется резервное копирование. Пожалуйста, подождите...',
|
||||
'bkp-restore-running' => 'Выполняется восстановление из резервной копии. Пожалуйста, подождите...',
|
||||
|
||||
'Menu:BackupStatus' => 'Резервное копирование',
|
||||
'bkp-status-title' => 'Резервное копирование по расписанию',
|
||||
'bkp-status-checks' => 'Настройки и проверки',
|
||||
'bkp-mysqldump-ok' => 'Утилита mysqldump найдена: %1$s',
|
||||
'bkp-mysqldump-notfound' => 'Утилиту mysqldump найти не удалось: %1$s - пожалуйста, убедитесь в том, что она установлена, и путь до директории с бинарными файлами добавлен в PATH, либо измените параметр mysql_bindir в файле конфигурации.',
|
||||
'bkp-mysqldump-issue' => 'Утилита mysqldump на может быть запущена (retcode=%1$d) Пожалуйста, убедитесь в том, что она установлена, и путь до директории с бинарными файлами добавлен в PATH, либо измените параметр mysql_bindir в файле конфигурации.',
|
||||
'bkp-missing-dir' => 'The target directory %1$s count not be found',
|
||||
'bkp-free-disk-space' => '<b>%1$s свободно</b> в %2$s',
|
||||
'bkp-dir-not-writeable' => '%1$s недоступен для записи',
|
||||
'bkp-wrong-format-spec' => 'Неправильный формат шаблона названия файлов резервных копий (%1$s). Будет использован шаблон по умолчанию: %2$s',
|
||||
'bkp-name-sample' => 'Название файлов резервных копий зависит от идентификатора БД, даты и времени. Пример: %1$s',
|
||||
'bkp-week-days' => 'Резервное копирование будет выполняться <b>каждый %1$s в %2$s</b>',
|
||||
'bkp-retention' => 'Не более <b>%1$d файлов резервных копий будут храниться</b> в целевом каталоге.',
|
||||
'bkp-next-to-delete' => 'Будет удалена при следующем запуске резервного копирования (см. параметр \"retention_count\")',
|
||||
'bkp-table-file' => 'Файл',
|
||||
'bkp-table-file+' => 'Только файлы с расширением .zip считаются файлами резервных копий.',
|
||||
'bkp-table-size' => 'Размер',
|
||||
'bkp-table-size+' => '',
|
||||
'bkp-table-actions' => 'Действия',
|
||||
'bkp-table-actions+' => '',
|
||||
'bkp-status-backups-auto' => 'Резервное копирование по расписанию',
|
||||
'bkp-status-backups-manual' => 'Резервное копирование вручную',
|
||||
'bkp-status-backups-none' => 'Резервных копий ещё нет',
|
||||
'bkp-next-backup' => 'Следующее резервное копирование будет выполняться в <b>%1$s</b> (%2$s) в %3$s',
|
||||
'bkp-button-backup-now' => 'Запустить сейчас!',
|
||||
'bkp-button-restore-now' => 'Восстановить!',
|
||||
'bkp-confirm-backup' => 'Пожалуйста, подтвердите, что вы хотите выполнить резервное копирование прямо сейчас.',
|
||||
'bkp-confirm-restore' => 'Пожалуйста, подтвердите, что вы хотите выполнить восстановление из резервной копии %1$s.',
|
||||
'bkp-wait-backup' => 'Пожалуйста, дождитесь завершения резервного копирования...',
|
||||
'bkp-wait-restore' => 'Пожалуйста, дождитесь завершения восстановления...',
|
||||
'bkp-success-restore' => 'Восстановление успешно завершено.',
|
||||
));
|
||||
?>
|
||||
@@ -2,39 +2,45 @@
|
||||
|
||||
/**
|
||||
* Локализация интерфейса Combodo iTop подготовлена сообществом iTop по-русски http://community.itop-itsm.ru.
|
||||
*
|
||||
* @author Vladimir Kunin <v.b.kunin@gmail.com>
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*
|
||||
* @author Vladimir Kunin <v.b.kunin@gmail.com>
|
||||
* @link http://community.itop-itsm.ru iTop Russian Community
|
||||
* @link https://github.com/itop-itsm-ru/itop-rus
|
||||
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
|
||||
*
|
||||
* Инструкция по установке
|
||||
*
|
||||
* Процесс установки заключается в замене имеющихся локализационных файлов полученными и последующем запуске процедуры обновления iTop для перекомпиляции кода.
|
||||
* 1. Скопируйте с заменой два полученных файла из "itop-rus/dictionaries" в "путь/до/вашего/itop/dictionaries".
|
||||
* 2. Скопируйте с заменой полученные файлы "itop-rus/datamodels/2.x/название-модуля/ru.dict.название-модуля.php" в "путь/до/вашего/itop/datamodels/2.x/название-модуля".
|
||||
* 3. Перейдите по адресу "http://адрес/вашего/itop/setup", при этом файл "путь/до/вашего/itop/conf/production/config-itop.php" должен быть доступен для записи.
|
||||
* 4. На второй странице установщика выберите "Upgrade an existing iTop instance" и следуйте дальнейшим инструкциям установщика.
|
||||
*
|
||||
* Ответы на вопросы по установке и использованию переводов, а также на любые другие вопросы по iTop всегда можно получить на сайте сообщества iTop по-русски http://community.itop-itsm.ru.
|
||||
*
|
||||
*/
|
||||
|
||||
Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Menu:ChangeManagement' => 'Управление изменениями',
|
||||
'Menu:Change:Overview' => 'Обзор',
|
||||
'Menu:Change:Overview+' => 'Управление изменениями - Обзор',
|
||||
'Menu:Change:Overview+' => '',
|
||||
'Menu:NewChange' => 'Новый запрос на изменение',
|
||||
'Menu:NewChange+' => 'Создание нового запроса на изменение',
|
||||
'Menu:SearchChanges' => 'Поиск изменений',
|
||||
'Menu:SearchChanges+' => 'Поиск запросов на изменение',
|
||||
'Menu:Change:Shortcuts' => 'Ярлыки',
|
||||
'Menu:Change:Shortcuts+' => 'Ярлыки',
|
||||
'Menu:WaitingAcceptance' => 'Ожидающие принятия',
|
||||
'Menu:WaitingAcceptance+' => 'Изменения, ожидающие принятия',
|
||||
'Menu:WaitingApproval' => 'Ожидающие утверждения',
|
||||
'Menu:WaitingApproval+' => 'Изменения, ожидающие утверждения',
|
||||
'Menu:Changes' => 'Открытые',
|
||||
'Menu:Change:Shortcuts+' => '',
|
||||
'Menu:WaitingAcceptance' => 'Изменения, ожидающие принятия',
|
||||
'Menu:WaitingAcceptance+' => '',
|
||||
'Menu:WaitingApproval' => 'Изменения, ожидающие утверждения',
|
||||
'Menu:WaitingApproval+' => '',
|
||||
'Menu:Changes' => 'Открытые изменения',
|
||||
'Menu:Changes+' => 'Все открытые изменения',
|
||||
'Menu:MyChanges' => 'Назначенные мне',
|
||||
'Menu:MyChanges+' => 'Изменения, назначенные мне',
|
||||
'Menu:MyChanges' => 'Изменения, назначенные на меня',
|
||||
'Menu:MyChanges+' => 'Изменения, назначенные на меня (как агента)',
|
||||
'UI-ChangeManagementOverview-ChangeByCategory-last-7-days' => 'Изменения по категориям за 7 дней',
|
||||
'UI-ChangeManagementOverview-Last-7-days' => 'Количество изменений за 7 дней',
|
||||
'UI-ChangeManagementOverview-ChangeByDomain-last-7-days' => 'Изменения по домену за 7 дней',
|
||||
'UI-ChangeManagementOverview-ChangeByStatus-last-7-days' => 'Изменения по статусу за 7 дней',
|
||||
'Tickets:Related:OpenChanges' => 'Открытые изменения',
|
||||
'Tickets:Related:RecentChanges' => 'Недавние изменения (72ч)',
|
||||
|
||||
));
|
||||
|
||||
// Dictionnay conventions
|
||||
@@ -83,7 +89,7 @@ Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Class:Change/Attribute:requestor_id+' => '',
|
||||
'Class:Change/Attribute:requestor_email' => 'Email инициатора запроса',
|
||||
'Class:Change/Attribute:requestor_email+' => '',
|
||||
'Class:Change/Attribute:creation_date' => 'Дата создания',
|
||||
'Class:Change/Attribute:creation_date' => 'Создан',
|
||||
'Class:Change/Attribute:creation_date+' => '',
|
||||
'Class:Change/Attribute:impact' => 'Критичность',
|
||||
'Class:Change/Attribute:impact+' => '',
|
||||
@@ -113,7 +119,7 @@ Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Class:Change/Attribute:fallback+' => '',
|
||||
'Class:Change/Attribute:parent_id' => 'Родительское изменение',
|
||||
'Class:Change/Attribute:parent_id+' => '',
|
||||
'Class:Change/Attribute:parent_name' => 'Родительское изменение',
|
||||
'Class:Change/Attribute:parent_name' => 'Имя родительского изменения',
|
||||
'Class:Change/Attribute:parent_name+' => '',
|
||||
'Class:Change/Attribute:related_request_list' => 'Связанные запросы',
|
||||
'Class:Change/Attribute:related_request_list+' => 'Связанные запросы',
|
||||
@@ -191,7 +197,7 @@ Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Class:ApprovedChange+' => '',
|
||||
'Class:ApprovedChange/Attribute:approval_date' => 'Дата утверждения',
|
||||
'Class:ApprovedChange/Attribute:approval_date+' => '',
|
||||
'Class:ApprovedChange/Attribute:approval_comment' => 'Комментарий утверждения',
|
||||
'Class:ApprovedChange/Attribute:approval_comment' => 'Коментарий утверждения',
|
||||
'Class:ApprovedChange/Attribute:approval_comment+' => '',
|
||||
'Class:ApprovedChange/Stimulus:ev_validate' => 'Подтвердить',
|
||||
'Class:ApprovedChange/Stimulus:ev_validate+' => '',
|
||||
@@ -207,7 +213,7 @@ Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Class:ApprovedChange/Stimulus:ev_approve+' => '',
|
||||
'Class:ApprovedChange/Stimulus:ev_replan' => 'Перепланировать',
|
||||
'Class:ApprovedChange/Stimulus:ev_replan+' => '',
|
||||
'Class:ApprovedChange/Stimulus:ev_notapprove' => 'Отклонить',
|
||||
'Class:ApprovedChange/Stimulus:ev_notapprove' => 'Отклонить утверждение',
|
||||
'Class:ApprovedChange/Stimulus:ev_notapprove+' => '',
|
||||
'Class:ApprovedChange/Stimulus:ev_implement' => 'Реализовать',
|
||||
'Class:ApprovedChange/Stimulus:ev_implement+' => '',
|
||||
@@ -281,4 +287,8 @@ Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Class:EmergencyChange/Stimulus:ev_monitor+' => '',
|
||||
'Class:EmergencyChange/Stimulus:ev_finish' => 'Закончить',
|
||||
'Class:EmergencyChange/Stimulus:ev_finish+' => '',
|
||||
));
|
||||
'Tickets:Related:OpenChanges' => 'Open changes~~',
|
||||
'Tickets:Related:RecentChanges' => 'Recent changes (72h)~~',
|
||||
));
|
||||
|
||||
?>
|
||||
|
||||
@@ -1,127 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Локализация интерфейса Combodo iTop подготовлена сообществом iTop по-русски http://community.itop-itsm.ru.
|
||||
*
|
||||
* @author Vladimir Kunin <v.b.kunin@gmail.com>
|
||||
* @link http://community.itop-itsm.ru iTop Russian Community
|
||||
* @link https://github.com/itop-itsm-ru/itop-rus
|
||||
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
|
||||
*
|
||||
*/
|
||||
|
||||
Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Menu:ChangeManagement' => 'Управление изменениями',
|
||||
'Menu:Change:Overview' => 'Обзор',
|
||||
'Menu:Change:Overview+' => 'Управление изменениями - Обзор',
|
||||
'Menu:NewChange' => 'Новый запрос на изменение',
|
||||
'Menu:NewChange+' => 'Создание нового запроса на изменение',
|
||||
'Menu:SearchChanges' => 'Поиск изменений',
|
||||
'Menu:SearchChanges+' => 'Поиск запросов на изменения',
|
||||
'Menu:Change:Shortcuts' => 'Ярлыки',
|
||||
'Menu:Change:Shortcuts+' => 'Ярлыки',
|
||||
'Menu:WaitingAcceptance' => 'Ожидающие принятия',
|
||||
'Menu:WaitingAcceptance+' => 'Изменения, ожидающие принятия',
|
||||
'Menu:WaitingApproval' => 'Ожидающие утверждения',
|
||||
'Menu:WaitingApproval+' => 'Изменения, ожидающие утверждения',
|
||||
'Menu:Changes' => 'Открытые',
|
||||
'Menu:Changes+' => 'Открытые изменения',
|
||||
'Menu:MyChanges' => 'Назначенные мне',
|
||||
'Menu:MyChanges+' => 'Изменения, назначенные мне',
|
||||
'UI-ChangeManagementOverview-ChangeByCategory-last-7-days' => 'Изменения по категориям за 7 дней',
|
||||
'UI-ChangeManagementOverview-Last-7-days' => 'Количество изменений за 7 дней',
|
||||
'UI-ChangeManagementOverview-ChangeByDomain-last-7-days' => 'Изменения по домену за 7 дней',
|
||||
'UI-ChangeManagementOverview-ChangeByStatus-last-7-days' => 'Изменения по статусу за 7 дней',
|
||||
));
|
||||
|
||||
// Dictionnay conventions
|
||||
// Class:<class_name>
|
||||
// Class:<class_name>+
|
||||
// Class:<class_name>/Attribute:<attribute_code>
|
||||
// Class:<class_name>/Attribute:<attribute_code>+
|
||||
// Class:<class_name>/Attribute:<attribute_code>/Value:<value>
|
||||
// Class:<class_name>/Attribute:<attribute_code>/Value:<value>+
|
||||
// Class:<class_name>/Stimulus:<stimulus_code>
|
||||
// Class:<class_name>/Stimulus:<stimulus_code>+
|
||||
|
||||
|
||||
//
|
||||
// Class: Change
|
||||
//
|
||||
|
||||
Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Class:Change' => 'Изменение',
|
||||
'Class:Change+' => '',
|
||||
'Class:Change/Attribute:status' => 'Статус',
|
||||
'Class:Change/Attribute:status+' => '',
|
||||
'Class:Change/Attribute:status/Value:new' => 'Новый',
|
||||
'Class:Change/Attribute:status/Value:new+' => '',
|
||||
'Class:Change/Attribute:status/Value:assigned' => 'Назначен',
|
||||
'Class:Change/Attribute:status/Value:assigned+' => '',
|
||||
'Class:Change/Attribute:status/Value:planned' => 'Запланировано',
|
||||
'Class:Change/Attribute:status/Value:planned+' => '',
|
||||
'Class:Change/Attribute:status/Value:rejected' => 'Отклонён',
|
||||
'Class:Change/Attribute:status/Value:rejected+' => '',
|
||||
'Class:Change/Attribute:status/Value:approved' => 'Утверждён',
|
||||
'Class:Change/Attribute:status/Value:approved+' => '',
|
||||
'Class:Change/Attribute:status/Value:closed' => 'Закрыт',
|
||||
'Class:Change/Attribute:status/Value:closed+' => '',
|
||||
'Class:Change/Attribute:category' => 'Категория',
|
||||
'Class:Change/Attribute:category+' => '',
|
||||
'Class:Change/Attribute:category/Value:application' => 'Приложение',
|
||||
'Class:Change/Attribute:category/Value:application+' => 'Приложение',
|
||||
'Class:Change/Attribute:category/Value:hardware' => 'Оборудование',
|
||||
'Class:Change/Attribute:category/Value:hardware+' => 'Оборудование',
|
||||
'Class:Change/Attribute:category/Value:network' => 'Сеть',
|
||||
'Class:Change/Attribute:category/Value:network+' => 'Сеть',
|
||||
'Class:Change/Attribute:category/Value:other' => 'Другое',
|
||||
'Class:Change/Attribute:category/Value:other+' => 'Другое',
|
||||
'Class:Change/Attribute:category/Value:software' => 'Программное обеспечение',
|
||||
'Class:Change/Attribute:category/Value:software+' => 'Программное обеспечение',
|
||||
'Class:Change/Attribute:category/Value:system' => 'Система',
|
||||
'Class:Change/Attribute:category/Value:system+' => 'Система',
|
||||
'Class:Change/Attribute:reject_reason' => 'Причина отклонения',
|
||||
'Class:Change/Attribute:reject_reason+' => '',
|
||||
'Class:Change/Attribute:changemanager_id' => 'Менеджер изменения',
|
||||
'Class:Change/Attribute:changemanager_id+' => '',
|
||||
'Class:Change/Attribute:changemanager_email' => 'Email менеджера',
|
||||
'Class:Change/Attribute:changemanager_email+' => '',
|
||||
'Class:Change/Attribute:parent_id' => 'Родительское изменение',
|
||||
'Class:Change/Attribute:parent_id+' => '',
|
||||
'Class:Change/Attribute:parent_name' => 'Родительское изменение',
|
||||
'Class:Change/Attribute:parent_name+' => '',
|
||||
'Class:Change/Attribute:creation_date' => 'Дата создания',
|
||||
'Class:Change/Attribute:creation_date+' => '',
|
||||
'Class:Change/Attribute:approval_date' => 'Дата утверждения',
|
||||
'Class:Change/Attribute:approval_date+' => '',
|
||||
'Class:Change/Attribute:fallback_plan' => 'План отката',
|
||||
'Class:Change/Attribute:fallback_plan+' => '',
|
||||
'Class:Change/Attribute:related_request_list' => 'Связанные запросы',
|
||||
'Class:Change/Attribute:related_request_list+' => 'Связанные запросы',
|
||||
'Class:Change/Attribute:related_incident_list' => 'Связанные инциденты',
|
||||
'Class:Change/Attribute:related_incident_list+' => 'Связанные инциденты',
|
||||
'Class:Change/Attribute:related_problems_list' => 'Связанные проблемы',
|
||||
'Class:Change/Attribute:related_problems_list+' => 'Связанные проблемы',
|
||||
'Class:Change/Attribute:child_changes_list' => 'Дочерние изменения',
|
||||
'Class:Change/Attribute:child_changes_list+' => 'Дочерние изменения',
|
||||
'Class:Change/Attribute:parent_id_friendlyname' => 'Родительское изменение',
|
||||
'Class:Change/Attribute:parent_id_friendlyname+' => '',
|
||||
'Class:Change/Stimulus:ev_assign' => 'Назначить',
|
||||
'Class:Change/Stimulus:ev_assign+' => '',
|
||||
'Class:Change/Stimulus:ev_plan' => 'Планировать',
|
||||
'Class:Change/Stimulus:ev_plan+' => '',
|
||||
'Class:Change/Stimulus:ev_reject' => 'Отклонить',
|
||||
'Class:Change/Stimulus:ev_reject+' => '',
|
||||
'Class:Change/Stimulus:ev_reopen' => 'Вновь открыть',
|
||||
'Class:Change/Stimulus:ev_reopen+' => '',
|
||||
'Class:Change/Stimulus:ev_approve' => 'Утвердить',
|
||||
'Class:Change/Stimulus:ev_approve+' => '',
|
||||
'Class:Change/Stimulus:ev_finish' => 'Закрыть',
|
||||
'Class:Change/Stimulus:ev_finish+' => '',
|
||||
'Class:Change/Attribute:outage' => 'Простой услуги',
|
||||
'Class:Change/Attribute:outage+' => '',
|
||||
'Class:Change/Attribute:outage/Value:no' => 'Нет',
|
||||
'Class:Change/Attribute:outage/Value:no+' => '',
|
||||
'Class:Change/Attribute:outage/Value:yes' => 'Да',
|
||||
'Class:Change/Attribute:outage/Value:yes+' => '',
|
||||
));
|
||||
@@ -552,7 +552,7 @@
|
||||
<static>false</static>
|
||||
<access>public</access>
|
||||
<type>Overload-DBObject</type>
|
||||
<code><![CDATA[ public function DBDeleteSingleObject()
|
||||
<code><![CDATA[ public function DBDeleteSingleObject(&$oDeletionPlan)
|
||||
{
|
||||
if (MetaModel::GetConfig()->Get('demo_mode'))
|
||||
{
|
||||
@@ -1582,8 +1582,7 @@
|
||||
$sStateAttCode = MetaModel::GetStateAttributeCode($sSubClass);
|
||||
if ($sStateAttCode != '')
|
||||
{
|
||||
// Todo: base the search condition on operational_status = 'ongoing' for a more flexible behavior
|
||||
$oSearch = DBSearch::FromOQL("SELECT $sSubClass AS t JOIN $sLnkClass AS lnk ON lnk.$sExtKeyToRemote = t.id WHERE lnk.$sExtKeyToMe = :myself AND t.$sStateAttCode NOT IN ('rejected', 'resolved', 'closed')", array('myself' => $this->GetKey()));
|
||||
$oSearch = DBSearch::FromOQL("SELECT $sSubClass AS t JOIN $sLnkClass AS lnk ON lnk.$sExtKeyToRemote = t.id WHERE $sExtKeyToMe = :myself AND $sStateAttCode NOT IN ('rejected', 'resolved', 'closed')", array('myself' => $this->GetKey()));
|
||||
$aSearches[$sSubClass] = $oSearch;
|
||||
|
||||
$oSet = new DBObjectSet($oSearch);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -105,7 +105,7 @@ try
|
||||
{
|
||||
$oP->add("<div class=\"header_message message_info\">Sorry, iTop is in <b>demonstration mode</b>: the configuration file cannot be edited.</div>");
|
||||
}
|
||||
else if (MetaModel::GetModuleSetting('itop-config', 'config_editor', '') == 'disabled')
|
||||
if (MetaModel::GetModuleSetting('itop-config', 'config_editor', '') == 'disabled')
|
||||
{
|
||||
$oP->add("<div class=\"header_message message_info\">iTop interactive edition of the configuration as been disabled. See <tt>'config_editor' => 'disabled'</tt> in the configuration file.</div>");
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ Dict::Add('DE DE', 'German', 'Deutsch', array(
|
||||
|
||||
'Menu:ConfigEditor' => 'Konfiguration',
|
||||
'config-edit-title' => 'Konfigurations-Editor',
|
||||
'config-edit-intro' => 'Seien sie bei der Bearbeitung der Konfigurationsdatei sehr vorsichtig.',
|
||||
'config-edit-intro' => 'Seien sie bei der Bearbeitung der Konfigurationsdatei sehr vorsichtig. Normalerweise sollten es ausreichen die Einträge im oberen Teil der Konfiguration zu bearbeiten (Bsp.: die globalen Konfigurations- und Moduleinstellungen).',
|
||||
'config-apply' => 'Anwenden',
|
||||
'config-cancel' => 'Zurücksetzen',
|
||||
'config-confirm-cancel' => 'Ihre Änderungen werden nicht gespeichert.',
|
||||
|
||||
@@ -10,7 +10,7 @@ Dict::Add('EN US', 'English', 'English', array(
|
||||
|
||||
'Menu:ConfigEditor' => 'Configuration',
|
||||
'config-edit-title' => 'Configuration File Editor',
|
||||
'config-edit-intro' => 'Be very cautious when editing the configuration file.',
|
||||
'config-edit-intro' => 'Be very cautious when editing the configuration file. In particular, only the upper items (i.e. the global configuration and modules settings) should be edited.',
|
||||
'config-apply' => 'Apply',
|
||||
'config-cancel' => 'Reset',
|
||||
'config-confirm-cancel' => 'Your changes will be lost.',
|
||||
|
||||
@@ -10,7 +10,7 @@ Dict::Add('FR FR', 'French', 'Français', array(
|
||||
|
||||
'Menu:ConfigEditor' => 'Configuration',
|
||||
'config-edit-title' => 'Editeur du Fichier de Configuration',
|
||||
'config-edit-intro' => 'Attention: une configuration incorrecte peut rendre iTop inopérant pour tous les utilisateurs!',
|
||||
'config-edit-intro' => 'Attention: une configuration incorrecte peut rendre iTop indisponible. En particulier, vous ne devriez éditer QUE les deux premiers éléments, à savoir la configuration globale et la configuration des modules.',
|
||||
'config-save' => 'Appliquer',
|
||||
'config-restore' => 'Réinitialiser',
|
||||
'config-confirm-cancel' => 'Vos modifications seront perdues.',
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Локализация интерфейса Combodo iTop подготовлена сообществом iTop по-русски http://community.itop-itsm.ru.
|
||||
*
|
||||
* @author Vladimir Kunin <v.b.kunin@gmail.com>
|
||||
* @link http://community.itop-itsm.ru iTop Russian Community
|
||||
* @link https://github.com/itop-itsm-ru/itop-rus
|
||||
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
|
||||
*
|
||||
*/
|
||||
|
||||
Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
|
||||
'Menu:ConfigEditor' => 'Конфигурация',
|
||||
'config-edit-title' => 'Редактор файла конфигурации',
|
||||
'config-edit-intro' => 'Будьте очень осторожны при редактировании файла конфигурации. В частности, могут быть отредактированы только верхние элементы (т.е. глобальная конфигурация и настройки модулей).',
|
||||
'config-apply' => 'Применить',
|
||||
'config-cancel' => 'Сбросить',
|
||||
'config-confirm-cancel' => 'Ваши изменения будут утеряны.',
|
||||
'config-no-change' => 'Изменений нет: файл не был изменён.',
|
||||
'config-parse-error' => 'Строка %2$d: %1$s.<br/>Файл не был обновлен.',
|
||||
'config-current-line' => 'Редактируемая строка: %1$s',
|
||||
));
|
||||
?>
|
||||
@@ -1229,7 +1229,7 @@
|
||||
if (!MetaModel::IsValidClass('UserRequest')) return true; // Do nothing
|
||||
|
||||
$oLog = $this->Get('public_log');
|
||||
$sLogPublic = $oLog->GetModifiedEntry('html');
|
||||
$sLogPublic = $oLog->GetModifiedEntry();
|
||||
if ($sLogPublic != '')
|
||||
{
|
||||
$sOQL = "SELECT UserRequest WHERE parent_incident_id=:ticket";
|
||||
@@ -1247,7 +1247,7 @@
|
||||
|
||||
}
|
||||
$oLog = $this->Get('private_log');
|
||||
$sLogPrivate = $oLog->GetModifiedEntry('html');
|
||||
$sLogPrivate = $oLog->GetModifiedEntry();
|
||||
if ($sLogPrivate != '')
|
||||
{
|
||||
$sOQL = "SELECT UserRequest WHERE parent_incident_id=:ticket";
|
||||
@@ -1274,7 +1274,7 @@
|
||||
<code><![CDATA[ public function UpdateChildIncidentLog()
|
||||
{
|
||||
$oLog = $this->Get('public_log');
|
||||
$sLogPublic = $oLog->GetModifiedEntry('html');
|
||||
$sLogPublic = $oLog->GetModifiedEntry();
|
||||
if ($sLogPublic != '')
|
||||
{
|
||||
$sOQL = "SELECT Incident WHERE parent_incident_id=:ticket";
|
||||
@@ -1292,7 +1292,7 @@
|
||||
|
||||
}
|
||||
$oLog = $this->Get('private_log');
|
||||
$sLogPrivate = $oLog->GetModifiedEntry('html');
|
||||
$sLogPrivate = $oLog->GetModifiedEntry();
|
||||
if ($sLogPrivate != '')
|
||||
{
|
||||
$sOQL = "SELECT Incident WHERE parent_incident_id=:ticket";
|
||||
|
||||
@@ -1,217 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Локализация интерфейса Combodo iTop подготовлена сообществом iTop по-русски http://community.itop-itsm.ru.
|
||||
*
|
||||
* @author Vladimir Kunin <v.b.kunin@gmail.com>
|
||||
* @link http://community.itop-itsm.ru iTop Russian Community
|
||||
* @link https://github.com/itop-itsm-ru/itop-rus
|
||||
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
|
||||
*
|
||||
*/
|
||||
|
||||
Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Menu:IncidentManagement' => 'Управление инцидентами',
|
||||
'Menu:IncidentManagement+' => 'Управление инцидентами',
|
||||
'Menu:Incident:Overview' => 'Обзор',
|
||||
'Menu:Incident:Overview+' => 'Обзор',
|
||||
'Menu:NewIncident' => 'Новый инцидент',
|
||||
'Menu:NewIncident+' => 'Создать новый инцидент',
|
||||
'Menu:SearchIncidents' => 'Поиск инцидентов',
|
||||
'Menu:SearchIncidents+' => 'Поиск инцидентов',
|
||||
'Menu:Incident:Shortcuts' => 'Ярлыки',
|
||||
'Menu:Incident:Shortcuts+' => 'Ярлыки',
|
||||
'Menu:Incident:MyIncidents' => 'Назначенные мне',
|
||||
'Menu:Incident:MyIncidents+' => 'Инциденты, назначенные мне (в качестве агента)',
|
||||
'Menu:Incident:EscalatedIncidents' => 'Эскалированные',
|
||||
'Menu:Incident:EscalatedIncidents+' => 'Эскалированные инциденты',
|
||||
'Menu:Incident:OpenIncidents' => 'Открытые',
|
||||
'Menu:Incident:OpenIncidents+' => 'Открытые инциденты',
|
||||
'UI-IncidentManagementOverview-IncidentByPriority-last-14-days' => 'Инциденты по приоритету за 14 дней',
|
||||
'UI-IncidentManagementOverview-Last-14-days' => 'Количество инцидентов за 14 дней',
|
||||
'UI-IncidentManagementOverview-OpenIncidentByStatus' => 'Открытые инциденты по статусу',
|
||||
'UI-IncidentManagementOverview-OpenIncidentByAgent' => 'Открытые инциденты по агенту',
|
||||
'UI-IncidentManagementOverview-OpenIncidentByCustomer' => 'Открытые инциденты по заказчику',
|
||||
));
|
||||
|
||||
//
|
||||
// Class: Incident
|
||||
//
|
||||
|
||||
Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Class:Incident' => 'Инцидент',
|
||||
'Class:Incident+' => '',
|
||||
'Class:Incident/Attribute:status' => 'Статус',
|
||||
'Class:Incident/Attribute:status+' => '',
|
||||
'Class:Incident/Attribute:status/Value:new' => 'Новый',
|
||||
'Class:Incident/Attribute:status/Value:new+' => '',
|
||||
'Class:Incident/Attribute:status/Value:escalated_tto' => 'Эскалация TTO',
|
||||
'Class:Incident/Attribute:status/Value:escalated_tto+' => '',
|
||||
'Class:Incident/Attribute:status/Value:assigned' => 'Назначен',
|
||||
'Class:Incident/Attribute:status/Value:assigned+' => '',
|
||||
'Class:Incident/Attribute:status/Value:escalated_ttr' => 'Эскалация TTR',
|
||||
'Class:Incident/Attribute:status/Value:escalated_ttr+' => '',
|
||||
'Class:Incident/Attribute:status/Value:waiting_for_approval' => 'Ожидание утверждения',
|
||||
'Class:Incident/Attribute:status/Value:waiting_for_approval+' => '',
|
||||
'Class:Incident/Attribute:status/Value:pending' => 'В ожидании',
|
||||
'Class:Incident/Attribute:status/Value:pending+' => '',
|
||||
'Class:Incident/Attribute:status/Value:resolved' => 'Решенный',
|
||||
'Class:Incident/Attribute:status/Value:resolved+' => '',
|
||||
'Class:Incident/Attribute:status/Value:closed' => 'Закрыт',
|
||||
'Class:Incident/Attribute:status/Value:closed+' => '',
|
||||
'Class:Incident/Attribute:impact' => 'Влияние',
|
||||
'Class:Incident/Attribute:impact+' => '',
|
||||
'Class:Incident/Attribute:impact/Value:1' => 'Департамент',
|
||||
'Class:Incident/Attribute:impact/Value:1+' => '',
|
||||
'Class:Incident/Attribute:impact/Value:2' => 'Служба',
|
||||
'Class:Incident/Attribute:impact/Value:2+' => '',
|
||||
'Class:Incident/Attribute:impact/Value:3' => 'Персона',
|
||||
'Class:Incident/Attribute:impact/Value:3+' => '',
|
||||
'Class:Incident/Attribute:priority' => 'Приоритет',
|
||||
'Class:Incident/Attribute:priority+' => '',
|
||||
'Class:Incident/Attribute:priority/Value:1' => 'Критический',
|
||||
'Class:Incident/Attribute:priority/Value:1+' => 'Критический',
|
||||
'Class:Incident/Attribute:priority/Value:2' => 'Высокий',
|
||||
'Class:Incident/Attribute:priority/Value:2+' => 'Высокий',
|
||||
'Class:Incident/Attribute:priority/Value:3' => 'Средний',
|
||||
'Class:Incident/Attribute:priority/Value:3+' => 'Средний',
|
||||
'Class:Incident/Attribute:priority/Value:4' => 'Низкий',
|
||||
'Class:Incident/Attribute:priority/Value:4+' => 'Низкий',
|
||||
'Class:Incident/Attribute:urgency' => 'Срочность',
|
||||
'Class:Incident/Attribute:urgency+' => '',
|
||||
'Class:Incident/Attribute:urgency/Value:1' => 'Критическая',
|
||||
'Class:Incident/Attribute:urgency/Value:1+' => 'Критическая',
|
||||
'Class:Incident/Attribute:urgency/Value:2' => 'Высокая',
|
||||
'Class:Incident/Attribute:urgency/Value:2+' => 'Высокая',
|
||||
'Class:Incident/Attribute:urgency/Value:3' => 'Средняя',
|
||||
'Class:Incident/Attribute:urgency/Value:3+' => 'Средняя',
|
||||
'Class:Incident/Attribute:urgency/Value:4' => 'Низкая',
|
||||
'Class:Incident/Attribute:urgency/Value:4+' => 'Низкая',
|
||||
'Class:Incident/Attribute:origin' => 'Источник',
|
||||
'Class:Incident/Attribute:origin+' => '',
|
||||
'Class:Incident/Attribute:origin/Value:mail' => 'Почта',
|
||||
'Class:Incident/Attribute:origin/Value:mail+' => 'Почта',
|
||||
'Class:Incident/Attribute:origin/Value:monitoring' => 'Мониторинг',
|
||||
'Class:Incident/Attribute:origin/Value:monitoring+' => 'Мониторинг',
|
||||
'Class:Incident/Attribute:origin/Value:phone' => 'Телефон',
|
||||
'Class:Incident/Attribute:origin/Value:phone+' => 'Телефон',
|
||||
'Class:Incident/Attribute:origin/Value:portal' => 'Портал',
|
||||
'Class:Incident/Attribute:origin/Value:portal+' => 'Портал',
|
||||
'Class:Incident/Attribute:service_id' => 'Услуга',
|
||||
'Class:Incident/Attribute:service_id+' => '',
|
||||
'Class:Incident/Attribute:service_name' => 'Услуга',
|
||||
'Class:Incident/Attribute:service_name+' => '',
|
||||
'Class:Incident/Attribute:servicesubcategory_id' => 'Подкатегория',
|
||||
'Class:Incident/Attribute:servicesubcategory_id+' => 'Подкатегория услуги',
|
||||
'Class:Incident/Attribute:servicesubcategory_name' => 'Подкатегория услуги',
|
||||
'Class:Incident/Attribute:servicesubcategory_name+' => '',
|
||||
'Class:Incident/Attribute:escalation_flag' => '«Флаг эскалации',
|
||||
'Class:Incident/Attribute:escalation_flag+' => 'Флаг повышенного приоритета',
|
||||
'Class:Incident/Attribute:escalation_flag/Value:no' => 'Нет',
|
||||
'Class:Incident/Attribute:escalation_flag/Value:no+' => 'Нет',
|
||||
'Class:Incident/Attribute:escalation_flag/Value:yes' => 'Да',
|
||||
'Class:Incident/Attribute:escalation_flag/Value:yes+' => 'Да',
|
||||
'Class:Incident/Attribute:escalation_reason' => 'Причина эскалации',
|
||||
'Class:Incident/Attribute:escalation_reason+' => '',
|
||||
'Class:Incident/Attribute:assignment_date' => 'Дата назначения',
|
||||
'Class:Incident/Attribute:assignment_date+' => '',
|
||||
'Class:Incident/Attribute:resolution_date' => 'Дата решения',
|
||||
'Class:Incident/Attribute:resolution_date+' => '',
|
||||
'Class:Incident/Attribute:last_pending_date' => 'Дата последнего ожидания',
|
||||
'Class:Incident/Attribute:last_pending_date+' => '',
|
||||
'Class:Incident/Attribute:cumulatedpending' => 'Накопленное ожидание',
|
||||
'Class:Incident/Attribute:cumulatedpending+' => '',
|
||||
'Class:Incident/Attribute:tto' => 'TTO',
|
||||
'Class:Incident/Attribute:tto+' => '',
|
||||
'Class:Incident/Attribute:ttr' => 'TTR',
|
||||
'Class:Incident/Attribute:ttr+' => '',
|
||||
'Class:Incident/Attribute:tto_escalation_deadline' => 'Срок TTO',
|
||||
'Class:Incident/Attribute:tto_escalation_deadline+' => 'Крайний срок назаначения агента (принятия в работу) по текущему SLA',
|
||||
'Class:Incident/Attribute:sla_tto_passed' => 'SLA TTO пропущено',
|
||||
'Class:Incident/Attribute:sla_tto_passed+' => '',
|
||||
'Class:Incident/Attribute:sla_tto_over' => 'SLA TTO превышено',
|
||||
'Class:Incident/Attribute:sla_tto_over+' => '',
|
||||
'Class:Incident/Attribute:ttr_escalation_deadline' => 'Срок TTR',
|
||||
'Class:Incident/Attribute:ttr_escalation_deadline+' => 'Крайний срок решения по текущему SLA',
|
||||
'Class:Incident/Attribute:sla_ttr_passed' => 'SLA TTR пропущено',
|
||||
'Class:Incident/Attribute:sla_ttr_passed+' => '',
|
||||
'Class:Incident/Attribute:sla_ttr_over' => 'SLA TTR превышено',
|
||||
'Class:Incident/Attribute:sla_ttr_over+' => '',
|
||||
'Class:Incident/Attribute:time_spent' => 'Время на решение',
|
||||
'Class:Incident/Attribute:time_spent+' => '',
|
||||
'Class:Incident/Attribute:resolution_code' => 'Код решения',
|
||||
'Class:Incident/Attribute:resolution_code+' => '',
|
||||
'Class:Incident/Attribute:resolution_code/Value:assistance' => 'Помощь',
|
||||
'Class:Incident/Attribute:resolution_code/Value:assistance+' => 'Помощь',
|
||||
'Class:Incident/Attribute:resolution_code/Value:bug fixed' => 'Исправление ошибки',
|
||||
'Class:Incident/Attribute:resolution_code/Value:bug fixed+' => 'Исправление ошибки',
|
||||
'Class:Incident/Attribute:resolution_code/Value:hardware repair' => 'Ремонт оборудования',
|
||||
'Class:Incident/Attribute:resolution_code/Value:hardware repair+' => 'Ремонт оборудования',
|
||||
'Class:Incident/Attribute:resolution_code/Value:other' => 'Другое',
|
||||
'Class:Incident/Attribute:resolution_code/Value:other+' => 'Другое',
|
||||
'Class:Incident/Attribute:resolution_code/Value:software patch' => 'Патч ПО',
|
||||
'Class:Incident/Attribute:resolution_code/Value:software patch+' => 'Патч ПО',
|
||||
'Class:Incident/Attribute:resolution_code/Value:system update' => 'Обновление системы',
|
||||
'Class:Incident/Attribute:resolution_code/Value:system update+' => 'Обновление системы',
|
||||
'Class:Incident/Attribute:resolution_code/Value:training' => 'Обучение',
|
||||
'Class:Incident/Attribute:resolution_code/Value:training+' => 'Обучение',
|
||||
'Class:Incident/Attribute:solution' => 'Описание решения',
|
||||
'Class:Incident/Attribute:solution+' => '',
|
||||
'Class:Incident/Attribute:pending_reason' => 'Причина ожидания',
|
||||
'Class:Incident/Attribute:pending_reason+' => '',
|
||||
'Class:Incident/Attribute:parent_incident_id' => 'Родительский инцидент',
|
||||
'Class:Incident/Attribute:parent_incident_id+' => '',
|
||||
'Class:Incident/Attribute:parent_problem_id' => 'Родительская проблема',
|
||||
'Class:Incident/Attribute:parent_problem_id+' => '',
|
||||
'Class:Incident/Attribute:parent_problem_ref' => 'Родительская проблема',
|
||||
'Class:Incident/Attribute:parent_problem_ref+' => '',
|
||||
'Class:Incident/Attribute:parent_incident_ref' => 'Родительский инцидент',
|
||||
'Class:Incident/Attribute:parent_incident_ref+' => '',
|
||||
'Class:Incident/Attribute:parent_change_id' => 'Родительское изменение',
|
||||
'Class:Incident/Attribute:parent_change_id+' => '',
|
||||
'Class:Incident/Attribute:parent_change_ref' => 'Родительское изменение',
|
||||
'Class:Incident/Attribute:parent_change_ref+' => '',
|
||||
'Class:Incident/Attribute:child_incidents_list' => 'Дочерние инциденты',
|
||||
'Class:Incident/Attribute:child_incidents_list+' => 'Все инциденты, связанные с этим инцидентом',
|
||||
'Class:Incident/Attribute:related_request_list' => 'Запросы',
|
||||
'Class:Incident/Attribute:related_request_list+' => 'Все пользовательские запросы, связанные с этим инцидентом',
|
||||
'Class:Incident/Attribute:public_log' => 'Общий журнал',
|
||||
'Class:Incident/Attribute:public_log+' => 'Информация в общем журнале доступна для пользователей портала',
|
||||
'Class:Incident/Attribute:user_satisfaction' => 'Удовлетворенность пользователя',
|
||||
'Class:Incident/Attribute:user_satisfaction+' => '',
|
||||
'Class:Incident/Attribute:user_satisfaction/Value:1' => 'Очень доволен',
|
||||
'Class:Incident/Attribute:user_satisfaction/Value:1+' => 'Очень доволен',
|
||||
'Class:Incident/Attribute:user_satisfaction/Value:2' => 'Вполне доволен',
|
||||
'Class:Incident/Attribute:user_satisfaction/Value:2+' => 'Вполне доволен',
|
||||
'Class:Incident/Attribute:user_satisfaction/Value:3' => 'Скорее недоволен',
|
||||
'Class:Incident/Attribute:user_satisfaction/Value:3+' => 'Скорее недоволен',
|
||||
'Class:Incident/Attribute:user_satisfaction/Value:4' => 'Очень недоволен',
|
||||
'Class:Incident/Attribute:user_satisfaction/Value:4+' => 'Очень недоволен',
|
||||
'Class:Incident/Attribute:user_comment' => 'Комментарий пользователя',
|
||||
'Class:Incident/Attribute:user_comment+' => '',
|
||||
'Class:Incident/Attribute:parent_incident_id_friendlyname' => 'Родительский инцидент',
|
||||
'Class:Incident/Attribute:parent_incident_id_friendlyname+' => '',
|
||||
'Class:Incident/Stimulus:ev_assign' => 'Назначить',
|
||||
'Class:Incident/Stimulus:ev_assign+' => '',
|
||||
'Class:Incident/Stimulus:ev_reassign' => 'Переназначить',
|
||||
'Class:Incident/Stimulus:ev_reassign+' => '',
|
||||
'Class:Incident/Stimulus:ev_pending' => 'В ожидание',
|
||||
'Class:Incident/Stimulus:ev_pending+' => '',
|
||||
'Class:Incident/Stimulus:ev_timeout' => 'Таймаут',
|
||||
'Class:Incident/Stimulus:ev_timeout+' => '',
|
||||
'Class:Incident/Stimulus:ev_autoresolve' => 'Автоматическое решение',
|
||||
'Class:Incident/Stimulus:ev_autoresolve+' => '',
|
||||
'Class:Incident/Stimulus:ev_autoclose' => 'Автоматическое закрытие',
|
||||
'Class:Incident/Stimulus:ev_autoclose+' => '',
|
||||
'Class:Incident/Stimulus:ev_resolve' => 'Отметить как решенный',
|
||||
'Class:Incident/Stimulus:ev_resolve+' => '',
|
||||
'Class:Incident/Stimulus:ev_close' => 'Закрыть',
|
||||
'Class:Incident/Stimulus:ev_close+' => '',
|
||||
'Class:Incident/Stimulus:ev_reopen' => 'Вновь открыть',
|
||||
'Class:Incident/Stimulus:ev_reopen+' => '',
|
||||
'Class:Incident/Error:CannotAssignParentIncidentIdToSelf' => 'Невозможно назначить этот же инцидент в качестве родительского',
|
||||
|
||||
'Class:Incident/Method:ResolveChildTickets' => 'ResolveChildTickets',
|
||||
'Class:Incident/Method:ResolveChildTickets+' => 'Cascade the resolution to child ticket (ev_autoresolve), and align the following characteristics: service, team, agent, resolution info',
|
||||
'Tickets:Related:OpenIncidents' => 'Открытые инциденты',
|
||||
));
|
||||
@@ -622,7 +622,7 @@
|
||||
<parent_att/>
|
||||
<name_att/>
|
||||
<tooltip_att/>
|
||||
<title>Class:FAQCategory</title>
|
||||
<title>Catégories</title>
|
||||
<actions/>
|
||||
<levels>
|
||||
<level id="1">
|
||||
@@ -630,7 +630,7 @@
|
||||
<parent_att>category_id</parent_att>
|
||||
<name_att>title</name_att>
|
||||
<tooltip_att>summary</tooltip_att>
|
||||
<title>Class:FAQ</title>
|
||||
<title>FAQs</title>
|
||||
<fields>
|
||||
<field id="error_code"/>
|
||||
<field id="key_words">
|
||||
|
||||
@@ -125,8 +125,5 @@ Dict::Add('DE DE', 'German', 'Deutsch', array(
|
||||
'Class:lnkDocumentToError/Attribute:error_name+' => '',
|
||||
'Class:FAQ/Attribute:category_name' => 'Kategoriename',
|
||||
'Class:FAQ/Attribute:category_name+' => '',
|
||||
'Brick:Portal:FAQ:Menu' => 'FAQ',
|
||||
'Brick:Portal:FAQ:Title' => 'Oft gestellte Fragen (FAQs)',
|
||||
'Brick:Portal:FAQ:Title+' => '<p>In Eile?</p><p>Sehen Sie sich die meistgestellten Fragen an (FAQs) und finden Sie (eventuell) die Antwort direkt dort.</p>',
|
||||
));
|
||||
?>
|
||||
|
||||
@@ -187,8 +187,5 @@ Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
|
||||
'Menu:FAQ' => 'Preguntas y Respuestas Frecuentes',
|
||||
'Menu:FAQ+' => 'Preguntas y Respuestas Frecuentes',
|
||||
|
||||
'Brick:Portal:FAQ:Menu' => 'FAQ',
|
||||
'Brick:Portal:FAQ:Title' => 'Preguntas y Respuestas Frecuentes',
|
||||
'Brick:Portal:FAQ:Title+' => '<p>¿En una prisa?</p><p>Vea la lista de las preguntas más comunes y encontrará (tal vez) la respuesta inmediata a sus necesidades.</p>',
|
||||
));
|
||||
?>
|
||||
|
||||
@@ -2,14 +2,48 @@
|
||||
|
||||
/**
|
||||
* Локализация интерфейса Combodo iTop подготовлена сообществом iTop по-русски http://community.itop-itsm.ru.
|
||||
*
|
||||
* @author Vladimir Kunin <v.b.kunin@gmail.com>
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*
|
||||
* @author Vladimir Kunin <v.b.kunin@gmail.com>
|
||||
* @link http://community.itop-itsm.ru iTop Russian Community
|
||||
* @link https://github.com/itop-itsm-ru/itop-rus
|
||||
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
|
||||
*
|
||||
* Инструкция по установке
|
||||
*
|
||||
* Процесс установки заключается в замене имеющихся локализационных файлов полученными и последующем запуске процедуры обновления iTop для перекомпиляции кода.
|
||||
* 1. Скопируйте с заменой два полученных файла из "itop-rus/dictionaries" в "путь/до/вашего/itop/dictionaries".
|
||||
* 2. Скопируйте с заменой полученные файлы "itop-rus/datamodels/2.x/название-модуля/ru.dict.название-модуля.php" в "путь/до/вашего/itop/datamodels/2.x/название-модуля".
|
||||
* 3. Перейдите по адресу "http://адрес/вашего/itop/setup", при этом файл "путь/до/вашего/itop/conf/production/config-itop.php" должен быть доступен для записи.
|
||||
* 4. На второй странице установщика выберите "Upgrade an existing iTop instance" и следуйте дальнейшим инструкциям установщика.
|
||||
*
|
||||
* Ответы на вопросы по установке и использованию переводов, а также на любые другие вопросы по iTop всегда можно получить на сайте сообщества iTop по-русски http://community.itop-itsm.ru.
|
||||
*
|
||||
*/
|
||||
|
||||
// Dictionnay conventions
|
||||
// Class:<class_name>
|
||||
// Class:<class_name>+
|
||||
// Class:<class_name>/Attribute:<attribute_code>
|
||||
// Class:<class_name>/Attribute:<attribute_code>+
|
||||
// Class:<class_name>/Attribute:<attribute_code>/Value:<value>
|
||||
// Class:<class_name>/Attribute:<attribute_code>/Value:<value>+
|
||||
// Class:<class_name>/Stimulus:<stimulus_code>
|
||||
// Class:<class_name>/Stimulus:<stimulus_code>+
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Classes in 'bizmodel'
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
||||
// Dictionnay conventions
|
||||
// Class:<class_name>
|
||||
// Class:<class_name>+
|
||||
// Class:<class_name>/Attribute:<attribute_code>
|
||||
// Class:<class_name>/Attribute:<attribute_code>+
|
||||
// Class:<class_name>/Attribute:<attribute_code>/Value:<value>
|
||||
// Class:<class_name>/Attribute:<attribute_code>/Value:<value>+
|
||||
// Class:<class_name>/Stimulus:<stimulus_code>
|
||||
// Class:<class_name>/Stimulus:<stimulus_code>+
|
||||
|
||||
//
|
||||
// Class: KnownError
|
||||
//
|
||||
@@ -21,11 +55,11 @@ Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Class:KnownError/Attribute:name+' => '',
|
||||
'Class:KnownError/Attribute:org_id' => 'Организация',
|
||||
'Class:KnownError/Attribute:org_id+' => '',
|
||||
'Class:KnownError/Attribute:cust_name' => 'Организация',
|
||||
'Class:KnownError/Attribute:cust_name' => 'Имя клиента',
|
||||
'Class:KnownError/Attribute:cust_name+' => '',
|
||||
'Class:KnownError/Attribute:problem_id' => 'Проблема',
|
||||
'Class:KnownError/Attribute:problem_id+' => '',
|
||||
'Class:KnownError/Attribute:problem_ref' => 'Проблема',
|
||||
'Class:KnownError/Attribute:problem_ref' => 'Ссылка на проблему',
|
||||
'Class:KnownError/Attribute:problem_ref+' => '',
|
||||
'Class:KnownError/Attribute:symptom' => 'Проявление',
|
||||
'Class:KnownError/Attribute:symptom+' => '',
|
||||
@@ -68,11 +102,11 @@ Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Class:lnkErrorToFunctionalCI+' => 'Infra related to a known error',
|
||||
'Class:lnkErrorToFunctionalCI/Attribute:functionalci_id' => 'КЕ',
|
||||
'Class:lnkErrorToFunctionalCI/Attribute:functionalci_id+' => '',
|
||||
'Class:lnkErrorToFunctionalCI/Attribute:functionalci_name' => 'КЕ',
|
||||
'Class:lnkErrorToFunctionalCI/Attribute:functionalci_name' => 'Имя КЕ',
|
||||
'Class:lnkErrorToFunctionalCI/Attribute:functionalci_name+' => '',
|
||||
'Class:lnkErrorToFunctionalCI/Attribute:error_id' => 'Известная ошибка',
|
||||
'Class:lnkErrorToFunctionalCI/Attribute:error_id+' => '',
|
||||
'Class:lnkErrorToFunctionalCI/Attribute:error_name' => 'Известная ошибка',
|
||||
'Class:lnkErrorToFunctionalCI/Attribute:error_name' => 'Имя известной ошибки',
|
||||
'Class:lnkErrorToFunctionalCI/Attribute:error_name+' => '',
|
||||
'Class:lnkErrorToFunctionalCI/Attribute:reason' => 'Причина',
|
||||
'Class:lnkErrorToFunctionalCI/Attribute:reason+' => '',
|
||||
@@ -87,11 +121,11 @@ Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Class:lnkDocumentToError+' => 'A link between a document and a known error',
|
||||
'Class:lnkDocumentToError/Attribute:document_id' => 'Документ',
|
||||
'Class:lnkDocumentToError/Attribute:document_id+' => '',
|
||||
'Class:lnkDocumentToError/Attribute:document_name' => 'Документ',
|
||||
'Class:lnkDocumentToError/Attribute:document_name' => 'Имя документа',
|
||||
'Class:lnkDocumentToError/Attribute:document_name+' => '',
|
||||
'Class:lnkDocumentToError/Attribute:error_id' => 'Известная ошибка',
|
||||
'Class:lnkDocumentToError/Attribute:error_id+' => '',
|
||||
'Class:lnkDocumentToError/Attribute:error_name' => 'Известная ошибка',
|
||||
'Class:lnkDocumentToError/Attribute:error_name' => 'Часто задаваемые вопросы',
|
||||
'Class:lnkDocumentToError/Attribute:error_name+' => '',
|
||||
'Class:lnkDocumentToError/Attribute:link_type' => 'Тип связи',
|
||||
'Class:lnkDocumentToError/Attribute:link_type+' => '',
|
||||
@@ -112,7 +146,7 @@ Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Class:FAQ/Attribute:description+' => '',
|
||||
'Class:FAQ/Attribute:category_id' => 'Категория',
|
||||
'Class:FAQ/Attribute:category_id+' => '',
|
||||
'Class:FAQ/Attribute:category_name' => 'Категория',
|
||||
'Class:FAQ/Attribute:category_name' => 'Имя категории',
|
||||
'Class:FAQ/Attribute:category_name+' => '',
|
||||
'Class:FAQ/Attribute:error_code' => 'Код ошибки',
|
||||
'Class:FAQ/Attribute:error_code+' => '',
|
||||
@@ -125,31 +159,27 @@ Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
//
|
||||
|
||||
Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Class:FAQCategory' => 'Категории FAQ',
|
||||
'Class:FAQCategory+' => 'Категории FAQ',
|
||||
'Class:FAQCategory/Attribute:name' => 'Название',
|
||||
'Class:FAQCategory' => 'Категории ЧаВо',
|
||||
'Class:FAQCategory+' => 'Category for FAQ',
|
||||
'Class:FAQCategory/Attribute:name' => 'Имя',
|
||||
'Class:FAQCategory/Attribute:name+' => '',
|
||||
'Class:FAQCategory/Attribute:faq_list' => 'FAQ',
|
||||
'Class:FAQCategory/Attribute:faq_list+' => 'Связанные FAQ',
|
||||
'Class:FAQCategory/Attribute:faq_list' => 'ЧаВо',
|
||||
'Class:FAQCategory/Attribute:faq_list+' => 'All the frequently asked questions related to this category',
|
||||
));
|
||||
|
||||
Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Menu:ProblemManagement' => 'Управление проблемами',
|
||||
'Menu:ProblemManagement+' => 'Управление проблемами',
|
||||
'Menu:Problem:Shortcuts' => 'Ярлыки',
|
||||
'Menu:NewError' => 'Новая известная ошибка',
|
||||
'Menu:NewError+' => 'Создать новую известную ошибку',
|
||||
'Menu:SearchError' => 'Поиск известных ошибок',
|
||||
'Menu:SearchError+' => 'Поиск известных ошибок',
|
||||
'Menu:Problem:KnownErrors' => 'Известные ошибки',
|
||||
'Menu:Problem:KnownErrors+' => 'База известных ошибок',
|
||||
'Menu:ProblemManagement' => 'Problem Management',
|
||||
'Menu:ProblemManagement+' => 'Problem Management',
|
||||
'Menu:Problem:Shortcuts' => 'Shortcuts',
|
||||
'Menu:NewError' => 'Создать известную ошибку',
|
||||
'Menu:NewError+' => 'Creation of a new known error',
|
||||
'Menu:SearchError' => 'Найти известную ошибку',
|
||||
'Menu:SearchError+' => 'Search for known errors',
|
||||
'Menu:Problem:KnownErrors' => 'Известные ошибки',
|
||||
'Menu:Problem:KnownErrors+' => 'База известных ошибок',
|
||||
'Menu:FAQCategory' => 'Категории FAQ',
|
||||
'Menu:FAQCategory+' => 'Категории FAQ',
|
||||
'Menu:FAQ' => 'FAQ',
|
||||
'Menu:FAQ+' => 'Часто задаваемые вопросы',
|
||||
|
||||
'Brick:Portal:FAQ:Menu' => 'FAQ',
|
||||
'Brick:Portal:FAQ:Title' => 'Часто задаваемые вопросы',
|
||||
'Brick:Portal:FAQ:Title+' => '<p>Торопитесь?</p><p>Проверьте список часто задаваемых вопросов, возможно, ответ уже есть.</p>',
|
||||
|
||||
));
|
||||
));
|
||||
?>
|
||||
|
||||
@@ -40,15 +40,13 @@ Dict::Add('CS CZ', 'Czech', 'Čeština', array(
|
||||
'Portal:Button:Add' => 'Přidat',
|
||||
'Portal:Button:Remove' => 'Odebrat',
|
||||
'Portal:Button:Delete' => 'Smazat',
|
||||
'Portal:EnvironmentBanner:Title' => 'You are currently in <strong>%1$s</strong> mode~~',
|
||||
'Portal:EnvironmentBanner:GoToProduction' => 'Go back to PRODUCTION mode~~',
|
||||
'Error:HTTP:404' => 'Stránka nenalezena',
|
||||
'Error:HTTP:404' => 'Stránka nenalezena',
|
||||
'Error:HTTP:500' => 'Jejda! Nastal problém',
|
||||
'Error:HTTP:GetHelp' => 'Kontaktujte prosím administrátora, pokud problém přetrvá.',
|
||||
'Error:XHR:Fail' => 'Data se nepodařilo načíst, kontaktujte prosím administrátora.',
|
||||
'Portal:Datatables:Language:Processing' => 'Počkejte prosím',
|
||||
'Portal:Datatables:Language:Search' => 'Filtr :',
|
||||
'Portal:Datatables:Language:LengthMenu' => 'Zobrazit _MENU_ položek na stránku',
|
||||
'Portal:Datatables:Language:Search' => 'filtr :',
|
||||
'Portal:Datatables:Language:LengthMenu' => 'Zobrazit _MENU_ položek na stránku',
|
||||
'Portal:Datatables:Language:ZeroRecords' => 'Žádný výsledek',
|
||||
'Portal:Datatables:Language:Info' => 'Stránka _PAGE_ z _PAGES_',
|
||||
'Portal:Datatables:Language:InfoEmpty' => 'Žádná informace',
|
||||
@@ -63,9 +61,6 @@ Dict::Add('CS CZ', 'Czech', 'Čeština', array(
|
||||
'Portal:Datatables:Language:Sort:Descending' => 'řadit sestupně',
|
||||
'Portal:Autocomplete:NoResult' => 'Žádná data',
|
||||
'Portal:Attachments:DropZone:Message' => 'Přesuňte soubory myší pro vložení',
|
||||
'Portal:File:None' => 'No file',
|
||||
'Portal:File:DisplayInfo' => '<a href="%2$s" class="file_download_link">%1$s</a>',
|
||||
'Portal:File:DisplayInfo+' => '%1$s (%2$s) <a href="%3$s" class="file_open_link" target="_blank">Open</a> / <a href="%4$s" class="file_download_link">Download</a>',
|
||||
));
|
||||
|
||||
// UserProfile brick
|
||||
|
||||
@@ -1,117 +0,0 @@
|
||||
<?php
|
||||
|
||||
// Copyright (C) 2010-2016 Combodo SARL
|
||||
//
|
||||
// This file is part of iTop.
|
||||
//
|
||||
// iTop is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// iTop is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2012 Combodo SARL
|
||||
* @copyright Copyright (C) 2016 ITOMIG GmbH
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
|
||||
// Portal
|
||||
Dict::Add('DE DE', 'German', 'Deutsch', array(
|
||||
'Page:DefaultTitle' => 'iTop - Benutzer Portal',
|
||||
'Page:PleaseWait' => 'Bitte warten...',
|
||||
'Page:Home' => 'Start',
|
||||
'Page:GoPortalHome' => 'Startseite',
|
||||
'Page:GoPreviousPage' => 'vorherige Seite',
|
||||
'Portal:Button:Submit' => 'Abschicken',
|
||||
'Portal:Button:Cancel' => 'Zurück',
|
||||
'Portal:Button:Close' => 'Schließen',
|
||||
'Portal:Button:Add' => 'Hinzu',
|
||||
'Portal:Button:Remove' => 'Wegnehmen',
|
||||
'Portal:Button:Delete' => 'Löschen',
|
||||
'Portal:EnvironmentBanner:Title' => 'Sie sind im Moment im <strong>%1$s</strong> Modus',
|
||||
'Portal:EnvironmentBanner:GoToProduction' => 'Zurück zum PRODUCTION Modus',
|
||||
'Error:HTTP:404' => 'Seite nicht gefunden.',
|
||||
'Error:HTTP:500' => 'Oops! Es ist ein Fehler aufgetreten.',
|
||||
'Error:HTTP:GetHelp' => 'Bitte kontaktieren Sie Ihren iTop administrator falls das Problem öfter auftaucht.',
|
||||
'Error:XHR:Fail' => 'Konnte Daten nicht laden, bitte kontaktieren Sie Ihren iTop administrator',
|
||||
'Portal:Datatables:Language:Processing' => 'Bitte warten...',
|
||||
'Portal:Datatables:Language:Search' => 'Filter :',
|
||||
'Portal:Datatables:Language:LengthMenu' => 'Anzahl _MENU_ Einträge pro Seite',
|
||||
'Portal:Datatables:Language:ZeroRecords' => 'Keine Resultate',
|
||||
'Portal:Datatables:Language:Info' => 'Seite _PAGE_ von _PAGES_',
|
||||
'Portal:Datatables:Language:InfoEmpty' => 'Keine Information',
|
||||
'Portal:Datatables:Language:InfoFiltered' => 'gefiltert aus _MAX_ Resultaten',
|
||||
'Portal:Datatables:Language:EmptyTable' => 'Keine Daten in dieser Tabelle verfügbar',
|
||||
'Portal:Datatables:Language:DisplayLength:All' => 'Alle',
|
||||
'Portal:Datatables:Language:Paginate:First' => '1.Seite',
|
||||
'Portal:Datatables:Language:Paginate:Previous' => 'vorherige',
|
||||
'Portal:Datatables:Language:Paginate:Next' => 'Nächste',
|
||||
'Portal:Datatables:Language:Paginate:Last' => 'Letzte',
|
||||
'Portal:Datatables:Language:Sort:Ascending' => 'wähle aufsteigende Sortierung',
|
||||
'Portal:Datatables:Language:Sort:Descending' => 'wähle abfallende Sortierung',
|
||||
'Portal:Autocomplete:NoResult' => 'keine Daten',
|
||||
'Portal:Attachments:DropZone:Message' => 'Legen Sie hier Ihre Files ab, um sie als Anhang dem Ticket hinzuzufügen',
|
||||
'Portal:File:None' => 'Kein File vorhanden',
|
||||
'Portal:File:DisplayInfo' => '<a href="%2$s" class="file_download_link">%1$s</a>',
|
||||
'Portal:File:DisplayInfo+' => '%1$s (%2$s) <a href="%3$s" class="file_open_link" target="_blank">Öffnen</a> / <a href="%4$s" class="file_download_link">Download</a>',
|
||||
));
|
||||
|
||||
Dict::Add('DE DE', 'German', 'Deutsch', array(
|
||||
'Brick:Portal:UserProfile:Name' => 'Benutzer Profil',
|
||||
'Brick:Portal:UserProfile:Navigation:Dropdown:MyProfil' => 'Mein Profil',
|
||||
'Brick:Portal:UserProfile:Navigation:Dropdown:Logout' => 'Abmelden',
|
||||
'Brick:Portal:UserProfile:Password:Title' => 'Passwort',
|
||||
'Brick:Portal:UserProfile:Password:ChoosePassword' => 'Passwort wählen',
|
||||
'Brick:Portal:UserProfile:Password:ConfirmPassword' => 'Passwort bestätigen',
|
||||
'Brick:Portal:UserProfile:Password:CantChangeContactAdministrator' => 'Um das Password zu ändern, kontaktieren Sie bitte Ihren iTop Administrator',
|
||||
'Brick:Portal:UserProfile:Password:CantChangeForUnknownReason' => 'Kann das Passwort nicht ändern - bitte kontaktieren Sie Ihren iTop Administrator',
|
||||
'Brick:Portal:UserProfile:PersonalInformations:Title' => 'Persönliche Informationen',
|
||||
'Brick:Portal:UserProfile:Photo:Title' => 'Foto',
|
||||
));
|
||||
|
||||
// BrowseBrick brick
|
||||
Dict::Add('DE DE', 'German', 'Deutsch', array(
|
||||
'Brick:Portal:Browse:Name' => 'List durchgehen',
|
||||
'Brick:Portal:Browse:Mode:List' => 'Liste',
|
||||
'Brick:Portal:Browse:Mode:Tree' => 'Baum',
|
||||
'Brick:Portal:Browse:Action:Drilldown' => 'Drilldown',
|
||||
'Brick:Portal:Browse:Action:View' => 'Details',
|
||||
'Brick:Portal:Browse:Action:Edit' => 'Editieren',
|
||||
'Brick:Portal:Browse:Action:Create' => 'Erstellen',
|
||||
'Brick:Portal:Browse:Action:CreateObjectFromThis' => 'Neue %1$s',
|
||||
'Brick:Portal:Browse:Tree:ExpandAll' => 'Alle expandieren',
|
||||
'Brick:Portal:Browse:Tree:CollapseAll' => 'Alle kollabieren',
|
||||
'Brick:Portal:Browse:Filter:NoData' => 'Kein Eintrag',
|
||||
));
|
||||
|
||||
Dict::Add('DE DE', 'German', 'Deutsch', array(
|
||||
'Brick:Portal:Manage:Name' => 'Einträge managen',
|
||||
'Brick:Portal:Manage:Table:NoData' => 'Kein Eintrag.',
|
||||
));
|
||||
|
||||
// ObjectBrick brick
|
||||
Dict::Add('DE DE', 'German', 'Deutsch', array(
|
||||
'Brick:Portal:Object:Name' => 'Object',
|
||||
'Brick:Portal:Object:Form:Create:Title' => 'Neue %1$s',
|
||||
'Brick:Portal:Object:Form:Edit:Title' => 'Wird aktualisiert %2$s (%1$s)',
|
||||
'Brick:Portal:Object:Form:View:Title' => '%1$s : %2$s',
|
||||
'Brick:Portal:Object:Form:Stimulus:Title' => 'Bitte die folgendenen Informationen ausfüllen:',
|
||||
'Brick:Portal:Object:Form:Message:Saved' => 'Saved',
|
||||
'Brick:Portal:Object:Search:Regular:Title' => 'Select %1$s (%2$s)',
|
||||
'Brick:Portal:Object:Search:Hierarchy:Title' => 'Select %1$s (%2$s)',
|
||||
));
|
||||
|
||||
// CreateBrick brick
|
||||
Dict::Add('DE DE', 'German', 'Deutsch', array(
|
||||
'Brick:Portal:Create:Name' => 'Schnelles Erstellen',
|
||||
));
|
||||
?>
|
||||
@@ -36,14 +36,12 @@ Dict::Add('EN US', 'English', 'English', array(
|
||||
'Portal:Button:Add' => 'Add',
|
||||
'Portal:Button:Remove' => 'Remove',
|
||||
'Portal:Button:Delete' => 'Delete',
|
||||
'Portal:EnvironmentBanner:Title' => 'You are currently in <strong>%1$s</strong> mode',
|
||||
'Portal:EnvironmentBanner:GoToProduction' => 'Go back to PRODUCTION mode',
|
||||
'Error:HTTP:404' => 'Page not found',
|
||||
'Error:HTTP:500' => 'Oops! An error has occured.',
|
||||
'Error:HTTP:GetHelp' => 'Please contact your iTop administrator if the problem keeps happening.',
|
||||
'Error:XHR:Fail' => 'Could not load data, please contact your iTop administrator',
|
||||
'Portal:Datatables:Language:Processing' => 'Please wait...',
|
||||
'Portal:Datatables:Language:Search' => 'Filter:',
|
||||
'Portal:Datatables:Language:Search' => 'filter :',
|
||||
'Portal:Datatables:Language:LengthMenu' => 'Display _MENU_ items per page',
|
||||
'Portal:Datatables:Language:ZeroRecords' => 'No result',
|
||||
'Portal:Datatables:Language:Info' => 'Page _PAGE_ of _PAGES_',
|
||||
@@ -59,9 +57,6 @@ Dict::Add('EN US', 'English', 'English', array(
|
||||
'Portal:Datatables:Language:Sort:Descending' => 'enable for a descending sort',
|
||||
'Portal:Autocomplete:NoResult' => 'No data',
|
||||
'Portal:Attachments:DropZone:Message' => 'Drop your files to add them as attachments',
|
||||
'Portal:File:None' => 'No file',
|
||||
'Portal:File:DisplayInfo' => '<a href="%2$s" class="file_download_link">%1$s</a>',
|
||||
'Portal:File:DisplayInfo+' => '%1$s (%2$s) <a href="%3$s" class="file_open_link" target="_blank">Open</a> / <a href="%4$s" class="file_download_link">Download</a>',
|
||||
));
|
||||
|
||||
// UserProfile brick
|
||||
|
||||
@@ -1,118 +0,0 @@
|
||||
<?php
|
||||
|
||||
// Copyright (C) 2010-2015 Combodo SARL
|
||||
//
|
||||
// This file is part of iTop.
|
||||
//
|
||||
// iTop is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// iTop is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2012 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
|
||||
// Portal
|
||||
Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
|
||||
'Page:DefaultTitle' => 'iTop User portal',
|
||||
'Page:PleaseWait' => 'Please wait...',
|
||||
'Page:Home' => 'Bienvenido',
|
||||
'Page:GoPortalHome' => 'Regresar a bienvenida',
|
||||
'Page:GoPreviousPage' => 'página anterior',
|
||||
'Portal:Button:Submit' => 'Enviar',
|
||||
'Portal:Button:Cancel' => 'Cancelar',
|
||||
'Portal:Button:Close' => 'Cerrar',
|
||||
'Portal:Button:Add' => 'Añadir',
|
||||
'Portal:Button:Remove' => 'Eliminar',
|
||||
'Portal:Button:Delete' => 'Borrar',
|
||||
'Portal:EnvironmentBanner:Title' => 'You are currently in <strong>%1$s</strong> mode~~',
|
||||
'Portal:EnvironmentBanner:GoToProduction' => 'Go back to PRODUCTION mode~~',
|
||||
'Error:HTTP:404' => 'Página no encontrada',
|
||||
'Error:HTTP:500' => '¡Vaya! Ha ocurrido un error.',
|
||||
'Error:HTTP:GetHelp' => 'Póngase en contacto con el administrador de iTop si el problema persiste.',
|
||||
'Error:XHR:Fail' => 'No se pudieron cargar datos, póngase en contacto con su administrador de iTop',
|
||||
'Portal:Datatables:Language:Processing' => 'Por favor esperar...',
|
||||
'Portal:Datatables:Language:Search' => 'Filtrar:',
|
||||
'Portal:Datatables:Language:LengthMenu' => 'Mostrar _MENU_ elementos por página',
|
||||
'Portal:Datatables:Language:ZeroRecords' => 'Sin resultados',
|
||||
'Portal:Datatables:Language:Info' => 'Página _PAGE_ de _PAGES_',
|
||||
'Portal:Datatables:Language:InfoEmpty' => 'Sin información',
|
||||
'Portal:Datatables:Language:InfoFiltered' => 'Filtrada de _MAX_ elementos',
|
||||
'Portal:Datatables:Language:EmptyTable' => 'No hay datos disponibles en esta tabla',
|
||||
'Portal:Datatables:Language:DisplayLength:All' => 'Todas',
|
||||
'Portal:Datatables:Language:Paginate:First' => 'primero',
|
||||
'Portal:Datatables:Language:Paginate:Previous' => 'Anterior',
|
||||
'Portal:Datatables:Language:Paginate:Next' => 'Siguiente',
|
||||
'Portal:Datatables:Language:Paginate:Last' => 'Último',
|
||||
'Portal:Datatables:Language:Sort:Ascending' => 'Habilitar para un orden ascendente',
|
||||
'Portal:Datatables:Language:Sort:Descending' => 'Habilitar para un tipo descendente',
|
||||
'Portal:Autocomplete:NoResult' => 'Sin datos',
|
||||
'Portal:Attachments:DropZone:Message' => 'Agrega tus archivos para agregarlos como documentos adjuntos',
|
||||
'Portal:File:None' => 'No file',
|
||||
'Portal:File:DisplayInfo' => '<a href="%2$s" class="file_download_link">%1$s</a>',
|
||||
'Portal:File:DisplayInfo+' => '%1$s (%2$s) <a href="%3$s" class="file_open_link" target="_blank">Open</a> / <a href="%4$s" class="file_download_link">Download</a>',
|
||||
));
|
||||
|
||||
// UserProfile brick
|
||||
Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
|
||||
'Brick:Portal:UserProfile:Name' => 'Perfil del usuario',
|
||||
'Brick:Portal:UserProfile:Navigation:Dropdown:MyProfil' => 'Mi perfil',
|
||||
'Brick:Portal:UserProfile:Navigation:Dropdown:Logout' => 'Desconectarse',
|
||||
'Brick:Portal:UserProfile:Password:Title' => 'Contraseña',
|
||||
'Brick:Portal:UserProfile:Password:ChoosePassword' => 'Elegir una contraseña',
|
||||
'Brick:Portal:UserProfile:Password:ConfirmPassword' => 'Confirmar contraseña',
|
||||
'Brick:Portal:UserProfile:Password:CantChangeContactAdministrator' => 'Para cambiar su contraseña, póngase en contacto con su administrador de iTop',
|
||||
'Brick:Portal:UserProfile:Password:CantChangeForUnknownReason' => 'No se puede cambiar la contraseña, póngase en contacto con el administrador de iTop',
|
||||
'Brick:Portal:UserProfile:PersonalInformations:Title' => 'Informaciones personales',
|
||||
'Brick:Portal:UserProfile:Photo:Title' => 'Foto',
|
||||
));
|
||||
|
||||
// BrowseBrick brick
|
||||
Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
|
||||
'Brick:Portal:Browse:Name' => 'Buscar en todos los elementos',
|
||||
'Brick:Portal:Browse:Mode:List' => 'Lista',
|
||||
'Brick:Portal:Browse:Mode:Tree' => 'Árbol',
|
||||
'Brick:Portal:Browse:Action:Drilldown' => 'Desglose',
|
||||
'Brick:Portal:Browse:Action:View' => 'Detalles',
|
||||
'Brick:Portal:Browse:Action:Edit' => 'Editar',
|
||||
'Brick:Portal:Browse:Action:Create' => 'Crear',
|
||||
'Brick:Portal:Browse:Action:CreateObjectFromThis' => 'Nuevo %1$s',
|
||||
'Brick:Portal:Browse:Tree:ExpandAll' => 'Expandir todo',
|
||||
'Brick:Portal:Browse:Tree:CollapseAll' => 'Desplegar todo',
|
||||
'Brick:Portal:Browse:Filter:NoData' => 'Sin objeto',
|
||||
));
|
||||
|
||||
// ManageBrick brick
|
||||
Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
|
||||
'Brick:Portal:Manage:Name' => 'Administrar elementos',
|
||||
'Brick:Portal:Manage:Table:NoData' => 'Sin objeto.',
|
||||
));
|
||||
|
||||
// ObjectBrick brick
|
||||
Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
|
||||
'Brick:Portal:Object:Name' => 'Object',
|
||||
'Brick:Portal:Object:Form:Create:Title' => 'New %1$s',
|
||||
'Brick:Portal:Object:Form:Edit:Title' => 'Updating %2$s (%1$s)',
|
||||
'Brick:Portal:Object:Form:View:Title' => '%1$s : %2$s',
|
||||
'Brick:Portal:Object:Form:Stimulus:Title' => 'Please, fill the following informations:',
|
||||
'Brick:Portal:Object:Form:Message:Saved' => 'Saved',
|
||||
'Brick:Portal:Object:Search:Regular:Title' => 'Select %1$s (%2$s)',
|
||||
'Brick:Portal:Object:Search:Hierarchy:Title' => 'Select %1$s (%2$s)',
|
||||
));
|
||||
|
||||
// CreateBrick brick
|
||||
Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
|
||||
'Brick:Portal:Create:Name' => 'Creación rápida',
|
||||
));
|
||||
?>
|
||||
@@ -36,8 +36,6 @@ Dict::Add('FR FR', 'French', 'Français', array(
|
||||
'Portal:Button:Add' => 'Ajouter',
|
||||
'Portal:Button:Remove' => 'Enlever',
|
||||
'Portal:Button:Delete' => 'Supprimer',
|
||||
'Portal:EnvironmentBanner:Title' => 'Vous êtes dans le mode <strong>%1$s</strong>',
|
||||
'Portal:EnvironmentBanner:GoToProduction' => 'Retourner au mode PRODUCTION',
|
||||
'Error:HTTP:404' => 'Page non trouvée',
|
||||
'Error:HTTP:500' => 'Oups ! Une erreur est survenue.',
|
||||
'Error:HTTP:GetHelp' => 'Si le problème persiste, veuillez contacter votre administrateur iTop.',
|
||||
@@ -59,9 +57,6 @@ Dict::Add('FR FR', 'French', 'Français', array(
|
||||
'Portal:Datatables:Language:Sort:Descending' => 'activer pour trier la colonne par ordre décroissant',
|
||||
'Portal:Autocomplete:NoResult' => 'Aucun résultat',
|
||||
'Portal:Attachments:DropZone:Message' => 'Déposez vos fichiers pour les ajouter en pièces jointes',
|
||||
'Portal:File:None' => 'Aucun fichier',
|
||||
'Portal:File:DisplayInfo' => '<a href="%2$s" class="file_download_link">%1$s</a>',
|
||||
'Portal:File:DisplayInfo+' => '%1$s (%2$s) <a href="%3$s" class="file_open_link" target="_blank">Ouvrir</a> / <a href="%4$s" class="file_download_link">Télécharger</a>',
|
||||
));
|
||||
|
||||
// UserProfile brick
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-portal-base/1.0.1', array(
|
||||
'itop-portal-base/1.0.0', array(
|
||||
// Identification
|
||||
'label' => 'Portal Development Library',
|
||||
'category' => 'Portal',
|
||||
|
||||
@@ -93,19 +93,11 @@ class BrowseBrickController extends BrickController
|
||||
{
|
||||
// Retrieving class alias for all depth
|
||||
array_unshift($aLevelsClasses, $aLevelsProperties[$aLevelsPropertiesKeys[$i]]['search']->GetClassAlias());
|
||||
|
||||
|
||||
// Joining queries from bottom-up
|
||||
if ($i < $iLoopMax)
|
||||
{
|
||||
$aRealiasingMap = array();
|
||||
$aLevelsProperties[$aLevelsPropertiesKeys[$i]]['search'] = $aLevelsProperties[$aLevelsPropertiesKeys[$i]]['search']->Join($aLevelsProperties[$aLevelsPropertiesKeys[$i + 1]]['search'], DBSearch::JOIN_REFERENCED_BY, $aLevelsProperties[$aLevelsPropertiesKeys[$i + 1]]['parent_att'], TREE_OPERATOR_EQUALS, $aRealiasingMap);
|
||||
foreach ($aLevelsPropertiesKeys as $sLevelAlias)
|
||||
{
|
||||
if (array_key_exists($sLevelAlias, $aRealiasingMap))
|
||||
{
|
||||
$aLevelsProperties[$aLevelsPropertiesKeys[$i]]['search']->RenameAlias($aRealiasingMap[$sLevelAlias], $sLevelAlias);
|
||||
}
|
||||
}
|
||||
$aLevelsProperties[$aLevelsPropertiesKeys[$i]]['search'] = $aLevelsProperties[$aLevelsPropertiesKeys[$i]]['search']->Join($aLevelsProperties[$aLevelsPropertiesKeys[$i + 1]]['search'], DBSearch::JOIN_REFERENCED_BY, $aLevelsProperties[$aLevelsPropertiesKeys[$i + 1]]['parent_att']);
|
||||
}
|
||||
|
||||
// Adding search clause
|
||||
@@ -176,7 +168,7 @@ class BrowseBrickController extends BrickController
|
||||
}
|
||||
}
|
||||
$oQuery = $aLevelsProperties[$aLevelsPropertiesKeys[0]]['search'];
|
||||
|
||||
|
||||
// Testing appropriate data loading mode if we are in auto
|
||||
if ($sDataLoading === AbstractBrick::ENUM_DATA_LOADING_AUTO)
|
||||
{
|
||||
@@ -267,32 +259,7 @@ class BrowseBrickController extends BrickController
|
||||
{
|
||||
$oSet = new DBObjectSet($oQuery);
|
||||
}
|
||||
|
||||
// Optimizing the ObjectSet to retrieve only necessary columns
|
||||
$aColumnAttrs = array();
|
||||
foreach ($oSet->GetFilter()->GetSelectedClasses() as $sTmpClassAlias => $sTmpClassName)
|
||||
{
|
||||
if (isset($aLevelsProperties[$sTmpClassAlias]))
|
||||
{
|
||||
$aTmpLevelProperties = $aLevelsProperties[$sTmpClassAlias];
|
||||
// Mandatory main attribute
|
||||
$aTmpColumnAttrs = array($aTmpLevelProperties['name_att']);
|
||||
// Optionnal attributes, only if in list mode
|
||||
if ($sBrowseMode === BrowseBrick::ENUM_BROWSE_MODE_LIST)
|
||||
{
|
||||
foreach ($aTmpLevelProperties['fields'] as $aTmpField)
|
||||
{
|
||||
$aTmpColumnAttrs[] = $aTmpField['code'];
|
||||
}
|
||||
}
|
||||
$aColumnAttrs[$sTmpClassAlias] = $aTmpColumnAttrs;
|
||||
}
|
||||
}
|
||||
$oSet->OptimizeColumnLoad($aColumnAttrs);
|
||||
|
||||
// Sorting objects through defined order (in DM)
|
||||
$oSet->SetOrderByClasses();
|
||||
|
||||
|
||||
// Retrieving results and organizing them for templating
|
||||
$aItems = array();
|
||||
while ($aCurrentRow = $oSet->FetchAssoc())
|
||||
@@ -371,16 +338,10 @@ class BrowseBrickController extends BrickController
|
||||
{
|
||||
$sCurrentLevelAlias = $sLevelAliasPrefix . static::LEVEL_SEPARATOR . $aLevel['id'];
|
||||
$oSearch = DBSearch::CloneWithAlias(DBSearch::FromOQL($aLevel['oql']), $sCurrentLevelAlias);
|
||||
|
||||
|
||||
// Restricting to the allowed scope
|
||||
$oScopeSearch = $oApp['scope_validator']->GetScopeFilterForProfiles(UserRights::ListProfiles(), $oSearch->GetClass(), UR_ACTION_READ);
|
||||
$oSearch = ($oScopeSearch !== null) ? $oSearch->Intersect($oScopeSearch) : null;
|
||||
// - Allowing all data if necessary
|
||||
if ($oScopeSearch->IsAllDataAllowed())
|
||||
{
|
||||
$oSearch->AllowAllData();
|
||||
}
|
||||
|
||||
if ($oSearch !== null)
|
||||
{
|
||||
$aLevelsProperties[$sCurrentLevelAlias] = array(
|
||||
@@ -600,15 +561,7 @@ class BrowseBrickController extends BrickController
|
||||
$aRow[$key]['fields'] = array();
|
||||
foreach ($aLevelsProperties[$key]['fields'] as $aField)
|
||||
{
|
||||
$oAttDef = MetaModel::GetAttributeDef(get_class($value), $aField['code']);
|
||||
if ($oAttDef->GetEditClass() === 'Duration')
|
||||
{
|
||||
$aRow[$key]['fields'][$aField['code']] = $oAttDef->GetAsHTML($value->Get($aField['code']));
|
||||
}
|
||||
else
|
||||
{
|
||||
$aRow[$key]['fields'][$aField['code']] = $oAttDef->GetValueLabel($value->Get($aField['code']));
|
||||
}
|
||||
$aRow[$key]['fields'][$aField['code']] = $value->Get($aField['code']);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -677,3 +630,5 @@ class BrowseBrickController extends BrickController
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -37,17 +37,8 @@ class DefaultController
|
||||
// Doing it only for tile visible on home page to avoid unnecessary rendering
|
||||
if (($oBrick->GetVisibleHome() === true) && ($oBrick->GetTileControllerAction() !== null))
|
||||
{
|
||||
$aControllerActionParts = explode('::', $oBrick->GetTileControllerAction());
|
||||
if (count($aControllerActionParts) !== 2)
|
||||
{
|
||||
$oApp->abort(500, 'Tile controller action must be of form "\Namespace\ControllerClass::FunctionName" for brick "' . $oBrick->GetId() . '"');
|
||||
}
|
||||
|
||||
$sControllerName = $aControllerActionParts[0];
|
||||
$sControllerAction = $aControllerActionParts[1];
|
||||
|
||||
$oController = new $sControllerName($oRequest, $oApp, $oBrick->GetId());
|
||||
$aData['aTilesRendering'][$oBrick->GetId()] = $oController->$sControllerAction($oRequest, $oApp, $oBrick->GetId());
|
||||
$oController = new \Combodo\iTop\Portal\Controller\ManageBrickController($oRequest, $oApp);
|
||||
$aData['aTilesRendering'][$oBrick->GetId()] = $oController->HomeAction($oRequest, $oApp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,8 +28,6 @@ use \MetaModel;
|
||||
use \AttributeDefinition;
|
||||
use \AttributeDate;
|
||||
use \AttributeDateTime;
|
||||
use \AttributeDuration;
|
||||
use \AttributeSubItem;
|
||||
use \DBSearch;
|
||||
use \DBObjectSearch;
|
||||
use \DBObjectSet;
|
||||
@@ -61,15 +59,6 @@ class ManageBrickController extends BrickController
|
||||
// Getting search value
|
||||
$sSearchValue = $oRequest->get('sSearchValue', null);
|
||||
|
||||
// Getting area columns properties
|
||||
$aColumnsAttrs = $oBrick->GetFields();
|
||||
// Adding friendlyname attribute to the list is not already in it
|
||||
$sTitleAttrCode = 'friendlyname';
|
||||
if (($sTitleAttrCode !== null) && !in_array($sTitleAttrCode, $aColumnsAttrs))
|
||||
{
|
||||
$aColumnsAttrs = array_merge(array($sTitleAttrCode), $aColumnsAttrs);
|
||||
}
|
||||
|
||||
// Starting to build query
|
||||
$oQuery = DBSearch::FromOQL($oBrick->GetOql());
|
||||
|
||||
@@ -209,11 +198,6 @@ class ManageBrickController extends BrickController
|
||||
if ($oDistinctScopeQuery != null)
|
||||
{
|
||||
$oDistinctQuery = $oDistinctQuery->Intersect($oDistinctScopeQuery);
|
||||
// - Allowing all data if necessary
|
||||
if ($oDistinctScopeQuery->IsAllDataAllowed())
|
||||
{
|
||||
$oDistinctQuery->AllowAllData();
|
||||
}
|
||||
}
|
||||
// Adding grouping conditions
|
||||
$oFieldExp = new FieldExpression($sGroupingAreaAttCode, $sParentAlias);
|
||||
@@ -268,19 +252,7 @@ class ManageBrickController extends BrickController
|
||||
// Note : Will need to moved the scope restriction on queries elsewhere when we consider grouping on something else than finalclass
|
||||
// Note : We now get view scope instead of edit scope as we allowed users to view/edit objects in the brick regarding their rights
|
||||
$oScopeQuery = $oApp['scope_validator']->GetScopeFilterForProfiles(UserRights::ListProfiles(), $aGroupingAreasValue['value'], UR_ACTION_READ);
|
||||
if ($oScopeQuery !== null)
|
||||
{
|
||||
$oAreaQuery = $oAreaQuery->Intersect($oScopeQuery);
|
||||
// - Allowing all data if necessary
|
||||
if ($oScopeQuery->IsAllDataAllowed())
|
||||
{
|
||||
$oAreaQuery->AllowAllData();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$oAreaQuery = null;
|
||||
}
|
||||
$oAreaQuery = ($oScopeQuery !== null) ? $oAreaQuery->Intersect($oScopeQuery) : null;
|
||||
|
||||
$aQueries[$sKey] = $oAreaQuery;
|
||||
}
|
||||
@@ -292,7 +264,6 @@ class ManageBrickController extends BrickController
|
||||
// - Check how many records there is.
|
||||
// - Update $sDataLoading with its new value regarding the number of record and the threshold
|
||||
$oCountSet = new DBObjectSet($oQuery);
|
||||
$oCountSet->OptimizeColumnLoad(array());
|
||||
$fThreshold = (float) MetaModel::GetModuleSetting($oApp['combodo.portal.instance.id'], 'lazy_loading_threshold');
|
||||
$sDataLoading = ($oCountSet->Count() > $fThreshold) ? AbstractBrick::ENUM_DATA_LOADING_LAZY : AbstractBrick::ENUM_DATA_LOADING_FULL;
|
||||
unset($oCountSet);
|
||||
@@ -314,7 +285,6 @@ class ManageBrickController extends BrickController
|
||||
|
||||
// Getting total records number
|
||||
$oCountSet = new DBObjectSet($oQuery);
|
||||
$oCountSet->OptimizeColumnLoad(array($oQuery->GetClassAlias() => $aColumnsAttrs));
|
||||
$aData['recordsTotal'] = $oCountSet->Count();
|
||||
$aData['recordsFiltered'] = $oCountSet->Count();
|
||||
unset($oCountSet);
|
||||
@@ -326,8 +296,6 @@ class ManageBrickController extends BrickController
|
||||
{
|
||||
$oSet = new DBObjectSet($oQuery);
|
||||
}
|
||||
$oSet->OptimizeColumnLoad(array($oQuery->GetClassAlias() => $aColumnsAttrs));
|
||||
$oSet->SetOrderByClasses();
|
||||
$aSets[$sKey] = $oSet;
|
||||
}
|
||||
}
|
||||
@@ -338,7 +306,15 @@ class ManageBrickController extends BrickController
|
||||
{
|
||||
// Set properties
|
||||
$sCurrentClass = $sKey;
|
||||
|
||||
$sTitleAttrCode = MetaModel::GetFriendlyNameAttributeCode($sCurrentClass);
|
||||
|
||||
// Getting area columns properties
|
||||
$aColumnsAttrs = $oBrick->GetFields();
|
||||
// Adding friendlyname attribute to the list is not already in it
|
||||
if (($sTitleAttrCode !== null) && !in_array($sTitleAttrCode, $aColumnsAttrs))
|
||||
{
|
||||
$aColumnsAttrs = array_merge(array($sTitleAttrCode), $aColumnsAttrs);
|
||||
}
|
||||
// Defining which attribute will open the edition form)
|
||||
$sMainActionAttrCode = $aColumnsAttrs[0];
|
||||
|
||||
@@ -391,7 +367,7 @@ class ManageBrickController extends BrickController
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$oAttDef = MetaModel::GetAttributeDef($sCurrentClass, $sItemAttr);
|
||||
if ($oAttDef->IsExternalKey())
|
||||
{
|
||||
@@ -411,10 +387,6 @@ class ManageBrickController extends BrickController
|
||||
}
|
||||
}
|
||||
}
|
||||
elseif ($oAttDef instanceof AttributeSubItem || $oAttDef instanceof AttributeDuration)
|
||||
{
|
||||
$sValue = $oAttDef->GetAsHTML($oCurrentRow->Get($sItemAttr));
|
||||
}
|
||||
else
|
||||
{
|
||||
$sValue = $oAttDef->GetValueLabel($oCurrentRow->Get($sItemAttr));
|
||||
@@ -474,3 +446,5 @@ class ManageBrickController extends BrickController
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -32,7 +32,6 @@ use \IssueLog;
|
||||
use \MetaModel;
|
||||
use \DBSearch;
|
||||
use \DBObjectSearch;
|
||||
use \FalseExpression;
|
||||
use \BinaryExpression;
|
||||
use \FieldExpression;
|
||||
use \VariableExpression;
|
||||
@@ -40,8 +39,6 @@ use \ListExpression;
|
||||
use \ScalarExpression;
|
||||
use \DBObjectSet;
|
||||
use \cmdbAbstractObject;
|
||||
use \AttributeEnum;
|
||||
use \AttributeFinalClass;
|
||||
use \UserRights;
|
||||
use \Combodo\iTop\Portal\Helper\ApplicationHelper;
|
||||
use \Combodo\iTop\Portal\Helper\SecurityHelper;
|
||||
@@ -86,7 +83,7 @@ class ObjectController extends AbstractController
|
||||
}
|
||||
|
||||
// Retrieving object
|
||||
$oObject = MetaModel::GetObject($sObjectClass, $sObjectId, false /* MustBeFound */, $oApp['scope_validator']->IsAllDataAllowedForScope(UserRights::ListProfiles(), $sObjectClass));
|
||||
$oObject = MetaModel::GetObject($sObjectClass, $sObjectId, false /* MustBeFound */);
|
||||
if ($oObject === null)
|
||||
{
|
||||
// We should never be there as the secuirty helper makes sure that the object exists, but just in case.
|
||||
@@ -158,7 +155,7 @@ class ObjectController extends AbstractController
|
||||
}
|
||||
|
||||
// Retrieving object
|
||||
$oObject = MetaModel::GetObject($sObjectClass, $sObjectId, false /* MustBeFound */, $oApp['scope_validator']->IsAllDataAllowedForScope(UserRights::ListProfiles(), $sObjectClass));
|
||||
$oObject = MetaModel::GetObject($sObjectClass, $sObjectId, false /* MustBeFound */);
|
||||
if ($oObject === null)
|
||||
{
|
||||
// We should never be there as the secuirty helper makes sure that the object exists, but just in case.
|
||||
@@ -278,26 +275,23 @@ class ObjectController extends AbstractController
|
||||
}
|
||||
|
||||
// Retrieving origin object
|
||||
// Note : AllowAllData set to true here instead of checking scope's flag because we are displaying a value that has been set and validated
|
||||
$oOriginObject = MetaModel::GetObject($sObjectClass, $sObjectId, true, true);
|
||||
|
||||
$oOriginObject = MetaModel::GetObject($sObjectClass, $sObjectId);
|
||||
|
||||
// Retrieving target object (We check if the method is a simple function or if it's part of a class in which case only static function are supported)
|
||||
if (!strpos($sMethodName, '::'))
|
||||
{
|
||||
$oTargetObject = $sMethodName($oOriginObject);
|
||||
$sTargetObject = $sMethodName($oOriginObject);
|
||||
}
|
||||
else
|
||||
{
|
||||
$aMethodNameParts = explode('::', $sMethodName);
|
||||
$sMethodClass = $aMethodNameParts[0];
|
||||
$sMethodName = $aMethodNameParts[1];
|
||||
$oTargetObject = $sMethodClass::$sMethodName($oOriginObject);
|
||||
$sTargetObject = $aMethodNameParts[0]::$aMethodNameParts[1]($oOriginObject);
|
||||
}
|
||||
|
||||
// Preparing redirection
|
||||
// - Route
|
||||
$aRouteParams = array(
|
||||
'sObjectClass' => get_class($oTargetObject)
|
||||
'sObjectClass' => get_class($sTargetObject)
|
||||
);
|
||||
$sRedirectRoute = $oApp['url_generator']->generate('p_object_create', $aRouteParams);
|
||||
// - Request
|
||||
@@ -333,7 +327,7 @@ class ObjectController extends AbstractController
|
||||
// }
|
||||
|
||||
// Retrieving object
|
||||
$oObject = MetaModel::GetObject($sObjectClass, $sObjectId, false /* MustBeFound */, $oApp['scope_validator']->IsAllDataAllowedForScope(UserRights::ListProfiles(), $sObjectClass));
|
||||
$oObject = MetaModel::GetObject($sObjectClass, $sObjectId, false /* MustBeFound */);
|
||||
if ($oObject === null)
|
||||
{
|
||||
// We should never be there as the secuirty helper makes sure that the object exists, but just in case.
|
||||
@@ -341,9 +335,6 @@ class ObjectController extends AbstractController
|
||||
$oApp->abort(404, Dict::S('UI:ObjectDoesNotExist'));
|
||||
}
|
||||
|
||||
// Retrieving request parameters
|
||||
$sOperation = $oRequest->request->get('operation');
|
||||
|
||||
// Preparing a dedicated form for the stimulus application
|
||||
$aFormProperties = array(
|
||||
'id' => 'apply-stimulus',
|
||||
@@ -381,39 +372,14 @@ class ObjectController extends AbstractController
|
||||
'url' => $oApp['url_generator']->generate('p_object_edit', array('sObjectClass' => $sObjectClass, 'sObjectId' => $sObjectId))
|
||||
);
|
||||
|
||||
// TODO : This is a ugly patch to avoid showing a modal with a readonly form to the user as it would prevent user from finishing the transition.
|
||||
// Instead, we apply the stimulus directly here and then go to the edited object.
|
||||
if ($sOperation === null)
|
||||
{
|
||||
if (isset($aData['form']['editable_fields_count']) && $aData['form']['editable_fields_count'] === 0)
|
||||
{
|
||||
$sOperation = 'redirect';
|
||||
|
||||
$oSubRequest = $oRequest;
|
||||
$oSubRequest->request->set('operation', 'submit');
|
||||
$oSubRequest->request->set('stimulus_code', null);
|
||||
|
||||
$aData = array('sMode' => 'apply_stimulus');
|
||||
$aData['form'] = $this->HandleForm($oSubRequest, $oApp, $aData['sMode'], $sObjectClass, $sObjectId, $aFormProperties);
|
||||
// Redefining the array to be as simple as possible :
|
||||
$aData = array('redirection' =>
|
||||
array('url' => $oApp['url_generator']->generate('p_object_edit', array('sObjectClass' => $sObjectClass, 'sObjectId' => $sObjectId)))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Preparing response
|
||||
if ($oRequest->isXmlHttpRequest())
|
||||
{
|
||||
// We have to check whether the 'operation' parameter is defined or not in order to know if the form is required via ajax (to be displayed as a modal dialog) or if it's a lifecycle call from a existing form.
|
||||
if ($sOperation === null)
|
||||
if ($oRequest->request->get('operation') === null)
|
||||
{
|
||||
$oResponse = $oApp['twig']->render('itop-portal-base/portal/src/views/bricks/object/modal.html.twig', $aData);
|
||||
}
|
||||
elseif ($sOperation === 'redirect')
|
||||
{
|
||||
$oResponse = $oApp['twig']->render('itop-portal-base/portal/src/views/modal/mode_loader.html.twig', $aData);
|
||||
}
|
||||
else
|
||||
{
|
||||
$oResponse = $oApp->json($aData);
|
||||
@@ -462,7 +428,7 @@ class ObjectController extends AbstractController
|
||||
}
|
||||
else
|
||||
{
|
||||
$oObject = MetaModel::GetObject($sObjectClass, $sObjectId, true, $oApp['scope_validator']->IsAllDataAllowedForScope(UserRights::ListProfiles(), $sObjectClass));
|
||||
$oObject = MetaModel::GetObject($sObjectClass, $sObjectId);
|
||||
}
|
||||
|
||||
// Preparing transitions only if we are currently going through one
|
||||
@@ -507,16 +473,9 @@ class ObjectController extends AbstractController
|
||||
->SetMode($sMode)
|
||||
->SetActionRulesToken($sActionRulesToken)
|
||||
->SetRenderer($oFormRenderer)
|
||||
->SetFormProperties($aFormProperties);
|
||||
|
||||
if ($sMode === 'apply_stimulus')
|
||||
{
|
||||
$aEditFormProperties = ApplicationHelper::GetLoadedFormFromClass($oApp, $sObjectClass, ObjectFormManager::ENUM_MODE_APPLY_STIMULUS);
|
||||
$oFormManager->MergeFormProperties($aEditFormProperties);
|
||||
}
|
||||
|
||||
$oFormManager->Build();
|
||||
|
||||
->SetFormProperties($aFormProperties)
|
||||
->Build();
|
||||
|
||||
// Check the number of editable fields
|
||||
$aFormData['editable_fields_count'] = $oFormManager->GetForm()->GetEditableFieldCount();
|
||||
}
|
||||
@@ -654,8 +613,6 @@ class ObjectController extends AbstractController
|
||||
|
||||
// Retrieving parameters
|
||||
$sQuery = $aRequestContent['sQuery'];
|
||||
$sFormPath = $aRequestContent['sFormPath'];
|
||||
$sFieldId = $aRequestContent['sFieldId'];
|
||||
|
||||
// Checking security layers
|
||||
if (!SecurityHelper::IsActionAllowed($oApp, UR_ACTION_READ, $sHostObjectClass, $sHostObjectId))
|
||||
@@ -667,8 +624,7 @@ class ObjectController extends AbstractController
|
||||
// Retrieving host object for future DBSearch parameters
|
||||
if ($sHostObjectId !== null)
|
||||
{
|
||||
// Note : AllowAllData set to true here instead of checking scope's flag because we are displaying a value that has been set and validated
|
||||
$oHostObject = MetaModel::GetObject($sHostObjectClass, $sHostObjectId, true, true);
|
||||
$oHostObject = MetaModel::GetObject($sHostObjectClass, $sHostObjectId);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -709,58 +665,20 @@ class ObjectController extends AbstractController
|
||||
// Building search query
|
||||
// - Retrieving target object class from attcode
|
||||
$oTargetAttDef = MetaModel::GetAttributeDef($sHostObjectClass, $sTargetAttCode);
|
||||
if ($oTargetAttDef->GetEditClass() === 'CustomFields')
|
||||
{
|
||||
$oRequestTemplate = $oHostObject->Get($sTargetAttCode);
|
||||
$oTemplateFieldSearch = $oRequestTemplate->GetForm()->GetField('user_data')->GetForm()->GetField($sFieldId)->GetSearch();
|
||||
$sTargetObjectClass = $oTemplateFieldSearch->GetClass();
|
||||
}
|
||||
elseif ($oTargetAttDef->IsLinkSet())
|
||||
{
|
||||
throw new Exception('Search autocomplete cannot apply on AttributeLinkedSet objects, ' . get_class($oTargetAttDef) . ' (' . $sHostObjectClass . '->' . $sTargetAttCode . ') given.');
|
||||
}
|
||||
else
|
||||
{
|
||||
$sTargetObjectClass = $oTargetAttDef->GetTargetClass();
|
||||
}
|
||||
$sTargetObjectClass = $oTargetAttDef->GetTargetClass();
|
||||
// - Base query from meta model
|
||||
if ($oTargetAttDef->GetEditClass() === 'CustomFields')
|
||||
{
|
||||
$oSearch = $oTemplateFieldSearch;
|
||||
}
|
||||
else
|
||||
{
|
||||
$oSearch = DBSearch::FromOQL($oTargetAttDef->GetValuesDef()->GetFilterExpression());
|
||||
}
|
||||
$oSearch = DBSearch::FromOQL($oTargetAttDef->GetValuesDef()->GetFilterExpression());
|
||||
// - Adding query condition
|
||||
$oSearch->AddConditionExpression(new BinaryExpression(new FieldExpression('friendlyname', $oSearch->GetClassAlias()), 'LIKE', new VariableExpression('ac_query')));
|
||||
// - Intersecting with scope constraints
|
||||
// Note : This do NOT apply to custom fields as the portal administrator is not supposed to know which objects will be put in the templates.
|
||||
// It is the responsability of the template designer to write the right query so the user see only what he should.
|
||||
if ($oTargetAttDef->GetEditClass() !== 'CustomFields')
|
||||
{
|
||||
$oScopeSearch = $oApp['scope_validator']->GetScopeFilterForProfiles(UserRights::ListProfiles(), $sTargetObjectClass, UR_ACTION_READ);
|
||||
$oSearch = $oSearch->Intersect($oScopeSearch);
|
||||
// - Allowing all data if necessary
|
||||
if ($oScopeSearch->IsAllDataAllowed())
|
||||
{
|
||||
$oSearch->AllowAllData();
|
||||
}
|
||||
}
|
||||
|
||||
$oSearch = $oSearch->Intersect($oApp['scope_validator']->GetScopeFilterForProfiles(UserRights::ListProfiles(), $sTargetObjectClass, UR_ACTION_READ));
|
||||
|
||||
// Retrieving results
|
||||
// - Preparing object set
|
||||
$oSet = new DBObjectSet($oSearch, array(), array('this' => $oHostObject, 'ac_query' => '%' . $sQuery . '%'));
|
||||
$oSet->OptimizeColumnLoad(array($oSearch->GetClassAlias() => array('friendlyname')));
|
||||
// Note : This limit is also used in the field renderer by typeahead to determine how many suggestions to display
|
||||
if ($oTargetAttDef->GetEditClass() === 'CustomFields')
|
||||
{
|
||||
$oSet->SetLimit(static::DEFAULT_COUNT_PER_PAGE_LIST);
|
||||
}
|
||||
else
|
||||
{
|
||||
$oSet->SetLimit($oTargetAttDef->GetMaximumComboLength()); // TODO : Is this the right limit value ? We might want to use another parameter
|
||||
}
|
||||
$oSet->SetLimit($oTargetAttDef->GetMaximumComboLength()); // TODO : Is this the right limit value ? We might want to use another parameter
|
||||
// - Retrieving objects
|
||||
while ($oItem = $oSet->Fetch())
|
||||
{
|
||||
@@ -811,8 +729,7 @@ class ObjectController extends AbstractController
|
||||
// Retrieving host object for future DBSearch parameters
|
||||
if ($sHostObjectId !== null)
|
||||
{
|
||||
// Note : AllowAllData set to true here instead of checking scope's flag because we are displaying a value that has been set and validated
|
||||
$oHostObject = MetaModel::GetObject($sHostObjectClass, $sHostObjectId, true, true);
|
||||
$oHostObject = MetaModel::GetObject($sHostObjectClass, $sHostObjectId);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -878,12 +795,6 @@ class ObjectController extends AbstractController
|
||||
$sTargetObjectClass = $oRemoteAttDef->GetTargetClass();
|
||||
}
|
||||
}
|
||||
elseif ($oTargetAttDef->GetEditClass() === 'CustomFields')
|
||||
{
|
||||
$oRequestTemplate = $oHostObject->Get($sTargetAttCode);
|
||||
$oTemplateFieldSearch = $oRequestTemplate->GetForm()->GetField('user_data')->GetForm()->GetField($sFieldId)->GetSearch();
|
||||
$sTargetObjectClass = $oTemplateFieldSearch->GetClass();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception('Search from attribute can only apply on AttributeExternalKey or AttributeLinkedSet objects, ' . get_class($oTargetAttDef) . ' given.');
|
||||
@@ -892,18 +803,16 @@ class ObjectController extends AbstractController
|
||||
// - Retrieving class attribute list
|
||||
$aAttCodes = ApplicationHelper::GetLoadedListFromClass($oApp, $sTargetObjectClass, 'list');
|
||||
// - Adding friendlyname attribute to the list is not already in it
|
||||
$sTitleAttCode = 'friendlyname';
|
||||
$sTitleAttCode = MetaModel::GetFriendlyNameAttributeCode($sTargetObjectClass);
|
||||
if (($sTitleAttCode !== null) && !in_array($sTitleAttCode, $aAttCodes))
|
||||
{
|
||||
$aAttCodes = array_merge(array($sTitleAttCode), $aAttCodes);
|
||||
}
|
||||
|
||||
// - Retrieving scope search
|
||||
// Note : This do NOT apply to custom fields as the portal administrator is not supposed to know which objects will be put in the templates.
|
||||
// It is the responsability of the template designer to write the right query so the user see only what he should.
|
||||
$oScopeSearch = $oApp['scope_validator']->GetScopeFilterForProfiles(UserRights::ListProfiles(), $sTargetObjectClass, UR_ACTION_READ);
|
||||
$aInternalParams = array();
|
||||
if (($oScopeSearch === null) && ($oTargetAttDef->GetEditClass() !== 'CustomFields'))
|
||||
if ($oScopeSearch === null)
|
||||
{
|
||||
IssueLog::Info(__METHOD__ . ' at line ' . __LINE__ . ' : User #' . UserRights::GetUserId() . ' has no scope query for ' . $sTargetObjectClass . ' class.');
|
||||
$oApp->abort(404, Dict::S('UI:ObjectDoesNotExist'));
|
||||
@@ -918,11 +827,6 @@ class ObjectController extends AbstractController
|
||||
{
|
||||
$oSearch = $oScopeSearch;
|
||||
}
|
||||
elseif ($oTargetAttDef->GetEditClass() === 'CustomFields')
|
||||
{
|
||||
// Note : $oTemplateFieldSearch has been defined in the "Retrieving target object class from attcode" part, it is not available otherwise
|
||||
$oSearch = $oTemplateFieldSearch;
|
||||
}
|
||||
|
||||
// - Filtering objects to ignore
|
||||
if (($aObjectIdsToIgnore !== null) && (is_array($aObjectIdsToIgnore)))
|
||||
@@ -935,7 +839,7 @@ class ObjectController extends AbstractController
|
||||
}
|
||||
$oSearch->AddConditionExpression(new BinaryExpression(new FieldExpression('id', $oSearch->GetClassAlias()), 'NOT IN', new ListExpression($aExpressions)));
|
||||
}
|
||||
|
||||
|
||||
// - Adding query condition
|
||||
$aInternalParams['this'] = $oHostObject;
|
||||
if ($sQuery !== null)
|
||||
@@ -947,35 +851,7 @@ class ObjectController extends AbstractController
|
||||
$oAttDef = MetaModel::GetAttributeDef($sTargetObjectClass, $aAttCodes[$i]);
|
||||
$sAttCode = (!$oAttDef->IsExternalKey()) ? $aAttCodes[$i] : $aAttCodes[$i] . '_friendlyname';
|
||||
// Building expression for the current attcode
|
||||
// - For attributes that need conversion from their display value to storage value
|
||||
// Note : This is dirty hack that will need to be refactored in the OQL core in order to be nicer and to be extended to other types such as dates etc...
|
||||
if (($oAttDef instanceof AttributeEnum) || ($oAttDef instanceof AttributeFinalClass))
|
||||
{
|
||||
// Looking up storage value
|
||||
$aMatchedCodes = array();
|
||||
foreach ($oAttDef->GetAllowedValues() as $sValueCode => $sValueLabel)
|
||||
{
|
||||
if (stripos($sValueLabel, $sQuery) !== false)
|
||||
{
|
||||
$aMatchedCodes[] = $sValueCode;
|
||||
}
|
||||
}
|
||||
// Building expression
|
||||
if (!empty($aMatchedCodes))
|
||||
{
|
||||
$oEnumeratedListExpr = ListExpression::FromScalars($aMatchedCodes);
|
||||
$oBinExpr = new BinaryExpression(new FieldExpression($sAttCode, $oSearch->GetClassAlias()), 'IN', $oEnumeratedListExpr);
|
||||
}
|
||||
else
|
||||
{
|
||||
$oBinExpr = new FalseExpression();
|
||||
}
|
||||
}
|
||||
// - For regular attributs
|
||||
else
|
||||
{
|
||||
$oBinExpr = new BinaryExpression(new FieldExpression($sAttCode, $oSearch->GetClassAlias()), 'LIKE', new VariableExpression('re_query'));
|
||||
}
|
||||
$oBinExpr = new BinaryExpression(new FieldExpression($sAttCode, $oSearch->GetClassAlias()), 'LIKE', new VariableExpression('re_query'));
|
||||
// Adding expression to the full expression (all attcodes)
|
||||
if ($i === 0)
|
||||
{
|
||||
@@ -992,17 +868,7 @@ class ObjectController extends AbstractController
|
||||
}
|
||||
|
||||
// - Intersecting with scope constraints
|
||||
// Note : This do NOT apply to custom fields as the portal administrator is not supposed to know which objects will be put in the templates.
|
||||
// It is the responsability of the template designer to write the right query so the user see only what he should.
|
||||
if (($oScopeSearch !== null) && ($oTargetAttDef->GetEditClass() !== 'CustomFields'))
|
||||
{
|
||||
$oSearch = $oSearch->Intersect($oScopeSearch);
|
||||
// - Allowing all data if necessary
|
||||
if ($oScopeSearch->IsAllDataAllowed())
|
||||
{
|
||||
$oSearch->AllowAllData();
|
||||
}
|
||||
}
|
||||
$oSearch = $oSearch->Intersect($oScopeSearch);
|
||||
|
||||
// Retrieving results
|
||||
// - Preparing object set
|
||||
@@ -1080,7 +946,7 @@ class ObjectController extends AbstractController
|
||||
'sFormManagerData' => $sFormManagerData
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
if ($oRequest->isXmlHttpRequest())
|
||||
{
|
||||
$oResponse = $oApp['twig']->render('itop-portal-base/portal/src/views/bricks/object/modal.html.twig', $aData);
|
||||
@@ -1135,8 +1001,7 @@ class ObjectController extends AbstractController
|
||||
// Retrieving host object for future DBSearch parameters
|
||||
if ($sHostObjectId !== null)
|
||||
{
|
||||
// Note : AllowAllData set to true here instead of checking scope's flag because we are displaying a value that has been set and validated
|
||||
$oHostObject = MetaModel::GetObject($sHostObjectClass, $sHostObjectId, true, true);
|
||||
$oHostObject = MetaModel::GetObject($sHostObjectClass, $sHostObjectId);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1176,7 +1041,7 @@ class ObjectController extends AbstractController
|
||||
// // - Retrieving class attribute list
|
||||
// $aAttCodes = MetaModel::FlattenZList(MetaModel::GetZListItems($sTargetObjectClass, 'list'));
|
||||
// // - Adding friendlyname attribute to the list is not already in it
|
||||
// $sTitleAttrCode = 'friendlyname';
|
||||
// $sTitleAttrCode = MetaModel::GetFriendlyNameAttributeCode($sTargetObjectClass);
|
||||
// if (($sTitleAttrCode !== null) && !in_array($sTitleAttrCode, $aAttCodes))
|
||||
// {
|
||||
// $aAttCodes = array_merge(array($sTitleAttrCode), $aAttCodes);
|
||||
@@ -1227,11 +1092,6 @@ class ObjectController extends AbstractController
|
||||
// }
|
||||
// - Intersecting with scope constraints
|
||||
$oSearch = $oSearch->Intersect($oScopeSearch);
|
||||
// - Allowing all data if necessary
|
||||
if ($oScopeSearch->IsAllDataAllowed())
|
||||
{
|
||||
$oSearch->AllowAllData();
|
||||
}
|
||||
|
||||
// Retrieving results
|
||||
// - Preparing object set
|
||||
@@ -1386,8 +1246,7 @@ class ObjectController extends AbstractController
|
||||
}
|
||||
}
|
||||
|
||||
// Note : The Content-Type header is set to 'text/plain' in order to be IE9 compatible. Otherwise ('application/json') IE9 will download the response as a JSON file to the user computer...
|
||||
$oResponse = $oApp->json($aData, 200, array('Content-Type' => 'text/plain'));
|
||||
$oResponse = $oApp->json($aData);
|
||||
break;
|
||||
|
||||
case 'download':
|
||||
@@ -1448,12 +1307,7 @@ class ObjectController extends AbstractController
|
||||
}
|
||||
|
||||
// Building the search
|
||||
$bIgnoreSilos = $oApp['scope_validator']->IsAllDataAllowedForScope(UserRights::ListProfiles(), $sObjectClass);
|
||||
$oSearch = DBObjectSearch::FromOQL("SELECT " . $sObjectClass . " WHERE id IN ('" . implode("','", $aObjectIds) . "')");
|
||||
if ($bIgnoreSilos === true)
|
||||
{
|
||||
$oSearch->AllowAllData();
|
||||
}
|
||||
$oSet = new DBObjectSet($oSearch);
|
||||
$oSet->OptimizeColumnLoad($aObjectAttCodes);
|
||||
|
||||
|
||||
@@ -493,9 +493,6 @@ abstract class PortalBrick extends AbstractBrick
|
||||
$this->SetDecorationClassNavigationMenu($optionalNodeValue);
|
||||
}
|
||||
break;
|
||||
case 'tile_controller_action':
|
||||
$this->SetTileControllerAction($oBrickSubNode->GetText(static::DEFAULT_TILE_CONTROLLER_ACTION));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,6 @@ use \MetaModel;
|
||||
use \CMDBSource;
|
||||
use \DBObject;
|
||||
use \DBObjectSet;
|
||||
use \DBSearch;
|
||||
use \DBObjectSearch;
|
||||
use \DBObjectSetComparator;
|
||||
use \InlineImage;
|
||||
@@ -50,7 +49,6 @@ class ObjectFormManager extends FormManager
|
||||
const ENUM_MODE_VIEW = 'view';
|
||||
const ENUM_MODE_EDIT = 'edit';
|
||||
const ENUM_MODE_CREATE = 'create';
|
||||
const ENUM_MODE_APPLY_STIMULUS = 'apply_stimulus';
|
||||
|
||||
protected $oApp;
|
||||
protected $oObject;
|
||||
@@ -94,8 +92,7 @@ class ObjectFormManager extends FormManager
|
||||
}
|
||||
else
|
||||
{
|
||||
// Note : AllowAllData set to true here instead of checking scope's flag because we are displaying a value that has been set and validated
|
||||
$oObject = MetaModel::GetObject($sObjectClass, $aJson['formobject_id'], true, true);
|
||||
$oObject = MetaModel::GetObject($sObjectClass, $aJson['formobject_id'], true);
|
||||
}
|
||||
$oFormManager->SetObject($oObject);
|
||||
|
||||
@@ -485,18 +482,6 @@ class ObjectFormManager extends FormManager
|
||||
{
|
||||
$oField->SetReadOnly(true);
|
||||
}
|
||||
// - Else if it's must change, we force it as not readonly and not hidden
|
||||
elseif (($iFieldFlags & OPT_ATT_MUSTCHANGE) === OPT_ATT_MUSTCHANGE)
|
||||
{
|
||||
$oField->SetReadOnly(false);
|
||||
$oField->SetHidden(false);
|
||||
}
|
||||
// - Else if it's must prompt, we force it as not readonly and not hidden
|
||||
elseif (($iFieldFlags & OPT_ATT_MUSTPROMPT) === OPT_ATT_MUSTPROMPT)
|
||||
{
|
||||
$oField->SetReadOnly(false);
|
||||
$oField->SetHidden(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Normal field
|
||||
@@ -531,61 +516,6 @@ class ObjectFormManager extends FormManager
|
||||
$oField->SetInformationEndpoint($this->oApp['url_generator']->generate('p_object_get_informations_json'));
|
||||
}
|
||||
}
|
||||
// - Field that require to apply scope on its DM OQL
|
||||
if (in_array(get_class($oField), array('Combodo\\iTop\\Form\\Field\\SelectObjectField')))
|
||||
{
|
||||
if ($this->oApp !== null)
|
||||
{
|
||||
$oScopeOriginal = ($oField->GetSearch() !== null) ? $oField->GetSearch() : DBSearch::FromOQL($oAttDef->GetValuesDef()->GetFilterExpression());
|
||||
|
||||
$oScopeSearch = $this->oApp['scope_validator']->GetScopeFilterForProfiles(UserRights::ListProfiles(), $oScopeOriginal->GetClass(), UR_ACTION_READ);
|
||||
if ($oScopeSearch === null)
|
||||
{
|
||||
IssueLog::Info(__METHOD__ . ' at line ' . __LINE__ . ' : User #' . UserRights::GetUserId() . ' has no scope query for ' . $oScopeOriginal->GetClass() . ' class.');
|
||||
$this->oApp->abort(404, Dict::S('UI:ObjectDoesNotExist'));
|
||||
}
|
||||
$oScopeOriginal = $oScopeOriginal->Intersect($oScopeSearch);
|
||||
// Note : This is to skip the silo restriction on the final query
|
||||
if ($oScopeSearch->IsAllDataAllowed())
|
||||
{
|
||||
$oScopeOriginal->AllowAllData();
|
||||
}
|
||||
$oScopeOriginal->SetInternalParams(array('this' => $this->oObject));
|
||||
$oField->SetSearch($oScopeOriginal);
|
||||
}
|
||||
}
|
||||
// - Field that require processing on their subfields
|
||||
if (in_array(get_class($oField), array('Combodo\\iTop\\Form\\Field\\SubFormField')))
|
||||
{
|
||||
$oSubForm = $oField->GetForm();
|
||||
if ($oAttDef->GetEditClass() === 'CustomFields')
|
||||
{
|
||||
// Retrieving only user data fields (not the metadata fields of the template)
|
||||
if ($oSubForm->HasField('user_data'))
|
||||
{
|
||||
$oUserDataField = $oSubForm->GetField('user_data');
|
||||
$oUserDataForm = $oUserDataField->GetForm();
|
||||
foreach ($oUserDataForm->GetFields() as $oCustomField)
|
||||
{
|
||||
// - Field that require a search endpoint (OQL based dropdown list fields)
|
||||
if (in_array(get_class($oCustomField), array('Combodo\\iTop\\Form\\Field\\SelectObjectField')))
|
||||
{
|
||||
if ($this->oApp !== null)
|
||||
{
|
||||
|
||||
$sSearchEndpoint = $this->oApp['url_generator']->generate('p_object_search_generic', array(
|
||||
'sTargetAttCode' => $oAttDef->GetCode(),
|
||||
'sHostObjectClass' => get_class($this->oObject),
|
||||
'sHostObjectId' => ($this->oObject->IsNew()) ? null : $this->oObject->GetKey(),
|
||||
'ar_token' => $this->GetActionRulesToken(),
|
||||
));
|
||||
$oCustomField->SetSearchEndpoint($sSearchEndpoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -609,7 +539,7 @@ class ObjectFormManager extends FormManager
|
||||
// Note : This snippet is inspired from AttributeLinkedSet::MakeFormField()
|
||||
$aAttCodesToDisplay = ApplicationHelper::GetLoadedListFromClass($this->oApp, $oField->GetTargetClass(), 'list');
|
||||
// - Adding friendlyname attribute to the list is not already in it
|
||||
$sTitleAttCode = 'friendlyname';
|
||||
$sTitleAttCode = MetaModel::GetFriendlyNameAttributeCode($oField->GetTargetClass());
|
||||
if (($sTitleAttCode !== null) && !in_array($sTitleAttCode, $aAttCodesToDisplay))
|
||||
{
|
||||
$aAttCodesToDisplay = array_merge(array($sTitleAttCode), $aAttCodesToDisplay);
|
||||
@@ -695,87 +625,6 @@ class ObjectFormManager extends FormManager
|
||||
$this->oRenderer->SetForm($this->oForm);
|
||||
}
|
||||
|
||||
/**
|
||||
* Merging $this->aFormProperties with $aFormPropertiesToMerge. Merge only layout for now
|
||||
*
|
||||
* @param array $aFormPropertiesToMerge
|
||||
* @throws Exception
|
||||
*/
|
||||
public function MergeFormProperties($aFormPropertiesToMerge)
|
||||
{
|
||||
if ($aFormPropertiesToMerge['layout'] !== null)
|
||||
{
|
||||
// Checking if we need to render the template from twig to html in order to parse the fields
|
||||
if ($aFormPropertiesToMerge['layout']['type'] === 'twig')
|
||||
{
|
||||
// Creating sandbox twig env. to load and test the custom form template
|
||||
$oTwig = new \Twig_Environment(new \Twig_Loader_String());
|
||||
$sRendered = $oTwig->render($aFormPropertiesToMerge['layout']['content'], array('oRenderer' => $this->oRenderer, 'oObject' => $this->oObject));
|
||||
}
|
||||
else
|
||||
{
|
||||
$sRendered = $aFormPropertiesToMerge['layout']['content'];
|
||||
}
|
||||
|
||||
// Parsing rendered template to find the fields
|
||||
$oHtmlDocument = new \DOMDocument();
|
||||
$oHtmlDocument->loadHTML('<root>' . $sRendered . '</root>');
|
||||
|
||||
// Adding fields to the list
|
||||
$oXPath = new \DOMXPath($oHtmlDocument);
|
||||
foreach ($oXPath->query('//div[@class="form_field"][@data-field-id]') as $oFieldNode)
|
||||
{
|
||||
$sFieldId = $oFieldNode->getAttribute('data-field-id');
|
||||
$sFieldFlags = $oFieldNode->getAttribute('data-field-flags');
|
||||
// $iFieldFlags = OPT_ATT_NORMAL;
|
||||
|
||||
// // Checking if field has form_path, if not, we add it
|
||||
// if (!$oFieldNode->hasAttribute('data-form-path'))
|
||||
// {
|
||||
// $oFieldNode->setAttribute('data-form-path', $oForm->GetId());
|
||||
// }
|
||||
// Merging only fields that are already in the form
|
||||
if (array_key_exists($sFieldId, $this->aFormProperties['fields']))
|
||||
{
|
||||
// Settings field flags from the data-field-flags attribute
|
||||
foreach (explode(' ', $sFieldFlags) as $sFieldFlag)
|
||||
{
|
||||
if ($sFieldFlag !== '')
|
||||
{
|
||||
$sConst = 'OPT_ATT_' . strtoupper(str_replace('_', '', $sFieldFlag));
|
||||
if (defined($sConst))
|
||||
{
|
||||
switch ($sConst)
|
||||
{
|
||||
case 'OPT_ATT_SLAVE':
|
||||
case 'OPT_ATT_HIDDEN':
|
||||
if (!array_key_exists($sFieldId, $this->aFormProperties['fields']))
|
||||
{
|
||||
$this->aFormProperties['fields'][$sFieldId] = array();
|
||||
}
|
||||
$this->aFormProperties['fields'][$sFieldId]['hidden'] = true;
|
||||
break;
|
||||
case 'OPT_ATT_READONLY':
|
||||
if (!array_key_exists($sFieldId, $this->aFormProperties['fields']))
|
||||
{
|
||||
$this->aFormProperties['fields'][$sFieldId] = array();
|
||||
}
|
||||
$this->aFormProperties['fields'][$sFieldId]['read_only'] = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
IssueLog::Error(__METHOD__ . ' at line ' . __LINE__ . ' : Flag "' . $sFieldFlag . '" is not valid for field [@data-field-id="' . $sFieldId . '"] in form[@id="' . $aFormPropertiesToMerge['id'] . '"]');
|
||||
throw new Exception('Flag "' . $sFieldFlag . '" is not valid for field [@data-field-id="' . $sFieldId . '"] in form[@id="' . $aFormPropertiesToMerge['id'] . '"]');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls all form fields OnCancel method in order to delegate them the cleanup;
|
||||
*
|
||||
@@ -942,8 +791,7 @@ class ObjectFormManager extends FormManager
|
||||
// LinkedSet
|
||||
if (!$oAttDef->IsIndirect())
|
||||
{
|
||||
// Note : AllowAllData set to true here instead of checking scope's flag because we are displaying a value that has been set and validated
|
||||
$oLinkedObject = MetaModel::GetObject($sTargetClass, abs($iTargetId), true, true);
|
||||
$oLinkedObject = MetaModel::GetObject($sTargetClass, abs($iTargetId));
|
||||
$oValueSet->AddObject($oLinkedObject);
|
||||
}
|
||||
// LinkedSetIndirect
|
||||
@@ -959,8 +807,7 @@ class ObjectFormManager extends FormManager
|
||||
// Existing relation
|
||||
else
|
||||
{
|
||||
// Note : AllowAllData set to true here instead of checking scope's flag because we are displaying a value that has been set and validated
|
||||
$oLink = MetaModel::GetObject($sTargetClass, $iTargetId, true, true);
|
||||
$oLink = MetaModel::GetObject($sTargetClass, $iTargetId);
|
||||
}
|
||||
$oValueSet->AddObject($oLink);
|
||||
}
|
||||
@@ -1013,7 +860,7 @@ class ObjectFormManager extends FormManager
|
||||
else
|
||||
{
|
||||
$this->oObject->Set($sAttCode, $value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->oObject->DoComputeValues();
|
||||
|
||||
@@ -202,7 +202,6 @@ class ApplicationHelper
|
||||
return Dict::S($sStringCode, $sDefault, $bUserLanguageOnly);
|
||||
})
|
||||
);
|
||||
|
||||
// A filter to format a string via the Dict::Format function
|
||||
// Usage in twig : {{ 'String:ToTranslate'|dict_format() }}
|
||||
$oApp['twig']->addFilter(new Twig_SimpleFilter('dict_format', function($sStringCode, $sParam01 = null, $sParam02 = null, $sParam03 = null, $sParam04 = null)
|
||||
@@ -210,12 +209,10 @@ class ApplicationHelper
|
||||
return Dict::Format($sStringCode, $sParam01, $sParam02, $sParam03, $sParam04);
|
||||
})
|
||||
);
|
||||
|
||||
// Filters to enable base64 encode/decode
|
||||
// Usage in twig : {{ 'String to encode'|base64_encode }}
|
||||
$oApp['twig']->addFilter(new Twig_SimpleFilter('base64_encode', 'base64_encode'));
|
||||
$oApp['twig']->addFilter(new Twig_SimpleFilter('base64_decode', 'base64_decode'));
|
||||
|
||||
// Filters to enable json decode (encode already exists)
|
||||
// Usage in twig : {{ aSomeArray|json_decode }}
|
||||
$oApp['twig']->addFilter(new Twig_SimpleFilter('json_decode', function($sJsonString, $bAssoc = false)
|
||||
@@ -223,21 +220,6 @@ class ApplicationHelper
|
||||
return json_decode($sJsonString, $bAssoc);
|
||||
})
|
||||
);
|
||||
|
||||
// Filter to add itopversion to an url
|
||||
$oApp['twig']->addFilter(new Twig_SimpleFilter('add_itop_version', function($sUrl)
|
||||
{
|
||||
if (strpos($sUrl, '?') === false)
|
||||
{
|
||||
$sUrl = $sUrl . "?itopversion=" . ITOP_VERSION;
|
||||
}
|
||||
else
|
||||
{
|
||||
$sUrl = $sUrl . "&itopversion=" . ITOP_VERSION;
|
||||
}
|
||||
|
||||
return $sUrl;
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
//
|
||||
// This file is part of iTop.
|
||||
//
|
||||
// iTop is free software; you can redistribute it and/or modify
|
||||
// iTop is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
@@ -23,7 +23,6 @@ use \Exception;
|
||||
use \Silex\Application;
|
||||
use \DOMNodeList;
|
||||
use \DOMFormatException;
|
||||
use \UserRights;
|
||||
use \DBObject;
|
||||
use \DBSearch;
|
||||
use \DBObjectSet;
|
||||
@@ -43,7 +42,6 @@ class ContextManipulatorHelper
|
||||
const ENUM_RULE_CALLBACK_OPEN_EDIT = 'edit';
|
||||
const DEFAULT_RULE_CALLBACK_OPEN = self::ENUM_RULE_CALLBACK_OPEN_VIEW;
|
||||
|
||||
protected $oApp;
|
||||
protected $aRules;
|
||||
|
||||
public function __construct()
|
||||
@@ -61,7 +59,7 @@ class ContextManipulatorHelper
|
||||
public function Init(DOMNodeList $oNodes)
|
||||
{
|
||||
$this->aRules = array();
|
||||
|
||||
|
||||
// Iterating over the scope nodes
|
||||
foreach ($oNodes as $oRuleNode)
|
||||
{
|
||||
@@ -183,11 +181,6 @@ class ContextManipulatorHelper
|
||||
}
|
||||
}
|
||||
|
||||
public function SetApp($oApp)
|
||||
{
|
||||
$this->oApp = $oApp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a hash array of rules
|
||||
*
|
||||
@@ -229,7 +222,7 @@ class ContextManipulatorHelper
|
||||
* ...
|
||||
* )
|
||||
* )
|
||||
*
|
||||
*
|
||||
* @param array $aData
|
||||
* @param DBObject $oObject
|
||||
*/
|
||||
@@ -297,13 +290,6 @@ class ContextManipulatorHelper
|
||||
}
|
||||
}
|
||||
|
||||
// Checking for silos
|
||||
$oScopeSearch = $this->oApp['scope_validator']->GetScopeFilterForProfiles(UserRights::ListProfiles(), $sSearchClass, UR_ACTION_READ);
|
||||
if ($oScopeSearch->IsAllDataAllowed())
|
||||
{
|
||||
$oSearch->AllowAllData();
|
||||
}
|
||||
|
||||
// Retrieving source object(s) and applying rules
|
||||
$oSet = new DBObjectSet($oSearch, array(), $aSearchParams);
|
||||
while ($oSourceObject = $oSet->Fetch())
|
||||
|
||||
@@ -36,7 +36,6 @@ class ScopeValidatorHelper
|
||||
const ENUM_TYPE_ALLOW = 'allow';
|
||||
const ENUM_TYPE_RESTRICT = 'restrict';
|
||||
const DEFAULT_GENERATED_CLASS = 'PortalScopesValues';
|
||||
const DEFAULT_IGNORE_SILOS = false;
|
||||
|
||||
protected $sCachePath;
|
||||
protected $sFilename;
|
||||
@@ -180,9 +179,6 @@ class ScopeValidatorHelper
|
||||
// Retrieving the edit query
|
||||
$oOqlEditNode = $oScopeNode->GetOptionalElement('oql_edit');
|
||||
$sOqlEdit = ( ($oOqlEditNode !== null) && ($oOqlEditNode->GetText() !== null) ) ? $oOqlEditNode->GetText() : null;
|
||||
// Retrieving ignore allowed org flag
|
||||
$oIgnoreSilosNode = $oScopeNode->GetOptionalElement('ignore_silos');
|
||||
$bIgnoreSilos = ( ($oIgnoreSilosNode !== null) && ($oIgnoreSilosNode->GetText() === 'true') ) ? true : static::DEFAULT_IGNORE_SILOS;
|
||||
|
||||
// Retrieving profiles for the scope
|
||||
$oProfilesNode = $oScopeNode->GetOptionalElement('allowed_profiles');
|
||||
@@ -225,20 +221,13 @@ class ScopeValidatorHelper
|
||||
$oExistingFilter = DBSearch::FromOQL($aProfiles[$sMatrixPrefix . static::ENUM_MODE_READ][$sOqlViewType]);
|
||||
$aFilters = array($oExistingFilter, $oViewFilter);
|
||||
$oResFilter = new DBUnionSearch($aFilters);
|
||||
|
||||
// Applying ignore_silos flag on result filter if necessary (As the union will remove it if it is not on all sub-queries)
|
||||
if ($aProfiles[$sMatrixPrefix . static::ENUM_MODE_READ]['ignore_silos'] === true)
|
||||
{
|
||||
$bIgnoreSilos = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$oResFilter = $oViewFilter;
|
||||
}
|
||||
$aProfiles[$sMatrixPrefix . static::ENUM_MODE_READ] = array(
|
||||
$sOqlViewType => $oResFilter->ToOQL(),
|
||||
'ignore_silos' => $bIgnoreSilos
|
||||
$sOqlViewType => $oResFilter->ToOQL()
|
||||
);
|
||||
// - Edit query
|
||||
if ($sOqlEdit !== null)
|
||||
@@ -275,8 +264,7 @@ class ScopeValidatorHelper
|
||||
$oResFilter = $oEditFilter;
|
||||
}
|
||||
$aProfiles[$sMatrixPrefix . static::ENUM_MODE_WRITE] = array(
|
||||
$sOqlViewType => $oResFilter->ToOQL(),
|
||||
'ignore_silos' => $bIgnoreSilos
|
||||
$sOqlViewType => $oResFilter->ToOQL()
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -285,7 +273,7 @@ class ScopeValidatorHelper
|
||||
$aProfileClasses[] = $sClass;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Filling the array with missing classes from MetaModel, so we can have an inheritance principle on the scope
|
||||
// For each class explicitly given in the scopes, we check if its child classes were also in the scope :
|
||||
// If not, we add them with the same OQL
|
||||
@@ -307,14 +295,10 @@ class ScopeValidatorHelper
|
||||
$aTmpProfile = $aProfiles[$iProfileId . '_' . $sProfileClass . '_' . $sAction];
|
||||
foreach ($aTmpProfile as $sType => $sOql)
|
||||
{
|
||||
// IF condition is just to skip the 'ignore_silos' flag
|
||||
if (in_array($sType, array(static::ENUM_TYPE_ALLOW, static::ENUM_TYPE_RESTRICT)))
|
||||
{
|
||||
$oTmpFilter = DBSearch::FromOQL($sOql);
|
||||
$oTmpFilter->ChangeClass($sChildClass);
|
||||
$oTmpFilter = DBSearch::FromOQL($sOql);
|
||||
$oTmpFilter->ChangeClass($sChildClass);
|
||||
|
||||
$aTmpProfile[$sType] = $oTmpFilter->ToOQL();
|
||||
}
|
||||
$aTmpProfile[$sType] = $oTmpFilter->ToOQL();
|
||||
}
|
||||
|
||||
$aProfiles[$iProfileId . '_' . $sChildClass . '_' . $sAction] = $aTmpProfile;
|
||||
@@ -487,7 +471,6 @@ class ScopeValidatorHelper
|
||||
$oSearch = null;
|
||||
$aAllowSearches = array();
|
||||
$aRestrictSearches = array();
|
||||
$bIgnoreSilos = static::DEFAULT_IGNORE_SILOS;
|
||||
|
||||
// Checking the default mode
|
||||
if ($iAction === null)
|
||||
@@ -515,11 +498,6 @@ class ScopeValidatorHelper
|
||||
{
|
||||
$aRestrictSearches[] = DBSearch::FromOQL($aProfileMatrix['restrict']);
|
||||
}
|
||||
// If a profile should ignore allowed org, we set it for all its queries no matter the profile
|
||||
if (isset($aProfileMatrix['ignore_silos']) && $aProfileMatrix['ignore_silos'] === true)
|
||||
{
|
||||
$bIgnoreSilos = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -536,47 +514,10 @@ class ScopeValidatorHelper
|
||||
$oSearch = new DBUnionSearch($aAllowSearches);
|
||||
$oSearch = $oSearch->RemoveDuplicateQueries();
|
||||
}
|
||||
if ($bIgnoreSilos === true)
|
||||
{
|
||||
$oSearch->AllowAllData();
|
||||
}
|
||||
|
||||
|
||||
return $oSearch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if at least one of the $aProfiles has the ignore_silos flag set to true for the $sClass.
|
||||
*
|
||||
* @param array $aProfiles
|
||||
* @param string $sClass
|
||||
* @return boolean
|
||||
*/
|
||||
public function IsAllDataAllowedForScope($aProfiles, $sClass)
|
||||
{
|
||||
$bIgnoreSilos = false;
|
||||
|
||||
// Iterating on profiles to retrieving the different OQLs parts
|
||||
foreach ($aProfiles as $sProfile)
|
||||
{
|
||||
// Retrieving matrix informtions
|
||||
$iProfileId = $this->GetProfileIdFromProfileName($sProfile);
|
||||
|
||||
// Retrieving profile OQLs
|
||||
$sScopeValuesClass = $this->sGeneratedClass;
|
||||
$aProfileMatrix = $sScopeValuesClass::GetProfileScope($iProfileId, $sClass, static::ENUM_MODE_READ);
|
||||
if ($aProfileMatrix !== null)
|
||||
{
|
||||
// If a profile should ignore allowed org, we set it for all its queries no matter the profile
|
||||
if (isset($aProfileMatrix['ignore_silos']) && $aProfileMatrix['ignore_silos'] === true)
|
||||
{
|
||||
$bIgnoreSilos = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $bIgnoreSilos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the profile id from a string being either a constant or its name.
|
||||
*
|
||||
|
||||
@@ -112,7 +112,7 @@ class SecurityHelper
|
||||
// Checking if the cmdbAbstractObject exists if id is specified
|
||||
if ($sObjectId !== null)
|
||||
{
|
||||
$oObject = MetaModel::GetObject($sObjectClass, $sObjectId, false /* MustBeFound */, $oApp['scope_validator']->IsAllDataAllowedForScope(UserRights::ListProfiles(), $sObjectClass));
|
||||
$oObject = MetaModel::GetObject($sObjectClass, $sObjectId, false /* MustBeFound */);
|
||||
if ($oObject === null)
|
||||
{
|
||||
if ($oApp['debug'])
|
||||
|
||||
@@ -44,7 +44,6 @@ class UrlGenerator extends SymfonyUrlGenerator
|
||||
*/
|
||||
public function generate($name, $parameters = array(), $referenceType = SymfonyUrlGenerator::ABSOLUTE_PATH)
|
||||
{
|
||||
// Mandatory parameters
|
||||
$sExecModule = utils::ReadParam('exec_module', '', false, 'string');
|
||||
$sExecPage = utils::ReadParam('exec_page', '', false, 'string');
|
||||
if ($sExecModule !== '' && $sExecPage !== '')
|
||||
@@ -53,18 +52,6 @@ class UrlGenerator extends SymfonyUrlGenerator
|
||||
$parameters['exec_page'] = $sExecPage;
|
||||
}
|
||||
|
||||
// Optional parameters
|
||||
$sEnvSwitch = utils::ReadParam('env_switch', '', false, 'string');
|
||||
if ($sEnvSwitch !== '')
|
||||
{
|
||||
$parameters['env_switch'] = $sEnvSwitch;
|
||||
}
|
||||
$sDebug = utils::ReadParam('debug', '', false, 'string');
|
||||
if ($sDebug !== '')
|
||||
{
|
||||
$parameters['debug'] = $sDebug;
|
||||
}
|
||||
|
||||
return parent::generate($name, $parameters, $referenceType);
|
||||
}
|
||||
|
||||
|
||||
@@ -38,7 +38,6 @@ class ContextManipulatorServiceProvider implements ServiceProviderInterface
|
||||
$oApp->flush();
|
||||
|
||||
$oContextManipulatorHelper = new ContextManipulatorHelper();
|
||||
$oContextManipulatorHelper->SetApp($oApp);
|
||||
|
||||
return $oContextManipulatorHelper;
|
||||
});
|
||||
|
||||
@@ -73,11 +73,11 @@
|
||||
// For the same reason, tooltip widget is created in "drawCallback" instead of here.
|
||||
if( (data.tooltip !== undefined) && (data.tooltip !== ''))
|
||||
{
|
||||
cellElem.html( $('<span></span>').attr('title', data.tooltip).attr('data-toggle', 'tooltip').html(data.name).prop('outerHTML') );
|
||||
cellElem.html( $('<span></span>').attr('title', data.tooltip).attr('data-toggle', 'tooltip').text(data.name).prop('outerHTML') );
|
||||
}
|
||||
else
|
||||
{
|
||||
cellElem.html(data.name);
|
||||
cellElem.text(data.name);
|
||||
}
|
||||
|
||||
// Building actions
|
||||
@@ -97,11 +97,11 @@
|
||||
break;
|
||||
case '{{ constant('Combodo\\iTop\\Portal\\Brick\\BrowseBrick::ENUM_ACTION_CREATE_FROM_THIS') }}':
|
||||
url = levelPrimaryAction.url.replace(/-objectClass-/, data.class).replace(/-objectId-/, data.id);
|
||||
url = AddParameterToUrl(url, 'ar_token', data.action_rules_token[levelPrimaryAction.type]);
|
||||
url = addParameterToUrl(url, 'ar_token', data.action_rules_token[levelPrimaryAction.type]);
|
||||
cellElem.attr('data-toggle', 'modal').attr('data-target', '#modal-for-all').attr('href', url);
|
||||
break;
|
||||
default:
|
||||
//console.log('Action "'+levelPrimaryAction.type+'" not implemented');
|
||||
console.log('Action "'+levelPrimaryAction.type+'" not implemented');
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -150,11 +150,11 @@
|
||||
break;
|
||||
case '{{ constant('Combodo\\iTop\\Portal\\Brick\\BrowseBrick::ENUM_ACTION_CREATE_FROM_THIS') }}':
|
||||
url = action.url.replace(/-objectClass-/, data.class).replace(/-objectId-/, data.id);
|
||||
url = AddParameterToUrl(url, 'ar_token', data.action_rules_token[action.type]);
|
||||
url = addParameterToUrl(url, 'ar_token', data.action_rules_token[action.type]);
|
||||
actionElem.attr('data-toggle', 'modal').attr('data-target', '#modal-for-all').attr('href', url);
|
||||
break;
|
||||
default:
|
||||
//console.log('Action "'+action.type+'" not implemented for secondary action');
|
||||
console.log('Action "'+action.type+'" not implemented for secondary action');
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -201,6 +201,7 @@
|
||||
"type": "html",
|
||||
"data": oLevelsProperties[sKey].alias+".fields."+oLevelsProperties[sKey].fields[i].code
|
||||
});
|
||||
console.log(oLevelsProperties[sKey].fields[i].visible);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -239,7 +240,6 @@
|
||||
"displayLength": {{ constant('Combodo\\iTop\\Portal\\Brick\\BrowseBrick::DEFAULT_COUNT_PER_PAGE_LIST') }},
|
||||
"dom": '<"row"<"col-sm-6"l><"col-sm-6"<f><"visible-xs"p>>>t<"row"<"col-sm-6"i><"col-sm-6"p>>',
|
||||
"columns": getColumnsDefinition(),
|
||||
"order": [],
|
||||
"drawCallback": function(settings){
|
||||
// Tooltip has to been created here, as the render callback only returns a string, not an object.
|
||||
$(this).find('[data-toggle="tooltip"]').tooltip({container: 'body', html: true, trigger: 'hover', placement: 'right'}); // container option is necessary when in a table
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-8 col-sm-10 col-lg-11 text-right">
|
||||
<label>{{ 'Portal:Datatables:Language:Search'|dict_s }}<input type="search" class="form-control input-sm" id="brick_search_field" placeholder="" aria-controls="brick_main_table" value="{{ sSearchValue }}"></label>
|
||||
<label>Filtrer :<input type="search" class="form-control input-sm" id="brick_search_field" placeholder="" aria-controls="brick_main_table" value="{{ sSearchValue }}"></label>
|
||||
</div>
|
||||
</div>
|
||||
<ul class="list-group" id="brick_content_tree" data-level-id="L">
|
||||
@@ -223,11 +223,11 @@
|
||||
break;
|
||||
case '{{ constant('Combodo\\iTop\\Portal\\Brick\\BrowseBrick::ENUM_ACTION_CREATE_FROM_THIS') }}':
|
||||
url = levelPrimaryAction.url.replace(/-objectClass-/, item.class).replace(/-objectId-/, item.id);
|
||||
url = AddParameterToUrl(url, 'ar_token', item.action_rules_token[levelPrimaryAction.type]);
|
||||
url = addParameterToUrl(url, 'ar_token', item.action_rules_token[levelPrimaryAction.type]);
|
||||
aElem.attr('data-toggle', 'modal').attr('data-target', '#modal-for-all').attr('href', url);
|
||||
break;
|
||||
default:
|
||||
//console.log('Action "'+levelPrimaryAction.type+'" not implemented for primary action');
|
||||
console.log('Action "'+levelPrimaryAction.type+'" not implemented for primary action');
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -275,11 +275,11 @@
|
||||
break;
|
||||
case '{{ constant('Combodo\\iTop\\Portal\\Brick\\BrowseBrick::ENUM_ACTION_CREATE_FROM_THIS') }}':
|
||||
url = action.url.replace(/-objectClass-/, item.class).replace(/-objectId-/, item.id);
|
||||
url = AddParameterToUrl(url, 'ar_token', item.action_rules_token[action.type]);
|
||||
url = addParameterToUrl(url, 'ar_token', item.action_rules_token[action.type]);
|
||||
actionElem.attr('data-toggle', 'modal').attr('data-target', '#modal-for-all').attr('href', url);
|
||||
break;
|
||||
default:
|
||||
//console.log('Action "'+action.type+'" not implemented for secondary action');
|
||||
console.log('Action "'+action.type+'" not implemented for secondary action');
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,35 +17,24 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block pMainContentHolder%}
|
||||
{% set iTableCount = 0 %}
|
||||
{% if aGroupingAreasData|length > 0 %}
|
||||
{% for aAreaData in aGroupingAreasData %}
|
||||
{% if aAreaData.iItemsCount > 0 %}
|
||||
{% set iTableCount = iTableCount + 1 %}
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">{{ aAreaData.sTitle }}</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
{# We decided not to show empty tables anymore #}
|
||||
{#
|
||||
{% if aAreaData.iItemsCount > 0 %}
|
||||
#}
|
||||
<table id="table-{{ aAreaData.sId }}" class="table table-striped table-bordered responsive" width="100%"></table>
|
||||
{#
|
||||
{% else %}
|
||||
<div class="text-center">
|
||||
{{ 'Brick:Portal:Manage:Table:NoData'|dict_s }}
|
||||
</div>
|
||||
{% endif %}
|
||||
#}
|
||||
</div>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">{{ aAreaData.sTitle }}</h3>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="panel-body">
|
||||
{% if aAreaData.iItemsCount > 0 %}
|
||||
<table id="table-{{ aAreaData.sId }}" class="table table-striped table-bordered responsive" width="100%"></table>
|
||||
{% else %}
|
||||
<div class="text-center">
|
||||
{{ 'Brick:Portal:Manage:Table:NoData'|dict_s }}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
{% if iTableCount == 0 %}
|
||||
{% else %}
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-body">
|
||||
<h3 class="text-center">{{ 'Brick:Portal:Manage:Table:NoData'|dict_s }}</h3>
|
||||
@@ -80,12 +69,12 @@
|
||||
{
|
||||
var tableProperties = columnsProperties[tableName];
|
||||
|
||||
if(tableProperties === undefined && window.console)
|
||||
if(tableProperties === undefined)
|
||||
{
|
||||
console.log('Could not retrieve columns properties for table "'+tableName+'"');
|
||||
return false;
|
||||
}
|
||||
if(rawData[tableName] === undefined && window.console)
|
||||
if(rawData[tableName] === undefined)
|
||||
{
|
||||
console.log('Could not retrieve data for table "'+tableName+'"');
|
||||
return false;
|
||||
@@ -114,7 +103,7 @@
|
||||
|
||||
// Preparing the cell data
|
||||
cellElem = (itemActions.length > 0) ? $('<a></a>') : $('<span></span>');
|
||||
cellElem.html(row.attributes[att_code].value);
|
||||
cellElem.text(row.attributes[att_code].value);
|
||||
// Building actions
|
||||
if(itemActions.length > 0)
|
||||
{
|
||||
@@ -131,7 +120,7 @@
|
||||
cellElem.attr('data-toggle', 'modal').attr('data-target', '#modal-for-all').attr('href', url);
|
||||
break;
|
||||
default:
|
||||
//console.log('Action "'+itemPrimaryAction+'" not implemented');
|
||||
console.log('Action "'+itemPrimaryAction+'" not implemented');
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -238,7 +227,7 @@
|
||||
// Note : The '.off()' call is to unbind event from DataTables that where triggered before we could intercept anything
|
||||
$('#table-{{ sAreaId }}_filter input').off().on('keyup', function(){
|
||||
var me = this;
|
||||
|
||||
console.log('here');
|
||||
clearTimeout(oKeyTimeout);
|
||||
oKeyTimeout = setTimeout(function() {
|
||||
oTable{{ sAreaId }}.search(me.value.latinise()).draw();
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
{% if form.buttons is defined and form.buttons.transitions is defined and form.buttons.transitions|length > 0 %}
|
||||
<div class="form_btn_transitions">
|
||||
{% for sStimulusCode, sStimulusLabel in form.buttons.transitions %}
|
||||
<button class="btn btn-primary form_btn_transition" type="submit" name="stimulus_code" value="{{ sStimulusCode }}">{{ sStimulusLabel }}</button>
|
||||
<button class="btn btn-default form_btn_transition" type="submit" name="stimulus_code" value="{{ sStimulusCode }}">{{ sStimulusLabel }}</button>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
@@ -67,63 +67,60 @@
|
||||
|
||||
// Sticky buttons handler
|
||||
{% if sMode != 'view' %}
|
||||
if( $('#{{ sFormId }} .form_btn_regular button').length > 0 )
|
||||
// Note : This pattern if to prevent performance issues
|
||||
// - Cloning buttons
|
||||
var oNormalRegularButtons_{{ sFormIdSanitized }} = $('#{{ sFormId }} .form_btn_regular');
|
||||
var oStickyRegularButtons_{{ sFormIdSanitized }} = oNormalRegularButtons_{{ sFormIdSanitized }}.clone(true, true);
|
||||
oStickyRegularButtons_{{ sFormIdSanitized }}.addClass('sticky');
|
||||
if(oStickyRegularButtons_{{ sFormIdSanitized }}.find('.form_btn_submit span.glyphicon').length > 0)
|
||||
{
|
||||
// Note : This pattern if to prevent performance issues
|
||||
// - Cloning buttons
|
||||
var oNormalRegularButtons_{{ sFormIdSanitized }} = $('#{{ sFormId }} .form_btn_regular');
|
||||
var oStickyRegularButtons_{{ sFormIdSanitized }} = oNormalRegularButtons_{{ sFormIdSanitized }}.clone(true, true);
|
||||
oStickyRegularButtons_{{ sFormIdSanitized }}.addClass('sticky');
|
||||
if(oStickyRegularButtons_{{ sFormIdSanitized }}.find('.form_btn_submit span.glyphicon').length > 0)
|
||||
{
|
||||
oStickyRegularButtons_{{ sFormIdSanitized }}.find('.form_btn_submit').html( oStickyRegularButtons_{{ sFormIdSanitized }}.find('.form_btn_submit span.glyphicon')[0].outerHTML );
|
||||
}
|
||||
if(oStickyRegularButtons_{{ sFormIdSanitized }}.find('.form_btn_cancel span.glyphicon').length > 0)
|
||||
{
|
||||
oStickyRegularButtons_{{ sFormIdSanitized }}.find('.form_btn_cancel').html( oStickyRegularButtons_{{ sFormIdSanitized }}.find('.form_btn_cancel span.glyphicon')[0].outerHTML );
|
||||
}
|
||||
|
||||
$('#{{ sFormId }}').closest({% if tIsModal == true %}'.modal'{% else %}'#main-content'{% endif %}).append(oStickyRegularButtons_{{ sFormIdSanitized }});
|
||||
|
||||
// - Global timeout for any
|
||||
var oScrollTimeout;
|
||||
// - Scroll handler
|
||||
scrollHandler_{{ sFormIdSanitized }} = function () {
|
||||
if($('#{{ sFormId }} .form_buttons').visible())
|
||||
{
|
||||
oStickyRegularButtons_{{ sFormIdSanitized }}.addClass('closed');
|
||||
}
|
||||
else
|
||||
{
|
||||
oStickyRegularButtons_{{ sFormIdSanitized }}.removeClass('closed');
|
||||
}
|
||||
};
|
||||
// - Event binding for scroll
|
||||
$({% if tIsModal == true %}'.modal.in'{% else %}window{% endif %}).off('scroll').on('scroll', function () {
|
||||
if (oScrollTimeout) {
|
||||
// Clear the timeout, if one is pending
|
||||
clearTimeout(oScrollTimeout);
|
||||
oScrollTimeout = null;
|
||||
}
|
||||
oScrollTimeout = setTimeout(scrollHandler_{{ sFormIdSanitized }}, 50);
|
||||
});
|
||||
// - Event binding for linkedset collapse
|
||||
$({% if tIsModal == true %}'.modal.in'{% else %}window{% endif %}).off('shown.bs.collapse hidden.bs.collapse').on('shown.bs.collapse hidden.bs.collapse', function () {
|
||||
scrollHandler_{{ sFormIdSanitized }}();
|
||||
});
|
||||
// - Event binding for form building / updating
|
||||
// Note : We do not want to 'off' the event or it will remove listeners from the widget
|
||||
oFieldSet_{{ sFormIdSanitized }}.on('form_built', function(oEvent){
|
||||
scrollHandler_{{ sFormIdSanitized }}();
|
||||
});
|
||||
// - Initial test
|
||||
setTimeout(function(){ scrollHandler_{{ sFormIdSanitized }}(); }, 400);
|
||||
|
||||
// Remove sticky button when closing modal
|
||||
$('#{{ sFormId }}').closest('.modal').on('hide.bs.modal', function () {
|
||||
oStickyRegularButtons_{{ sFormIdSanitized }}.remove();
|
||||
});
|
||||
oStickyRegularButtons_{{ sFormIdSanitized }}.find('.form_btn_submit').html( oStickyRegularButtons_{{ sFormIdSanitized }}.find('.form_btn_submit span.glyphicon')[0].outerHTML );
|
||||
}
|
||||
if(oStickyRegularButtons_{{ sFormIdSanitized }}.find('.form_btn_cancel span.glyphicon').length > 0)
|
||||
{
|
||||
oStickyRegularButtons_{{ sFormIdSanitized }}.find('.form_btn_cancel').html( oStickyRegularButtons_{{ sFormIdSanitized }}.find('.form_btn_cancel span.glyphicon')[0].outerHTML );
|
||||
}
|
||||
|
||||
$('#{{ sFormId }}').closest({% if tIsModal == true %}'.modal'{% else %}'#main-content'{% endif %}).append(oStickyRegularButtons_{{ sFormIdSanitized }});
|
||||
|
||||
// - Global timeout for any
|
||||
var oScrollTimeout;
|
||||
// - Scroll handler
|
||||
scrollHandler_{{ sFormIdSanitized }} = function () {
|
||||
if($('#{{ sFormId }} .form_buttons').visible())
|
||||
{
|
||||
oStickyRegularButtons_{{ sFormIdSanitized }}.addClass('closed');
|
||||
}
|
||||
else
|
||||
{
|
||||
oStickyRegularButtons_{{ sFormIdSanitized }}.removeClass('closed');
|
||||
}
|
||||
};
|
||||
// - Event binding for scroll
|
||||
$({% if tIsModal == true %}'.modal.in'{% else %}window{% endif %}).off('scroll').on('scroll', function () {
|
||||
if (oScrollTimeout) {
|
||||
// Clear the timeout, if one is pending
|
||||
clearTimeout(oScrollTimeout);
|
||||
oScrollTimeout = null;
|
||||
}
|
||||
oScrollTimeout = setTimeout(scrollHandler_{{ sFormIdSanitized }}, 50);
|
||||
});
|
||||
// - Event binding for linkedset collapse
|
||||
$({% if tIsModal == true %}'.modal.in'{% else %}window{% endif %}).off('shown.bs.collapse hidden.bs.collapse').on('shown.bs.collapse hidden.bs.collapse', function () {
|
||||
scrollHandler_{{ sFormIdSanitized }}();
|
||||
});
|
||||
// - Event binding for form building / updating
|
||||
// Note : We do not want to 'off' the event or it will remove listeners from the widget
|
||||
oFieldSet_{{ sFormIdSanitized }}.on('form_built', function(oEvent){
|
||||
scrollHandler_{{ sFormIdSanitized }}();
|
||||
});
|
||||
// - Initial test
|
||||
setTimeout(function(){ scrollHandler_{{ sFormIdSanitized }}(); }, 400);
|
||||
|
||||
// Remove sticky button when closing modal
|
||||
$('#{{ sFormId }}').closest('.modal').on('hide.bs.modal', function () {
|
||||
oStickyRegularButtons_{{ sFormIdSanitized }}.remove();
|
||||
});
|
||||
{% endif %}
|
||||
|
||||
{% if tIsModal == true %}
|
||||
|
||||
@@ -92,7 +92,7 @@
|
||||
|
||||
$(document).ready(function(){
|
||||
showTableLoader();
|
||||
|
||||
|
||||
// Note : Those options should be externalized in an library so we can use them on any DataTables for the portal.
|
||||
// We would just have to override / complete the necessary elements
|
||||
oTable = $('#{{ sTableId }}').DataTable({
|
||||
@@ -152,8 +152,6 @@
|
||||
"url": "{{ app.url_generator.generate('p_object_search_from_attribute', {'sTargetAttCode': sTargetAttCode, 'sHostObjectClass': sHostObjectClass, 'sHostObjectId': sHostObjectId, 'ar_token': sActionRulesToken})|raw }}",
|
||||
"type": "POST",
|
||||
"data": function(d){
|
||||
d.sFormPath = '{{ aSource.sFormPath }}';
|
||||
d.sFieldId = '{{ aSource.sFieldId }}';
|
||||
d.aObjectIdsToIgnore = {{ aSource.aObjectIdsToIgnore|json_encode()|raw }};
|
||||
d.iPageNumber = Math.floor(d.start/d.length) + 1;
|
||||
d.iCountPerPage = d.length;
|
||||
@@ -170,24 +168,6 @@
|
||||
// Retrieving values from source form
|
||||
d.current_values = $('[data-form-path="{{aSource.sFormPath}}"][data-field-id="{{aSource.sFieldId}}"]').closest('.portal_form_handler').portal_form_handler('getCurrentValues');
|
||||
{% endif %}
|
||||
},
|
||||
"error": function(oData, sError, sThrow){
|
||||
if(oData.responseJSON !== undefined && oData.responseJSON !== null)
|
||||
{
|
||||
var oResponse = oData.responseJSON;
|
||||
// If we encounter an error
|
||||
if(oResponse.exception !== undefined)
|
||||
{
|
||||
// Note : This could be refactored for a global use
|
||||
$('#{{ sTableId }}').closest('.modal').html( $('#modal-for-alert').html() );
|
||||
var oModalElem = $('#{{ sTableId }}').closest('.modal');
|
||||
oModalElem.find('.modal-title').html(oResponse.error_title);
|
||||
oModalElem.find('.modal-body .alert').html(oResponse.error_message)
|
||||
.removeClass('alert-success alert-info alert-warning alert-danger')
|
||||
.addClass('alert-danger');
|
||||
oModalElem.modal('show');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
{% if form.buttons is defined and form.buttons.links is defined %}
|
||||
<div class="form_btn_transitions">
|
||||
{% for aLink in form.buttons.links %}
|
||||
<a class="btn btn-primary" href="{{ aLink.url }}">{{ aLink.label }}</a>
|
||||
<a class="btn btn-default" href="{{ aLink.url }}">{{ aLink.label }}</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
<div class="col-sm-6">
|
||||
<div class="panel panel-default user_profile_picture">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">{{ 'Brick:Portal:UserProfile:Photo:Title'|dict_s }}</h3>
|
||||
<h3 class="panel-title">Photo</h3>
|
||||
</div>
|
||||
<div class="panel-body" style="position: relative;">
|
||||
<div class="form_alerts">
|
||||
@@ -189,11 +189,11 @@
|
||||
});
|
||||
// - Undo button
|
||||
/*$('#user-profile-wrapper .actions .btn_undo').on('click', function(oEvent){
|
||||
//console.log('Picture undo trigger');
|
||||
console.log('Picture undo trigger');
|
||||
});*/
|
||||
// - Reset button
|
||||
$('#user-profile-wrapper .actions .btn_reset').on('click', function(oEvent){
|
||||
//console.log('Picture reset trigger');
|
||||
console.log('Picture reset trigger');
|
||||
});
|
||||
|
||||
// Submit button
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
<div class="content_loader">
|
||||
<div class="icon glyphicon glyphicon-refresh"></div>
|
||||
<div class="message">
|
||||
{{ 'Page:PleaseWait'|dict_s }}
|
||||
</div>
|
||||
</div>
|
||||
@@ -22,99 +22,87 @@
|
||||
{# This block can be used to add your own meta tags by extending the default template #}
|
||||
{% block pPageExtraMetas %}
|
||||
{% endblock %}
|
||||
<title>{% block pPageTitle %}{% if sPageTitle is defined and sPageTitle is not null %}{{ sPageTitle }} - {{ constant('ITOP_APPLICATION') }}{% else %}{{ 'Page:DefaultTitle'|dict_s }}{% endif %}{% endblock %}</title>
|
||||
<link rel="shortcut icon" href="{{ app['combodo.absolute_url'] ~ 'images/favicon.ico'|add_itop_version }}" />
|
||||
<title>{% block pPageTitle %}{% if sPageTitle is defined and sPageTitle is not null %}{{ sPageTitle }} - iTop{% else %}{{ 'Page:DefaultTitle'|dict_s }}{% endif %}{% endblock %}</title>
|
||||
<link rel="shortcut icon" href="{{ app['combodo.absolute_url'] }}images/favicon.ico?itopversion=$ITOP_VERSION$" />
|
||||
{% block pPageStylesheets %}
|
||||
{# First bootstrap core, lib themes, then bootstrap theme, portal adjustements #}
|
||||
<link href="{{ app['combodo.portal.base.absolute_url'] ~ 'lib/bootstrap/css/bootstrap.min.css'|add_itop_version }}" rel="stylesheet">
|
||||
<link href="{{ app['combodo.portal.base.absolute_url'] }}lib/bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
||||
{# - Bootstrap Datetime picker #}
|
||||
<link href="{{ app['combodo.portal.base.absolute_url'] ~ 'lib/bootstrap-datetimepicker/css/bootstrap-datetimepicker.min.css'|add_itop_version }}" rel="stylesheet">
|
||||
<link href="{{ app['combodo.portal.base.absolute_url'] }}lib/bootstrap-datetimepicker/css/bootstrap-datetimepicker.min.css" rel="stylesheet">
|
||||
{# - Datatables #}
|
||||
<link href="{{ app['combodo.portal.base.absolute_url'] ~ 'lib/datatables/css/dataTables.bootstrap.min.css'|add_itop_version }}" rel="stylesheet">
|
||||
<link href="{{ app['combodo.portal.base.absolute_url'] ~ 'lib/datatables/css/fixedHeader.bootstrap.min.css'|add_itop_version }}" rel="stylesheet">
|
||||
<link href="{{ app['combodo.portal.base.absolute_url'] ~ 'lib/datatables/css/responsive.bootstrap.min.css'|add_itop_version }}" rel="stylesheet">
|
||||
<link href="{{ app['combodo.portal.base.absolute_url'] ~ 'lib/datatables/css/scroller.bootstrap.min.css'|add_itop_version }}" rel="stylesheet">
|
||||
<link href="{{ app['combodo.portal.base.absolute_url'] ~ 'lib/datatables/css/select.bootstrap.min.css'|add_itop_version }}" rel="stylesheet">
|
||||
<link href="{{ app['combodo.portal.base.absolute_url'] ~ 'lib/datatables/css/select.dataTables.min.css'|add_itop_version }}" rel="stylesheet">
|
||||
<link href="{{ app['combodo.portal.base.absolute_url'] }}lib/datatables/css/dataTables.bootstrap.min.css" rel="stylesheet">
|
||||
<link href="{{ app['combodo.portal.base.absolute_url'] }}lib/datatables/css/fixedHeader.bootstrap.min.css" rel="stylesheet">
|
||||
<link href="{{ app['combodo.portal.base.absolute_url'] }}lib/datatables/css/responsive.bootstrap.min.css" rel="stylesheet">
|
||||
<link href="{{ app['combodo.portal.base.absolute_url'] }}lib/datatables/css/scroller.bootstrap.min.css" rel="stylesheet">
|
||||
<link href="{{ app['combodo.portal.base.absolute_url'] }}lib/datatables/css/select.bootstrap.min.css" rel="stylesheet">
|
||||
<link href="{{ app['combodo.portal.base.absolute_url'] }}lib/datatables/css/select.dataTables.min.css" rel="stylesheet">
|
||||
{# - Font Combodo #}
|
||||
<link href="{{ app['combodo.absolute_url'] ~ 'css/font-combodo/font-combodo.css'|add_itop_version }}" rel="stylesheet">
|
||||
<link href="{{ app['combodo.absolute_url'] }}css/font-combodo/font-combodo.css" rel="stylesheet">
|
||||
{# - Font awesome #}
|
||||
<link href="{{ app['combodo.portal.base.absolute_url'] ~ 'lib/font-awesome/css/font-awesome.min.css'|add_itop_version }}" rel="stylesheet">
|
||||
<link href="{{ app['combodo.portal.base.absolute_url'] }}lib/font-awesome/css/font-awesome.min.css" rel="stylesheet">
|
||||
{# - Misc libs #}
|
||||
<link href="{{ app['combodo.portal.base.absolute_url'] ~ 'lib/typeahead/css/typeaheadjs.bootstrap.css'|add_itop_version }}" rel="stylesheet">
|
||||
<link href="{{ app['combodo.absolute_url'] ~ 'css/magnific-popup.css'|add_itop_version }}" rel="stylesheet">
|
||||
<link href="{{ app['combodo.portal.base.absolute_url'] }}lib/typeahead/css/typeaheadjs.bootstrap.css" rel="stylesheet">
|
||||
<link href="{{ app['combodo.absolute_url'] }}css/magnific-popup.css" rel="stylesheet">
|
||||
{# - Bootstrap theme #}
|
||||
<link href="{{ app['combodo.portal.instance.conf'].properties.themes.bootstrap|add_itop_version }}" rel="stylesheet" id="css_bootstrap_theme">
|
||||
<link href="{{ app['combodo.portal.instance.conf'].properties.themes.bootstrap }}" rel="stylesheet" id="css_bootstrap_theme">
|
||||
{# - Portal adjustments for BS theme #}
|
||||
<link href="{{ app['combodo.portal.instance.conf'].properties.themes.portal|add_itop_version }}" rel="stylesheet" id="css_portal">
|
||||
<link href="{{ app['combodo.portal.instance.conf'].properties.themes.portal }}" rel="stylesheet" id="css_portal">
|
||||
{# Custom CSS that is supposed to do adjustments to the portal #}
|
||||
{% if app['combodo.portal.instance.conf'].properties.themes.custom is defined %}
|
||||
<link href="{{ app['combodo.portal.instance.conf'].properties.themes.custom|add_itop_version }}" rel="stylesheet">
|
||||
<link href="{{ app['combodo.portal.instance.conf'].properties.themes.custom }}" rel="stylesheet">
|
||||
{% endif %}
|
||||
{# Others CSS that will come after the theme/portal/custom, in an undefined order #}
|
||||
{% if app['combodo.portal.instance.conf'].properties.themes.others is defined %}
|
||||
{% for theme in app['combodo.portal.instance.conf'].properties.themes.others %}
|
||||
<link href="{{ theme|add_itop_version }}" rel="stylesheet">
|
||||
<link href="{{ theme }}" rel="stylesheet">
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
{% block pPageScripts %}
|
||||
<script type="text/javascript" src="{{ app['combodo.portal.base.absolute_url'] ~ 'lib/jquery/jquery-1.11.3.min.js'|add_itop_version }}"></script>
|
||||
<script type="text/javascript" src="{{ app['combodo.absolute_url'] ~ 'js/jquery-ui-1.10.3.custom.min.js'|add_itop_version }}"></script>
|
||||
<script type="text/javascript" src="{{ app['combodo.absolute_url'] ~ 'js/jquery.magnific-popup.min.js'|add_itop_version }}"></script>
|
||||
<script type="text/javascript" src="{{ app['combodo.absolute_url'] ~ 'js/jquery.iframe-transport.js'|add_itop_version }}"></script>
|
||||
<script type="text/javascript" src="{{ app['combodo.absolute_url'] ~ 'js/jquery.fileupload.js'|add_itop_version }}"></script>
|
||||
<script type="text/javascript" src="{{ app['combodo.portal.base.absolute_url'] ~ 'lib/bootstrap/js/bootstrap.min.js'|add_itop_version }}"></script>
|
||||
<script type="text/javascript" src="{{ app['combodo.portal.base.absolute_url'] ~ 'lib/latinise/latinise.min.js'|add_itop_version }}"></script>
|
||||
<script type="text/javascript" src="{{ app['combodo.portal.base.absolute_url'] }}lib/jquery/jquery-1.11.3.min.js"></script>
|
||||
<script type="text/javascript" src="{{ app['combodo.absolute_url'] }}js/jquery-ui-1.10.3.custom.min.js"></script>
|
||||
<script type="text/javascript" src="{{ app['combodo.absolute_url'] }}js/jquery.magnific-popup.min.js"></script>
|
||||
<script type="text/javascript" src="{{ app['combodo.absolute_url'] }}js/jquery.fileupload.js"></script>
|
||||
<script type="text/javascript" src="{{ app['combodo.portal.base.absolute_url'] }}lib/bootstrap/js/bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="{{ app['combodo.portal.base.absolute_url'] }}lib/latinise/latinise.min.js"></script>
|
||||
{# Visible.js to check if an element is visible on screen #}
|
||||
<script type="text/javascript" src="{{ app['combodo.portal.base.absolute_url'] ~ 'lib/jquery-visible/js/jquery.visible.min.js'|add_itop_version }}"></script>
|
||||
<script type="text/javascript" src="{{ app['combodo.portal.base.absolute_url'] }}lib/jquery-visible/js/jquery.visible.min.js"></script>
|
||||
{# Base64.js #}
|
||||
<script type="text/javascript" src="{{ app['combodo.portal.base.absolute_url'] ~ 'lib/jquery-base64/js/jquery.base64.min.js'|add_itop_version }}"></script>
|
||||
<script type="text/javascript" src="{{ app['combodo.portal.base.absolute_url'] }}lib/jquery-base64/js/jquery.base64.min.js"></script>
|
||||
{# Moment.js #}
|
||||
<script type="text/javascript" src="{{ app['combodo.portal.base.absolute_url'] ~ 'lib/moment/js/moment.min.js'|add_itop_version }}"></script>
|
||||
<script type="text/javascript" src="{{ app['combodo.portal.base.absolute_url'] }}lib/moment/js/moment.min.js"></script>
|
||||
{# Datatables #}
|
||||
<script type="text/javascript" src="{{ app['combodo.portal.base.absolute_url'] ~ 'lib/datatables/js/jquery.dataTables.min.js'|add_itop_version }}"></script>
|
||||
<script type="text/javascript" src="{{ app['combodo.portal.base.absolute_url'] ~ 'lib/datatables/js/dataTables.bootstrap.min.js'|add_itop_version }}"></script>
|
||||
<script type="text/javascript" src="{{ app['combodo.portal.base.absolute_url'] ~ 'lib/datatables/js/dataTables.fixedHeader.min.js'|add_itop_version }}"></script>
|
||||
<script type="text/javascript" src="{{ app['combodo.portal.base.absolute_url'] ~ 'lib/datatables/js/dataTables.responsive.min.js'|add_itop_version }}"></script>
|
||||
<script type="text/javascript" src="{{ app['combodo.portal.base.absolute_url'] ~ 'lib/datatables/js/dataTables.scroller.min.js'|add_itop_version }}"></script>
|
||||
<script type="text/javascript" src="{{ app['combodo.portal.base.absolute_url'] ~ 'lib/datatables/js/dataTables.select.min.js'|add_itop_version }}"></script>
|
||||
<script type="text/javascript" src="{{ app['combodo.portal.base.absolute_url'] ~ 'lib/datatables/js/datetime-moment.js'|add_itop_version }}"></script>
|
||||
<script type="text/javascript" src="{{ app['combodo.portal.base.absolute_url'] ~ 'js/dataTables.accentNeutraliseForFilter.js'|add_itop_version }}"></script>
|
||||
<script type="text/javascript" src="{{ app['combodo.portal.base.absolute_url'] }}lib/datatables/js/jquery.dataTables.min.js"></script>
|
||||
<script type="text/javascript" src="{{ app['combodo.portal.base.absolute_url'] }}lib/datatables/js/dataTables.bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="{{ app['combodo.portal.base.absolute_url'] }}lib/datatables/js/dataTables.fixedHeader.min.js"></script>
|
||||
<script type="text/javascript" src="{{ app['combodo.portal.base.absolute_url'] }}lib/datatables/js/dataTables.responsive.min.js"></script>
|
||||
<script type="text/javascript" src="{{ app['combodo.portal.base.absolute_url'] }}lib/datatables/js/dataTables.scroller.min.js"></script>
|
||||
<script type="text/javascript" src="{{ app['combodo.portal.base.absolute_url'] }}lib/datatables/js/dataTables.select.min.js"></script>
|
||||
<script type="text/javascript" src="{{ app['combodo.portal.base.absolute_url'] }}lib/datatables/js/datetime-moment.js"></script>
|
||||
<script type="text/javascript" src="{{ app['combodo.portal.base.absolute_url'] }}js/dataTables.accentNeutraliseForFilter.js"></script>
|
||||
{# CKEditor files for HTML WYSIWYG #}
|
||||
<script type="text/javascript" src="{{ app['combodo.absolute_url'] ~ 'js/ckeditor/ckeditor.js'|add_itop_version }}"></script>
|
||||
<script type="text/javascript" src="{{ app['combodo.absolute_url'] ~ 'js/ckeditor/adapters/jquery.js'|add_itop_version }}"></script>
|
||||
<script type="text/javascript" src="{{ app['combodo.absolute_url'] }}js/ckeditor/ckeditor.js"></script>
|
||||
<script type="text/javascript" src="{{ app['combodo.absolute_url'] }}js/ckeditor/adapters/jquery.js"></script>
|
||||
{# Date-time picker for Bootstrap #}
|
||||
<script type="text/javascript" src="{{ app['combodo.portal.base.absolute_url'] ~ 'lib/bootstrap-datetimepicker/js/bootstrap-datetimepicker.min.js'|add_itop_version }}"></script>
|
||||
<script type="text/javascript" src="{{ app['combodo.portal.base.absolute_url'] }}lib/bootstrap-datetimepicker/js/bootstrap-datetimepicker.min.js"></script>
|
||||
{# Typeahead files for autocomplete #}
|
||||
<script type="text/javascript" src="{{ app['combodo.portal.base.absolute_url'] ~ 'lib/typeahead/js/bloodhound.min.js'|add_itop_version }}"></script>
|
||||
<script type="text/javascript" src="{{ app['combodo.portal.base.absolute_url'] ~ 'lib/typeahead/js/typeahead.bundle.min.js'|add_itop_version }}"></script>
|
||||
<script type="text/javascript" src="{{ app['combodo.portal.base.absolute_url'] ~ 'lib/typeahead/js/typeahead.jquery.min.js'|add_itop_version }}"></script>
|
||||
<script type="text/javascript" src="{{ app['combodo.portal.base.absolute_url'] ~ 'lib/handlebars/js/handlebars.min-768ddbd.js'|add_itop_version }}"></script>
|
||||
<script type="text/javascript" src="{{ app['combodo.portal.base.absolute_url'] }}lib/typeahead/js/bloodhound.min.js"></script>
|
||||
<script type="text/javascript" src="{{ app['combodo.portal.base.absolute_url'] }}lib/typeahead/js/typeahead.bundle.min.js"></script>
|
||||
<script type="text/javascript" src="{{ app['combodo.portal.base.absolute_url'] }}lib/typeahead/js/typeahead.jquery.min.js"></script>
|
||||
<script type="text/javascript" src="{{ app['combodo.portal.base.absolute_url'] }}lib/handlebars/js/handlebars.min-768ddbd.js"></script>
|
||||
{# Form files #}
|
||||
<script type="text/javascript" src="{{ app['combodo.absolute_url'] ~ 'js/form_handler.js'|add_itop_version }}"></script>
|
||||
<script type="text/javascript" src="{{ app['combodo.absolute_url'] ~ 'js/form_field.js'|add_itop_version }}"></script>
|
||||
<script type="text/javascript" src="{{ app['combodo.absolute_url'] ~ 'js/subform_field.js'|add_itop_version }}"></script>
|
||||
<script type="text/javascript" src="{{ app['combodo.absolute_url'] ~ 'js/field_set.js'|add_itop_version }}"></script>
|
||||
<script type="text/javascript" src="{{ app['combodo.absolute_url'] }}js/form_handler.js"></script>
|
||||
<script type="text/javascript" src="{{ app['combodo.absolute_url'] }}js/form_field.js"></script>
|
||||
<script type="text/javascript" src="{{ app['combodo.absolute_url'] }}js/subform_field.js"></script>
|
||||
<script type="text/javascript" src="{{ app['combodo.absolute_url'] }}js/field_set.js"></script>
|
||||
{# Form files for portal #}
|
||||
<script type="text/javascript" src="{{ app['combodo.portal.base.absolute_url'] ~ 'js/portal_form_handler.js'|add_itop_version }}"></script>
|
||||
<script type="text/javascript" src="{{ app['combodo.portal.base.absolute_url'] ~ 'js/portal_form_field.js'|add_itop_version }}"></script>
|
||||
<script type="text/javascript" src="{{ app['combodo.portal.base.absolute_url'] ~ 'js/portal_form_field_html.js'|add_itop_version }}"></script>
|
||||
<script type="text/javascript" src="{{ app['combodo.portal.base.absolute_url'] }}js/portal_form_handler.js"></script>
|
||||
<script type="text/javascript" src="{{ app['combodo.portal.base.absolute_url'] }}js/portal_form_field.js"></script>
|
||||
<script type="text/javascript" src="{{ app['combodo.portal.base.absolute_url'] }}js/portal_form_field_html.js"></script>
|
||||
{% endblock %}
|
||||
</head>
|
||||
<body class="{% block pPageBodyClass %}{% endblock %}">
|
||||
{% block pPageBodyWrapper %}
|
||||
{% block pEnvBannerWrapper %}
|
||||
{% if app['combodo.current_environment'] != 'production' %}
|
||||
<div id="envbanner" class="alert alert-danger" role="alert">
|
||||
{{ 'Portal:EnvironmentBanner:Title'|dict_format( app['combodo.current_environment']|upper )|raw }}
|
||||
<button type="button" onclick="window;location.href='{{ app['url_generator'].generate('p_home', {'switch_env': 'production'}) }}'">
|
||||
{{ 'Portal:EnvironmentBanner:GoToProduction'|dict_s|raw }}
|
||||
</button>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block pNavigationWrapper %}
|
||||
{# Topbar navigation menu for mobile screens #}
|
||||
<nav class="navbar navbar-fixed-top navbar-default visible-xs" id="topbar" role="navigation">
|
||||
@@ -272,7 +260,12 @@
|
||||
<div class="modal fade" id="modal-for-all" role="dialog">
|
||||
<div class="modal-dialog modal-lg" role="document">
|
||||
<div class="modal-content">
|
||||
{% include 'itop-portal-base/portal/src/views/helpers/loader.html.twig' %}
|
||||
<div class="content_loader">
|
||||
<div class="icon glyphicon glyphicon-refresh"></div>
|
||||
<div class="message">
|
||||
{{ 'Page:PleaseWait'|dict_s }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -296,7 +289,12 @@
|
||||
|
||||
<div id="page_overlay" class="global_overlay">
|
||||
<div class="overlay_content">
|
||||
{% include 'itop-portal-base/portal/src/views/helpers/loader.html.twig' %}
|
||||
<div class="content_loader">
|
||||
<div class="icon glyphicon glyphicon-refresh"></div>
|
||||
<div class="message">
|
||||
{{ 'Page:PleaseWait'|dict_s }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -307,22 +305,19 @@
|
||||
{
|
||||
return '{{ app['combodo.absolute_url'] }}';
|
||||
};
|
||||
var AddParameterToUrl = function(sUrl, sParamName, sParamValue)
|
||||
var addParameterToUrl = function(sUrl, sParamName, sParamValue)
|
||||
{
|
||||
sUrl += (sUrl.split('?')[1] ? '&':'?') + sParamName + '=' + sParamValue;
|
||||
return sUrl;
|
||||
};
|
||||
var GetContentLoaderTemplate = function()
|
||||
{
|
||||
return '<div class="content_loader"><div class="icon glyphicon glyphicon-refresh"></div><div class="message">{{ 'Page:PleaseWait'|dict_s }}</div></div>';
|
||||
}
|
||||
var contentLoaderTemplate = '<div class="content_loader"><div class="icon glyphicon glyphicon-refresh"></div><div class="message">{{ 'Page:PleaseWait'|dict_s }}</div></div>';
|
||||
|
||||
$(document).ready(function(){
|
||||
{% block pPageReadyScripts %}
|
||||
// Hack to enable a same modal to load content from different urls
|
||||
$('body').on('hidden.bs.modal', '.modal#modal-for-all', function () {
|
||||
$(this).removeData('bs.modal');
|
||||
$(this).find('.modal-content').html(GetContentLoaderTemplate());
|
||||
$(this).find('.modal-content').html(contentLoaderTemplate);
|
||||
});
|
||||
// Hack to enable multiple modals by making sure the .modal-open class is set to the <body> when there is at least one modal open left
|
||||
$('body').on('hidden.bs.modal', function () {
|
||||
@@ -340,7 +335,7 @@
|
||||
$('body').on('loaded.bs.modal', function (oEvent) {
|
||||
var sModalContent = $(oEvent.target).find('.modal-content').html();
|
||||
|
||||
if( (sModalContent === '') || (sModalContent.replace(/[\n\r\t]+/g, '') === GetContentLoaderTemplate()) )
|
||||
if( (sModalContent === '') || (sModalContent.replace(/[\n\r\t]+/g, '') === contentLoaderTemplate) )
|
||||
{
|
||||
$(oEvent.target).find('.modal-content').html($('#modal-for-alert .modal-content').html());
|
||||
$(oEvent.target).find('.modal-content .modal-header .modal-title').text('{{ 'Error:HTTP:500'|dict_s }}');
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
{# modal/layout.html.twig #}
|
||||
{# Base modal layout, used to fill Bootstrap .modal-content #}
|
||||
{% block pModalContent %}
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h4 class="modal-title">{% block pModalTitle %}{% endblock %}</h4>
|
||||
</div>
|
||||
<div class="modal-body">{% block pModalBody %}{% endblock %}</div>
|
||||
<div class="modal-footer">
|
||||
{% block pModalFooter %}
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">{{ 'Portal:ButtonClose'|dict_s }}</button>
|
||||
{% endblock %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h4 class="modal-title">{% block pModalTitle %}{% endblock %}</h4>
|
||||
</div>
|
||||
<div class="modal-body">{% block pModalBody %}{% endblock %}</div>
|
||||
<div class="modal-footer">
|
||||
{% block pModalFooter %}
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">{{ 'Portal:ButtonClose'|dict_s }}</button>
|
||||
{% endblock %}
|
||||
</div>
|
||||
@@ -1,15 +0,0 @@
|
||||
{# itop-portal-base/portal/src/views/bricks/object/mode_loader.html.twig #}
|
||||
{# Modal loader layout #}
|
||||
{% extends 'itop-portal-base/portal/src/views/modal/layout.html.twig' %}
|
||||
|
||||
{% block pModalContent %}
|
||||
{% include 'itop-portal-base/portal/src/views/helpers/loader.html.twig' %}
|
||||
|
||||
{% if redirection is defined and redirection.url is defined %}
|
||||
<script type="text/javascript">
|
||||
$(document).ready( function(){
|
||||
window.location = '{{ redirection.url|raw }}';
|
||||
});
|
||||
</script>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
@@ -15,17 +15,6 @@
|
||||
footer {
|
||||
margin: 5em 1em;
|
||||
}
|
||||
/* Environment banner */
|
||||
#envbanner {
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
padding: 5px 15px;
|
||||
text-align: center;
|
||||
}
|
||||
#envbanner > button {
|
||||
margin-left: 5px;
|
||||
color: #000;
|
||||
}
|
||||
/* Navigation menu */
|
||||
.navbar-nav .dropdown-menu a .glyphicon, .user_infos .dropdown-menu a .glyphicon {
|
||||
margin-right: 15px;
|
||||
@@ -278,10 +267,6 @@ footer {
|
||||
.mfp-wrap {
|
||||
z-index: 1210;
|
||||
}
|
||||
.mfp-img {
|
||||
cursor: pointer;
|
||||
cursor: zoom-out;
|
||||
}
|
||||
/********************/
|
||||
/* Typeahed setting */
|
||||
/********************/
|
||||
@@ -453,10 +438,6 @@ footer {
|
||||
.dataTables_wrapper {
|
||||
padding: 10px 10px;
|
||||
}
|
||||
.dataTable.table td img {
|
||||
max-width: 100%;
|
||||
height: initial !important;
|
||||
}
|
||||
#brick_content_toolbar {
|
||||
/* margin: 10px 0px 6px 0px; */
|
||||
padding: 10px;
|
||||
@@ -621,11 +602,6 @@ table .group-actions {
|
||||
color: #ea7d1e;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
/* InlineImage */
|
||||
.inline-image {
|
||||
cursor: pointer;
|
||||
cursor: zoom-in;
|
||||
}
|
||||
/* CaseLog field */
|
||||
.caselog_field_entry {
|
||||
border: 1px solid #ddd;
|
||||
@@ -646,7 +622,6 @@ table .group-actions {
|
||||
font-size: 16px;
|
||||
border: 1px solid #a6a6a6;
|
||||
border-bottom-color: #979797;
|
||||
cursor: pointer;
|
||||
}
|
||||
.caselog_field_entry_button:hover {
|
||||
background-color: #ccc;
|
||||
@@ -663,12 +638,10 @@ table .group-actions {
|
||||
}
|
||||
/* LinkedSet*/
|
||||
.form_linkedset_toggler, .form_linkedset_toggler:hover, .form_linkedset_toggler:focus {
|
||||
margin-left: 0.4em;
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
}
|
||||
.form_linkedset_toggler > .text {
|
||||
margin-left: 0.4em;
|
||||
}
|
||||
.form_linkedset_toggler > .text:before {
|
||||
content: "(";
|
||||
}
|
||||
@@ -823,10 +796,6 @@ table .group-actions {
|
||||
}
|
||||
}
|
||||
}
|
||||
/* BlobField */
|
||||
.form_fields .file_open_link {
|
||||
margin-left: 10px;
|
||||
}
|
||||
.form_field .form-control-static img {
|
||||
max-width: 100% !important;
|
||||
height: initial !important;
|
||||
@@ -847,8 +816,7 @@ table .group-actions {
|
||||
@media (min-width: 768px) {
|
||||
/* Making regular button sticky */
|
||||
.form_buttons .form_btn_transitions {
|
||||
float: right !important;
|
||||
margin-left: 3px;
|
||||
float: left !important;
|
||||
}
|
||||
.form_buttons .form_btn_regular {
|
||||
text-align: right;
|
||||
@@ -917,17 +885,9 @@ table .group-actions {
|
||||
border-color: #fbeed5;
|
||||
color: #c09853;
|
||||
}
|
||||
/* CKEditor : Misc */
|
||||
.cke_toolbox_collapser, .cke_toolbox_collapser .cke_arrow {
|
||||
cursor: pointer !important;
|
||||
}
|
||||
/* DataTables : Selection inputs */
|
||||
.dataTable.table th span.row_input, .dataTable.table td span.row_input {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
/* Wiki text (hyperlinks) */
|
||||
.wiki_broken_link {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
@@ -19,18 +19,6 @@ footer{
|
||||
margin: 5em 1em;
|
||||
}
|
||||
|
||||
/* Environment banner */
|
||||
#envbanner{
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
padding: 5px 15px;
|
||||
text-align: center;
|
||||
}
|
||||
#envbanner > button{
|
||||
margin-left: 5px;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
/* Navigation menu */
|
||||
.navbar-nav .dropdown-menu a .glyphicon,
|
||||
.user_infos .dropdown-menu a .glyphicon{
|
||||
@@ -294,10 +282,6 @@ footer{
|
||||
.mfp-wrap{
|
||||
z-index: 1210;
|
||||
}
|
||||
.mfp-img{
|
||||
cursor: pointer;
|
||||
cursor: zoom-out;
|
||||
}
|
||||
|
||||
/********************/
|
||||
/* Typeahed setting */
|
||||
@@ -477,10 +461,6 @@ footer{
|
||||
.dataTables_wrapper{
|
||||
padding: 10px 10px;
|
||||
}
|
||||
.dataTable.table td img{
|
||||
max-width: 100%;
|
||||
height: initial !important;
|
||||
}
|
||||
#brick_content_toolbar{
|
||||
/* margin: 10px 0px 6px 0px; */
|
||||
padding: 10px;
|
||||
@@ -660,11 +640,6 @@ table .group-actions .item-action-wrapper .panel-body > p:last-child{
|
||||
color: $brand-primary;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
/* InlineImage */
|
||||
.inline-image{
|
||||
cursor: pointer;
|
||||
cursor: zoom-in;
|
||||
}
|
||||
/* CaseLog field */
|
||||
.caselog_field_entry{
|
||||
border: 1px solid $gray-lighter;
|
||||
@@ -685,7 +660,6 @@ table .group-actions .item-action-wrapper .panel-body > p:last-child{
|
||||
font-size: 16px;
|
||||
border: 1px solid #a6a6a6;
|
||||
border-bottom-color: #979797;
|
||||
cursor: pointer;
|
||||
}
|
||||
.caselog_field_entry_button:hover{
|
||||
background-color: #cccccc;
|
||||
@@ -704,12 +678,10 @@ table .group-actions .item-action-wrapper .panel-body > p:last-child{
|
||||
.form_linkedset_toggler,
|
||||
.form_linkedset_toggler:hover,
|
||||
.form_linkedset_toggler:focus{
|
||||
margin-left: 0.4em;
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
}
|
||||
.form_linkedset_toggler > .text{
|
||||
margin-left: 0.4em;
|
||||
}
|
||||
.form_linkedset_toggler > .text:before{
|
||||
content: "(";
|
||||
}
|
||||
@@ -864,10 +836,6 @@ table .group-actions .item-action-wrapper .panel-body > p:last-child{
|
||||
}
|
||||
}
|
||||
}
|
||||
/* BlobField */
|
||||
.form_fields .file_open_link{
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.form_field .form-control-static img{
|
||||
max-width: 100% !important;
|
||||
@@ -889,8 +857,7 @@ table .group-actions .item-action-wrapper .panel-body > p:last-child{
|
||||
}
|
||||
@media (min-width: 768px){
|
||||
.form_buttons .form_btn_transitions{
|
||||
float: right !important;
|
||||
margin-left: 3px;
|
||||
float: left !important;
|
||||
}
|
||||
.form_buttons .form_btn_regular{
|
||||
text-align: right;
|
||||
@@ -960,11 +927,6 @@ table .group-actions .item-action-wrapper .panel-body > p:last-child{
|
||||
border-color: $alert-warning-border;
|
||||
color: $alert-warning-text;
|
||||
}
|
||||
/* CKEditor : Misc */
|
||||
.cke_toolbox_collapser,
|
||||
.cke_toolbox_collapser .cke_arrow{
|
||||
cursor: pointer !important;
|
||||
}
|
||||
|
||||
/* DataTables : Selection inputs */
|
||||
.dataTable.table th span.row_input,
|
||||
@@ -972,8 +934,4 @@ table .group-actions .item-action-wrapper .panel-body > p:last-child{
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
/* Wiki text (hyperlinks) */
|
||||
.wiki_broken_link {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
@@ -73,16 +73,12 @@ $oApp->register(new Combodo\iTop\Portal\Provider\ScopeValidatorServiceProvider()
|
||||
'scope_validator.instance_name' => PORTAL_ID
|
||||
));
|
||||
$oApp->register(new Silex\Provider\TwigServiceProvider(), array(
|
||||
'twig.path' => MODULESROOT,
|
||||
'twig.options' => array(
|
||||
'cache' => utils::GetCachePath() . 'twig/'
|
||||
)
|
||||
'twig.path' => MODULESROOT
|
||||
));
|
||||
$oApp->register(new Silex\Provider\HttpFragmentServiceProvider());
|
||||
|
||||
// Configuring Silex application
|
||||
$oApp['debug'] = $bDebug;
|
||||
$oApp['combodo.current_environment'] = utils::GetCurrentEnvironment();
|
||||
$oApp['combodo.absolute_url'] = utils::GetAbsoluteUrlAppRoot();
|
||||
$oApp['combodo.portal.base.absolute_url'] = utils::GetAbsoluteUrlAppRoot() . 'env-' . utils::GetCurrentEnvironment() . '/itop-portal-base/portal/web/';
|
||||
$oApp['combodo.portal.base.absolute_path'] = MODULESROOT . '/itop-portal-base/portal/web/';
|
||||
|
||||
@@ -135,16 +135,6 @@ $(function()
|
||||
// If everything is okay, we close the form and reload it.
|
||||
if(oValidation.valid)
|
||||
{
|
||||
// Resetting textarea fields (delay is necessary has we have to wait for the form to be built.
|
||||
setTimeout(function(){
|
||||
me.options.field_set.find('.portal_form_field_html').each(function(iIndex, oElem){
|
||||
if($(oElem).find('.cke').length > 0)
|
||||
{
|
||||
$(oElem).triggerHandler('set_current_value', '');
|
||||
}
|
||||
});
|
||||
}, 200);
|
||||
|
||||
if(me.options.is_modal)
|
||||
{
|
||||
me.element.closest('.modal').modal('hide');
|
||||
@@ -181,13 +171,7 @@ $(function()
|
||||
oModalElem.attr('id', '').appendTo('body');
|
||||
// Loading content
|
||||
oModalElem.find('.modal-content').html($('#page_overlay .overlay_content').html());
|
||||
oModalElem.find('.modal-content').load(sUrl, {
|
||||
// Passing formmanager data to the next page, just in case it needs it (eg. when applying stimulus)
|
||||
formmanager_class: me.options.formmanager_class,
|
||||
formmanager_data: JSON.stringify(me.options.formmanager_data)
|
||||
}
|
||||
);
|
||||
|
||||
oModalElem.find('.modal-content').load(sUrl);
|
||||
oModalElem.modal('show');
|
||||
}
|
||||
else
|
||||
|
||||
@@ -1,99 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Локализация интерфейса Combodo iTop подготовлена сообществом iTop по-русски http://community.itop-itsm.ru.
|
||||
*
|
||||
* @author Vladimir Kunin <v.b.kunin@gmail.com>
|
||||
* @link http://community.itop-itsm.ru iTop Russian Community
|
||||
* @link https://github.com/itop-itsm-ru/itop-rus
|
||||
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
|
||||
*
|
||||
*/
|
||||
|
||||
// Portal
|
||||
Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Page:DefaultTitle' => 'Пользовательский портал iTop',
|
||||
'Page:PleaseWait' => 'Пожалуйста, подождите...',
|
||||
'Page:Home' => 'Домашняя страница',
|
||||
'Page:GoPortalHome' => 'Домашняя страница',
|
||||
'Page:GoPreviousPage' => 'Предыдущяя страница',
|
||||
'Portal:Button:Submit' => 'Применить',
|
||||
'Portal:Button:Cancel' => 'Отменить',
|
||||
'Portal:Button:Close' => 'Закрыть',
|
||||
'Portal:Button:Add' => 'Добавить',
|
||||
'Portal:Button:Remove' => 'Удалить',
|
||||
'Portal:Button:Delete' => 'Удалить',
|
||||
'Error:HTTP:404' => 'Страница не найдена',
|
||||
'Error:HTTP:500' => 'Упс! Произошла ошибка.',
|
||||
'Error:XHR:Fail' => 'Не удалось загрузить данные. Пожалуйста, свяжитесь с вашим администратором iTop.',
|
||||
'Error:HTTP:GetHelp' => 'Пожалуйста, свяжитесь с вашим администратором iTop, если проблема сохраняется.',
|
||||
'Portal:Datatables:Language:Processing' => 'Пожалуйста, подождите...',
|
||||
'Portal:Datatables:Language:Search' => 'Фильтр :',
|
||||
'Portal:Datatables:Language:LengthMenu' => 'Показывать _MENU_ элементов на странице',
|
||||
'Portal:Datatables:Language:ZeroRecords' => 'Нет записей',
|
||||
'Portal:Datatables:Language:Info' => 'Страница _PAGE_ из _PAGES_',
|
||||
'Portal:Datatables:Language:InfoEmpty' => 'Нет информации',
|
||||
'Portal:Datatables:Language:InfoFiltered' => 'Отфильтровано из _MAX_ элементов',
|
||||
'Portal:Datatables:Language:EmptyTable' => 'Нет данных в этой таблице',
|
||||
'Portal:Datatables:Language:DisplayLength:All' => 'Все',
|
||||
'Portal:Datatables:Language:Paginate:First' => 'Первая',
|
||||
'Portal:Datatables:Language:Paginate:Previous' => 'Предыдущая',
|
||||
'Portal:Datatables:Language:Paginate:Next' => 'Следующая',
|
||||
'Portal:Datatables:Language:Paginate:Last' => 'Последняя',
|
||||
'Portal:Datatables:Language:Sort:Ascending' => 'Включить сортировку по возрастанию',
|
||||
'Portal:Datatables:Language:Sort:Descending' => 'Включить сортировку по убыванию',
|
||||
'Portal:Autocomplete:NoResult' => 'Нет данных',
|
||||
'Portal:Attachments:DropZone:Message' => 'Перетащите файл для добавления вложения',
|
||||
));
|
||||
|
||||
// UserProfile brick
|
||||
Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Brick:Portal:UserProfile:Name' => 'Профиль пользователя',
|
||||
'Brick:Portal:UserProfile:Navigation:Dropdown:MyProfil' => 'Мой профиль',
|
||||
'Brick:Portal:UserProfile:Navigation:Dropdown:Logout' => 'Выйти',
|
||||
'Brick:Portal:UserProfile:Password:Title' => 'Пароль',
|
||||
'Brick:Portal:UserProfile:Password:ChoosePassword' => 'Введите новый пароль',
|
||||
'Brick:Portal:UserProfile:Password:ConfirmPassword' => 'Подтвердите новый пароль',
|
||||
'Brick:Portal:UserProfile:Password:CantChangeContactAdministrator' => 'Пожалуйста, свяжитесь с вашим администратором iTop для изменения пароля.',
|
||||
'Brick:Portal:UserProfile:Password:CantChangeForUnknownReason' => 'Не удалось изменить пароль, пожалуйста, свяжитесь с вашим администратором iTop.',
|
||||
'Brick:Portal:UserProfile:PersonalInformations:Title' => 'Персональная информация',
|
||||
'Brick:Portal:UserProfile:Photo:Title' => 'Фотография',
|
||||
));
|
||||
|
||||
// BrowseBrick brick
|
||||
Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Brick:Portal:Browse:Name' => 'Просмотр элементов',
|
||||
'Brick:Portal:Browse:Mode:List' => 'Список',
|
||||
'Brick:Portal:Browse:Mode:Tree' => 'Дерево',
|
||||
'Brick:Portal:Browse:Action:Drilldown' => 'Детализация',
|
||||
'Brick:Portal:Browse:Action:View' => 'Подробно',
|
||||
'Brick:Portal:Browse:Action:Edit' => 'Изменить',
|
||||
'Brick:Portal:Browse:Action:Create' => 'Создать',
|
||||
'Brick:Portal:Browse:Action:CreateObjectFromThis' => 'Новый %1$s',
|
||||
'Brick:Portal:Browse:Tree:ExpandAll' => 'Развернуть все',
|
||||
'Brick:Portal:Browse:Tree:CollapseAll' => 'Свернуть все',
|
||||
'Brick:Portal:Browse:Filter:NoData' => 'Нет элементов',
|
||||
));
|
||||
|
||||
// ManageBrick brick
|
||||
Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Brick:Portal:Manage:Name' => 'Управление элементами',
|
||||
'Brick:Portal:Manage:Table:NoData' => 'Нет элементов',
|
||||
));
|
||||
|
||||
// ObjectBrick brick
|
||||
Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Brick:Portal:Object:Name' => 'Object',
|
||||
'Brick:Portal:Object:Form:Create:Title' => 'Создать %1$s',
|
||||
'Brick:Portal:Object:Form:Edit:Title' => 'Обновление %2$s (%1$s)',
|
||||
'Brick:Portal:Object:Form:View:Title' => '%1$s : %2$s',
|
||||
'Brick:Portal:Object:Form:Stimulus:Title' => 'Пожалуйста, укажите следующую информацию:',
|
||||
'Brick:Portal:Object:Form:Message:Saved' => 'Сохранено',
|
||||
'Brick:Portal:Object:Search:Regular:Title' => 'Выбрать %1$s (%2$s)',
|
||||
'Brick:Portal:Object:Search:Hierarchy:Title' => 'Выбрать %1$s (%2$s)',
|
||||
));
|
||||
|
||||
// CreateBrick brick
|
||||
Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Brick:Portal:Create:Name' => 'Быстрое создание',
|
||||
));
|
||||
@@ -37,5 +37,4 @@ $sDir = basename(__DIR__);
|
||||
define('PORTAL_MODULE_ID', $sDir);
|
||||
define('PORTAL_ID', $sDir);
|
||||
|
||||
ApplicationContext::SetUrlMakerClass('iTopPortalViewUrlMaker');
|
||||
require_once APPROOT . '/env-' . utils::GetCurrentEnvironment() . '/itop-portal-base/portal/web/index.php';
|
||||
|
||||
@@ -22,26 +22,20 @@
|
||||
*
|
||||
* @author Guillaume Lajarige <guillaume.lajarige@combodo.com>
|
||||
*/
|
||||
class iTopPortalEditUrlMaker implements iDBObjectURLMaker
|
||||
class iTopPortalUrlMaker implements iDBObjectURLMaker
|
||||
{
|
||||
/**
|
||||
* Generate an (absolute) URL to an object, either in view or edit mode
|
||||
* @param string $sClass The class of the object
|
||||
* @param int $iId The identifier of the object
|
||||
* @param string $sMode edit|view
|
||||
* @return string
|
||||
*/
|
||||
public static function PrepareObjectURL($sClass, $iId, $sMode)
|
||||
|
||||
public static function MakeObjectURL($sClass, $iId)
|
||||
{
|
||||
require_once APPROOT . '/lib/silex/vendor/autoload.php';
|
||||
require_once APPROOT . '/env-' . utils::GetCurrentEnvironment() . '/itop-portal-base/portal/src/providers/urlgeneratorserviceprovider.class.inc.php';
|
||||
require_once APPROOT . '/env-' . utils::GetCurrentEnvironment() . '/itop-portal-base/portal/src/helpers/urlgeneratorhelper.class.inc.php';
|
||||
require_once APPROOT . '/env-' . utils::GetCurrentEnvironment() . '/itop-portal-base/portal/src/helpers/applicationhelper.class.inc.php';
|
||||
|
||||
|
||||
// Using a static var allows to preserve the object through function calls
|
||||
static $oApp = null;
|
||||
static $sPortalId = null;
|
||||
|
||||
|
||||
// Initializing Silex app
|
||||
if ($oApp === null)
|
||||
{
|
||||
@@ -55,51 +49,15 @@ class iTopPortalEditUrlMaker implements iDBObjectURLMaker
|
||||
// Retrieving portal id
|
||||
$sPortalId = basename(__DIR__);
|
||||
}
|
||||
// The object is reachable in the specified mode (edit/view)
|
||||
switch($sMode)
|
||||
{
|
||||
case 'view':
|
||||
$sObjectQueryString = $oApp['url_generator']->generate('p_object_view', array('sObjectClass' => $sClass, 'sObjectId' => $iId));
|
||||
break;
|
||||
|
||||
case 'edit':
|
||||
default:
|
||||
$sObjectQueryString = $oApp['url_generator']->generate('p_object_edit', array('sObjectClass' => $sClass, 'sObjectId' => $iId));
|
||||
}
|
||||
|
||||
|
||||
$sObjectQueryString = $oApp['url_generator']->generate('p_object_edit', array('sObjectClass' => $sClass, 'sObjectId' => $iId));
|
||||
$sPortalAbsoluteUrl = utils::GetAbsoluteUrlModulePage($sPortalId, 'index.php');
|
||||
if (strpos($sPortalAbsoluteUrl, '?') !== false)
|
||||
{
|
||||
$sUrl = substr($sPortalAbsoluteUrl, 0, strpos($sPortalAbsoluteUrl, '?')).$sObjectQueryString;
|
||||
}
|
||||
else
|
||||
{
|
||||
$sUrl = $sPortalAbsoluteUrl.$sObjectQueryString;
|
||||
}
|
||||
|
||||
$sUrl = str_replace('?', $sObjectQueryString . '?', $sPortalAbsoluteUrl);
|
||||
|
||||
return $sUrl;
|
||||
}
|
||||
|
||||
public static function MakeObjectURL($sClass, $iId)
|
||||
{
|
||||
return static::PrepareObjectURL($sClass, $iId, 'edit');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Hyperlinks to the "view" of the object (vs edition)
|
||||
* @author denis
|
||||
*
|
||||
*/
|
||||
class iTopPortalViewUrlMaker extends iTopPortalEditUrlMaker
|
||||
{
|
||||
public static function MakeObjectURL($sClass, $iId)
|
||||
{
|
||||
return static::PrepareObjectURL($sClass, $iId, 'view');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Default portal hyperlink (for notifications) is the edit hyperlink
|
||||
DBObject::RegisterURLMakerClass('portal', 'iTopPortalEditUrlMaker');
|
||||
DBObject::RegisterURLMakerClass('portal', 'iTopPortalUrlMaker');
|
||||
|
||||
|
||||
@@ -2,30 +2,67 @@
|
||||
|
||||
/**
|
||||
* Локализация интерфейса Combodo iTop подготовлена сообществом iTop по-русски http://community.itop-itsm.ru.
|
||||
*
|
||||
* @author Vladimir Kunin <v.b.kunin@gmail.com>
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*
|
||||
* @author Vladimir Kunin <v.b.kunin@gmail.com>
|
||||
* @link http://community.itop-itsm.ru iTop Russian Community
|
||||
* @link https://github.com/itop-itsm-ru/itop-rus
|
||||
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
|
||||
*
|
||||
* Инструкция по установке
|
||||
*
|
||||
* Процесс установки заключается в замене имеющихся локализационных файлов полученными и последующем запуске процедуры обновления iTop для перекомпиляции кода.
|
||||
* 1. Скопируйте с заменой два полученных файла из "itop-rus/dictionaries" в "путь/до/вашего/itop/dictionaries".
|
||||
* 2. Скопируйте с заменой полученные файлы "itop-rus/datamodels/2.x/название-модуля/ru.dict.название-модуля.php" в "путь/до/вашего/itop/datamodels/2.x/название-модуля".
|
||||
* 3. Перейдите по адресу "http://адрес/вашего/itop/setup", при этом файл "путь/до/вашего/itop/conf/production/config-itop.php" должен быть доступен для записи.
|
||||
* 4. На второй странице установщика выберите "Upgrade an existing iTop instance" и следуйте дальнейшим инструкциям установщика.
|
||||
*
|
||||
* Ответы на вопросы по установке и использованию переводов, а также на любые другие вопросы по iTop всегда можно получить на сайте сообщества iTop по-русски http://community.itop-itsm.ru.
|
||||
*
|
||||
*/
|
||||
|
||||
// Dictionnay conventions
|
||||
// Class:<class_name>
|
||||
// Class:<class_name>+
|
||||
// Class:<class_name>/Attribute:<attribute_code>
|
||||
// Class:<class_name>/Attribute:<attribute_code>+
|
||||
// Class:<class_name>/Attribute:<attribute_code>/Value:<value>
|
||||
// Class:<class_name>/Attribute:<attribute_code>/Value:<value>+
|
||||
// Class:<class_name>/Stimulus:<stimulus_code>
|
||||
// Class:<class_name>/Stimulus:<stimulus_code>+
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Classes in 'bizmodel'
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
||||
// Dictionnay conventions
|
||||
// Class:<class_name>
|
||||
// Class:<class_name>+
|
||||
// Class:<class_name>/Attribute:<attribute_code>
|
||||
// Class:<class_name>/Attribute:<attribute_code>+
|
||||
// Class:<class_name>/Attribute:<attribute_code>/Value:<value>
|
||||
// Class:<class_name>/Attribute:<attribute_code>/Value:<value>+
|
||||
// Class:<class_name>/Stimulus:<stimulus_code>
|
||||
// Class:<class_name>/Stimulus:<stimulus_code>+
|
||||
|
||||
|
||||
|
||||
|
||||
Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Menu:ProblemManagement' => 'Управление проблемами',
|
||||
'Menu:ProblemManagement+' => 'Управление проблемами',
|
||||
'Menu:Problem:Overview' => 'Обзор',
|
||||
'Menu:Problem:Overview+' => 'Управление проблемами - Обзор',
|
||||
'Menu:NewProblem' => 'Новая проблема',
|
||||
'Menu:NewProblem+' => 'Создать новую проблему',
|
||||
'Menu:SearchProblems' => 'Поиск проблем',
|
||||
'Menu:SearchProblems+' => 'Поиск проблем',
|
||||
'Menu:Problem:Shortcuts' => 'Ярлыки',
|
||||
'Menu:Problem:MyProblems' => 'Назначенные мне',
|
||||
'Menu:Problem:MyProblems+' => 'Назначенные мне проблемы',
|
||||
'Menu:Problem:OpenProblems' => 'Открытые',
|
||||
'Menu:Problem:OpenProblems+' => 'Все открытые проблемы',
|
||||
'UI-ProblemManagementOverview-ProblemByService' => 'Проблемы по услугам',
|
||||
'UI-ProblemManagementOverview-ProblemByService+' => 'Проблемы по услугам',
|
||||
'Menu:ProblemManagement' => 'Управление проблемами',
|
||||
'Menu:ProblemManagement+' => 'Управление проблемами',
|
||||
'Menu:Problem:Overview' => 'Обзор',
|
||||
'Menu:Problem:Overview+' => 'Overview',
|
||||
'Menu:NewProblem' => 'Создать проблему',
|
||||
'Menu:NewProblem+' => 'Новая проблема',
|
||||
'Menu:SearchProblems' => 'Найти проблему',
|
||||
'Menu:SearchProblems+' => 'Search for problems',
|
||||
'Menu:Problem:Shortcuts' => 'Ярлыки',
|
||||
'Menu:Problem:MyProblems' => 'Назначенные мне проблемы',
|
||||
'Menu:Problem:MyProblems+' => 'Мои проблемы',
|
||||
'Menu:Problem:OpenProblems' => 'Открытые проблемы',
|
||||
'Menu:Problem:OpenProblems+' => 'Все открытые проблемы',
|
||||
'UI-ProblemManagementOverview-ProblemByService' => 'Проблемы по сервису',
|
||||
'UI-ProblemManagementOverview-ProblemByService+' => 'Проблемы по сервису',
|
||||
'UI-ProblemManagementOverview-ProblemByPriority' => 'Проблемы по приоритету',
|
||||
'UI-ProblemManagementOverview-ProblemByPriority+' => 'Проблемы по приоритету',
|
||||
'UI-ProblemManagementOverview-ProblemUnassigned' => 'Неназначенные проблемы',
|
||||
@@ -53,56 +90,54 @@ Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Class:Problem/Attribute:status/Value:closed+' => '',
|
||||
'Class:Problem/Attribute:service_id' => 'Услуга',
|
||||
'Class:Problem/Attribute:service_id+' => '',
|
||||
'Class:Problem/Attribute:service_name' => 'Услуга',
|
||||
'Class:Problem/Attribute:service_name' => 'Имя услуги',
|
||||
'Class:Problem/Attribute:service_name+' => '',
|
||||
'Class:Problem/Attribute:servicesubcategory_id' => 'Подкатегория',
|
||||
'Class:Problem/Attribute:servicesubcategory_id+' => 'Подкатегория услуги',
|
||||
'Class:Problem/Attribute:servicesubcategory_name' => 'Подкатегория услуги',
|
||||
'Class:Problem/Attribute:servicesubcategory_id' => 'Тип запроса',
|
||||
'Class:Problem/Attribute:servicesubcategory_id+' => '',
|
||||
'Class:Problem/Attribute:servicesubcategory_name' => 'Тип запроса',
|
||||
'Class:Problem/Attribute:servicesubcategory_name+' => '',
|
||||
'Class:Problem/Attribute:product' => 'Продукт',
|
||||
'Class:Problem/Attribute:product+' => '',
|
||||
'Class:Problem/Attribute:impact' => 'Влияние',
|
||||
'Class:Problem/Attribute:impact+' => '',
|
||||
'Class:Problem/Attribute:impact/Value:1' => 'Департамент',
|
||||
'Class:Problem/Attribute:impact/Value:1' => 'Услуга',
|
||||
'Class:Problem/Attribute:impact/Value:1+' => '',
|
||||
'Class:Problem/Attribute:impact/Value:2' => 'Служба',
|
||||
'Class:Problem/Attribute:impact/Value:2' => 'Отдел',
|
||||
'Class:Problem/Attribute:impact/Value:2+' => '',
|
||||
'Class:Problem/Attribute:impact/Value:3' => 'Персона',
|
||||
'Class:Problem/Attribute:impact/Value:3+' => '',
|
||||
'Class:Problem/Attribute:urgency' => 'Срочность',
|
||||
'Class:Problem/Attribute:urgency+' => '',
|
||||
'Class:Problem/Attribute:urgency/Value:1' => 'Критическая',
|
||||
'Class:Problem/Attribute:urgency/Value:1+' => 'Критическая',
|
||||
'Class:Problem/Attribute:urgency/Value:1+' => 'critical',
|
||||
'Class:Problem/Attribute:urgency/Value:2' => 'Высокая',
|
||||
'Class:Problem/Attribute:urgency/Value:2+' => 'Высокая',
|
||||
'Class:Problem/Attribute:urgency/Value:2+' => 'high',
|
||||
'Class:Problem/Attribute:urgency/Value:3' => 'Средняя',
|
||||
'Class:Problem/Attribute:urgency/Value:3+' => 'Средняя',
|
||||
'Class:Problem/Attribute:urgency/Value:3+' => 'medium',
|
||||
'Class:Problem/Attribute:urgency/Value:4' => 'Низкая',
|
||||
'Class:Problem/Attribute:urgency/Value:4+' => 'Низкая',
|
||||
'Class:Problem/Attribute:urgency/Value:4+' => 'low',
|
||||
'Class:Problem/Attribute:priority' => 'Приоритет',
|
||||
'Class:Problem/Attribute:priority+' => '',
|
||||
'Class:Problem/Attribute:priority/Value:1' => 'Критический',
|
||||
'Class:Problem/Attribute:priority/Value:1+' => 'Критический',
|
||||
'Class:Problem/Attribute:priority/Value:1+' => 'Critical',
|
||||
'Class:Problem/Attribute:priority/Value:2' => 'Высокий',
|
||||
'Class:Problem/Attribute:priority/Value:2+' => 'Высокий',
|
||||
'Class:Problem/Attribute:priority/Value:2+' => 'High',
|
||||
'Class:Problem/Attribute:priority/Value:3' => 'Средний',
|
||||
'Class:Problem/Attribute:priority/Value:3+' => 'Средний',
|
||||
'Class:Problem/Attribute:priority/Value:3+' => 'Medium',
|
||||
'Class:Problem/Attribute:priority/Value:4' => 'Низкий',
|
||||
'Class:Problem/Attribute:priority/Value:4+' => 'Низкий',
|
||||
'Class:Problem/Attribute:priority/Value:4+' => 'Low',
|
||||
'Class:Problem/Attribute:related_change_id' => 'Связанное изменение',
|
||||
'Class:Problem/Attribute:related_change_id+' => '',
|
||||
'Class:Problem/Attribute:related_change_ref' => 'Связанное изменение',
|
||||
'Class:Problem/Attribute:related_change_ref' => 'Ссылка на изменение',
|
||||
'Class:Problem/Attribute:related_change_ref+' => '',
|
||||
'Class:Problem/Attribute:assignment_date' => 'Дата назначения',
|
||||
'Class:Problem/Attribute:assignment_date' => 'Назначение',
|
||||
'Class:Problem/Attribute:assignment_date+' => '',
|
||||
'Class:Problem/Attribute:resolution_date' => 'Дата решения',
|
||||
'Class:Problem/Attribute:resolution_date' => 'Решение',
|
||||
'Class:Problem/Attribute:resolution_date+' => '',
|
||||
'Class:Problem/Attribute:knownerrors_list' => 'Известные ошибки',
|
||||
'Class:Problem/Attribute:knownerrors_list+' => 'Связанные известные ошибки',
|
||||
'Class:Problem/Attribute:related_request_list' => 'Запросы',
|
||||
'Class:Problem/Attribute:related_request_list+' => 'Связанные запросы',
|
||||
'Class:Problem/Attribute:related_incident_list' => 'Инциденты',
|
||||
'Class:Problem/Attribute:related_incident_list+' => 'Связанные инциденты',
|
||||
'Class:Problem/Stimulus:ev_assign' => 'Назначить',
|
||||
'Class:Problem/Stimulus:ev_assign+' => '',
|
||||
'Class:Problem/Stimulus:ev_reassign' => 'Переназначить',
|
||||
@@ -111,4 +146,8 @@ Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Class:Problem/Stimulus:ev_resolve+' => '',
|
||||
'Class:Problem/Stimulus:ev_close' => 'Закрыть',
|
||||
'Class:Problem/Stimulus:ev_close+' => '',
|
||||
));
|
||||
'Class:Problem/Attribute:related_incident_list' => 'Related incidents~~',
|
||||
'Class:Problem/Attribute:related_incident_list+' => 'All the incidents that are related to this problem~~',
|
||||
));
|
||||
|
||||
?>
|
||||
|
||||
@@ -1325,7 +1325,7 @@
|
||||
<code><![CDATA[ public function UpdateChildRequestLog()
|
||||
{
|
||||
$oLog = $this->Get('public_log');
|
||||
$sLogPublic = $oLog->GetModifiedEntry('html');
|
||||
$sLogPublic = $oLog->GetModifiedEntry();
|
||||
if ($sLogPublic != '')
|
||||
{
|
||||
$sOQL = "SELECT UserRequest WHERE parent_request_id=:ticket";
|
||||
@@ -1343,7 +1343,7 @@
|
||||
|
||||
}
|
||||
$oLog = $this->Get('private_log');
|
||||
$sLogPrivate = $oLog->GetModifiedEntry('html');
|
||||
$sLogPrivate = $oLog->GetModifiedEntry();
|
||||
if ($sLogPrivate != '')
|
||||
{
|
||||
$sOQL = "SELECT UserRequest WHERE parent_request_id=:ticket";
|
||||
|
||||
@@ -1,255 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Локализация интерфейса Combodo iTop подготовлена сообществом iTop по-русски http://community.itop-itsm.ru.
|
||||
*
|
||||
* @author Vladimir Kunin <v.b.kunin@gmail.com>
|
||||
* @link http://community.itop-itsm.ru iTop Russian Community
|
||||
* @link https://github.com/itop-itsm-ru/itop-rus
|
||||
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
|
||||
*
|
||||
*/
|
||||
|
||||
Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Menu:RequestManagement' => 'Управление запросами',
|
||||
'Menu:RequestManagement+' => 'Управление запросами',
|
||||
'Menu:RequestManagementProvider' => 'Поставщик техподдержки',
|
||||
'Menu:RequestManagementProvider+' => 'Поставщик техподдержки',
|
||||
'Menu:UserRequest:Provider' => 'Открытые запросы, отправленные поставщику',
|
||||
'Menu:UserRequest:Provider+' => 'Открытые запросы, отправленные поставщику',
|
||||
'Menu:UserRequest:Overview' => 'Обзор',
|
||||
'Menu:UserRequest:Overview+' => 'Обзор',
|
||||
'Menu:NewUserRequest' => 'Новый запрос',
|
||||
'Menu:NewUserRequest+' => 'Создать новый запрос на обслуживание',
|
||||
'Menu:SearchUserRequests' => 'Поиск запросов',
|
||||
'Menu:SearchUserRequests+' => 'Поиск запросов на обслуживание',
|
||||
'Menu:UserRequest:Shortcuts' => 'Ярлыки',
|
||||
'Menu:UserRequest:Shortcuts+' => 'Ярлыки',
|
||||
'Menu:UserRequest:MyRequests' => 'Назначенные мне',
|
||||
'Menu:UserRequest:MyRequests+' => 'Назначенные мне запросы',
|
||||
'Menu:UserRequest:MySupportRequests' => "Созданные мной",
|
||||
'Menu:UserRequest:MySupportRequests+' => "Созданные мной запросы",
|
||||
'Menu:UserRequest:EscalatedRequests' => 'Эскалированные',
|
||||
'Menu:UserRequest:EscalatedRequests+' => 'Эскалированные запросы',
|
||||
'Menu:UserRequest:OpenRequests' => 'Открытые',
|
||||
'Menu:UserRequest:OpenRequests+' => 'Открытые запросы',
|
||||
'UI:WelcomeMenu:MyAssignedCalls' => 'Назначенные мне запросы',
|
||||
'UI-RequestManagementOverview-RequestByType-last-14-days' => 'Запросы по типу за 14 дней',
|
||||
'UI-RequestManagementOverview-Last-14-days' => 'Количество запросов за 14 дней',
|
||||
'UI-RequestManagementOverview-OpenRequestByStatus' => 'Открытые запросы по статусу',
|
||||
'UI-RequestManagementOverview-OpenRequestByAgent' => 'Открытые запросы по агенту',
|
||||
'UI-RequestManagementOverview-OpenRequestByType' => 'Открытые запросы по типу',
|
||||
'UI-RequestManagementOverview-OpenRequestByCustomer' => 'Открытые запросы по заказчику',
|
||||
'Class:UserRequest:KnownErrorList' => 'Известные ошибки',
|
||||
));
|
||||
|
||||
// Dictionnay conventions
|
||||
// Class:<class_name>
|
||||
// Class:<class_name>+
|
||||
// Class:<class_name>/Attribute:<attribute_code>
|
||||
// Class:<class_name>/Attribute:<attribute_code>+
|
||||
// Class:<class_name>/Attribute:<attribute_code>/Value:<value>
|
||||
// Class:<class_name>/Attribute:<attribute_code>/Value:<value>+
|
||||
// Class:<class_name>/Stimulus:<stimulus_code>
|
||||
// Class:<class_name>/Stimulus:<stimulus_code>+
|
||||
|
||||
//
|
||||
// Class: UserRequest
|
||||
//
|
||||
|
||||
Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Class:UserRequest' => 'Запрос',
|
||||
'Class:UserRequest+' => '',
|
||||
'Class:UserRequest/Attribute:status' => 'Статус',
|
||||
'Class:UserRequest/Attribute:status+' => '',
|
||||
'Class:UserRequest/Attribute:status/Value:new' => 'Новый',
|
||||
'Class:UserRequest/Attribute:status/Value:new+' => '',
|
||||
'Class:UserRequest/Attribute:status/Value:escalated_tto' => 'Эскалация TTO',
|
||||
'Class:UserRequest/Attribute:status/Value:escalated_tto+' => '',
|
||||
'Class:UserRequest/Attribute:status/Value:assigned' => 'Назначен',
|
||||
'Class:UserRequest/Attribute:status/Value:assigned+' => '',
|
||||
'Class:UserRequest/Attribute:status/Value:escalated_ttr' => 'Эскалация TTR',
|
||||
'Class:UserRequest/Attribute:status/Value:escalated_ttr+' => '',
|
||||
'Class:UserRequest/Attribute:status/Value:waiting_for_approval' => 'Ожидание утверждения',
|
||||
'Class:UserRequest/Attribute:status/Value:waiting_for_approval+' => '',
|
||||
'Class:UserRequest/Attribute:status/Value:approved' => 'Утвержден',
|
||||
'Class:UserRequest/Attribute:status/Value:approved+' => '',
|
||||
'Class:UserRequest/Attribute:status/Value:rejected' => 'Отклонен',
|
||||
'Class:UserRequest/Attribute:status/Value:rejected+' => '',
|
||||
'Class:UserRequest/Attribute:status/Value:pending' => 'В ожидании',
|
||||
'Class:UserRequest/Attribute:status/Value:pending+' => '',
|
||||
'Class:UserRequest/Attribute:status/Value:resolved' => 'Решенный',
|
||||
'Class:UserRequest/Attribute:status/Value:resolved+' => '',
|
||||
'Class:UserRequest/Attribute:status/Value:closed' => 'Закрыт',
|
||||
'Class:UserRequest/Attribute:status/Value:closed+' => '',
|
||||
'Class:UserRequest/Attribute:request_type' => 'Тип запроса',
|
||||
'Class:UserRequest/Attribute:request_type+' => '',
|
||||
'Class:UserRequest/Attribute:request_type/Value:service_request' => 'Запрос на обслуживание',
|
||||
'Class:UserRequest/Attribute:request_type/Value:service_request+' => 'Запрос на обслуживание',
|
||||
'Class:UserRequest/Attribute:impact' => 'Влияние',
|
||||
'Class:UserRequest/Attribute:impact+' => '',
|
||||
'Class:UserRequest/Attribute:impact/Value:1' => 'Департамент',
|
||||
'Class:UserRequest/Attribute:impact/Value:1+' => '',
|
||||
'Class:UserRequest/Attribute:impact/Value:2' => 'Служба',
|
||||
'Class:UserRequest/Attribute:impact/Value:2+' => '',
|
||||
'Class:UserRequest/Attribute:impact/Value:3' => 'Персона',
|
||||
'Class:UserRequest/Attribute:impact/Value:3+' => '',
|
||||
'Class:UserRequest/Attribute:priority' => 'Приоритет',
|
||||
'Class:UserRequest/Attribute:priority+' => '',
|
||||
'Class:UserRequest/Attribute:priority/Value:1' => 'Критический',
|
||||
'Class:UserRequest/Attribute:priority/Value:1+' => 'Критический',
|
||||
'Class:UserRequest/Attribute:priority/Value:2' => 'Высокий',
|
||||
'Class:UserRequest/Attribute:priority/Value:2+' => 'Высокий',
|
||||
'Class:UserRequest/Attribute:priority/Value:3' => 'Средний',
|
||||
'Class:UserRequest/Attribute:priority/Value:3+' => 'Средний',
|
||||
'Class:UserRequest/Attribute:priority/Value:4' => 'Низкий',
|
||||
'Class:UserRequest/Attribute:priority/Value:4+' => 'Низкий',
|
||||
'Class:UserRequest/Attribute:urgency' => 'Срочность',
|
||||
'Class:UserRequest/Attribute:urgency+' => '',
|
||||
'Class:UserRequest/Attribute:urgency/Value:1' => 'Критическая',
|
||||
'Class:UserRequest/Attribute:urgency/Value:1+' => 'Критическая',
|
||||
'Class:UserRequest/Attribute:urgency/Value:2' => 'Высокая',
|
||||
'Class:UserRequest/Attribute:urgency/Value:2+' => 'Высокая',
|
||||
'Class:UserRequest/Attribute:urgency/Value:3' => 'Средняя',
|
||||
'Class:UserRequest/Attribute:urgency/Value:3+' => 'Средняя',
|
||||
'Class:UserRequest/Attribute:urgency/Value:4' => 'Низкая',
|
||||
'Class:UserRequest/Attribute:urgency/Value:4+' => 'Низкая',
|
||||
'Class:UserRequest/Attribute:origin' => 'Источник',
|
||||
'Class:UserRequest/Attribute:origin+' => '',
|
||||
'Class:UserRequest/Attribute:origin/Value:mail' => 'Почта',
|
||||
'Class:UserRequest/Attribute:origin/Value:mail+' => 'Почта',
|
||||
'Class:UserRequest/Attribute:origin/Value:monitoring' => 'Мониторинг',
|
||||
'Class:UserRequest/Attribute:origin/Value:monitoring+' => 'Мониторинг',
|
||||
'Class:UserRequest/Attribute:origin/Value:phone' => 'Телефон',
|
||||
'Class:UserRequest/Attribute:origin/Value:phone+' => 'Телефон',
|
||||
'Class:UserRequest/Attribute:origin/Value:portal' => 'Портал',
|
||||
'Class:UserRequest/Attribute:origin/Value:portal+' => 'Портал',
|
||||
'Class:UserRequest/Attribute:approver_id' => 'Утверждающий',
|
||||
'Class:UserRequest/Attribute:approver_id+' => '',
|
||||
'Class:UserRequest/Attribute:approver_email' => 'Email утверждающего',
|
||||
'Class:UserRequest/Attribute:approver_email+' => '',
|
||||
'Class:UserRequest/Attribute:service_id' => 'Услуга',
|
||||
'Class:UserRequest/Attribute:service_id+' => '',
|
||||
'Class:UserRequest/Attribute:service_name' => 'Услуга',
|
||||
'Class:UserRequest/Attribute:service_name+' => '',
|
||||
'Class:UserRequest/Attribute:servicesubcategory_id' => 'Подкатегория',
|
||||
'Class:UserRequest/Attribute:servicesubcategory_id+' => 'Подкатегория услуги',
|
||||
'Class:UserRequest/Attribute:servicesubcategory_name' => 'Подкатегория услуги',
|
||||
'Class:UserRequest/Attribute:servicesubcategory_name+' => '',
|
||||
'Class:UserRequest/Attribute:escalation_flag' => 'Флаг эскалации',
|
||||
'Class:UserRequest/Attribute:escalation_flag+' => '',
|
||||
'Class:UserRequest/Attribute:escalation_flag/Value:no' => 'Нет',
|
||||
'Class:UserRequest/Attribute:escalation_flag/Value:no+' => 'Нет',
|
||||
'Class:UserRequest/Attribute:escalation_flag/Value:yes' => 'Да',
|
||||
'Class:UserRequest/Attribute:escalation_flag/Value:yes+' => 'Да',
|
||||
'Class:UserRequest/Attribute:escalation_reason' => 'Причина эскалации',
|
||||
'Class:UserRequest/Attribute:escalation_reason+' => '',
|
||||
'Class:UserRequest/Attribute:assignment_date' => 'Дата назначения',
|
||||
'Class:UserRequest/Attribute:assignment_date+' => '',
|
||||
'Class:UserRequest/Attribute:resolution_date' => 'Дата решения',
|
||||
'Class:UserRequest/Attribute:resolution_date+' => '',
|
||||
'Class:UserRequest/Attribute:last_pending_date' => 'Дата последнего ожидания',
|
||||
'Class:UserRequest/Attribute:last_pending_date+' => '',
|
||||
'Class:UserRequest/Attribute:cumulatedpending' => 'Накопленное ожидание',
|
||||
'Class:UserRequest/Attribute:cumulatedpending+' => '',
|
||||
'Class:UserRequest/Attribute:tto' => 'TTO',
|
||||
'Class:UserRequest/Attribute:tto+' => '',
|
||||
'Class:UserRequest/Attribute:ttr' => 'TTR',
|
||||
'Class:UserRequest/Attribute:ttr+' => '',
|
||||
'Class:UserRequest/Attribute:tto_escalation_deadline' => 'Срок TTO',
|
||||
'Class:UserRequest/Attribute:tto_escalation_deadline+' => 'Крайний срок назаначения агента (принятия в работу) по текущему SLA',
|
||||
'Class:UserRequest/Attribute:sla_tto_passed' => 'SLA TTO пропущено',
|
||||
'Class:UserRequest/Attribute:sla_tto_passed+' => '',
|
||||
'Class:UserRequest/Attribute:sla_tto_over' => 'SLA TTO превышено',
|
||||
'Class:UserRequest/Attribute:sla_tto_over+' => '',
|
||||
'Class:UserRequest/Attribute:ttr_escalation_deadline' => 'Срок TTR',
|
||||
'Class:UserRequest/Attribute:ttr_escalation_deadline+' => 'Крайний срок решения по текущему SLA',
|
||||
'Class:UserRequest/Attribute:sla_ttr_passed' => 'SLA TTR пропущено',
|
||||
'Class:UserRequest/Attribute:sla_ttr_passed+' => '',
|
||||
'Class:UserRequest/Attribute:sla_ttr_over' => 'SLA TTR превышено',
|
||||
'Class:UserRequest/Attribute:sla_ttr_over+' => '',
|
||||
'Class:UserRequest/Attribute:time_spent' => 'Время на решение',
|
||||
'Class:UserRequest/Attribute:time_spent+' => '',
|
||||
'Class:UserRequest/Attribute:resolution_code' => 'Код решения',
|
||||
'Class:UserRequest/Attribute:resolution_code+' => '',
|
||||
'Class:UserRequest/Attribute:resolution_code/Value:assistance' => 'Помощь',
|
||||
'Class:UserRequest/Attribute:resolution_code/Value:assistance+' => 'Помощь',
|
||||
'Class:UserRequest/Attribute:resolution_code/Value:bug fixed' => 'Исправление ошибки',
|
||||
'Class:UserRequest/Attribute:resolution_code/Value:bug fixed+' => 'Исправление ошибки',
|
||||
'Class:UserRequest/Attribute:resolution_code/Value:hardware repair' => 'Ремонт оборудования',
|
||||
'Class:UserRequest/Attribute:resolution_code/Value:hardware repair+' => 'Ремонт оборудования',
|
||||
'Class:UserRequest/Attribute:resolution_code/Value:other' => 'Другое',
|
||||
'Class:UserRequest/Attribute:resolution_code/Value:other+' => 'Другое',
|
||||
'Class:UserRequest/Attribute:resolution_code/Value:software patch' => 'Патч ПО',
|
||||
'Class:UserRequest/Attribute:resolution_code/Value:software patch+' => 'Патч ПО',
|
||||
'Class:UserRequest/Attribute:resolution_code/Value:system update' => 'Обновление системы',
|
||||
'Class:UserRequest/Attribute:resolution_code/Value:system update+' => 'Обновление системы',
|
||||
'Class:UserRequest/Attribute:resolution_code/Value:training' => 'Обучение',
|
||||
'Class:UserRequest/Attribute:resolution_code/Value:training+' => 'Обучение',
|
||||
'Class:UserRequest/Attribute:solution' => 'Описание решения',
|
||||
'Class:UserRequest/Attribute:solution+' => '',
|
||||
'Class:UserRequest/Attribute:pending_reason' => 'Причина ожидания',
|
||||
'Class:UserRequest/Attribute:pending_reason+' => '',
|
||||
'Class:UserRequest/Attribute:parent_request_id' => 'Родительский запрос',
|
||||
'Class:UserRequest/Attribute:parent_request_id+' => '',
|
||||
'Class:UserRequest/Attribute:parent_incident_id' => 'Родительский инцидент',
|
||||
'Class:UserRequest/Attribute:parent_incident_id+' => '',
|
||||
'Class:UserRequest/Attribute:parent_incident_ref' => 'Родительский инцидент',
|
||||
'Class:UserRequest/Attribute:parent_incident_ref+' => '',
|
||||
'Class:UserRequest/Attribute:parent_request_ref' => 'Родительский запрос',
|
||||
'Class:UserRequest/Attribute:parent_request_ref+' => '',
|
||||
'Class:UserRequest/Attribute:parent_problem_id' => 'Родительская проблема',
|
||||
'Class:UserRequest/Attribute:parent_problem_id+' => '',
|
||||
'Class:UserRequest/Attribute:parent_problem_ref' => 'Родительская проблема',
|
||||
'Class:UserRequest/Attribute:parent_problem_ref+' => '',
|
||||
'Class:UserRequest/Attribute:parent_change_id' => 'Родительское изменение',
|
||||
'Class:UserRequest/Attribute:parent_change_id+' => '',
|
||||
'Class:UserRequest/Attribute:parent_change_ref' => 'Родительское изменение',
|
||||
'Class:UserRequest/Attribute:parent_change_ref+' => '',
|
||||
'Class:UserRequest/Attribute:related_request_list' => 'Дочерние запросы',
|
||||
'Class:UserRequest/Attribute:related_request_list+' => 'Дочерние запросы',
|
||||
'Class:UserRequest/Attribute:public_log' => 'Общий журнал',
|
||||
'Class:UserRequest/Attribute:public_log+' => 'Информация в общем журнале доступна для пользователей портала',
|
||||
'Class:UserRequest/Attribute:user_satisfaction' => 'Удовлетворенность пользователя',
|
||||
'Class:UserRequest/Attribute:user_satisfaction+' => '',
|
||||
'Class:UserRequest/Attribute:user_satisfaction/Value:1' => 'Очень доволен',
|
||||
'Class:UserRequest/Attribute:user_satisfaction/Value:1+' => 'Очень доволен',
|
||||
'Class:UserRequest/Attribute:user_satisfaction/Value:2' => 'Вполне доволен',
|
||||
'Class:UserRequest/Attribute:user_satisfaction/Value:2+' => 'Вполне доволен',
|
||||
'Class:UserRequest/Attribute:user_satisfaction/Value:3' => 'Скорее недоволен',
|
||||
'Class:UserRequest/Attribute:user_satisfaction/Value:3+' => 'Скорее недоволен',
|
||||
'Class:UserRequest/Attribute:user_satisfaction/Value:4' => 'Очень недоволен',
|
||||
'Class:UserRequest/Attribute:user_satisfaction/Value:4+' => 'Очень недоволен',
|
||||
'Class:UserRequest/Attribute:user_comment' => 'Комментарий пользователя',
|
||||
'Class:UserRequest/Attribute:user_comment+' => '',
|
||||
'Class:UserRequest/Attribute:parent_request_id_friendlyname' => 'Родительский запрос',
|
||||
'Class:UserRequest/Attribute:parent_request_id_friendlyname+' => '',
|
||||
'Class:UserRequest/Stimulus:ev_assign' => 'Назначить',
|
||||
'Class:UserRequest/Stimulus:ev_assign+' => '',
|
||||
'Class:UserRequest/Stimulus:ev_reassign' => 'Переназначить',
|
||||
'Class:UserRequest/Stimulus:ev_reassign+' => '',
|
||||
'Class:UserRequest/Stimulus:ev_approve' => 'Утвердить',
|
||||
'Class:UserRequest/Stimulus:ev_approve+' => '',
|
||||
'Class:UserRequest/Stimulus:ev_reject' => 'Отклонить',
|
||||
'Class:UserRequest/Stimulus:ev_reject+' => '',
|
||||
'Class:UserRequest/Stimulus:ev_pending' => 'В ожидание',
|
||||
'Class:UserRequest/Stimulus:ev_pending+' => '',
|
||||
'Class:UserRequest/Stimulus:ev_timeout' => 'Таймаут',
|
||||
'Class:UserRequest/Stimulus:ev_timeout+' => '',
|
||||
'Class:UserRequest/Stimulus:ev_autoresolve' => 'Автоматическое решение',
|
||||
'Class:UserRequest/Stimulus:ev_autoresolve+' => '',
|
||||
'Class:UserRequest/Stimulus:ev_autoclose' => 'Автоматическое закрытие',
|
||||
'Class:UserRequest/Stimulus:ev_autoclose+' => '',
|
||||
'Class:UserRequest/Stimulus:ev_resolve' => 'Отметить как решенный',
|
||||
'Class:UserRequest/Stimulus:ev_resolve+' => '',
|
||||
'Class:UserRequest/Stimulus:ev_close' => 'Закрыть',
|
||||
'Class:UserRequest/Stimulus:ev_close+' => '',
|
||||
'Class:UserRequest/Stimulus:ev_reopen' => 'Вновь открыть',
|
||||
'Class:UserRequest/Stimulus:ev_reopen+' => '',
|
||||
'Class:UserRequest/Stimulus:ev_wait_for_approval' => 'Ждать утверждения',
|
||||
'Class:UserRequest/Stimulus:ev_wait_for_approval+' => '',
|
||||
'Class:UserRequest/Error:CannotAssignParentRequestIdToSelf' => 'Невозможно назначить этот же запрос в качестве родительского',
|
||||
|
||||
'Class:UserRequest/Method:ResolveChildTickets' => 'ResolveChildTickets',
|
||||
'Class:UserRequest/Method:ResolveChildTickets+' => 'Cascade the resolution to child requests (ev_autoresolve), and align the following characteristics of the request: service, team, agent, resolution info',
|
||||
));
|
||||
@@ -1338,7 +1338,7 @@
|
||||
<code><![CDATA[ public function UpdateChildRequestLog()
|
||||
{
|
||||
$oLog = $this->Get('public_log');
|
||||
$sLogPublic = $oLog->GetModifiedEntry('html');
|
||||
$sLogPublic = $oLog->GetModifiedEntry();
|
||||
if ($sLogPublic != '')
|
||||
{
|
||||
$sOQL = "SELECT UserRequest WHERE parent_request_id=:ticket";
|
||||
@@ -1356,7 +1356,7 @@
|
||||
|
||||
}
|
||||
$oLog = $this->Get('private_log');
|
||||
$sLogPrivate = $oLog->GetModifiedEntry('html');
|
||||
$sLogPrivate = $oLog->GetModifiedEntry();
|
||||
if ($sLogPrivate != '')
|
||||
{
|
||||
$sOQL = "SELECT UserRequest WHERE parent_request_id=:ticket";
|
||||
|
||||
@@ -1,284 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Локализация интерфейса Combodo iTop подготовлена сообществом iTop по-русски http://community.itop-itsm.ru.
|
||||
*
|
||||
* @author Vladimir Kunin <v.b.kunin@gmail.com>
|
||||
* @link http://community.itop-itsm.ru iTop Russian Community
|
||||
* @link https://github.com/itop-itsm-ru/itop-rus
|
||||
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
|
||||
*
|
||||
*/
|
||||
|
||||
Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Menu:RequestManagement' => 'Helpdesk',
|
||||
'Menu:RequestManagement+' => 'Helpdesk',
|
||||
'Menu:RequestManagementProvider' => 'Поставщик техподдержки',
|
||||
'Menu:RequestManagementProvider+' => 'Поставщик техподдержки',
|
||||
'Menu:UserRequest:Provider' => 'Открытые запросы, отправленные поставщику',
|
||||
'Menu:UserRequest:Provider+' => 'Открытые запросы, отправленные поставщику',
|
||||
'Menu:UserRequest:Overview' => 'Обзор',
|
||||
'Menu:UserRequest:Overview+' => 'Обзор',
|
||||
'Menu:NewUserRequest' => 'Новый запрос',
|
||||
'Menu:NewUserRequest+' => 'Создать новый запрос на обслуживание',
|
||||
'Menu:SearchUserRequests' => 'Поиск запросов',
|
||||
'Menu:SearchUserRequests+' => 'Поиск запросов на обслуживание',
|
||||
'Menu:UserRequest:Shortcuts' => 'Ярлыки',
|
||||
'Menu:UserRequest:Shortcuts+' => 'Ярлыки',
|
||||
'Menu:UserRequest:MyRequests' => 'Назначенные мне',
|
||||
'Menu:UserRequest:MyRequests+' => 'Назначенные мне (в качестве агента)',
|
||||
'Menu:UserRequest:MySupportRequests' => "Созданные мной",
|
||||
'Menu:UserRequest:MySupportRequests+' => "Созданные мной запросы",
|
||||
'Menu:UserRequest:EscalatedRequests' => 'Эскалированные',
|
||||
'Menu:UserRequest:EscalatedRequests+' => 'Эскалированные запросы',
|
||||
'Menu:UserRequest:OpenRequests' => 'Открытые',
|
||||
'Menu:UserRequest:OpenRequests+' => 'Открытые запросы',
|
||||
'UI:WelcomeMenu:MyAssignedCalls' => 'Назначенные мне запросы',
|
||||
'UI-RequestManagementOverview-RequestByType-last-14-days' => 'Запросы по типу за 14 дней',
|
||||
'UI-RequestManagementOverview-Last-14-days' => 'Количество запросов за 14 дней',
|
||||
'UI-RequestManagementOverview-OpenRequestByStatus' => 'Открытые запросы по статусу',
|
||||
'UI-RequestManagementOverview-OpenRequestByAgent' => 'Открытые запросы по агенту',
|
||||
'UI-RequestManagementOverview-OpenRequestByType' => 'Открытые запросы по типу',
|
||||
'UI-RequestManagementOverview-OpenRequestByCustomer' => 'Открытые запросы по заказчику',
|
||||
'Class:UserRequest:KnownErrorList' => 'Известные ошибки',
|
||||
'Menu:UserRequest:MyWorkOrders' => 'Назначенные мне наряды на работу',
|
||||
'Menu:UserRequest:MyWorkOrders+' => 'Назначенные мне наряды на работу',
|
||||
'Class:Problem:KnownProblemList' => 'Известные проблемы',
|
||||
'Tickets:Related:OpenIncidents' => 'Открытые инциденты',
|
||||
));
|
||||
|
||||
// Dictionnay conventions
|
||||
// Class:<class_name>
|
||||
// Class:<class_name>+
|
||||
// Class:<class_name>/Attribute:<attribute_code>
|
||||
// Class:<class_name>/Attribute:<attribute_code>+
|
||||
// Class:<class_name>/Attribute:<attribute_code>/Value:<value>
|
||||
// Class:<class_name>/Attribute:<attribute_code>/Value:<value>+
|
||||
// Class:<class_name>/Stimulus:<stimulus_code>
|
||||
// Class:<class_name>/Stimulus:<stimulus_code>+
|
||||
|
||||
//
|
||||
// Class: UserRequest
|
||||
//
|
||||
|
||||
Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Class:UserRequest' => 'Запрос',
|
||||
'Class:UserRequest+' => '',
|
||||
'Class:UserRequest/Attribute:status' => 'Статус',
|
||||
'Class:UserRequest/Attribute:status+' => '',
|
||||
'Class:UserRequest/Attribute:status/Value:new' => 'Новый',
|
||||
'Class:UserRequest/Attribute:status/Value:new+' => '',
|
||||
'Class:UserRequest/Attribute:status/Value:escalated_tto' => 'Эскалация TTO',
|
||||
'Class:UserRequest/Attribute:status/Value:escalated_tto+' => '',
|
||||
'Class:UserRequest/Attribute:status/Value:assigned' => 'Назначен',
|
||||
'Class:UserRequest/Attribute:status/Value:assigned+' => '',
|
||||
'Class:UserRequest/Attribute:status/Value:escalated_ttr' => 'Эскалация TTR',
|
||||
'Class:UserRequest/Attribute:status/Value:escalated_ttr+' => '',
|
||||
'Class:UserRequest/Attribute:status/Value:waiting_for_approval' => 'Ожидание утверждения',
|
||||
'Class:UserRequest/Attribute:status/Value:waiting_for_approval+' => '',
|
||||
'Class:UserRequest/Attribute:status/Value:approved' => 'Утвержден',
|
||||
'Class:UserRequest/Attribute:status/Value:approved+' => '',
|
||||
'Class:UserRequest/Attribute:status/Value:rejected' => 'Отклонен',
|
||||
'Class:UserRequest/Attribute:status/Value:rejected+' => '',
|
||||
'Class:UserRequest/Attribute:status/Value:pending' => 'В ожидании',
|
||||
'Class:UserRequest/Attribute:status/Value:pending+' => '',
|
||||
'Class:UserRequest/Attribute:status/Value:resolved' => 'Решенный',
|
||||
'Class:UserRequest/Attribute:status/Value:resolved+' => '',
|
||||
'Class:UserRequest/Attribute:status/Value:closed' => 'Закрыт',
|
||||
'Class:UserRequest/Attribute:status/Value:closed+' => '',
|
||||
'Class:UserRequest/Attribute:request_type' => 'Тип запроса',
|
||||
'Class:UserRequest/Attribute:request_type+' => '',
|
||||
'Class:UserRequest/Attribute:request_type/Value:incident' => 'Инцидент',
|
||||
'Class:UserRequest/Attribute:request_type/Value:incident+' => 'Инцидент',
|
||||
'Class:UserRequest/Attribute:request_type/Value:service_request' => 'Запрос на обслуживание',
|
||||
'Class:UserRequest/Attribute:request_type/Value:service_request+' => 'Запрос на обслуживание',
|
||||
'Class:UserRequest/Attribute:impact' => 'Влияние',
|
||||
'Class:UserRequest/Attribute:impact+' => '',
|
||||
'Class:UserRequest/Attribute:impact/Value:1' => 'Департамент',
|
||||
'Class:UserRequest/Attribute:impact/Value:1+' => '',
|
||||
'Class:UserRequest/Attribute:impact/Value:2' => 'Служба',
|
||||
'Class:UserRequest/Attribute:impact/Value:2+' => '',
|
||||
'Class:UserRequest/Attribute:impact/Value:3' => 'Персона',
|
||||
'Class:UserRequest/Attribute:impact/Value:3+' => '',
|
||||
'Class:UserRequest/Attribute:priority' => 'Приоритет',
|
||||
'Class:UserRequest/Attribute:priority+' => '',
|
||||
'Class:UserRequest/Attribute:priority/Value:1' => 'Критический',
|
||||
'Class:UserRequest/Attribute:priority/Value:1+' => 'Критический',
|
||||
'Class:UserRequest/Attribute:priority/Value:2' => 'Высокий',
|
||||
'Class:UserRequest/Attribute:priority/Value:2+' => 'Высокий',
|
||||
'Class:UserRequest/Attribute:priority/Value:3' => 'Средний',
|
||||
'Class:UserRequest/Attribute:priority/Value:3+' => 'Средний',
|
||||
'Class:UserRequest/Attribute:priority/Value:4' => 'Низкий',
|
||||
'Class:UserRequest/Attribute:priority/Value:4+' => 'Низкий',
|
||||
'Class:UserRequest/Attribute:urgency' => 'Срочность',
|
||||
'Class:UserRequest/Attribute:urgency+' => '',
|
||||
'Class:UserRequest/Attribute:urgency/Value:1' => 'Критическая',
|
||||
'Class:UserRequest/Attribute:urgency/Value:1+' => 'Критическая',
|
||||
'Class:UserRequest/Attribute:urgency/Value:2' => 'Высокая',
|
||||
'Class:UserRequest/Attribute:urgency/Value:2+' => 'Высокая',
|
||||
'Class:UserRequest/Attribute:urgency/Value:3' => 'Средняя',
|
||||
'Class:UserRequest/Attribute:urgency/Value:3+' => 'Средняя',
|
||||
'Class:UserRequest/Attribute:urgency/Value:4' => 'Низкая',
|
||||
'Class:UserRequest/Attribute:urgency/Value:4+' => 'Низкая',
|
||||
'Class:UserRequest/Attribute:origin' => 'Источник',
|
||||
'Class:UserRequest/Attribute:origin+' => '',
|
||||
'Class:UserRequest/Attribute:origin/Value:mail' => 'Почта',
|
||||
'Class:UserRequest/Attribute:origin/Value:mail+' => 'Почта',
|
||||
'Class:UserRequest/Attribute:origin/Value:monitoring' => 'Мониторинг',
|
||||
'Class:UserRequest/Attribute:origin/Value:monitoring+' => 'Мониторинг',
|
||||
'Class:UserRequest/Attribute:origin/Value:phone' => 'Телефон',
|
||||
'Class:UserRequest/Attribute:origin/Value:phone+' => 'Телефон',
|
||||
'Class:UserRequest/Attribute:origin/Value:portal' => 'Портал',
|
||||
'Class:UserRequest/Attribute:origin/Value:portal+' => 'Портал',
|
||||
'Class:UserRequest/Attribute:approver_id' => 'Утверждающий',
|
||||
'Class:UserRequest/Attribute:approver_id+' => '',
|
||||
'Class:UserRequest/Attribute:approver_email' => 'Email утверждающего',
|
||||
'Class:UserRequest/Attribute:approver_email+' => '',
|
||||
'Class:UserRequest/Attribute:service_id' => 'Услуга',
|
||||
'Class:UserRequest/Attribute:service_id+' => '',
|
||||
'Class:UserRequest/Attribute:service_name' => 'Услуга',
|
||||
'Class:UserRequest/Attribute:service_name+' => '',
|
||||
'Class:UserRequest/Attribute:servicesubcategory_id' => 'Подкатегория',
|
||||
'Class:UserRequest/Attribute:servicesubcategory_id+' => 'Подкатегория услуги',
|
||||
'Class:UserRequest/Attribute:servicesubcategory_name' => 'Подкатегория услуги',
|
||||
'Class:UserRequest/Attribute:servicesubcategory_name+' => '',
|
||||
'Class:UserRequest/Attribute:escalation_flag' => 'Флаг эскалации',
|
||||
'Class:UserRequest/Attribute:escalation_flag+' => '',
|
||||
'Class:UserRequest/Attribute:escalation_flag/Value:no' => 'Нет',
|
||||
'Class:UserRequest/Attribute:escalation_flag/Value:no+' => 'Нет',
|
||||
'Class:UserRequest/Attribute:escalation_flag/Value:yes' => 'Да',
|
||||
'Class:UserRequest/Attribute:escalation_flag/Value:yes+' => 'Да',
|
||||
'Class:UserRequest/Attribute:escalation_reason' => 'Причина эскалации',
|
||||
'Class:UserRequest/Attribute:escalation_reason+' => '',
|
||||
'Class:UserRequest/Attribute:assignment_date' => 'Дата назначения',
|
||||
'Class:UserRequest/Attribute:assignment_date+' => '',
|
||||
'Class:UserRequest/Attribute:resolution_date' => 'Дата решения',
|
||||
'Class:UserRequest/Attribute:resolution_date+' => '',
|
||||
'Class:UserRequest/Attribute:last_pending_date' => 'Дата последнего ожидания',
|
||||
'Class:UserRequest/Attribute:last_pending_date+' => '',
|
||||
'Class:UserRequest/Attribute:cumulatedpending' => 'Накопленное ожидание',
|
||||
'Class:UserRequest/Attribute:cumulatedpending+' => '',
|
||||
'Class:UserRequest/Attribute:tto' => 'TTO',
|
||||
'Class:UserRequest/Attribute:tto+' => '',
|
||||
'Class:UserRequest/Attribute:ttr' => 'TTR',
|
||||
'Class:UserRequest/Attribute:ttr+' => '',
|
||||
'Class:UserRequest/Attribute:tto_escalation_deadline' => 'Срок TTO',
|
||||
'Class:UserRequest/Attribute:tto_escalation_deadline+' => 'Крайний срок назаначения агента (принятия в работу) по текущему SLA',
|
||||
'Class:UserRequest/Attribute:sla_tto_passed' => 'SLA TTO пропущено',
|
||||
'Class:UserRequest/Attribute:sla_tto_passed+' => '',
|
||||
'Class:UserRequest/Attribute:sla_tto_over' => 'SLA TTO превышено',
|
||||
'Class:UserRequest/Attribute:sla_tto_over+' => '',
|
||||
'Class:UserRequest/Attribute:ttr_escalation_deadline' => 'Срок TTR',
|
||||
'Class:UserRequest/Attribute:ttr_escalation_deadline+' => 'Крайний срок решения по текущему SLA',
|
||||
'Class:UserRequest/Attribute:sla_ttr_passed' => 'SLA TTR пропущено',
|
||||
'Class:UserRequest/Attribute:sla_ttr_passed+' => '',
|
||||
'Class:UserRequest/Attribute:sla_ttr_over' => 'SLA TTR превышено',
|
||||
'Class:UserRequest/Attribute:sla_ttr_over+' => '',
|
||||
'Class:UserRequest/Attribute:time_spent' => 'Время на решение',
|
||||
'Class:UserRequest/Attribute:time_spent+' => '',
|
||||
'Class:UserRequest/Attribute:resolution_code' => 'Код решения',
|
||||
'Class:UserRequest/Attribute:resolution_code+' => '',
|
||||
'Class:UserRequest/Attribute:resolution_code/Value:assistance' => 'Помощь',
|
||||
'Class:UserRequest/Attribute:resolution_code/Value:assistance+' => 'Помощь',
|
||||
'Class:UserRequest/Attribute:resolution_code/Value:bug fixed' => 'Исправление ошибки',
|
||||
'Class:UserRequest/Attribute:resolution_code/Value:bug fixed+' => 'Исправление ошибки',
|
||||
'Class:UserRequest/Attribute:resolution_code/Value:hardware repair' => 'Ремонт оборудования',
|
||||
'Class:UserRequest/Attribute:resolution_code/Value:hardware repair+' => 'Ремонт оборудования',
|
||||
'Class:UserRequest/Attribute:resolution_code/Value:other' => 'Другое',
|
||||
'Class:UserRequest/Attribute:resolution_code/Value:other+' => 'Другое',
|
||||
'Class:UserRequest/Attribute:resolution_code/Value:software patch' => 'Патч ПО',
|
||||
'Class:UserRequest/Attribute:resolution_code/Value:software patch+' => 'Патч ПО',
|
||||
'Class:UserRequest/Attribute:resolution_code/Value:system update' => 'Обновление системы',
|
||||
'Class:UserRequest/Attribute:resolution_code/Value:system update+' => 'Обновление системы',
|
||||
'Class:UserRequest/Attribute:resolution_code/Value:training' => 'Обучение',
|
||||
'Class:UserRequest/Attribute:resolution_code/Value:training+' => 'Обучение',
|
||||
'Class:UserRequest/Attribute:solution' => 'Описание решения',
|
||||
'Class:UserRequest/Attribute:solution+' => '',
|
||||
'Class:UserRequest/Attribute:pending_reason' => 'Причина ожидания',
|
||||
'Class:UserRequest/Attribute:pending_reason+' => '',
|
||||
'Class:UserRequest/Attribute:parent_request_id' => 'Родительский запрос',
|
||||
'Class:UserRequest/Attribute:parent_request_id+' => '',
|
||||
'Class:UserRequest/Attribute:parent_request_ref' => 'Родительский запрос',
|
||||
'Class:UserRequest/Attribute:parent_request_ref+' => '',
|
||||
'Class:UserRequest/Attribute:parent_problem_id' => 'Родительская проблема',
|
||||
'Class:UserRequest/Attribute:parent_problem_id+' => '',
|
||||
'Class:UserRequest/Attribute:parent_problem_ref' => 'Родительская проблема',
|
||||
'Class:UserRequest/Attribute:parent_problem_ref+' => '',
|
||||
'Class:UserRequest/Attribute:parent_change_id' => 'Родительское изменение',
|
||||
'Class:UserRequest/Attribute:parent_change_id+' => '',
|
||||
'Class:UserRequest/Attribute:parent_change_ref' => 'Родительское изменение',
|
||||
'Class:UserRequest/Attribute:parent_change_ref+' => '',
|
||||
'Class:UserRequest/Attribute:related_request_list' => 'Дочерние запросы',
|
||||
'Class:UserRequest/Attribute:related_request_list+' => 'Дочерние запросы',
|
||||
'Class:UserRequest/Attribute:public_log' => 'Общий журнал',
|
||||
'Class:UserRequest/Attribute:public_log+' => 'Информация в общем журнале доступна для пользователей портала',
|
||||
'Class:UserRequest/Attribute:user_satisfaction' => 'Удовлетворенность пользователя',
|
||||
'Class:UserRequest/Attribute:user_satisfaction+' => '',
|
||||
'Class:UserRequest/Attribute:user_satisfaction/Value:1' => 'Очень доволен',
|
||||
'Class:UserRequest/Attribute:user_satisfaction/Value:1+' => 'Очень доволен',
|
||||
'Class:UserRequest/Attribute:user_satisfaction/Value:2' => 'Вполне доволен',
|
||||
'Class:UserRequest/Attribute:user_satisfaction/Value:2+' => 'Вполне доволен',
|
||||
'Class:UserRequest/Attribute:user_satisfaction/Value:3' => 'Скорее недоволен',
|
||||
'Class:UserRequest/Attribute:user_satisfaction/Value:3+' => 'Скорее недоволен',
|
||||
'Class:UserRequest/Attribute:user_satisfaction/Value:4' => 'Очень недоволен',
|
||||
'Class:UserRequest/Attribute:user_satisfaction/Value:4+' => 'Очень недоволен',
|
||||
'Class:UserRequest/Attribute:user_comment' => 'Комментарий пользователя',
|
||||
'Class:UserRequest/Attribute:user_comment+' => '',
|
||||
'Class:UserRequest/Attribute:parent_request_id_friendlyname' => 'Родительский запрос',
|
||||
'Class:UserRequest/Attribute:parent_request_id_friendlyname+' => '',
|
||||
'Class:UserRequest/Stimulus:ev_assign' => 'Назначить',
|
||||
'Class:UserRequest/Stimulus:ev_assign+' => '',
|
||||
'Class:UserRequest/Stimulus:ev_reassign' => 'Переназначить',
|
||||
'Class:UserRequest/Stimulus:ev_reassign+' => '',
|
||||
'Class:UserRequest/Stimulus:ev_approve' => 'Утвердить',
|
||||
'Class:UserRequest/Stimulus:ev_approve+' => '',
|
||||
'Class:UserRequest/Stimulus:ev_reject' => 'Отклонить',
|
||||
'Class:UserRequest/Stimulus:ev_reject+' => '',
|
||||
'Class:UserRequest/Stimulus:ev_pending' => 'В ожидание',
|
||||
'Class:UserRequest/Stimulus:ev_pending+' => '',
|
||||
'Class:UserRequest/Stimulus:ev_timeout' => 'Таймаут',
|
||||
'Class:UserRequest/Stimulus:ev_timeout+' => '',
|
||||
'Class:UserRequest/Stimulus:ev_autoresolve' => 'Автоматическое решение',
|
||||
'Class:UserRequest/Stimulus:ev_autoresolve+' => '',
|
||||
'Class:UserRequest/Stimulus:ev_autoclose' => 'Автоматическое закрытие',
|
||||
'Class:UserRequest/Stimulus:ev_autoclose+' => '',
|
||||
'Class:UserRequest/Stimulus:ev_resolve' => 'Отметить как решенный',
|
||||
'Class:UserRequest/Stimulus:ev_resolve+' => '',
|
||||
'Class:UserRequest/Stimulus:ev_close' => 'Закрыть',
|
||||
'Class:UserRequest/Stimulus:ev_close+' => '',
|
||||
'Class:UserRequest/Stimulus:ev_reopen' => 'Вновь открыть',
|
||||
'Class:UserRequest/Stimulus:ev_reopen+' => '',
|
||||
'Class:UserRequest/Stimulus:ev_wait_for_approval' => 'Ждать утверждения',
|
||||
'Class:UserRequest/Stimulus:ev_wait_for_approval+' => '',
|
||||
'Class:UserRequest/Error:CannotAssignParentRequestIdToSelf' => 'Невозможно назначить этот же запрос в качестве родительского',
|
||||
));
|
||||
|
||||
|
||||
Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Portal:TitleDetailsFor_Request' => 'Детали запроса',
|
||||
'Portal:ButtonUpdate' => 'Обновить',
|
||||
'Portal:ButtonClose' => 'Закрыть',
|
||||
'Portal:ButtonReopen' => 'Открыть вновь',
|
||||
'Portal:ShowServices' => 'Каталог услуг',
|
||||
'Portal:SelectRequestType' => 'Выберите тип запроса',
|
||||
'Portal:SelectServiceElementFrom_Service' => 'Выберите элемент услуги для %1$s',
|
||||
'Portal:SelectRequestTemplate' => 'Выберите шаблон для %1$s',
|
||||
'Portal:ListServices' => 'Список услуг',
|
||||
'Portal:TitleDetailsFor_Service' => 'Детали услуги',
|
||||
'Portal:Button:CreateRequestFromService' => 'Создать запрос по услуге',
|
||||
'Portal:ListOpenRequests' => 'Открытые запросы',
|
||||
'Portal:UserRequest:MoreInfo' => 'Дополнительная информация',
|
||||
'Portal:Details-Service-Element' => 'Элементы услуги',
|
||||
'Portal:NoClosedTicket' => 'Нет закрытых запросов',
|
||||
'Portal:NoService' => '',
|
||||
'Portal:ListOpenProblems' => 'Открытые проблемы',
|
||||
'Portal:ShowProblem' => 'Проблемы',
|
||||
'Portal:ShowFaqs' => 'FAQ',
|
||||
'Portal:NoOpenProblem' => 'Нет открытых проблем',
|
||||
'Portal:SelectLanguage' => "Изменить язык",
|
||||
'Portal:LanguageChangedTo_Lang' => 'Язык изменен на',
|
||||
'Portal:ChooseYourFavoriteLanguage' => 'Выберите язык',
|
||||
|
||||
'Class:UserRequest/Method:ResolveChildTickets' => 'ResolveChildTickets',
|
||||
'Class:UserRequest/Method:ResolveChildTickets+' => 'Cascade the resolution to child requests (ev_autoresolve), and align the following characteristics of the request: service, team, agent, resolution info',
|
||||
));
|
||||
@@ -1,494 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Локализация интерфейса Combodo iTop подготовлена сообществом iTop по-русски http://community.itop-itsm.ru.
|
||||
*
|
||||
* @author Vladimir Kunin <v.b.kunin@gmail.com>
|
||||
* @link http://community.itop-itsm.ru iTop Russian Community
|
||||
* @link https://github.com/itop-itsm-ru/itop-rus
|
||||
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Menu:ServiceManagement' => 'Управление услугами',
|
||||
'Menu:ServiceManagement+' => 'Управление услугами',
|
||||
'Menu:Service:Overview' => 'Обзор',
|
||||
'Menu:Service:Overview+' => 'Управление услугами - Обзор',
|
||||
'UI-ServiceManagementMenu-ContractsBySrvLevel' => 'Договоры по уровню услуги',
|
||||
'UI-ServiceManagementMenu-ContractsByStatus' => 'Договоры по статусу',
|
||||
'UI-ServiceManagementMenu-ContractsEndingIn30Days' => 'Договоры, оканчивающиеся в течение 30-ти дней',
|
||||
|
||||
'Menu:ProviderContract' => 'Договоры с поставщиками',
|
||||
'Menu:ProviderContract+' => 'Договоры с поставщиками',
|
||||
'Menu:CustomerContract' => 'Договоры с заказчиками',
|
||||
'Menu:CustomerContract+' => 'Договоры с заказчиками',
|
||||
'Menu:ServiceSubcategory' => 'Подкатегории услуг',
|
||||
'Menu:ServiceSubcategory+' => 'Подкатегории услуг',
|
||||
'Menu:Service' => 'Услуги',
|
||||
'Menu:Service+' => 'Услуги',
|
||||
'Menu:ServiceElement' => 'Элементы услуг',
|
||||
'Menu:ServiceElement+' => 'Элементы услуг',
|
||||
'Menu:SLA' => 'SLA',
|
||||
'Menu:SLA+' => 'Соглашения об уровне услуг',
|
||||
'Menu:SLT' => 'SLT',
|
||||
'Menu:SLT+' => 'Целевые показатели уровня услуг',
|
||||
'Menu:DeliveryModel' => 'Модели предоставления услуг',
|
||||
'Menu:DeliveryModel+' => 'Модели предоставления услуг (Delivery Models)',
|
||||
|
||||
));
|
||||
|
||||
|
||||
//
|
||||
// Class: Organization
|
||||
//
|
||||
|
||||
Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Class:Organization/Attribute:deliverymodel_id' => 'Модель предоставления услуг',
|
||||
'Class:Organization/Attribute:deliverymodel_id+' => 'Модель предоставления услуг (Delivery Model)',
|
||||
'Class:Organization/Attribute:deliverymodel_name' => 'Модель предоставления услуг',
|
||||
'Class:Organization/Attribute:deliverymodel_name+' => '',
|
||||
));
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Class: ContractType
|
||||
//
|
||||
|
||||
Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Class:ContractType' => 'Тип договора',
|
||||
'Class:ContractType+' => '',
|
||||
));
|
||||
|
||||
|
||||
//
|
||||
// Class: Contract
|
||||
//
|
||||
|
||||
Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Class:Contract' => 'Договор',
|
||||
'Class:Contract+' => '',
|
||||
'Class:Contract/Attribute:name' => 'Название',
|
||||
'Class:Contract/Attribute:name+' => '',
|
||||
'Class:Contract/Attribute:org_id' => 'Заказчик',
|
||||
'Class:Contract/Attribute:org_id+' => '',
|
||||
'Class:Contract/Attribute:organization_name' => 'Заказчик',
|
||||
'Class:Contract/Attribute:organization_name+' => '',
|
||||
'Class:Contract/Attribute:contacts_list' => 'Контакты',
|
||||
'Class:Contract/Attribute:contacts_list+' => 'Связанные контакты',
|
||||
'Class:Contract/Attribute:documents_list' => 'Документы',
|
||||
'Class:Contract/Attribute:documents_list+' => 'Связанные документы',
|
||||
'Class:Contract/Attribute:description' => 'Описание',
|
||||
'Class:Contract/Attribute:description+' => '',
|
||||
'Class:Contract/Attribute:start_date' => 'Дата начала',
|
||||
'Class:Contract/Attribute:start_date+' => '',
|
||||
'Class:Contract/Attribute:end_date' => 'Дата окончания',
|
||||
'Class:Contract/Attribute:end_date+' => '',
|
||||
'Class:Contract/Attribute:cost' => 'Стоимость',
|
||||
'Class:Contract/Attribute:cost+' => '',
|
||||
'Class:Contract/Attribute:cost_currency' => 'Валюта стоимости',
|
||||
'Class:Contract/Attribute:cost_currency+' => '',
|
||||
'Class:Contract/Attribute:cost_currency/Value:dollars' => 'Доллары',
|
||||
'Class:Contract/Attribute:cost_currency/Value:dollars+' => '',
|
||||
'Class:Contract/Attribute:cost_currency/Value:euros' => 'Евро',
|
||||
'Class:Contract/Attribute:cost_currency/Value:euros+' => '',
|
||||
'Class:Contract/Attribute:contracttype_id' => 'Тип договора',
|
||||
'Class:Contract/Attribute:contracttype_id+' => '',
|
||||
'Class:Contract/Attribute:contracttype_name' => 'Тип договора',
|
||||
'Class:Contract/Attribute:contracttype_name+' => '',
|
||||
'Class:Contract/Attribute:billing_frequency' => 'Периодичность платежей',
|
||||
'Class:Contract/Attribute:billing_frequency+' => '',
|
||||
'Class:Contract/Attribute:cost_unit' => 'Единица стоимости',
|
||||
'Class:Contract/Attribute:cost_unit+' => '',
|
||||
'Class:Contract/Attribute:provider_id' => 'Поставщик',
|
||||
'Class:Contract/Attribute:provider_id+' => '',
|
||||
'Class:Contract/Attribute:provider_name' => 'Поставщик',
|
||||
'Class:Contract/Attribute:provider_name+' => '',
|
||||
'Class:Contract/Attribute:status' => 'Статус',
|
||||
'Class:Contract/Attribute:status+' => '',
|
||||
'Class:Contract/Attribute:status/Value:implementation' => 'Внедрение',
|
||||
'Class:Contract/Attribute:status/Value:implementation+' => 'Внедрение',
|
||||
'Class:Contract/Attribute:status/Value:obsolete' => 'Устаревшее',
|
||||
'Class:Contract/Attribute:status/Value:obsolete+' => 'Устаревшее',
|
||||
'Class:Contract/Attribute:status/Value:production' => 'Эксплуатация',
|
||||
'Class:Contract/Attribute:status/Value:production+' => 'Эксплуатация',
|
||||
'Class:Contract/Attribute:finalclass' => 'Тип',
|
||||
'Class:Contract/Attribute:finalclass+' => '',
|
||||
));
|
||||
|
||||
//
|
||||
// Class: CustomerContract
|
||||
//
|
||||
|
||||
Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Class:CustomerContract' => 'Договор с заказчиком',
|
||||
'Class:CustomerContract+' => '',
|
||||
'Class:CustomerContract/Attribute:services_list' => 'Услуги',
|
||||
'Class:CustomerContract/Attribute:services_list+' => 'Все услуги, предоставляемые по договору',
|
||||
'Class:CustomerContract/Attribute:functionalcis_list' => 'КЕ',
|
||||
'Class:CustomerContract/Attribute:functionalcis_list+' => 'Конфигурационные единицы, охватываемые договором',
|
||||
'Class:CustomerContract/Attribute:providercontracts_list' => 'Договоры с поставщиками',
|
||||
'Class:CustomerContract/Attribute:providercontracts_list+' => 'Договоры с поставщиками, используемые для поддержки услуг данного договора (Underpinning Contracts)',
|
||||
));
|
||||
|
||||
//
|
||||
// Class: ProviderContract
|
||||
//
|
||||
|
||||
Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Class:ProviderContract' => 'Договор с поставщиком',
|
||||
'Class:ProviderContract+' => '',
|
||||
'Class:ProviderContract/Attribute:functionalcis_list' => 'КЕ',
|
||||
'Class:ProviderContract/Attribute:functionalcis_list+' => 'Конфигурационные единицы, охватываемые договором',
|
||||
'Class:ProviderContract/Attribute:sla' => 'SLA',
|
||||
'Class:ProviderContract/Attribute:sla+' => 'Соглашение об уровне услуги (Service Level Agreement)',
|
||||
'Class:ProviderContract/Attribute:coverage' => 'Время обслуживания',
|
||||
'Class:ProviderContract/Attribute:coverage+' => '',
|
||||
));
|
||||
|
||||
//
|
||||
// Class: lnkContactToContract
|
||||
//
|
||||
|
||||
Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Class:lnkContactToContract' => 'Связь Контакт/Договор',
|
||||
'Class:lnkContactToContract+' => '',
|
||||
'Class:lnkContactToContract/Attribute:contract_id' => 'Договор',
|
||||
'Class:lnkContactToContract/Attribute:contract_id+' => '',
|
||||
'Class:lnkContactToContract/Attribute:contract_name' => 'Договор',
|
||||
'Class:lnkContactToContract/Attribute:contract_name+' => '',
|
||||
'Class:lnkContactToContract/Attribute:contact_id' => 'Контакт',
|
||||
'Class:lnkContactToContract/Attribute:contact_id+' => '',
|
||||
'Class:lnkContactToContract/Attribute:contact_name' => 'Контакт',
|
||||
'Class:lnkContactToContract/Attribute:contact_name+' => '',
|
||||
));
|
||||
|
||||
//
|
||||
// Class: lnkContractToDocument
|
||||
//
|
||||
|
||||
Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Class:lnkContractToDocument' => 'Связь Договор/Документ',
|
||||
'Class:lnkContractToDocument+' => '',
|
||||
'Class:lnkContractToDocument/Attribute:contract_id' => 'Договор',
|
||||
'Class:lnkContractToDocument/Attribute:contract_id+' => '',
|
||||
'Class:lnkContractToDocument/Attribute:contract_name' => 'Договор',
|
||||
'Class:lnkContractToDocument/Attribute:contract_name+' => '',
|
||||
'Class:lnkContractToDocument/Attribute:document_id' => 'Документ',
|
||||
'Class:lnkContractToDocument/Attribute:document_id+' => '',
|
||||
'Class:lnkContractToDocument/Attribute:document_name' => 'Документ',
|
||||
'Class:lnkContractToDocument/Attribute:document_name+' => '',
|
||||
));
|
||||
|
||||
//
|
||||
// Class: lnkFunctionalCIToProviderContract
|
||||
//
|
||||
|
||||
Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Class:lnkFunctionalCIToProviderContract' => 'Связь Функциональная КЕ/Договор с поставщиком',
|
||||
'Class:lnkFunctionalCIToProviderContract+' => '',
|
||||
'Class:lnkFunctionalCIToProviderContract/Attribute:providercontract_id' => 'Договор с поставщиком',
|
||||
'Class:lnkFunctionalCIToProviderContract/Attribute:providercontract_id+' => '',
|
||||
'Class:lnkFunctionalCIToProviderContract/Attribute:providercontract_name' => 'Договор с поставщиком',
|
||||
'Class:lnkFunctionalCIToProviderContract/Attribute:providercontract_name+' => '',
|
||||
'Class:lnkFunctionalCIToProviderContract/Attribute:functionalci_id' => 'КЕ',
|
||||
'Class:lnkFunctionalCIToProviderContract/Attribute:functionalci_id+' => '',
|
||||
'Class:lnkFunctionalCIToProviderContract/Attribute:functionalci_name' => 'КЕ',
|
||||
'Class:lnkFunctionalCIToProviderContract/Attribute:functionalci_name+' => '',
|
||||
));
|
||||
|
||||
//
|
||||
// Class: ServiceFamily
|
||||
//
|
||||
|
||||
Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Class:ServiceFamily' => 'Пакет услуг',
|
||||
'Class:ServiceFamily+' => '',
|
||||
'Class:ServiceFamily/Attribute:name' => 'Название',
|
||||
'Class:ServiceFamily/Attribute:name+' => '',
|
||||
'Class:ServiceFamily/Attribute:services_list' => 'Услуги',
|
||||
'Class:ServiceFamily/Attribute:services_list+' => 'Связанные услуги',
|
||||
));
|
||||
|
||||
//
|
||||
// Class: Service
|
||||
//
|
||||
|
||||
Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Class:Service' => 'Услуга',
|
||||
'Class:Service+' => '',
|
||||
'Class:Service/Attribute:name' => 'Название',
|
||||
'Class:Service/Attribute:name+' => '',
|
||||
'Class:Service/Attribute:org_id' => 'Поставщик',
|
||||
'Class:Service/Attribute:org_id+' => '',
|
||||
'Class:Service/Attribute:organization_name' => 'Поставщик',
|
||||
'Class:Service/Attribute:organization_name+' => '',
|
||||
'Class:Service/Attribute:description' => 'Описание',
|
||||
'Class:Service/Attribute:description+' => '',
|
||||
'Class:Service/Attribute:servicefamily_id' => 'Пакет услуг',
|
||||
'Class:Service/Attribute:servicefamily_id+' => '',
|
||||
'Class:Service/Attribute:servicefamily_name' => 'Пакет услуг',
|
||||
'Class:Service/Attribute:servicefamily_name+' => '',
|
||||
'Class:Service/Attribute:documents_list' => 'Документы',
|
||||
'Class:Service/Attribute:documents_list+' => 'Связанные документы',
|
||||
'Class:Service/Attribute:contacts_list' => 'Контакты',
|
||||
'Class:Service/Attribute:contacts_list+' => 'Связанные контакты',
|
||||
'Class:Service/Attribute:status' => 'Статус',
|
||||
'Class:Service/Attribute:status+' => '',
|
||||
'Class:Service/Attribute:status/Value:implementation' => 'Внедрение',
|
||||
'Class:Service/Attribute:status/Value:implementation+' => 'Внедрение',
|
||||
'Class:Service/Attribute:status/Value:obsolete' => 'Устаревшее',
|
||||
'Class:Service/Attribute:status/Value:obsolete+' => 'Устаревшее',
|
||||
'Class:Service/Attribute:status/Value:production' => 'Эксплуатация',
|
||||
'Class:Service/Attribute:status/Value:production+' => 'Эксплуатация',
|
||||
'Class:Service/Attribute:customercontracts_list' => 'Договоры с заказчиками',
|
||||
'Class:Service/Attribute:customercontracts_list+' => 'Договоры с заказчиками, по которым предоставляется услуга',
|
||||
'Class:Service/Attribute:servicesubcategories_list' => 'Подкатегории услуги',
|
||||
'Class:Service/Attribute:servicesubcategories_list+' => 'Подкатегории услуги',
|
||||
));
|
||||
|
||||
//
|
||||
// Class: lnkDocumentToService
|
||||
//
|
||||
|
||||
Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Class:lnkDocumentToService' => 'Связь Документ/Услуга',
|
||||
'Class:lnkDocumentToService+' => '',
|
||||
'Class:lnkDocumentToService/Attribute:service_id' => 'Услуга',
|
||||
'Class:lnkDocumentToService/Attribute:service_id+' => '',
|
||||
'Class:lnkDocumentToService/Attribute:service_name' => 'Услуга',
|
||||
'Class:lnkDocumentToService/Attribute:service_name+' => '',
|
||||
'Class:lnkDocumentToService/Attribute:document_id' => 'Документ',
|
||||
'Class:lnkDocumentToService/Attribute:document_id+' => '',
|
||||
'Class:lnkDocumentToService/Attribute:document_name' => 'Документ',
|
||||
'Class:lnkDocumentToService/Attribute:document_name+' => '',
|
||||
));
|
||||
|
||||
//
|
||||
// Class: lnkContactToService
|
||||
//
|
||||
|
||||
Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Class:lnkContactToService' => 'Связь Контакт/Услуга',
|
||||
'Class:lnkContactToService+' => '',
|
||||
'Class:lnkContactToService/Attribute:service_id' => 'Услуга',
|
||||
'Class:lnkContactToService/Attribute:service_id+' => '',
|
||||
'Class:lnkContactToService/Attribute:service_name' => 'Услуга',
|
||||
'Class:lnkContactToService/Attribute:service_name+' => '',
|
||||
'Class:lnkContactToService/Attribute:contact_id' => 'Контакт',
|
||||
'Class:lnkContactToService/Attribute:contact_id+' => '',
|
||||
'Class:lnkContactToService/Attribute:contact_name' => 'Контакт',
|
||||
'Class:lnkContactToService/Attribute:contact_name+' => '',
|
||||
));
|
||||
|
||||
//
|
||||
// Class: ServiceSubcategory
|
||||
//
|
||||
|
||||
Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Class:ServiceSubcategory' => 'Подкатегория услуги',
|
||||
'Class:ServiceSubcategory+' => '',
|
||||
'Class:ServiceSubcategory/Attribute:name' => 'Название',
|
||||
'Class:ServiceSubcategory/Attribute:name+' => '',
|
||||
'Class:ServiceSubcategory/Attribute:description' => 'Описание',
|
||||
'Class:ServiceSubcategory/Attribute:description+' => '',
|
||||
'Class:ServiceSubcategory/Attribute:service_id' => 'Услуга',
|
||||
'Class:ServiceSubcategory/Attribute:service_id+' => '',
|
||||
'Class:ServiceSubcategory/Attribute:service_name' => 'Услуга',
|
||||
'Class:ServiceSubcategory/Attribute:service_name+' => '',
|
||||
'Class:ServiceSubcategory/Attribute:status' => 'Статус',
|
||||
'Class:ServiceSubcategory/Attribute:status+' => '',
|
||||
'Class:ServiceSubcategory/Attribute:status/Value:implementation' => 'Внедрение',
|
||||
'Class:ServiceSubcategory/Attribute:status/Value:implementation+' => 'Внедрение',
|
||||
'Class:ServiceSubcategory/Attribute:status/Value:obsolete' => 'Устаревшее',
|
||||
'Class:ServiceSubcategory/Attribute:status/Value:obsolete+' => 'Устаревшее',
|
||||
'Class:ServiceSubcategory/Attribute:status/Value:production' => 'Эксплуатация',
|
||||
'Class:ServiceSubcategory/Attribute:status/Value:production+' => 'Эксплуатация',
|
||||
'Class:ServiceSubcategory/Attribute:request_type' => 'Тип запроса',
|
||||
'Class:ServiceSubcategory/Attribute:request_type+' => '',
|
||||
'Class:ServiceSubcategory/Attribute:request_type/Value:incident' => 'Инцидент',
|
||||
'Class:ServiceSubcategory/Attribute:request_type/Value:incident+' => 'Инцидент',
|
||||
'Class:ServiceSubcategory/Attribute:request_type/Value:service_request' => 'Запрос на обслуживание',
|
||||
'Class:ServiceSubcategory/Attribute:request_type/Value:service_request+' => 'Запрос на обслуживание',
|
||||
'Class:ServiceSubcategory/Attribute:service_provider' => 'Поставщик',
|
||||
'Class:ServiceSubcategory/Attribute:service_org_id' => 'Поставщик',
|
||||
|
||||
));
|
||||
|
||||
//
|
||||
// Class: SLA
|
||||
//
|
||||
|
||||
Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Class:SLA' => 'SLA',
|
||||
'Class:SLA+' => '',
|
||||
'Class:SLA/Attribute:name' => 'Название',
|
||||
'Class:SLA/Attribute:name+' => '',
|
||||
'Class:SLA/Attribute:description' => 'Описание',
|
||||
'Class:SLA/Attribute:description+' => '',
|
||||
'Class:SLA/Attribute:org_id' => 'Организация',
|
||||
'Class:SLA/Attribute:org_id+' => '',
|
||||
'Class:SLA/Attribute:organization_name' => 'Организация',
|
||||
'Class:SLA/Attribute:organization_name+' => '',
|
||||
'Class:SLA/Attribute:slts_list' => 'SLT',
|
||||
'Class:SLA/Attribute:slts_list+' => 'Целевой показатель уровня услуги (Service Level Target)',
|
||||
'Class:SLA/Attribute:customercontracts_list' => 'Договоры с заказчиками',
|
||||
'Class:SLA/Attribute:customercontracts_list+' => 'Договоры с заказчиками, в которых используется SLA',
|
||||
));
|
||||
|
||||
//
|
||||
// Class: SLT
|
||||
//
|
||||
|
||||
Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Class:SLT' => 'SLT',
|
||||
'Class:SLT+' => '',
|
||||
'Class:SLT/Attribute:name' => 'Название',
|
||||
'Class:SLT/Attribute:name+' => '',
|
||||
'Class:SLT/Attribute:priority' => 'Приоритет',
|
||||
'Class:SLT/Attribute:priority+' => '',
|
||||
'Class:SLT/Attribute:priority/Value:1' => 'Критический',
|
||||
'Class:SLT/Attribute:priority/Value:1+' => 'Критический',
|
||||
'Class:SLT/Attribute:priority/Value:2' => 'Высокий',
|
||||
'Class:SLT/Attribute:priority/Value:2+' => 'Высокий',
|
||||
'Class:SLT/Attribute:priority/Value:3' => 'Средний',
|
||||
'Class:SLT/Attribute:priority/Value:3+' => 'Средний',
|
||||
'Class:SLT/Attribute:priority/Value:4' => 'Низкий',
|
||||
'Class:SLT/Attribute:priority/Value:4+' => 'Низкий',
|
||||
'Class:SLT/Attribute:request_type' => 'Тип запроса',
|
||||
'Class:SLT/Attribute:request_type+' => '',
|
||||
'Class:SLT/Attribute:request_type/Value:incident' => 'Инцидент',
|
||||
'Class:SLT/Attribute:request_type/Value:incident+' => 'Инцидент',
|
||||
'Class:SLT/Attribute:request_type/Value:service_request' => 'Запрос на обслуживание',
|
||||
'Class:SLT/Attribute:request_type/Value:service_request+' => 'Запрос на обслуживание',
|
||||
'Class:SLT/Attribute:metric' => 'Метрика',
|
||||
'Class:SLT/Attribute:metric+' => '',
|
||||
'Class:SLT/Attribute:metric/Value:tto' => 'TTO',
|
||||
'Class:SLT/Attribute:metric/Value:tto+' => 'Time-To-Own - время до назначения агента (принятия в работу)',
|
||||
'Class:SLT/Attribute:metric/Value:ttr' => 'TTR',
|
||||
'Class:SLT/Attribute:metric/Value:ttr+' => 'Time-To-Resolve - время до решения',
|
||||
'Class:SLT/Attribute:value' => 'Значение',
|
||||
'Class:SLT/Attribute:value+' => '',
|
||||
'Class:SLT/Attribute:unit' => 'Единицы',
|
||||
'Class:SLT/Attribute:unit+' => '',
|
||||
'Class:SLT/Attribute:unit/Value:hours' => 'Часы',
|
||||
'Class:SLT/Attribute:unit/Value:hours+' => 'Часы',
|
||||
'Class:SLT/Attribute:unit/Value:minutes' => 'Минуты',
|
||||
'Class:SLT/Attribute:unit/Value:minutes+' => 'Минуты',
|
||||
));
|
||||
|
||||
//
|
||||
// Class: lnkSLAToSLT
|
||||
//
|
||||
|
||||
Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Class:lnkSLAToSLT' => 'Связь SLA/SLT',
|
||||
'Class:lnkSLAToSLT+' => '',
|
||||
'Class:lnkSLAToSLT/Attribute:sla_id' => 'SLA',
|
||||
'Class:lnkSLAToSLT/Attribute:sla_id+' => '',
|
||||
'Class:lnkSLAToSLT/Attribute:sla_name' => 'SLA',
|
||||
'Class:lnkSLAToSLT/Attribute:sla_name+' => '',
|
||||
'Class:lnkSLAToSLT/Attribute:slt_id' => 'SLT',
|
||||
'Class:lnkSLAToSLT/Attribute:slt_id+' => '',
|
||||
'Class:lnkSLAToSLT/Attribute:slt_name' => 'SLT',
|
||||
'Class:lnkSLAToSLT/Attribute:slt_name+' => '',
|
||||
));
|
||||
|
||||
//
|
||||
// Class: lnkCustomerContractToService
|
||||
//
|
||||
|
||||
Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Class:lnkCustomerContractToService' => 'Связь Договор с заказчиком/Услуга',
|
||||
'Class:lnkCustomerContractToService+' => '',
|
||||
'Class:lnkCustomerContractToService/Attribute:customercontract_id' => 'Договор с заказчиком',
|
||||
'Class:lnkCustomerContractToService/Attribute:customercontract_id+' => '',
|
||||
'Class:lnkCustomerContractToService/Attribute:customercontract_name' => 'Договор с заказчиком',
|
||||
'Class:lnkCustomerContractToService/Attribute:customercontract_name+' => '',
|
||||
'Class:lnkCustomerContractToService/Attribute:service_id' => 'Услуга',
|
||||
'Class:lnkCustomerContractToService/Attribute:service_id+' => '',
|
||||
'Class:lnkCustomerContractToService/Attribute:service_name' => 'Услуга',
|
||||
'Class:lnkCustomerContractToService/Attribute:service_name+' => '',
|
||||
'Class:lnkCustomerContractToService/Attribute:sla_id' => 'SLA',
|
||||
'Class:lnkCustomerContractToService/Attribute:sla_id+' => '',
|
||||
'Class:lnkCustomerContractToService/Attribute:sla_name' => 'SLA',
|
||||
'Class:lnkCustomerContractToService/Attribute:sla_name+' => '',
|
||||
));
|
||||
|
||||
//
|
||||
// Class: lnkCustomerContractToProviderContract
|
||||
//
|
||||
|
||||
Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Class:lnkCustomerContractToProviderContract' => 'Связь Договор с заказчиком/Договор с поставщиком',
|
||||
'Class:lnkCustomerContractToProviderContract+' => '',
|
||||
'Class:lnkCustomerContractToProviderContract/Attribute:customercontract_id' => 'Договор с заказчиком',
|
||||
'Class:lnkCustomerContractToProviderContract/Attribute:customercontract_id+' => '',
|
||||
'Class:lnkCustomerContractToProviderContract/Attribute:customercontract_name' => 'Договор с заказчиком',
|
||||
'Class:lnkCustomerContractToProviderContract/Attribute:customercontract_name+' => '',
|
||||
'Class:lnkCustomerContractToProviderContract/Attribute:providercontract_id' => 'Договор с поставщиком',
|
||||
'Class:lnkCustomerContractToProviderContract/Attribute:providercontract_id+' => '',
|
||||
'Class:lnkCustomerContractToProviderContract/Attribute:providercontract_name' => 'Договор с поставщиком',
|
||||
'Class:lnkCustomerContractToProviderContract/Attribute:providercontract_name+' => '',
|
||||
));
|
||||
|
||||
//
|
||||
// Class: lnkCustomerContractToFunctionalCI
|
||||
//
|
||||
|
||||
Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Class:lnkCustomerContractToFunctionalCI' => 'Связь Договор с заказчиком/Функциональная КЕ',
|
||||
'Class:lnkCustomerContractToFunctionalCI+' => '',
|
||||
'Class:lnkCustomerContractToFunctionalCI/Attribute:customercontract_id' => 'Договор с заказчиком',
|
||||
'Class:lnkCustomerContractToFunctionalCI/Attribute:customercontract_id+' => '',
|
||||
'Class:lnkCustomerContractToFunctionalCI/Attribute:customercontract_name' => 'Договор с заказчиком',
|
||||
'Class:lnkCustomerContractToFunctionalCI/Attribute:customercontract_name+' => '',
|
||||
'Class:lnkCustomerContractToFunctionalCI/Attribute:functionalci_id' => 'КЕ',
|
||||
'Class:lnkCustomerContractToFunctionalCI/Attribute:functionalci_id+' => '',
|
||||
'Class:lnkCustomerContractToFunctionalCI/Attribute:functionalci_name' => 'КЕ',
|
||||
'Class:lnkCustomerContractToFunctionalCI/Attribute:functionalci_name+' => '',
|
||||
));
|
||||
|
||||
//
|
||||
// Class: DeliveryModel
|
||||
//
|
||||
|
||||
Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Class:DeliveryModel' => 'Модель предоставления услуг',
|
||||
'Class:DeliveryModel+' => '',
|
||||
'Class:DeliveryModel/Attribute:name' => 'Название',
|
||||
'Class:DeliveryModel/Attribute:name+' => '',
|
||||
'Class:DeliveryModel/Attribute:org_id' => 'Организация',
|
||||
'Class:DeliveryModel/Attribute:org_id+' => '',
|
||||
'Class:DeliveryModel/Attribute:organization_name' => 'Организация',
|
||||
'Class:DeliveryModel/Attribute:organization_name+' => '',
|
||||
'Class:DeliveryModel/Attribute:description' => 'Описание',
|
||||
'Class:DeliveryModel/Attribute:description+' => '',
|
||||
'Class:DeliveryModel/Attribute:contacts_list' => 'Контакты',
|
||||
'Class:DeliveryModel/Attribute:contacts_list+' => 'Контакты (команды и персоны), которые участвуют в предоставлении услуг по этой модели',
|
||||
'Class:DeliveryModel/Attribute:customers_list' => 'Заказчики',
|
||||
'Class:DeliveryModel/Attribute:customers_list+' => 'Заказчики, которым предоставляются услуги по этой модели',
|
||||
));
|
||||
|
||||
//
|
||||
// Class: lnkDeliveryModelToContact
|
||||
//
|
||||
|
||||
Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Class:lnkDeliveryModelToContact' => 'Связь Модель предоставления услуг/Контакт',
|
||||
'Class:lnkDeliveryModelToContact+' => '',
|
||||
'Class:lnkDeliveryModelToContact/Attribute:deliverymodel_id' => 'Модель предоставления услуг',
|
||||
'Class:lnkDeliveryModelToContact/Attribute:deliverymodel_id+' => '',
|
||||
'Class:lnkDeliveryModelToContact/Attribute:deliverymodel_name' => 'Модель предоставления услуг',
|
||||
'Class:lnkDeliveryModelToContact/Attribute:deliverymodel_name+' => '',
|
||||
'Class:lnkDeliveryModelToContact/Attribute:contact_id' => 'Контакт',
|
||||
'Class:lnkDeliveryModelToContact/Attribute:contact_id+' => '',
|
||||
'Class:lnkDeliveryModelToContact/Attribute:contact_name' => 'Контакт',
|
||||
'Class:lnkDeliveryModelToContact/Attribute:contact_name+' => '',
|
||||
'Class:lnkDeliveryModelToContact/Attribute:role_id' => 'Роль',
|
||||
'Class:lnkDeliveryModelToContact/Attribute:role_id+' => '',
|
||||
'Class:lnkDeliveryModelToContact/Attribute:role_name' => 'Роль',
|
||||
'Class:lnkDeliveryModelToContact/Attribute:role_name+' => '',
|
||||
));
|
||||
@@ -174,6 +174,7 @@
|
||||
</fields>
|
||||
<methods/>
|
||||
<presentation>
|
||||
<parent>Typology</parent>
|
||||
<details>
|
||||
<items>
|
||||
<item id="name">
|
||||
|
||||
@@ -2,20 +2,39 @@
|
||||
|
||||
/**
|
||||
* Локализация интерфейса Combodo iTop подготовлена сообществом iTop по-русски http://community.itop-itsm.ru.
|
||||
*
|
||||
* @author Vladimir Kunin <v.b.kunin@gmail.com>
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*
|
||||
* @author Vladimir Kunin <v.b.kunin@gmail.com>
|
||||
* @link http://community.itop-itsm.ru iTop Russian Community
|
||||
* @link https://github.com/itop-itsm-ru/itop-rus
|
||||
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
|
||||
*
|
||||
* Инструкция по установке
|
||||
*
|
||||
* Процесс установки заключается в замене имеющихся локализационных файлов полученными и последующем запуске процедуры обновления iTop для перекомпиляции кода.
|
||||
* 1. Скопируйте с заменой два полученных файла из "itop-rus/dictionaries" в "путь/до/вашего/itop/dictionaries".
|
||||
* 2. Скопируйте с заменой полученные файлы "itop-rus/datamodels/2.x/название-модуля/ru.dict.название-модуля.php" в "путь/до/вашего/itop/datamodels/2.x/название-модуля".
|
||||
* 3. Перейдите по адресу "http://адрес/вашего/itop/setup", при этом файл "путь/до/вашего/itop/conf/production/config-itop.php" должен быть доступен для записи.
|
||||
* 4. На второй странице установщика выберите "Upgrade an existing iTop instance" и следуйте дальнейшим инструкциям установщика.
|
||||
*
|
||||
* Ответы на вопросы по установке и использованию переводов, а также на любые другие вопросы по iTop всегда можно получить на сайте сообщества iTop по-русски http://community.itop-itsm.ru.
|
||||
*
|
||||
*/
|
||||
|
||||
// Dictionnay conventions
|
||||
// Class:<class_name>
|
||||
// Class:<class_name>+
|
||||
// Class:<class_name>/Attribute:<attribute_code>
|
||||
// Class:<class_name>/Attribute:<attribute_code>+
|
||||
// Class:<class_name>/Attribute:<attribute_code>/Value:<value>
|
||||
// Class:<class_name>/Attribute:<attribute_code>/Value:<value>+
|
||||
// Class:<class_name>/Stimulus:<stimulus_code>
|
||||
// Class:<class_name>/Stimulus:<stimulus_code>+
|
||||
|
||||
|
||||
Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Menu:ServiceManagement' => 'Управление услугами',
|
||||
'Menu:ServiceManagement+' => 'Управление услугами',
|
||||
'Menu:Service:Overview' => 'Обзор',
|
||||
'Menu:Service:Overview+' => 'Управление услугами - Обзор',
|
||||
'Menu:Service:Overview+' => '',
|
||||
'UI-ServiceManagementMenu-ContractsBySrvLevel' => 'Договоры по уровню услуг',
|
||||
'UI-ServiceManagementMenu-ContractsByStatus' => 'Договоры по статусу',
|
||||
'UI-ServiceManagementMenu-ContractsEndingIn30Days' => 'Договоры, оканчивающиеся в течение 30-ти дней',
|
||||
@@ -35,7 +54,7 @@ Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Menu:SLT' => 'SLT',
|
||||
'Menu:SLT+' => 'Целевые показатели уровня услуг',
|
||||
'Menu:DeliveryModel' => 'Модели предоставления услуг',
|
||||
'Menu:DeliveryModel+' => 'Модели предоставления услуг (Delivery Models)',
|
||||
'Menu:DeliveryModel+' => 'Модели предоставления услуг (Delivery models)',
|
||||
'Menu:ServiceFamily' => 'Пакеты услуг',
|
||||
'Menu:ServiceFamily+' => 'Пакеты услуг',
|
||||
'Menu:Procedure' => 'Каталог процедур',
|
||||
@@ -50,9 +69,9 @@ Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
//
|
||||
|
||||
Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Class:Organization/Attribute:deliverymodel_id' => 'Модель предоставления услуг',
|
||||
'Class:Organization/Attribute:deliverymodel_id+' => 'Модель предоставления услуг (Delivery Model)',
|
||||
'Class:Organization/Attribute:deliverymodel_name' => 'Модель предоставления услуг',
|
||||
'Class:Organization/Attribute:deliverymodel_id' => 'Delivery model',
|
||||
'Class:Organization/Attribute:deliverymodel_id+' => '',
|
||||
'Class:Organization/Attribute:deliverymodel_name' => 'Delivery model name',
|
||||
|
||||
));
|
||||
|
||||
@@ -77,8 +96,8 @@ Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Class:Contract/Attribute:name+' => '',
|
||||
'Class:Contract/Attribute:org_id' => 'Заказчик',
|
||||
'Class:Contract/Attribute:org_id+' => '',
|
||||
'Class:Contract/Attribute:organization_name' => 'Заказчик',
|
||||
'Class:Contract/Attribute:organization_name+' => '',
|
||||
'Class:Contract/Attribute:organization_name' => 'Имя заказчика',
|
||||
'Class:Contract/Attribute:organization_name+' => 'Common name',
|
||||
'Class:Contract/Attribute:contacts_list' => 'Контакты',
|
||||
'Class:Contract/Attribute:contacts_list+' => 'Связанные контакты',
|
||||
'Class:Contract/Attribute:documents_list' => 'Документы',
|
||||
@@ -99,25 +118,25 @@ Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Class:Contract/Attribute:cost_currency/Value:euros+' => '',
|
||||
'Class:Contract/Attribute:contracttype_id' => 'Тип договора',
|
||||
'Class:Contract/Attribute:contracttype_id+' => '',
|
||||
'Class:Contract/Attribute:contracttype_name' => 'Тип договора',
|
||||
'Class:Contract/Attribute:contracttype_name' => 'Имя типа договора',
|
||||
'Class:Contract/Attribute:contracttype_name+' => '',
|
||||
'Class:Contract/Attribute:billing_frequency' => 'Периодичность платежей',
|
||||
'Class:Contract/Attribute:billing_frequency' => 'Частота платежей',
|
||||
'Class:Contract/Attribute:billing_frequency+' => '',
|
||||
'Class:Contract/Attribute:cost_unit' => 'Единица стоимости',
|
||||
'Class:Contract/Attribute:cost_unit+' => '',
|
||||
'Class:Contract/Attribute:provider_id' => 'Поставщик',
|
||||
'Class:Contract/Attribute:provider_id+' => '',
|
||||
'Class:Contract/Attribute:provider_name' => 'Поставщик',
|
||||
'Class:Contract/Attribute:provider_name+' => '',
|
||||
'Class:Contract/Attribute:provider_name' => 'Имя поставщика',
|
||||
'Class:Contract/Attribute:provider_name+' => 'Common name',
|
||||
'Class:Contract/Attribute:status' => 'Статус',
|
||||
'Class:Contract/Attribute:status+' => '',
|
||||
'Class:Contract/Attribute:status/Value:implementation' => 'Внедрение',
|
||||
'Class:Contract/Attribute:status/Value:implementation+' => 'Внедрение',
|
||||
'Class:Contract/Attribute:status/Value:implementation+' => 'implementation',
|
||||
'Class:Contract/Attribute:status/Value:obsolete' => 'Устаревшее',
|
||||
'Class:Contract/Attribute:status/Value:obsolete+' => 'Устаревшее',
|
||||
'Class:Contract/Attribute:status/Value:production' => 'Эксплуатация',
|
||||
'Class:Contract/Attribute:status/Value:production+' => 'Эксплуатация',
|
||||
'Class:Contract/Attribute:finalclass' => 'Тип',
|
||||
'Class:Contract/Attribute:status/Value:obsolete+' => 'obsolete',
|
||||
'Class:Contract/Attribute:status/Value:production' => 'Производство',
|
||||
'Class:Contract/Attribute:status/Value:production+' => 'production',
|
||||
'Class:Contract/Attribute:finalclass' => 'Тип договора',
|
||||
'Class:Contract/Attribute:finalclass+' => '',
|
||||
));
|
||||
//
|
||||
@@ -128,7 +147,7 @@ Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Class:CustomerContract' => 'Договор с заказчиком',
|
||||
'Class:CustomerContract+' => '',
|
||||
'Class:CustomerContract/Attribute:services_list' => 'Услуги',
|
||||
'Class:CustomerContract/Attribute:services_list+' => 'Все услуги, предоставляемые по договору',
|
||||
'Class:CustomerContract/Attribute:services_list+' => 'Связанные услуги',
|
||||
));
|
||||
|
||||
//
|
||||
@@ -139,14 +158,14 @@ Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Class:ProviderContract' => 'Договор с поставщиком',
|
||||
'Class:ProviderContract+' => '',
|
||||
'Class:ProviderContract/Attribute:functionalcis_list' => 'КЕ',
|
||||
'Class:ProviderContract/Attribute:functionalcis_list+' => 'Конфигурационные единицы, охватываемые договором',
|
||||
'Class:ProviderContract/Attribute:functionalcis_list+' => 'Связанные конфигурационные единицы',
|
||||
'Class:ProviderContract/Attribute:sla' => 'SLA',
|
||||
'Class:ProviderContract/Attribute:sla+' => 'Соглашение об уровне услуги (Service Level Agreement)',
|
||||
'Class:ProviderContract/Attribute:coverage' => 'Время обслуживания',
|
||||
'Class:ProviderContract/Attribute:coverage' => 'Время работы',
|
||||
'Class:ProviderContract/Attribute:coverage+' => '',
|
||||
'Class:ProviderContract/Attribute:contracttype_id' => 'Тип договора',
|
||||
'Class:ProviderContract/Attribute:contracttype_id+' => '',
|
||||
'Class:ProviderContract/Attribute:contracttype_name' => 'Тип договора',
|
||||
'Class:ProviderContract/Attribute:contracttype_name' => 'Имя типа договора',
|
||||
'Class:ProviderContract/Attribute:contracttype_name+' => '',
|
||||
));
|
||||
|
||||
@@ -159,11 +178,11 @@ Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Class:lnkContactToContract+' => '',
|
||||
'Class:lnkContactToContract/Attribute:contract_id' => 'Договор',
|
||||
'Class:lnkContactToContract/Attribute:contract_id+' => '',
|
||||
'Class:lnkContactToContract/Attribute:contract_name' => 'Договор',
|
||||
'Class:lnkContactToContract/Attribute:contract_name' => 'Имя договора',
|
||||
'Class:lnkContactToContract/Attribute:contract_name+' => '',
|
||||
'Class:lnkContactToContract/Attribute:contact_id' => 'Контакт',
|
||||
'Class:lnkContactToContract/Attribute:contact_id+' => '',
|
||||
'Class:lnkContactToContract/Attribute:contact_name' => 'Контакт',
|
||||
'Class:lnkContactToContract/Attribute:contact_name' => 'Контактное лицо',
|
||||
'Class:lnkContactToContract/Attribute:contact_name+' => '',
|
||||
));
|
||||
|
||||
@@ -176,11 +195,11 @@ Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Class:lnkContractToDocument+' => '',
|
||||
'Class:lnkContractToDocument/Attribute:contract_id' => 'Договор',
|
||||
'Class:lnkContractToDocument/Attribute:contract_id+' => '',
|
||||
'Class:lnkContractToDocument/Attribute:contract_name' => 'Договор',
|
||||
'Class:lnkContractToDocument/Attribute:contract_name' => 'Имя договора',
|
||||
'Class:lnkContractToDocument/Attribute:contract_name+' => '',
|
||||
'Class:lnkContractToDocument/Attribute:document_id' => 'Документ',
|
||||
'Class:lnkContractToDocument/Attribute:document_id+' => '',
|
||||
'Class:lnkContractToDocument/Attribute:document_name' => 'Документ',
|
||||
'Class:lnkContractToDocument/Attribute:document_name' => 'Имя документа',
|
||||
'Class:lnkContractToDocument/Attribute:document_name+' => '',
|
||||
));
|
||||
|
||||
@@ -193,11 +212,11 @@ Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Class:lnkFunctionalCIToProviderContract+' => '',
|
||||
'Class:lnkFunctionalCIToProviderContract/Attribute:providercontract_id' => 'Договор с поставщиком',
|
||||
'Class:lnkFunctionalCIToProviderContract/Attribute:providercontract_id+' => '',
|
||||
'Class:lnkFunctionalCIToProviderContract/Attribute:providercontract_name' => 'Договор с поставщиком',
|
||||
'Class:lnkFunctionalCIToProviderContract/Attribute:providercontract_name' => 'Имя договора поставщика',
|
||||
'Class:lnkFunctionalCIToProviderContract/Attribute:providercontract_name+' => '',
|
||||
'Class:lnkFunctionalCIToProviderContract/Attribute:functionalci_id' => 'КЕ',
|
||||
'Class:lnkFunctionalCIToProviderContract/Attribute:functionalci_id+' => '',
|
||||
'Class:lnkFunctionalCIToProviderContract/Attribute:functionalci_name' => 'КЕ',
|
||||
'Class:lnkFunctionalCIToProviderContract/Attribute:functionalci_name' => 'Имя КЕ',
|
||||
'Class:lnkFunctionalCIToProviderContract/Attribute:functionalci_name+' => '',
|
||||
));
|
||||
|
||||
@@ -225,11 +244,11 @@ Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Class:Service/Attribute:name+' => '',
|
||||
'Class:Service/Attribute:org_id' => 'Поставщик',
|
||||
'Class:Service/Attribute:org_id+' => '',
|
||||
'Class:Service/Attribute:organization_name' => 'Поставщик',
|
||||
'Class:Service/Attribute:organization_name' => 'Имя поставщика',
|
||||
'Class:Service/Attribute:organization_name+' => '',
|
||||
'Class:Service/Attribute:servicefamily_id' => 'Пакет услуг',
|
||||
'Class:Service/Attribute:servicefamily_id+' => '',
|
||||
'Class:Service/Attribute:servicefamily_name' => 'Пакет услуг',
|
||||
'Class:Service/Attribute:servicefamily_name' => 'Имя пакета услуг',
|
||||
'Class:Service/Attribute:servicefamily_name+' => '',
|
||||
'Class:Service/Attribute:description' => 'Описание',
|
||||
'Class:Service/Attribute:description+' => '',
|
||||
@@ -240,17 +259,17 @@ Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Class:Service/Attribute:status' => 'Статус',
|
||||
'Class:Service/Attribute:status+' => '',
|
||||
'Class:Service/Attribute:status/Value:implementation' => 'Внедрение',
|
||||
'Class:Service/Attribute:status/Value:implementation+' => 'Внедрение',
|
||||
'Class:Service/Attribute:status/Value:implementation+' => '',
|
||||
'Class:Service/Attribute:status/Value:obsolete' => 'Устаревшее',
|
||||
'Class:Service/Attribute:status/Value:obsolete+' => 'Устаревшее',
|
||||
'Class:Service/Attribute:status/Value:production' => 'Эксплуатация',
|
||||
'Class:Service/Attribute:status/Value:production+' => 'Эксплуатация',
|
||||
'Class:Service/Attribute:status/Value:obsolete+' => '',
|
||||
'Class:Service/Attribute:status/Value:production' => 'Производство',
|
||||
'Class:Service/Attribute:status/Value:production+' => '',
|
||||
'Class:Service/Attribute:customercontracts_list' => 'Договоры с заказчиками',
|
||||
'Class:Service/Attribute:customercontracts_list+' => 'Договоры с заказчиками, по которым предоставляется услуга',
|
||||
'Class:Service/Attribute:customercontracts_list+' => 'Договоры с заказчиками',
|
||||
'Class:Service/Attribute:providercontracts_list' => 'Договоры с поставщиками',
|
||||
'Class:Service/Attribute:providercontracts_list+' => 'Договоры с поставщиками, по которым поддерживается услуга',
|
||||
'Class:Service/Attribute:providercontracts_list+' => 'Договоры с поставщиками',
|
||||
'Class:Service/Attribute:functionalcis_list' => 'Зависимость от КЕ',
|
||||
'Class:Service/Attribute:functionalcis_list+' => 'Конфигурационные единицы, которые используются для предоставления услуги',
|
||||
'Class:Service/Attribute:functionalcis_list+' => 'Зависимость услуги от конфигурационных единиц',
|
||||
'Class:Service/Attribute:servicesubcategories_list' => 'Подкатегории услуги',
|
||||
'Class:Service/Attribute:servicesubcategories_list+' => 'Подкатегории услуги',
|
||||
));
|
||||
@@ -264,11 +283,11 @@ Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Class:lnkDocumentToService+' => '',
|
||||
'Class:lnkDocumentToService/Attribute:service_id' => 'Услуга',
|
||||
'Class:lnkDocumentToService/Attribute:service_id+' => '',
|
||||
'Class:lnkDocumentToService/Attribute:service_name' => 'Услуга',
|
||||
'Class:lnkDocumentToService/Attribute:service_name' => 'Имя услуги',
|
||||
'Class:lnkDocumentToService/Attribute:service_name+' => '',
|
||||
'Class:lnkDocumentToService/Attribute:document_id' => 'Документ',
|
||||
'Class:lnkDocumentToService/Attribute:document_id+' => '',
|
||||
'Class:lnkDocumentToService/Attribute:document_name' => 'Документ',
|
||||
'Class:lnkDocumentToService/Attribute:document_name' => 'Имя документа',
|
||||
'Class:lnkDocumentToService/Attribute:document_name+' => '',
|
||||
));
|
||||
|
||||
@@ -281,11 +300,11 @@ Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Class:lnkContactToService+' => '',
|
||||
'Class:lnkContactToService/Attribute:service_id' => 'Услуга',
|
||||
'Class:lnkContactToService/Attribute:service_id+' => '',
|
||||
'Class:lnkContactToService/Attribute:service_name' => 'Услуга',
|
||||
'Class:lnkContactToService/Attribute:service_name' => 'Имя услуги',
|
||||
'Class:lnkContactToService/Attribute:service_name+' => '',
|
||||
'Class:lnkContactToService/Attribute:contact_id' => 'Контакт',
|
||||
'Class:lnkContactToService/Attribute:contact_id+' => '',
|
||||
'Class:lnkContactToService/Attribute:contact_name' => 'Контакт',
|
||||
'Class:lnkContactToService/Attribute:contact_name' => 'Контактное лицо',
|
||||
'Class:lnkContactToService/Attribute:contact_name+' => '',
|
||||
));
|
||||
|
||||
@@ -307,19 +326,17 @@ Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Class:ServiceSubcategory/Attribute:request_type' => 'Тип запроса',
|
||||
'Class:ServiceSubcategory/Attribute:request_type+' => '',
|
||||
'Class:ServiceSubcategory/Attribute:request_type/Value:incident' => 'Инцидент',
|
||||
'Class:ServiceSubcategory/Attribute:request_type/Value:incident+' => 'Инцидент',
|
||||
'Class:ServiceSubcategory/Attribute:request_type/Value:incident+' => 'incident',
|
||||
'Class:ServiceSubcategory/Attribute:request_type/Value:service_request' => 'Запрос на обслуживание',
|
||||
'Class:ServiceSubcategory/Attribute:request_type/Value:service_request+' => 'Запрос на обслуживание',
|
||||
'Class:ServiceSubcategory/Attribute:request_type/Value:service_request+' => 'service request',
|
||||
'Class:ServiceSubcategory/Attribute:status' => 'Статус',
|
||||
'Class:ServiceSubcategory/Attribute:status+' => '',
|
||||
'Class:ServiceSubcategory/Attribute:status/Value:implementation' => 'Внедрение',
|
||||
'Class:ServiceSubcategory/Attribute:status/Value:implementation+' => 'Внедрение',
|
||||
'Class:ServiceSubcategory/Attribute:status/Value:implementation+' => 'implementation',
|
||||
'Class:ServiceSubcategory/Attribute:status/Value:obsolete' => 'Устаревшее',
|
||||
'Class:ServiceSubcategory/Attribute:status/Value:obsolete+' => 'Устаревшее',
|
||||
'Class:ServiceSubcategory/Attribute:status/Value:production' => 'Эксплуатация',
|
||||
'Class:ServiceSubcategory/Attribute:status/Value:production+' => 'Эксплуатация',
|
||||
'Class:ServiceSubcategory/Attribute:service_provider' => 'Поставщик',
|
||||
'Class:ServiceSubcategory/Attribute:service_org_id' => 'Поставщик',
|
||||
'Class:ServiceSubcategory/Attribute:status/Value:obsolete+' => 'obsolete',
|
||||
'Class:ServiceSubcategory/Attribute:status/Value:production' => 'Производство',
|
||||
'Class:ServiceSubcategory/Attribute:status/Value:production+' => 'production',
|
||||
));
|
||||
|
||||
//
|
||||
@@ -335,12 +352,12 @@ Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Class:SLA/Attribute:description+' => '',
|
||||
'Class:SLA/Attribute:org_id' => 'Поставщик',
|
||||
'Class:SLA/Attribute:org_id+' => '',
|
||||
'Class:SLA/Attribute:organization_name' => 'Поставщик',
|
||||
'Class:SLA/Attribute:organization_name+' => '',
|
||||
'Class:SLA/Attribute:organization_name' => 'Имя поставщика',
|
||||
'Class:SLA/Attribute:organization_name+' => 'Common name',
|
||||
'Class:SLA/Attribute:slts_list' => 'SLT',
|
||||
'Class:SLA/Attribute:slts_list+' => 'Целевые показатели уровня услуги (Service Level Target)',
|
||||
'Class:SLA/Attribute:slts_list+' => 'Целевой показатель уровня услуги (Service Level Target)',
|
||||
'Class:SLA/Attribute:customercontracts_list' => 'Договоры с заказчиками',
|
||||
'Class:SLA/Attribute:customercontracts_list+' => 'Договоры с заказчиками, в которых используется SLA',
|
||||
'Class:SLA/Attribute:customercontracts_list+' => 'Договоры с заказчиками',
|
||||
));
|
||||
|
||||
//
|
||||
@@ -355,33 +372,33 @@ Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Class:SLT/Attribute:priority' => 'Приоритет',
|
||||
'Class:SLT/Attribute:priority+' => '',
|
||||
'Class:SLT/Attribute:priority/Value:1' => 'Критический',
|
||||
'Class:SLT/Attribute:priority/Value:1+' => 'Критический',
|
||||
'Class:SLT/Attribute:priority/Value:1+' => 'critical',
|
||||
'Class:SLT/Attribute:priority/Value:2' => 'Высокий',
|
||||
'Class:SLT/Attribute:priority/Value:2+' => 'Высокий',
|
||||
'Class:SLT/Attribute:priority/Value:2+' => 'high',
|
||||
'Class:SLT/Attribute:priority/Value:3' => 'Средний',
|
||||
'Class:SLT/Attribute:priority/Value:3+' => 'Средний',
|
||||
'Class:SLT/Attribute:priority/Value:3+' => 'medium',
|
||||
'Class:SLT/Attribute:priority/Value:4' => 'Низкий',
|
||||
'Class:SLT/Attribute:priority/Value:4+' => 'Низкий',
|
||||
'Class:SLT/Attribute:priority/Value:4+' => 'low',
|
||||
'Class:SLT/Attribute:request_type' => 'Тип запроса',
|
||||
'Class:SLT/Attribute:request_type+' => '',
|
||||
'Class:SLT/Attribute:request_type/Value:incident' => 'Инцидент',
|
||||
'Class:SLT/Attribute:request_type/Value:incident+' => 'Инцидент',
|
||||
'Class:SLT/Attribute:request_type/Value:service_request' => 'Запрос на обслуживание',
|
||||
'Class:SLT/Attribute:request_type/Value:service_request+' => 'Запрос на обслуживание',
|
||||
'Class:SLT/Attribute:request_type/Value:incident+' => 'incident',
|
||||
'Class:SLT/Attribute:request_type/Value:service_request' => 'service request',
|
||||
'Class:SLT/Attribute:request_type/Value:service_request+' => 'service request',
|
||||
'Class:SLT/Attribute:metric' => 'Метрика',
|
||||
'Class:SLT/Attribute:metric+' => '',
|
||||
'Class:SLT/Attribute:metric/Value:tto' => 'TTO',
|
||||
'Class:SLT/Attribute:metric/Value:tto+' => 'Time-To-Own - время до назначения агента (принятия в работу)',
|
||||
'Class:SLT/Attribute:metric/Value:tto+' => 'TTO',
|
||||
'Class:SLT/Attribute:metric/Value:ttr' => 'TTR',
|
||||
'Class:SLT/Attribute:metric/Value:ttr+' => 'Time-To-Resolve - время до решения',
|
||||
'Class:SLT/Attribute:metric/Value:ttr+' => 'TTR',
|
||||
'Class:SLT/Attribute:value' => 'Значение',
|
||||
'Class:SLT/Attribute:value+' => '',
|
||||
'Class:SLT/Attribute:unit' => 'Единицы',
|
||||
'Class:SLT/Attribute:unit+' => '',
|
||||
'Class:SLT/Attribute:unit/Value:hours' => 'Часы',
|
||||
'Class:SLT/Attribute:unit/Value:hours+' => 'Часы',
|
||||
'Class:SLT/Attribute:unit/Value:hours+' => 'часов',
|
||||
'Class:SLT/Attribute:unit/Value:minutes' => 'Минуты',
|
||||
'Class:SLT/Attribute:unit/Value:minutes+' => 'Минуты',
|
||||
'Class:SLT/Attribute:unit/Value:minutes+' => 'минут',
|
||||
));
|
||||
|
||||
//
|
||||
@@ -393,11 +410,11 @@ Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Class:lnkSLAToSLT+' => '',
|
||||
'Class:lnkSLAToSLT/Attribute:sla_id' => 'SLA',
|
||||
'Class:lnkSLAToSLT/Attribute:sla_id+' => '',
|
||||
'Class:lnkSLAToSLT/Attribute:sla_name' => 'SLA',
|
||||
'Class:lnkSLAToSLT/Attribute:sla_name' => 'Название SLA',
|
||||
'Class:lnkSLAToSLT/Attribute:sla_name+' => '',
|
||||
'Class:lnkSLAToSLT/Attribute:slt_id' => 'SLT',
|
||||
'Class:lnkSLAToSLT/Attribute:slt_id+' => '',
|
||||
'Class:lnkSLAToSLT/Attribute:slt_name' => 'SLT',
|
||||
'Class:lnkSLAToSLT/Attribute:slt_name' => 'Название SLT',
|
||||
'Class:lnkSLAToSLT/Attribute:slt_name+' => '',
|
||||
));
|
||||
|
||||
@@ -410,15 +427,15 @@ Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Class:lnkCustomerContractToService+' => '',
|
||||
'Class:lnkCustomerContractToService/Attribute:customercontract_id' => 'Договор с заказчиком',
|
||||
'Class:lnkCustomerContractToService/Attribute:customercontract_id+' => '',
|
||||
'Class:lnkCustomerContractToService/Attribute:customercontract_name' => 'Договор с заказчиком',
|
||||
'Class:lnkCustomerContractToService/Attribute:customercontract_name' => 'Контактное лицо клиента',
|
||||
'Class:lnkCustomerContractToService/Attribute:customercontract_name+' => '',
|
||||
'Class:lnkCustomerContractToService/Attribute:service_id' => 'Услуга',
|
||||
'Class:lnkCustomerContractToService/Attribute:service_id+' => '',
|
||||
'Class:lnkCustomerContractToService/Attribute:service_name' => 'Услуга',
|
||||
'Class:lnkCustomerContractToService/Attribute:service_name' => 'Имя услуги',
|
||||
'Class:lnkCustomerContractToService/Attribute:service_name+' => '',
|
||||
'Class:lnkCustomerContractToService/Attribute:sla_id' => 'SLA',
|
||||
'Class:lnkCustomerContractToService/Attribute:sla_id+' => '',
|
||||
'Class:lnkCustomerContractToService/Attribute:sla_name' => 'SLA',
|
||||
'Class:lnkCustomerContractToService/Attribute:sla_name' => 'Название SLA',
|
||||
'Class:lnkCustomerContractToService/Attribute:sla_name+' => '',
|
||||
));
|
||||
|
||||
@@ -431,11 +448,11 @@ Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Class:lnkProviderContractToService+' => '',
|
||||
'Class:lnkProviderContractToService/Attribute:service_id' => 'Услуга',
|
||||
'Class:lnkProviderContractToService/Attribute:service_id+' => '',
|
||||
'Class:lnkProviderContractToService/Attribute:service_name' => 'Услуга',
|
||||
'Class:lnkProviderContractToService/Attribute:service_name' => 'Имя услуги',
|
||||
'Class:lnkProviderContractToService/Attribute:service_name+' => '',
|
||||
'Class:lnkProviderContractToService/Attribute:providercontract_id' => 'Договор с поставщиком',
|
||||
'Class:lnkProviderContractToService/Attribute:providercontract_id+' => '',
|
||||
'Class:lnkProviderContractToService/Attribute:providercontract_name' => 'Договор с поставщиком',
|
||||
'Class:lnkProviderContractToService/Attribute:providercontract_name' => 'Имя договора поставщика',
|
||||
'Class:lnkProviderContractToService/Attribute:providercontract_name+' => '',
|
||||
));
|
||||
|
||||
@@ -448,11 +465,11 @@ Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Class:lnkFunctionalCIToService+' => '',
|
||||
'Class:lnkFunctionalCIToService/Attribute:service_id' => 'Услуга',
|
||||
'Class:lnkFunctionalCIToService/Attribute:service_id+' => '',
|
||||
'Class:lnkFunctionalCIToService/Attribute:service_name' => 'Услуга',
|
||||
'Class:lnkFunctionalCIToService/Attribute:service_name' => 'Имя услуги',
|
||||
'Class:lnkFunctionalCIToService/Attribute:service_name+' => '',
|
||||
'Class:lnkFunctionalCIToService/Attribute:functionalci_id' => 'КЕ',
|
||||
'Class:lnkFunctionalCIToService/Attribute:functionalci_id+' => '',
|
||||
'Class:lnkFunctionalCIToService/Attribute:functionalci_name' => 'КЕ',
|
||||
'Class:lnkFunctionalCIToService/Attribute:functionalci_name' => 'Имя КЕ',
|
||||
'Class:lnkFunctionalCIToService/Attribute:functionalci_name+' => '',
|
||||
));
|
||||
|
||||
@@ -467,14 +484,14 @@ Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Class:DeliveryModel/Attribute:name+' => '',
|
||||
'Class:DeliveryModel/Attribute:org_id' => 'Организация',
|
||||
'Class:DeliveryModel/Attribute:org_id+' => '',
|
||||
'Class:DeliveryModel/Attribute:organization_name' => 'Организация',
|
||||
'Class:DeliveryModel/Attribute:organization_name+' => '',
|
||||
'Class:DeliveryModel/Attribute:organization_name' => 'Название организации',
|
||||
'Class:DeliveryModel/Attribute:organization_name+' => 'Common name',
|
||||
'Class:DeliveryModel/Attribute:description' => 'Описание',
|
||||
'Class:DeliveryModel/Attribute:description+' => '',
|
||||
'Class:DeliveryModel/Attribute:contacts_list' => 'Контакты',
|
||||
'Class:DeliveryModel/Attribute:contacts_list+' => 'Контакты (команды и персоны), которые участвуют в предоставлении услуг по этой модели',
|
||||
'Class:DeliveryModel/Attribute:contacts_list+' => 'Связанные контакты',
|
||||
'Class:DeliveryModel/Attribute:customers_list' => 'Заказчики',
|
||||
'Class:DeliveryModel/Attribute:customers_list+' => 'Заказчики, которым предоставляются услуги по этой модели',
|
||||
'Class:DeliveryModel/Attribute:customers_list+' => 'Связанные заказчик',
|
||||
));
|
||||
|
||||
//
|
||||
@@ -486,14 +503,17 @@ Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Class:lnkDeliveryModelToContact+' => '',
|
||||
'Class:lnkDeliveryModelToContact/Attribute:deliverymodel_id' => 'Модель предоставления услуг',
|
||||
'Class:lnkDeliveryModelToContact/Attribute:deliverymodel_id+' => '',
|
||||
'Class:lnkDeliveryModelToContact/Attribute:deliverymodel_name' => 'Модель предоставления услуг',
|
||||
'Class:lnkDeliveryModelToContact/Attribute:deliverymodel_name' => 'Название модели предоставления услуг',
|
||||
'Class:lnkDeliveryModelToContact/Attribute:deliverymodel_name+' => '',
|
||||
'Class:lnkDeliveryModelToContact/Attribute:contact_id' => 'Контакт',
|
||||
'Class:lnkDeliveryModelToContact/Attribute:contact_id+' => '',
|
||||
'Class:lnkDeliveryModelToContact/Attribute:contact_name' => 'Контакт',
|
||||
'Class:lnkDeliveryModelToContact/Attribute:contact_name' => 'Контактное лицо',
|
||||
'Class:lnkDeliveryModelToContact/Attribute:contact_name+' => '',
|
||||
'Class:lnkDeliveryModelToContact/Attribute:role_id' => 'Роль',
|
||||
'Class:lnkDeliveryModelToContact/Attribute:role_id+' => '',
|
||||
'Class:lnkDeliveryModelToContact/Attribute:role_name' => 'Роль',
|
||||
'Class:lnkDeliveryModelToContact/Attribute:role_name' => 'Должность',
|
||||
'Class:lnkDeliveryModelToContact/Attribute:role_name+' => '',
|
||||
));
|
||||
));
|
||||
|
||||
|
||||
?>
|
||||
|
||||
@@ -698,7 +698,7 @@
|
||||
<code><![CDATA[ public function UpdateParentTicketLog()
|
||||
{
|
||||
$oLog = $this->Get('log');
|
||||
$sLog = $oLog->GetModifiedEntry('html');
|
||||
$sLog = $oLog->GetModifiedEntry();
|
||||
if ($sLog != '')
|
||||
{
|
||||
$oTicket = MetaModel::GetObject('Ticket', $this->Get('ticket_id'), false);
|
||||
@@ -998,7 +998,7 @@
|
||||
<default>fa fa-user fa-2x</default>
|
||||
</decoration_class>
|
||||
<form>
|
||||
<!-- Optionnal tag to list the fields. If empty only fields from <twig> tag will be displayed, if ommited fields from zlist details will. -->
|
||||
<!-- Optionnal tag to list the fields -->
|
||||
<fields />
|
||||
<!-- Optionnal tag to specify the form layout. Fields that are not positionned in the layout will be placed at the end of the form -->
|
||||
<twig>
|
||||
@@ -1052,7 +1052,7 @@
|
||||
<!-- Description text from attribute of above class [from the OQL] -->
|
||||
<tooltip_att>description</tooltip_att>
|
||||
<!-- Title of the level, will be display in lists and others browse modes -->
|
||||
<title>Class:Service</title>
|
||||
<title>Service</title>
|
||||
<!-- Optional tag to add attributes to the table by their code, can be specified for each level -->
|
||||
<!-- <fields /> -->
|
||||
<!-- Can be empty on intermediate levels, default is drilldown -->
|
||||
@@ -1066,7 +1066,7 @@
|
||||
<parent_att>service_id</parent_att>
|
||||
<name_att/>
|
||||
<tooltip_att>description</tooltip_att>
|
||||
<title>Class:ServiceSubcategory</title>
|
||||
<title>Sous-Service</title>
|
||||
<actions>
|
||||
<action id="view" xsi:type="view"/>
|
||||
<action id="create_from_this" xsi:type="create_from_this">
|
||||
@@ -1130,9 +1130,9 @@
|
||||
</fields>
|
||||
<!-- Optional tag to add attributes to the table by their code -->
|
||||
<grouping>
|
||||
<!-- Mandatory -->
|
||||
<!-- Optionnal -->
|
||||
<tabs>
|
||||
<!-- Mandatory. Grouping by tabs -->
|
||||
<!-- Optionnal. Grouping by tabs -->
|
||||
<!--<attribute>operational_status</attribute>-->
|
||||
<!-- attribute xor groups tag -->
|
||||
<groups>
|
||||
@@ -1145,7 +1145,7 @@
|
||||
<group id="resolved">
|
||||
<rank>2</rank>
|
||||
<title>Brick:Portal:OngoingRequests:Tab:Resolved</title>
|
||||
<condition><![CDATA[SELECT Ticket AS T WHERE operational_status = 'resolved']]></condition>
|
||||
<condition><![CDATA[SELECT Ticket AS T WHERE org_id = :current_contact->org_id AND operational_status = 'resolved']]></condition>
|
||||
</group>
|
||||
</groups>
|
||||
</tabs>
|
||||
@@ -1169,7 +1169,7 @@
|
||||
<decoration_class>
|
||||
<default>fc fc-closed-request fc-2x</default>
|
||||
</decoration_class>
|
||||
<oql><![CDATA[SELECT Ticket WHERE org_id = :current_contact->org_id AND caller_id = :current_contact_id AND operational_status = 'closed']]></oql>
|
||||
<oql><![CDATA[SELECT UserRequest WHERE org_id = :current_contact->org_id AND caller_id = :current_contact_id AND status = 'closed']]></oql>
|
||||
<!-- Can be either a class tag with the class name or an oql tag with the query -->
|
||||
<!-- <class>Ticket</class> -->
|
||||
<fields>
|
||||
@@ -1181,18 +1181,6 @@
|
||||
<field id="priority"/>
|
||||
<field id="caller_id"/>
|
||||
</fields>
|
||||
<grouping>
|
||||
<tabs>
|
||||
<groups>
|
||||
<group id="all">
|
||||
<rank>1</rank>
|
||||
<title>Brick:Portal:ClosedRequests:Title</title>
|
||||
<condition><![CDATA[SELECT Ticket]]></condition>
|
||||
</group>
|
||||
</groups>
|
||||
</tabs>
|
||||
<!-- Implicit grouping on y axis by finalclass -->
|
||||
</grouping>
|
||||
<data_loading>auto</data_loading>
|
||||
</brick>
|
||||
</bricks>
|
||||
@@ -1321,21 +1309,6 @@
|
||||
<mode id="view"/>
|
||||
</modes>
|
||||
</form>
|
||||
<form id="ticket-apply-stimulus">
|
||||
<class>Ticket</class>
|
||||
<fields />
|
||||
<twig>
|
||||
<div>
|
||||
<div class="form_field" data-field-id="team_id" data-field-flags="read_only">
|
||||
</div>
|
||||
<div class="form_field" data-field-id="agent_id" data-field-flags="read_only">
|
||||
</div>
|
||||
</div>
|
||||
</twig>
|
||||
<modes>
|
||||
<mode id="apply_stimulus"/>
|
||||
</modes>
|
||||
</form>
|
||||
<form id="service-view">
|
||||
<class>Service</class>
|
||||
<fields></fields>
|
||||
@@ -1386,13 +1359,6 @@
|
||||
</scope>
|
||||
</scopes>
|
||||
</class>
|
||||
<class id="Location">
|
||||
<scopes>
|
||||
<scope id="all">
|
||||
<oql_view><![CDATA[SELECT Location WHERE org_id = :current_contact->org_id]]></oql_view>
|
||||
</scope>
|
||||
</scopes>
|
||||
</class>
|
||||
<class id="Contact">
|
||||
<scopes>
|
||||
<scope id="all">
|
||||
@@ -1425,7 +1391,6 @@
|
||||
<scopes>
|
||||
<scope id="all">
|
||||
<oql_view><![CDATA[SELECT ServiceFamily AS sf JOIN Service AS s ON s.servicefamily_id = sf.id JOIN lnkCustomerContractToService AS l1 ON l1.service_id=s.id JOIN CustomerContract AS cc ON l1.customercontract_id=cc.id WHERE cc.org_id = :current_contact->org_id]]></oql_view>
|
||||
<ignore_silos>true</ignore_silos>
|
||||
</scope>
|
||||
</scopes>
|
||||
</class>
|
||||
@@ -1433,7 +1398,6 @@
|
||||
<scopes>
|
||||
<scope id="all">
|
||||
<oql_view><![CDATA[SELECT Service AS s JOIN lnkCustomerContractToService AS l1 ON l1.service_id=s.id JOIN CustomerContract AS cc ON l1.customercontract_id=cc.id WHERE cc.org_id = :current_contact->org_id AND s.status != 'obsolete']]></oql_view>
|
||||
<ignore_silos>true</ignore_silos>
|
||||
</scope>
|
||||
</scopes>
|
||||
</class>
|
||||
@@ -1441,7 +1405,6 @@
|
||||
<scopes>
|
||||
<scope id="all">
|
||||
<oql_view><![CDATA[SELECT ServiceSubcategory AS ssc JOIN Service AS s ON ssc.service_id=s.id JOIN lnkCustomerContractToService AS l1 ON l1.service_id=s.id JOIN CustomerContract AS cc ON l1.customercontract_id=cc.id WHERE cc.org_id = :current_contact->org_id AND ssc.status != 'obsolete']]></oql_view>
|
||||
<ignore_silos>true</ignore_silos>
|
||||
</scope>
|
||||
</scopes>
|
||||
</class>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user