Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Integration of REST/API in client #2 #355

Merged
merged 13 commits into from
Mar 21, 2019
8,589 changes: 0 additions & 8,589 deletions cvat/apps/dashboard/static/dashboard/js/3rdparty/jstree/jstree.js

This file was deleted.

Large diffs are not rendered by default.

Binary file not shown.
Binary file not shown.

This file was deleted.

Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

This file was deleted.

Large diffs are not rendered by default.

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
175 changes: 88 additions & 87 deletions cvat/apps/dashboard/static/dashboard/js/dashboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,104 +81,91 @@ class TaskView {
});
}

_upload(tid) {
function parse(overlay, e) {
const xmlText = e.target.result;
$.get(`/api/v1/tasks/${tid}/frames/meta`).done((imageMetaCache) => {
const labelsCopy = JSON.parse(JSON.stringify(this._labels));
_upload() {
async function saveChunk(parsed, start, version) {
const CHUNK_SIZE = 100000;
let end = start + CHUNK_SIZE;
let chunk = {};
let next = false;

let chunk = {
shapes: [],
tracks: [],
tags: [],
version,
}

for (let prop in parsed) {
if (parsed.hasOwnProperty(prop)) {
chunk[prop] = parsed[prop].slice(start, end);
next |= chunk[prop].length > 0;
}
}

if (next) {
const response = await $.ajax({
url: `/api/v1/tasks/${this._id}/annotations`,
type: 'PATCH',
data: JSON.stringify(chunk),
contentType: 'application/json',
});

saveChunk.call(this, parsed, end, response.version);
}
}

async function save(parsed) {3
const response = await $.ajax({
url: `/api/v1/tasks/${this._id}/annotations`,
type: 'DELETE',
});

await saveChunk.call(this, parsed, 0, response.version);
}

async function onload(overlay, text) {
try {
overlay.setMessage('Required data are being downloaded from the server..');
const imageCache = await $.get(`/api/v1/tasks/${this._id}/frames/meta`);
const labelsCopy = JSON.parse(JSON.stringify(this._labels));
const parser = new AnnotationParser({
start: 0,
stop: this._size,
flipped: this._flipped,
image_meta_data: imageMetaCache,
image_meta_data: imageCache,
}, new LabelsInfo(labelsCopy));

function asyncParse() {
let parsed = null;
try {
parsed = parser.parse(xmlText);
}
catch(error) {
overlay.remove();
showMessage('Parsing errors occured. ' + error);
return;
}

function asyncSave() {
$.ajax({
// TODO: Use REST API
url: '/delete/annotation/task/' + window.cvat.dashboard.taskID,
type: 'DELETE',
success: function() {
asyncSaveChunk(0);
},
error: function(errorData) {
const message = `Could not remove current annotation. Code: ${errorData.status}. ` +
`Message: ${errorData.responseText || errorData.statusText}`;
showMessage(message);
},
});
};

function asyncSaveChunk(start) {
const CHUNK_SIZE = 100000;
let end = start + CHUNK_SIZE;
let chunk = {};
let next = false;
for (let prop in parsed) {
if (parsed.hasOwnProperty(prop)) {
chunk[prop] = parsed[prop].slice(start, end);
next |= chunk[prop].length > 0;
}
}
overlay.setMessage('The annotation file is being parsed..');
const parsed = parser.parse(text);

if (next) {
const exportData = createExportContainer();
exportData.create = chunk;

$.ajax({
// TODO: Use REST API
url: `/save/annotation/task/${tid}`,
type: 'POST',
data: JSON.stringify(exportData),
contentType: 'application/json',
}).done(() => {
asyncSaveChunk(end);
}).fail((errorData) => {
const message = `Annotation uploading errors occurred. Code: ${errorData.status}. ` +
`Message: ${errorData.responseText || errorData.statusText}`;
showMessage(message);
});
} else {
const message = 'Annotation have been successfully uploaded';
showMessage(message);
overlay.remove();
}
}
overlay.setMessage('The annotation is being saved..');
await save.call(this, parsed);

overlay.setMessage('The annotation is being saved..');
setTimeout(asyncSave);
const message = 'Annotation have been successfully uploaded';
showMessage(message);
} catch(errorData) {
let message = null;
if (typeof(errorData) === 'string') {
message = `Can not upload annotations. ${errorData}`;
} else {
message = `Can not upload annotations. Code: ${errorData.status}. ` +
`Message: ${errorData.responseText || errorData.statusText}`;
}

overlay.setMessage('The annotation file is being parsed..');
setTimeout(asyncParse);
}).fail((errorData) => {
const message = `Can not get required data from the server. Code: ${errorData.status}. ` +
`Message: ${errorData.responseText || errorData.statusText}`;
showMessage(message);
});

overlay.setMessage('Required data are being downloaded from the server..');
} finally {
overlay.remove();
}
}

self = this;
$('<input type="file" accept="text/xml">').on('change', function() {
const file = this.files[0];
$(this).remove();
$('<input type="file" accept="text/xml">').on('change', (e) => {
const file = e.target.files[0];
$(e.target).remove();
if (file) {
const overlay = showOverlay('File is being parsed..');
const fileReader = new FileReader();
fileReader.onload = parse.bind(self, overlay);
fileReader.onload = (e) => {
onload.call(this, overlay, e.target.result);
}
fileReader.readAsText(file);
}
}).click();
Expand Down Expand Up @@ -473,9 +460,23 @@ class DashboardView {
shareFileSelector.removeClass('hidden');
shareBrowseTree.jstree({
core: {
data: {
url: 'get_share_nodes',
data: (node) => { return {'id' : node.id}; }
data: async function (obj, callback) {
let url = '/api/v1/server/share';

if (obj.id != '#') {
url += `?directory=${obj.id.substr(2)}`;
}

const response = await $.get(url);
const files = Array.from(response, (element) => {
return {
id: `${obj.id}/${element.name}`,
children: element.type === 'DIR',
text: element.name}
}
);

callback.call(this, files);
}
},
plugins: ['checkbox', 'sort'],
Expand All @@ -491,7 +492,7 @@ class DashboardView {
cancelBrowseServer.on('click', () => shareFileSelector.addClass('hidden'));
submitBrowseServer.on('click', () => {
if (!createModal.hasClass('hidden')) {
files = shareBrowseTree.jstree(true).get_selected();
files = Array.from(shareBrowseTree.jstree(true).get_selected(), (el) => el.substr(2));
cancelBrowseServer.click();
updateSelectedFiles();
}
Expand Down
4 changes: 2 additions & 2 deletions cvat/apps/dashboard/templates/dashboard/dashboard.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
{% block head_css %}
{{ block.super }}
<link rel="stylesheet" type="text/css" href="{% static 'dashboard/stylesheet.css' %}">
<link rel="stylesheet" type="text/css" href="{% static 'dashboard/js/3rdparty/jstree/themes/default/style.css' %}">
<link rel="stylesheet" type="text/css" href="{% static 'dashboard/js/3rdparty/jstree/themes/default/style.min.css' %}">
<link rel="stylesheet" type="text/css" href="{% static 'dashboard/js/3rdparty/pagination/pagination.css' %}">
{% for css_file in css_3rdparty %}
<link rel="stylesheet" type="text/css" href="{% static css_file %}">
Expand All @@ -24,7 +24,7 @@

{% block head_js_3rdparty %}
{{ block.super }}
<script type="text/javascript" src="{% static 'dashboard/js/3rdparty/jstree/jstree.js' %}"></script>
<script type="text/javascript" src="{% static 'dashboard/js/3rdparty/jstree/jstree.min.js' %}"></script>
<script type="text/javascript" src="{% static 'dashboard/js/3rdparty/pagination/pagination.min.js' %}"></script>
{% for js_file in js_3rdparty %}
<script type="text/javascript" src="{% static js_file %}" defer></script>
Expand Down
1 change: 0 additions & 1 deletion cvat/apps/dashboard/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
from . import views

urlpatterns = [
path('get_share_nodes', views.JsTreeView),
path('', views.DashboardView),
path('meta', views.DashboardMeta),
]
Expand Down
39 changes: 0 additions & 39 deletions cvat/apps/dashboard/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,45 +14,6 @@

import os

def ScanNode(directory):
if '..' in directory.split(os.path.sep):
return HttpResponseBadRequest('Permission Denied')

act_dir = os.path.normpath(settings.SHARE_ROOT + directory)
result = []

nodes = os.listdir(act_dir)
files = filter(os.path.isfile, map(lambda f: os.path.join(act_dir, f), nodes))
dirs = filter(os.path.isdir, map(lambda d: os.path.join(act_dir, d), nodes))

for d in dirs:
name = os.path.basename(d)
children = len(os.listdir(d)) > 0
node = {'id': directory + name + '/', 'text': name, 'children': children}
result.append(node)

for f in files:
name = os.path.basename(f)
node = {'id': directory + name, 'text': name, "icon" : "jstree-file"}
result.append(node)

return result

@login_required
def JsTreeView(request):
node_id = None
if 'id' in request.GET:
node_id = request.GET['id']

if node_id is None or node_id == '#':
node_id = '/'
response = [{"id": node_id, "text": node_id, "children": ScanNode(node_id)}]
else:
response = ScanNode(node_id)

return JsonResponse(response, safe=False,
json_dumps_params=dict(ensure_ascii=False))

@login_required
def DashboardView(request):
return render(request, 'dashboard/dashboard.html', {
Expand Down
Loading