Updated dump/upload in cvat-core (#635)

* Annotation formats from the server
* Fixed dump
* Added API tests
* Dashboard integration
main
Boris Sekachev 7 years ago committed by Nikita Manovich
parent bf61962195
commit 3a6a49625c

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2018 Intel Corporation * Copyright (C) 2019 Intel Corporation
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
*/ */

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2018 Intel Corporation * Copyright (C) 2019 Intel Corporation
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
*/ */

@ -0,0 +1,235 @@
/*
* Copyright (C) 2019 Intel Corporation
* SPDX-License-Identifier: MIT
*/
(() => {
/**
* Class representing an annotation loader
* @memberof module:API.cvat.classes
* @hideconstructor
*/
class Loader {
constructor(initialData) {
const data = {
display_name: initialData.display_name,
format: initialData.format,
handler: initialData.handler,
version: initialData.version,
};
Object.defineProperties(this, {
name: {
/**
* @name name
* @type {string}
* @memberof module:API.cvat.classes.Loader
* @readonly
* @instance
*/
get: () => data.display_name,
},
format: {
/**
* @name format
* @type {string}
* @memberof module:API.cvat.classes.Loader
* @readonly
* @instance
*/
get: () => data.format,
},
handler: {
/**
* @name handler
* @type {string}
* @memberof module:API.cvat.classes.Loader
* @readonly
* @instance
*/
get: () => data.handler,
},
version: {
/**
* @name version
* @type {string}
* @memberof module:API.cvat.classes.Loader
* @readonly
* @instance
*/
get: () => data.version,
},
});
}
}
/**
* Class representing an annotation dumper
* @memberof module:API.cvat.classes
* @hideconstructor
*/
class Dumper {
constructor(initialData) {
const data = {
display_name: initialData.display_name,
format: initialData.format,
handler: initialData.handler,
version: initialData.version,
};
Object.defineProperties(this, {
name: {
/**
* @name name
* @type {string}
* @memberof module:API.cvat.classes.Dumper
* @readonly
* @instance
*/
get: () => data.display_name,
},
format: {
/**
* @name format
* @type {string}
* @memberof module:API.cvat.classes.Dumper
* @readonly
* @instance
*/
get: () => data.format,
},
handler: {
/**
* @name handler
* @type {string}
* @memberof module:API.cvat.classes.Dumper
* @readonly
* @instance
*/
get: () => data.handler,
},
version: {
/**
* @name version
* @type {string}
* @memberof module:API.cvat.classes.Dumper
* @readonly
* @instance
*/
get: () => data.version,
},
});
}
}
/**
* Class representing an annotation format
* @memberof module:API.cvat.classes
* @hideconstructor
*/
class AnnotationFormat {
constructor(initialData) {
const data = {
created_date: initialData.created_date,
updated_date: initialData.updated_date,
id: initialData.id,
owner: initialData.owner,
name: initialData.name,
handler_file: initialData.handler_file,
};
data.dumpers = initialData.dumpers.map(el => new Dumper(el));
data.loaders = initialData.loaders.map(el => new Loader(el));
// Now all fields are readonly
Object.defineProperties(this, {
id: {
/**
* @name id
* @type {integer}
* @memberof module:API.cvat.classes.AnnotationFormat
* @readonly
* @instance
*/
get: () => data.id,
},
owner: {
/**
* @name owner
* @type {integer}
* @memberof module:API.cvat.classes.AnnotationFormat
* @readonly
* @instance
*/
get: () => data.owner,
},
name: {
/**
* @name name
* @type {string}
* @memberof module:API.cvat.classes.AnnotationFormat
* @readonly
* @instance
*/
get: () => data.name,
},
createdDate: {
/**
* @name createdDate
* @type {string}
* @memberof module:API.cvat.classes.AnnotationFormat
* @readonly
* @instance
*/
get: () => data.created_date,
},
updatedDate: {
/**
* @name updatedDate
* @type {string}
* @memberof module:API.cvat.classes.AnnotationFormat
* @readonly
* @instance
*/
get: () => data.updated_date,
},
handlerFile: {
/**
* @name handlerFile
* @type {string}
* @memberof module:API.cvat.classes.AnnotationFormat
* @readonly
* @instance
*/
get: () => data.handler_file,
},
loaders: {
/**
* @name loaders
* @type {module:API.cvat.classes.Loader[]}
* @memberof module:API.cvat.classes.AnnotationFormat
* @readonly
* @instance
*/
get: () => [...data.loaders],
},
dumpers: {
/**
* @name dumpers
* @type {module:API.cvat.classes.Dumper[]}
* @memberof module:API.cvat.classes.AnnotationFormat
* @readonly
* @instance
*/
get: () => [...data.dumpers],
},
});
}
}
module.exports = {
AnnotationFormat,
Loader,
Dumper,
};
})();

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2018 Intel Corporation * Copyright (C) 2019 Intel Corporation
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
*/ */

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2018 Intel Corporation * Copyright (C) 2019 Intel Corporation
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
*/ */

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2018 Intel Corporation * Copyright (C) 2019 Intel Corporation
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
*/ */

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2018 Intel Corporation * Copyright (C) 2019 Intel Corporation
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
*/ */
@ -13,9 +13,14 @@
const AnnotationsSaver = require('./annotations-saver'); const AnnotationsSaver = require('./annotations-saver');
const { checkObjectType } = require('./common'); const { checkObjectType } = require('./common');
const { Task } = require('./session'); const { Task } = require('./session');
const {
Loader,
Dumper,
} = require('./annotation-format.js');
const { const {
ScriptingError, ScriptingError,
DataError, DataError,
ArgumentError,
} = require('./exceptions'); } = require('./exceptions');
const jobCache = new WeakMap(); const jobCache = new WeakMap();
@ -190,15 +195,33 @@
); );
} }
async function uploadAnnotations(session, file, format) { async function uploadAnnotations(session, file, loader) {
const sessionType = session instanceof Task ? 'task' : 'job'; const sessionType = session instanceof Task ? 'task' : 'job';
await serverProxy.annotations.uploadAnnotations(sessionType, session.id, file, format); if (!(loader instanceof Loader)) {
throw new ArgumentError(
'A loader must be instance of Loader class',
);
}
await serverProxy.annotations.uploadAnnotations(sessionType, session.id, file, loader.name);
} }
async function dumpAnnotations(session, name, format) { async function dumpAnnotations(session, name, dumper) {
if (!(dumper instanceof Dumper)) {
throw new ArgumentError(
'A dumper must be instance of Dumper class',
);
}
let result = null;
const sessionType = session instanceof Task ? 'task' : 'job'; const sessionType = session instanceof Task ? 'task' : 'job';
const result = await serverProxy.annotations if (sessionType === 'job') {
.dumpAnnotations(sessionType, session.id, name, format); result = await serverProxy.annotations
.dumpAnnotations(session.task.id, name, dumper.name);
} else {
result = await serverProxy.annotations
.dumpAnnotations(session.id, name, dumper.name);
}
return result; return result;
} }

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2018 Intel Corporation * Copyright (C) 2019 Intel Corporation
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
*/ */
@ -27,6 +27,7 @@
} = require('./enums'); } = require('./enums');
const User = require('./user'); const User = require('./user');
const { AnnotationFormat } = require('./annotation-format.js');
const { ArgumentError } = require('./exceptions'); const { ArgumentError } = require('./exceptions');
const { Task } = require('./session'); const { Task } = require('./session');
@ -44,6 +45,11 @@
return result; return result;
}; };
cvat.server.formats.implementation = async () => {
const result = await serverProxy.server.formats();
return result.map(el => new AnnotationFormat(el));
};
cvat.server.login.implementation = async (username, password) => { cvat.server.login.implementation = async (username, password) => {
await serverProxy.server.login(username, password); await serverProxy.server.login(username, password);
}; };

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2018 Intel Corporation * Copyright (C) 2019 Intel Corporation
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
*/ */
@ -101,6 +101,20 @@ function build() {
.apiWrapper(cvat.server.share, directory); .apiWrapper(cvat.server.share, directory);
return result; return result;
}, },
/**
* Method returns available annotation formats
* @method formats
* @async
* @memberof module:API.cvat.server
* @returns {module:API.cvat.classes.AnnotationFormat[]}
* @throws {module:API.cvat.exceptions.PluginError}
* @throws {module:API.cvat.exceptions.ServerError}
*/
async formats() {
const result = await PluginRegistry
.apiWrapper(cvat.server.formats);
return result;
},
/** /**
* Method allows to login on a server * Method allows to login on a server
* @method login * @method login
@ -218,7 +232,7 @@ function build() {
* @async * @async
* @memberof module:API.cvat.users * @memberof module:API.cvat.users
* @param {UserFilter} [filter={}] user filter * @param {UserFilter} [filter={}] user filter
* @returns {User[]} * @returns {module:API.cvat.classes.User[]}
* @throws {module:API.cvat.exceptions.PluginError} * @throws {module:API.cvat.exceptions.PluginError}
* @throws {module:API.cvat.exceptions.ServerError} * @throws {module:API.cvat.exceptions.ServerError}
*/ */

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2018 Intel Corporation * Copyright (C) 2019 Intel Corporation
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
*/ */

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2018 Intel Corporation * Copyright (C) 2019 Intel Corporation
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
*/ */

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2018 Intel Corporation * Copyright (C) 2019 Intel Corporation
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
*/ */

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2018 Intel Corporation * Copyright (C) 2019 Intel Corporation
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
*/ */

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2018 Intel Corporation * Copyright (C) 2019 Intel Corporation
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
*/ */

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2018 Intel Corporation * Copyright (C) 2019 Intel Corporation
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
*/ */

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2018 Intel Corporation * Copyright (C) 2019 Intel Corporation
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
*/ */

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2018 Intel Corporation * Copyright (C) 2019 Intel Corporation
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
*/ */

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2018 Intel Corporation * Copyright (C) 2019 Intel Corporation
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
*/ */

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2018 Intel Corporation * Copyright (C) 2019 Intel Corporation
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
*/ */
@ -90,6 +90,25 @@
} }
} }
async function formats() {
const { backendAPI } = config;
let response = null;
try {
response = await Axios.get(`${backendAPI}/server/annotation/formats`, {
proxy: config.proxy,
});
} catch (errorData) {
const code = errorData.response ? errorData.response.status : errorData.code;
throw new ServerError(
'Could not get annotation formats from the server',
code,
);
}
return response.data;
}
async function login(username, password) { async function login(username, password) {
function setCookie(response) { function setCookie(response) {
if (response.headers['set-cookie']) { if (response.headers['set-cookie']) {
@ -532,7 +551,7 @@
async function request() { async function request() {
try { try {
const response = await Axios const response = await Axios
.post(`${backendAPI}/${session}s/${id}/annotations?upload_format=${format}`, annotationData, { .put(`${backendAPI}/${session}s/${id}/annotations?format=${format}`, annotationData, {
proxy: config.proxy, proxy: config.proxy,
}); });
if (response.status === 202) { if (response.status === 202) {
@ -560,7 +579,7 @@
async function dumpAnnotations(id, name, format) { async function dumpAnnotations(id, name, format) {
const { backendAPI } = config; const { backendAPI } = config;
const filename = name.replace(/\//g, '_'); const filename = name.replace(/\//g, '_');
let url = `${backendAPI}/tasks/${id}/annotations/${filename}?dump_format=${format}`; let url = `${backendAPI}/tasks/${id}/annotations/${filename}?format=${format}`;
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
async function request() { async function request() {
@ -603,6 +622,7 @@
value: Object.freeze({ value: Object.freeze({
about, about,
share, share,
formats,
exception, exception,
login, login,
logout, logout,

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2018 Intel Corporation * Copyright (C) 2019 Intel Corporation
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
*/ */
@ -19,9 +19,9 @@
Object.defineProperties(prototype, { Object.defineProperties(prototype, {
annotations: Object.freeze({ annotations: Object.freeze({
value: { value: {
async upload(file, format) { async upload(file, loader) {
const result = await PluginRegistry const result = await PluginRegistry
.apiWrapper.call(this, prototype.annotations.upload, file, format); .apiWrapper.call(this, prototype.annotations.upload, file, loader);
return result; return result;
}, },
@ -37,9 +37,9 @@
return result; return result;
}, },
async dump(name, format) { async dump(name, dumper) {
const result = await PluginRegistry const result = await PluginRegistry
.apiWrapper.call(this, prototype.annotations.dump, name, format); .apiWrapper.call(this, prototype.annotations.dump, name, dumper);
return result; return result;
}, },
@ -183,7 +183,8 @@
* @method upload * @method upload
* @memberof Session.annotations * @memberof Session.annotations
* @param {File} annotations - a text file with annotations * @param {File} annotations - a text file with annotations
* @param {string} format - a format of the file * @param {module:API.cvat.classes.Loader} loader - a loader
* which will be used to upload
* @instance * @instance
* @async * @async
* @throws {module:API.cvat.exceptions.PluginError} * @throws {module:API.cvat.exceptions.PluginError}
@ -224,10 +225,12 @@
* @method dump * @method dump
* @memberof Session.annotations * @memberof Session.annotations
* @param {string} name - a name of a file with annotations * @param {string} name - a name of a file with annotations
* @param {string} format - a format of the file * @param {module:API.cvat.classes.Dumper} dumper - a dumper
* which will be used to dump
* @returns {string} URL which can be used in order to get a dump file * @returns {string} URL which can be used in order to get a dump file
* @throws {module:API.cvat.exceptions.PluginError} * @throws {module:API.cvat.exceptions.PluginError}
* @throws {module:API.cvat.exceptions.ServerError} * @throws {module:API.cvat.exceptions.ServerError}
* @throws {module:API.cvat.exceptions.ArgumentError}
* @instance * @instance
* @async * @async
*/ */
@ -1272,13 +1275,13 @@
return result; return result;
}; };
Job.prototype.annotations.upload.implementation = async function (file, format) { Job.prototype.annotations.upload.implementation = async function (file, loader) {
const result = await uploadAnnotations(this, file, format); const result = await uploadAnnotations(this, file, loader);
return result; return result;
}; };
Job.prototype.annotations.dump.implementation = async function (name, format) { Job.prototype.annotations.dump.implementation = async function (name, dumper) {
const result = await dumpAnnotations(this, name, format); const result = await dumpAnnotations(this, name, dumper);
return result; return result;
}; };
@ -1418,13 +1421,13 @@
return result; return result;
}; };
Task.prototype.annotations.upload.implementation = async function (file, format) { Task.prototype.annotations.upload.implementation = async function (file, loader) {
const result = await uploadAnnotations(this, file, format); const result = await uploadAnnotations(this, file, loader);
return result; return result;
}; };
Task.prototype.annotations.dump.implementation = async function (name, format) { Task.prototype.annotations.dump.implementation = async function (name, dumper) {
const result = await dumpAnnotations(this, name, format); const result = await dumpAnnotations(this, name, dumper);
return result; return result;
}; };
})(); })();

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2018 Intel Corporation * Copyright (C) 2019 Intel Corporation
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
*/ */

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2018 Intel Corporation * Copyright (C) 2019 Intel Corporation
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
*/ */

@ -17,6 +17,11 @@ jest.mock('../../src/server-proxy', () => {
// Initialize api // Initialize api
window.cvat = require('../../src/api'); window.cvat = require('../../src/api');
const {
AnnotationFormat,
Loader,
Dumper,
} = require('../../src/annotation-format');
// Test cases // Test cases
describe('Feature: get info about cvat', () => { describe('Feature: get info about cvat', () => {
@ -49,3 +54,43 @@ describe('Feature: get share storage info', () => {
)).rejects.toThrow(window.cvat.exceptions.ServerError); )).rejects.toThrow(window.cvat.exceptions.ServerError);
}); });
}); });
describe('Feature: get annotation formats', () => {
test('get annotation formats from a server', async () => {
const result = await window.cvat.server.formats();
expect(Array.isArray(result)).toBeTruthy();
for (const format of result) {
expect(format).toBeInstanceOf(AnnotationFormat);
}
});
});
describe('Feature: get annotation loaders', () => {
test('get annotation formats from a server', async () => {
const result = await window.cvat.server.formats();
expect(Array.isArray(result)).toBeTruthy();
for (const format of result) {
expect(format).toBeInstanceOf(AnnotationFormat);
const { loaders } = format;
expect(Array.isArray(loaders)).toBeTruthy();
for (const loader of loaders) {
expect(loader).toBeInstanceOf(Loader);
}
}
});
});
describe('Feature: get annotation dumpers', () => {
test('get annotation formats from a server', async () => {
const result = await window.cvat.server.formats();
expect(Array.isArray(result)).toBeTruthy();
for (const format of result) {
expect(format).toBeInstanceOf(AnnotationFormat);
const { dumpers } = format;
expect(Array.isArray(dumpers)).toBeTruthy();
for (const dumper of dumpers) {
expect(dumper).toBeInstanceOf(Dumper);
}
}
});
});

@ -6,6 +6,85 @@ const aboutDummyData = {
"version": "0.5.dev20190516142240" "version": "0.5.dev20190516142240"
} }
const formatsDummyData = [{
"id": 1,
"dumpers": [
{
"display_name": "CVAT XML 1.1 for videos",
"format": "XML",
"version": "1.1",
"handler": "dump_as_cvat_interpolation"
},
{
"display_name": "CVAT XML 1.1 for images",
"format": "XML",
"version": "1.1",
"handler": "dump_as_cvat_annotation"
}
],
"loaders": [
{
"display_name": "CVAT XML 1.1",
"format": "XML",
"version": "1.1",
"handler": "load"
}
],
"name": "CVAT",
"created_date": "2019-08-08T12:18:56.571488+03:00",
"updated_date": "2019-08-08T12:18:56.571533+03:00",
"handler_file": "cvat/apps/annotation/cvat.py",
"owner": null
},
{
"id": 2,
"dumpers": [
{
"display_name": "PASCAL VOC ZIP 1.0",
"format": "ZIP",
"version": "1.0",
"handler": "dump"
}
],
"loaders": [
{
"display_name": "PASCAL VOC ZIP 1.0",
"format": "ZIP",
"version": "1.0",
"handler": "load"
}
],
"name": "PASCAL VOC",
"created_date": "2019-08-08T12:18:56.625025+03:00",
"updated_date": "2019-08-08T12:18:56.625071+03:00",
"handler_file": "cvat/apps/annotation/pascal_voc.py",
"owner": null
},
{
"id": 3,
"dumpers": [
{
"display_name": "YOLO ZIP 1.0",
"format": "ZIP",
"version": "1.0",
"handler": "dump"
}
],
"loaders": [
{
"display_name": "YOLO ZIP 1.0",
"format": "ZIP",
"version": "1.0",
"handler": "load"
}
],
"name": "YOLO",
"created_date": "2019-08-08T12:18:56.667534+03:00",
"updated_date": "2019-08-08T12:18:56.667578+03:00",
"handler_file": "cvat/apps/annotation/yolo.py",
"owner": null
}];
const usersDummyData = { const usersDummyData = {
"count": 2, "count": 2,
"next": null, "next": null,
@ -2445,4 +2524,5 @@ module.exports = {
taskAnnotationsDummyData, taskAnnotationsDummyData,
jobAnnotationsDummyData, jobAnnotationsDummyData,
frameMetaDummyData, frameMetaDummyData,
formatsDummyData,
} }

@ -12,6 +12,7 @@
const { const {
tasksDummyData, tasksDummyData,
aboutDummyData, aboutDummyData,
formatsDummyData,
shareDummyData, shareDummyData,
usersDummyData, usersDummyData,
taskAnnotationsDummyData, taskAnnotationsDummyData,
@ -48,6 +49,10 @@ class ServerProxy {
return JSON.parse(JSON.stringify(position)); return JSON.parse(JSON.stringify(position));
} }
async function formats() {
return JSON.parse(JSON.stringify(formatsDummyData));
}
async function exception() { async function exception() {
return null; return null;
} }
@ -239,6 +244,7 @@ class ServerProxy {
value: Object.freeze({ value: Object.freeze({
about, about,
share, share,
formats,
exception, exception,
login, login,
logout, logout,

@ -6,8 +6,6 @@
/* global /* global
userConfirm:false userConfirm:false
dumpAnnotationRequest:false
uploadTaskAnnotationRequest:false
LabelsInfo:false LabelsInfo:false
showMessage:false showMessage:false
showOverlay:false showOverlay:false
@ -85,10 +83,8 @@ class TaskView {
if (file) { if (file) {
button.text('Uploading..'); button.text('Uploading..');
button.prop('disabled', true); button.prop('disabled', true);
const annotationData = new FormData();
annotationData.append('annotation_file', file);
try { try {
await uploadTaskAnnotationRequest(this._task.id, annotationData, format); await this._task.annotations.upload(file, format);
} catch (error) { } catch (error) {
showMessage(error.message); showMessage(error.message);
} finally { } finally {
@ -102,7 +98,12 @@ class TaskView {
async _dump(button, format) { async _dump(button, format) {
button.disabled = true; button.disabled = true;
try { try {
await dumpAnnotationRequest(this._task.id, this._task.name, format); const url = await this._task.annotations.dump(this._task.name, format);
const a = document.createElement('a');
a.href = `${url}`;
document.body.appendChild(a);
a.click();
a.remove();
} catch (error) { } catch (error) {
showMessage(error.message); showMessage(error.message);
} finally { } finally {
@ -139,22 +140,22 @@ class TaskView {
for (const format of this._annotationFormats) { for (const format of this._annotationFormats) {
for (const dumper of format.dumpers) { for (const dumper of format.dumpers) {
const listItem = $(`<li>${dumper.display_name}</li>`).on('click', () => { const listItem = $(`<li>${dumper.name}</li>`).on('click', () => {
dropdownDownloadMenu.addClass('hidden'); dropdownDownloadMenu.addClass('hidden');
this._dump(downloadButton[0], dumper.display_name); this._dump(downloadButton[0], dumper);
}); });
if (isDefaultFormat(dumper.display_name, this._task.mode)) { if (isDefaultFormat(dumper.name, this._task.mode)) {
listItem.addClass('bold'); listItem.addClass('bold');
} }
dropdownDownloadMenu.append(listItem); dropdownDownloadMenu.append(listItem);
} }
for (const loader of format.loaders) { for (const loader of format.loaders) {
dropdownUploadMenu.append($(`<li>${loader.display_name}</li>`).on('click', () => { dropdownUploadMenu.append($(`<li>${loader.name}</li>`).on('click', () => {
dropdownUploadMenu.addClass('hidden'); dropdownUploadMenu.addClass('hidden');
userConfirm('The current annotation will be lost. Are you sure?', () => { userConfirm('The current annotation will be lost. Are you sure?', () => {
this._upload(uploadButton, loader.display_name); this._upload(uploadButton, loader);
}); });
})); }));
} }
@ -728,10 +729,10 @@ window.addEventListener('DOMContentLoaded', () => {
// TODO: Use REST API in order to get meta // TODO: Use REST API in order to get meta
$.get('/dashboard/meta'), $.get('/dashboard/meta'),
$.get(`/api/v1/tasks${window.location.search}`), $.get(`/api/v1/tasks${window.location.search}`),
$.get('/api/v1/server/annotation/formats'), window.cvat.server.formats(),
).then((metaData, taskData, annotationFormats) => { ).then((metaData, taskData, annotationFormats) => {
try { try {
new DashboardView(metaData[0], taskData[0], annotationFormats[0]); new DashboardView(metaData[0], taskData[0], annotationFormats);
} catch (exception) { } catch (exception) {
$('#content').empty(); $('#content').empty();
const message = `Can not build CVAT dashboard. Exception: ${exception}.`; const message = `Can not build CVAT dashboard. Exception: ${exception}.`;

File diff suppressed because one or more lines are too long
Loading…
Cancel
Save