mirror of
https://gitlab.ub.uni-bielefeld.de/sfb1288inf/nopaque.git
synced 2024-12-25 02:44:18 +00:00
Use JSON patch the correct way!
This commit is contained in:
parent
7702de8770
commit
8f3c53dad2
@ -45,8 +45,8 @@ def background_task(user_id, session_id):
|
|||||||
with app.app_context():
|
with app.app_context():
|
||||||
user = db.session.query(User).filter_by(id=user_id).first()
|
user = db.session.query(User).filter_by(id=user_id).first()
|
||||||
''' Get current values from the database. '''
|
''' Get current values from the database. '''
|
||||||
corpora = list(map(lambda x: x.to_dict(), user.corpora))
|
corpora = user.corpora_as_dict()
|
||||||
jobs = list(map(lambda x: x.to_dict(), user.jobs))
|
jobs = user.jobs_as_dict()
|
||||||
''' Send initial values. '''
|
''' Send initial values. '''
|
||||||
socketio.emit('init-corpora',
|
socketio.emit('init-corpora',
|
||||||
json.dumps(corpora),
|
json.dumps(corpora),
|
||||||
@ -59,8 +59,8 @@ def background_task(user_id, session_id):
|
|||||||
# print(session_id + ' running')
|
# print(session_id + ' running')
|
||||||
# socketio.emit('message', 'heartbeat', room=session_id)
|
# socketio.emit('message', 'heartbeat', room=session_id)
|
||||||
''' Get current values from the database '''
|
''' Get current values from the database '''
|
||||||
new_corpora = list(map(lambda x: x.to_dict(), user.corpora))
|
new_corpora = user.corpora_as_dict()
|
||||||
new_jobs = list(map(lambda x: x.to_dict(), user.jobs))
|
new_jobs = user.jobs_as_dict()
|
||||||
''' Compute JSON patches. '''
|
''' Compute JSON patches. '''
|
||||||
corpus_patch = jsonpatch.JsonPatch.from_diff(corpora, new_corpora)
|
corpus_patch = jsonpatch.JsonPatch.from_diff(corpora, new_corpora)
|
||||||
jobs_patch = jsonpatch.JsonPatch.from_diff(jobs, new_jobs)
|
jobs_patch = jsonpatch.JsonPatch.from_diff(jobs, new_jobs)
|
||||||
|
@ -204,6 +204,17 @@ class User(UserMixin, db.Model):
|
|||||||
"""
|
"""
|
||||||
return self.can(Permission.ADMIN)
|
return self.can(Permission.ADMIN)
|
||||||
|
|
||||||
|
def corpora_as_dict(self):
|
||||||
|
corpora = {}
|
||||||
|
for corpus in self.corpora:
|
||||||
|
corpora[str(corpus.id)] = corpus.to_dict()
|
||||||
|
return corpora
|
||||||
|
|
||||||
|
def jobs_as_dict(self):
|
||||||
|
jobs = {}
|
||||||
|
for job in self.jobs:
|
||||||
|
jobs[str(job.id)] = job.to_dict()
|
||||||
|
return jobs
|
||||||
|
|
||||||
class AnonymousUser(AnonymousUserMixin):
|
class AnonymousUser(AnonymousUserMixin):
|
||||||
"""
|
"""
|
||||||
|
@ -5,30 +5,59 @@ class CorpusList extends List {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
init() {
|
_init() {
|
||||||
var corpus;
|
for (let [id, corpus] of Object.entries(corpora)) {
|
||||||
|
this.addCorpus(corpus);
|
||||||
for (corpus of corpora) {
|
|
||||||
this.list.appendChild(this.createCorpusElement(corpus));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.reIndex();
|
|
||||||
this.update();
|
|
||||||
List.updatePagination(this);
|
List.updatePagination(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
createCorpusElement(corpus) {
|
_update(patch) {
|
||||||
|
var item, operation, pathArray, valueName;
|
||||||
|
|
||||||
|
for (operation of patch) {
|
||||||
|
pathArray = operation.path.split("/").slice(1);
|
||||||
|
switch(operation.op) {
|
||||||
|
case "add":
|
||||||
|
this.addCorpus(operation.value);
|
||||||
|
break;
|
||||||
|
case "remove":
|
||||||
|
if (pathArray.length != 1) {break;}
|
||||||
|
this.remove("id", pathArray[0]);
|
||||||
|
break;
|
||||||
|
case "replace":
|
||||||
|
if (pathArray.length != 2) {break;}
|
||||||
|
item = this.get("id", pathArray[0])[0];
|
||||||
|
valueName = pathArray[1];
|
||||||
|
switch(valueName) {
|
||||||
|
case "description":
|
||||||
|
item.values({"description": operation.value});
|
||||||
|
break;
|
||||||
|
case "title":
|
||||||
|
item.values({"title": operation.value});
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
addCorpus(corpus) {
|
||||||
var corpusDescriptionElement, corpusElement, corpusIconElement,
|
var corpusDescriptionElement, corpusElement, corpusIconElement,
|
||||||
corpusTitleElement;
|
corpusTitleElement;
|
||||||
|
|
||||||
corpusDescriptionElement = document.createElement("p");
|
corpusDescriptionElement = document.createElement("p");
|
||||||
corpusDescriptionElement.dataset.key = "description";
|
corpusDescriptionElement.classList.add("description");
|
||||||
corpusDescriptionElement.innerText = corpus.description;
|
corpusDescriptionElement.innerText = corpus.description;
|
||||||
corpusElement = document.createElement("a");
|
corpusElement = document.createElement("a");
|
||||||
corpusElement.classList.add("avatar", "collection-item");
|
corpusElement.classList.add("avatar", "collection-item");
|
||||||
corpusElement.dataset.key = "id";
|
corpusElement.dataset.id = corpus.id;
|
||||||
corpusElement.dataset.value = corpus.id;
|
|
||||||
corpusElement.href = `/corpora/${corpus.id}`;
|
corpusElement.href = `/corpora/${corpus.id}`;
|
||||||
corpusIconElement = document.createElement("i");
|
corpusIconElement = document.createElement("i");
|
||||||
corpusIconElement.classList.add("circle", "material-icons");
|
corpusIconElement.classList.add("circle", "material-icons");
|
||||||
@ -42,35 +71,9 @@ class CorpusList extends List {
|
|||||||
corpusElement.appendChild(corpusTitleElement);
|
corpusElement.appendChild(corpusTitleElement);
|
||||||
corpusElement.appendChild(corpusDescriptionElement);
|
corpusElement.appendChild(corpusDescriptionElement);
|
||||||
|
|
||||||
return corpusElement;
|
this.add(
|
||||||
}
|
[{description: corpus.description, id: corpus.id, title: corpus.title}],
|
||||||
|
function(items) {items[0].elm = corpusElement;}
|
||||||
|
);
|
||||||
updateWithPatch(delta) {
|
|
||||||
var corpusElement, key, listItem;
|
|
||||||
|
|
||||||
for (key in delta) {
|
|
||||||
if (key === "_t") {continue;}
|
|
||||||
if (key.startsWith("_")) {
|
|
||||||
this.remove("id", delta[key][0].id);
|
|
||||||
} else if (Array.isArray(delta[key])) {
|
|
||||||
corpusElement = this.createCorpusElement(delta[key][0]);
|
|
||||||
listItem = this.add({"description": delta[key][0].description,
|
|
||||||
"title": delta[key][0].title,
|
|
||||||
"id": delta[key][0].id})[0];
|
|
||||||
if (listItem.elm) {
|
|
||||||
listItem.elm.replaceWith(corpusElement);
|
|
||||||
}
|
|
||||||
listItem.elm = corpusElement;
|
|
||||||
} else {
|
|
||||||
listItem = this.get("id", corpora[parseInt(key)].id)[0];
|
|
||||||
if (delta[key]["description"]) {
|
|
||||||
listItem.values({"description": delta[key]["description"][1]});
|
|
||||||
}
|
|
||||||
if (delta[key]["title"]) {
|
|
||||||
listItem.values({"title": delta[key]["title"][1]});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,22 +5,69 @@ class JobList extends List {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
init() {
|
_init() {
|
||||||
var job;
|
for (let [id, job] of Object.entries(jobs)) {
|
||||||
|
this.addJob(job);
|
||||||
for (job of jobs) {
|
|
||||||
this.list.appendChild(this.createJobElement(job));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.reIndex();
|
|
||||||
this.update();
|
|
||||||
List.updatePagination(this);
|
List.updatePagination(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
createJobElement(job) {
|
_update(patch) {
|
||||||
|
var item, jobStatusElement, newStatusColor, operation, pathArray, status,
|
||||||
|
statusColor, valueName;
|
||||||
|
|
||||||
|
for (operation of patch) {
|
||||||
|
pathArray = operation.path.split("/").slice(1);
|
||||||
|
switch(operation.op) {
|
||||||
|
case "add":
|
||||||
|
this.addJob(operation.value);
|
||||||
|
break;
|
||||||
|
case "remove":
|
||||||
|
if (pathArray.length != 1) {break;}
|
||||||
|
this.remove("id", pathArray[0]);
|
||||||
|
break;
|
||||||
|
case "replace":
|
||||||
|
if (pathArray.length != 2) {break;}
|
||||||
|
item = this.get("id", pathArray[0])[0];
|
||||||
|
valueName = pathArray[1];
|
||||||
|
switch(valueName) {
|
||||||
|
case "description":
|
||||||
|
item.values({"description": operation.value});
|
||||||
|
break;
|
||||||
|
case "status":
|
||||||
|
jobStatusElement = item.elm.querySelector(".status");
|
||||||
|
status = jobStatusElement.innerHTML;
|
||||||
|
if (JobList.STATUS_COLORS.hasOwnProperty(status)) {
|
||||||
|
statusColor = JobList.STATUS_COLORS[status];
|
||||||
|
} else {
|
||||||
|
statusColor = JobList.STATUS_COLORS['default'];
|
||||||
|
}
|
||||||
|
if (JobList.STATUS_COLORS.hasOwnProperty(operation.value)) {
|
||||||
|
newStatusColor = JobList.STATUS_COLORS[operation.value];
|
||||||
|
} else {
|
||||||
|
newStatusColor = JobList.STATUS_COLORS['default'];
|
||||||
|
}
|
||||||
|
jobStatusElement.classList.remove(statusColor);
|
||||||
|
jobStatusElement.classList.add(newStatusColor);
|
||||||
|
jobStatusElement.innerHTML = operation.value;
|
||||||
|
case "title":
|
||||||
|
item.values({"title": operation.value});
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
addJob(job) {
|
||||||
var jobDescriptionElement, jobElement, jobServiceElement, jobStatusElement,
|
var jobDescriptionElement, jobElement, jobServiceElement, jobStatusElement,
|
||||||
jobTitleElement;
|
jobTitleElement, serviceColor, serviceIcon, statusColor;
|
||||||
|
|
||||||
jobDescriptionElement = document.createElement("p");
|
jobDescriptionElement = document.createElement("p");
|
||||||
jobDescriptionElement.classList.add("description");
|
jobDescriptionElement.classList.add("description");
|
||||||
@ -29,11 +76,26 @@ class JobList extends List {
|
|||||||
jobElement.classList.add("avatar", "collection-item");
|
jobElement.classList.add("avatar", "collection-item");
|
||||||
jobElement.dataset.id = job.id;
|
jobElement.dataset.id = job.id;
|
||||||
jobElement.href = `/jobs/${job.id}`;
|
jobElement.href = `/jobs/${job.id}`;
|
||||||
|
if (JobList.SERVICE_COLORS.hasOwnProperty(job.service)) {
|
||||||
|
serviceColor = JobList.SERVICE_COLORS[job.service];
|
||||||
|
} else {
|
||||||
|
serviceColor = JobList.SERVICE_COLORS['default'];
|
||||||
|
}
|
||||||
|
if (JobList.SERVICE_ICONS.hasOwnProperty(job.service)) {
|
||||||
|
serviceIcon = JobList.SERVICE_ICONS[job.service];
|
||||||
|
} else {
|
||||||
|
serviceIcon = JobList.SERVICE_ICONS['default'];
|
||||||
|
}
|
||||||
jobServiceElement = document.createElement("i");
|
jobServiceElement = document.createElement("i");
|
||||||
jobServiceElement.classList.add("circle", "material-icons", "service-icon", JobList.SERVICE_COLORS[job.service]);
|
jobServiceElement.classList.add("circle", "material-icons", "service-icon", serviceColor);
|
||||||
jobServiceElement.innerText = JobList.SERVICE_ICONS[job.service];
|
jobServiceElement.innerText = serviceIcon;
|
||||||
|
if (JobList.STATUS_COLORS.hasOwnProperty(job.status)) {
|
||||||
|
statusColor = JobList.STATUS_COLORS[job.status];
|
||||||
|
} else {
|
||||||
|
statusColor = JobList.STATUS_COLORS['default'];
|
||||||
|
}
|
||||||
jobStatusElement = document.createElement("span");
|
jobStatusElement = document.createElement("span");
|
||||||
jobStatusElement.classList.add("badge", "new", "status", JobList.STATUS_COLORS[job.status]);
|
jobStatusElement.classList.add("badge", "new", "status", statusColor);
|
||||||
jobStatusElement.dataset.badgeCaption = "";
|
jobStatusElement.dataset.badgeCaption = "";
|
||||||
jobStatusElement.innerText = job.status;
|
jobStatusElement.innerText = job.status;
|
||||||
jobTitleElement = document.createElement("span");
|
jobTitleElement = document.createElement("span");
|
||||||
@ -45,45 +107,12 @@ class JobList extends List {
|
|||||||
jobElement.appendChild(jobTitleElement);
|
jobElement.appendChild(jobTitleElement);
|
||||||
jobElement.appendChild(jobDescriptionElement);
|
jobElement.appendChild(jobDescriptionElement);
|
||||||
|
|
||||||
return jobElement;
|
this.add(
|
||||||
}
|
[{description: job.description, id: job.id, title: job.title}],
|
||||||
|
function(items) {items[0].elm = jobElement;}
|
||||||
|
);
|
||||||
updateWithPatch(delta) {
|
|
||||||
var jobElement, jobStatusElement, key, listItem;
|
|
||||||
|
|
||||||
for (key in delta) {
|
|
||||||
if (key === "_t") {continue;}
|
|
||||||
if (key.startsWith("_")) {
|
|
||||||
this.remove("id", delta[key][0].id);
|
|
||||||
} else if (Array.isArray(delta[key])) {
|
|
||||||
jobElement = this.createJobElement(delta[key][0]);
|
|
||||||
listItem = this.add({"description": delta[key][0].description,
|
|
||||||
"title": delta[key][0].title,
|
|
||||||
"id": delta[key][0].id})[0];
|
|
||||||
if (listItem.elm) {
|
|
||||||
listItem.elm.replaceWith(jobElement);
|
|
||||||
}
|
|
||||||
listItem.elm = jobElement;
|
|
||||||
} else {
|
|
||||||
listItem = this.get("id", jobs[parseInt(key)].id)[0];
|
|
||||||
if (delta[key]["status"]) {
|
|
||||||
jobStatusElement = listItem.elm.querySelector(".status");
|
|
||||||
jobStatusElement.classList.remove(JobList.STATUS_COLORS[delta[key]["status"][0]]);
|
|
||||||
jobStatusElement.classList.add(JobList.STATUS_COLORS[delta[key]["status"][1]]);
|
|
||||||
jobStatusElement.innerHTML = delta[key]["status"][1];
|
|
||||||
}
|
|
||||||
if (delta[key]["description"]) {
|
|
||||||
listItem.values({"description": delta[key]["description"][1]});
|
|
||||||
}
|
|
||||||
if (delta[key]["title"]) {
|
|
||||||
listItem.values({"title": delta[key]["title"][1]});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
JobList.SERVICE_COLORS = {"nlp": "blue",
|
JobList.SERVICE_COLORS = {"nlp": "blue",
|
||||||
"ocr": "green",
|
"ocr": "green",
|
||||||
"default": "red"};
|
"default": "red"};
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -11,9 +11,8 @@
|
|||||||
<link type="text/css" rel="stylesheet" href="{{ url_for('static', filename='fonts/material-icons/material-icons.css') }}">
|
<link type="text/css" rel="stylesheet" href="{{ url_for('static', filename='fonts/material-icons/material-icons.css') }}">
|
||||||
<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/materialize.min.css') }}" media="screen,projection"/>
|
||||||
<link type="text/css" rel="stylesheet" href="{{ url_for('static', filename='css/opaque.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/jsonpatch.min.js') }}"></script>
|
||||||
<script src="{{ url_for('static', filename='js/jsondiffpatch.umd.js') }}"></script>
|
<script src="{{ url_for('static', filename='js/socket.io.js') }}"></script>
|
||||||
<script src="{{ url_for('static', filename='js/list.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/list.utils.js') }}"></script>
|
||||||
<script src="{{ url_for('static', filename='js/CorpusList.js') }}"></script>
|
<script src="{{ url_for('static', filename='js/CorpusList.js') }}"></script>
|
||||||
@ -29,7 +28,7 @@
|
|||||||
var subscriber;
|
var subscriber;
|
||||||
|
|
||||||
corpora = JSON.parse(msg);
|
corpora = JSON.parse(msg);
|
||||||
for (subscriber of corporaSubscribers) {subscriber.init();}
|
for (subscriber of corporaSubscribers) {subscriber._init();}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@ -37,7 +36,7 @@
|
|||||||
var subscriber;
|
var subscriber;
|
||||||
|
|
||||||
jobs = JSON.parse(msg);
|
jobs = JSON.parse(msg);
|
||||||
for (subscriber of jobsSubscribers) {subscriber.init();}
|
for (subscriber of jobsSubscribers) {subscriber._init();}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@ -45,12 +44,8 @@
|
|||||||
var patch, patchedCorpora, subscriber;
|
var patch, patchedCorpora, subscriber;
|
||||||
|
|
||||||
patch = JSON.parse(msg);
|
patch = JSON.parse(msg);
|
||||||
patchedCorpora = jsonpatch.apply_patch(corpora, patch);
|
corpora = jsonpatch.apply_patch(corpora, patch);
|
||||||
delta = jsondiffpatch.diff(corpora, patchedCorpora);
|
for (subscriber of corporaSubscribers) {subscriber._update(patch);}
|
||||||
corpora = patchedCorpora;
|
|
||||||
for (subscriber of corporaSubscribers) {
|
|
||||||
subscriber.updateWithPatch(delta);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@ -58,12 +53,8 @@
|
|||||||
var patch, patchedJobs, subscriber;
|
var patch, patchedJobs, subscriber;
|
||||||
|
|
||||||
patch = JSON.parse(msg);
|
patch = JSON.parse(msg);
|
||||||
patchedJobs = jsonpatch.apply_patch(jobs, patch);
|
jobs = jsonpatch.apply_patch(jobs, patch);
|
||||||
delta = jsondiffpatch.diff(jobs, patchedJobs);
|
for (subscriber of jobsSubscribers) {subscriber._update(patch);}
|
||||||
jobs = patchedJobs;
|
|
||||||
for (subscriber of jobsSubscribers) {
|
|
||||||
subscriber.updateWithPatch(delta);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
@ -31,11 +31,12 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script>
|
<script>
|
||||||
var corpusListOptions = {item: '<a><span class="title"></span><span class="description"></span></a>',
|
var corpusList = new CorpusList("corpus-list", {
|
||||||
page: 4,
|
item: '<div><span class="title"></span><span class="description"></span></div>',
|
||||||
pagination: true,
|
page: 4,
|
||||||
valueNames: ["description", "title", {data: ["id"]}]}
|
pagination: true,
|
||||||
var corpusList = new CorpusList("corpus-list", corpusListOptions);
|
valueNames: ["description", "title", {data: ["id"]}]
|
||||||
|
});
|
||||||
corpusList.on("filterComplete", List.updatePagination);
|
corpusList.on("filterComplete", List.updatePagination);
|
||||||
corpusList.on("searchComplete", List.updatePagination);
|
corpusList.on("searchComplete", List.updatePagination);
|
||||||
</script>
|
</script>
|
||||||
@ -74,13 +75,14 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script>
|
<script>
|
||||||
jobListOptions = {item: '<a><span class="title"></span><span class="description"></span></a>',
|
var jobList = new JobList("job-list", {
|
||||||
page: 4,
|
item: '<div><span class="title"></span><span class="description"></span></div>',
|
||||||
pagination: true,
|
page: 4,
|
||||||
valueNames: ["description", "title", {data: ["id"]}]}
|
pagination: true,
|
||||||
var jobList = new JobList("job-list", jobListOptions);
|
valueNames: ["description", "title", {data: ["id"]}]
|
||||||
jobList.on("filterComplete", List.updatePagination);
|
});
|
||||||
jobList.on("searchComplete", List.updatePagination);
|
jobList.on("filterComplete", List.updatePagination);
|
||||||
|
jobList.on("searchComplete", List.updatePagination);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div id="new-corpus-modal" class="modal">
|
<div id="new-corpus-modal" class="modal">
|
||||||
|
Loading…
Reference in New Issue
Block a user