diff --git a/htdocs/web_portal/controllers/downtime/add_downtime.php b/htdocs/web_portal/controllers/downtime/add_downtime.php index becb0c73f..bf352e178 100644 --- a/htdocs/web_portal/controllers/downtime/add_downtime.php +++ b/htdocs/web_portal/controllers/downtime/add_downtime.php @@ -24,6 +24,7 @@ require_once __DIR__.'/../../../../lib/Gocdb_Services/Factory.php'; require_once __DIR__.'/../utils.php'; require_once __DIR__.'/../../../web_portal/components/Get_User_Principle.php'; +require_once __DIR__ . '/downtime_utils.php'; /** * Controller for a new_downtime request. @@ -71,54 +72,58 @@ function submit(\User $user = null) { if($confirmed == true){ //Downtime is confirmed, submit it //$downtimeInfo = unserialize($_REQUEST['newValues']); // didn't cater for UTF-8 chars + /** + * If confirmed by an user, submit the details of affected services + * and endpoints along with other details for each individual site. + */ + $params = []; $downtimeInfo = json_decode($_POST['newValues'], TRUE); $serv = \Factory::getDowntimeService(); + $downtimeInfo = unsetVariables($downtimeInfo, 'add'); + + foreach ( + $downtimeInfo['SERVICE_WITH_ENDPOINTS'] as $siteID => $serviceIDs + ) { + $serviceIDList = []; + $endpointIDList = []; + + foreach ($serviceIDs as $serviceID => $endpointsInfo) { + $serviceIDList[] = $serviceID; + $endpointIDList = array_merge( + $endpointIDList, + $endpointsInfo['endpointIDs'] + ); + } - $params['dt'] = $serv->addDowntime($downtimeInfo, $user); - show_view("downtime/added_downtime.php", $params); - }else{ - //Show user confirmation screen with their input - $downtimeInfo = getDtDataFromWeb(); - - //Need to sort the impacted_ids into impacted services and impacted endpoints - $impactedids = $downtimeInfo['IMPACTED_IDS']; + $downtimeInfo['Impacted_Services'] = $serviceIDList; + $downtimeInfo['Impacted_Endpoints'] = $endpointIDList; - $services=array(); - $endpoints=array(); + $siteDetails = \Factory::getSiteService()->getSite($siteID); + $siteName = $siteDetails->getShortName(); - //For each impacted id sort between endpoints and services using the prepended letter - foreach($impactedids as $id){ - if (strpos($id, 's') !== FALSE){ - //This is a service id - $services[] = str_replace('s', '', $id); //trim off the identifying char before storing in array - }else{ - //This is an endpoint id - $endpoints[] = str_replace('e', '', $id); //trim off the identifying char before storing in array - } + $params['submittedDowntimes'][$siteName] = + $serv->addDowntime($downtimeInfo, $user); } - unset($downtimeInfo['IMPACTED_IDS']); //Delete the unsorted Ids from the downtime info - - $downtimeInfo['Impacted_Endpoints'] = $endpoints; + show_view("downtime/added_downtime.php", $params); + }else{ + //Show user confirmation screen with their input + $downtimeInfo = getDtDataFromWeb(); + $downtimeInfo['SERVICE_WITH_ENDPOINTS'] = endpointToServiceMapping( + $downtimeInfo['IMPACTED_IDS'] + ); - $serv = \Factory::getServiceService(); + /** + * Delete the `IMPACTED_IDS` from the `downtimeInfo` as we + * extracted the details we need in `endpointToServiceMapping`. + */ + unset($downtimeInfo['IMPACTED_IDS']); - /** For endpoint put into downtime we want the parent service also. If a user has selected - * endpoints but not the parent service here we will add the service to maintain the link beteween - * a downtime having both the service and the endpoint. - */ - foreach($downtimeInfo['Impacted_Endpoints'] as $endpointIds){ - $endpoint = $serv->getEndpoint($endpointIds); - $services[] = $endpoint->getService()->getId(); + if (count($downtimeInfo['SERVICE_WITH_ENDPOINTS']) === 1) { + $downtimeInfo['SELECTED_SINGLE_SITE'] = true; } - //Remove any duplicate service ids and store the array of ids - $services = array_unique($services); - - //Assign the impacted services and endpoints to their own arrays for us by the addDowntime method - $downtimeInfo['Impacted_Services'] = $services; - show_view("downtime/confirm_add_downtime.php", $downtimeInfo); } } diff --git a/htdocs/web_portal/controllers/downtime/downtime_utils.php b/htdocs/web_portal/controllers/downtime/downtime_utils.php new file mode 100644 index 000000000..a8cd1bee5 --- /dev/null +++ b/htdocs/web_portal/controllers/downtime/downtime_utils.php @@ -0,0 +1,80 @@ +serviceID->EndpointID(s)' details. + */ +function endpointToServiceMapping($impactedIDs) +{ + $serviceWithEndpoints = []; + + /** + * For each impacted ID, sort between endpoints and services + * using the prepended letter. + */ + foreach ($impactedIDs as $impactedID) { + $indexPosition = 0; + + list($siteID, $serviceID, $idType) = explode(':', $impactedID); + /** + * `idType` => It will have either `s` followed by service ID or + * `e` followed by endpoint ID. + */ + $trimmedID = str_replace(['s', 'e'], '', $idType); + + if (strpos($idType, 's') === $indexPosition) { + continue; + } + + // Using '+' to ensure we have an integer value after type coercion. + $serviceWithEndpoints[$siteID][$serviceID]['endpointIDs'][] = + +$trimmedID; + } + + return $serviceWithEndpoints; +} + +/** + * Unset a given variable, helper method to destroy the specified variables. + * + * @param mixed $downtimeObj Object to destroy specified variables. + * @param string $fromLocation Location from where the + * function is being called. + */ +function unsetVariables($downtimeObj, $fromLocation) +{ + if ($fromLocation == "edit") { + unset($downtimeObj['DOWNTIME']['EXISTINGID']); + unset($downtimeObj['isEdit']); + } + + unset($downtimeObj['SELECTED_SINGLE_SITE']); + + return $downtimeObj; +} diff --git a/htdocs/web_portal/controllers/downtime/edit_downtime.php b/htdocs/web_portal/controllers/downtime/edit_downtime.php index 9bf244428..33d28d519 100644 --- a/htdocs/web_portal/controllers/downtime/edit_downtime.php +++ b/htdocs/web_portal/controllers/downtime/edit_downtime.php @@ -21,6 +21,7 @@ require_once __DIR__ . '/../../../../lib/Gocdb_Services/Factory.php'; require_once __DIR__ . '/../../../../htdocs/web_portal/components/Get_User_Principle.php'; require_once __DIR__ . '/../utils.php'; +require_once __DIR__ . '/downtime_utils.php'; /** * Controller for an edit downtime request @@ -88,11 +89,31 @@ function submit(\User $user = null) { if($confirmed == true){ //Downtime is confirmed, submit it $downtimeInfo = json_decode($_POST['newValues'], TRUE); - + $params = []; $serv = \Factory::getDowntimeService(); $dt = $serv->getDowntime($downtimeInfo['DOWNTIME']['EXISTINGID']); - unset($downtimeInfo['DOWNTIME']['EXISTINGID']); - unset($downtimeInfo['isEdit']); + $downtimeInfo = unsetVariables($downtimeInfo, 'edit'); + + foreach ( + $downtimeInfo['SERVICE_WITH_ENDPOINTS'] as $serviceIDs + ) { + $serviceIDList = []; + $endpointIDList = []; + + foreach ($serviceIDs as $serviceID => $endpointsInfo) { + $serviceIDList[] = $serviceID; + $endpointIDList = array_merge( + $endpointIDList, + $endpointsInfo['endpointIDs'] + ); + } + + $downtimeInfo['Impacted_Services'] = $serviceIDList; + $downtimeInfo['Impacted_Endpoints'] = $endpointIDList; + } + + unset($downtimeInfo['SERVICE_WITH_ENDPOINTS']); + $params['dt'] = $serv->editDowntime($dt, $downtimeInfo, $user); show_view("downtime/edited_downtime.php", $params); @@ -101,43 +122,17 @@ function submit(\User $user = null) { $downtimeInfo = getDtDataFromWeb(); //Need to sort the impacted_ids into impacted services and impacted endpoints - $impactedids = $downtimeInfo['IMPACTED_IDS']; - - $services=array(); - $endpoints=array(); - - //For each impacted id sort between endpoints and services using the prepended letter - foreach($impactedids as $id){ - if (strpos($id, 's') !== FALSE){ - //This is a service id - $services[] = str_replace('s', '', $id); //trim off the identifying char before storing in array - }else{ - //This is an endpoint id - $endpoints[] = str_replace('e', '', $id); //trim off the identifying char before storing in array - } - } - - unset($downtimeInfo['IMPACTED_IDS']); //Delete the unsorted Ids from the downtime info + $downtimeInfo['SERVICE_WITH_ENDPOINTS'] = endpointToServiceMapping( + $downtimeInfo['IMPACTED_IDS'] + ); - $downtimeInfo['Impacted_Endpoints'] = $endpoints; + // Delete the unsorted IDs from the downtime info + unset($downtimeInfo['IMPACTED_IDS']); - - $serv = \Factory::getServiceService(); - - /** For endpoint put into downtime we want the parent service also. If a user has selected - * endpoints but not the parent service here we will add the service to maintain the link beteween - * a downtime having both the service and the endpoint. - */ - foreach($downtimeInfo['Impacted_Endpoints'] as $endpointIds){ - $endpoint = $serv->getEndpoint($endpointIds); - $services[] = $endpoint->getService()->getId(); + if (count($downtimeInfo['SERVICE_WITH_ENDPOINTS']) === 1) { + $downtimeInfo['SELECTED_SINGLE_SITE'] = true; } - //Remove any duplicate service ids and store the array of ids - $services = array_unique($services); - - //Assign the impacted services and endpoints to their own arrays for us by the addDowntime method - $downtimeInfo['Impacted_Services'] = $services; //Pass the edit variable so the confirm_add view works as the confirm edit view. $downtimeInfo['isEdit'] = true; show_view("downtime/confirm_add_downtime.php", $downtimeInfo); diff --git a/htdocs/web_portal/controllers/downtime/view_endpoint_tree.php b/htdocs/web_portal/controllers/downtime/view_endpoint_tree.php index eb9f81946..d2be2bed4 100644 --- a/htdocs/web_portal/controllers/downtime/view_endpoint_tree.php +++ b/htdocs/web_portal/controllers/downtime/view_endpoint_tree.php @@ -19,20 +19,34 @@ * limitations under the License. * /*====================================================== */ +use Doctrine\Common\Collections\ArrayCollection; +use Exception; + function getServiceandEndpointList() { require_once __DIR__ . '/../utils.php'; require_once __DIR__ . '/../../../web_portal/components/Get_User_Principle.php'; + $params = []; $dn = Get_User_Principle(); $user = \Factory::getUserService()->getUserByPrinciple($dn); $params['portalIsReadOnly'] = portalIsReadOnlyAndUserIsNotAdmin($user); + $siteIDs = $_REQUEST['site_id']; - if (!isset($_REQUEST['site_id']) || !is_numeric($_REQUEST['site_id']) ){ - throw new Exception("An id must be specified"); + if (empty($siteIDs)) { + throw new Exception("Please select at least one site."); } - $site = \Factory::getSiteService()->getSite($_REQUEST['site_id']); - $services = $site->getServices(); - $params['services'] = $services; + + $siteIdWithServices = new ArrayCollection(); + + foreach ($siteIDs as $siteID) { + // Using '+' to ensure we have integer value after type coercion. + $siteID = +$siteID; + $site = \Factory::getSiteService()->getSite($siteID); + $siteIdWithServices[$siteID] = $site->getServices(); + } + + $params['siteIdWithServices'] = $siteIdWithServices; + show_view("downtime/view_nested_endpoints_list.php", $params, null, true); } @@ -41,19 +55,29 @@ function editDowntimePopulateEndpointTree() { require_once __DIR__ . '/../utils.php'; require_once __DIR__ . '/../../../web_portal/components/Get_User_Principle.php'; + $params = []; $dn = Get_User_Principle(); $user = \Factory::getUserService()->getUserByPrinciple($dn); $params['portalIsReadOnly'] = portalIsReadOnlyAndUserIsNotAdmin($user); + $siteIDs = $_REQUEST['site_id']; - if (!isset($_REQUEST['site_id']) || !is_numeric($_REQUEST['site_id']) ){ - throw new Exception("A site id must be specified"); + if (empty($_REQUEST['site_id'])) { + throw new Exception("Please select at least one site."); } if (!isset($_REQUEST['dt_id']) || !is_numeric($_REQUEST['dt_id']) ){ throw new Exception("A downtime id must be specified"); } - $site = \Factory::getSiteService()->getSite($_REQUEST['site_id']); - $services = $site->getServices(); - $params['services'] = $services; + + $siteIdWithServices = new ArrayCollection(); + + foreach ($siteIDs as $siteID) { + // Using '+' to ensure we have integer value after type coercion. + $siteID = +$siteID; + $site = \Factory::getSiteService()->getSite($siteID); + $siteIdWithServices[$siteID] = $site->getServices(); + } + + $params['siteIdWithServices'] = $siteIdWithServices; $downtime = \Factory::getDowntimeService()->getDowntime($_REQUEST['dt_id']); $params['downtime'] = $downtime; diff --git a/htdocs/web_portal/views/downtime/add_downtime.php b/htdocs/web_portal/views/downtime/add_downtime.php index 35508c0d2..b5643d344 100644 --- a/htdocs/web_portal/views/downtime/add_downtime.php +++ b/htdocs/web_portal/views/downtime/add_downtime.php @@ -67,7 +67,12 @@        - +
+

+ WARNING: When selecting multiple sites, you must use the + Enter Times In: UTC option. +

+
@@ -147,10 +152,15 @@ $size = sizeof($sites) + 2; } ?> - getName(); @@ -221,6 +231,7 @@ class="form-control" id="Select_Sites" name="select_sites" size="10" $("#timezoneSelectGroup").find(":input").change(function(){ updateStartEndTimesInUtc(); + validate(); }); // The bootstrap datetimepickers don't fire the change event @@ -231,7 +242,7 @@ class="form-control" id="Select_Sites" name="select_sites" size="10" validate(); }); - + selectedValidTimezoneUsecase(); }); @@ -294,6 +305,23 @@ function updateStartEndTimesInUtc(){ } } + function selectedValidTimezoneUsecase() + { + let siteID = $('#Select_Sites').val(); + let selectedSiteTz = $('#siteRadioButton').is(':checked'); + let validSelection = true; + + if ((siteID && siteID.length > 1) && selectedSiteTz) { + validSelection = false; + + $('#invalidSelection').show(); + } else { + $('#invalidSelection').hide(); + } + + return validSelection; + } + /* * Dynamically update the UTC time label and SCHEDULED/UNSCHEDULED labels. */ @@ -438,9 +466,17 @@ function validate(){ $('#chooseServices').removeClass("has-success"); } - //----------Set the Button based on validate status-------------// + //----------Verify whether the site has mutiple timezones----------// + const timezoneValid = selectedValidTimezoneUsecase(); - if(epValid && severityValid && descriptionValid && datesValid){ + //----------Set the Button based on validate status-------------// + if ( + epValid + && severityValid + && descriptionValid + && datesValid + && timezoneValid + ) { $('#submitDowntime_btn').addClass('btn btn-success'); $('#submitDowntime_btn').prop('disabled', false); }else{ @@ -497,11 +533,15 @@ function getSitesServices(){ var siteId=$('#Select_Sites').val(); if(siteId != null){ //If the user clicks on the box but not a specific row there will be no input, so catch that here $('#chooseEndpoints').empty(); //Remove any previous content from the endpoints select list - $('#chooseServices').load('index.php?Page_Type=Downtime_view_endpoint_tree&site_id='+siteId,function( response, status, xhr ) { - if ( status == "success" ) { - validate(); + $('#chooseServices').load( + 'index.php?Page_Type=Downtime_view_endpoint_tree', + { site_id: siteId }, + function(response, status, xhr) { + if (status == "success") { + validate(); + } } - }); + ); } } @@ -513,6 +553,7 @@ function getSitesServices(){ function onSiteSelected(){ var siteId=$('#Select_Sites').val(); updateSiteTimezoneVars(siteId); + validate(); } /** @@ -522,19 +563,32 @@ function onSiteSelected(){ * @returns {null} */ function updateSiteTimezoneVars(siteId){ - if(siteId){ + if (siteId && siteId.length <= 1 ) { // use ajax to get the selected site's timezone label and offset // and update display+vars //console.log('fetching selected site timezone label'); - $.get('index.php', {Page_Type: 'Add_Downtime', siteid_timezone: siteId}, - function(data){ - var jsonRsp = JSON.parse(data); - // update global variables - used when calculating DT rules - TARGETTIMEZONEID = jsonRsp[0]; - TARGETTIMEZONEOFFSETFROMUTCSECS = jsonRsp[1]; //Returns the targetTimezone offset in seconds from UTC - //console.log("updateSiteTimezoneVars, siteId: ["+siteId+"] TARGETTIMEZONEID: ["+TARGETTIMEZONEID+"] TARGETTIMEZONEOFFSETFROMUTCSECS: ["+TARGETTIMEZONEOFFSETFROMUTCSECS+"]"); - $('#siteTimezoneText').val(TARGETTIMEZONEID); - }); + $.get( + 'index.php', + { Page_Type: 'Add_Downtime', siteid_timezone: siteId[0] }, + function(data) { + let jsonRsp = JSON.parse(data); + // Update global variables - used when calculating DT rules + TARGETTIMEZONEID = jsonRsp[0]; + // Returns the targetTimezone offset in seconds from UTC + TARGETTIMEZONEOFFSETFROMUTCSECS = jsonRsp[1]; + + $('#siteTimezoneText').val(TARGETTIMEZONEID); + + updateStartEndTimesInUtc(); + } + ); + } else { + TARGETTIMEZONEID = "UTC"; + TARGETTIMEZONEOFFSETFROMUTCSECS = 0; + + $('#siteTimezoneText').val(TARGETTIMEZONEID); + + updateStartEndTimesInUtc(); } } diff --git a/htdocs/web_portal/views/downtime/added_downtime.php b/htdocs/web_portal/views/downtime/added_downtime.php index 563515a0c..b7332e704 100644 --- a/htdocs/web_portal/views/downtime/added_downtime.php +++ b/htdocs/web_portal/views/downtime/added_downtime.php @@ -1,5 +1,29 @@

