You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
241 lines
8.3 KiB
TypeScript
241 lines
8.3 KiB
TypeScript
// Copyright (C) 2019-2022 Intel Corporation
|
|
// Copyright (C) 2022 CVAT.ai Corporation
|
|
//
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
import { StorageLocation } from './enums';
|
|
import { Storage } from './storage';
|
|
|
|
import PluginRegistry from './plugins';
|
|
import { ArgumentError } from './exceptions';
|
|
import { Label } from './labels';
|
|
import User from './user';
|
|
import { FieldUpdateTrigger } from './common';
|
|
|
|
export default class Project {
|
|
constructor(initialData) {
|
|
const data = {
|
|
id: undefined,
|
|
name: undefined,
|
|
status: undefined,
|
|
assignee: undefined,
|
|
organization: undefined,
|
|
owner: undefined,
|
|
bug_tracker: undefined,
|
|
created_date: undefined,
|
|
updated_date: undefined,
|
|
task_subsets: undefined,
|
|
dimension: undefined,
|
|
source_storage: undefined,
|
|
target_storage: undefined,
|
|
labels: undefined,
|
|
};
|
|
|
|
const updateTrigger = new FieldUpdateTrigger();
|
|
|
|
for (const property in data) {
|
|
if (Object.prototype.hasOwnProperty.call(data, property) && property in initialData) {
|
|
data[property] = initialData[property];
|
|
}
|
|
}
|
|
|
|
data.labels = [];
|
|
|
|
if (Array.isArray(initialData.labels)) {
|
|
data.labels = initialData.labels
|
|
.map((labelData) => new Label(labelData)).filter((label) => !label.hasParent);
|
|
}
|
|
|
|
Object.defineProperties(
|
|
this,
|
|
Object.freeze({
|
|
id: {
|
|
get: () => data.id,
|
|
},
|
|
name: {
|
|
get: () => data.name,
|
|
set: (value) => {
|
|
if (!value.trim().length) {
|
|
throw new ArgumentError('Value must not be empty');
|
|
}
|
|
data.name = value;
|
|
updateTrigger.update('name');
|
|
},
|
|
},
|
|
status: {
|
|
get: () => data.status,
|
|
},
|
|
assignee: {
|
|
get: () => data.assignee,
|
|
set: (assignee) => {
|
|
if (assignee !== null && !(assignee instanceof User)) {
|
|
throw new ArgumentError('Value must be a user instance');
|
|
}
|
|
data.assignee = assignee;
|
|
updateTrigger.update('assignee');
|
|
},
|
|
},
|
|
owner: {
|
|
get: () => data.owner,
|
|
},
|
|
organization: {
|
|
get: () => data.organization,
|
|
},
|
|
bugTracker: {
|
|
get: () => data.bug_tracker,
|
|
set: (tracker) => {
|
|
data.bug_tracker = tracker;
|
|
updateTrigger.update('bugTracker');
|
|
},
|
|
},
|
|
createdDate: {
|
|
get: () => data.created_date,
|
|
},
|
|
updatedDate: {
|
|
get: () => data.updated_date,
|
|
},
|
|
dimension: {
|
|
get: () => data.dimension,
|
|
},
|
|
labels: {
|
|
get: () => [...data.labels],
|
|
set: (labels) => {
|
|
if (!Array.isArray(labels)) {
|
|
throw new ArgumentError('Value must be an array of Labels');
|
|
}
|
|
|
|
if (!Array.isArray(labels) || labels.some((label) => !(label instanceof Label))) {
|
|
throw new ArgumentError(
|
|
`Each array value must be an instance of Label. ${typeof label} was found`,
|
|
);
|
|
}
|
|
|
|
const IDs = labels.map((_label) => _label.id);
|
|
const deletedLabels = data.labels.filter((_label) => !IDs.includes(_label.id));
|
|
deletedLabels.forEach((_label) => {
|
|
_label.deleted = true;
|
|
});
|
|
|
|
data.labels = [...deletedLabels, ...labels];
|
|
updateTrigger.update('labels');
|
|
},
|
|
},
|
|
subsets: {
|
|
get: () => [...data.task_subsets],
|
|
},
|
|
sourceStorage: {
|
|
get: () => (
|
|
new Storage({
|
|
location: data.source_storage?.location || StorageLocation.LOCAL,
|
|
cloudStorageId: data.source_storage?.cloud_storage_id,
|
|
})
|
|
),
|
|
},
|
|
targetStorage: {
|
|
get: () => (
|
|
new Storage({
|
|
location: data.target_storage?.location || StorageLocation.LOCAL,
|
|
cloudStorageId: data.target_storage?.cloud_storage_id,
|
|
})
|
|
),
|
|
},
|
|
_internalData: {
|
|
get: () => data,
|
|
},
|
|
_updateTrigger: {
|
|
get: () => updateTrigger,
|
|
},
|
|
}),
|
|
);
|
|
|
|
// When we call a function, for example: project.annotations.get()
|
|
// In the method get we lose the project context
|
|
// So, we need return it
|
|
this.annotations = {
|
|
exportDataset: Object.getPrototypeOf(this).annotations.exportDataset.bind(this),
|
|
importDataset: Object.getPrototypeOf(this).annotations.importDataset.bind(this),
|
|
};
|
|
}
|
|
|
|
async preview() {
|
|
const result = await PluginRegistry.apiWrapper.call(this, Project.prototype.preview);
|
|
return result;
|
|
}
|
|
|
|
async save() {
|
|
const result = await PluginRegistry.apiWrapper.call(this, Project.prototype.save);
|
|
return result;
|
|
}
|
|
|
|
async delete() {
|
|
const result = await PluginRegistry.apiWrapper.call(this, Project.prototype.delete);
|
|
return result;
|
|
}
|
|
|
|
async backup(targetStorage: Storage, useDefaultSettings: boolean, fileName?: string) {
|
|
const result = await PluginRegistry.apiWrapper.call(
|
|
this,
|
|
Project.prototype.backup,
|
|
targetStorage,
|
|
useDefaultSettings,
|
|
fileName,
|
|
);
|
|
return result;
|
|
}
|
|
|
|
static async restore(storage: Storage, file: File | string) {
|
|
const result = await PluginRegistry.apiWrapper.call(this, Project.restore, storage, file);
|
|
return result;
|
|
}
|
|
}
|
|
|
|
Object.defineProperties(
|
|
Project.prototype,
|
|
Object.freeze({
|
|
annotations: Object.freeze({
|
|
value: {
|
|
async exportDataset(
|
|
format: string,
|
|
saveImages: boolean,
|
|
useDefaultSettings: boolean,
|
|
targetStorage: Storage,
|
|
customName?: string,
|
|
) {
|
|
const result = await PluginRegistry.apiWrapper.call(
|
|
this,
|
|
Project.prototype.annotations.exportDataset,
|
|
format,
|
|
saveImages,
|
|
useDefaultSettings,
|
|
targetStorage,
|
|
customName,
|
|
);
|
|
return result;
|
|
},
|
|
async importDataset(
|
|
format: string,
|
|
useDefaultSettings: boolean,
|
|
sourceStorage: Storage,
|
|
file: File | string,
|
|
options?: {
|
|
convMaskToPoly?: boolean,
|
|
updateStatusCallback?: (s: string, n: number) => void,
|
|
},
|
|
) {
|
|
const result = await PluginRegistry.apiWrapper.call(
|
|
this,
|
|
Project.prototype.annotations.importDataset,
|
|
format,
|
|
useDefaultSettings,
|
|
sourceStorage,
|
|
file,
|
|
options,
|
|
);
|
|
return result;
|
|
},
|
|
},
|
|
writable: true,
|
|
}),
|
|
}),
|
|
);
|