Ignore:
Timestamp:
2023-11-21T19:35:39+13:00 (7 months ago)
Author:
anupama
Message:
  1. User comment edits (but not other document editor edits) happen before user comment deletes, as user comment deletes are based on metapositions and thus alter metapositions, which can affect user comment edits if these happened later. 2. When needed*, I'm also forcesyncing the user comment edits setMetadataArray AJAX call to perl, so that usercomment deletes (removeMetadataArray) can't happen simultaneously or in overlap with edits (setMetadataArray), which could in theory also mess up metapositions or anything else unforeseen. *When needed: Only if user comments' delete metadatapositions are earlier for any docid that has user comment edits. Still to do: if user comment rows are deleted where any of the cells are also edited, discard those pending edits (before calling setMetaArray) instead of passing them on to perl to process.
Location:
main/trunk/greenstone3/web/interfaces/default/js
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • main/trunk/greenstone3/web/interfaces/default/js/documentedit_scripts_usercomments.js

    r38423 r38424  
    6161    });
    6262    }
     63
     64    //alert("editing: " + JSON.stringify(docArray));
    6365   
    6466    return docArray;
     
    7274    var docids = Object.keys(docids_to_delCommentsMetapositions);
    7375    var docArray = [];
    74 
    7576    var i = 0;
    7677    for(i = 0; i < docids.length; i++) { //if(docids.length > 0) {
    7778      var _docid = docids[i];
    78       var delCommentsMetapositions = docids_to_delCommentsMetapositions[_docid];
    79      
     79      var delCommentsMetapositions = docids_to_delCommentsMetapositions[_docid].sort();
     80    // sort unnecessary as modmetadataaction.pm ensures (reverse) sort of metapositions
    8081
    8182      // build up the data structure for all the usercomments to be deleted
     
    105106    }
    106107
     108    //alert("deleting: " + JSON.stringify(docArray));
    107109    return docArray;
     110}
     111
     112// Determine if the user comment edits should be a synchronous AJAX call
     113function forceSyncUserCommentsEdits(editsDocArray, docids_to_delCommentsMetapositions) {
     114    var forceSync = false;
     115    var docids = Object.keys(docids_to_delCommentsMetapositions);
     116    if(docids.length == 0) { // no user comments deletions, so can process user comment edits async
     117    return false;
     118    }
     119    var edits = Object.keys(editsDocArray);
     120    if(edits.length == 0) { // no user comments edits
     121    return false;
     122    }
     123   
     124    var i = 0;
     125    for(i = 0; i < docids.length; i++) {
     126    var docid = docids[i];
     127
     128    // sort metapositions of deletes to get at lowest metaposition for this docid
     129    var metapositions = docids_to_delCommentsMetapositions[docid].sort(); // non-zero length array
     130    var lowestDelMetapos = metapositions[0]; // lowest metaposition at lowest index
     131   
     132    // https://javascript.plainenglish.io/check-if-an-array-contains-an-object-with-a-certain-property-value-in-javascript-5325295a5820
     133    // https://stackoverflow.com/questions/237104/how-do-i-check-if-an-array-includes-a-value-in-javascript/24827594#24827594
     134    // https://stackoverflow.com/questions/254302/how-can-i-determine-the-type-of-an-html-element-in-javascript
     135   
     136    var match_docRecord = editsDocArray.find((doc_rec) => doc_rec.docid === docid);
     137    if (match_docRecord) { // defined: this docid exists in an object in array
     138    //if(editsDocArray.some(item => item.docid === docid)) { // this docid exists in object
     139    //if(editsDocArray[docid] !== undefined) {
     140        // compare lowest metaposition of user comment to be deleted for this docid
     141        // against the highest metapos of user comment being edited for this docid
     142        // Metapositions array of deletes would contain metapos in ascending order
     143        var metatable = match_docRecord.metatable; // array of non-zero length
     144        //alert("Found docid match " + JSON.stringify(match_docRecord) + " comparing low metapos " + lowestDelMetapos);
     145         
     146        // https://www.digitalocean.com/community/tutorials/js-array-search-methods
     147        // Get array of user comment edits that are affected by deletions happening earlier
     148        // in the file (deletes that have a lower metapos than the metapos of the edit).
     149        var editsAffectedByDeletes = metatable.filter(meta_rec => meta_rec.metapos >= lowestDelMetapos);
     150        if(editsAffectedByDeletes.length > 0) { //if any edits affected by dels, forceSync ajax
     151        forceSync = true; // ensure we process all edits first before processing deletes
     152        //alert("FORCE_SYNC because " + JSON.stringify(editsAffectedByDeletes)
     153        //      + " are affected by deletes starting: " + lowestDelMetapos);
     154        } // else all user comment edits for this docid happen earlier (lower metapos) to deletes
     155    }
     156    }
     157    return forceSync;
    108158}
    109159
  • main/trunk/greenstone3/web/interfaces/default/js/documentedit_scripts_util.js

    r38422 r38424  
    501501    }
    502502
    503     // we can now process the deleted user comments, by organizing them into a single JSON
    504     // so that a single call to removeMetadataArray can delete them all more efficiently
    505     var docArray = getUserCommentsDeletions(
    506     userCommentsMetaFields, docids_to_delCommentsMetapositions);
    507    
    508     if(docArray.length > 0) {
    509     metadataChanges.push({type:'deleteUserComments', docArray:docArray});
    510     addCollectionToBuild(collection);
    511     }
    512     // clear used up vars https://bobbyhadz.com/blog/javascript-clear-object-delete-all-properties
    513     docArray = [];
    514     docids_to_delCommentsMetapositions = {};
     503   
    515504
    516505  }
    517506
    518507    var changes = changesToUpdate();
    519  
     508    // expect user comment edits to be processed async from deletes
     509    var forcesync_userCommentsEdits = false;
     510   
    520511  //Clean changes
    521512  ////editableInitStates = editableLastStates; // moved into processChangesLoop(): when all changes have successfully been processed.
     
    594585        }
    595586    }
     587
    596588   
    597589    if(userCommentsRowsChanged.length > 0) {
     
    605597    metadataChanges.push({type:'editUserComments',collection:collection,docArray:docArray});
    606598    addCollectionToBuild(collection);
     599    forcesync_userCommentsEdits = forceSyncUserCommentsEdits(docArray, docids_to_delCommentsMetapositions);
    607600    docArray = []; // clear it
    608601    }
     602
     603    // process user comment edits *before* user comment deletes,
     604    // since deletes change usercomments' metapos values which would affect
     605    // edits if edits were to happen after deletes
     606   
     607    // we can now process the deleted user comments, by organizing them into a single JSON
     608    // so that a single call to removeMetadataArray can delete them all more efficiently
     609    var docArray = getUserCommentsDeletions(
     610    userCommentsMetaFields, docids_to_delCommentsMetapositions);
     611   
     612    if(docArray.length > 0) {
     613    metadataChanges.push({type:'deleteUserComments', docArray:docArray});
     614    addCollectionToBuild(collection);
     615    }
     616    // clear used up vars https://bobbyhadz.com/blog/javascript-clear-object-delete-all-properties
     617    docArray = [];
     618    docids_to_delCommentsMetapositions = {};
     619   
    609620   
    610621    // Check for changes to any map editors in the document
     
    666677        if (change.type == "delete") {
    667678            gs.functions.removeArchivesMetadata(collection, gs.xsltParams.site_name, change.docID, change.name, null, encodeDelimiters(change.value), function(){callbackFunction();});
     679       
     680        } else if (change.type === "editUserComments") {           
     681           
     682            var edit_locations = "import|archives|index";
     683            //alert("editUserComments: " + JSON.stringify(change.docArray));
     684            gs.functions.setMetadataArray(
     685            collection,
     686            gs.xsltParams.site_name,
     687            change.docArray,
     688            "override", //metamode
     689            edit_locations,
     690            function(ajaxResult) {
     691                console.log("Edited comments in "+edit_locations);
     692                //callbackFunction();               
     693                if(!hadErrorResponseOnSave(ajaxResult)) {
     694                callbackFunction(); // move on to processing next & eventually rebuild
     695                }
     696            },
     697            // if necessary, forcesync AJAX call to make sure user comments edits are
     698            // all processed before deletes, as deletes can alter metapositions
     699            forcesync_userCommentsEdits, // false for asynchronous, see comment in gs.usercomments.addUserComment()
     700            function(ajaxError) {
     701                console.log("Set usercomments meta FAILED!");
     702               
     703                var errData = (ajaxError.responseText) ? ajaxError.responseText : ajaxError;
     704                //alert(gs.text.dse.setmeta_server_error + ". Set meta failed. Got: " + errData);
     705                console.log("A server side error occurred during setMetadataArray. (Is the server running?)\nNot proceeding further with saving and rebuilding. Got error: " + JSON.stringify(errData));
     706               
     707                alert("A server side error occurred during setMetadataArray. (Is the server running?)\nNot proceeding further with saving and rebuilding. Got error: " + JSON.stringify(errData));
     708            }
     709            );         
     710
    668711        } else if (change.type === "deleteUserComments") {
    669712           
     
    686729            );         
    687730
    688         }  else if (change.type === "editUserComments") {
    689             var edit_locations = "import|archives|index";
    690             //alert("editUserComments: " + JSON.stringify(change.docArray));
    691             gs.functions.setMetadataArray(
    692             collection,
    693             gs.xsltParams.site_name,
    694             change.docArray,
    695             "override", //metamode
    696             edit_locations,
    697             function(ajaxResult) {
    698                 console.log("Edited comments in "+edit_locations);
    699                 //callbackFunction();               
    700                 if(!hadErrorResponseOnSave(ajaxResult)) {
    701                 callbackFunction(); // move on to processing next & eventually rebuild
    702                 }               
    703             },
    704             false, // false for asynchronous, see comment in gs.usercomments.addUserComment()
    705             function(ajaxError) {
    706                 console.log("Set usercomments meta FAILED!");
    707                
    708                 var errData = (ajaxError.responseText) ? ajaxError.responseText : ajaxError;
    709                 //alert(gs.text.dse.setmeta_server_error + ". Set meta failed. Got: " + errData);
    710                 console.log("A server side error occurred during setMetadataArray. (Is the server running?)\nNot proceeding further with saving and rebuilding. Got error: " + JSON.stringify(errData));
    711                
    712                 alert("A server side error occurred during setMetadataArray. (Is the server running?)\nNot proceeding further with saving and rebuilding. Got error: " + JSON.stringify(errData));
    713             }
    714             );         
    715            
    716731        } else {
    717732          // Checking "if(change.metapos)" doesn't work for us as it becomes false when the property doesn't exist AND when the property is 0. But metapos IS 0 for us.
Note: See TracChangeset for help on using the changeset viewer.