How To store a List of revision for a record and apply those later

Can we store a records list of revision and apply those revisions,  when required ? Yes it can be done, it can be done using form script of any object.

1.Requirements

I assume that the reader of this article has a good understanding of  Java script, Jquery. User should have some knowledge on add or delete DOM elements. User should have some knowledge on Agileapps exposed Rest API and Ajax calls.

2.Challenges

While storing a list of revisions following challenges has to resolve.

  • Where to store those revisions and how to store?
  • How to get previous revisions of the current record ?
  • How to differentiate among multiple revisions of a record created by different users?
  • How to apply a revision , if record form layout got changed?
  • How many numbers of revisions a user can save?

3.Getting Started

  • Create a object lets name it "RevisionStore"
  • Create some fields 'Related Record', 'Related Object', 'User id', 'Revision data'.
  • Now open any object for script and write below scripts

 

Write below scripts in the Form onload script section.

 /*****   Create required custom buttons and section   *****/

var $revisionBtn = $('<button id="revBtn" class="mat-icon-button"><span class="mat-button-wrapper"><i class="material-icons">settings_backup_restore</i></span><div class="mat-button-ripple mat-ripple mat-button-ripple-round" matripple=""></div><div class="mat-button-focus-overlay"></div></button>'); 

var $addBtn = $('<button id="addBtn" class="mat-icon-button"><span class="mat-button-wrapper"><i class="material-icons">add_to_queue</i></span><div class="mat-button-ripple mat-ripple mat-button-ripple-round" matripple=""></div><div class="mat-button-focus-overlay"></div></button>');

var $revBtn = $('<input type="button" id="revBtn" style="margin-left:2px" value="rev" class="mat-raised-button mat-primary"/>'); 

var $revisionSection = $('<div id=""><p id="revSection"></p></div>'); 

/*****   
 *Define eveents and place of bttons and define
 *Define crueent Object name and id
 *Define Revision Object name and id
 *Devine How many revisions you want to store for a record
*****/

$addBtn.appendTo($(".left-container")[0]);
$revisionBtn.appendTo($(".left-container")[0]);
$revisionSection.appendTo($('aac-record-actions'));
 var objectName='Object_1test';
 var revisionObjectId = '1014657a89fe41d2bae161b4bdcb3463';
 var userId=getUserDetails().id;
 var revisionObjectName = 'RevisionStore';
 var revisionLength = 10;
 var currentObjectId = 'ca5f9c94e27f4733a556ca3ef5ec30f7';

$('#revBtn').click(function() { 
$("#revSection").slideToggle(); 
})
  
$('#addBtn').click(function() { 
setRevision(); 
})
  
$('#revBtn').click();
puplateRevisions();

In the Reusable function sections writhe below script

 /*****   Show all the existing revisions of a record   *****/
 
