From f4c4a5f0824a50bb2ed608b4647c8354c9dbb808 Mon Sep 17 00:00:00 2001 From: cyrilphoenix71 Date: Sat, 25 Jan 2020 15:32:20 +0100 Subject: [PATCH] fix 1666 fix #1666 fix sonar fix Modification ajax et manager optimize notif update phase 2 fix increment update fix --- assets/css/components/_buttons.scss | 3 +- assets/css/containers/_containers.scss | 5 + assets/css/divers/_positions.scss | 3 + assets/css/pages/_modals.scss | 9 + assets/css/themes/_base.scss | 3 +- assets/js/core/log.class.js | 12 +- assets/js/core/update.class.js | 9 +- assets/js/desktop/diagnostic/log.js | 6 +- assets/js/desktop/gui.js | 64 +++++- assets/js/desktop/inits.js | 68 +++++++ assets/js/desktop/loads.js | 57 ------ assets/js/desktop/pages/connection.js | 2 + assets/js/desktop/tools/backup.js | 185 +++++++++--------- assets/js/desktop/tools/update.js | 101 ++++------ assets/js/desktop/utils.js | 36 +--- assets/js/modals/cmd.configure.js | 18 +- assets/js/modals/icon.selector.js | 2 +- assets/js/modals/message.js | 2 +- src/Ajax/UpdateAjax.php | 4 +- src/Controller/Modals/LogBasic.php | 46 +++++ src/Enums/Common.php | 4 + src/Enums/SQLField.php | 1 + src/Enums/UpdateType.php | 35 ++++ src/Helpers/ConsoleHelper.php | 20 +- src/Helpers/DBHelper.php | 24 +++ src/Managers/BackupManager.php | 54 ++--- src/Managers/UpdateManager.php | 102 ++++++---- src/Model/Entity/Listener.php | 2 +- src/Model/Entity/Update.php | 16 +- src/modals_routes.yml | 4 + tests/launch_php_tests.py | 2 - .../Managers/UpdateManagerTest.php | 76 +++++++ views/desktop/tools/backup.html.twig | 22 ++- views/desktop/tools/update-view.html.twig | 33 ++-- views/modals/cmd.configure.html.twig | 2 - views/modals/icon.selector.html.twig | 2 +- views/modals/log.basic.html.twig | 22 +++ 37 files changed, 690 insertions(+), 366 deletions(-) create mode 100644 src/Controller/Modals/LogBasic.php create mode 100644 src/Enums/UpdateType.php create mode 100644 views/modals/log.basic.html.twig diff --git a/assets/css/components/_buttons.scss b/assets/css/components/_buttons.scss index 02e2fa6a2..a4e8bb8e5 100644 --- a/assets/css/components/_buttons.scss +++ b/assets/css/components/_buttons.scss @@ -92,7 +92,8 @@ .btn-box-tool { padding: 8px 5px; } -.btn-action-bar { +.btn-action-bar, +.box-footer .btn { margin-bottom: 2px; margin-top: 2px; } diff --git a/assets/css/containers/_containers.scss b/assets/css/containers/_containers.scss index 23a4603ef..43ed5e0c2 100644 --- a/assets/css/containers/_containers.scss +++ b/assets/css/containers/_containers.scss @@ -117,6 +117,11 @@ .form-control { width: auto; } + legend { + width: auto; + margin-right: auto; + padding-right: 20px; + } } .form-group-light { margin-bottom: 4px; diff --git a/assets/css/divers/_positions.scss b/assets/css/divers/_positions.scss index 455ab54aa..7891a5612 100644 --- a/assets/css/divers/_positions.scss +++ b/assets/css/divers/_positions.scss @@ -59,6 +59,9 @@ .spacing-top-big { margin-top: 10px !important; } +.spacing-top-big-three { + margin-top: 30px !important; +} .no-spacing { margin-right: 0 !important; } diff --git a/assets/css/pages/_modals.scss b/assets/css/pages/_modals.scss index f849b9d6f..af2d2c6f0 100644 --- a/assets/css/pages/_modals.scss +++ b/assets/css/pages/_modals.scss @@ -43,6 +43,7 @@ min-height: 0; pre { margin: 0; + overflow: scroll; } } .ui-dialog-content { @@ -131,3 +132,11 @@ .modal-padding { padding: 15px !important; } +.modal-pre-full { + height: calc(100% - 30px); + width: calc(100% - 30px); + position: absolute; + bottom: 0; + top: 0; + margin: 15px 0 !important; +} diff --git a/assets/css/themes/_base.scss b/assets/css/themes/_base.scss index c6f260897..edf217fd0 100644 --- a/assets/css/themes/_base.scss +++ b/assets/css/themes/_base.scss @@ -439,7 +439,8 @@ html { /* Progressbar */ .box-body .progress, -.tab-pane .progress { +.tab-pane .progress, +.form-group .progress { background-color: map_get($color_theme, 'color7') !important; } diff --git a/assets/js/core/log.class.js b/assets/js/core/log.class.js index 8c750f662..135124061 100644 --- a/assets/js/core/log.class.js +++ b/assets/js/core/log.class.js @@ -67,7 +67,7 @@ nextdom.log.autoupdate = function (queryParams) { } else { queryParams['search'].value(''); } - queryParams.display.scrollTop(queryParams.display.height() + 200000); + queryParams.display.scrollTop(queryParams.display.innerHeight()+scrollTopToDown); if (queryParams['control'].attr('data-state') == 0) { queryParams['control'].attr('data-state', 1); } @@ -80,7 +80,7 @@ nextdom.log.autoupdate = function (queryParams) { $(this).removeClass('btn-success').addClass('btn-warning'); $(this).html('{{Pause}}'); $(this).attr('data-state', 1); - queryParams.display.scrollTop(queryParams.display.height() + 200000); + queryParams.display.scrollTop(queryParams.display.innerHeight()+scrollTopToDown); nextdom.log.autoupdate(queryParams); } }); @@ -115,13 +115,13 @@ nextdom.log.autoupdate = function (queryParams) { } } queryParams.display.text(log); - queryParams.display.scrollTop(queryParams.display.height() + 200000); + queryParams.display.scrollTop(queryParams.display.innerHeight()+scrollTopToDown); if (nextdom.log.timeout !== null) { - clearTimeout(jeedom.log.timeout); + clearTimeout(nextdom.log.timeout); } nextdom.log.timeout = setTimeout(function () { nextdom.log.autoupdate(queryParams) - }, 1000); + }, 500); }, error: function () { if (nextdom.log.timeout !== null) { @@ -129,7 +129,7 @@ nextdom.log.autoupdate = function (queryParams) { } nextdom.log.timeout = setTimeout(function () { nextdom.log.autoupdate(queryParams) - }, 1000); + }, 500); }, }); }; diff --git a/assets/js/core/update.class.js b/assets/js/core/update.class.js index a7a13922c..3919d9b96 100644 --- a/assets/js/core/update.class.js +++ b/assets/js/core/update.class.js @@ -62,5 +62,10 @@ nextdom.update.saves = function (queryParams) { }; nextdom.update.number = function (queryParams) { - nextdom.private.ajax('Update', 'nbUpdate', queryParams, false, false, false); -}; \ No newline at end of file + var params = $.extend({}, nextdom.private.default_params, queryParams || {}); + var ajaxParams = nextdom.private.getParamsAJAX(params, 'Update', 'nbUpdate'); + if (queryParams !== undefined && queryParams.hasOwnProperty('filter')) { + ajaxParams.data['filter'] = json_encode(queryParams.filter); + } + nextdom.private.ajaxCall(ajaxParams); +}; diff --git a/assets/js/desktop/diagnostic/log.js b/assets/js/desktop/diagnostic/log.js index 90a416428..122ce627f 100644 --- a/assets/js/desktop/diagnostic/log.js +++ b/assets/js/desktop/diagnostic/log.js @@ -43,8 +43,8 @@ initEvents(); */ function loadInformations() { $(document).ready(function () { - $('pre').height($(window).height() - 339); - $('#ul_object').height($(window).height() - 339); + $('pre').height($(window).height() - 300); + $('#ul_object').height($(window).height() - 279); $('#ul_object').css("overflow-y", "auto"); $('#ul_object').css("padding-right", "5px"); sortList("#ul_object", "timing"); @@ -122,6 +122,7 @@ function initEvents() { // Display log by alphabetic sort $("#bt_LogAlphabetic").on('click', function (event) { sortList("#ul_object", "log"); + $(".li_log").removeClass('active'); $('.li_log').first().addClass('active'); $('#bt_LogAlphabetic').removeClass('btn-action').addClass('btn-info'); $('#bt_LogChronologic').removeClass('btn-info').addClass('btn-action'); @@ -131,6 +132,7 @@ function initEvents() { // Display log by timing sort $("#bt_LogChronologic").on('click', function (event) { sortList("#ul_object", "timing"); + $(".li_log").removeClass('active'); $('.li_log').first().addClass('active'); $('#bt_LogChronologic').removeClass('btn-action').addClass('btn-info'); $('#bt_LogAlphabetic').removeClass('btn-info').addClass('btn-action'); diff --git a/assets/js/desktop/gui.js b/assets/js/desktop/gui.js index 86f262e5a..0a5a4a73e 100644 --- a/assets/js/desktop/gui.js +++ b/assets/js/desktop/gui.js @@ -349,6 +349,36 @@ function refreshUpdateNumber() { } } }); + if($('#spanNbUpdates').length){ + nextdom.update.number({ + filter: ['core', 'plugin', 'widget', 'script'], + error: function (error) { + notify("Erreur", error.message, 'error'); + }, + success: function (updatesData) { + var updateSum = 0; + for (var updateIndex in updatesData) { + var target = $('#spanNbUpdates-' + updatesData[updateIndex].type); + var targetCount = updatesData[updateIndex].count; + updateSum += targetCount; + if (targetCount == 0) { + target.hide(); + } + else { + target.html(targetCount); + target.show(); + } + } + if (updateSum == 0) { + $('#spanNbUpdates').hide(); + } + else { + $('#spanNbUpdates').html(updateSum); + $('#spanNbUpdates').hide(); + } + } + }); + } } /** @@ -406,18 +436,50 @@ function displayClock() { * Adjust size and position of jquery modales */ function modalesAdjust() { - var modals = [$('#md_modal'), $('#md_modal2')]; + var modals = [$('#md_modal'), $('#md_modal2'), $('#md_pageHelp')]; modals.forEach(function (modal) { if (modal.is(':ui-dialog')) { modal.dialog('option', 'width', getModalWidth()); + modal.dialog('option', 'height', getModalHeight()); modal.dialog('option', 'position', {my: 'center', at: 'center', of: window}); } }); } +/** + * Calcul modal width depend of width screen + */ function getModalWidth() { if (jQuery(window).width() < 1000) { return '96%'; } return '80%'; } + +/** + * Calcul modal width depend of width screen + */ +function getModalHeight() { + return (jQuery(window).height() - 100); +} + +/** + * Set new progress bar value + * + * @param progressElement the progress element to set. + * @param newValue new progress value. + */ +function setProgressBar(progressElement, newValue) { + if (newValue == 0) { + progressStatus = 0; + } + $(progressElement).attr('aria-valuenow',newValue); + $(progressElement).css('width',newValue + '%'); + $(progressElement).find('span').html(newValue + '%'); + if ($(progressElement).parent().hasClass('progress') && $(progressElement).parent().next('span').length>0) { + let spanValue = $(progressElement).parent().next('span').html(); + let spanSplit = spanValue.split('%'); + spanSplit[0] = newValue + '%'; + $(progressElement).parent().next('span').html(spanSplit.join('')); + } +} diff --git a/assets/js/desktop/inits.js b/assets/js/desktop/inits.js index 04bf1a591..476edf53a 100644 --- a/assets/js/desktop/inits.js +++ b/assets/js/desktop/inits.js @@ -49,6 +49,7 @@ function initPage(){ initTextArea(); initEventHandler(); initFields(); + initModals(); // Trig page loaded $('body').trigger('nextdom_page_load'); @@ -179,3 +180,70 @@ function initTextArea(){ } }); } + + /** + * Init of modals pages + */ + function initModals(){ + // Help modal trigger declaration + $("#md_pageHelp").dialog({ + autoOpen: false, + modal: false, + closeText: '', + height: getModalHeight(), + width: getModalWidth(), + resizable: false, + open: function () { + $("body").css({overflow: 'hidden'}); + modalesAdjust(); + $(".wrapper").addClass("blur"); + }, + beforeClose: function (event, ui) { + $("body").css({overflow: 'inherit'}); + $("#md_pageHelp").empty(); + $(".wrapper").removeClass("blur"); + } + }); + + // modal trigger declaration + $("#md_modal").dialog({ + autoOpen: false, + modal: false, + closeText: '', + height: getModalHeight(), + width: getModalWidth(), + resizable: false, + open: function () { + $("body").css({overflow: 'hidden'}); + modalesAdjust(); + $(".wrapper").addClass("blur"); + }, + beforeClose: function (event, ui) { + $("body").css({overflow: 'inherit'}); + $("#md_modal").empty(); + $("#md_modal").dialog('option', 'buttons', []); + $(".wrapper").removeClass("blur"); + } + }); + + // modal bis trigger declaration + $("#md_modal2").dialog({ + autoOpen: false, + modal: false, + closeText: '', + height: getModalHeight(), + width: getModalWidth(), + resizable: false, + open: function () { + $("body").css({overflow: 'hidden'}); + modalesAdjust(); + $(".wrapper").addClass("blur"); + }, + beforeClose: function (event, ui) { + $("body").css({overflow: 'inherit'}); + $("#md_modal2").empty(); + $("#md_modal2").dialog('option', 'buttons', []); + $(".wrapper").removeClass("blur"); + } + }); +} diff --git a/assets/js/desktop/loads.js b/assets/js/desktop/loads.js index 8bf04abd6..0166b4a94 100644 --- a/assets/js/desktop/loads.js +++ b/assets/js/desktop/loads.js @@ -310,63 +310,6 @@ $(function () { }); }); - // Help modal trigger declaration - $("#md_pageHelp").dialog({ - autoOpen: false, - modal: false, - closeText: '', - height: (jQuery(window).height() - 100), - width: getModalWidth(), - show: { effect: "blind", duration: 200 }, - resizable: false, - open: function () { - $("body").css({overflow: 'hidden'}); - $(this).dialog("option", "position", {my: "center", at: "center", of: window}); - }, - beforeClose: function (event, ui) { - $("body").css({overflow: 'inherit'}); - $("#md_pageHelp").empty(); - } - }); - - // modal trigger declaration - $("#md_modal").dialog({ - autoOpen: false, - modal: false, - closeText: '', - height: (jQuery(window).height() - 100), - width: getModalWidth(), - show: { effect: "blind", duration: 200 }, - resizable: false, - open: function () { - $("body").css({overflow: 'hidden'}); - $(this).dialog("option", "position", {my: "center", at: "center", of: window}); - }, - beforeClose: function (event, ui) { - $("body").css({overflow: 'inherit'}); - $("#md_modal").empty(); - } - }); - - // modal bis trigger declaration - $("#md_modal2").dialog({ - autoOpen: false, - modal: false, - closeText: '', - height: (jQuery(window).height() - 100), - width: getModalWidth(), - show: { effect: "blind", duration: 200 }, - resizable: false, - open: function () { - $("body").css({overflow: 'hidden'}); - $(this).dialog("option", "position", {my: "center", at: "center", of: window}); - }, - beforeClose: function (event, ui) { - $("body").css({overflow: 'inherit'}); - $("#md_modal2").empty(); - } - }); - // Prevent close event handler declaration to advise user for exit without saving $(window).bind('beforeunload', function (e) { if (modifyWithoutSave) { diff --git a/assets/js/desktop/pages/connection.js b/assets/js/desktop/pages/connection.js index a37de3459..51107f222 100644 --- a/assets/js/desktop/pages/connection.js +++ b/assets/js/desktop/pages/connection.js @@ -135,9 +135,11 @@ function updateTwoFactorVisibility() { if (useTwoFactor === 1) { divLogin.hide(); divTwoFactor.show(); + twoFactorInput.focus(); } else { divLogin.show(); divTwoFactor.hide(); + loginInput.focus(); } } diff --git a/assets/js/desktop/tools/backup.js b/assets/js/desktop/tools/backup.js index 740b4b384..d92e95e3d 100644 --- a/assets/js/desktop/tools/backup.js +++ b/assets/js/desktop/tools/backup.js @@ -33,6 +33,7 @@ * @Email * @Authors/Contributors: Sylvaner, Byackee, cyrilphoenix71, ColonelMoutarde, edgd1er, slobberbone, Astral0, DanoneKiD */ +var backupInfoModal = $('#md_modal'); // Page init loadInformations(); @@ -101,27 +102,10 @@ function initEvents() { }); }); - // Backup modale init - $("#md_backupInfo").dialog({ - closeText: '', - autoOpen: false, - modal: true, - height: jQuery(window).height() - 100, - width: getModalWidth(), - open: function () { - $("body").css({overflow: 'hidden'}); - $(this).dialog("option", "position", {my: "center", at: "center", of: window}); - $('#pre_backupInfo').css('height', $('#md_backupInfo').height()); - }, - beforeClose: function (event, ui) { - $("body").css({overflow: 'inherit'}); - } - }); - // Open log button $("#bt_saveOpenLog").on('click', function (event) { - $('#md_backupInfo').dialog({title: "{{Avancement de la sauvegarde}}"}); - $("#md_backupInfo").dialog('open'); + backupInfoModal.dialog({title: "{{Avancement de la sauvegarde}}"}); + backupInfoModal.load('index.php?v=d&modal=log.basic').dialog('open'); }); // Backup button @@ -132,14 +116,15 @@ function initEvents() { $('#bt_backupNextDom').addClass('disabled'); el.find('.fa-refresh').show(); el.find('.fa-floppy-o').hide(); - $('#md_backupInfo').dialog({title: "{{Avancement de la sauvegarde}}"}); - $("#md_backupInfo").dialog('open'); nextdom.backup.backup({ error: function (error) { notify("Erreur", error.message, 'error'); }, success: function () { - getNextDomLog(1, 'backup'); + backupInfoModal.dialog({title: "{{Avancement de la sauvegarde}}"}); + setProgressBar($("#progressbar"), 0); + $("#progressbar_div").show(); + getNextDomLog(1, 'backup'); } }); } @@ -156,15 +141,15 @@ function initEvents() { $('#bt_restoreRepoNextDom').addClass('disabled'); el.find('.fa-refresh').show(); el.find('.fa-window-restore').hide(); - $('#md_backupInfo').dialog({title: "{{Avancement de la restauration}}"}); - $("#md_backupInfo").dialog('open'); nextdom.backup.restoreLocal({ backup: $('#sel_restoreBackup').value(), error: function (error) { notify("Erreur", error.message, 'error'); }, success: function () { - getNextDomLog(1, 'restore'); + backupInfoModal.dialog({title: "{{Avancement de la restauration}}"}); + setProgressBar($("#progressbar"), 0); + $("#progressbar_div").show(); } }); } @@ -239,8 +224,9 @@ function initEvents() { notify("Erreur", error.message, 'error'); }, success: function () { - $('#md_backupInfo').dialog({title: "{{Avancement de la restauration}}"}); - $("#md_backupInfo").dialog('open'); + backupInfoModal.dialog({title: "{{Avancement de la restauration}}"}); + setProgressBar($("#progressbar"), 0); + $("#progressbar_div").show(); getNextDomLog(1, 'restore'); } }); @@ -250,75 +236,84 @@ function initEvents() { } function getNextDomLog(_autoUpdate, _log) { - $.ajax({ - type: 'POST', - url: 'src/ajax.php', - data: { - target: 'Log', - action: 'get', - log: _log, - }, - dataType: 'json', - global: false, - error: function (request, status, error) { - setTimeout(function () { - getNextDomLog(_autoUpdate, _log) - }, 1000); - }, - success: function (data) { - if (data.state != 'ok') { - setTimeout(function () { - getNextDomLog(_autoUpdate, _log) - }, 1000); - return; - } - var log = ''; - if($.isArray(data.result)){ - for (var i in data.result.reverse()) { - log += data.result[i]+"\n"; - if(data.result[i].indexOf('Closing with success') != -1){ - switchNotify(1); - nextdom.user.refresh(); - notify("Info", '{{L\'opération est réussie}}', 'success'); - _autoUpdate = 0; - } - if(data.result[i].indexOf('Closing with error') != -1){ - switchNotify(1); - nextdom.user.refresh(); - notify("Erreur", '{{L\'opération a échoué}}', 'error'); - _autoUpdate = 0; - } - if(data.result[i].indexOf('Fatal error') != -1){ - switchNotify(1); - nextdom.user.refresh(); - notify("Erreur", '{{L\'opération a échoué}}', 'error'); - _autoUpdate = 0; - } - } - } - $('#pre_backupInfo').text(log); - if (init(_autoUpdate, 0) == 1) { - setTimeout(function () { - getNextDomLog(_autoUpdate, _log) - }, 500); - } else { - $('#bt_' + _log + 'NextDom').removeClass('disabled'); - $('#bt_' + _log + 'RepoNextDom').removeClass('disabled'); - $('#bt_' + _log + 'NextDom .fa-refresh').hide(); - $('#bt_' + _log + 'RepoNextDom .fa-refresh').hide(); - $('#bt_' + _log + 'NextDom .fa-floppy-o').show(); - $('#bt_' + _log + 'NextDom .fa-window-restore').show(); - $('#bt_' + _log + 'RepoNextDom .fa-window-restore').show(); - $('#bt_' + _log + 'NextDom .fa-cloud-upload-alt').show(); - $('#bt_' + _log + 'NextDom .fa-cloud-dowload-alt').show(); - updateListBackup(); - for(var i in REPO_LIST){ - updateRepoListBackup(REPO_LIST[i]); - } - refreshMessageNumber(); - } + nextdom.log.get({ + log: _log, + success: function (result) { + var log = ''; + var search = $('#generalSearch'); + var regex = //gi; + if ($.isArray(result)) { + for (var i in result.reverse()) { + if (!isset(search) || search.value() == '' || result[i].toLowerCase().indexOf(search.value().toLowerCase()) != -1) { + log += $.trim(result[i]) + "\n"; + } } - }); + if(log.indexOf('Closing with success') != -1){ + switchNotify(1); + nextdom.user.refresh(); + notify("Info", '{{L\'opération est réussie}}', 'success'); + _autoUpdate = 0; + } + if(log.indexOf('Closing with error') != -1){ + switchNotify(1); + nextdom.user.refresh(); + notify("Erreur", '{{L\'opération a échoué}}', 'error'); + _autoUpdate = 0; + } + if(log.indexOf('Fatal error') != -1){ + switchNotify(1); + nextdom.user.refresh(); + notify("Erreur", '{{L\'opération a échoué}}', 'error'); + _autoUpdate = 0; + } + if(log.indexOf('OK (') != -1){ + let progressPos = log.indexOf('OK (')+4; + let newProgressStatus = parseInt(log.substr(progressPos, log.indexOf('%')-progressPos)); + if (newProgressStatus > progressStatus) { + progressStatus = newProgressStatus; + setProgressBar($("#progressbar"), progressStatus); + } + } + } + $('#pre_modal').text(log); + $('#pre_modal').scrollTop($('#pre_modal').innerHeight()+scrollTopToDown); + if (init(_autoUpdate, 0) == 1) { + setTimeout(function () { + getNextDomLog(_autoUpdate, _log) + }, 500); + } else { + $('#bt_' + _log + 'NextDom').removeClass('disabled'); + $('#bt_' + _log + 'RepoNextDom').removeClass('disabled'); + $('#bt_' + _log + 'NextDom .fa-refresh').hide(); + $('#bt_' + _log + 'RepoNextDom .fa-refresh').hide(); + $('#bt_' + _log + 'NextDom .fa-floppy-o').show(); + $('#bt_' + _log + 'NextDom .fa-window-restore').show(); + $('#bt_' + _log + 'RepoNextDom .fa-window-restore').show(); + $('#bt_' + _log + 'NextDom .fa-cloud-upload-alt').show(); + $('#bt_' + _log + 'NextDom .fa-cloud-dowload-alt').show(); + $("#progressbar_div").hide(); + updateListBackup(); + for(var i in REPO_LIST){ + updateRepoListBackup(REPO_LIST[i]); + } + refreshMessageNumber(); + } + if (nextdom.log.timeout !== null) { + clearTimeout(nextdom.log.timeout); + } + nextdom.log.timeout = setTimeout(function () { + getNextDomLog(_autoUpdate, _log) + }, 500); + }, + error: function () { + if (nextdom.log.timeout !== null) { + clearTimeout(nextdom.log.timeout); + } + nextdom.log.timeout = setTimeout(function () { + getNextDomLog(_autoUpdate, _log) + }, 500); + }, + }); } function updateListBackup() { diff --git a/assets/js/desktop/tools/update.js b/assets/js/desktop/tools/update.js index 888ad4c55..b2a2bf3ac 100644 --- a/assets/js/desktop/tools/update.js +++ b/assets/js/desktop/tools/update.js @@ -35,24 +35,20 @@ */ var tabsList = $('#accordionUpdate > .tab-pane > .row > div'); -var updateInfoModal = $('#updateInfoModal'); +var updateModale = $("#md_modal"); var selectiveUpdateModal = $('#selectiveUpdateModal'); var updateCollapseButton = $('#updateCollapseButton'); var updateUncollapseButton = $('#updateUncollapseButton'); -var updateLogView = $('#updateLog'); // Page init loadInformations(); -initUpdateTabsContent(); -initDialogs(); -initEvents(); /** * Load informations in all forms of the page */ function loadInformations() { - updateLogView.height($(window).height() - $('header').height() - 150); - updateLogView.parent().height($(window).outerHeight() - $('header').outerHeight() - 160); + initUpdateTabsContent(); + initEvents(); } /** @@ -77,24 +73,23 @@ function initEvents() { // Selective update start button $('#startUpdateButton').off('click').on('click', function () { selectiveUpdateModal.modal('hide'); - showLogDialog(); - $('#lbl_updateRunning').show(); + setProgressBar($("#progressbar"), 0); + $("#progressbar_div").show(); + getNextDomLog(1, 'update'); var options = selectiveUpdateModal.getValues('.updateOption')[0]; nextdom.update.doAll({ options: options, error: function (error) { notify('Erreur', error.message, 'error'); - }, - success: function () { - notify("Info", '{{L\'opération est réussie.}}', 'success'); - window.location.reload(); } }); }); // Show log button $('#logDialogButton').on('click', function () { - showLogDialog(); + getNextDomLog(1, 'update'); + updateModale.dialog({title: '{{Avancement de la mise à jour}}'}); + updateModale.load('index.php?v=d&modal=log.basic').dialog('open'); }); // Updates check all button @@ -106,6 +101,7 @@ function initEvents() { $('#checkAllUpdatesButton').children().removeClass('fa-spin'); }, success: function () { + notify('Info', '{{Vérifications terminées}}', 'success'); initUpdateTabsContent(); $('#checkAllUpdatesButton').children().removeClass('fa-spin'); } @@ -149,8 +145,10 @@ function initEvents() { // Check update button on one update box tabsList.delegate('.checkUpdate', 'click', function () { + $(this).children().addClass('fa-spin'); var updateId = $(this).closest('.box').attr('data-id'); checkSingleUpdate(updateId); + $(this).children().removeClass('fa-spin'); }); // Save button @@ -273,7 +271,7 @@ function createUpdateBox(updateData,updateId) { htmlData += '{{Changelog}}'; } } - htmlData += '{{Vérifier}}'; + htmlData += '{{Vérifier}}'; htmlData += ''; htmlData += ''; htmlData += ''; @@ -327,6 +325,7 @@ function checkSingleUpdate(updateId) { notify('Erreur', error.message, 'error'); }, success: function () { + notify('Info', '{{Vérification terminée}}', 'success'); initUpdateTabsContent(updateId); } }); @@ -346,6 +345,7 @@ function removeUpdate(updateId) { notify('Erreur', error.message, 'error'); }, success: function () { + notify('Info', '{{Objet supprimé}}', 'success'); initUpdateTabsContent(); } }); @@ -361,16 +361,13 @@ function removeUpdate(updateId) { function launchUpdate(updateId) { bootbox.confirm('{{Etes vous sur de vouloir mettre à jour cet objet ?}}', function (result) { if (result) { - showLogDialog(); - $('#lbl_updateRunning').show(); + setProgressBar($("#progressbar"), 0); + $("#progressbar_div").show(); + getNextDomLog(1, 'update'); nextdom.update.do({ id: updateId, error: function (error) { notify('Erreur', error.message, 'error'); - }, - success: function () { - notify("Info", '{{L\'opération est réussie.}}', 'success'); - window.location.reload(); } }); } @@ -397,62 +394,50 @@ function getNextDomLog(_autoUpdate, _log) { error: function (request, status, error) { setTimeout(function () { getNextDomLog(_autoUpdate, _log) - }, 1000); + }, 500); }, success: function (data) { if (data.state != 'ok') { setTimeout(function () { getNextDomLog(_autoUpdate, _log) - }, 1000); + }, 500); return; } var log = ''; if ($.isArray(data.result)) { for (var i in data.result.reverse()) { log += data.result[i] + "\n"; - if (data.result[i].indexOf('[END') != -1) { - initUpdateTabsContent(); - _autoUpdate = 0; + if(data.result[i].indexOf('[END UPDATE SUCCESS]') != -1){ + notify("Info", '{{L\'opération est réussie}}', 'success'); + initUpdateTabsContent(); + _autoUpdate = 0; + } + if(data.result[i].indexOf('[END UPDATE ERROR]') != -1){ + notify("Erreur", '{{L\'opération a échoué}}', 'error'); + initUpdateTabsContent(); + _autoUpdate = 0; + } + if(data.result[i].indexOf('OK (') != -1){ + let progressPos = data.result[i].indexOf('OK (')+4; + let newProgressStatus = parseInt(data.result[i].substr(progressPos, data.result[i].indexOf('%')-progressPos)); + if (newProgressStatus > progressStatus) { + progressStatus = newProgressStatus; + setProgressBar($("#progressbar"), progressStatus); + } } } } - updateLogView.text(log); - updateLogView.parent().scrollTop(updateLogView.parent().height() + 200000); + $('#pre_modal').text(log); + $('#pre_modal').scrollTop($('#pre_modal').innerHeight()+scrollTopToDown); if (init(_autoUpdate, 0) == 1) { setTimeout(function () { getNextDomLog(_autoUpdate, _log) - }, 1000); + }, 500); } else { - $('#lbl_updateRunning').hide(); + setTimeout(function () { + window.location.reload(); + }, 500); } } }); } - -/** - * Show log update modale - */ -function showLogDialog() { - updateInfoModal.dialog({title: '{{Avancement de la mise à jour}}'}); - updateInfoModal.dialog('open'); - getNextDomLog(1, 'update'); -} - -/** - * Init dialogs - */ -function initDialogs() { - updateInfoModal.dialog({ - closeText: '', - autoOpen: false, - modal: true, - width: getModalWidth(), - open: function () { - $('body').css({overflow: 'hidden'}); - $(this).dialog("option", "position", {my: "center", at: "center", of: window}); - }, - beforeClose: function (event, ui) { - $('body').css({overflow: 'inherit'}); - } - }); -} diff --git a/assets/js/desktop/utils.js b/assets/js/desktop/utils.js index 4840e878f..d0aa80ddb 100644 --- a/assets/js/desktop/utils.js +++ b/assets/js/desktop/utils.js @@ -37,6 +37,9 @@ /* Global variables Initialisations */ var modifyWithoutSave = false; var lockModify = false; +var progressStatus = 0; +var progressInc = 0; +const scrollTopToDown = 1000000000; uniqId_count = 0; modifyWithoutSave = false; nbActiveAjaxRequest = 0; @@ -77,7 +80,7 @@ function notify(_title, _text, _class_name) { } if (_class_name == "success") { _backgroundColor = '#00a65a'; - _icon = 'far fa-check-circle fa-3x'; + _icon = 'far fa-check fa-3x'; } else if (_class_name == "warning") { _backgroundColor = '#f39c12'; _icon = 'fas fa-exclamation-triangle fa-3x'; @@ -155,28 +158,9 @@ function notify(_title, _text, _class_name) { * @param _callback callback who receive the icon code */ function chooseIcon(_callback) { - if ($("#mod_selectIcon").length == 0) { - $('#div_pageContainer').append('
'); - - $("#mod_selectIcon").dialog({ - closeText: '', - autoOpen: false, - modal: true, - height: (jQuery(window).height() - 150), - width: getModalWidth(), - open: function () { - $("body").css({overflow: 'hidden'}); - $(this).dialog("option", "position", {my: "center", at: "center", of: window}); - }, - beforeClose: function (event, ui) { - $("body").css({overflow: 'inherit'}); - } - }); - jQuery.ajaxSetup({async: false}); - $('#mod_selectIcon').load('index.php?v=d&modal=icon.selector'); - jQuery.ajaxSetup({async: true}); - } - $("#mod_selectIcon").dialog('option', 'buttons', { + $('#md_modal2').dialog({title: "{{Choisissez votre icône}}"}); + $('#md_modal2').load('index.php?v=d&modal=icon.selector'); + $("#md_modal2").dialog('option', 'buttons', { "Annuler": function () { $(this).dialog("close"); }, @@ -190,7 +174,7 @@ function chooseIcon(_callback) { $(this).dialog('close'); } }); - $('#mod_selectIcon').dialog('open'); + $('#md_modal2').dialog('open'); } /** @@ -709,11 +693,11 @@ function passwordScore(password, progressbar=null, spanLevel=null) { /** * Decode HTML entities in string like é - * @param string message + * @param string message */ function decodeHtmlEntities(message) { var temporaryTextArea = document.createElement('textarea'); temporaryTextArea.innerHTML = message; return temporaryTextArea.value; -} \ No newline at end of file +} diff --git a/assets/js/modals/cmd.configure.js b/assets/js/modals/cmd.configure.js index 53d2a1e7f..b92c016c5 100644 --- a/assets/js/modals/cmd.configure.js +++ b/assets/js/modals/cmd.configure.js @@ -100,21 +100,6 @@ function loadInformations() { * Init events on the profils page */ function initEvents() { - $("#md_cmdConfigureSelectMultiple").dialog({ - closeText: '', - autoOpen: false, - modal: true, - height: jQuery(window).height() - 100, - width: getModalWidth(), - open: function () { - $("body").css({overflow: 'hidden'}); - $(this).dialog("option", "position", {my: "center", at: "center", of: window}); - }, - beforeClose: function (event, ui) { - $("body").css({overflow: 'inherit'}); - } - }); - $('#table_widgetParametersCmd').delegate('.removeWidgetParameter', 'click', function () { $(this).closest('tr').remove(); }); @@ -428,7 +413,8 @@ function initEvents() { cmd.display.parameters[$(this).find('.key').value()] = $(this).find('.value').value(); }); cmd = {display: cmd.display, template: cmd.template}; - $('#md_cmdConfigureSelectMultiple').load('index.php?v=d&modal=cmd.selectMultiple&cmd_id=' + cmdInfo.id, function () { + $('#md_modal2').dialog({title: "{{Sélection multiple de commandes}}"}); + $('#md_modal2').load('index.php?v=d&modal=cmd.selectMultiple&cmd_id=' + cmdInfo.id, function () { initTableSorter(); $('#bt_cmdConfigureSelectMultipleAlertToogle').off().on('click', function () { var state = false; diff --git a/assets/js/modals/icon.selector.js b/assets/js/modals/icon.selector.js index 10b379f4f..f0630ede3 100644 --- a/assets/js/modals/icon.selector.js +++ b/assets/js/modals/icon.selector.js @@ -63,7 +63,7 @@ $('.btn-selector').on('click', function () { $('.btn-selector').on('dblclick', function () { $('.btn-selector').removeClass('iconSelected'); $(this).closest('.btn-selector').addClass('iconSelected'); - $('#mod_selectIcon').dialog("option", "buttons")['Valider'].apply($('#mod_selectIcon')); + $('#md_modal2').dialog("option", "buttons")['Valider'].apply($('#md_modal2')); }); $('#bt_iconCollapse').on('click',function(){ diff --git a/assets/js/modals/message.js b/assets/js/modals/message.js index aea69908f..2bf6bf8f3 100644 --- a/assets/js/modals/message.js +++ b/assets/js/modals/message.js @@ -43,7 +43,7 @@ function initEvents() { notify('Erreur', error.message, 'error'); }, success: function () { - $('#table_message tbody').remove(); + $('#table_message .menu').empty(); refreshMessageNumber(); } }); diff --git a/src/Ajax/UpdateAjax.php b/src/Ajax/UpdateAjax.php index 655c4c00e..c0bd4c932 100644 --- a/src/Ajax/UpdateAjax.php +++ b/src/Ajax/UpdateAjax.php @@ -44,7 +44,8 @@ class UpdateAjax extends BaseAjax public function nbUpdate() { - $this->ajax->success(UpdateManager::nbNeedUpdate()); + $filter = json_decode(Utils::init(AjaxParams::FILTER, '')); + $this->ajax->success(UpdateManager::nbNeedUpdate($filter)); } public function all() @@ -105,7 +106,6 @@ public function update() } LogHelper::addAlert(LogTarget::UPDATE, __("[END UPDATE SUCCESS]")); - LogHelper::addAlert(LogTarget::UPDATE, __("Refresh with F5 key to discover news")); } } catch (\Exception $e) { if ($update->getType() != 'core') { diff --git a/src/Controller/Modals/LogBasic.php b/src/Controller/Modals/LogBasic.php new file mode 100644 index 000000000..c0896aacc --- /dev/null +++ b/src/Controller/Modals/LogBasic.php @@ -0,0 +1,46 @@ +. + * + * @Support + * @Email + * @Authors/Contributors: Sylvaner, Byackee, cyrilphoenix71, ColonelMoutarde, edgd1er, slobberbone, Astral0, DanoneKiD + */ + +namespace NextDom\Controller\Modals; + +use NextDom\Exceptions\CoreException; +use NextDom\Helpers\Render; + +/** + * Class LogBasic + * @package NextDom\Controller\Modals + */ +class LogBasic extends BaseAbstractModal +{ + /** + * Render backup log modal + * + * @return string + * @throws CoreException + */ + public static function get(): string + { + $pageData = []; + return Render::getInstance()->get('/modals/log.basic.html.twig', $pageData); + } + +} diff --git a/src/Enums/Common.php b/src/Enums/Common.php index 66075c1cd..611dfc0d9 100644 --- a/src/Enums/Common.php +++ b/src/Enums/Common.php @@ -43,11 +43,14 @@ class Common extends Enum const DATE = 'date'; const DATETIME = 'datetime'; const DEFAULT = 'default'; + const DESCRIPTION = 'description'; const DETAIL = 'detail'; + const DISABLE = 'disable'; const DISPLAY = 'display'; const DISPLAY_VALUE = 'display_value'; const END = 'end'; const EQLOGIC_ID = 'eqLogic_id'; + const ENABLE = 'enable'; const EVENT = 'event'; const FUNCTION = 'function'; const GENERIC_TYPE = 'generic_type'; @@ -82,6 +85,7 @@ class Common extends Enum const REPLY_CMD = 'reply_cmd'; const RESULT = 'result'; const SCENARIO_ID = 'scenario_id'; + const SCOPE = 'scope'; const SCHEDULE = 'schedule'; const START = 'start'; const STATE = 'state'; diff --git a/src/Enums/SQLField.php b/src/Enums/SQLField.php index d7a6834f1..97df03a0b 100644 --- a/src/Enums/SQLField.php +++ b/src/Enums/SQLField.php @@ -28,4 +28,5 @@ class SQLField extends Enum const LINK_TYPE = 'link_type'; const LINK_ID = 'link_id'; const LOGIN = 'login'; + const COUNT = 'count(*)'; } diff --git a/src/Enums/UpdateType.php b/src/Enums/UpdateType.php new file mode 100644 index 000000000..f3dc4e88e --- /dev/null +++ b/src/Enums/UpdateType.php @@ -0,0 +1,35 @@ +. + */ + +namespace NextDom\Enums; + +/** + * Class UpdateStatus + * + * Type of update in database + * + * @package NextDom\Enums + */ +class UpdateType extends Enum +{ + const ALL = 'ALL'; + const CORE = 'core'; + const OTHERS = 'others'; + const PLUGIN = 'plugin'; + const SCRIPT = 'script'; + const WIDGET = 'widget'; +} diff --git a/src/Helpers/ConsoleHelper.php b/src/Helpers/ConsoleHelper.php index 3d3447e3d..be56aa4b5 100644 --- a/src/Helpers/ConsoleHelper.php +++ b/src/Helpers/ConsoleHelper.php @@ -86,18 +86,30 @@ public static function enter() /** * Show ok message + * + * @param int $progress progress value */ - public static function ok() + public static function ok(int $progress = NULL) { - printf(" OK\n"); + if ($progress == NULL) { + printf(" OK\n"); + } else { + printf(" OK (" . $progress . "%%)\n"); + } } /** * Show not ok message + * + * @param int $progress progress value */ - public static function nok() + public static function nok(int $progress = NULL) { - printf(" Failure\n"); + if ($progress == NULL) { + printf(" Failure\n"); + } else { + printf(" Failure (" . $progress . "%%)\n"); + } } /** diff --git a/src/Helpers/DBHelper.php b/src/Helpers/DBHelper.php index 24e98f197..2e5384826 100755 --- a/src/Helpers/DBHelper.php +++ b/src/Helpers/DBHelper.php @@ -34,6 +34,7 @@ namespace NextDom\Helpers; +use NextDom\Enums\LogTarget; use NextDom\Exceptions\CoreException; /** @@ -219,6 +220,29 @@ public static function exec(string $query, array $params = []) return false; } + /** + * Generate IN params for query + * + * @param array $params + * + * @return bool|string + * + * @throws \Exception + */ + public static function getInParamFromArray($params) + { + if (count($params) > 0) { + $stringifiedParams = "'" . implode("', '", $params) . "'"; + preg_match_all('/^\'\w*\'(?:, \'\w*\')*$/', $stringifiedParams, $checkValidity); + if (count($checkValidity) > 0 && count($checkValidity[0]) === 1) { + return '(' . $stringifiedParams . ')'; + } + else { + LogHelper::addError(LogTarget::NEXTDOM, __('Bad SQL WHERE IN params ') . $stringifiedParams); + } + } + return false; + } /** * Begin transaction */ diff --git a/src/Managers/BackupManager.php b/src/Managers/BackupManager.php index 9715ae939..b7994d69b 100755 --- a/src/Managers/BackupManager.php +++ b/src/Managers/BackupManager.php @@ -93,38 +93,38 @@ public static function createBackup() NextDomHelper::event('begin_backup', true); ConsoleHelper::step("stopping NextDom (cron & scenario)"); NextDomHelper::stopSystem(true); - ConsoleHelper::ok(); + ConsoleHelper::ok(10); ConsoleHelper::step("starting plugin backup"); self::backupPlugins(); - ConsoleHelper::ok(); + ConsoleHelper::ok(20); ConsoleHelper::step("checking database integrity"); self::repairDB(); - ConsoleHelper::ok(); + ConsoleHelper::ok(30); ConsoleHelper::step("starting database backup"); self::createDBBackup($sqlPath); - ConsoleHelper::ok(); + ConsoleHelper::ok(40); ConsoleHelper::step("starting cache backup"); CacheManager::persist(); - ConsoleHelper::ok(); + ConsoleHelper::ok(50); ConsoleHelper::step("creating backup archive"); ConsoleHelper::enter(); self::createBackupArchive($backupPath, $sqlPath, $cachePath, LogTarget::BACKUP); - ConsoleHelper::ok(); + ConsoleHelper::ok(70); ConsoleHelper::step("rotating backup archives"); self::rotateBackups($backupDir); - ConsoleHelper::ok(); + ConsoleHelper::ok(80); ConsoleHelper::step("checking remote backup systems"); self::sendRemoteBackup($backupPath); - ConsoleHelper::ok(); + ConsoleHelper::ok(90); } catch (\Exception $e) { $status = "error"; - ConsoleHelper::nok(); + ConsoleHelper::nok(100); ConsoleHelper::error($e); LogHelper::addError(LogTarget::BACKUP, $e->getMessage()); } finally { ConsoleHelper::step("starting NextDom (cron & scenario)"); NextDomHelper::startSystem(); - ConsoleHelper::ok(); + ConsoleHelper::ok(100); NextDomHelper::event('end_backup'); ConsoleHelper::subTitle("end of backup procedure at " . date(DateFormat::FULL)); ConsoleHelper::subTitle("elapsed time " . (strtotime('now') - $startTime)); @@ -285,11 +285,13 @@ public static function createBackupArchive(string $outputPath, $sqlPath, $cacheP $roots = [NEXTDOM_DATA . '/data/', NEXTDOM_DATA . '/config/']; $pattern = NEXTDOM_DATA . '/'; self::addPathToArchive($roots, $pattern, $tar, $logFile); + ConsoleHelper::ok(55); // Backup plugins folder $roots = [NEXTDOM_ROOT . '/plugins/']; $pattern = NEXTDOM_ROOT . '/'; self::addPathToArchive($roots, $pattern, $tar, $logFile); + ConsoleHelper::ok(60); $dir = new \RecursiveDirectoryIterator(NEXTDOM_ROOT, \FilesystemIterator::SKIP_DOTS); // Flatten the recursive iterator, folders come before their files @@ -307,6 +309,7 @@ public static function createBackupArchive(string $outputPath, $sqlPath, $cacheP if ($fileInfo->isDir()) { $roots = [NEXTDOM_ROOT . '/' . $fileInfo->getFilename()]; self::addPathToArchive($roots, $pattern, $tar, $logFile); + ConsoleHelper::ok(65); } } } @@ -495,53 +498,53 @@ public static function restoreBackup($file = '') $file = self::getLastBackupFilePath($backupDir, "newest"); } ConsoleHelper::process("file used for restoration: " . $file); - ConsoleHelper::ok(); + ConsoleHelper::ok(10); ConsoleHelper::step("stopping Nextdom system..."); NextDomHelper::stopSystem(false); - ConsoleHelper::ok(); + ConsoleHelper::ok(20); ConsoleHelper::step("extracting backup archive..."); $tmpDir = self::extractArchive($file); - ConsoleHelper::ok(); + ConsoleHelper::ok(30); ConsoleHelper::step("restoring plugins..."); self::restorePlugins($tmpDir); - ConsoleHelper::ok(); + ConsoleHelper::ok(50); ConsoleHelper::step("restoring mysql database..."); self::restoreDatabase($tmpDir); - ConsoleHelper::ok(); + ConsoleHelper::ok(55); ConsoleHelper::step("importing Jeedom configuration..."); self::restoreJeedomConfig($tmpDir); - ConsoleHelper::ok(); + ConsoleHelper::ok(60); ConsoleHelper::step("restoring custom data...\n"); self::restoreCustomData($tmpDir, LogTarget::RESTORE); - ConsoleHelper::ok(); + ConsoleHelper::ok(65); ConsoleHelper::step("migrating data..."); MigrationHelper::migrate(LogTarget::RESTORE); - ConsoleHelper::ok(); + ConsoleHelper::ok(70); ConsoleHelper::step("starting nextdom system..."); NextDomHelper::startSystem(); - ConsoleHelper::ok(); + ConsoleHelper::ok(75); ConsoleHelper::step("updating system configuration..."); self::updateConfig(); - ConsoleHelper::ok(); + ConsoleHelper::ok(80); ConsoleHelper::step("checking system consistency..."); ConsistencyManager::checkConsistency(); - ConsoleHelper::ok(); + ConsoleHelper::ok(85); ConsoleHelper::step("init values..."); self::initValues(); - ConsoleHelper::ok(); + ConsoleHelper::ok(90); ConsoleHelper::step("clearing cache..."); self::clearCache(); - ConsoleHelper::ok(); + ConsoleHelper::ok(95); ConsoleHelper::step("restoring cache..."); self::restoreCache($tmpDir,LogTarget::RESTORE); - ConsoleHelper::ok(); + ConsoleHelper::ok(100); FileSystemHelper::rrmdir($tmpDir); NextDomHelper::event("end_restore"); ConsoleHelper::subTitle("end of restore procedure at " . date(DateFormat::FULL)); ConsoleHelper::subTitle("elapsed time " . (strtotime('now') - $startTime)); } catch (\Exception $e) { $status = "error"; - ConsoleHelper::nok(); + ConsoleHelper::nok(100); ConsoleHelper::error($e); LogHelper::addError(LogTarget::RESTORE, $e->getMessage()); if (true === is_dir($tmpDir)) { @@ -623,6 +626,7 @@ private static function restorePlugins($tmpDir) } } self::restorePublicPerms($pluginRoot); + ConsoleHelper::ok(40); $plugins = PluginManager::listPlugin(true); foreach ($plugins as $c_plugin) { diff --git a/src/Managers/UpdateManager.php b/src/Managers/UpdateManager.php index e37009545..d8297a7cf 100644 --- a/src/Managers/UpdateManager.php +++ b/src/Managers/UpdateManager.php @@ -33,10 +33,13 @@ namespace NextDom\Managers; +use NextDom\Enums\Common; use NextDom\Enums\DateFormat; use NextDom\Enums\LogTarget; use NextDom\Enums\NextDomObj; +use NextDom\Enums\SQLField; use NextDom\Enums\UpdateStatus; +use NextDom\Enums\UpdateType; use NextDom\Helpers\DBHelper; use NextDom\Helpers\FileSystemHelper; use NextDom\Helpers\LogHelper; @@ -90,8 +93,8 @@ public static function checkAllUpdate($filter = '', $findNewObjects = true) foreach ($updatesToCheckBySource as $source => $updates) { if (ConfigManager::byKey($source . '::enable') == 1) { $repoData = self::getRepoDataFromName($source); - if (array_key_exists('phpClass', $repoData)) { - $repoPhpClass = $repoData['phpClass']; + if (array_key_exists(Common::PHP_CLASS, $repoData)) { + $repoPhpClass = $repoData[Common::PHP_CLASS]; if (class_exists($repoPhpClass) && method_exists($repoPhpClass, 'checkUpdate')) { $repoPhpClass::checkUpdate($updates); } @@ -148,7 +151,7 @@ public static function findNewUpdateObject() } else { // Remove all update if plugin is removed $params = [ - 'type' => $pluginId, + Common::TYPE => $pluginId, ]; $sql = 'DELETE FROM ' . self::DB_CLASS_NAME . ' WHERE `type` = :type'; @@ -169,7 +172,7 @@ public static function findNewUpdateObject() */ public static function byTypeAndLogicalId($type, $logicalId) { - return static::getOneByClauses(['logicalId' => $logicalId, 'type' => $type]); + return static::getOneByClauses(['logicalId' => $logicalId, Common::TYPE => $type]); } /** @@ -183,7 +186,7 @@ public static function byTypeAndLogicalId($type, $logicalId) */ public static function byType($type) { - return static::getMultipleByClauses(['type' => $type]); + return static::getMultipleByClauses([Common::TYPE => $type]); } /** @@ -200,7 +203,7 @@ public static function all($filter = '') $params = []; $sql = static::getBaseSQL() . ' '; if ($filter != '') { - $params['type'] = $filter; + $params[Common::TYPE] = $filter; $sql .= 'WHERE `type` = :type '; } $sql .= 'ORDER BY FIELD(`status`, "update", "ok", "depreciated") ASC, FIELD(`type`, "plugin", "core") DESC, `name` ASC'; @@ -220,10 +223,10 @@ public static function getRepoDataFromName($name): array { $repoList = self::listRepo(); foreach ($repoList as $repoData) { - if (ucfirst($repoData['name']) == ucfirst($name)) { + if (ucfirst($repoData[Common::NAME]) == ucfirst($name)) { return [ - 'className' => str_replace(self::REPO_CLASS_PATH, '', $repoData['class']), - 'phpClass' => $repoData['class'] + Common::CLASS_NAME => str_replace(self::REPO_CLASS_PATH, '', $repoData[Common::CLASS_CODE]), + Common::PHP_CLASS => $repoData[Common::CLASS_CODE] ]; } } @@ -246,14 +249,14 @@ public static function listRepo(): array if (class_exists($fullNameClass) && is_subclass_of($fullNameClass, '\\NextDom\\Interfaces\\BaseRepo')) { $repoCode = strtolower(str_replace('Repo', '', $repoClassName)); $result[$repoCode] = [ - 'name' => $fullNameClass::$_name, - 'class' => $fullNameClass, - 'configuration' => $fullNameClass::$_configuration, - 'scope' => $fullNameClass::$_scope, - 'description' => $fullNameClass::$_description, - 'icon' => $fullNameClass::$_icon + Common::NAME => $fullNameClass::$_name, + Common::CLASS_CODE => $fullNameClass, + Common::CONFIGURATION => $fullNameClass::$_configuration, + Common::SCOPE => $fullNameClass::$_scope, + Common::DESCRIPTION => $fullNameClass::$_description, + Common::ICON => $fullNameClass::$_icon ]; - $result[$repoCode]['enable'] = ConfigManager::byKey($repoCode . '::enable'); + $result[$repoCode][Common::ENABLE] = ConfigManager::byKey($repoCode . '::enable'); } } return $result; @@ -271,16 +274,16 @@ public static function listRepo(): array public static function repoById($id) { $repoClassData = self::getRepoDataFromName($id); - $phpClass = $repoClassData['phpClass']; + $phpClass = $repoClassData[Common::PHP_CLASS]; $result = [ - 'name' => $phpClass::$_name, - 'class' => $repoClassData['className'], - 'configuration' => $phpClass::$_configuration, - 'scope' => $phpClass::$_scope, - 'description' => $phpClass::$_description, - 'icon' => $phpClass::$_icon + Common::NAME => $phpClass::$_name, + Common::CLASS_CODE => $repoClassData[Common::CLASS_NAME], + Common::CONFIGURATION => $phpClass::$_configuration, + Common::SCOPE => $phpClass::$_scope, + Common::DESCRIPTION => $phpClass::$_description, + Common::ICON => $phpClass::$_icon ]; - $result['enable'] = ConfigManager::byKey($id . '::enable'); + $result[Common::ENABLE] = ConfigManager::byKey($id . '::enable'); return $result; } @@ -308,7 +311,11 @@ public static function updateAll(string $filter = '') $updatesList = self::byType($filter); } if (is_array($updatesList)) { + $progressIncrement = 100 / $updatesList.length; + $progressLoop = -1; foreach ($updatesList as $update) { + $progressLoop += 1; + $update->setProgressParams($progressIncrement / 4, $progressLoop * $progressIncrement); if ($update->getStatus() != UpdateStatus::HOLD && $update->getStatus() == UpdateStatus::UPDATE && $update->getType() != 'core') { try { $update->doUpdate(); @@ -334,7 +341,7 @@ public static function updateAll(string $filter = '') */ public static function byStatus($status) { - return static::getMultipleByClauses(['status' => $status]); + return static::getMultipleByClauses([Common::STATUS => $status]); } /** @@ -348,7 +355,7 @@ public static function byStatus($status) */ public static function byLogicalId($logicalId) { - return static::getOneByClauses(['logicalId' => $logicalId]); + return static::getOneByClauses([Common::LOGICAL_ID => $logicalId]); } /** @@ -363,20 +370,39 @@ public static function byLogicalId($logicalId) public static function nbNeedUpdate($filter = '') { $params = [ - 'status' => 'update', - 'configuration' => '%"doNotUpdate":"1"%' + Common::STATUS => 'update', + Common::CONFIGURATION => '%"doNotUpdate":"1"%' ]; - $sql = 'SELECT count(*) - FROM ' . self::DB_CLASS_NAME . ' - WHERE `status` = :status - AND `configuration` NOT LIKE :configuration'; - if ($filter != '') { - $params['type'] = $filter; - $sql .= ' AND `type` = :type'; + if (is_array($filter)) { + $likeParams = DBHelper::getInParamFromArray($filter); + if ($params) { + $sql = 'SELECT `type`, SUM(CASE WHEN status = :status AND configuration NOT LIKE :configuration THEN 1 ELSE 0 END) AS count + FROM ' . self::DB_CLASS_NAME . ' + WHERE `type` IN ' . $likeParams . ' + GROUP BY `type`'; + $result = DBHelper::getAll($sql, $params); + $sql = 'SELECT SUM(CASE WHEN status = :status AND configuration NOT LIKE :configuration THEN 1 ELSE 0 END) AS count + FROM ' . self::DB_CLASS_NAME . ' + WHERE `type` NOT IN ' . $likeParams . ' + GROUP BY `type`'; + $othersCount = DBHelper::getOne($sql, $params); + array_push($result, ['type' => 'others', 'count' => intval($othersCount['count'])]); + return $result; + } } - - $result = DBHelper::getOne($sql, $params); - return $result['count(*)']; + else { + $sql = 'SELECT count(*) + FROM ' . self::DB_CLASS_NAME . ' + WHERE `status` = :status + AND `configuration` NOT LIKE :configuration'; + if ($filter != '') { + $params[Common::TYPE] = $filter; + $sql .= ' AND `type` = :type'; + } + $result = DBHelper::getOne($sql, $params); + return $result[SQLField::COUNT]; + } + return false; } /** diff --git a/src/Model/Entity/Listener.php b/src/Model/Entity/Listener.php index 9a63177c7..7e74d0ef2 100644 --- a/src/Model/Entity/Listener.php +++ b/src/Model/Entity/Listener.php @@ -135,7 +135,7 @@ public function execute($_event, $_value, $_datetime = '') if (class_exists($targetClass) && method_exists($targetClass, $function)) { $targetClass::$function($option); } else { - LogHelper::addDebug(LogTarget::LISTENER, __('[Erreur] Classe ou fonction non trouvée ') . $this->getName()); + LogHelper::addDebug(LogTarget::LISTENER, __('[Erreur] Classe ou fonction non trouvée : ') . $this->getName()); $this->remove(); return; } diff --git a/src/Model/Entity/Update.php b/src/Model/Entity/Update.php index f1358cd2d..44a0043e9 100644 --- a/src/Model/Entity/Update.php +++ b/src/Model/Entity/Update.php @@ -49,6 +49,8 @@ class Update extends BaseEntity { const TABLE_NAME = NextDomObj::UPDATE; + var $progressInc = 0; + var $progressStart = 0; use ConfigurationEntity, LogicalIdEntity, NameEntity, RefreshEntity, TypeEntity; @@ -156,7 +158,7 @@ public function doUpdate() $info = $class::downloadObject($this); if ($info['path'] !== false) { $tmp = $info['path']; - LogHelper::addAlert(LogTarget::UPDATE, __("OK\n")); + LogHelper::addAlert(LogTarget::UPDATE, __("OK" . $progressStart + (2*$progressInc) ."\n")); if (!file_exists($tmp)) { throw new CoreException(__('Impossible de trouver le fichier zip : ') . $this->getConfiguration('path')); @@ -200,7 +202,7 @@ public function doUpdate() if (file_exists($cibDir)) { rrmdir($cibDir); } - LogHelper::addAlert(LogTarget::UPDATE, __("OK\n")); + LogHelper::addAlert(LogTarget::UPDATE, __("OK" . $progressStart + (3*$progressInc) ."\n")); } else { throw new CoreException(__('Impossible de décompresser l\'archive zip : ') . $tmp . ' => ' . Utils::getZipErrorMessage($res)); } @@ -236,7 +238,7 @@ public function preInstallUpdate() if (is_object($plugin)) { LogHelper::addAlert(LogTarget::UPDATE, __('Action de pré-update...')); $plugin->callInstallFunction('pre_update'); - LogHelper::addAlert(LogTarget::UPDATE, __("OK\n")); + LogHelper::addAlert(LogTarget::UPDATE, __("OK" . $progressStart + $progressInc ."\n")); } } catch (\Exception $e) { @@ -269,7 +271,7 @@ public function postInstallUpdate($informations) $this->setLocalVersion($informations['localVersion']); } $this->save(); - LogHelper::addAlert(LogTarget::UPDATE, __("OK\n")); + LogHelper::addAlert(LogTarget::UPDATE, __("OK" . $progressStart + (4*$progressInc) ."\n")); } /** @@ -477,4 +479,10 @@ public function setStatus($_status) $this->status = $_status; return $this; } + + public function setProgressParams($Increment,$Start) + { + $progressInc = $Increment; + $progressStart = $Start; + } } diff --git a/src/modals_routes.yml b/src/modals_routes.yml index 287ccfe30..eee434838 100644 --- a/src/modals_routes.yml +++ b/src/modals_routes.yml @@ -78,6 +78,10 @@ interact.test: path: 'interact.test' controller: NextDom\Controller\Modals\InteractTest::get condition: 'admin' +log.basic: + path: 'backup.log' + controller: NextDom\Controller\Modals\LogBasic::get + condition: 'admin' log.display: path: 'log.display' controller: NextDom\Controller\Modals\LogDisplay::get diff --git a/tests/launch_php_tests.py b/tests/launch_php_tests.py index 0199b1b18..baabc8f0a 100755 --- a/tests/launch_php_tests.py +++ b/tests/launch_php_tests.py @@ -25,8 +25,6 @@ def php_tests(): container_name, 'apt-get install -y php-phpdbg > /dev/null 2>&1') return_code = exec_command_in_container( container_name, 'bash -c "cd /var/www/html && export PANTHER_NO_SANDBOX=1 && export PANTHER_CHROME_ARGUMENTS=\"--disable-dev-shm-usage\" && phpdbg -d memory_limit=-1 -qrr phpunit --configuration tests/phpunit_tests/phpunit.xml --testsuite AllTests"') # pylint: disable=line-too-long -# return_code = exec_command_in_container( -# container_name, 'bash -c "cd /var/www/html && phpdbg -d memory_limit=-1 -qrr phpunit --configuration tests/phpunit_tests/phpunit.xml --testsuite AllTestsNoGui"') # pylint: disable=line-too-long copy_file_from_container(container_name, '/var/www/html/tests/coverage/clover.xml', 'coverage/') # pylint: disable=line-too-long copy_file_from_container(container_name, '/var/www/html/tests/coverage/junitlog.xml', diff --git a/tests/phpunit_tests/Managers/UpdateManagerTest.php b/tests/phpunit_tests/Managers/UpdateManagerTest.php index fc661bf13..d1cb20fb9 100644 --- a/tests/phpunit_tests/Managers/UpdateManagerTest.php +++ b/tests/phpunit_tests/Managers/UpdateManagerTest.php @@ -28,6 +28,12 @@ public static function tearDownAfterClass(): void DBHelper::exec('DELETE FROM `update` WHERE id > 2'); } + public function setUp(): void + { + DBHelper::exec('UPDATE `update` SET configuration = \'{"doNotUpdate":"1"}\''); + DBHelper::exec('UPDATE `update` SET status = \'ok\' WHERE id = 1'); + } + public function testFindNewUpdateObject() { UpdateManager::findNewUpdateObject(); @@ -111,4 +117,74 @@ public function testListRepo() $this->assertEquals('\NextDom\Repo\RepoNextDom', $repoList['nextdom']['class']); $this->assertEquals('input', $repoList['samba']['configuration']['configuration']['backup::ip']['type']); } + + public function testNbUpdateWithoutFilter() + { + $this->assertEquals(0, UpdateManager::nbNeedUpdate()); + $coreUpdate = UpdateManager::byId(1); + $coreUpdate->setConfiguration('doNotUpdate', 0); + $coreUpdate->save(); + $this->assertEquals(0, UpdateManager::nbNeedUpdate()); + $pluginUpdate = UpdateManager::byId(2); + $pluginUpdate->setStatus('update'); + $pluginUpdate->save(); + $this->assertEquals(0, UpdateManager::nbNeedUpdate()); + $pluginUpdate->setConfiguration('doNotUpdate', 0); + $pluginUpdate->save(); + $this->assertEquals(1, UpdateManager::nbNeedUpdate()); + } + + public function testNbUpdateWithTextFilter() + { + $this->assertEquals(0, UpdateManager::nbNeedUpdate('core')); + $coreUpdate = UpdateManager::byId(1); + $coreUpdate->setConfiguration('doNotUpdate', 0); + $coreUpdate->save(); + $this->assertEquals(0, UpdateManager::nbNeedUpdate('core')); + $pluginUpdate = UpdateManager::byId(2); + $pluginUpdate->setStatus('update'); + $pluginUpdate->save(); + $this->assertEquals(0, UpdateManager::nbNeedUpdate('plugin')); + $pluginUpdate->setConfiguration('doNotUpdate', 0); + $pluginUpdate->save(); + $this->assertEquals(1, UpdateManager::nbNeedUpdate('plugin')); + } + + public function testNbUpdateWithArrayFilter() + { + $result = UpdateManager::nbNeedUpdate(['core']); + $this->assertEquals('core', $result[0]['type']); + $this->assertEquals(0, $result[0]['count']); + $this->assertEquals('others', $result[1]['type']); + $this->assertEquals(0, $result[1]['count']); + $coreUpdate = UpdateManager::byId(1); + $coreUpdate->setConfiguration('doNotUpdate', 0); + $coreUpdate->save(); + $result = UpdateManager::nbNeedUpdate(['core', 'plugin']); + $this->assertEquals('core', $result[0]['type']); + $this->assertEquals('plugin', $result[1]['type']); + $this->assertEquals(0, $result[0]['count']); + $this->assertEquals(0, $result[1]['count']); + $this->assertEquals('others', $result[2]['type']); + $this->assertEquals(0, $result[2]['count']); + $pluginUpdate = UpdateManager::byId(2); + $pluginUpdate->setStatus('update'); + $pluginUpdate->save(); + $coreUpdate->setStatus('update'); + $coreUpdate->save(); + $result = UpdateManager::nbNeedUpdate(['plugin']); + $this->assertEquals('plugin', $result[0]['type']); + $this->assertEquals('others', $result[1]['type']); + $this->assertEquals(0, $result[0]['count']); + $this->assertEquals(1, $result[1]['count']); + $pluginUpdate->setConfiguration('doNotUpdate', 0); + $pluginUpdate->save(); + $result = UpdateManager::nbNeedUpdate(['core', 'plugin']); + $this->assertEquals('core', $result[0]['type']); + $this->assertEquals('plugin', $result[1]['type']); + $this->assertEquals('others', $result[2]['type']); + $this->assertEquals(1, $result[0]['count']); + $this->assertEquals(1, $result[1]['count']); + $this->assertEquals(0, $result[2]['count']); + } } \ No newline at end of file diff --git a/views/desktop/tools/backup.html.twig b/views/desktop/tools/backup.html.twig index e02856d53..e48d72618 100644 --- a/views/desktop/tools/backup.html.twig +++ b/views/desktop/tools/backup.html.twig @@ -37,17 +37,31 @@
+ +
- -
-
-

-            
-
diff --git a/views/desktop/tools/update-view.html.twig b/views/desktop/tools/update-view.html.twig index e1edaf8dd..3ebe542b5 100644 --- a/views/desktop/tools/update-view.html.twig +++ b/views/desktop/tools/update-view.html.twig @@ -38,7 +38,6 @@ -
-
-

-        
-
-