(Re)Implement live update of corpus and job lists.

This commit is contained in:
Patrick Jentsch committed 2019-08-29 15:12:08 +02:00
1 parent 1955d3c015
commit 7702de8770
5 files changed
+4975 -10

No files matched your search

+1 -3
View File
@@ -46,8 +46,7 @@ class CorpusList extends List {
}
/*
corporaUpdateHandler(delta) {
updateWithPatch(delta) {
var corpusElement, key, listItem;
for (key in delta) {
@@ -74,5 +73,4 @@ class CorpusList extends List {
}
}
}
*/
}
+1 -3
View File
@@ -49,8 +49,7 @@ class JobList extends List {
}
/*
jobsUpdateHandler(delta) {
updateWithPatch(delta) {
var jobElement, jobStatusElement, key, listItem;
for (key in delta) {
@@ -83,7 +82,6 @@ class JobList extends List {
}
}
}
*/
}
JobList.SERVICE_COLORS = {"nlp": "blue",
File diff suppressed because it is too large. Load diff
+36
View File
@@ -0,0 +1,36 @@
/* @preserve
* JSONPatch.js
*
* A Dharmafly project written by Thomas Parslow
* <tom@almostobsolete.net> and released with the kind permission of
* NetDev.
*
* Copyright 2011-2013 Thomas Parslow. All rights reserved.
* Permission is hereby granted,y free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*
* Implements the JSON Patch IETF RFC 6902 as specified at:
*
* http://tools.ietf.org/html/rfc6902
*
* Also implements the JSON Pointer IETF RFC 6901 as specified at:
*
* http://tools.ietf.org/html/rfc6901
*
*/
!function(root,factory){"object"==typeof exports?factory(module.exports):"function"==typeof define&&define.amd?define(["exports"],factory):(root.jsonpatch={},root.returnExports=factory(root.jsonpatch))}(this,function(exports){function InvalidPatch(message){Error.call(this,message),this.message=message}function PatchApplyError(message){Error.call(this,message),this.message=message}function clone(o){var cloned,key;if(isArray(o))return o.slice();if(null===o)return o;if("object"==typeof o){cloned={};for(key in o)Object.hasOwnProperty.call(o,key)&&(cloned[key]=o[key]);return cloned}return o}function deepEqual(a,b){var key;if(a===b)return!0;if(typeof a!=typeof b)return!1;if("object"!=typeof a)return!1;var aIsArray=isArray(a),bIsArray=isArray(b);if(aIsArray!==bIsArray)return!1;if(!aIsArray){for(key in a)if(Object.hasOwnProperty(a,key)&&(!Object.hasOwnProperty(b,key)||!deepEqual(a[key],b[key])))return!1;for(key in b)if(Object.hasOwnProperty(b,key)&&!Object.hasOwnProperty(a,key))return!1;return!0}if(a.length!=b.length)return!1;for(var i=0;i<a.length;i++)return deepEqual(a[i],b[i])}function validateOp(operation){var i,required;if(!operation.op)throw new InvalidPatch("Operation missing!");if(!_operationRequired.hasOwnProperty(operation.op))throw new InvalidPatch("Invalid operation!");if(!("path"in operation))throw new InvalidPatch("Path missing!");for(required=_operationRequired[operation.op],i=0;i<required.length;i++)if(!(required[i]in operation))throw new InvalidPatch(operation.op+" must have key "+required[i])}function compileOperation(operation,mutate){validateOp(operation);var op=operation.op,path=new JSONPointer(operation.path),value=operation.value,from=operation.from?new JSONPointer(operation.from):null;switch(op){case"add":return function(doc){return path.add(doc,value,mutate)};case"remove":return function(doc){return path.remove(doc,mutate)};case"replace":return function(doc){return path.replace(doc,value,mutate)};case"move":if(path.subsetOf(from))throw new InvalidPatch("destination must not be a child of source");return function(doc){var value=from.get(doc),intermediate=from.remove(doc,mutate);return path.add(intermediate,value,mutate)};case"copy":return function(doc){var value=from.get(doc);return path.add(doc,value,mutate)};case"test":return function(doc){if(!deepEqual(path.get(doc),value))throw new PatchApplyError("Test operation failed. Value did not match.");return doc}}}var apply_patch,JSONPatch,JSONPointer,_operationRequired,isArray;isArray=Array.isArray||function(obj){return"[object Array]"==Object.prototype.toString.call(obj)},exports.apply_patch=apply_patch=function(doc,patch){return new JSONPatch(patch).apply(doc)},exports.InvalidPatch=InvalidPatch,InvalidPatch.prototype=new Error,exports.PatchApplyError=PatchApplyError,PatchApplyError.prototype=new Error,exports.JSONPointer=JSONPointer=function(pathStr){var i,split,path=[];if(split=pathStr.split("/"),""!==split[0])throw new InvalidPatch("JSONPointer must start with a slash (or be an empty string)!");for(i=1;i<split.length;i++)path[i-1]=split[i].replace(/~1/g,"/").replace(/~0/g,"~");this.path=path,this.length=path.length},JSONPointer.prototype._get_segment=function(index,node){var segment=this.path[index];if(isArray(node))if("-"===segment)segment=node.length;else{if(!segment.match(/^[0-9]*$/))throw new PatchApplyError("Expected a number to segment an array");segment=parseInt(segment,10)}return segment},JSONPointer.prototype._action=function(doc,handler,mutate){function follow_pointer(node,index){var segment,subnode;if(mutate||(node=clone(node)),segment=that._get_segment(index,node),index==that.path.length-1)node=handler(node,segment);else{if(isArray(node)){if(node.length<=segment)throw new PatchApplyError("Path not found in document")}else{if("object"!=typeof node)throw new PatchApplyError("Path not found in document");if(!Object.hasOwnProperty.call(node,segment))throw new PatchApplyError("Path not found in document")}subnode=follow_pointer(node[segment],index+1),mutate||(node[segment]=subnode)}return node}var that=this;return follow_pointer(doc,0)},JSONPointer.prototype.add=function(doc,value,mutate){return 0===this.length?value:this._action(doc,function(node,lastSegment){if(isArray(node)){if(lastSegment>node.length)throw new PatchApplyError("Add operation must not attempt to create a sparse array!");node.splice(lastSegment,0,clone(value))}else node[lastSegment]=clone(value);return node},mutate)},JSONPointer.prototype.remove=function(doc,mutate){return 0===this.length?void 0:this._action(doc,function(node,lastSegment){if(!Object.hasOwnProperty.call(node,lastSegment))throw new PatchApplyError("Remove operation must point to an existing value!");return isArray(node)?node.splice(lastSegment,1):delete node[lastSegment],node},mutate)},JSONPointer.prototype.replace=function(doc,value,mutate){return 0===this.length?value:this._action(doc,function(node,lastSegment){if(!Object.hasOwnProperty.call(node,lastSegment))throw new PatchApplyError("Replace operLine truncated
+24 -4
View File
@@ -12,6 +12,8 @@
<link type="text/css" rel="stylesheet" href="{{ url_for('static', filename='css/materialize.min.css') }}" media="screen,projection"/>
<link type="text/css" rel="stylesheet" href="{{ url_for('static', filename='css/opaque.css') }}" media="screen,projection"/>
<script src="{{ url_for('static', filename='js/socket.io.js') }}"></script>
<script src="{{ url_for('static', filename='js/jsonpatch.min.js') }}"></script>
<script src="{{ url_for('static', filename='js/jsondiffpatch.umd.js') }}"></script>
<script src="{{ url_for('static', filename='js/list.js') }}"></script>
<script src="{{ url_for('static', filename='js/list.utils.js') }}"></script>
<script src="{{ url_for('static', filename='js/CorpusList.js') }}"></script>
@@ -21,29 +23,47 @@
var corporaSubscribers = [];
var jobs;
var jobsSubscribers = [];
</script>
<script>
var socket = io();
socket.on('init-corpora', function(msg) {
var subscriber;
corpora = JSON.parse(msg);
for (subscriber of corporaSubscribers) {subscriber.init();}
});
socket.on('init-jobs', function(msg) {
var subscriber;
jobs = JSON.parse(msg);
for (subscriber of jobsSubscribers) {subscriber.init();}
});
socket.on('update-corpora', function(msg) {
console.log(msg);
var patch, patchedCorpora, subscriber;
patch = JSON.parse(msg);
patchedCorpora = jsonpatch.apply_patch(corpora, patch);
delta = jsondiffpatch.diff(corpora, patchedCorpora);
corpora = patchedCorpora;
for (subscriber of corporaSubscribers) {
subscriber.updateWithPatch(delta);
}
});
socket.on('update-jobs', function(msg) {
console.log(msg);
var patch, patchedJobs, subscriber;
patch = JSON.parse(msg);
patchedJobs = jsonpatch.apply_patch(jobs, patch);
delta = jsondiffpatch.diff(jobs, patchedJobs);
jobs = patchedJobs;
for (subscriber of jobsSubscribers) {
subscriber.updateWithPatch(delta);
}
});