N°3569 - Migrate backoffice pages to new UIBlock system : DB Tools

This commit is contained in:
Eric
2021-03-23 18:30:40 +01:00
parent c7425558e7
commit 699944711b
6 changed files with 275 additions and 217 deletions

View File

@@ -4,8 +4,6 @@
*/
.ibo-toolbar--button {
.ibo-toolbar-spacer {
flex-grow: 1;
}
.ibo-toolbar-spacer {
flex-grow: 1;
}

View File

@@ -17,6 +17,19 @@
* You should have received a copy of the GNU Affero General Public License
*/
use Combodo\iTop\Application\UI\Base\Component\Alert\AlertUIBlockFactory;
use Combodo\iTop\Application\UI\Base\Component\Button\ButtonUIBlockFactory;
use Combodo\iTop\Application\UI\Base\Component\CollapsibleSection\CollapsibleSectionUIBlockFactory;
use Combodo\iTop\Application\UI\Base\Component\DataTable\DataTableUIBlockFactory;
use Combodo\iTop\Application\UI\Base\Component\FieldSet\FieldSetUIBlockFactory;
use Combodo\iTop\Application\UI\Base\Component\Form\FormUIBlockFactory;
use Combodo\iTop\Application\UI\Base\Component\Html\Html;
use Combodo\iTop\Application\UI\Base\Component\Input\InputUIBlockFactory;
use Combodo\iTop\Application\UI\Base\Component\Panel\PanelUIBlockFactory;
use Combodo\iTop\Application\UI\Base\Component\Title\TitleUIBlockFactory;
use Combodo\iTop\Application\UI\Base\Component\Toolbar\Separator\ToolbarSeparatorUIBlockFactory;
use Combodo\iTop\Application\UI\Base\Component\Toolbar\ToolbarUIBlockFactory;
use Combodo\iTop\Application\UI\Base\Layout\UIContentBlockUIBlockFactory;
use Combodo\iTop\DBTools\Service\DBAnalyzerUtils;
@include_once('../../approot.inc.php');
@@ -38,157 +51,110 @@ const MAX_RESULTS = 10;
function DisplayDBInconsistencies(iTopWebPage &$oP, ApplicationContext &$oAppContext)
{
$iShowId = intval(utils::ReadParam('show_id', '0'));
$sErrorLabelSelection = utils::ReadParam('error_selection', '');
$sClassSelection = utils::ReadParam('class_selection', '');
if (!empty($sClassSelection))
{
if (!empty($sClassSelection)) {
$aClassSelection = explode(",", $sClassSelection);
}
else
{
} else {
$aClassSelection = array();
}
$sClassSelection = utils::ReadParam('class_selection', '');
$oP->SetCurrentTab('DBTools:Inconsistencies');
$bRunAnalysis = intval(utils::ReadParam('run_analysis', '0'));
if ($bRunAnalysis)
{
if ($bRunAnalysis) {
$oDBAnalyzer = new DatabaseAnalyzer(0);
$aResults = $oDBAnalyzer->CheckIntegrity($aClassSelection);
if (empty($aResults))
{
$oP->p('<div class="header_message message_ok">'.Dict::S('DBTools:NoError').'</div>');
if (empty($aResults)) {
$oAlert = AlertUIBlockFactory::MakeForSuccess(Dict::S('DBTools:NoError'));
$oP->AddUiBlock($oAlert);
}
}
$oP->add('<div style="padding: 15px; background: #ddd;">');
$oP->add("<form>");
$oP->add('<table style="border=0;">');
$oPanel = FieldSetUIBlockFactory::MakeStandard(Dict::S('DBTools:SelectAnalysisType'));
$oP->AddUiBlock($oPanel);
$oForm = FormUIBlockFactory::MakeStandard();
$oPanel->AddSubBlock($oForm);
$oP->add("<tr><td>");
$sChecked = ($iShowId == 0) ? 'checked' : '';
$oP->add("<label><input type=\"radio\" $sChecked name=\"show_id\" value=\"0\">".Dict::S('DBTools:HideIds').'</label>');
$oP->add("</td><td>");
$sChecked = ($iShowId == 1) ? 'checked' : '';
$oP->add("<label><input type=\"radio\" $sChecked name=\"show_id\" value=\"1\">".Dict::S('DBTools:ShowIds').'</label>');
$oP->add("</td><td>");
$sChecked = ($iShowId == 3) ? 'checked' : '';
$oP->add("<label><input type=\"radio\" $sChecked name=\"show_id\" value=\"3\">".Dict::S('DBTools:ShowReport').'</label>');
$oP->add("</td></tr>\n");
$oToolbar = ToolbarUIBlockFactory::MakeStandard();
$oForm->AddSubBlock($oToolbar);
$oP->add("</table><br>\n");
$oInput = InputUIBlockFactory::MakeForInputWithLabel(Dict::S('DBTools:HideIds'), 'show_id');
$oToolbar->AddSubBlock($oInput);
$oInput->GetInput()->SetType('radio');
$oInput->GetInput()->SetValue('0');
$oInput->GetInput()->SetIsChecked($iShowId == 0);
$oInput->GetInput()->AddCSSClasses(['ibo-input-checkbox', 'ibo-input--label-left']);
$oP->add("<input type=\"submit\" value=\"".Dict::S('DBTools:Analyze')."\">\n");
$oP->add('<input type="hidden" name="class_selection" value="'.$sClassSelection.'"/>');
$oP->add('<input type="hidden" name="error_selection" value="'.$sErrorLabelSelection.'"/>');
$oP->add('<input type="hidden" name="run_analysis" value="1"/>');
$oP->add('<input type="hidden" name="exec_module" value="combodo-db-tools"/>');
$oP->add('<input type="hidden" name="exec_page" value="dbtools.php"/>');
$oP->add($oAppContext->GetForForm());
$oP->add("</form>\n");
$oP->add('</div>');
$oToolbar->AddSubBlock(ToolbarSeparatorUIBlockFactory::MakeVertical());
$oInput = InputUIBlockFactory::MakeForInputWithLabel(Dict::S('DBTools:ShowIds'), 'show_id');
$oToolbar->AddSubBlock($oInput);
$oInput->GetInput()->SetType('radio');
$oInput->GetInput()->SetValue('1');
$oInput->GetInput()->SetIsChecked($iShowId == 1);
$oInput->GetInput()->AddCSSClasses(['ibo-input-checkbox', 'ibo-input--label-left']);
$oToolbar->AddSubBlock(ToolbarSeparatorUIBlockFactory::MakeVertical());
$oInput = InputUIBlockFactory::MakeForInputWithLabel(Dict::S('DBTools:ShowReport'), 'show_id');
$oToolbar->AddSubBlock($oInput);
$oInput->GetInput()->SetType('radio');
$oInput->GetInput()->SetValue('3');
$oInput->GetInput()->SetIsChecked($iShowId == 3);
$oInput->GetInput()->AddCSSClasses(['ibo-input-checkbox', 'ibo-input--label-left']);
$oButton = ButtonUIBlockFactory::MakeForPrimaryAction(Dict::S('DBTools:Analyze'), null, null, true);
// TODO 3.0 Spacing ?
$oButton->AddCSSClasses(['mt-5', 'mb-5']);
$oForm->AddSubBlock($oButton);
$oInput = InputUIBlockFactory::MakeForHidden('class_selection', $sClassSelection);
$oForm->AddSubBlock($oInput);
$oInput = InputUIBlockFactory::MakeForHidden('run_analysis', 1);
$oForm->AddSubBlock($oInput);
$oInput = InputUIBlockFactory::MakeForHidden('exec_module', 'combodo-db-tools');
$oForm->AddSubBlock($oInput);
$oInput = InputUIBlockFactory::MakeForHidden('exec_page', 'dbtools.php');
$oForm->AddSubBlock($oInput);
$oForm->AddSubBlock($oAppContext->GetForFormBlock());
if (!empty($sErrorLabelSelection) || !empty($sClassSelection))
{
$oP->add("<br>");
$oP->add("<form>");
$oP->add('<input type="hidden" name="show_id" value="0"/>');
$oP->add('<input type="hidden" name="class_selection" value=""/>');
$oP->add('<input type="hidden" name="error_selection" value=""/>');
$oP->add('<input type="hidden" name="exec_module" value="combodo-db-tools"/>');
$oP->add('<input type="hidden" name="exec_page" value="dbtools.php"/>');
$oP->add("<input type=\"submit\" value=\"".Dict::S('DBTools:ShowAll')."\">\n");
$oP->add("</form>\n");
if (!empty($sErrorLabelSelection) || !empty($sClassSelection)) {
$oForm = FormUIBlockFactory::MakeStandard();
$oP->AddUiBlock($oForm);
$oInput = InputUIBlockFactory::MakeForHidden('show_id', '0');
$oForm->AddSubBlock($oInput);
$oInput = InputUIBlockFactory::MakeForHidden('class_selection', '');
$oForm->AddSubBlock($oInput);
$oInput = InputUIBlockFactory::MakeForHidden('error_selection', '');
$oForm->AddSubBlock($oInput);
$oInput = InputUIBlockFactory::MakeForHidden('exec_module', 'combodo-db-tools');
$oForm->AddSubBlock($oInput);
$oInput = InputUIBlockFactory::MakeForHidden('exec_page', 'dbtools.php');
$oForm->AddSubBlock($oInput);
$oButton = ButtonUIBlockFactory::MakeForPrimaryAction(Dict::S('DBTools:ShowAll'), null, null, true);
$oForm->AddSubBlock($oButton);
}
if (!empty($aResults))
{
if ($iShowId == 3)
{
if (!empty($aResults)) {
if ($iShowId == 3) {
// Report
DisplayInconsistenciesReport($aResults);
}
$oP->p(Dict::S('DBTools:ErrorsFound'));
$oPanel = PanelUIBlockFactory::MakeForWarning(Dict::S('DBTools:ErrorsFound'));
$oPanel->AddCSSClass('ibo-datatable-panel');
$oP->AddUiBlock($oPanel);
$oP->add('<table class="listResults"><tr><th>'.Dict::S('DBTools:Class').'</th><th>'.Dict::S('DBTools:Count').'</th><th>'.Dict::S('DBTools:Error').'</th></tr>');
$bTable = true;
foreach($aResults as $sClass => $aErrorList)
{
foreach($aErrorList as $sErrorLabel => $aError)
{
if (!empty($sErrorLabelSelection) && ($sErrorLabel != $sErrorLabelSelection))
{
continue;
}
if (!$bTable)
{
$oP->add('<br>');
$oP->add('<table class="listResults"><tr><th></th><th>Class</th><th>Count</th><th>Error</th></tr>');
$bTable = true;
}
$oP->add('<tr>');
$oP->add('<td>'.MetaModel::GetName($sClass).' ('.$sClass.')</td>');
$iCount = $aError['count'];
$oP->add('<td>'.$iCount.'</td>');
$oP->add('<td>'.$sErrorLabel.'</td>');
$oP->add('</tr>');
if ($iShowId > 0)
{
$oP->add('</table>');
$bTable = false;
$oP->p(Dict::S('DBTools:SQLquery'));
$sQuery = $aError['query'];
$oP->add('<div style="padding: 15px; background: #f1f1f1;">');
$oP->add('<code>'.$sQuery.'</code>');
$oP->add('</div>');
if (isset($aError['fixit']))
{
$oP->p(Dict::S('DBTools:FixitSQLquery'));
$aQueries = $aError['fixit'];
$oP->add('<div style="padding: 15px; background: #f1f1f1;">');
foreach($aQueries as $sFixQuery)
{
$oP->add('<pre>'.$sFixQuery.'</pre>');
}
$oP->add('<br></div>');
}
$oP->p(Dict::S('DBTools:SQLresult'));
$sQueryResult = '';
$iCount = count($aError['res']);
$iMaxCount = MAX_RESULTS;
foreach($aError['res'] as $aRes)
{
$iMaxCount--;
if ($iMaxCount < 0)
{
$sQueryResult .= 'Displayed '.MAX_RESULTS."/$iCount results.<br>";
break;
}
foreach($aRes as $sKey => $sValue)
{
$sQueryResult .= "'$sKey'='$sValue'&nbsp;";
}
$sQueryResult .= '<br>';
}
$oP->add('<div style="padding: 15px; background: #f1f1f1;">');
$oP->add('<code>'.$sQueryResult.'</code>');
$oP->add('</div>');
}
}
if ($iShowId == 0) {
// Error List
$oPanel->AddSubBlock(DisplayErrorList($aResults));
} else {
// Detail List
$oPanel->AddSubBlock(DisplayErrorDetails($aResults));
}
$oP->add('</table>');
}
return $oP;
}
@@ -221,6 +187,84 @@ function DisplayInconsistenciesReport($aResults)
exit(0);
}
/**
* @param $aResults
*
* @return \Combodo\iTop\Application\UI\Base\UIBlock
* @throws \CoreException
* @throws \DictExceptionMissingString
*/
function DisplayErrorList($aResults)
{
$aColumns = [
'class' => ['label' => Dict::S('DBTools:Class')],
'count' => ['label' => Dict::S('DBTools:Count')],
'error' => ['label' => Dict::S('DBTools:Error')],
];
$aRows = [];
foreach ($aResults as $sClass => $aErrorList) {
foreach ($aErrorList as $sErrorLabel => $aError) {
$aRows[] = [
'class' => MetaModel::GetName($sClass).' ('.$sClass.')',
'count' => $aError['count'],
'error' => $sErrorLabel,
];
}
}
return DataTableUIBlockFactory::MakeForForm('', $aColumns, $aRows);
}
function DisplayErrorDetails($aResults)
{
$oBlock = UIContentBlockUIBlockFactory::MakeStandard();
foreach ($aResults as $sClass => $aErrorList) {
foreach ($aErrorList as $sErrorLabel => $aError) {
$sErrorTitle = Dict::Format('DBTools:DetailedErrorTitle', MetaModel::GetName($sClass).' ('.$sClass.')', $aError['count'], $sErrorLabel);
$oCollapsible = CollapsibleSectionUIBlockFactory::MakeStandard($sErrorTitle);
$oBlock->AddSubBlock($oCollapsible);
$oFieldSet = FieldSetUIBlockFactory::MakeStandard(Dict::S('DBTools:SQLquery'));
$oCollapsible->AddSubBlock($oFieldSet);
$oFieldSet->AddSubBlock(new Html("<pre>{$aError['query']}</pre>"));
if (isset($aError['fixit'])) {
$oFieldSet = FieldSetUIBlockFactory::MakeStandard(Dict::S('DBTools:FixitSQLquery'));
$oCollapsible->AddSubBlock($oFieldSet);
$aQueries = $aError['fixit'];
foreach ($aQueries as $sFixQuery) {
$oFieldSet->AddSubBlock(new Html("<pre>{$sFixQuery}</pre>"));
}
}
$oFieldSet = FieldSetUIBlockFactory::MakeStandard(Dict::S('DBTools:SQLresult'));
$oCollapsible->AddSubBlock($oFieldSet);
$sQueryResult = '';
$iCount = count($aError['res']);
$iMaxCount = MAX_RESULTS;
foreach ($aError['res'] as $aRes) {
$iMaxCount--;
if ($iMaxCount < 0) {
$sQueryResult .= 'Displayed '.MAX_RESULTS."/$iCount results.<br>";
break;
}
foreach ($aRes as $sKey => $sValue) {
$sQueryResult .= "'$sKey'='$sValue'&nbsp;";
}
$sQueryResult .= '<br>';
}
$oFieldSet->AddSubBlock(new Html("<pre>{$sQueryResult}</pre>"));
}
}
return $oBlock;
}
/**
* @param iTopWebPage $oP
* @param ApplicationContext $oAppContext
@@ -246,29 +290,37 @@ function DisplayLostAttachments(iTopWebPage &$oP, ApplicationContext &$oAppConte
// Build HTML
$oP->SetCurrentTab('DBTools:LostAttachments');
$oP->add('<div class="db-tools-tab-content">');
$oP->add('<div class="dbt-lostattachments">');
$oLostAttachmentsBlock = UIContentBlockUIBlockFactory::MakeStandard(null, ['ibo-dbt-lostattachments']);
$oP->AddUiBlock($oLostAttachmentsBlock);
$oP->add('<div class="header_message message_info">'.Dict::S('DBTools:LostAttachments:Disclaimer').'</div>');
$oP->add('<div class="dbt-steps">');
$oP->add('<form>');
$oP->add('<input type="hidden" name="exec_module" value="combodo-db-tools"/>');
$oP->add('<input type="hidden" name="exec_page" value="dbtools.php"/>');
$oForm = FormUIBlockFactory::MakeStandard();
$oLostAttachmentsBlock->AddSubBlock($oForm);
$oInput = InputUIBlockFactory::MakeForHidden('exec_module', 'combodo-db-tools');
$oForm->AddSubBlock($oInput);
$oInput = InputUIBlockFactory::MakeForHidden('exec_page', 'dbtools.php');
$oForm->AddSubBlock($oInput);
// Step 1: Analyze DB
$oP->add('<div class="dbt-step"><p class="dbt-step-description"><span class="dbt-step-number">1.</span><span>'.Dict::S('DBTools:LostAttachments:Step:Analyze').'</span></p><button type="submit" name="step_name" value="analyze">'.Dict::S('DBTools:LostAttachments:Button:Analyze') .'</button></div>');
if (!$bDoAnalyze) {
$oAlert = AlertUIBlockFactory::MakeForInformation(Dict::S('DBTools:LostAttachments:Disclaimer'));
$oForm->AddSubBlock($oAlert);
$oPanel = FieldSetUIBlockFactory::MakeStandard(Dict::S('DBTools:LostAttachments:Step:Analyze'));
$oForm->AddSubBlock($oPanel);
$oButton = ButtonUIBlockFactory::MakeForPrimaryAction(Dict::S('DBTools:LostAttachments:Button:Analyze'), 'step_name', 'analyze', true);
// TODO 3.0 Spacing ?
$oButton->AddCSSClasses(['mt-5', 'mb-5']);
$oPanel->AddSubBlock($oButton);
}
// Step 2: Display results
if($bDoAnalyze)
{
if ($bDoAnalyze) {
// Check if we have to restore some items first
if($bDoRestore)
{
foreach($aRecordsToClean as $sRecordToClean)
{
if ($bDoRestore) {
foreach ($aRecordsToClean as $sRecordToClean) {
utils::PushArchiveMode(false); // For iTop < 2.5, the application can be wrongly set to archive mode true when it fails from retrieving an object. See r5340.
try
{
try {
// Retrieve attachment
$aLocationParts = explode('::', $sRecordToClean);
/** @var \DBObject $oOriginObject */
@@ -308,8 +360,7 @@ function DisplayLostAttachments(iTopWebPage &$oP, ApplicationContext &$oAppConte
$iRestoredItemsCount++;
}
catch(Exception $e)
{
catch (Exception $e) {
$aErrorsReport[] = 'Could not restore attachment from '.$sRecordToClean.', cause: '.$e->getMessage();
}
utils::PopArchiveMode();
@@ -321,23 +372,30 @@ function DisplayLostAttachments(iTopWebPage &$oP, ApplicationContext &$oAppConte
$sSelWrongRecs = 'SELECT id, secret, "InlineImage" AS current_class, id AS current_id, item_class AS target_class, item_id AS target_id, contents_filename AS filename FROM '.$sInlineImageDBTable.' WHERE contents_mimetype NOT LIKE "image/%"';
$aWrongRecords = CMDBSource::QueryToArray($sSelWrongRecs);
$oP->add('<div class="dbt-step">');
$oP->add('<p class="dbt-step-description"><span class="dbt-step-number">2.</span><span>'.Dict::S('DBTools:LostAttachments:Step:AnalyzeResults').'</span></p>');
if(empty($aWrongRecords))
{
$oP->add('<div class="header_message message_ok">'.Dict::S('DBTools:LostAttachments:Step:AnalyzeResults:None').'</div>');
}
else
{
$oP->add('<div class="header_message message_error">'.Dict::Format('DBTools:LostAttachments:Step:AnalyzeResults:Some', count($aWrongRecords)).'</div>');
if (empty($aWrongRecords)) {
$oAlert = AlertUIBlockFactory::MakeForSuccess(Dict::S('DBTools:LostAttachments:Step:AnalyzeResults:None'));
$oForm->AddSubBlock($oAlert);
} else {
// Errors found
$oAlert = AlertUIBlockFactory::MakeForFailure(Dict::Format('DBTools:LostAttachments:Step:AnalyzeResults:Some', count($aWrongRecords)));
// TODO 3.0 Spacing ?
$oAlert->AddCSSClass('mb-5');
$oForm->AddSubBlock($oAlert);
$oPanel = PanelUIBlockFactory::MakeForWarning(Dict::S('DBTools:LostAttachments:Step:AnalyzeResults'));
$oPanel->AddCSSClass('ibo-datatable-panel');
$oForm->AddSubBlock($oPanel);
// Display errors as table
$oP->add('<table class="listResults">');
$oP->add('<tr><th><input type="checkbox" class="dbt-toggler-cbx" /></th><th>'.Dict::S('DBTools:LostAttachments:Step:AnalyzeResults:Item:Filename').'</th><th>'.Dict::S('DBTools:LostAttachments:Step:AnalyzeResults:Item:CurrentLocation').'</th><th>'.Dict::S('DBTools:LostAttachments:Step:AnalyzeResults:Item:TargetLocation').'</th></tr>');
foreach($aWrongRecords as $iIndex => $aWrongRecord)
{
$aColumns = [
'select' => ['label' => '<input type="checkbox" class="dbt-toggler-cbx" />'],
'filename' => ['label' => Dict::S('DBTools:LostAttachments:Step:AnalyzeResults:Item:Filename')],
'location' => ['label' => Dict::S('DBTools:LostAttachments:Step:AnalyzeResults:Item:CurrentLocation')],
'target' => ['label' => Dict::S('DBTools:LostAttachments:Step:AnalyzeResults:Item:TargetLocation')],
];
$aRows = [];
foreach ($aWrongRecords as $iIndex => $aWrongRecord) {
$sCurrentClass = $aWrongRecord['current_class'];
$sCurrentId = $aWrongRecord['current_id'];
@@ -349,76 +407,79 @@ function DisplayLostAttachments(iTopWebPage &$oP, ApplicationContext &$oAppConte
$sFilename = '<a href="'.utils::GetAbsoluteUrlAppRoot().INLINEIMAGE_DOWNLOAD_URL.$aWrongRecord['id'].'&s='.$aWrongRecord['secret'].'" target="_blank">'.$aWrongRecord['filename'].'</a>';
$sRowClass = ($iIndex % 2 === 0) ? 'odd' : 'even'; // (Starts at 0, not 1)
$oP->add('<tr class="'.$sRowClass.'"><td><input type="checkbox" class="dbt-cbx" name="dbt-cbx[]" value="'.$sCurrentClass.'::'.$sCurrentId.'" /></td><td>'.$sFilename.'</td><td>'.$sRecordToClean.'</td><td>'.$sTargetLocation.'</td></tr>');
$aRows[] = [
'select' => '<input type="checkbox" class="dbt-cbx" name="dbt-cbx[]" value="'.$sCurrentClass.'::'.$sCurrentId.'" />',
'filename' => $sFilename,
'location' => $sRecordToClean,
'target' => $sTargetLocation,
];
// $oP->add('<tr class="'.$sRowClass.'"><td><input type="checkbox" class="dbt-cbx" name="dbt-cbx[]" value="'.$sCurrentClass.'::'.$sCurrentId.'" /></td><td>'.$sFilename.'</td><td>'.$sRecordToClean.'</td><td>'.$sTargetLocation.'</td></tr>');
}
$oP->add('</table>');
$oP->add('<div><button type="submit" name="step_name" value="restore" disabled>'.Dict::S('DBTools:LostAttachments:Button:Restore').'</button></div>');
$oTable = DataTableUIBlockFactory::MakeForForm('results', $aColumns, $aRows);
$oPanel->AddSubBlock($oTable);
/** @var \Combodo\iTop\Application\UI\Base\Component\Button\ButtonJS $oButton */
$oButton = ButtonUIBlockFactory::MakeForPrimaryAction(Dict::S('DBTools:LostAttachments:Button:Restore'), 'step_name', 'restore', true);
// TODO 3.0 Spacing ?
$oButton->AddCSSClasses(['mt-5', 'ml-5']);
$oButton->SetIsDisabled(true);
$oPanel->AddSubBlock($oButton);
// JS to handle checkboxes and button
$oP->add_ready_script(
<<<EOF
<<<EOF
// Check all / none checkboxes
$('.dbt-lostattachments .dbt-toggler-cbx').on('click', function(){
$('.dbt-lostattachments .dbt-cbx').prop('checked', $(this).prop('checked'));
$('.ibo-dbt-lostattachments .dbt-toggler-cbx').on('click', function(){
$('.ibo-dbt-lostattachments .dbt-cbx').prop('checked', $(this).prop('checked'));
// Disable restore button if at lest one checkbox clicked
var bDisableButton = ($('.dbt-lostattachments .dbt-cbx:checked').length === 0)
$('.dbt-lostattachments button[name="step_name"][value="restore"]').prop('disabled', bDisableButton);
var bDisableButton = ($('.ibo-dbt-lostattachments .dbt-cbx:checked').length === 0)
$('.ibo-dbt-lostattachments button[name="step_name"][value="restore"]').prop('disabled', bDisableButton);
});
// Click on a checkbox
$('.dbt-lostattachments .dbt-cbx').on('click', function(){
$('.ibo-dbt-lostattachments .dbt-cbx').on('click', function(){
// Disable restore button if at lest one checkbox clicked
var bDisableButton = ($('.dbt-lostattachments .dbt-cbx:checked').length === 0)
$('.dbt-lostattachments button[name="step_name"][value="restore"]').prop('disabled', bDisableButton);
var bDisableButton = ($('.ibo-dbt-lostattachments .dbt-cbx:checked').length === 0)
$('.ibo-dbt-lostattachments button[name="step_name"][value="restore"]').prop('disabled', bDisableButton);
// Uncheck global checkbox
if( $('.dbt-lostattachments .dbt-cbx:not(:checked)').length > 0 )
if( $('.ibo-dbt-lostattachments .dbt-cbx:not(:checked)').length > 0 )
{
$('.dbt-lostattachments .dbt-toggler-cbx').prop('checked', false);
$('.ibo-dbt-lostattachments .dbt-toggler-cbx').prop('checked', false);
}
});
EOF
);
}
$oP->add('</div>');
}
// Step 3: Restore results
if($bDoRestore)
{
$oP->add('<div class="dbt-step">');
$oP->add('<p class="dbt-step-description"><span class="dbt-step-number">3.</span><span>'.Dict::S('DBTools:LostAttachments:Step:RestoreResults').'</span></p>');
if ($bDoRestore) {
$oPanel = FieldSetUIBlockFactory::MakeStandard(Dict::S('DBTools:LostAttachments:Step:RestoreResults'));
$oForm->AddSubBlock($oPanel);
$oP->add('<div class="header_message message_info">'.Dict::Format('DBTools:LostAttachments:Step:RestoreResults:Results', $iRestoredItemsCount, $iRecordsToCleanCount).'</div>');
$oAlert = AlertUIBlockFactory::MakeForSuccess(Dict::Format('DBTools:LostAttachments:Step:RestoreResults:Results', $iRestoredItemsCount, $iRecordsToCleanCount));
$oPanel->AddSubBlock($oAlert);
if(!empty($aErrorsReport))
{
foreach($aErrorsReport as $sErrorReport)
{
$oP->add('<div class="header_message message_error">'.$sErrorReport.'</div>');
if (!empty($aErrorsReport)) {
foreach ($aErrorsReport as $sErrorReport) {
$oAlert = AlertUIBlockFactory::MakeForFailure($sErrorReport);
$oPanel->AddSubBlock($oAlert);
}
}
$oP->add('</div>');
}
$oP->add($oAppContext->GetForForm());
$oP->add('</form>');
$oP->add('</div>');
$oP->add('</div>');
$oP->add('</div>');
$oForm->AddSubBlock($oAppContext->GetForFormBlock());
// Buttons disabling on click
$sConfirmText = Dict::S('DBTools:LostAttachments:Button:Restore:Confirm');
$sButtonBusyText = Dict::S('DBTools:LostAttachments:Button:Busy');
$oP->add_ready_script(
<<<EOF
$('.dbt-lostattachments button[name="step_name"]').on('click', function(){
<<<EOF
$('.ibo-dbt-lostattachments button[name="step_name"]').on('click', function(){
if($(this).val() === 'restore')
{
@@ -427,7 +488,6 @@ EOF
return false;
}
}
//$(this).prop('disabled', true);
$(this).text('{$sButtonBusyText}');
});
EOF
@@ -439,15 +499,11 @@ EOF
/////////////////////////////////////////////////////////////////////
// Main program
//
try
{
if (method_exists('ApplicationMenu', 'CheckMenuIdEnabled'))
{
try {
if (method_exists('ApplicationMenu', 'CheckMenuIdEnabled')) {
LoginWebPage::DoLogin(); // Check user rights and prompt if needed
ApplicationMenu::CheckMenuIdEnabled('DBToolsMenu');
}
else
{
} else {
LoginWebPage::DoLogin(true); // Check user rights and prompt if needed
}
@@ -460,13 +516,9 @@ try
$oP = new iTopWebPage($sPageTitle);
$oP->add_saas('env-'.utils::GetCurrentEnvironment().'/combodo-db-tools/default.scss');
$oP->add(
<<<EOF
<div class="page_header">
<h1>$sPageTitle</h1>
</div>
EOF
);
$oTitle = TitleUIBlockFactory::MakeForPage($sPageTitle);
$oP->AddUiBlock($oTitle);
$oP->AddTabContainer('db-tools');
$oP->SetCurrentTabContainer('db-tools');
@@ -476,12 +528,10 @@ EOF
// Lost attachments
$oP = DisplayLostAttachments($oP, $oAppContext);
}
catch (Exception $e)
{
catch (Exception $e) {
$oP->p('<b>'.$e->getMessage().'</b>');
}
if (isset($oP))
{
if (isset($oP)) {
$oP->output();
}

View File

@@ -39,12 +39,14 @@ Dict::Add('EN US', 'English', 'English', array(
'DBTools:ShowReport' => 'Report',
'DBTools:IntegrityCheck' => 'Integrity check',
'DBTools:FetchCheck' => 'Fetch Check (long)',
'DBTools:SelectAnalysisType' => 'Select analysis type',
'DBTools:Analyze' => 'Analyze',
'DBTools:Details' => 'Show Details',
'DBTools:ShowAll' => 'Show All Errors',
'DBTools:Inconsistencies' => 'Database inconsistencies',
'DBTools:DetailedErrorTitle' => '%2$s error(s) in class %1$s: %3$s',
'DBAnalyzer-Integrity-OrphanRecord' => 'Orphan record in `%1$s`, it should have its counterpart in table `%2$s`',
'DBAnalyzer-Integrity-InvalidExtKey' => 'Invalid external key %1$s (column: `%2$s.%3$s`)',

View File

@@ -34,12 +34,14 @@ Dict::Add('FR FR', 'French', 'Français', array(
'DBTools:ShowReport' => 'Rapport',
'DBTools:IntegrityCheck' => 'Contrôle d\'intégrité',
'DBTools:FetchCheck' => 'Contrôle de récupération (long)',
'DBTools:SelectAnalysisType' => 'Type d\'analyse',
'DBTools:Analyze' => 'Analyser',
'DBTools:Details' => 'Afficher détails',
'DBTools:ShowAll' => 'Afficher toutes les erreurs',
'DBTools:Inconsistencies' => 'Incohérences de base de données',
'DBTools:DetailedErrorTitle' => '%2$s erreur(s) dans la classe %1$s : %3$s',
'DBAnalyzer-Integrity-OrphanRecord' => 'Enregistrement orphelin dans `%1$s`, il devrait avoir son équivalent dans la tableit `%2$s`',
'DBAnalyzer-Integrity-InvalidExtKey' => 'Clef externe invalide %1$s (colonne: `%2$s.%3$s`)',

View File

@@ -105,7 +105,7 @@ class StaticTable extends UIContentBlock
}
/**
* @param string $sUrlForRefresh
* @param string $sFilter
*/
public function SetFilter($sFilter): void
{

View File

@@ -6,9 +6,15 @@ var table{{ oUIBlock.GetId()|sanitize(constant('utils::ENUM_SANITIZATION_FILTER_
scrollCollapse: true,
paging: false,
filter: false,
autoWidth: false,
search: false,
dom: "t",
"order": [],
{% if oUIBlock.GetOption("select_mode") is not empty %}
select: {
style: "{{ oUIBlock.GetOption("select_mode") }}"
},
{% endif %}
});
if ($('#{{ oUIBlock.GetId() }}').find('thead').is(':visible'))
{