function puplateRevisions() {
$.ajax({ 
  type: 'GET', 
  url: "/networking/rest/execSQL?sql=select * from "+revisionObjectName+" where related_record='"+recordId+"' AND related_object='"+objectId+"' AND user_id='"+userId+"'",
  contentType: 'application/xml', 
  Accept:'application/xml', 
  dataType: 'json', 
  success: function (data) 
{
    if (data.platform.recordCount == '1') {
    var revisionData = JSON.parse(data.platform.record.revision_data);
    var revisionRecordId = data.platform.record.id;
    var revNum=0;
  while(revNum<revisionData.revision.length) {
  var recordData=revisionData.revision[revNum];
  var newId='revBtn'+revNum;
  var value='revision'+(revNum+1);
  var $revBtn = $('<input type="button" id='+newId+' style="margin-left:12px" value='+value+' class="mat-raised-button mat-primary"/>'); 
  $revBtn.appendTo($("#revSection")); 
  $('#'+newId).click(function() {
    var revisionNum=parseInt(this.value[this.value.length-1])-1;
applyRevision(revisionData.revision[revisionNum], revisionNum, revisionRecordId, revisionData);
})
  revNum++;
}
       
 
}
 }
 
});
 
/*****   Apply a pirticular revision   *****/  
 
function applyRevision(data, revisionNum, rid, rvData) {
  var inputJson = '{"platform":{"record":'+JSON.stringify(data)+'}}';
  $.ajax({
      type: 'PUT',
      url: '/networking/rest/record/'+currentObjectId+'/'+recordId,
      contentType: 'application/json',
      Accept:'application/json',
      data: inputJson, 
      dataType: 'json',
      success: function (data2) 
      {
        alert('Revision applied');
    deleteRevision(rvData, revisionNum, rid);
    location.reload();
      }
 
    });
  
}
 
/*****   Delate a list of revision after apply   *****/
function deleteRevision(data, revisionNum, rid) {
var dataJson = data;
  while(dataJson.revision.length > revisionNum) {
  dataJson.revision.pop();
  }
    var inputXML = "<platform><record><revision_data>"+JSON.stringify(dataJson)+"</revision_data></record></platform>";
     $.ajax({
      type: 'PUT',
      url: '/networking/rest/record/'+revisionObjectId+'/'+rid,
      contentType: 'application/xml',
      Accept:'application/xml',
      data: inputXML, 
      dataType: 'json',
      success: function (data) 
      {
      }
 
    });
}
 
/*****   Set a revions by clicking add revision button   *****/
function setRevision() { 
  $.ajax({ 
  type: 'GET', 
  url: "/networking/rest/execSQL?sql=select * from "+objectName+" where id="+recordId, 
  contentType: 'application/xml', 
  Accept:'application/xml', 
  dataType: 'json', 
  success: function (data) 
{
    var len=0;
    while(Object.keys(data.platform.record).length >len)
      {
    var key=Object.keys(data.platform.record)[len];
    var valueType=typeof Object.values(data.platform.record)[len];
      if (valueType == 'object') {
    data.platform.record[key] = '';
    }
      len++;
   
        isRevisionExist(data.platform.record) 
}
});
   
 
}
 
/*****   Add a recrod to revsion store   *****/  
function addDataToRevisionStore(revData) { 
  revData = JSON.stringify({revision:[JSON.parse(revData)]});
  var inputXML = "<platform><record><revision_data>"+revData+"</revision_data>"
      +"<related_object>"+objectId+"</related_object>"
      +"<related_record>"+recordId+"</related_record>"
      +"<user_id>"+userId+"</user_id>"
      +"</record></platform>"; 
 
    // Use jQuery's ajax method to invoke the REST API
    $.ajax({
      type: 'POST',
      url: '/networking/rest/record/'+revisionObjectId,
      contentType: 'application/xml',
      Accept:'application/xml',
      data: inputXML, 
      dataType: 'json',
      success: function (data) 
      {
        alert('Revision saved'); 
      }
 
    });
}
 
/*****   Check if a revision already present for the current record   *****/
function isRevisionExist(currentData) {
 $.ajax({ 
  type: 'GET', 
  url: "/networking/rest/execSQL?sql=select * from "+revisionObjectName+" where related_record='"+recordId+"' AND related_object='"+objectId+"' AND user_id='"+userId+"'",
  contentType: 'application/xml', 
  Accept:'application/xml', 
  dataType: 'json', 
  success: function (data) 
{
    if (data.platform.recordCount == '0') {
  addDataToRevisionStore(JSON.stringify(currentData));
  } else { 
    updateRevision(data.platform.record.revision_data, data.platform.record.id,currentData);
        }
  }
 
});
}
 
/*****   Update revision store record for existing recrods   *****/  
function updateRevision(data,id, currentData) {
  var dataJson = JSON.parse(data);
    if (dataJson.revision.length < revisionLength) {
    dataJson['revision'].push(currentData);
    var inputXML = "<platform><record><revision_data>"+JSON.stringify(dataJson)+"</revision_data></record></platform>";
      $.ajax({
      type: 'PUT',
      url: '/networking/rest/record/'+revisionObjectId+'/'+id,
      contentType: 'application/xml',
      Accept:'application/xml',
      data: inputXML, 
      dataType: 'json',
      success: function (data) 
      {
        alert('Revision saved'); 
      }
 
    });
    
    } else {
    dataJson.revision.shift();
    alert('As you selected Max storage '+revisionLength+', it will delete the oldest revision');
    updateRevision(JSON.stringify(dataJson), id, currentData);
    }
  }
 
4. Challenges Achived
  • For the lsit of revisions of a record it will create a new record in RevisionStore object and store its metadata in revision_data field.
  • User can define how many revisions he want to store for a record.
  • Once  a revsion applied It will delete the newer revisions till the applied revision.
  • The revisions of a record are specific to user. Only creator of the revision can only apply the same revision to the record.

5.Considerations

  • Once user applies a revision it will delete the older revisions till that revision, for example: suppose there are 10 revisions of a record user applies 8th revision then 8th,9th and 10th revision will remove.
  • User are not allowed to change the records of RevisionStore object. Otherwise it may imact whilie applying revision.
  • User should not use junction object field while creating revision.
  • If there are already max number of revisions and user wants to add a new revision, then user has to change the max limit in script , otherwise it will delete the oldest revision and add the current revision.
  • User should not change the internal object name of revision object or applied object, if it changes then user has to change in script as well.

6.Anonymous user access

  • This revision can be accessible to creator of it only.
  • Users can not access others revision and apply.
  • User can add as many as number of revisions he want. Max limit has to be defined in script.
  • Max number of revisions are same for all user.

 

7. Note

  • This capability is not applicable for image/file field
  • This is not applicable for Junction object field.