Lifecycle Status

View live sample

Description

When a feature or row is submitted to the Reviewer workspace it becomes a Reviewer result. Data Reviewer exposes a data quality control workflow that helps you review a result, correct any problems with the result, and then verify the fix to the result.Lifecycle status represents the state of a Reviewer result in the workflow.

This sample updates Lifecycle Status of Reviewer results to Data Reviewer for Server using the updateLifecycleStatus function. Select the Records Per page, Session Name and Return Fields. The Reviewer Results will be displayed in a grid. To update Lifecycle status, select results from the grid and click on Update Status button.

The live sample updates Lifecycle status to a hosted instance of Data Reviewer for Server. To run the sample against your own Reviewer server, you must specify the URL of your own Data Reviewer for Server and relative paths to your local copies of drs.js, style.css, and proxy.ashx.

NoteNote:

The Data Reviewer API for JavaScript 3.13 or later requires a proxy page to support POST requests and ArcGIS token-based authentication.

Code

The following code sample demonstrates how to update Lifecycle Status of Reviewer results for Data Reviewer for Server.

<!DOCTYPE html>
<!--
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2011-2015 Esri
//
// All rights reserved under the copyright laws of the United States
// and applicable international laws, treaties, and conventions.
//
// You may freely redistribute and use this software, with or without
// modification, provided you include the original copyright and use
// restrictions. See use restrictions in the file use_restrictions.txt.
//
////////////////////////////////////////////////////////////////////////////////
-->
<html>
   <head>
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge" />
	<link rel="stylesheet" type="text/css" href="http://js.arcgis.com/3.13/dijit/themes/claro/claro.css">
	<link rel="stylesheet" type="text/css" href="http://js.arcgis.com/3.13/dojox/grid/resources/claroGrid.css">
	<link rel="stylesheet" type="text/css" href="../style.css"/>

	<title>DRS Reviewer Results reviewerResults.updateLifecycleStatus Sample</title>
	<!-- configure dojo -->
	<script>
	 dojoConfig = {
		async : true
	 };
	</script>      

	<!--  load esri api and dojo -->
	<script src="http://js.arcgis.com/3.13/"></script>
	<!--  load drs api -->
	<script src="../drs_js_api/drs.js"></script>
	<script>  
	//This should point to the Data Reviewer soe
	var drsSoeUrl = "http://datareviewer.arcgisonline.com/arcgis/rest/services/Samples/reviewerWriteResults/MapServer/exts/DataReviewerServer";
	//array of return fields
	var returnFields = [];
	//Records per page
	var recordsPerPage;
	
	require(
	[
	 "dojo/parser",
	 "dojo/dom",
	 "dojo/on",
	 "dojo/_base/array",
	 "dojo/data/ItemFileReadStore",
	 "dojox/grid/DataGrid", "dijit/Dialog",
	 "dijit/form/MultiSelect",
	 "drs/ReviewerResultsTask",
	 "drs/GetResultsQueryParameters","drs/ReviewerFilters","drs/Lifecycle",
	 "dijit/registry",
	 "dojo/domReady!"
	], 
	function(parser, dom, on, array, ItemFileReadStore, DataGrid,Dialog, MultiSelect, ReviewerResultsTask, GetResultsQueryParameters,ReviewerFilters,Lifecycle,registry) {

		parser.parse();
		//identify proxy page to use
        esri.config.defaults.io.proxyUrl = "/arcgisserver/apis/javascript/proxy/proxy.ashx"; 
        esri.config.defaults.io.alwaysUseProxy = false;
		var reviewerResultsTask,selectedItems;
		//RevTableFields object. 
		//Add any custom fields if required
		revTableFields =  [
		{ field:'correctionTechnician', name:'Correction Technician' },
		{ field:'verificationTechnician', name:'Verification Technician' },
		{ field:'correctionDateUtc', name:'Correction Date',formatter: getFormattedString},
		{ field:'verificationDateUtc', name:'Verification Date',formatter: getFormattedString },
		{ field:'objectId', name:'Object Id' },
		{ field:'category',	name:'Category' },
		{ field:'checktitle', name:'Checktitle' },
		{ field:'resourceName',	name:'Resource Name' },
		{ field:'subtype', name:'Subtype' },
		{ field:'checkName', name:'Check Name' },
		{ field:'notes', name:'Notes' },
		{ field:'severity',	name:'Severity' },
		{ field:'reviewStatus',	name:'Review Status' },
		{ field:'reviewTechnician',	name:'Review Technician' },
		{ field: 'reviewDateUtc', name: 'Review Date' ,formatter: getFormattedString}];

		//Populate field names to be returned by Get Results operation
		array.forEach(revTableFields, function(field, i) {
			dom.byId("fieldNamesCombo")[i] = new Option(field.name, i);
		});
		//Click event of previousButton button
		on(dom.byId("previousButton"), "click", loadPreviousPage);
		//Click event of nextButton button
		on(dom.byId("nextButton"), "click", loadNextPage);
		//Click event of getResultsButton button
		on(dom.byId("getResultsButton"), "click", populateDataGrid);
		//Click event of Update Status button
		on(dom.byId("displayDialogButton"), "click", displayStatusDialog);
		//Click event of Update button
		on(dom.byId("updateStatusButton"), "click", updateStatus);
		getReviewerSessions();

        function getReviewerSessions()
        {
	         reviewerResultsTask = new ReviewerResultsTask(drsSoeUrl);
	         var deferred=reviewerResultsTask.getReviewerSessions();
	         deferred.then(function(response) {
	         	var reviewerSessions = response.reviewerSessions;
	            for (var i = 0; i < reviewerSessions.length; i++) {
	            	dom.byId("sessionIdCombo")[i+1] = new Option(reviewerSessions[i].toString(), reviewerSessions[i].sessionId);
				}
              }, function(error) {
	               alert(error.message);
	          });
		}
		function populateDataGrid() {
			// Get the number of records per page
			recordsPerPage = parseInt(dom.byId("RecordsPerPage").value);
			//Get Selected fields from the list box
			var selectItem = registry.byId('fieldNamesCombo').getSelected();
			if(isNaN(recordsPerPage) || recordsPerPage < 1) 
			{
			   alert("Please fill out records per page.");
			   return;
			}
			if(recordsPerPage>1000)
			{
			  alert("Records per page can not be greater than 1000.");
			  return;
			}
			if(selectItem.length < 1)
			{
				alert("Please select return fields.");
				return;
			}
			//Generate grid layout and returnFields based on fields selected in the list box
			var layout = [];
			returnFields = [];
			// adding default fields in layout
			layout.push({ field:'recordId',	name:'Record Id' });
			layout.push({ field:'sessionId',name:'Session Id' });
			layout.push({ field:'lifecycleStatus',name:'Lifecycle Status', 'formatter':getFormattedString });
			
			//adding field in return fields list
			returnFields.push("recordId");
			returnFields.push("sessionId");
			returnFields.push("lifecycleStatus");
			array.forEach(selectItem, function(option) {
				var selectedIndex =  option.value;
				var fieldValue=revTableFields[selectedIndex];
				if (fieldValue.field =="verificationDateUtc" || fieldValue.field=="correctionDateUtc" || fieldValue.field=="reviewDateUtc")
				{
					
				}
				layout.push(revTableFields[selectedIndex]);	
                returnFields.push(revTableFields[selectedIndex].field);
			});
			//set default page number for the grid
			//dom.byId('lblPageNumber').innerHTML=1;
			//show the grid with a loading message and populate it
			loadDataInGrid("",layout);
		}
	 
		function loadDataInGrid(moveType,layout) {
			showGrid(true, 'loading');
			// create ReviewerResultsTask instance 
			var queryParameters=GetQueryParameters(moveType);
			// call getResults to retrieve the results stored in the reviewer workspace.
			var reviewerFilters = new ReviewerFilters();
		    reviewerFilters.addAttributeFilter("SESSIONID", dom.byId("sessionIdCombo").value);
			var deferred = reviewerResultsTask.getResults(queryParameters,reviewerFilters);            
			// we're using dojo deferred 'then' function to set callback and errback functions
			deferred.then(function(response) {
				// map attributes from features to items array to populate dataGrid
				var items = array.map(response.featureSet.features, function(feature) {
				return feature.attributes;
				});
				// create a dojo ReadStore
				var store = new ItemFileReadStore({
				  data : {
					 items : items
				  }
				});
				// set the store in the DataGrid, this will populate the datagrid with the reviewer results
				reviewerResultsGrid.setStore(store);
				reviewerResultsGrid.setStructure(layout);
				//update current page number label
				if(moveType == "previous" && (parseInt(dom.byId('lblPageNumber').innerHTML) > 1))
				{
					dom.byId('lblPageNumber').innerHTML =  parseInt(dom.byId('lblPageNumber').innerHTML) - 1;
				}
				else if(moveType == "next")
				{
					dom.byId('lblPageNumber').innerHTML =  parseInt(dom.byId('lblPageNumber').innerHTML) + 1;
				}
			}, function(err) {
			   if(moveType == "next" && (err.message.indexOf("No results returned for specified query:") == 0))
			   {
					showGrid(true);
					alert("You are already at the last page.");	
			   }
			   else
			   {
			   		showGrid(false);
			   		reviewerResultsGrid.setStore(null);
			   		alert("Error retrieving reviewer results: " + err.message);
			   }
			   return;
			});
		}
		function getFormattedString(value, obj,column)
		{
			if (value==null)
				return "";
			if(column.field=="lifecycleStatus")
			{
				var lifecycleString = new Lifecycle();
				if (value==null)
						return null;
				return lifecycleString.toLifecycleStatusString(value);
			}
			else if (column.field=="verificationDateUtc" || column.field=="correctionDateUtc" || column.field=="reviewDateUtc")
			{
				var date = new Date(value);
				var localDate = new Date(date.toLocaleString());
				return localDate.toDateString();
			}
		}
		function GetQueryParameters(moveType){
			var queryParameters = new GetResultsQueryParameters();
			queryParameters.pageSize = recordsPerPage;
			if(moveType == "previous" && (parseInt(dom.byId('lblPageNumber').innerHTML) > 1))
			{
				queryParameters.pageNumber = parseInt(dom.byId('lblPageNumber').innerHTML) - 2;
			}
			else if(moveType == "next")
			{
				queryParameters.pageNumber = parseInt(dom.byId('lblPageNumber').innerHTML);
			}
			else if (moveType=="")
			{
				queryParameters.pageNumber = parseInt(dom.byId('lblPageNumber').innerHTML) - 1;
			}
			else
			{
				queryParameters.pageNumber = 0;
			}
			queryParameters.returnFields = returnFields;
			return queryParameters;
		}
		//load next page
		function loadNextPage() {
			loadDataInGrid("next","");	   		   		
		}	
			
		//load previous page
		function loadPreviousPage() 
		{
			if(parseInt(dom.byId('lblPageNumber').innerHTML) == 1)
			{
				alert("You are already at the first page.");
				return;
			}
			else
			{
				loadDataInGrid("previous", "");	
			}
		}
		//Displays the next lifecycle status that the selected results can move to in a dialog
		function displayStatusDialog(){
			 selectedItems = reviewerResultsGrid.selection.getSelected();
			 if (selectedItems.length>0)
			 {
			 	var lifecycleList = new Array();
			 	//get an array of unique lifecycle status values of selected records
				for (i = 0; i < selectedItems.length; i++)
                {
                    if (lifecycleList.indexOf(selectedItems[i].lifecycleStatus[0]) == -1)
                    {
                        lifecycleList.push(selectedItems[i].lifecycleStatus[0]);
                    }
                }
                lifecycleList.sort();
               //get lifecycle information from the Lifecycle helper class
                var lifecycleHelperClass = new Lifecycle();
                var lifecycleInfo = lifecycleHelperClass.getLifecycleInfo(lifecycleList);
                if (lifecycleInfo != null)
                {
                    // clear out any previous values
                    dom.byId("technicianName").value="";
					for(i=dom.byId("statusSelect").options.length-1;i>=1;i--)
				    {
				        dom.byId("statusSelect").remove(i);
				    }
                    array.forEach (lifecycleInfo.nextLifecycleStatus,function(status,i)
                    {
                        dom.byId("statusSelect")[i+1] = new Option(lifecycleHelperClass.toLifecycleStatusString(status), status);
                    });
                }
                else
                {
                    alert("The selected records cannot be updated to a common lifecycle status");
                    return;
                }
		 		var statusDialog = registry.byId("statusDialog");
		 		statusDialog.show();
		 	 }
		 	else
		 	{
		 		alert("Please select records to update");	
		 	}
		}
		//calls the update lifecycleStatus method from the ReviewerResults task. If selected results are updated successfully an message will be displayed
        function updateStatus(){
			var reviewerFilters = new ReviewerFilters();
		    array.forEach(selectedItems, function(selectedItem){
		    	reviewerFilters.addAttributeFilter("RECORDID", selectedItem.recordId);
		    });
			var deferred=reviewerResultsTask.updateLifecycleStatus(dom.byId("sessionIdCombo").value,dom.byId("statusSelect").value,dom.byId("technicianName").value,reviewerFilters);
			deferred.then(function(response){
				registry.byId("statusDialog").hide();
				//refresh datagrid
				populateDataGrid();
				array.forEach(response.featureEditResults, function(featureEditResult){
					if (featureEditResult.success==false)
					{
						alert("Error updating records from the selection");
						return;
					}	
				});
				alert("Lifecycle Status updated");
			}, function(error){
				alert(error.message);
			});
        }
		//handle grid visibility
		function showGrid(show,message) {
			 reviewerResultsGrid.showMessage(message || "");
			 dom.byId('gridDiv').style.visibility = show ? "visible" : "hidden";
		}    
		
	});

	</script>
   
	</head>
	<body class="claro">
		<!--[if IE]>
		<div id="IEroot">
		<![endif]-->
		 <h2 align="center">Update Lifecycle Status Sample</h2>
		<div style="width:100%; overflow-x: auto;" >
			<div style="padding: 0px 20px 0px 20px; float:left;">
				<div class="reviewerForm" >
					<label for="RecordsPerPage">Records per page:</label>
					<input type="number" id="RecordsPerPage" placeholder="valid values are from 1 to 1000"/>
					<label for="sessionIdCombo">Session Name:</label>
					  <select id="sessionIdCombo" ><option value="">Select Session</option>
               		</select>
					<label for="fieldNamesCombo">Return fields:</label>
					 <select class ="reviewerMultiSelect" id="fieldNamesCombo" data-dojo-type="dijit/form/MultiSelect"></select>
					<label for="getResultsButton"></label>
					<button id="getResultsButton" class="submitButton">Get Results</button>
				</div>
			 </div>
		</div>
		<div id = "gridDiv" style="width: 100%; overflow-x: auto;visibility: hidden" class="reviewerGrid">
			<button id="previousButton"> &lt; </button>
			<label id = "lblPageNumber" >1</label>
			<button id="nextButton"> &gt; </button>	
			<button id="displayDialogButton"> Update Status </button>	
			<table data-dojo-id="reviewerResultsGrid" data-dojo-type="dojox/grid/DataGrid" autoheight="true" autowidth="true"></table>	 
		</div>
		<!--[if IE]>
		</div>
		<![endif]-->
		
		<div data-dojo-type="dijit/Dialog" data-dojo-id="statusDialog" title="Update Status" id="statusDialog"  class="reviewerForm" style="width:350px">
    	<table>
        <tr>
            <td><label for="name">Reviewer Technician:</label></td>
            <td><input id="technicianName" placeholder="Technician Name" style="width:170px"/></td>
        </tr>
        <tr>
            <td><label for="address">Lifecycle Status:</label></td>
            <td>  <select id="statusSelect" style="width: 176px" ><option value="">Select Status</option>
            	</td>
        </tr>
    </table>

    <div>
        	<button id="cancelButton" onclick="statusDialog.onCancel();" style="width:80px; float: right;"> Cancel </button>	
        	<button id="updateStatusButton" style="width:80px; float: right;"> Update</button>	
    </div>
</div>
	</body>
</html>

5/7/2015