Skip to content

Commit

Permalink
Integration of REST/API in client #5 (#367)
Browse files Browse the repository at this point in the history
* Updating of indexes after creating new objects on a server, links to objects were fixed, codacy issues
* Sent exceptions and logs to a server
* Removed outdated code
  • Loading branch information
bsekachev authored and nmanovic committed Mar 30, 2019
1 parent f0cf418 commit 1b8a8c3
Show file tree
Hide file tree
Showing 8 changed files with 108 additions and 83 deletions.
59 changes: 46 additions & 13 deletions cvat/apps/engine/static/engine/js/annotationSaver.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ class AnnotationSaverModel extends Listener {
this._version = initialData.version;
this._shapeCollection = shapeCollection;
this._initialObjects = [];
this._hash = objectHash(shapeCollection.export());

this._hash = this._getHash();

for (const shape of initialData.shapes) {
this._initialObjects[shape.id] = shape;
Expand Down Expand Up @@ -95,8 +96,20 @@ class AnnotationSaverModel extends Listener {
'points count': totalStat.points.annotation + totalStat.points.interpolation,
});

// const annotationLogs = Logger.getLogs();
// TODO: Save logs
const annotationLogs = Logger.getLogs();

try {
await $.ajax({
url: 'api/v1/server/logs',
type: 'POST',
data: JSON.stringify(annotationLogs),
});
} catch (errorData) {
annotationLogs.save();
const message = `Can not send logs. Code: ${errorData.status}. `
+ `Message: ${errorData.responseText || errorData.statusText}`;
throw Error(message);
}
}