Success


- New Downtime successfully created.
- View new downtime + '; + echo 'New Downtimes successfully created. '; + echo 'Please click the links below for more information.'; + echo '

'; + } else { + echo '

'; + echo 'New Downtime successfully created. '; + echo 'Please click the link below for more information.'; + echo '

'; + } + + echo ''; + ?>
\ No newline at end of file diff --git a/htdocs/web_portal/views/downtime/confirm_add_downtime.php b/htdocs/web_portal/views/downtime/confirm_add_downtime.php index 6ecebd831..6138a5b24 100644 --- a/htdocs/web_portal/views/downtime/confirm_add_downtime.php +++ b/htdocs/web_portal/views/downtime/confirm_add_downtime.php @@ -1,8 +1,6 @@ Downtime
- Please review your downtime before submitting.
+ '; + echo 'Please review your '; + + if (!($edit)) { + if ($params['SELECTED_SINGLE_SITE']) { + echo 'chosen site and the downtime '; + } else { + echo 'chosen sites and their downtimes '; + } + } else { + echo 'downtime '; + } + + echo 'before submitting.'; + echo '

'; + ?> + diff --git a/htdocs/web_portal/views/downtime/downtime_edit_view_nested_endpoints_list.php b/htdocs/web_portal/views/downtime/downtime_edit_view_nested_endpoints_list.php index 5be329d0e..f367c0ff1 100644 --- a/htdocs/web_portal/views/downtime/downtime_edit_view_nested_endpoints_list.php +++ b/htdocs/web_portal/views/downtime/downtime_edit_view_nested_endpoints_list.php @@ -1,5 +1,5 @@ $services) { + foreach ($services as $service) { $count=0; // Set the html 'SELECTED' attribute on the "); @@ -52,10 +56,14 @@ class="form-control" onclick="" $name = xssafe($endpoint->getName()); } //Option styling doesn't work well cross browser so just use 4 spaces to indent the branch - echo ""; + echo ""; $count++; } } +} ?> diff --git a/htdocs/web_portal/views/downtime/edit_downtime.php b/htdocs/web_portal/views/downtime/edit_downtime.php index 0f1fcd761..09cf93f73 100644 --- a/htdocs/web_portal/views/downtime/edit_downtime.php +++ b/htdocs/web_portal/views/downtime/edit_downtime.php @@ -154,10 +154,15 @@ class="glyphicon glyphicon-time"> $size = sizeof($sites) + 2; } ?> - @@ -7,9 +7,17 @@