Introduction

This SharePoint Maintenance Page has the ff. features

The Page uses jQuery and SharePoint REST API. This should work on SharePoint 2013 and Online.

 

How it works

 

HTML
Edit|Remove
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> 
<script language="Javascript" type="text/javascript"> 
    var threshholdwarning = 4000; 
    var delarchitemscount = 1000; 
 
    var myajaxhelper = {}; 
    var mycommon = {}; 
 
    myajaxhelper.getLists =  function (complete, failure) { 
        $.ajax({ 
            url: _spPageContextInfo.webAbsoluteUrl + "/_api/Web/Lists/?$filter=(IsCatalog eq false) and (Hidden eq false)", 
            method: "GET", 
            headers: { "Accept""application/json; odata=verbose" }, 
            success: function (data) { 
                complete(data); 
            }, 
            error: function (error) { 
                failure(error); 
            } 
        }); 
    }; 
 
    myajaxhelper.getListItems =  function (listname, complete, failure, query) { 
        $.ajax({ 
            url: _spPageContextInfo.webAbsoluteUrl + "/_api/web/lists/getbytitle('" + listname + "')/items?" + query, 
            method: "GET", 
            headers: { "Accept""application/json; odata=verbose" }, 
            success: function (data) { 
                complete(listname, data); 
            }, 
            error: function (data) { 
                failure(data.responseJSON.error); 
            } 
        }); 
    }; 
 
    myajaxhelper.createListItem = function (listName, itemProperties, complete, failure) { 
        $.ajax({ 
            url: _spPageContextInfo.webAbsoluteUrl + "/_api/web/lists/getbytitle('" + listName + "')/items", 
            type: "POST", 
            processData: false, 
            contentType: "application/json;odata=verbose", 
            data: JSON.stringify(itemProperties), 
            headers: { 
                "Accept""application/json;odata=verbose", 
                "X-RequestDigest": $("#__REQUESTDIGEST").val() 
            }, 
            success: function (data) { 
                complete(data.d); 
            }, 
            error: function (data) { 
                failure(data.responseJSON.error); 
            } 
        }); 
    } 
 
    myajaxhelper.deleteListItem = function (listname, itemid, complete, failure) { 
        $.ajax({ 
            url: _spPageContextInfo.webAbsoluteUrl + "/_api/Web/Lists/getByTitle('" + listname + "')/getItemById(" + itemid + ")", 
            type: "DELETE", 
            headers: { 
                "accept""application/json;odata=verbose", 
                "X-RequestDigest": $("#__REQUESTDIGEST").val(), 
                "If-Match""*" 
            }, 
            success: function (data) { 
                complete(itemid, data); 
            }, 
            error: function (error) { 
                failure(error); 
            } 
        }); 
    }; 
 
    mycommon.nodeWriter = function (textnode, color, targetelementid) { 
        var t = document.createTextNode(textnode); 
        var para = document.createElement("p"); 
        para.appendChild(t); 
        para.style.color = color; 
        document.getElementById(targetelementid).appendChild(para); 
    }; 
 
    mycommon.handleError = function (error) { 
        alert(JSON.stringify(error)); 
    }; 
 
    mycommon.buildListDropDown = function (data) { 
        data.d.results.forEach(function (item) { 
            $('#ListName').append($('<option>'{ 
                value: item.Title, 
                text: item.Title 
            })); 
        }); 
    }; 
 
    mycommon.GetItemTypeForListName = function (name) { 
        var itemType = "SP.Data." + name.charAt(0).toUpperCase() + name.slice(1) + "ListItem"; 
        var encItemType = itemType.replace(' ''_x0020_'); 
        return encItemType; 
    } 
 
    mycommon.copyListItem = function (sourceItem, sourceListName, targetListName, complete, failure) { 
        var copyItem = {}; 
        for (var propertyName in sourceItem) { 
            if (sourceItem.hasOwnProperty(propertyName)) { 
                if (sourceItem[propertyName] != null && sourceItem[propertyName].hasOwnProperty('__deferred'))  //exclude deffered objects  
                { 
                    continue; 
                } 
                if (propertyName == 'GUID' || propertyName == 'ID' || propertyName == 'Id'{ 
                    continue; 
                } 
                if (propertyName == '__metadata'{ 
                    var targetItemType = mycommon.GetItemTypeForListName(targetListName); 
                    copyItem['__metadata'] = { 'type': targetItemType }; 
                } 
                else { 
                    copyItem[propertyName] = sourceItem[propertyName]; 
                } 
            } 
        } 
 
        myajaxhelper.createListItem(targetListName, copyItem, function (targetItem) { 
            complete(sourceItem.ID, sourceListName, targetListName); 
        }, mycommon.handleError); 
    } 
 
    function logThreshold(listname, data) { 
        var textnode = listname + " | " + data.d.results.length; 
        var color = data.d.results.length >= threshholdwarning ? "red" : "green"; 
 
        mycommon.nodeWriter(textnode, color, "myHealth"); 
    } 
 
    function checkThreshold() { 
        $("#ListName > option").each(function () { 
            var listname = $(this).text(); 
 
            myajaxhelper.getListItems(listname, logThreshold, mycommon.handleError, "$top=5000"); 
        }); 
    }; 
 
    function logarchiveItem(sourceItemId, sourceListName, targetListName) { 
        var textnode = String.format('List Item {0} has been copied from {1} to {2}', sourceItemId, sourceListName, targetListName); 
        var color = "green"; 
        mycommon.nodeWriter(textnode, color, "myDeletedArchived"); 
 
        //Delete the Item once Copied successfully 
        myajaxhelper.deleteListItem(sourceListName, sourceItemId, logdeletedItem, mycommon.handleError); 
    } 
 
    function archiveItem(listname, data) { 
        var textnode = "Archiving " + data.d.results.length + " Item(s). from " + listname; 
        var color = "blue"; 
        mycommon.nodeWriter(textnode, color, "myDeletedArchived"); 
 
        data.d.results.forEach(function (item) { 
            mycommon.copyListItem(item, listname, listname + "Archive1", logarchiveItem, mycommon.handleError); 
        }); 
    } 
 
    function ArchiveItems() { 
        //Confirm Archive 
        var userinput = prompt("Type ARCHIVE to confirm."""); 
        if (userinput != "ARCHIVE"{ 
            if (userinput != null) { 
                alert("Invalid Input."); 
            } 
            return; 
        } 
 
        var customquery = $("#myCustomQuery").val() == "" ? "$top=" + delarchitemscount : $("#myCustomQuery").val(); 
        var listname = $("#ListName").val(); 
 
        myajaxhelper.getListItems(listname, archiveItem, mycommon.handleError, customquery); 
    }; 
 
    function logdeletedItem(itemid, data) { 
        var textnode = "Deleted Item ID: " + itemid; 
        var color = "green"; 
        mycommon.nodeWriter(textnode, color, "myDeletedArchived"); 
    } 
 
    function deleteItem(listname, data) { 
        var textnode = "Deleting " + data.d.results.length + " Item(s). from " + listname; 
        var color = "blue"; 
        mycommon.nodeWriter(textnode, color, "myDeletedArchived"); 
 
        data.d.results.forEach(function (item) { 
            myajaxhelper.deleteListItem(listname, item.ID, logdeletedItem, mycommon.handleError); 
        }); 
    } 
 
    function DeleteItems() { 
        //Confirm Delete 
        var userinput = prompt("Type DELETE to confirm."""); 
        if (userinput != "DELETE"{ 
            if (userinput != null) { 
                alert("Invalid Input."); 
            } 
            return; 
        } 
 
        var customquery = $("#myCustomQuery").val() == "" ? "$top=" + delarchitemscount : $("#myCustomQuery").val(); 
        var listname = $("#ListName").val(); 
 
        myajaxhelper.getListItems(listname, deleteItem, mycommon.handleError, customquery); 
    }; 
 
    function PopulateLists() { 
        myajaxhelper.getLists(mycommon.buildListDropDown, mycommon.handleError); 
    }; 
 
    function HealthCheck() { 
        //Check Lists and Libraries Threshold 
        checkThreshold(); 
    }; 
 
    $(document).ready(function () { 
        PopulateLists(); 
    }); 
</script> 
<div style="border-width: 1px; border-color: gray; padding: 20px; border-radius: 10px; border-style: dashed; width: 50%;"> 
    <p><b>SHAREPOINT MAINTENANCE</b></p> 
    <p>Dev Notes</p> 
    <ul> 
      <li>Deleted items are gone forever. They will not be in the recycle bin. Use with Caution</li> 
      <li>Create an Archive List Manually before Archiving a List. Use Format [SourceListName] + "Archive1" 
          <br/><i>Sample: SourceList = MyList then ArchiveList = MyListArchive1</i> 
      </li> 
      <li>Archived Items will be deleted from Source List. Archived Items will have a different Item ID from Source Item.</li> 
      <li>Validate your Custom REST API Query before passing the value below.</li> 
    </ul>  
    <br/> 
    <div> 
        <h3>Run Health Check for this Site.</h3> 
        <br/> 
        <input type="button" class="btn" value="Health Check" onclick="HealthCheck()" /> 
        <br/> 
        <br/> 
        <div id="myHealth" style="overflow:auto;max-height:200px;max-width:500px;"> 
        </div> 
    </div> 
    <br/> 
    <div> 
        <h3>Archive or Delete List/Library Items.</h3> 
        <br/> 
        <p> 
            <i>Put custom SharePoint REST API query below. If empty this will use default [$top=1000]. 
                <br/>Sample 1: $filter=ID eq 1  Sample 2: $filter=Created le datetime'2018-07-31T00%3a00%3a00'</i> 
        </p> 
        <input type="text" id="myCustomQuery" style="width:98%"/> 
        <br/> 
        <br/> 
        <span style="margin-right: 25px;"> 
            <b>Target List/Library</b> 
        </span> 
        <select type="text" id="ListName" /> 
        <br/> 
        <br/> 
        <input type="button" class="btn" value="Archive Items" onclick="ArchiveItems()" /> 
        <input type="button" class="btn" value="Delete Items" onclick="DeleteItems()" /> 
        <br/> 
        <div id="myDeletedArchived" style="overflow:auto;max-height:200px;max-width:500px;"> 
        </div> 
    </div> 
</div>
 

 

Running Health Check

Health Check will show all Lists & Libraries on your site with their Item Count.

Any List or Library with items greater than or equal to 4000 will be marked in RED else it will be in GREEN. The default value can be edited on the source code.



Deleting Items

You can delete Items or Documents from the Target List or Library using the Delete Items button. You have the option to provide a custom SharePoint REST API Filter using the Textbox. If Textbox is blank it will get the Top 1000 items by default.

A confirmation will prompt that requires you to type the word "DELETE" to proceed.

Below, I try to delete items from my ErrorLogging List using filter ID eq 0 which will not return any item.


Below, I try to delete items from ErrorLogging List without any filter. It shows the IDs of the Deleted Items. Running Health Check will show that ErrorLogging list is now empty.



Archiving Items

You can Archive Items or Documents from the Target List or Library using the Archive Items button. You have the option to provide a custom SharePoint REST API Filter using the Textbox. If Textbox is blank it will get the Top 1000 items by default. You need to create the Archive List/Library Manually before Archiving. Archive Lists should have the same columns and types from Source. IDs, Created, and Modified dates will not be retained.

A confirmation will prompt that requires you to type the word "ARCHIVE" to proceed.



Below, I try to archive items from my ProcessTasks List using a date filter. This will show you the IDs of the Items move from Source to Target List/Library.
These items will be deleted as well from Source List/Library.

Adding to your SharePoint Page

  1. Create a SharePoint Page (.aspx)
  2. Edit your Page and Click Embed Code
  3. Copy/Paste from the Source Code
  4. Save your Page