_split(exported) {
Expand Down Expand Up @@ -156,31 +169,52 @@ class AnnotationSaverModel extends Listener {
return [created, updated, deleted];
}

_getHash() {
const exported = this._shapeCollection.export()[0];
return objectHash(exported);
}

_updateCreatedObjects(objectsToSave, savedObjects, mapping) {
const allSavedObjects = savedObjects.shapes.concat(savedObjects.tracks);
const allObjectsToSave = objectsToSave.shapes.concat(objectsToSave.tracks);
if (allSavedObjects.length !== allObjectsToSave.length) {
throw Error('Number of saved objects and objects to save is not match');
}

for (let idx = 0; idx < allSavedObjects.length; idx += 1) {
const objectModel = mapping.filter(el => el[0] === allObjectsToSave[idx])[0][1];
objectModel.serverID = allSavedObjects[idx].id;
}

this._shapeCollection.update();
}

notify(status, message = null) {
this._state.status = status;
this._state.message = message;
Listener.prototype.notify.call(this);
}

hasUnsavedChanges() {
return objectHash(this._shapeCollection.export()) !== this._hash;
return this._getHash() !== this._hash;
}

async save() {
this.notify('saveStart');
try {
const exported = this._shapeCollection.export();
const [exported, mapping] = this._shapeCollection.export();
const { flush } = this._shapeCollection;
if (flush) {
const data = Object.assign({}, exported, {
version: this._version += 1,
version: this._version,
tags: [],
});

this._version += 1;

this.notify('saveCreated');
const savedObjects = await this._put(data);
this._shapeCollection.cleanupClientObjects();
this._shapeCollection.import(savedObjects).update();
this._updateCreatedObjects(exported, savedObjects, mapping);
this._shapeCollection.flush = false;
for (const object of savedObjects.shapes.concat(savedObjects.tracks)) {
this._initialObjects[object.id] = object;
Expand All @@ -189,11 +223,9 @@ class AnnotationSaverModel extends Listener {
this._version = savedObjects.version;
} else {
const [created, updated, deleted] = this._split(exported);

this.notify('saveCreated');
const savedCreated = await this._create(created);
this._shapeCollection.cleanupClientObjects();
this._shapeCollection.import(savedCreated).update();
this._updateCreatedObjects(created, savedCreated, mapping);
for (const object of savedCreated.shapes.concat(savedCreated.tracks)) {
this._initialObjects[object.id] = object;
}
Expand All @@ -216,6 +248,8 @@ class AnnotationSaverModel extends Listener {

this._version = savedDeleted.version;
}

await this._logs();
} catch (error) {
this.notify('saveUnlocked');
this.notify('saveError', error);
Expand All @@ -226,8 +260,7 @@ class AnnotationSaverModel extends Listener {
throw Error(error);
}


this._hash = objectHash(this._shapeCollection.export());
this._hash = this._getHash();
this.notify('saveDone');

setTimeout(() => {
Expand Down
21 changes: 13 additions & 8 deletions cvat/apps/engine/static/engine/js/annotationUI.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
PolyshapeEditorModel:false
PolyshapeEditorView:false
PolyShapeView:false
serverRequest:false
ShapeBufferController:false
ShapeBufferModel:false
ShapeBufferView:false
Expand All @@ -46,6 +45,7 @@
showMessage:false
showOverlay:false
buildAnnotationSaver:false
LabelsInfo:false
*/


Expand Down Expand Up @@ -75,20 +75,25 @@ function callAnnotationUI(jid) {
}).fail(onError);
}

function initLogger(jobID) {
if (!Logger.initializeLogger('CVAT', jobID))
{
let message = 'Could not initialize Logger. Please immediately report the problem to support team';
async function initLogger(jobID) {
if (!Logger.initializeLogger('CVAT', jobID)) {
const message = 'Could not initialize Logger. Please immediately report the problem to support team';
console.error(message);
showMessage(message);
return;
}

Logger.setTimeThreshold(Logger.EventType.zoomImage);
let user = null;
try {
user = await $.get('/api/v1/users/self');
} catch (errorData) {
const message = `Could not get username. Code: ${errorData.status}. `
+ `Message: ${errorData.responseText || errorData.statusText}`;
showMessage(message);
}

serverRequest('/api/v1/users/self', function(response) {
Logger.setUsername(response.username);
});
Logger.setUsername(user.username);
}

function buildAnnotationUI(jobData, taskData, imageMetaData, annotationData, loadJobEvent) {
Expand Down
16 changes: 7 additions & 9 deletions cvat/apps/engine/static/engine/js/bootstrap.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,27 +10,25 @@
platform:false
*/

"use strict";

String.prototype.normalize = function() {
let target = this;
target = target.charAt(0).toUpperCase() + target.substr(1);
return target;
};

window.onload = function() {
window.onerror = function(errorMsg, url, lineNumber, colNumber, error) {
window.onload = function boot() {
window.onerror = function exception(errorMsg, url, lineNumber, colNumber, error) {
Logger.sendException({
message: errorMsg,
filename: url,
line: lineNumber,
column: colNumber ? colNumber : '',
column: colNumber ? String(colNumber) : '',
stack: error && error.stack ? error.stack : '',
browser: platform.name + ' ' + platform.version,
os: platform.os.toString(),
}).catch(() => { return; });
client: `${platform.name} ${platform.version}`,
system: platform.os.toString(),
}).catch(() => {});
};

let id = window.location.href.match('id=[0-9]+')[0].slice(3);
const id = window.location.href.match('id=[0-9]+')[0].slice(3);
callAnnotationUI(id);
};
26 changes: 13 additions & 13 deletions cvat/apps/engine/static/engine/js/logger.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ class LogCollection extends Array {
var LoggerHandler = function(applicationName, jobId)
{
this._application = applicationName;
this._tabId = Date.now().toString().substr(-6);
this._clientID = Date.now().toString().substr(-6);
this._jobId = jobId;
this._username = null;
this._userActivityHandler = null;
Expand All @@ -83,20 +83,18 @@ var LoggerHandler = function(applicationName, jobId)
return event;
};

this.sendExceptions = function(exceptions)
this.sendExceptions = function(exception)
{
for (let e of exceptions) {
this._extendEvent(e);
}
this._extendEvent(exception);

return new Promise( (resolve, reject) => {
let xhr = new XMLHttpRequest();
xhr.open('POST', '/save/exception/' + this._jobId);
xhr.open('POST', '/api/v1/server/exception');
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.setRequestHeader("X-CSRFToken", Cookies.get('csrftoken'));

let onreject = () => {
Array.prototype.push.apply(this._logEvents, exceptions);
this._logEvents.push(exception);
reject({
status: xhr.status,
statusText: xhr.statusText,
Expand All @@ -117,8 +115,7 @@ var LoggerHandler = function(applicationName, jobId)
onreject();
};

const data = {'exceptions': Array.from(exceptions, log => log.toString())};
xhr.send(JSON.stringify(data));
xhr.send(JSON.stringify(exception.toString()));
});
};

Expand All @@ -140,8 +137,8 @@ var LoggerHandler = function(applicationName, jobId)
application: this._application,
task: this._jobId,
userid: this._username,
tabid: this._tabId,
focus: document.hasFocus()
client_id: this._clientID,
focus: document.hasFocus(),
});
};

Expand Down Expand Up @@ -258,6 +255,9 @@ var Logger = {
*/
LogEvent: function(type, values, closeCallback=null)
{
const d = new Date();
const time = `${d.getFullYear() + 1}-${d.getMonth() + 1}-${d.getDay()}`
+ `T${d.getHours()}:${d.getMinutes()}:${d.getSeconds()}.${d.getMilliseconds()}`;
this._type = type;
this._timestamp = Date.now();
this.onCloseCallback = closeCallback;
Expand All @@ -268,7 +268,7 @@ var Logger = {
{
return Object.assign({
event: Logger.eventTypeToString(this._type),
timestamp: this._timestamp,
time,
}, this._values);
};

Expand Down Expand Up @@ -439,7 +439,7 @@ var Logger = {
*/
sendException: function(exceptionData)
{
return this._logger.sendExceptions([new Logger.LogEvent(Logger.EventType.sendException, exceptionData)]);
return this._logger.sendExceptions(new Logger.LogEvent(Logger.EventType.sendException, exceptionData));
},

/**
Expand Down
24 changes: 1 addition & 23 deletions cvat/apps/engine/static/engine/js/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,8 @@
* SPDX-License-Identifier: MIT
*/

/* exported serverRequest encodeFilePathToURI */

/* global
showOverlay:false
*/

"use strict";

function serverRequest(url, successCallback)
{
$.ajax({
url: url,
dataType: "json",
success: successCallback,
error: serverError
});
}
/* exported encodeFilePathToURI */

function encodeFilePathToURI(path) {
return path.split('/').map(x => encodeURIComponent(x)).join('/');
}

function serverError() {
let message = 'Server errors was occured. Please contact with research automation team.';
showOverlay(message);
throw Error(message);
}
26 changes: 17 additions & 9 deletions cvat/apps/engine/static/engine/js/shapeCollection.js
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,6 @@ class ShapeCollectionModel extends Listener {

// Make copy of data in order to don't affect original data
data = JSON.parse(JSON.stringify(data));
this._idx = data.shapes.concat(data.tracks).reduce((acc, el) => Math.max(acc, el.id || 0), -1);

for (let imported of data.shapes.concat(data.tracks)) {
// Conversion from client object format to server object format
Expand Down Expand Up @@ -286,6 +285,8 @@ class ShapeCollectionModel extends Listener {
tracks: []
};

const mapping = [];

for (let shape of this._shapes) {
if (!shape.removed) {
const exported = shape.export();
Expand All @@ -308,10 +309,12 @@ class ShapeCollectionModel extends Listener {
} else {
data.tracks.push(exported);
}

mapping.push([exported, shape]);
}
}

return data;
return [data, mapping];
}

find(direction) {
Expand Down Expand Up @@ -380,7 +383,8 @@ class ShapeCollectionModel extends Listener {
}

add(data, type) {
const id = data.id || ++this._idx;
this._idx += 1;
const id = this._idx;
const model = buildShapeModel(data, type, id, this.nextColor());
if (type.startsWith('interpolation')) {
this._interpolationShapes.push(model);
Expand Down Expand Up @@ -1253,11 +1257,15 @@ class ShapeCollectionView {
case "object_url": {
let active = this._controller.activeShape;
if (active) {
window.cvat.search.set('frame', window.cvat.player.frames.current);
window.cvat.search.set('filter', `*[id="${active.id}"]`);
copyToClipboard(window.cvat.search.toString());
window.cvat.search.set('frame', null);
window.cvat.search.set('filter', null);
if (typeof active.serverID !== 'undefined') {
window.cvat.search.set('frame', window.cvat.player.frames.current);
window.cvat.search.set('filter', `*[serverID="${active.serverID}"]`);
copyToClipboard(window.cvat.search.toString());
window.cvat.search.set('frame', null);
window.cvat.search.set('filter', null);
} else {
showMessage('First save job in order to get static object URL');
}
}
break;
}
Expand Down Expand Up @@ -1444,7 +1452,7 @@ class ShapeCollectionView {
let newShapes = collection.currentShapes;
let newModels = newShapes.map((el) => el.model);

let frameChanged = this._frameMarker != window.cvat.player.frames.current;
const frameChanged = this._frameMarker !== window.cvat.player.frames.current;

if (frameChanged) {
this._frameContent.node.parent = null;
Expand Down
Loading

0 comments on commit 1b8a8c3

Please sign in to comment.