diff --git a/web/ajax/events.php b/web/ajax/events.php index 7b852c559..16c777ebf 100644 --- a/web/ajax/events.php +++ b/web/ajax/events.php @@ -16,10 +16,10 @@ if ( canEdit('Events') ) { switch ( $_REQUEST['action'] ) { case 'archive' : case 'unarchive' : - $archiveVal = ($_REQUEST['action'] == 'archive')?1:0; + $archiveVal = ($_REQUEST['action'] == 'archive') ? 1 : 0; dbQuery( 'UPDATE Events SET Archived = ? WHERE Id = ?', - array($archiveVal, $_REQUEST['id']) + array($archiveVal, $eid) ); break; case 'delete' : diff --git a/web/ajax/modal.php b/web/ajax/modal.php index 3b204495c..8f5cb8ac9 100644 --- a/web/ajax/modal.php +++ b/web/ajax/modal.php @@ -25,6 +25,16 @@ switch ( $modal ) { if ( empty($_REQUEST['ohndx']) ) ajaxError('Option Help Index Not Provided'); $data['html'] = getOptionHelpHTML($_REQUEST['ohndx'], $OLANG); break; + case 'enoperm' : + $data['html'] = getENoPermHTML(); + break; + case 'delconfirm' : + $data['html'] = getDelConfirmHTML(); + break; + case 'storage' : + if ( !isset($_REQUEST['id']) ) ajaxError('Storage Id Not Provided'); + $data['html'] = getStorageModalHTML($_REQUEST['id']); + break; default : // Maybe don't need both ZM\Warning('Unknown modal '.$modal); diff --git a/web/ajax/stats.php b/web/ajax/stats.php new file mode 100644 index 000000000..3789ff448 --- /dev/null +++ b/web/ajax/stats.php @@ -0,0 +1,24 @@ + diff --git a/web/includes/actions/storage.php b/web/includes/actions/storage.php index 49b5de3de..69ebfae0b 100644 --- a/web/includes/actions/storage.php +++ b/web/includes/actions/storage.php @@ -24,7 +24,7 @@ if ( !canEdit('System') ) { return; } -if ( $action == 'Save' ) { +if ( $action == 'save' ) { $storage = new ZM\Storage($_REQUEST['id']); $changes = $storage->changes($_REQUEST['newStorage']); @@ -33,7 +33,7 @@ if ( $action == 'Save' ) { $storage->save($changes); $refreshParent = true; } - $view = 'none'; + $redirect = '?view=options&tab=storage'; } else { ZM\Error("Unknown action $action in saving Storage"); } diff --git a/web/skins/classic/includes/functions.php b/web/skins/classic/includes/functions.php index c2fc0c93a..8facb1f80 100644 --- a/web/skins/classic/includes/functions.php +++ b/web/skins/classic/includes/functions.php @@ -790,6 +790,232 @@ function getOptionHelpHTML($optionHelpIndex, $OLANG) { return $result; } +// Return an Error No Permissions Modal +function getENoPermHTML() { + $result = ''; + + $result .= ''.PHP_EOL; + + return $result; +} + +function getStatsTableHTML($eid, $fid, $row='') { + if ( !canView('Events') ) return; + $result = ''; + + $sql = 'SELECT S.*,E.*,Z.Name AS ZoneName,Z.Units,Z.Area,M.Name AS MonitorName FROM Stats AS S LEFT JOIN Events AS E ON S.EventId = E.Id LEFT JOIN Zones AS Z ON S.ZoneId = Z.Id LEFT JOIN Monitors AS M ON E.MonitorId = M.Id WHERE S.EventId = ? AND S.FrameId = ? ORDER BY S.ZoneId'; + $stats = dbFetchAll( $sql, NULL, array( $eid, $fid ) ); + + $result .= ''.PHP_EOL; + $result .= ''.PHP_EOL; + $result .= ''.PHP_EOL; + $result .= ''.PHP_EOL; + $result .= ''.PHP_EOL; + $result .= ''.PHP_EOL; + $result .= ''.PHP_EOL; + $result .= ''.PHP_EOL; + $result .= ''.PHP_EOL; + $result .= ''.PHP_EOL; + $result .= ''.PHP_EOL; + $result .= ''.PHP_EOL; + $result .= ''.PHP_EOL; + $result .= ''.PHP_EOL; + + $result .= ''.PHP_EOL; + + if ( count($stats) ) { + foreach ( $stats as $stat ) { + $result .= ''.PHP_EOL; + $result .= ''.PHP_EOL; + $result .= ''.PHP_EOL; + $result .= ''.PHP_EOL; + $result .= ''.PHP_EOL; + $result .= ''.PHP_EOL; + $result .= ''.PHP_EOL; + + if ( $stat['Blobs'] > 1 ) { + $result .= ''.PHP_EOL; + } else { + $result .= ''.PHP_EOL; + } + + $result .= ''.PHP_EOL; + $result .= ''.PHP_EOL; + } + } else { + $result .= ''.PHP_EOL; + $result .= ''.PHP_EOL; + $result .= ''.PHP_EOL; + } + + $result .= ''.PHP_EOL; + $result .= '
' .translate('Zone'). '' .translate('PixelDiff'). '' .translate('AlarmPx'). '' .translate('FilterPx'). '' .translate('BlobPx'). '' .translate('Blobs'). '' .translate('BlobSizes'). '' .translate('AlarmLimits'). '' .translate('Score'). '
' .validHtmlStr($stat['ZoneName']). '' .validHtmlStr($stat['PixelDiff']). '' .sprintf( "%d (%d%%)", $stat['AlarmPixels'], (100*$stat['AlarmPixels']/$stat['Area']) ). '' .sprintf( "%d (%d%%)", $stat['FilterPixels'], (100*$stat['FilterPixels']/$stat['Area']) ).'' .sprintf( "%d (%d%%)", $stat['BlobPixels'], (100*$stat['BlobPixels']/$stat['Area']) ). '' .validHtmlStr($stat['Blobs']). '' .sprintf( "%d-%d (%d%%-%d%%)", $stat['MinBlobSize'], $stat['MaxBlobSize'], (100*$stat['MinBlobSize']/$stat['Area']), (100*$stat['MaxBlobSize']/$stat['Area']) ). '' .sprintf( "%d (%d%%)", $stat['MinBlobSize'], 100*$stat['MinBlobSize']/$stat['Area'] ). '' .validHtmlStr($stat['MinX'].",".$stat['MinY']."-".$stat['MaxX'].",".$stat['MaxY']). '' .$stat['Score']. '
' .translate('NoStatisticsRecorded'). '
'.PHP_EOL; + + return $result; +} + +// This is the HTML representing the Delete confirmation modal on the Events page +function getDelConfirmHTML() { + $result = ''; + + $result .= ''.PHP_EOL; + + return $result; +} + +function getStorageModalHTML($sid) { + $result = ''; + $null = ''; + $checked = 'checked="checked"'; + + if ( !canEdit('System') ) return; + + require_once('includes/Server.php'); + require_once('includes/Storage.php'); + + if ( $_REQUEST['id'] ) { + if ( !($newStorage = ZM\Storage::find_one(array('Id'=>$sid)) ) ) { + // Perhaps do something different here, rather than return nothing + return; + } + } else { + $newStorage = new ZM\Storage(); + $newStorage->Name(translate('NewStorage')); + } + + $type_options = array( 'local' => translate('Local'), 's3fs' => translate('s3fs') ); + $scheme_options = array( + 'Deep' => translate('Deep'), + 'Medium' => translate('Medium'), + 'Shallow' => translate('Shallow'), + ); + + $servers = ZM\Server::find( null, array('order'=>'lower(Name)') ); + $ServersById = array(); + foreach ( $servers as $S ) { + $ServersById[$S->Id()] = $S; + } + + // We have to manually insert the csrf key into the form when using a modal generated via ajax call + if ( isset($GLOBALS['csrf']['key']) ) { + $csrf_input = ''.PHP_EOL; + } else { + $csrf_input = ''; + } + + $result .= ''.PHP_EOL; + + return $result; +} + function xhtmlFooter() { global $css; global $cspNonce; diff --git a/web/skins/classic/js/skin.js b/web/skins/classic/js/skin.js index 92e264831..bdeeb6a63 100644 --- a/web/skins/classic/js/skin.js +++ b/web/skins/classic/js/skin.js @@ -416,6 +416,7 @@ if ( currentView != 'none' && currentView != 'login' ) { .done(setNavBar) .fail(function(jqxhr, textStatus, error) { console.log("Request Failed: " + textStatus + ", " + error); + console.log("Response Text: " + jqxhr.responseText); if ( textStatus != "timeout" ) { // The idea is that this should only fail due to auth, so reload the page // which should go to login if it can't stay logged in. @@ -711,7 +712,33 @@ function bwClickFunction() { function reminderClickFunction() { $j("#dropdown_reminder a").click(function() { var option = $j(this).data('pdsa-dropdown-val'); - $j.getJSON(thisUrl + '?view=version&action=version&option=' + option); - window.location.reload(true); //Do a full refresh to update ZM_DYN_LAST_VERSION + $j.getJSON(thisUrl + '?view=version&action=version&option=' + option) + .done(window.location.reload(true)) //Do a full refresh to update ZM_DYN_LAST_VERSION + .fail(function(jqxhr, textStatus, error) { + console.log("Request Failed: " + textStatus + ", " + error); + console.log("Response Text: " + jqxhr.responseText); + }); }); } + +// Load then show the "You No Permission" error modal +function enoperm() { + $j.getJSON(thisUrl + '?request=modal&modal=enoperm') + .done(function(data) { + if ( $j('#ENoPerm').length ) { + $j('#ENoPerm').replaceWith(data.html); + } else { + $j("body").append(data.html); + } + $j('#ENoPerm').modal('show'); + + // Manage the CLOSE optionhelp modal button + document.getElementById("enpCloseBtn").addEventListener("click", function onENPCloseClick(evt) { + $j('#ENoPerm').modal('hide'); + }); + }) + .fail(function(jqxhr, textStatus, error) { + console.log("Request Failed: " + textStatus + ", " + error); + console.log("Response Text: " + jqxhr.responseText); + }); +} diff --git a/web/skins/classic/views/_stats_table.php b/web/skins/classic/views/_stats_table.php deleted file mode 100644 index bf4bd14a6..000000000 --- a/web/skins/classic/views/_stats_table.php +++ /dev/null @@ -1,90 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 ) { -?> - - - - - - - - - - - - - -
- -
diff --git a/web/skins/classic/views/events.php b/web/skins/classic/views/events.php index 1d0507b4a..29bfb18c7 100644 --- a/web/skins/classic/views/events.php +++ b/web/skins/classic/views/events.php @@ -322,25 +322,4 @@ if ( $results ) { - - - diff --git a/web/skins/classic/views/frames.php b/web/skins/classic/views/frames.php index c29160549..3c2ad9277 100644 --- a/web/skins/classic/views/frames.php +++ b/web/skins/classic/views/frames.php @@ -206,15 +206,4 @@ if ( count($frames) ) { - - - diff --git a/web/skins/classic/views/js/console.js b/web/skins/classic/views/js/console.js index 850703bb7..522a6910e 100644 --- a/web/skins/classic/views/js/console.js +++ b/web/skins/classic/views/js/console.js @@ -151,7 +151,7 @@ function initPage() { $j('.functionLnk').click(function(evt) { evt.preventDefault(); if ( !canEditEvents ) { - alert('You do not have permission to change monitor function.'); + enoperm(); return; } var mid = evt.currentTarget.getAttribute('data-mid'); @@ -186,9 +186,12 @@ function initPage() { var mid = form.elements['mid'].value; var newFunc = $j('#newFunction').val(); var newEnabled = $j('#newEnabled').is(':checked') ? 1 : 0; - $j.getJSON(thisUrl + '?view=function&action=function&mid='+mid+'&newFunction='+newFunc+'&newEnabled='+newEnabled, function() { - window.location.reload(true); - }); + $j.getJSON(thisUrl + '?view=function&action=function&mid='+mid+'&newFunction='+newFunc+'&newEnabled='+newEnabled) + .done(window.location.reload(true)) + .fail(function(jqxhr, textStatus, error) { + console.log("Request Failed: " + textStatus + ", " + error); + console.log("Response Text: " + jqxhr.responseText); + }); }); } diff --git a/web/skins/classic/views/js/event.js b/web/skins/classic/views/js/event.js index 18eefb725..6781949d1 100644 --- a/web/skins/classic/views/js/event.js +++ b/web/skins/classic/views/js/event.js @@ -49,7 +49,11 @@ $j.ajaxSetup({timeout: AJAX_TIMEOUT}); //sets timeout for all getJSON. var cueFrames = null; //make cueFrames available even if we don't send another ajax query function initialAlarmCues(eventId) { - $j.getJSON(thisUrl + '?view=request&request=status&entity=frames&id=' + eventId, setAlarmCues); //get frames data for alarmCues and inserts into html + $j.getJSON(thisUrl + '?view=request&request=status&entity=frames&id=' + eventId, setAlarmCues) //get frames data for alarmCues and inserts into html + .fail(function(jqxhr, textStatus, error) { + console.log("Request Failed: " + textStatus + ", " + error); + console.log("Response Text: " + jqxhr.responseText); + }); } function setAlarmCues(data) { diff --git a/web/skins/classic/views/js/events.js b/web/skins/classic/views/js/events.js index 17df864d1..908be8c12 100644 --- a/web/skins/classic/views/js/events.js +++ b/web/skins/classic/views/js/events.js @@ -35,6 +35,50 @@ function getArchivedSelections() { return selection.includes("Yes"); } +// Load the Delete Confirmation Modal HTML via Ajax call +function getDelConfirmModal() { + $j.getJSON(thisUrl + '?request=modal&modal=delconfirm') + .done(function(data) { + if ( $j('#deleteConfirm').length ) { + $j('#deleteConfirm').replaceWith(data.html); + } else { + $j("body").append(data.html); + } + manageDelConfirmModalBtns(); + }) + .fail(function(jqxhr, textStatus, error) { + console.log("Request Failed: " + textStatus + ", " + error); + console.log("Response Text: " + jqxhr.responseText); + }); +} + +function manageDelConfirmModalBtns() { + // Manage the DELETE CONFIRMATION modal button + document.getElementById("delConfirmBtn").addEventListener("click", function onDelConfirmClick(evt) { + if ( ! canEditEvents ) { + enoperm(); + return; + } + + var selections = getIdSelections(); + + evt.preventDefault(); + $j.getJSON(thisUrl + '?request=events&action=delete&eids[]='+selections.join('&eids[]=')) + .done( function(data) { + $j('#eventTable').bootstrapTable('refresh'); + }) + .fail(function(jqxhr, textStatus, error) { + console.log("Request Failed: " + textStatus + ", " + error); + console.log("Response Text: " + jqxhr.responseText); + }); + }); + + // Manage the CANCEL modal button + document.getElementById("delCancelBtn").addEventListener("click", function onDelCancelClick(evt) { + $j('#deleteConfirm').modal('hide'); + }); +} + function initPage() { var backBtn = $j('#backBtn'); var viewBtn = $j('#viewBtn'); @@ -46,6 +90,9 @@ function initPage() { var deleteBtn = $j('#deleteBtn'); var table = $j('#eventTable'); + // Load the delete confirmation modal into the DOM + getDelConfirmModal(); + // Define the icons used in the bootstrap-table top-right toolbar var icons = { paginationSwitchDown: 'fa-caret-square-o-down', @@ -125,14 +172,21 @@ function initPage() { var selections = getIdSelections(); evt.preventDefault(); - $j.getJSON(thisUrl + '?view=events&action=archive&eids[]='+selections.join('&eids[]=')); - window.location.reload(true); + $j.getJSON(thisUrl + '?request=events&action=archive&eids[]='+selections.join('&eids[]=')) + .done( function(data) { + $j('#eventTable').bootstrapTable('refresh'); + window.location.reload(true); + }) + .fail(function(jqxhr, textStatus, error) { + console.log("Request Failed: " + textStatus + ", " + error); + console.log("Response Text: " + jqxhr.responseText); + }); }); // Manage the UNARCHIVE button document.getElementById("unarchiveBtn").addEventListener("click", function onUnarchiveClick(evt) { if ( ! canEditEvents ) { - alert("You do not have permission to Unarchive events."); + enoperm(); return; } @@ -140,7 +194,15 @@ function initPage() { console.log(selections); evt.preventDefault(); - $j.getJSON(thisUrl + '?view=events&action=unarchive&eids[]='+selections.join('&eids[]=')); + $j.getJSON(thisUrl + '?request=events&action=unarchive&eids[]='+selections.join('&eids[]=')) + .done( function(data) { + $j('#eventTable').bootstrapTable('refresh'); + window.location.reload(true); + }) + .fail(function(jqxhr, textStatus, error) { + console.log("Request Failed: " + textStatus + ", " + error); + console.log("Response Text: " + jqxhr.responseText); + }); if ( openFilterWindow ) { //opener.location.reload(true); @@ -154,7 +216,7 @@ function initPage() { // Manage the EDIT button document.getElementById("editBtn").addEventListener("click", function onEditClick(evt) { if ( ! canEditEvents ) { - alert("You do not have permission to edit events."); + enoperm(); return; } @@ -183,7 +245,7 @@ function initPage() { // Manage the DELETE button document.getElementById("deleteBtn").addEventListener("click", function onDeleteClick(evt) { if ( ! canEditEvents ) { - alert("You do not have permission to delete events."); + enoperm(); return; } @@ -191,25 +253,6 @@ function initPage() { $j('#deleteConfirm').modal('show'); }); - // Manage the DELETE CONFIRMATION modal button - document.getElementById("delConfirmBtn").addEventListener("click", function onDelConfirmClick(evt) { - if ( ! canEditEvents ) { - alert("You do not have permission to delete events."); - return; - } - - var selections = getIdSelections(); - - evt.preventDefault(); - $j.getJSON(thisUrl + '?request=events&action=delete&eids[]='+selections.join('&eids[]=')); - window.location.reload(true); - }); - - // Manage the CANCEL modal button - document.getElementById("delCancelBtn").addEventListener("click", function onDelCancelClick(evt) { - $j('#deleteConfirm').modal('hide'); - }); - // The table is initially given a hidden style, so now that we are done rendering, show it table.show(); } diff --git a/web/skins/classic/views/js/frames.js b/web/skins/classic/views/js/frames.js index 8b3ff28ec..a94e76c71 100644 --- a/web/skins/classic/views/js/frames.js +++ b/web/skins/classic/views/js/frames.js @@ -25,10 +25,18 @@ function processClicks(event, field, value, row, $element) { } } -function detailFormatter(index, row, element) { - return $j(element).html($j('#contentStatsTable'+index).clone(true).show()); +// This function handles when the user clicks a "+" link to retrieve stats for a frame +function detailFormatter(index, row, $detail) { + $detail.html('Please wait. Loading from ajax request...'); + $j.get(thisUrl + '?request=stats&eid=' + row.EventId + '&fid=' + row.FrameId + '&row=' + index) + .done(function(data) { + $detail.html(data.html); + }) + .fail(function(jqxhr, textStatus, error) { + console.log("Request Failed: " + textStatus + ", " + error); + console.log("Response Text: " + jqxhr.responseText); + }); } - function initPage() { var backBtn = $j('#backBtn'); var table = $j('#framesTable'); diff --git a/web/skins/classic/views/js/options.js b/web/skins/classic/views/js/options.js new file mode 100644 index 000000000..330a0e73b --- /dev/null +++ b/web/skins/classic/views/js/options.js @@ -0,0 +1,45 @@ +// Load the Storage Modal HTML via Ajax call +function getStorageModal(sid) { + $j.getJSON(thisUrl + '?request=modal&modal=storage&id=' + sid) + .done(function(data) { + if ( $j('#storageModal').length ) { + $j('#storageModal').replaceWith(data.html); + } else { + $j("body").append(data.html); + } + $j('#storageModal').modal('show'); + // Manage the Save button + $j('#storageSubmitBtn').click(function(evt) { + evt.preventDefault(); + $j('#storageModalForm').submit(); + }); + }) + .fail(function(jqxhr, textStatus, error) { + console.log("Request Failed: " + textStatus + ", " + error); + console.log("Response Text: " + jqxhr.responseText); + }); +} + +function enableStorageModal() { + $j(".storageCol").click(function(evt) { + evt.preventDefault(); + var sid = $j(this).data('sid'); + getStorageModal(sid); + }); + $j('#NewStorageBtn').click(function(evt) { + evt.preventDefault(); + getStorageModal(0); + }); +} + +function initPage() { + var NewStorageBtn = $j('#NewStorageBtn'); + + if ( canEditSystem ) enableStorageModal(); + + NewStorageBtn.prop('disabled', !canEditSystem); +} + +$j(document).ready(function() { + initPage(); +}); diff --git a/web/skins/classic/views/js/options.js.php b/web/skins/classic/views/js/options.js.php index 6947f8da8..5281cde8c 100644 --- a/web/skins/classic/views/js/options.js.php +++ b/web/skins/classic/views/js/options.js.php @@ -3,3 +3,5 @@ var restartWarning = ; if ( restartWarning ) { alert( "" ); } + +var canEditSystem = ; diff --git a/web/skins/classic/views/options.php b/web/skins/classic/views/options.php index 0fb5cb6e4..e1e6f4f78 100644 --- a/web/skins/classic/views/options.php +++ b/web/skins/classic/views/options.php @@ -272,12 +272,12 @@ foreach ( array_map('basename', glob('skins/'.$skin.'/css/*', GLOB_ONLYDIR)) as 'lower(Name)') ) as $Storage ) { ?> - Id(), 'zmStorage', 'storage', validHtmlStr($Storage->Id()), $canEdit ) ?> - Id(), 'zmStorage', 'storage', validHtmlStr($Storage->Name()), $canEdit ) ?> - Id(), 'zmStorage', 'storage', validHtmlStr($Storage->Path()), $canEdit ) ?> - Id(), 'zmStorage', 'storage', validHtmlStr($Storage->Type()), $canEdit ) ?> - Id(), 'zmStorage', 'storage', validHtmlStr($Storage->Scheme()), $canEdit ) ?> - Id(), 'zmStorage', 'storage', validHtmlStr($Storage->Server()->Name()), $canEdit ) ?> + Id()), $canEdit, 'class="storageCol" data-sid="'.$Storage->Id().'"' ) ?> + Name()), $canEdit, 'class="storageCol" data-sid="'.$Storage->Id().'"' ) ?> + Path()), $canEdit, 'class="storageCol" data-sid="'.$Storage->Id().'"' ) ?> + Type()), $canEdit, 'class="storageCol" data-sid="'.$Storage->Id().'"' ) ?> + Scheme()), $canEdit, 'class="storageCol" data-sid="'.$Storage->Id().'"' ) ?> + Server()->Name()), $canEdit, 'class="storageCol" data-sid="'.$Storage->Id().'"' ) ?> disk_used_space()) . ' of ' . human_filesize($Storage->disk_total_space()) ?> EventCount().' using '.human_filesize($Storage->event_disk_space()) ?> EventCount() or !$canEdit ) { ?> disabled="disabled"EventCount() ? ' title="Can\'t delete as long as there are events stored here."' : ''?>/> @@ -286,7 +286,7 @@ foreach ( array_map('basename', glob('skins/'.$skin.'/css/*', GLOB_ONLYDIR)) as
- +
diff --git a/web/skins/classic/views/stats.php b/web/skins/classic/views/stats.php index f6373151c..2cd5c69e4 100644 --- a/web/skins/classic/views/stats.php +++ b/web/skins/classic/views/stats.php @@ -44,9 +44,10 @@ xhtmlHeaders(__FILE__, translate('Stats')." - ".$eid." - ".$fid );
- +
+ diff --git a/web/skins/classic/views/storage.php b/web/skins/classic/views/storage.php deleted file mode 100644 index b25d12a21..000000000 --- a/web/skins/classic/views/storage.php +++ /dev/null @@ -1,114 +0,0 @@ -$_REQUEST['id'])) ) ) { - $view = 'error'; - return; - } -} else { - $newStorage = new ZM\Storage(); - $newStorage->Name(translate('NewStorage')); -} - -$type_options = array( 'local' => translate('Local'), 's3fs' => translate('s3fs') ); -$scheme_options = array( - 'Deep' => translate('Deep'), - 'Medium' => translate('Medium'), - 'Shallow' => translate('Shallow'), -); - -$servers = ZM\Server::find( null, array('order'=>'lower(Name)') ); -$ServersById = array(); -foreach ( $servers as $S ) { - $ServersById[$S->Id()] = $S; -} -$focusWindow = true; - -xhtmlHeaders(__FILE__, translate('Storage').' - '.$newStorage->Name()); -?> - -
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
'Remote / No Specific Server') + $ServersById, $newStorage->ServerId()); ?>
Type()); ?>
Scheme()); ?>
- DoDelete() ? 'checked="checked"' : '' ?>/>Yes - DoDelete() ? '' : 'checked="checked"' ?>/>No -
- Enabled() ? 'checked="checked"' : '' ?>/>Yes - Enabled() ? '' : 'checked="checked"' ?>/>No -
-
- - -
-
-
-
-