diff --git a/web/includes/actions/montage.php b/web/includes/actions/montage.php index c4b55b2af..18ebb2b68 100644 --- a/web/includes/actions/montage.php +++ b/web/includes/actions/montage.php @@ -21,9 +21,9 @@ require_once('includes/MontageLayout.php'); if ( isset($_REQUEST['object']) ) { if ( $_REQUEST['object'] == 'MontageLayout' ) { - if ($action == 'Save') { - $Layout = null; + $Layout = null; + if ($action == 'Save') { # Name is only populated when creating a new layout if ( $_REQUEST['Name'] != '' ) { $Layout = new ZM\MontageLayout(); @@ -44,7 +44,35 @@ if ( isset($_REQUEST['object']) ) { ZM\Warning('Need System permissions to edit layouts'); return; } - } // end if save + } else if ($action == 'Delete') { // end if save + if ( isset($_REQUEST['zmMontageLayout']) ) { + $Layout = new ZM\MontageLayout($_REQUEST['zmMontageLayout']); + } else { + ZM\Warning('Name of layout to be deleted is not specified'); + return; + } + + if (canEdit('System')) { + if ($Layout->Id()) { + $Layout->delete(); + zm_session_start(); + unset($_SESSION["zmMontageLayout"]); + $_SESSION['zmMontageLayout'] = ''; + session_write_close(); + unset($_COOKIE['zmMontageLayout']); + zm_setcookie('zmMontageLayout', '', array('expires'=>time()-3600*24)); //!!! After this JS still sees cookies, strange !!! + $redirect = '?view=montage'; + } else { + ZM\Warning('Layout Id=' . $_REQUEST['zmMontageLayout'] . ' not found for delete'); + $redirect = '?view=montage'; + } + } else { + ZM\Warning('Need System permissions to delete layouts'); + $redirect = '?view=montage'; + } + } else {// end if delete + ZM\Warning("Unsupported action $action in montage"); + } // end if else } # end if isset($_REQUEST['object'] ) } # end if isset($_REQUEST['object'] ) ?> diff --git a/web/lang/en_gb.php b/web/lang/en_gb.php index 3a7b07343..9f15884f3 100644 --- a/web/lang/en_gb.php +++ b/web/lang/en_gb.php @@ -220,6 +220,7 @@ $SLANG = array( 'ConfirmDeleteControl' => 'Warning, deleting a control will reset all monitors that use it to be uncontrollable.

Are you sure you wish to delete?', 'ConfirmDeleteDevices' => 'Are you sure you wish to delete the selected devices?', 'ConfirmDeleteEvents' => 'Are you sure you wish to delete the selected events?', + 'ConfirmDeleteLayout' => 'Are you sure you wish to delete current layout?', 'ConfirmDeleteTitle' => 'Delete Confirmation', 'ConfirmPassword' => 'Confirm Password', 'ConfirmUnarchiveEvents'=> 'Are you sure you wish to unarchive the selected events?', diff --git a/web/lang/fr_fr.php b/web/lang/fr_fr.php index a5a0453b4..2966b787f 100644 --- a/web/lang/fr_fr.php +++ b/web/lang/fr_fr.php @@ -226,6 +226,7 @@ $SLANG = array( 'Config' => 'Config', 'ConfiguredFor' => 'Configuré pour', 'ConfirmDeleteEvents' => 'Etes-vous sûr de vouloir effacer le(s) événement(s) sélectionné(s)?', + 'ConfirmDeleteLayout' => 'Êtes-vous sûr de vouloir supprimer la mise en page actuelle ?', 'ConfirmPassword' => 'Répéter mot de passe', 'ConjAnd' => 'et', 'ConjOr' => 'ou', diff --git a/web/lang/ru_ru.php b/web/lang/ru_ru.php index 55d2b4264..a922f91ba 100644 --- a/web/lang/ru_ru.php +++ b/web/lang/ru_ru.php @@ -246,6 +246,7 @@ $SLANG = array( 'Config' => 'Конфигурация', 'ConfiguredFor' => 'настроен на', 'ConfirmDeleteEvents' => 'Вы действительно хотите удалить выбранные события?', + 'ConfirmDeleteLayout' => 'Вы действительно хотите удалить текущий шаблон?', 'ConfirmPassword' => 'Подтвердите пароль', 'ConfirmUnarchiveEvents'=> 'Вы уверены, что хотите удалить из архива выбранные события?', 'ConjAnd' => 'и', diff --git a/web/skins/classic/views/js/montage.js b/web/skins/classic/views/js/montage.js index c587db670..95103f8c8 100644 --- a/web/skins/classic/views/js/montage.js +++ b/web/skins/classic/views/js/montage.js @@ -53,7 +53,7 @@ function stringToNumber(str) { } function isPresetLayout(name) { - return (( name=='Freeform' || name=='1 Wide' || name=='2 Wide' || name=='3 Wide' || name=='4 Wide' || name=='6 Wide' || name=='8 Wide' || name=='12 Wide' || name=='16 Wide' ) ? true : false); + return ((ZM_PRESET_LAYOUT_NAMES.indexOf(name) != -1) ? true : false); } function getCurrentNameLayout() { @@ -137,6 +137,7 @@ function selectLayout(new_layout_id) { } if (isPresetLayout(nameLayout)) { //PRESET + document.getElementById("btnDeleteLayout").setAttribute('disabled', ''); setSelected(document.getElementById("ratio"), getCookie('zmMontageRatioForAll')); changeRatioForAll(); @@ -158,6 +159,7 @@ function selectLayout(new_layout_id) { } initGridStack(); } else { //CUSTOM + document.getElementById("btnDeleteLayout").removeAttribute('disabled'); for (let i = 0, length = monitors.length; i < length; i++) { const monitor = monitors[i]; // Need to clear the current positioning, and apply the new @@ -409,6 +411,7 @@ function save_layout(button) { Positions['monitorRatio'][stringToNumber(this.id)] = getSelected(this); }); form.Positions.value = JSON.stringify(Positions, null, ' '); + $j('#action').attr('value', 'Save'); form.submit(); } // end function save_layout @@ -436,6 +439,53 @@ function cancel_layout(button) { selectLayout(); } +function delete_layout(button) { + if (!canEdit.System) { + enoperm(); + return; + } + if (!document.getElementById('deleteConfirm')) { + // Load the delete confirmation modal into the DOM +// $j.getJSON(thisUrl + '?request=modal&modal=delconfirm') + $j.getJSON(thisUrl + '?request=modal&modal=delconfirm', { + key: 'ConfirmDeleteLayout', + }) + .done(function(data) { + insertModalHtml('deleteConfirm', data.html); + manageDelConfirmModalBtns(); + $j('#deleteConfirm').modal('show'); + }) + .fail(function(jqXHR) { + console.log('error getting delconfirm', jqXHR); + logAjaxFail(jqXHR); + }); + return; + } else { + $j('#deleteConfirm').modal('show'); + } +} // end function delete_layout + +// Manage the DELETE CONFIRMATION modal button +function manageDelConfirmModalBtns() { + document.getElementById('delConfirmBtn').addEventListener('click', function onDelConfirmClick(evt) { + document.getElementById('delConfirmBtn').disabled = true; // prevent double click + if (!canEdit.Monitors) { + enoperm(); + return; + } + evt.preventDefault(); + + const form = $j('#btnDeleteLayout')[0].form; + $j('#action').attr('value', 'Delete'); + form.submit(); + }); + + // Manage the CANCEL modal button + document.getElementById('delCancelBtn').addEventListener('click', function onDelCancelClick(evt) { + $j('#deleteConfirm').modal('hide'); + }); +} + function reloadWebSite(ndx) { document.getElementById('imageFeed'+ndx).innerHTML = document.getElementById('imageFeed'+ndx).innerHTML; } @@ -656,9 +706,9 @@ function initPage() { $j("#flipMontageHeader").slideToggle("fast"); $j("#hdrbutton").toggleClass('glyphicon-menu-down').toggleClass('glyphicon-menu-up'); } - if (getCookie('zmMontageLayout')) { - $j('#zmMontageLayout').val(getCookie('zmMontageLayout')); - } +// if (getCookie('zmMontageLayout')) { //This is implemented in montage.php And the cookies may contain the number of a non-existent Layouts!!! +// $j('#zmMontageLayout').val(getCookie('zmMontageLayout')); +// } $j(".grid-monitor").hover( //Displaying "Scale" and other buttons at the top of the monitor image diff --git a/web/skins/classic/views/montage.php b/web/skins/classic/views/montage.php index 9ef9dc97c..56852e958 100644 --- a/web/skins/classic/views/montage.php +++ b/web/skins/classic/views/montage.php @@ -60,6 +60,18 @@ $monitorStatusPositon = array( $monitorStatusPositonSelected = 'outsideImgBottom'; +$presetLayoutsNames = array( //Order matters! + 'Freeform', + '1 Wide', + '2 Wide', + '3 Wide', + '4 Wide', + '6 Wide', + '8 Wide', + '12 Wide', + '16 Wide' +); + if (isset($_REQUEST['monitorStatusPositonSelected'])) { $monitorStatusPositonSelected = $_REQUEST['monitorStatusPositonSelected']; } else if (isset($_COOKIE['zmMonitorStatusPositonSelected'])) { @@ -69,16 +81,30 @@ if (isset($_REQUEST['monitorStatusPositonSelected'])) { $layouts = ZM\MontageLayout::find(NULL, array('order'=>"lower('Name')")); $layoutsById = array(); $FreeFormLayoutId = 0; + +/* Create an array "Name"=>"Id" to make it easier to find IDs by name*/ +$arrNameId = array(); +foreach ($layouts as $l) { + $arrNameId[$l->Name()] = $l->Id(); +} + +/* Fill with preinstalled Layouts. They should always come first */ +foreach ($presetLayoutsNames as $name) { + if (array_key_exists($name, $arrNameId)) // Layout may be missing in BD (rare case during update process) + $layoutsById[$arrNameId[$name]] = $name; //We will only assign a name, which is necessary for the sorting order. We will replace it with an object in the next loop. +} + +/* For some reason $layouts is already sorted by ID and requires analysis. But just in case, we will sort by ID */ +uasort($layouts, function($a, $b) { + return $a->Id <=> $b->Id; +}); + +/* Add custom Layouts & assign objects instead of names for preset Layouts */ foreach ( $layouts as $l ) { if ( $l->Name() == 'Freeform' ) { $FreeFormLayoutId = $l->Id(); - $layoutsById[$l->Id()] = $l; - break; } -} -foreach ( $layouts as $l ) { - if ( $l->Name() != 'Freeform' ) - $layoutsById[$l->Id()] = $l; + $layoutsById[$l->Id()] = $l; } zm_session_start(); @@ -173,30 +199,20 @@ foreach ($displayMonitors as &$row) { } } # end foreach Monitor -if (!$layout_id) { +if (!$layout_id || !is_numeric($layout_id) || !isset($layoutsById[$layout_id])) { $default_layout = ''; - if (!$default_layout) { - if ((count($monitors) > 5) and (count($monitors)%5 == 0)) { - $default_layout = '5 Wide'; - } else if ((count($monitors) > 4) and (count($monitors)%4 == 0)) { - $default_layout = '4 Wide'; - } else if (count($monitors)%3 == 0) { - $default_layout = '3 Wide'; - } else { - $default_layout = '2 Wide'; - } - } - foreach ($layouts as $l) { - if ($l->Name() == $default_layout) { - $layout_id = $l->Id(); - } + if (count($monitors) > 6) { + $default_layout = '6 Wide'; + } else if (count($monitors) > 4) { + $default_layout = '4 Wide'; + } else { + $default_layout = '2 Wide'; } + $layout_id = $arrNameId[$default_layout]; } -$Layout = ''; -$Positions = ''; + if ( $layout_id and is_numeric($layout_id) and isset($layoutsById[$layout_id]) ) { - $Layout = $layoutsById[$layout_id]; - $Positions = json_decode($Layout->Positions(), true); + } else { ZM\Debug('Layout not found'); } @@ -242,7 +258,7 @@ if (canView('System')) {
- + @@ -250,17 +266,17 @@ if (canView('System')) { - 'ratio', 'data-on-change'=>'changeRatioForAll', 'class'=>'chosen')); ?> + 'ratio', 'data-on-change'=>'changeRatioForAll', 'class'=>'chosen')); ?> -