Sometimes there is need for comparing the contents between two environments. It can be local to QA, QA to Stage or Stage to Production. So I thought of building a simple page, by which we can compare items between two environments.
There is already some popular tools available in market e.g Razl and each of these tools have their own niche role.
Here I tried to make it very simple for specific goals. When I thought of developing it, the first thing came to my mind that I don’t need to compare all the items in Sitecore, but I need to compare only the recently modified items.
So below are the steps.
- Need a list of recently modified items of the current environment.
- Need the current item details from DB.
- Need the same item from Target environment
- Compare between two items
- Create package from selected items from current environment.
So let’s do some coding.
Get Modified items between two dates
public JsonResult GetModifiedItems(string startDate, string endDate, string rootPath)public JsonResult GetModifiedItems(string startDate, string endDate, string rootPath) { var sitecoreItems = new List<SitecoreItem>(); DateTime dtStartDate = Utility.GetDate(startDate); DateTime dtEndDate = Utility.GetDate(endDate); dtEndDate = dtEndDate.AddDays(1); endDate = dtEndDate.ToString("yyyyMMdd"); startDate = dtStartDate.ToString("yyyyMMdd"); rootPath = rootPath.Trim('/'); rootPath = "/" + rootPath + "/"; string sitecoreQuery = string.Format("fast:" + rootPath + "/*[@__Updated >= '{0}T000000' and @__Updated < '{1}T000000']", startDate, endDate); var result = Utility.GetItems(sitecoreQuery); if (result.Count > 0) { int serialNo = 1; foreach (var item in result) { sitecoreItems.Add(new SitecoreItem { Id = item.ID.Guid.ToString().ToUpper(), Path = item.Paths.FullPath, SerialNo = serialNo, CreatedDate = Utility.GetIsoDate(item.Fields["__Created"].Value), UpdateDate = Utility.GetIsoDate(item.Fields["__Updated"].Value), UpdatedBy = Utility.GetUserName(item.Fields["__Updated by"].Value) }); serialNo++; } } return Json(sitecoreItems, JsonRequestBehavior.AllowGet); }
Get All field values of an Item
public JsonResult GetItem(string id, string database, string lang) { var fieldValues = new List<span data-mce-type="bookmark" id="mce_SELREST_start" data-mce-style="overflow:hidden;line-height:0" style="overflow:hidden;line-height:0" ></span><FieldValue><span data-mce-type="bookmark" id="mce_SELREST_end" data-mce-style="overflow:hidden;line-height:0" style="overflow:hidden;line-height:0" ></span>() var db = Factory.GetDatabase(database); var siecoreId = new Sitecore.Data.ID(new Guid(id)); //Check the language if (string.IsNullOrEmpty(lang)) { lang = "en"; } var language = Sitecore.Globalization.Language.Parse(lang); var item = db.GetItem(siecoreId, language); if (item != null) { item.Fields.ReadAll(); FieldCollection fieldCollection = item.Fields; foreach (Field field in fieldCollection) { //Use the following check if you do not want //the Sitecore Standard Fields if (!field.Name.StartsWith("__")) { fieldValues.Add(new FieldValue { Name = field.Name, Value = HttpUtility.HtmlEncode(field.Value) }); } else if (field.Name == "__Renderings") { fieldValues.Add(new FieldValue { Name = field.Name, Value = HttpUtility.HtmlEncode(field.Value) }); } } } return Json(fieldValues, JsonRequestBehavior.AllowGet); }
Get Item Difference
public JsonResult GetDifference(string id, string targetUrl, string lang) { var itemDifference = new ItemDifference { ErrorMessage = "", Items = new List<ItemDifferenceItem>() }; if (string.IsNullOrEmpty(lang)) { lang = "en"; } var localApiPath = apiPath.Replace("//", "/"); targetUrl = targetUrl.TrimEnd('/') + localApiPath; targetUrl = targetUrl.Replace("{id}", id); targetUrl = targetUrl.Replace("{lang}", lang); string currentUrl = Utility.GetDomainUrl(Request.Url.ToString()); currentUrl = currentUrl.TrimEnd('/') + localApiPath; currentUrl = currentUrl.Replace("{id}", id); currentUrl = currentUrl.Replace("{lang}", lang); string message = ""; try { string currentValue = ""; string targetValue = ""; ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12; try { using (var client = new WebClient()) { currentValue = client.DownloadString(currentUrl); } } catch { message = "Couldn't retrieve the difference. Error occurred in api." + "" + currentUrl; } try { using (var client = new WebClient()) { targetValue = client.DownloadString(targetUrl); } } catch { if (string.IsNullOrEmpty(message)) { message = "Couldn't retrieve the difference. Error occured in api." + "" + targetUrl; } } if (string.IsNullOrEmpty(currentValue) || string.IsNullOrEmpty(targetValue)) { itemDifference.ErrorMessage = message; return Json(itemDifference, JsonRequestBehavior.AllowGet); } var targetFieldValues = Utility.GetFieldAndValuesNew(targetValue); var currentFieldValues = Utility.GetFieldAndValuesNew(currentValue); if (targetFieldValues == null || targetFieldValues.Count == 0) { itemDifference.ErrorMessage = "The content doesn't exist in target environment."; return Json(itemDifference, JsonRequestBehavior.AllowGet); } itemDifference.Items = Utility.GetItemDifference(currentFieldValues, targetFieldValues); if (itemDifference.Items.Count == 0) { itemDifference.ErrorMessage = "No difference found."; } } catch (Exception ex) { itemDifference.ErrorMessage = message + ex.Message + "" + ex.StackTrace + "" + currentUrl + "" + targetUrl; } return Json(itemDifference, JsonRequestBehavior.AllowGet); }
Create Package of selected Items
[HttpPost] public JsonResult CreatePackage(string ids) { var response = new Package { Name = "" }; try { using (new Sitecore.SecurityModel.SecurityDisabler()) { Sitecore.Data.Database db = Factory.GetDatabase("master"); PackageProject document = new PackageProject(); document.Metadata.PackageName = "Item Package"; document.Metadata.Author = "Admin"; //Create source – source should be based on BaseSource ExplicitItemSource source = new ExplicitItemSource(); source.Name = "Sitecore"; string[] arrItemId = ids.Split('|'); foreach(string id in arrItemId) { var siecoreId = new Sitecore.Data.ID(new Guid(id)); var item = db.GetItem(siecoreId); source.Entries.Add(new ItemReference(item.Uri, false).ToString()); } document.Sources.Add(source); document.SaveProject = true; string packageName = "SitecoreItem_" + DateTime.Now.Ticks.ToString() + ".zip"; string folder = Settings.DataFolder + "\\packages\\"; response.Name = folder; //path where the zip file package is saved using (Sitecore.Install.Zip.PackageWriter writer = new Sitecore.Install.Zip.PackageWriter(folder + packageName)) { Sitecore.Context.SetActiveSite("shell"); writer.Initialize(Installer.CreateInstallationContext()); PackageGenerator.GeneratePackage(document, writer); Sitecore.Context.SetActiveSite("website"); } response.IsSuccess = true; response.Name = packageName; } } catch (Exception ex) { response.Name += ex.Message + "" + ex.StackTrace; } return Json(response); }
The source code is below
Controller
using SC.ItemCompare.Helper; using SC.ItemCompare.Model; using Sitecore.Collections; using Sitecore.Configuration; using Sitecore.Data.Fields; using Sitecore.Install; using Sitecore.Install.Items; using System; using System.Collections.Generic; using System.Net; using System.Web; using System.Web.Mvc; namespace SC.ItemCompare { public class ItemCompareServiceController : Controller { private const string apiPath = "//api//sitecore//ItemCompareService//GetItem?id={id}&database=master&lang={lang}"; public JsonResult GetModifiedItems(string startDate, string endDate, string rootPath) { var sitecoreItems = new List<SitecoreItem>(); DateTime dtStartDate = Utility.GetDate(startDate); DateTime dtEndDate = Utility.GetDate(endDate); dtEndDate = dtEndDate.AddDays(1); endDate = dtEndDate.ToString("yyyyMMdd"); startDate = dtStartDate.ToString("yyyyMMdd"); rootPath = rootPath.Trim('/'); rootPath = "/" + rootPath + "/"; string sitecoreQuery = string.Format("fast:" + rootPath + "/*[@__Updated >= '{0}T000000' and @__Updated < '{1}T000000']", startDate, endDate); var result = Utility.GetItems(sitecoreQuery); if (result.Count > 0) { int serialNo = 1; foreach (var item in result) { sitecoreItems.Add(new SitecoreItem { Id = item.ID.Guid.ToString().ToUpper(), Path = item.Paths.FullPath, SerialNo = serialNo, CreatedDate = Utility.GetIsoDate(item.Fields["__Created"].Value), UpdateDate = Utility.GetIsoDate(item.Fields["__Updated"].Value), UpdatedBy = Utility.GetUserName(item.Fields["__Updated by"].Value) }); serialNo++; } } return Json(sitecoreItems, JsonRequestBehavior.AllowGet); } public JsonResult GetItem(string id, string database, string lang) { var fieldValues = new List<FieldValue>(); var db = Factory.GetDatabase(database); var siecoreId = new Sitecore.Data.ID(new Guid(id)); //Check the language if (string.IsNullOrEmpty(lang)) { lang = "en"; } var language = Sitecore.Globalization.Language.Parse(lang); var item = db.GetItem(siecoreId, language); if (item != null) { item.Fields.ReadAll(); FieldCollection fieldCollection = item.Fields; foreach (Field field in fieldCollection) { //Use the following check if you do not want //the Sitecore Standard Fields if (!field.Name.StartsWith("__")) { fieldValues.Add(new FieldValue { Name = field.Name, Value = HttpUtility.HtmlEncode(field.Value) }); } else if (field.Name == "__Renderings") { fieldValues.Add(new FieldValue { Name = field.Name, Value = HttpUtility.HtmlEncode(field.Value) }); } } } return Json(fieldValues, JsonRequestBehavior.AllowGet); } public JsonResult GetDifference(string id, string targetUrl, string lang) { var itemDifference = new ItemDifference { ErrorMessage = "", Items = new List<ItemDifferenceItem>() }; if (string.IsNullOrEmpty(lang)) { lang = "en"; } var localApiPath = apiPath.Replace("//", "/"); targetUrl = targetUrl.TrimEnd('/') + localApiPath; targetUrl = targetUrl.Replace("{id}", id); targetUrl = targetUrl.Replace("{lang}", lang); string currentUrl = Utility.GetDomainUrl(Request.Url.ToString()); currentUrl = currentUrl.TrimEnd('/') + localApiPath; currentUrl = currentUrl.Replace("{id}", id); currentUrl = currentUrl.Replace("{lang}", lang); string message = ""; try { string currentValue = ""; string targetValue = ""; ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12; try { using (var client = new WebClient()) { currentValue = client.DownloadString(currentUrl); } } catch { message = "Couldn't retrieve the difference. Error occured in api." + "\n\n" + currentUrl; } try { using (var client = new WebClient()) { targetValue = client.DownloadString(targetUrl); } } catch { if (string.IsNullOrEmpty(message)) { message = "Couldn't retrieve the difference. Error occured in api." + "\n\n" + targetUrl; } } if (string.IsNullOrEmpty(currentValue) || string.IsNullOrEmpty(targetValue)) { itemDifference.ErrorMessage = message; return Json(itemDifference, JsonRequestBehavior.AllowGet); } var targetFieldValues = Utility.GetFieldAndValuesNew(targetValue); var currentFieldValues = Utility.GetFieldAndValuesNew(currentValue); if (targetFieldValues == null || targetFieldValues.Count == 0) { itemDifference.ErrorMessage = "The content doesn't exist in target environment."; return Json(itemDifference, JsonRequestBehavior.AllowGet); } itemDifference.Items = Utility.GetItemDifference(currentFieldValues, targetFieldValues); if (itemDifference.Items.Count == 0) { itemDifference.ErrorMessage = "No difference found."; } } catch (Exception ex) { itemDifference.ErrorMessage = message + ex.Message + "\n\n" + ex.StackTrace + "\n\n" + currentUrl + "\n\n" + targetUrl; } return Json(itemDifference, JsonRequestBehavior.AllowGet); } [HttpPost] public JsonResult CreatePackage(string ids) { var response = new Package { Name = "" }; try { using (new Sitecore.SecurityModel.SecurityDisabler()) { Sitecore.Data.Database db = Factory.GetDatabase("master"); PackageProject document = new PackageProject(); document.Metadata.PackageName = "AN Item Package"; document.Metadata.Author = "Admin"; //Create source – source should be based on BaseSource ExplicitItemSource source = new ExplicitItemSource(); source.Name = "Sitecore"; string[] arrItemId = ids.Split('|'); foreach(string id in arrItemId) { var siecoreId = new Sitecore.Data.ID(new Guid(id)); var item = db.GetItem(siecoreId); source.Entries.Add(new ItemReference(item.Uri, false).ToString()); } document.Sources.Add(source); document.SaveProject = true; string packageName = "SitecoreItem_" + DateTime.Now.Ticks.ToString() + ".zip"; string folder = Settings.DataFolder + "\\packages\\"; response.Name = folder; //path where the zip file package is saved using (Sitecore.Install.Zip.PackageWriter writer = new Sitecore.Install.Zip.PackageWriter(folder + packageName)) { Sitecore.Context.SetActiveSite("shell"); writer.Initialize(Installer.CreateInstallationContext()); PackageGenerator.GeneratePackage(document, writer); Sitecore.Context.SetActiveSite("website"); } response.IsSuccess = true; response.Name = packageName; } } catch (Exception ex) { response.Name += ex.Message + "\n\n" + ex.StackTrace; } return Json(response); } public JsonResult IsFileExists(string fileName) { string folder = Settings.DataFolder + "\\packages\\"; string filePath = folder + fileName; if (System.IO.File.Exists(filePath)) { return Json(true, JsonRequestBehavior.AllowGet); } else { return Json(false, JsonRequestBehavior.AllowGet); } } public ActionResult Download() { string fileName = Request.QueryString["fileName"]; string folder = Settings.DataFolder + "\\packages\\"; string filePath = folder + fileName; if (System.IO.File.Exists(filePath)) { return File(filePath, System.Net.Mime.MediaTypeNames.Application.Zip, fileName); } else { return Content(fileName + " not found in directory. Please try after some time."); } } } }
Utility class
using Sitecore.Data.Items; using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using Sitecore.Configuration; using SC.ItemCompare.Model; using System.Web.Script.Serialization; namespace SC.ItemCompare.Helper { public static class Utility { public static DateTime GetDate(string date) { return DateTime.ParseExact(date, "dd MMMM yyyy", CultureInfo.InvariantCulture); } public static List<Item> GetItems(string sitecoreQuery) { var database = Factory.GetDatabase("master"); var contentItems = database.SelectItems(sitecoreQuery); var orderedContentItems = contentItems.OrderByDescending(x => x[Sitecore.FieldIDs.Updated]); var result = new List<Item>(); if (orderedContentItems != null && orderedContentItems.Any()) { result = orderedContentItems.ToList(); } return result; } public static string GetDomainUrl(string url) { Uri uri = new Uri(url); return uri.GetLeftPart(UriPartial.Authority); } public static List<FieldValue> GetFieldAndValues(string response) { var fields = new List<FieldValue>(); if (response.IndexOf("{", StringComparison.OrdinalIgnoreCase) >= 0 && response.IndexOf("}", StringComparison.OrdinalIgnoreCase) >= 0) { var values = new JavaScriptSerializer().Deserialize<Dictionary<string, string>>(response); foreach (KeyValuePair<string, string> entry in values) { fields.Add(new FieldValue { Name = entry.Key, Value = entry.Value }); } } return fields; } public static List<FieldValue> GetFieldAndValuesNew(string response) { List<FieldValue> fields; fields = new JavaScriptSerializer().Deserialize<List<FieldValue>>(response); return fields; } public static List<ItemDifferenceItem> GetItemDifference(List<FieldValue> currentFieldValues, List<FieldValue> targetFieldValues) { var ItemDifferenceItems = new List<ItemDifferenceItem>(); foreach (var fieldValue in currentFieldValues) { if (!targetFieldValues.Exists(fv => fv.Name == fieldValue.Name)) { ItemDifferenceItems.Add(new ItemDifferenceItem { FieldName = fieldValue.Name, CurrentEnvironmentValue = fieldValue.Value, TargetEnvironmentValue = "" }); } else { var targetFieldValue = targetFieldValues.FirstOrDefault(fv => fv.Name == fieldValue.Name); if (fieldValue.Value != targetFieldValue.Value) { ItemDifferenceItems.Add(new ItemDifferenceItem { FieldName = fieldValue.Name, CurrentEnvironmentValue = fieldValue.Value, TargetEnvironmentValue = targetFieldValue.Value }); } } } return ItemDifferenceItems; } public static string GetUserName(string name) { if (!string.IsNullOrEmpty(name) && name.IndexOf("\\", StringComparison.OrdinalIgnoreCase) >= 0) { return name.Substring(name.LastIndexOf("\\", StringComparison.OrdinalIgnoreCase)).Replace("\\", ""); } return name; } public static string GetIsoDate(string isoDate) { DateTime d = Sitecore.DateUtil.IsoDateToDateTime(isoDate); return d.ToString("dd-MMM-yyyy hh:mm tt"); } } }
Models
public class ItemDifferenceItem { public string FieldName { get; set; } public string CurrentEnvironmentValue { get; set; } public string TargetEnvironmentValue { get; set; } } public class FieldValue { public string Name { get; set; } public string Value { get; set; } } public class ItemDifference { public string ErrorMessage { get; set; } public List<ItemDifferenceItem> Items { get; set; } } public class Package { public string Name { get; set; } public bool IsSuccess { get; set; } } public class SitecoreItem { public int SerialNo { get; set; } public string Id { get; set; } public string Path { get; set; } public string CreatedDate { get; set; } public string UpdateDate { get; set; } public string UpdatedBy { get; set; } }
The .aspx page
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="CompareItems.aspx.cs" Inherits="ProcessUpdatePackage.SC.Admin.CompareItems" %> <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <link rel="shortcut icon" href="/favicon.ico" type="image/vnd.microsoft.icon" /> <title>Compare Sitecore Items</title> <link rel="stylesheet" type="text/css" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" /> <link rel="stylesheet" type="text/css" href="//code.jquery.com/ui/1.12.0/themes/smoothness/jquery-ui.css" /> </head> <body> <form id="form1" runat="server"> <div class="jumbotron text-center"> <p>Compare Sitecore Items</p> </div> <div class="container-fluid"> <div class="row"> <div class="col-lg-12"> <div class="form-inline text-center"> <div class="form-group"> <label>Start:</label> <input type="text" readonly="true" style="cursor: pointer;" class="form-control" id="txtStartDate" /> </div> <div class="form-group"> <label>End:</label> <input type="text" readonly="true" style="cursor: pointer;" class="form-control" id="txtEndDate" /> </div> <div class="form-group"> <label>Root:</label> <input type="text" class="form-control" id="txtRootPath" style="width: 375px;" value="/sitecore/content/" /> </div> <button type="button" id="btnSearch" class="btn btn-default">Search</button> </div> </div> </div> <div id="dvContent" class="row" style="margin-top: 40px; display: none;"> <div class="col-lg-12"> <div class="form-inline" style="margin-bottom: 20px;"> <div class="form-group"> <button type="button" id="btnCreatePackage" class="btn btn-default">Create Package</button> </div> <div class="form-group pull-right" style="margin-right: 20px;"> <label id="lblTotalRecords"></label> </div> </div> <table class="table table-bordered"> <thead class="bg-info"> <tr> <th colspan="8" style="text-align:right; background-color:white;"> <button type="button" id="btnCompareAll" class="btn btn-default">Compare All</button> </th> </tr> <tr> <th> <input id="chkSelectAll" type="checkbox" value="" /></th> <th style="width: 320px;">Id</th> <th style="width: 450px">Path</th> <th>Created Date (UTC)</th> <th>Updated Date (UTC)</th> <th>Updated By</th> <th>Status</th> <th><span class="glyphicon glyphicon-th-list" style="font-size: 24px; cursor: pointer" data-toggle="modal" data-target="#settingsModal" data-backdrop="static" data-keyboard="false"></span></th> </tr> </thead> <tbody id="searchBody"> </tbody> </table> </div> </div> <div id="dvLoader" class="row" style="display: none;"> <div class="col-lg-12"> <div class="text-center"> <img src="/sitecore/admin/images/Loader.gif" style="width: 200px;" /> </div> </div> </div> </div> <%--Modal Item Difference--%> <div id="myModal" class="modal fade" role="dialog"> <div class="modal-dialog modal-lg"> <!-- Modal content--> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal">×</button> <h4 class="modal-title">Item Difference</h4> </div> <div class="modal-body"> <table id="tblDifference" class="table" style="display: none;"> <thead> <tr> <th>Field</th> <th>Current Environment Value</th> <th>Target Environment Value</th> </tr> </thead> <tbody id="modalBody"> </tbody> </table> <p id="errorMessage" style="display: none;"></p> <div id="dvModalLoader" class="text-center"> <img src="/sitecore/admin/images/Loader.gif" style="width: 200px;" /> </div> </div> <div class="modal-footer"> <button type="button" class="btn btn-default" data-dismiss="modal">Close</button> </div> </div> </div> </div> <%--Modal Settings--%> <div id="settingsModal" class="modal fade" role="dialog"> <div class="modal-dialog modal-lg"> <!-- Modal content--> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" id="btnCloseSettings">×</button> <h4 class="modal-title">Settings</h4> </div> <div class="modal-body"> <div class="form-horizontal"> <div class="form-group"> <label class="control-label col-sm-2">Compare with:</label> <div class="col-sm-10"> <input type="text" class="form-control" id="txtEnvironmentUrl" value="http://auth2.site.com" /> </div> </div> <div class="form-group"> <label class="control-label col-sm-2">Language:</label> <div class="col-sm-10"> <input type="text" class="form-control" id="txtLanguage" value="en" maxlength="6" /> </div> </div> </div> </div> <div class="modal-footer"> <button type="button" class="btn btn-default" data-dismiss="modal">OK</button> </div> </div> </div> </div> <%--Download Package Modal--%> <div id="downloadPackageModal" class="modal fade" role="dialog"> <div class="modal-dialog modal-lg"> <!-- Modal content--> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal">×</button> <h4 class="modal-title">Download Package</h4> </div> <div class="modal-body"> <p id="errorMessageDownloadPackage" style="display: none;"></p> <div id="dvModalLoaderDownloadPackage" class="text-center"> <img src="/sitecore/admin/images/Loader.gif" style="width: 200px;" /> </div> <div id="dvDownloadPackage" class="text-center"> <span id="spnDownloadPackage" class="glyphicon glyphicon-download-alt" style="font-size: 28px; cursor: pointer"></span> </div> </div> <div class="modal-footer"> <button type="button" class="btn btn-default" data-dismiss="modal">Close</button> </div> </div> </div> </div> <script type="text/template" data-template="listitem"> <tr> <td> <input type="checkbox" data-id="${Id}" class="chkSelect" /></td> <td>${Id}</td> <td>${Path}</td> <td>${CreatedDate}</td> <td>${UpdateDate}</td> <td>${UpdatedBy}</td> <td><span class="badge"></span></td> <td> <button type="button" data-id="${Id}" class="btn btn-default btnCompare" data-toggle="modal" data-target="#myModal">Compare</button></td> </tr> </script> <script type="text/template" data-template="listitemDifference"> <tr> <td>${FieldName}</td> <td>${CurrentEnvironmentValue}</td> <td>${TargetEnvironmentValue}</td> </tr> </script> <script type="text/javascript" src="//code.jquery.com/jquery-2.2.4.min.js"></script> <script type="text/javascript" src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script> <script type="text/javascript" src="//code.jquery.com/ui/1.12.0/jquery-ui.min.js"></script> <script type="text/javascript" src="/sitecore/admin/js/itemCompare.js"></script> </form> </body> </html>
The aspx.cs page
public partial class CompareItems : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { CheckSecurity(); } protected void CheckSecurity() { if (Sitecore.Context.User.IsAdministrator) { return; } var site = Sitecore.Context.Site; string loginPage = (site != null ? site.LoginPage : ""); if (loginPage.Length > 0) { string url = "/sitecore/admin/login.aspx?returnUrl=/sitecore/admin/compareItems.aspx"; Response.Redirect(url, true); } } }
The JS Script
function trimText(x) { return x.replace(/^\s+|\s+$/gm, ''); } function addDays(date, days) { var result = new Date(date); result.setDate(result.getDate() + days); return result; } function render(props) { return function (tok, i) { return (i % 2) ? props[tok] : tok; }; } function isUrlValid(userInput) { var res = userInput.match(/(http(s)?:\/\/.)?(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)/g); return res != null; } function populateSearchData(items) { var itemTpl = $('script[data-template="listitem"]').text().split(/\$\{(.+?)\}/g); $("#searchBody").html(""); if (items.length > 0) { $("#searchBody").append(items.map(function (item) { return itemTpl.map(render(item)).join(''); })); } else { $("#searchBody").html("<tr><td colspan='7' align='center'>No results found.</td></tr>"); } $("#lblTotalRecords").html("Total Records:" + items.length); } function populateDifference(items) { var itemTpl = $('script[data-template="listitemDifference"]').text().split(/\$\{(.+?)\}/g); $("#modalBody").html(""); $("#modalBody").append(items.map(function (item) { return itemTpl.map(render(item)).join(''); })); } function populateTargetUrl() { var environments = []; environments.push({ current: "local.site.com", target: "auth5.site.com" }); environments.push({ current: "auth5.site.com", target: "auth2.site.com" }); environments.push({ current: "auth2.site.com", target: "auth1.site.com" }); environments.push({ current: "auth1.site.com", target: "auth.site.com" }); var currentHost = document.location.host; var protocol = "http://"; for (var count = 0; count < environments.length; count++) { if (environments[count].current === currentHost) { var targetEnvUrl = protocol + environments[count].target + "/"; $("#txtEnvironmentUrl").val(targetEnvUrl); break; } } } function PopulateDatePicker() { $("#txtStartDate").datepicker({ dateFormat: "dd MM yy", maxDate: 0, minDate: '-24m' }); $("#txtStartDate").datepicker().datepicker("setDate", addDays(new Date(), -30)); $("#txtEndDate").datepicker({ dateFormat: "dd MM yy", maxDate: 0, minDate: '-3m' }); $("#txtEndDate").datepicker().datepicker("setDate", new Date()); } function searchButtonClickEvent() { $("#btnSearch").click(function () { var startDate = $("#txtStartDate").val(); var endDate = $("#txtEndDate").val(); var rootPath = $("#txtRootPath").val(); rootPath = trimText(rootPath); $("#txtRootPath").parent().removeClass("has-error"); if (rootPath.indexOf("/sitecore/") < 0) { $("#txtRootPath").parent().addClass("has-error"); return; } $("#dvContent").hide(); $("#dvLoader").show(); $("#lblTotalRecords").html(""); $.ajax({ type: "GET", url: "/api/sitecore/ItemCompareService/GetModifiedItems?startDate=" + startDate + "&endDate=" + endDate + "&rootPath=" + rootPath, contentType: "application/json; charset=utf-8", success: function (response) { var items = response; populateSearchData(items); $("#dvContent").show(); $("#dvLoader").hide(); }, failure: function () { alert(response.d); $("#dvLoader").hide(); } }); }); } function compareButtonClickEvent() { $(document).on("click", ".btnCompare", function () { $("#modalBody").html(""); $("#tblDifference").hide(); $("#errorMessage").hide(); $("#errorMessage").html(""); $("#dvModalLoader").show(); var id = $(this).attr("data-id"); var targetUrl = $("#txtEnvironmentUrl").val(); $.ajax({ type: "GET", url: "/api/sitecore/ItemCompareService/GetDifference?id=" + id + "&targetUrl=" + targetUrl + "&lang=en", contentType: "application/json; charset=utf-8", success: function (response) { var res = response; $("#dvModalLoader").hide(); if (res.ErrorMessage !== "") { $("#errorMessage").html(res.ErrorMessage); $("#errorMessage").show(); } else { populateDifference(res.Items); $("#tblDifference").show(); } }, failure: function () { } }); }); } function compareAllbuttonClickEvent() { $(document).on("click", "#btnCompareAll", function () { var compareButtons = $(".btnCompare"); var badges = $(".badge"); for (var count = 0; count < compareButtons.length; count++) { var id = $(compareButtons[count]).attr("data-id"); var targetUrl = $("#txtEnvironmentUrl").val(); $.ajax({ type: "GET", url: "/api/sitecore/ItemCompareService/GetDifference?id=" + id + "&targetUrl=" + targetUrl + "&lang=en", contentType: "application/json; charset=utf-8", indexValue: count, success: function (response) { var res = response; if (res.ErrorMessage === "") { $(badges[this.indexValue]).html("DIFFERENT"); $(badges[this.indexValue]).css("background-color", "red"); } else if (res.ErrorMessage === "No difference found.") { $(badges[this.indexValue]).html("NO DIFFERENCE"); $(badges[this.indexValue]).css("background-color", "green"); } else { $(badges[this.indexValue]).html("NEW"); $(badges[this.indexValue]).css("background-color", "orange"); } }, failure: function () { } }); } }); } function closeSettingsModalClickEvent() { $("#btnCloseSettings").click(function () { var url = trimText($("#txtEnvironmentUrl").val()); var language = trimText($("#txtLanguage").val()); var isValid = true; $("#txtLanguage").parent().parent().removeClass("has-error"); $("#txtEnvironmentUrl").parent().parent().removeClass("has-error"); if (language === "") { $("#txtLanguage").parent().parent().addClass("has-error"); isValid = false; } if (url === "" || !isUrlValid(url)) { $("#txtEnvironmentUrl").parent().parent().addClass("has-error"); isValid = false; } if (isValid) { $("#settingsModal").modal("hide"); } }); } function createPackageButtonClickEvent() { $("#btnCreatePackage").click(function () { var itemIds = ""; $(".chkSelect").each(function () { if ($(this).is(":checked")) { var id = $(this).attr("data-id"); if (itemIds === "") { itemIds = id; } else { itemIds += "|" + id; } } }); if (itemIds === "") { alert("Please select at least one item."); return; } $("#errorMessageDownloadPackage").hide(); $("#dvModalLoaderDownloadPackage").show(); $("#dvDownloadPackage").hide(); $("#downloadPackageModal").modal("show"); $.ajax({ type: "POST", url: "/api/sitecore/ItemCompareService/CreatePackage", data: "ids=" + itemIds, success: function (response) { $("#dvModalLoaderDownloadPackage").hide(); if (!response.IsSuccess) { $("#errorMessageDownloadPackage").show(); $("#errorMessageDownloadPackage").html(response.Name); } else { $("#dvDownloadPackage").show(); $("#spnDownloadPackage").attr("data-name", response.Name); } } }); }); } $(function () { populateTargetUrl(); PopulateDatePicker(); //Search Button click event searchButtonClickEvent(); //Compare button click event compareButtonClickEvent(); compareAllbuttonClickEvent(); //Close settings modal click event closeSettingsModalClickEvent(); //Select all check box select event $("#chkSelectAll").change(function () { $(".chkSelect").prop("checked", $(this).is(":checked")); }); //Create package click event createPackageButtonClickEvent(); //Download Package click event $("#spnDownloadPackage").click(function () { var fileName = $(this).attr("data-name"); var url = window.location.protocol.replace(/:/g, '') + "://" + window.location.hostname + "//api/sitecore/ItemCompareService/Download?fileName=" + fileName; window.open(url); }); });
Superb article
LikeLike