Client code refactoring (#7208)
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
// Copyright (C) 2018-2022 Intel Corporation
|
||||
// Copyright (C) 2023 CVAT.ai Corporation
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
@@ -14,9 +15,10 @@ module.exports = {
|
||||
parser: '@typescript-eslint/parser',
|
||||
},
|
||||
ignorePatterns: [
|
||||
'.eslintrc.js',
|
||||
'.eslintrc.cjs',
|
||||
'lint-staged.config.js',
|
||||
'site/themes/**',
|
||||
'webpack.config.cjs',
|
||||
],
|
||||
plugins: ['@typescript-eslint', 'security', 'no-unsanitized', 'import'],
|
||||
extends: [
|
||||
@@ -53,6 +55,10 @@ module.exports = {
|
||||
'import/order': ['error', {'groups': ['builtin', 'external', 'internal']}],
|
||||
'import/prefer-default-export': 0, // works incorrect with interfaces
|
||||
|
||||
'react/jsx-indent-props': 0, // new rule, breaks current styling
|
||||
'react/jsx-indent': 0, // new rule, conflicts with eslint@typescript-eslint/indent eslint@indent, breaks current styling
|
||||
'function-paren-newline': 0, // new rule, breaks current styling
|
||||
'@typescript-eslint/default-param-last': 0, // does not really work with redux reducers
|
||||
'@typescript-eslint/ban-ts-comment': 0,
|
||||
'@typescript-eslint/no-explicit-any': 0,
|
||||
'@typescript-eslint/indent': ['error', 4],
|
||||
Vendored
+1
-1
@@ -519,7 +519,7 @@
|
||||
"program": "${workspaceFolder}/node_modules/.bin/jest",
|
||||
"args": [
|
||||
"--config",
|
||||
"${workspaceFolder}/cvat-core/jest.config.js"
|
||||
"${workspaceFolder}/cvat-core/jest.config.cjs"
|
||||
],
|
||||
"console": "integratedTerminal",
|
||||
"internalConsoleOptions": "neverOpen",
|
||||
|
||||
@@ -7,7 +7,7 @@ const { join } = require('path');
|
||||
|
||||
module.exports = {
|
||||
ignorePatterns: [
|
||||
'.eslintrc.js',
|
||||
'.eslintrc.cjs',
|
||||
'webpack.config.js',
|
||||
'node_modules/**',
|
||||
'dist/**',
|
||||
@@ -1,16 +1,17 @@
|
||||
{
|
||||
"name": "cvat-canvas",
|
||||
"version": "2.19.0",
|
||||
"type": "module",
|
||||
"description": "Part of Computer Vision Annotation Tool which presents its canvas library",
|
||||
"main": "src/canvas.ts",
|
||||
"scripts": {
|
||||
"build": "tsc && webpack --config ./webpack.config.js"
|
||||
"build": "tsc && webpack --config ./webpack.config.cjs"
|
||||
},
|
||||
"author": "CVAT.ai",
|
||||
"license": "MIT",
|
||||
"browserslist": [
|
||||
"Chrome >= 63",
|
||||
"Firefox > 58",
|
||||
"Firefox > 102",
|
||||
"not IE 11",
|
||||
"> 2%"
|
||||
],
|
||||
|
||||
@@ -108,7 +108,7 @@ export class CanvasViewImpl implements CanvasView, Listener {
|
||||
},
|
||||
}),
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
private onError = (exception: unknown, domain?: string): void => {
|
||||
this.canvas.dispatchEvent(
|
||||
@@ -122,7 +122,7 @@ export class CanvasViewImpl implements CanvasView, Listener {
|
||||
},
|
||||
}),
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
private stateIsLocked(state: any): boolean {
|
||||
const { configuration } = this.controller;
|
||||
@@ -267,7 +267,7 @@ export class CanvasViewImpl implements CanvasView, Listener {
|
||||
enabled: false,
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private onDrawDone = (
|
||||
data: any | null,
|
||||
@@ -337,7 +337,7 @@ export class CanvasViewImpl implements CanvasView, Listener {
|
||||
// when draw stops from inside canvas (for example if use predefined number of points)
|
||||
this.controller.draw({ enabled: false });
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private onEditStart = (state?: any): void => {
|
||||
this.canvas.style.cursor = 'crosshair';
|
||||
@@ -411,7 +411,7 @@ export class CanvasViewImpl implements CanvasView, Listener {
|
||||
|
||||
this.controller.merge({ enabled: false });
|
||||
this.mode = Mode.IDLE;
|
||||
}
|
||||
};
|
||||
|
||||
private onSplitDone = (object?: any, duration?: number): void => {
|
||||
if (object && typeof duration !== 'undefined') {
|
||||
@@ -437,7 +437,7 @@ export class CanvasViewImpl implements CanvasView, Listener {
|
||||
|
||||
this.controller.split({ enabled: false });
|
||||
this.mode = Mode.IDLE;
|
||||
}
|
||||
};
|
||||
|
||||
private onSelectDone = (objects?: any[], duration?: number): void => {
|
||||
if (objects && typeof duration !== 'undefined') {
|
||||
@@ -503,7 +503,7 @@ export class CanvasViewImpl implements CanvasView, Listener {
|
||||
}
|
||||
|
||||
this.mode = Mode.IDLE;
|
||||
}
|
||||
};
|
||||
|
||||
private onSliceDone = (state?: any, results?: number[][], duration?: number): void => {
|
||||
if (state && results && typeof duration !== 'undefined') {
|
||||
@@ -527,7 +527,7 @@ export class CanvasViewImpl implements CanvasView, Listener {
|
||||
|
||||
this.controller.slice({ enabled: false });
|
||||
this.mode = Mode.IDLE;
|
||||
}
|
||||
};
|
||||
|
||||
private onRegionSelected = (points?: number[]): void => {
|
||||
if (points) {
|
||||
@@ -551,7 +551,7 @@ export class CanvasViewImpl implements CanvasView, Listener {
|
||||
|
||||
this.controller.selectRegion(false);
|
||||
this.mode = Mode.IDLE;
|
||||
}
|
||||
};
|
||||
|
||||
private onFindObject = (e: MouseEvent): void => {
|
||||
if (e.button === 0) {
|
||||
@@ -570,7 +570,7 @@ export class CanvasViewImpl implements CanvasView, Listener {
|
||||
this.canvas.dispatchEvent(event);
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private onFocusRegion = (x: number, y: number, width: number, height: number): void => {
|
||||
// First of all, compute and apply scale
|
||||
@@ -616,7 +616,7 @@ export class CanvasViewImpl implements CanvasView, Listener {
|
||||
this.controller.geometry = dragged;
|
||||
this.geometry = dragged;
|
||||
this.moveCanvas();
|
||||
}
|
||||
};
|
||||
|
||||
private moveCanvas(): void {
|
||||
for (const obj of [this.background, this.grid, this.bitmap]) {
|
||||
|
||||
@@ -294,6 +294,7 @@ export class SliceHandlerImpl implements SliceHandler {
|
||||
const d2 = Math.sqrt((p2[0] - p[0]) ** 2 + (p2[1] - p[1]) ** 2);
|
||||
|
||||
if (d2 > d1) {
|
||||
// @ts-ignore error TS2551 (need to update typescript up to 5.2)
|
||||
contour2.push(...otherPoints.toReversed().flat());
|
||||
} else {
|
||||
contour2.push(...otherPoints.flat());
|
||||
@@ -311,6 +312,7 @@ export class SliceHandlerImpl implements SliceHandler {
|
||||
...firstSegmentPoint, // first intersection
|
||||
// intermediate points (reversed if intersections order was swopped)
|
||||
...(firstSegmentIdx === firstIntersectedSegmentIdx ?
|
||||
// @ts-ignore error TS2551 (need to update typescript up to 5.2)
|
||||
intermediatePoints : intermediatePoints.toReversed()
|
||||
).flat(),
|
||||
// second intersection
|
||||
@@ -324,6 +326,7 @@ export class SliceHandlerImpl implements SliceHandler {
|
||||
...firstSegmentPoint, // first intersection
|
||||
// intermediate points (reversed if intersections order was swopped)
|
||||
...(firstSegmentIdx === firstIntersectedSegmentIdx ?
|
||||
// @ts-ignore error TS2551 (need to update typescript up to 5.2)
|
||||
intermediatePoints : intermediatePoints.toReversed()
|
||||
).flat(),
|
||||
...secondSegmentPoint,
|
||||
@@ -356,6 +359,7 @@ export class SliceHandlerImpl implements SliceHandler {
|
||||
drawOverOffscreenCanvas(context, shape as any as SVGImageElement);
|
||||
applyOffscreenCanvasMask(context, polygon1);
|
||||
const firstShape = zipChannels(context.getImageData(0, 0, width, height).data);
|
||||
// @ts-ignore error TS2339 https://github.com/microsoft/TypeScript/issues/55162
|
||||
context.reset();
|
||||
drawOverOffscreenCanvas(context, shape as any as SVGImageElement);
|
||||
applyOffscreenCanvasMask(context, polygon2);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es2020",
|
||||
"target": "ESNext",
|
||||
"lib": ["dom", "dom.iterable", "esnext"],
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// Copyright (C) 2020-2022 Intel Corporation
|
||||
// Copyright (C) 2023 CVAT.ai Corporation
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// Copyright (C) 2021-2022 Intel Corporation
|
||||
// Copyright (C) 2023 CVAT.ai Corporation
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
@@ -8,7 +9,7 @@ module.exports = {
|
||||
tsconfigRootDir: __dirname,
|
||||
},
|
||||
ignorePatterns: [
|
||||
'.eslintrc.js',
|
||||
'.eslintrc.cjs',
|
||||
'webpack.config.js',
|
||||
'node_modules/**',
|
||||
'dist/**',
|
||||
@@ -1,16 +1,17 @@
|
||||
{
|
||||
"name": "cvat-canvas3d",
|
||||
"version": "0.0.10",
|
||||
"type": "module",
|
||||
"description": "Part of Computer Vision Annotation Tool which presents its canvas3D library",
|
||||
"main": "src/canvas3d.ts",
|
||||
"scripts": {
|
||||
"build": "tsc && webpack --config ./webpack.config.js"
|
||||
"build": "tsc && webpack --config ./webpack.config.cjs"
|
||||
},
|
||||
"author": "CVAT.ai",
|
||||
"license": "MIT",
|
||||
"browserslist": [
|
||||
"Chrome >= 63",
|
||||
"Firefox > 58",
|
||||
"Firefox > 102",
|
||||
"not IE 11",
|
||||
"> 2%"
|
||||
],
|
||||
|
||||
@@ -745,7 +745,7 @@ export class Canvas3dViewImpl implements Canvas3dView, Listener {
|
||||
if (![Mode.DRAG_CANVAS, Mode.IDLE].includes(this.mode)) return;
|
||||
this.isPerspectiveBeingDragged = true;
|
||||
this.enablePerspectiveDragging();
|
||||
}
|
||||
};
|
||||
|
||||
private startAction(view: any, event: MouseEvent): void {
|
||||
const { clientID } = this.model.data.activeElement;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es2020",
|
||||
"target": "ESNext",
|
||||
"lib": ["dom", "dom.iterable", "esnext"],
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// Copyright (C) 2021-2022 Intel Corporation
|
||||
// Copyright (C) 2023 CVAT.ai Corporation
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
// Copyright (C) 2018-2022 Intel Corporation
|
||||
// Copyright (C) 2023 CVAT.ai Corporation
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
module.exports = {
|
||||
ignorePatterns: [
|
||||
'.eslintrc.js',
|
||||
'webpack.config.js',
|
||||
'jest.config.js',
|
||||
'src/3rdparty/**',
|
||||
'.eslintrc.cjs',
|
||||
'webpack.config.cjs',
|
||||
'jest.config.cjs',
|
||||
'node_modules/**',
|
||||
'dist/**',
|
||||
'tests/**/*.js',
|
||||
'tests/**/*.cjs',
|
||||
],
|
||||
parserOptions: {
|
||||
project: './tsconfig.json',
|
||||
+1
-1
@@ -18,7 +18,7 @@ If you make changes in this package, please do following:
|
||||
- Dependencies installation
|
||||
|
||||
```bash
|
||||
yarn ci --frozen-lockfile
|
||||
yarn install --frozen-lockfile
|
||||
```
|
||||
|
||||
- Building the module from sources in the `dist` directory:
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"presets": [
|
||||
[
|
||||
"@babel/preset-env",
|
||||
{
|
||||
"targets": {
|
||||
"node": "current"
|
||||
}
|
||||
}
|
||||
],
|
||||
"@babel/preset-typescript"
|
||||
],
|
||||
"plugins": [
|
||||
"babel-plugin-transform-import-meta"
|
||||
]
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
// Copyright (C) 2019-2022 Intel Corporation
|
||||
// Copyright (C) 2023 CVAT.ai Corporation
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
@@ -6,19 +7,11 @@ const { defaults } = require('jest-config');
|
||||
|
||||
module.exports = {
|
||||
testEnvironment: 'jsdom',
|
||||
preset: 'ts-jest',
|
||||
coverageDirectory: 'reports/coverage',
|
||||
coverageReporters: ['json', ['lcov', { projectRoot: '../' }]],
|
||||
moduleFileExtensions: [...defaults.moduleFileExtensions, 'ts', 'tsx'],
|
||||
reporters: ['default', ['jest-junit', { outputDirectory: 'reports/junit' }]],
|
||||
testMatch: ['**/tests/**/*.js'],
|
||||
testMatch: ['**/tests/**/*.cjs'],
|
||||
testPathIgnorePatterns: ['/node_modules/', '/tests/mocks/*'],
|
||||
automock: false,
|
||||
transform: {
|
||||
'^.+\\.ts?$': [
|
||||
'ts-jest',
|
||||
{ tsconfig: './tsconfig.json', diagnostics: false, },
|
||||
],
|
||||
},
|
||||
|
||||
};
|
||||
@@ -1,11 +1,12 @@
|
||||
{
|
||||
"name": "cvat-core",
|
||||
"version": "12.1.1",
|
||||
"version": "12.2.0",
|
||||
"type": "module",
|
||||
"description": "Part of Computer Vision Tool which presents an interface for client-side integration",
|
||||
"main": "src/api.ts",
|
||||
"scripts": {
|
||||
"build": "webpack",
|
||||
"test": "jest --config=jest.config.js --coverage",
|
||||
"test": "jest --config=jest.config.cjs --coverage",
|
||||
"type-check": "tsc --noEmit",
|
||||
"type-check:watch": "yarn run type-check --watch"
|
||||
},
|
||||
@@ -13,16 +14,18 @@
|
||||
"license": "MIT",
|
||||
"browserslist": [
|
||||
"Chrome >= 63",
|
||||
"Firefox > 58",
|
||||
"Firefox > 102",
|
||||
"not IE 11",
|
||||
"> 2%"
|
||||
],
|
||||
"devDependencies": {
|
||||
"@babel/preset-typescript": "^7.23.3",
|
||||
"babel-jest": "^29.7.0",
|
||||
"babel-plugin-transform-import-meta": "^2.2.1",
|
||||
"jest": "^29.5.0",
|
||||
"jest-config": "^29.5.0",
|
||||
"jest-environment-jsdom": "^29.5.0",
|
||||
"jest-junit": "^6.4.0",
|
||||
"ts-jest": "^29.1.0"
|
||||
"jest-junit": "^6.4.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/lodash": "^4.14.191",
|
||||
|
||||
@@ -5,9 +5,10 @@
|
||||
|
||||
import {
|
||||
shapeFactory, trackFactory, Track, Shape, Tag,
|
||||
MaskShape, BasicInjection, RawShapeData,
|
||||
RawTrackData, RawTagData, SkeletonShape, SkeletonTrack, PolygonShape,
|
||||
MaskShape, BasicInjection,
|
||||
SkeletonShape, SkeletonTrack, PolygonShape,
|
||||
} from './annotations-objects';
|
||||
import { SerializedCollection, SerializedTrack } from './server-response-types';
|
||||
import AnnotationsFilter from './annotations-filter';
|
||||
import { checkObjectType } from './common';
|
||||
import Statistics from './statistics';
|
||||
@@ -21,12 +22,6 @@ import {
|
||||
} from './enums';
|
||||
import AnnotationHistory from './annotations-history';
|
||||
|
||||
interface RawCollection {
|
||||
tags: RawTagData[],
|
||||
shapes: RawShapeData[],
|
||||
tracks: RawTrackData[],
|
||||
}
|
||||
|
||||
interface ImportedCollection {
|
||||
tags: Tag[],
|
||||
shapes: Shape[],
|
||||
@@ -61,7 +56,7 @@ export default class Collection {
|
||||
public flush: boolean;
|
||||
private stopFrame: number;
|
||||
private frameMeta: any;
|
||||
private labels: Record<number, Label>
|
||||
private labels: Record<number, Label>;
|
||||
private annotationsFilter: AnnotationsFilter;
|
||||
private history: AnnotationHistory;
|
||||
private shapes: Record<number, Shape[]>;
|
||||
@@ -109,7 +104,7 @@ export default class Collection {
|
||||
};
|
||||
}
|
||||
|
||||
import(data: RawCollection): ImportedCollection {
|
||||
import(data: SerializedCollection): ImportedCollection {
|
||||
const result = {
|
||||
tags: [],
|
||||
shapes: [],
|
||||
@@ -152,7 +147,7 @@ export default class Collection {
|
||||
return result;
|
||||
}
|
||||
|
||||
export(): RawCollection {
|
||||
export(): SerializedCollection {
|
||||
const data = {
|
||||
tracks: this.tracks.filter((track) => !track.removed).map((track) => track.toJSON()),
|
||||
shapes: Object.values(this.shapes)
|
||||
@@ -174,7 +169,7 @@ export default class Collection {
|
||||
return data;
|
||||
}
|
||||
|
||||
get(frame: number, allTracks: boolean, filters: string[]): ObjectState[] {
|
||||
public get(frame: number, allTracks: boolean, filters: string[]): ObjectState[] {
|
||||
const { tracks } = this;
|
||||
const shapes = this.shapes[frame] || [];
|
||||
const tags = this.tags[frame] || [];
|
||||
@@ -208,8 +203,8 @@ export default class Collection {
|
||||
return objectStates;
|
||||
}
|
||||
|
||||
_mergeInternal(objectsForMerge: (Track | Shape)[], shapeType: ShapeType, label: Label): RawTrackData {
|
||||
const keyframes: Record<number, RawTrackData['shapes'][0]> = {}; // frame: position
|
||||
_mergeInternal(objectsForMerge: (Track | Shape)[], shapeType: ShapeType, label: Label): SerializedTrack {
|
||||
const keyframes: Record<number, SerializedTrack['shapes'][0]> = {}; // frame: position
|
||||
const elements = {}; // element_sublabel_id: [element], each sublabel will be merged recursively
|
||||
|
||||
if (!Object.values(ShapeType).includes(shapeType)) {
|
||||
@@ -448,7 +443,7 @@ export default class Collection {
|
||||
);
|
||||
}
|
||||
|
||||
_splitInternal(objectState: ObjectState, object: Track, frame: number): RawTrackData[] {
|
||||
_splitInternal(objectState: ObjectState, object: Track, frame: number): SerializedTrack[] {
|
||||
const labelAttributes = labelAttributesAsDict(object.label);
|
||||
// first clear all server ids which may exist in the object being splitted
|
||||
const copy = trackFactory(object.toJSON(), -1, this.injection);
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
colors, Source, ShapeType, ObjectType, HistoryActions, DimensionType,
|
||||
} from './enums';
|
||||
import AnnotationHistory from './annotations-history';
|
||||
import { SerializedShape, SerializedTrack, SerializedTag } from './server-response-types';
|
||||
import {
|
||||
checkNumberOfPoints, attrsAsAnObject, checkShapeArea, mask2Rle, rle2Mask,
|
||||
computeWrappingBox, findAngleDiff, rotatePoint, validateAttributeValue, cropMask,
|
||||
@@ -492,31 +493,6 @@ class Drawn extends Annotation {
|
||||
}
|
||||
}
|
||||
|
||||
export interface RawShapeData {
|
||||
id?: number;
|
||||
clientID?: number;
|
||||
label_id: number;
|
||||
group: number;
|
||||
frame: number;
|
||||
source: Source;
|
||||
attributes: { spec_id: number; value: string }[];
|
||||
elements: {
|
||||
id?: number;
|
||||
attributes: RawTrackData['attributes'];
|
||||
label_id: number;
|
||||
occluded: boolean;
|
||||
outside: boolean;
|
||||
points: number[];
|
||||
type: ShapeType;
|
||||
}[];
|
||||
occluded: boolean;
|
||||
outside?: boolean; // only for skeleton elements
|
||||
points?: number[];
|
||||
rotation: number;
|
||||
z_order: number;
|
||||
type: ShapeType;
|
||||
}
|
||||
|
||||
export class Shape extends Drawn {
|
||||
public points: number[];
|
||||
public occluded: boolean;
|
||||
@@ -524,7 +500,7 @@ export class Shape extends Drawn {
|
||||
public rotation: number;
|
||||
public zOrder: number;
|
||||
|
||||
constructor(data: RawShapeData, clientID: number, color: string, injection: AnnotationInjection) {
|
||||
constructor(data: SerializedShape, clientID: number, color: string, injection: AnnotationInjection) {
|
||||
super(data, clientID, color, injection);
|
||||
this.points = data.points;
|
||||
this.rotation = data.rotation || 0;
|
||||
@@ -534,8 +510,8 @@ export class Shape extends Drawn {
|
||||
}
|
||||
|
||||
// Method is used to export data to the server
|
||||
public toJSON(): RawShapeData {
|
||||
const result: RawShapeData = {
|
||||
public toJSON(): SerializedShape {
|
||||
const result: SerializedShape = {
|
||||
type: this.shapeType,
|
||||
clientID: this.clientID,
|
||||
occluded: this.occluded,
|
||||
@@ -809,28 +785,6 @@ export class Shape extends Drawn {
|
||||
}
|
||||
}
|
||||
|
||||
export interface RawTrackData {
|
||||
id?: number;
|
||||
clientID?: number;
|
||||
label_id: number;
|
||||
group: number;
|
||||
frame: number;
|
||||
source: Source;
|
||||
attributes: { spec_id: number; value: string }[];
|
||||
shapes: {
|
||||
attributes: RawTrackData['attributes'];
|
||||
id?: number;
|
||||
points?: number[];
|
||||
frame: number;
|
||||
occluded: boolean;
|
||||
outside: boolean;
|
||||
rotation: number;
|
||||
type: ShapeType;
|
||||
z_order: number;
|
||||
}[];
|
||||
elements?: RawTrackData[];
|
||||
}
|
||||
|
||||
interface TrackedShape {
|
||||
serverID?: number;
|
||||
occluded: boolean;
|
||||
@@ -851,7 +805,7 @@ export interface InterpolatedPosition {
|
||||
|
||||
export class Track extends Drawn {
|
||||
public shapes: Record<number, TrackedShape>;
|
||||
constructor(data: RawTrackData, clientID: number, color: string, injection: AnnotationInjection) {
|
||||
constructor(data: SerializedTrack, clientID: number, color: string, injection: AnnotationInjection) {
|
||||
super(data, clientID, color, injection);
|
||||
this.shapes = data.shapes.reduce((shapeAccumulator, value) => {
|
||||
shapeAccumulator[value.frame] = {
|
||||
@@ -872,10 +826,10 @@ export class Track extends Drawn {
|
||||
}
|
||||
|
||||
// Method is used to export data to the server
|
||||
public toJSON(): RawTrackData {
|
||||
public toJSON(): SerializedTrack {
|
||||
const labelAttributes = attrsAsAnObject(this.label.attributes);
|
||||
|
||||
const result: RawTrackData = {
|
||||
const result: SerializedTrack = {
|
||||
clientID: this.clientID,
|
||||
label_id: this.label.id,
|
||||
frame: this.frame,
|
||||
@@ -1032,7 +986,7 @@ export class Track extends Drawn {
|
||||
return result;
|
||||
}
|
||||
|
||||
public updateServerID(body: RawTrackData): void {
|
||||
public updateServerID(body: SerializedTrack): void {
|
||||
this.serverID = body.id;
|
||||
for (const shape of body.shapes) {
|
||||
this.shapes[shape.frame].serverID = shape.id;
|
||||
@@ -1432,20 +1386,10 @@ export class Track extends Drawn {
|
||||
}
|
||||
}
|
||||
|
||||
export interface RawTagData {
|
||||
id?: number;
|
||||
clientID?: number;
|
||||
label_id: number;
|
||||
frame: number;
|
||||
group: number;
|
||||
source: Source;
|
||||
attributes: { spec_id: number; value: string }[];
|
||||
}
|
||||
|
||||
export class Tag extends Annotation {
|
||||
// Method is used to export data to the server
|
||||
public toJSON(): RawTagData {
|
||||
const result: RawTagData = {
|
||||
public toJSON(): SerializedTag {
|
||||
const result: SerializedTag = {
|
||||
clientID: this.clientID,
|
||||
frame: this.frame,
|
||||
label_id: this.label.id,
|
||||
@@ -1536,7 +1480,7 @@ export class Tag extends Annotation {
|
||||
}
|
||||
|
||||
export class RectangleShape extends Shape {
|
||||
constructor(data: RawShapeData, clientID: number, color: string, injection: AnnotationInjection) {
|
||||
constructor(data: SerializedShape, clientID: number, color: string, injection: AnnotationInjection) {
|
||||
super(data, clientID, color, injection);
|
||||
this.shapeType = ShapeType.RECTANGLE;
|
||||
this.pinned = false;
|
||||
@@ -1560,7 +1504,7 @@ export class RectangleShape extends Shape {
|
||||
}
|
||||
|
||||
export class EllipseShape extends Shape {
|
||||
constructor(data: RawShapeData, clientID: number, color: string, injection: AnnotationInjection) {
|
||||
constructor(data: SerializedShape, clientID: number, color: string, injection: AnnotationInjection) {
|
||||
super(data, clientID, color, injection);
|
||||
this.shapeType = ShapeType.ELLIPSE;
|
||||
this.pinned = false;
|
||||
@@ -1616,14 +1560,14 @@ export class EllipseShape extends Shape {
|
||||
}
|
||||
|
||||
class PolyShape extends Shape {
|
||||
constructor(data: RawShapeData, clientID: number, color: string, injection: AnnotationInjection) {
|
||||
constructor(data: SerializedShape, clientID: number, color: string, injection: AnnotationInjection) {
|
||||
super(data, clientID, color, injection);
|
||||
this.rotation = 0; // is not supported
|
||||
}
|
||||
}
|
||||
|
||||
export class PolygonShape extends PolyShape {
|
||||
constructor(data: RawShapeData, clientID: number, color: string, injection: AnnotationInjection) {
|
||||
constructor(data: SerializedShape, clientID: number, color: string, injection: AnnotationInjection) {
|
||||
super(data, clientID, color, injection);
|
||||
this.shapeType = ShapeType.POLYGON;
|
||||
checkNumberOfPoints(this.shapeType, this.points);
|
||||
@@ -1694,7 +1638,7 @@ export class PolygonShape extends PolyShape {
|
||||
}
|
||||
|
||||
export class PolylineShape extends PolyShape {
|
||||
constructor(data: RawShapeData, clientID: number, color: string, injection: AnnotationInjection) {
|
||||
constructor(data: SerializedShape, clientID: number, color: string, injection: AnnotationInjection) {
|
||||
super(data, clientID, color, injection);
|
||||
this.shapeType = ShapeType.POLYLINE;
|
||||
checkNumberOfPoints(this.shapeType, this.points);
|
||||
@@ -1738,7 +1682,7 @@ export class PolylineShape extends PolyShape {
|
||||
}
|
||||
|
||||
export class PointsShape extends PolyShape {
|
||||
constructor(data: RawShapeData, clientID: number, color: string, injection: AnnotationInjection) {
|
||||
constructor(data: SerializedShape, clientID: number, color: string, injection: AnnotationInjection) {
|
||||
super(data, clientID, color, injection);
|
||||
this.shapeType = ShapeType.POINTS;
|
||||
checkNumberOfPoints(this.shapeType, this.points);
|
||||
@@ -1763,7 +1707,7 @@ interface Point2D {
|
||||
}
|
||||
|
||||
export class CuboidShape extends Shape {
|
||||
constructor(data: RawShapeData, clientID: number, color: string, injection: AnnotationInjection) {
|
||||
constructor(data: SerializedShape, clientID: number, color: string, injection: AnnotationInjection) {
|
||||
super(data, clientID, color, injection);
|
||||
this.rotation = 0;
|
||||
this.shapeType = ShapeType.CUBOID;
|
||||
@@ -1888,7 +1832,7 @@ export class CuboidShape extends Shape {
|
||||
export class SkeletonShape extends Shape {
|
||||
public elements: Shape[];
|
||||
|
||||
constructor(data: RawShapeData, clientID: number, color: string, injection: AnnotationInjection) {
|
||||
constructor(data: SerializedShape, clientID: number, color: string, injection: AnnotationInjection) {
|
||||
super(data, clientID, color, injection);
|
||||
this.shapeType = ShapeType.SKELETON;
|
||||
this.pinned = false;
|
||||
@@ -1947,7 +1891,7 @@ export class SkeletonShape extends Shape {
|
||||
}
|
||||
|
||||
// Method is used to export data to the server
|
||||
public toJSON(): RawShapeData {
|
||||
public toJSON(): SerializedShape {
|
||||
const elements = this.elements.map((element) => ({
|
||||
...element.toJSON(),
|
||||
outside: element.outside,
|
||||
@@ -1959,7 +1903,7 @@ export class SkeletonShape extends Shape {
|
||||
elements: undefined,
|
||||
}));
|
||||
|
||||
const result: RawShapeData = {
|
||||
const result: SerializedShape = {
|
||||
type: this.shapeType,
|
||||
clientID: this.clientID,
|
||||
occluded: elements.every((el) => el.occluded),
|
||||
@@ -2030,7 +1974,7 @@ export class SkeletonShape extends Shape {
|
||||
};
|
||||
}
|
||||
|
||||
public updateServerID(body: RawShapeData): void {
|
||||
public updateServerID(body: SerializedShape): void {
|
||||
Shape.prototype.updateServerID.call(this, body);
|
||||
for (const element of body.elements) {
|
||||
const thisElement = this.elements.find((_element: Shape) => _element.label.id === element.label_id);
|
||||
@@ -2339,7 +2283,7 @@ MaskShape.prototype.get = function (frame) {
|
||||
};
|
||||
|
||||
export class RectangleTrack extends Track {
|
||||
constructor(data: RawTrackData, clientID: number, color: string, injection: AnnotationInjection) {
|
||||
constructor(data: SerializedTrack, clientID: number, color: string, injection: AnnotationInjection) {
|
||||
super(data, clientID, color, injection);
|
||||
this.shapeType = ShapeType.RECTANGLE;
|
||||
this.pinned = false;
|
||||
@@ -2364,7 +2308,7 @@ export class RectangleTrack extends Track {
|
||||
}
|
||||
|
||||
export class EllipseTrack extends Track {
|
||||
constructor(data: RawTrackData, clientID: number, color: string, injection: AnnotationInjection) {
|
||||
constructor(data: SerializedTrack, clientID: number, color: string, injection: AnnotationInjection) {
|
||||
super(data, clientID, color, injection);
|
||||
this.shapeType = ShapeType.ELLIPSE;
|
||||
this.pinned = false;
|
||||
@@ -2390,7 +2334,7 @@ export class EllipseTrack extends Track {
|
||||
}
|
||||
|
||||
class PolyTrack extends Track {
|
||||
constructor(data: RawTrackData, clientID: number, color: string, injection: AnnotationInjection) {
|
||||
constructor(data: SerializedTrack, clientID: number, color: string, injection: AnnotationInjection) {
|
||||
super(data, clientID, color, injection);
|
||||
for (const shape of Object.values(this.shapes)) {
|
||||
shape.rotation = 0; // is not supported
|
||||
@@ -2661,7 +2605,7 @@ class PolyTrack extends Track {
|
||||
}
|
||||
|
||||
export class PolygonTrack extends PolyTrack {
|
||||
constructor(data: RawTrackData, clientID: number, color: string, injection: AnnotationInjection) {
|
||||
constructor(data: SerializedTrack, clientID: number, color: string, injection: AnnotationInjection) {
|
||||
super(data, clientID, color, injection);
|
||||
this.shapeType = ShapeType.POLYGON;
|
||||
for (const shape of Object.values(this.shapes)) {
|
||||
@@ -2690,7 +2634,7 @@ export class PolygonTrack extends PolyTrack {
|
||||
}
|
||||
|
||||
export class PolylineTrack extends PolyTrack {
|
||||
constructor(data: RawTrackData, clientID: number, color: string, injection: AnnotationInjection) {
|
||||
constructor(data: SerializedTrack, clientID: number, color: string, injection: AnnotationInjection) {
|
||||
super(data, clientID, color, injection);
|
||||
this.shapeType = ShapeType.POLYLINE;
|
||||
for (const shape of Object.values(this.shapes)) {
|
||||
@@ -2700,7 +2644,7 @@ export class PolylineTrack extends PolyTrack {
|
||||
}
|
||||
|
||||
export class PointsTrack extends PolyTrack {
|
||||
constructor(data: RawTrackData, clientID: number, color: string, injection: AnnotationInjection) {
|
||||
constructor(data: SerializedTrack, clientID: number, color: string, injection: AnnotationInjection) {
|
||||
super(data, clientID, color, injection);
|
||||
this.shapeType = ShapeType.POINTS;
|
||||
for (const shape of Object.values(this.shapes)) {
|
||||
@@ -2733,7 +2677,7 @@ export class PointsTrack extends PolyTrack {
|
||||
}
|
||||
|
||||
export class CuboidTrack extends Track {
|
||||
constructor(data: RawTrackData, clientID: number, color: string, injection: AnnotationInjection) {
|
||||
constructor(data: SerializedTrack, clientID: number, color: string, injection: AnnotationInjection) {
|
||||
super(data, clientID, color, injection);
|
||||
this.shapeType = ShapeType.CUBOID;
|
||||
this.pinned = false;
|
||||
@@ -2793,7 +2737,7 @@ export class CuboidTrack extends Track {
|
||||
export class SkeletonTrack extends Track {
|
||||
public elements: Track[];
|
||||
|
||||
constructor(data: RawTrackData, clientID: number, color: string, injection: AnnotationInjection) {
|
||||
constructor(data: SerializedTrack, clientID: number, color: string, injection: AnnotationInjection) {
|
||||
super(data, clientID, color, injection);
|
||||
this.shapeType = ShapeType.SKELETON;
|
||||
|
||||
@@ -2803,7 +2747,7 @@ export class SkeletonTrack extends Track {
|
||||
|
||||
this.readOnlyFields = ['points', 'label', 'occluded', 'outside'];
|
||||
this.pinned = false;
|
||||
this.elements = data.elements.map((element: RawTrackData['elements'][0]) => (
|
||||
this.elements = data.elements.map((element: SerializedTrack['elements'][0]) => (
|
||||
/* eslint-disable-next-line @typescript-eslint/no-use-before-define */
|
||||
trackFactory({
|
||||
...element,
|
||||
@@ -2819,7 +2763,7 @@ export class SkeletonTrack extends Track {
|
||||
)).sort((a: Annotation, b: Annotation) => a.label.id - b.label.id) as any as Track[];
|
||||
}
|
||||
|
||||
public updateServerID(body: RawTrackData): void {
|
||||
public updateServerID(body: SerializedTrack): void {
|
||||
Track.prototype.updateServerID.call(this, body);
|
||||
for (const element of body.elements) {
|
||||
const thisElement = this.elements.find((_element: Track) => _element.label.id === element.label_id);
|
||||
@@ -2899,8 +2843,8 @@ export class SkeletonTrack extends Track {
|
||||
}
|
||||
|
||||
// Method is used to export data to the server
|
||||
public toJSON(): RawTrackData {
|
||||
const result: RawTrackData = Track.prototype.toJSON.call(this);
|
||||
public toJSON(): SerializedTrack {
|
||||
const result: SerializedTrack = Track.prototype.toJSON.call(this);
|
||||
result.elements = this.elements.map((el) => ({
|
||||
...el.toJSON(),
|
||||
elements: undefined,
|
||||
@@ -3153,7 +3097,7 @@ Object.defineProperty(EllipseTrack, 'distance', { value: EllipseShape.distance }
|
||||
Object.defineProperty(CuboidTrack, 'distance', { value: CuboidShape.distance });
|
||||
Object.defineProperty(SkeletonTrack, 'distance', { value: SkeletonShape.distance });
|
||||
|
||||
export function shapeFactory(data: RawShapeData, clientID: number, injection: AnnotationInjection): Shape {
|
||||
export function shapeFactory(data: SerializedShape, clientID: number, injection: AnnotationInjection): Shape {
|
||||
const { type } = data;
|
||||
const color = colors[clientID % colors.length];
|
||||
|
||||
@@ -3190,7 +3134,7 @@ export function shapeFactory(data: RawShapeData, clientID: number, injection: An
|
||||
return shapeModel;
|
||||
}
|
||||
|
||||
export function trackFactory(trackData: RawTrackData, clientID: number, injection: AnnotationInjection): Track {
|
||||
export function trackFactory(trackData: SerializedTrack, clientID: number, injection: AnnotationInjection): Track {
|
||||
if (trackData.shapes.length) {
|
||||
const { type } = trackData.shapes[0];
|
||||
const color = colors[clientID % colors.length];
|
||||
|
||||
+49
-282
@@ -5,19 +5,20 @@
|
||||
|
||||
import { Storage } from './storage';
|
||||
import serverProxy from './server-proxy';
|
||||
import Collection from './annotations-collection';
|
||||
import AnnotationsCollection from './annotations-collection';
|
||||
import AnnotationsSaver from './annotations-saver';
|
||||
import AnnotationsHistory from './annotations-history';
|
||||
import { checkObjectType } from './common';
|
||||
import Project from './project';
|
||||
import { Task, Job } from './session';
|
||||
import { ScriptingError, DataError, ArgumentError } from './exceptions';
|
||||
import { ScriptingError, ArgumentError } from './exceptions';
|
||||
import { getDeletedFrames } from './frames';
|
||||
|
||||
const jobCache = new WeakMap();
|
||||
const taskCache = new WeakMap();
|
||||
type WeakMapItem = { collection: AnnotationsCollection, saver: AnnotationsSaver, history: AnnotationsHistory };
|
||||
const jobCache = new WeakMap<Task | Job, WeakMapItem>();
|
||||
const taskCache = new WeakMap<Task | Job, WeakMapItem>();
|
||||
|
||||
function getCache(sessionType) {
|
||||
function getCache(sessionType): WeakMap<Task | Job, WeakMapItem> {
|
||||
if (sessionType === 'task') {
|
||||
return taskCache;
|
||||
}
|
||||
@@ -29,6 +30,33 @@ function getCache(sessionType) {
|
||||
throw new ScriptingError(`Unknown session type was received ${sessionType}`);
|
||||
}
|
||||
|
||||
class InstanceNotInitializedError extends Error {}
|
||||
|
||||
function getSession(session): WeakMapItem {
|
||||
const sessionType = session instanceof Task ? 'task' : 'job';
|
||||
const cache = getCache(sessionType);
|
||||
|
||||
if (cache.has(session)) {
|
||||
return cache.get(session);
|
||||
}
|
||||
|
||||
throw new InstanceNotInitializedError(
|
||||
'Session has not been initialized yet. Call annotations.get() or annotations.clear(true) before',
|
||||
);
|
||||
}
|
||||
|
||||
export function getCollection(session): AnnotationsCollection {
|
||||
return getSession(session).collection;
|
||||
}
|
||||
|
||||
export function getSaver(session): AnnotationsSaver {
|
||||
return getSession(session).saver;
|
||||
}
|
||||
|
||||
export function getHistory(session): AnnotationsHistory {
|
||||
return getSession(session).history;
|
||||
}
|
||||
|
||||
function processGroundTruthAnnotations(rawAnnotations, groundTruthAnnotations) {
|
||||
const annotations = [].concat(
|
||||
groundTruthAnnotations.shapes,
|
||||
@@ -59,7 +87,7 @@ function addJobId(rawAnnotations, jobID) {
|
||||
return result;
|
||||
}
|
||||
|
||||
async function getAnnotationsFromServer(session, groundTruthJobId) {
|
||||
async function getAnnotationsFromServer(session, groundTruthJobId): Promise<void> {
|
||||
const sessionType = session instanceof Task ? 'task' : 'job';
|
||||
const cache = getCache(sessionType);
|
||||
|
||||
@@ -82,7 +110,7 @@ async function getAnnotationsFromServer(session, groundTruthJobId) {
|
||||
frameMeta.deleted_frames = await getDeletedFrames(sessionType, session.id);
|
||||
|
||||
const history = new AnnotationsHistory();
|
||||
const collection = new Collection({
|
||||
const collection = new AnnotationsCollection({
|
||||
labels: session.labels || session.task.labels,
|
||||
history,
|
||||
stopFrame,
|
||||
@@ -97,7 +125,7 @@ async function getAnnotationsFromServer(session, groundTruthJobId) {
|
||||
}
|
||||
}
|
||||
|
||||
export async function clearCache(session) {
|
||||
export function clearCache(session): void {
|
||||
const sessionType = session instanceof Task ? 'task' : 'job';
|
||||
const cache = getCache(sessionType);
|
||||
|
||||
@@ -106,213 +134,30 @@ export async function clearCache(session) {
|
||||
}
|
||||
}
|
||||
|
||||
export async function getAnnotations(session, frame, allTracks, filters, groundTruthJobId) {
|
||||
const sessionType = session instanceof Task ? 'task' : 'job';
|
||||
const cache = getCache(sessionType);
|
||||
export async function getAnnotations(session, frame, allTracks, filters, groundTruthJobId): Promise<ReturnType<AnnotationsCollection['get']>> {
|
||||
try {
|
||||
return getCollection(session).get(frame, allTracks, filters);
|
||||
} catch (error) {
|
||||
if (error instanceof InstanceNotInitializedError) {
|
||||
await getAnnotationsFromServer(session, groundTruthJobId);
|
||||
return getCollection(session).get(frame, allTracks, filters);
|
||||
}
|
||||
|
||||
if (cache.has(session)) {
|
||||
return cache.get(session).collection.get(frame, allTracks, filters);
|
||||
throw error;
|
||||
}
|
||||
|
||||
await getAnnotationsFromServer(session, groundTruthJobId);
|
||||
return cache.get(session).collection.get(frame, allTracks, filters);
|
||||
}
|
||||
|
||||
export async function saveAnnotations(session, onUpdate) {
|
||||
const sessionType = session instanceof Task ? 'task' : 'job';
|
||||
const cache = getCache(sessionType);
|
||||
|
||||
if (cache.has(session)) {
|
||||
await cache.get(session).saver.save(onUpdate);
|
||||
}
|
||||
|
||||
// If a collection wasn't uploaded, than it wasn't changed, finally we shouldn't save it
|
||||
}
|
||||
|
||||
export function searchAnnotations(session, filters, frameFrom, frameTo) {
|
||||
const sessionType = session instanceof Task ? 'task' : 'job';
|
||||
const cache = getCache(sessionType);
|
||||
|
||||
if (cache.has(session)) {
|
||||
return cache.get(session).collection.search(filters, frameFrom, frameTo);
|
||||
}
|
||||
|
||||
throw new DataError(
|
||||
'Collection has not been initialized yet. Call annotations.get() or annotations.clear(true) before',
|
||||
);
|
||||
}
|
||||
|
||||
export function searchEmptyFrame(session, frameFrom, frameTo) {
|
||||
const sessionType = session instanceof Task ? 'task' : 'job';
|
||||
const cache = getCache(sessionType);
|
||||
|
||||
if (cache.has(session)) {
|
||||
return cache.get(session).collection.searchEmpty(frameFrom, frameTo);
|
||||
}
|
||||
|
||||
throw new DataError(
|
||||
'Collection has not been initialized yet. Call annotations.get() or annotations.clear(true) before',
|
||||
);
|
||||
}
|
||||
|
||||
export function mergeAnnotations(session, objectStates) {
|
||||
const sessionType = session instanceof Task ? 'task' : 'job';
|
||||
const cache = getCache(sessionType);
|
||||
|
||||
if (cache.has(session)) {
|
||||
return cache.get(session).collection.merge(objectStates);
|
||||
}
|
||||
|
||||
throw new DataError(
|
||||
'Collection has not been initialized yet. Call annotations.get() or annotations.clear(true) before',
|
||||
);
|
||||
}
|
||||
|
||||
export function splitAnnotations(session, objectState, frame) {
|
||||
const sessionType = session instanceof Task ? 'task' : 'job';
|
||||
const cache = getCache(sessionType);
|
||||
|
||||
if (cache.has(session)) {
|
||||
return cache.get(session).collection.split(objectState, frame);
|
||||
}
|
||||
|
||||
throw new DataError(
|
||||
'Collection has not been initialized yet. Call annotations.get() or annotations.clear(true) before',
|
||||
);
|
||||
}
|
||||
|
||||
export function groupAnnotations(session, objectStates, reset) {
|
||||
const sessionType = session instanceof Task ? 'task' : 'job';
|
||||
const cache = getCache(sessionType);
|
||||
|
||||
if (cache.has(session)) {
|
||||
return cache.get(session).collection.group(objectStates, reset);
|
||||
}
|
||||
|
||||
throw new DataError(
|
||||
'Collection has not been initialized yet. Call annotations.get() or annotations.clear(true) before',
|
||||
);
|
||||
}
|
||||
|
||||
export function joinAnnotations(session, objectStates, points) {
|
||||
const sessionType = session instanceof Task ? 'task' : 'job';
|
||||
const cache = getCache(sessionType);
|
||||
|
||||
if (cache.has(session)) {
|
||||
return cache.get(session).collection.join(objectStates, points);
|
||||
}
|
||||
|
||||
throw new DataError(
|
||||
'Collection has not been initialized yet. Call annotations.get() or annotations.clear(true) before',
|
||||
);
|
||||
}
|
||||
|
||||
export function sliceAnnotations(session, state, results) {
|
||||
const sessionType = session instanceof Task ? 'task' : 'job';
|
||||
const cache = getCache(sessionType);
|
||||
|
||||
if (cache.has(session)) {
|
||||
return cache.get(session).collection.slice(state, results);
|
||||
}
|
||||
|
||||
throw new DataError(
|
||||
'Collection has not been initialized yet. Call annotations.get() or annotations.clear(true) before',
|
||||
);
|
||||
}
|
||||
|
||||
export function hasUnsavedChanges(session) {
|
||||
const sessionType = session instanceof Task ? 'task' : 'job';
|
||||
const cache = getCache(sessionType);
|
||||
|
||||
if (cache.has(session)) {
|
||||
return cache.get(session).saver.hasUnsavedChanges();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
export async function clearAnnotations(session, reload, startframe, endframe, delTrackKeyframesOnly) {
|
||||
export async function clearAnnotations(session, reload, startframe, endframe, delTrackKeyframesOnly): Promise<void> {
|
||||
checkObjectType('reload', reload, 'boolean', null);
|
||||
const sessionType = session instanceof Task ? 'task' : 'job';
|
||||
const cache = getCache(sessionType);
|
||||
|
||||
if (cache.has(session)) {
|
||||
cache.get(session).collection.clear(startframe, endframe, delTrackKeyframesOnly);
|
||||
}
|
||||
|
||||
if (reload) {
|
||||
cache.delete(session);
|
||||
await getAnnotationsFromServer(session);
|
||||
}
|
||||
}
|
||||
|
||||
export function annotationsStatistics(session) {
|
||||
const sessionType = session instanceof Task ? 'task' : 'job';
|
||||
const cache = getCache(sessionType);
|
||||
|
||||
if (cache.has(session)) {
|
||||
if (sessionType === 'job') {
|
||||
return cache.get(session).collection.statistics({ jobID: session.id });
|
||||
}
|
||||
return cache.get(session).collection.statistics();
|
||||
return getAnnotationsFromServer(session);
|
||||
}
|
||||
|
||||
throw new DataError(
|
||||
'Collection has not been initialized yet. Call annotations.get() or annotations.clear(true) before',
|
||||
);
|
||||
}
|
||||
|
||||
export function putAnnotations(session, objectStates) {
|
||||
const sessionType = session instanceof Task ? 'task' : 'job';
|
||||
const cache = getCache(sessionType);
|
||||
|
||||
if (cache.has(session)) {
|
||||
return cache.get(session).collection.put(objectStates);
|
||||
}
|
||||
|
||||
throw new DataError(
|
||||
'Collection has not been initialized yet. Call annotations.get() or annotations.clear(true) before',
|
||||
);
|
||||
}
|
||||
|
||||
export function selectObject(session, objectStates, x, y) {
|
||||
const sessionType = session instanceof Task ? 'task' : 'job';
|
||||
const cache = getCache(sessionType);
|
||||
|
||||
if (cache.has(session)) {
|
||||
return cache.get(session).collection.select(objectStates, x, y);
|
||||
}
|
||||
|
||||
throw new DataError(
|
||||
'Collection has not been initialized yet. Call annotations.get() or annotations.clear(true) before',
|
||||
);
|
||||
}
|
||||
|
||||
export function importCollection(session, data) {
|
||||
const sessionType = session instanceof Task ? 'task' : 'job';
|
||||
const cache = getCache(sessionType);
|
||||
|
||||
if (cache.has(session)) {
|
||||
// eslint-disable-next-line no-unsanitized/method
|
||||
return cache.get(session).collection.import(data);
|
||||
}
|
||||
|
||||
throw new DataError(
|
||||
'Collection has not been initialized yet. Call annotations.get() or annotations.clear(true) before',
|
||||
);
|
||||
}
|
||||
|
||||
export function exportCollection(session) {
|
||||
const sessionType = session instanceof Task ? 'task' : 'job';
|
||||
const cache = getCache(sessionType);
|
||||
|
||||
if (cache.has(session)) {
|
||||
return cache.get(session).collection.export();
|
||||
}
|
||||
|
||||
throw new DataError(
|
||||
'Collection has not been initialized yet. Call annotations.get() or annotations.clear(true) before',
|
||||
);
|
||||
return getCollection(session).clear(startframe, endframe, delTrackKeyframesOnly);
|
||||
}
|
||||
|
||||
export async function exportDataset(
|
||||
@@ -322,7 +167,7 @@ export async function exportDataset(
|
||||
useDefaultSettings: boolean,
|
||||
targetStorage: Storage,
|
||||
name?: string,
|
||||
) {
|
||||
): Promise<string | void> {
|
||||
if (!(instance instanceof Task || instance instanceof Project || instance instanceof Job)) {
|
||||
throw new ArgumentError('A dataset can only be created from a job, task or project');
|
||||
}
|
||||
@@ -413,81 +258,3 @@ export function importDataset(
|
||||
adjustedOptions,
|
||||
);
|
||||
}
|
||||
|
||||
export function getHistory(session) {
|
||||
const sessionType = session instanceof Task ? 'task' : 'job';
|
||||
const cache = getCache(sessionType);
|
||||
|
||||
if (cache.has(session)) {
|
||||
return cache.get(session).history;
|
||||
}
|
||||
|
||||
throw new DataError(
|
||||
'Collection has not been initialized yet. Call annotations.get() or annotations.clear(true) before',
|
||||
);
|
||||
}
|
||||
|
||||
export async function undoActions(session, count) {
|
||||
const sessionType = session instanceof Task ? 'task' : 'job';
|
||||
const cache = getCache(sessionType);
|
||||
|
||||
if (cache.has(session)) {
|
||||
return cache.get(session).history.undo(count);
|
||||
}
|
||||
|
||||
throw new DataError(
|
||||
'Collection has not been initialized yet. Call annotations.get() or annotations.clear(true) before',
|
||||
);
|
||||
}
|
||||
|
||||
export async function redoActions(session, count) {
|
||||
const sessionType = session instanceof Task ? 'task' : 'job';
|
||||
const cache = getCache(sessionType);
|
||||
|
||||
if (cache.has(session)) {
|
||||
return cache.get(session).history.redo(count);
|
||||
}
|
||||
|
||||
throw new DataError(
|
||||
'Collection has not been initialized yet. Call annotations.get() or annotations.clear(true) before',
|
||||
);
|
||||
}
|
||||
|
||||
export function freezeHistory(session, frozen) {
|
||||
const sessionType = session instanceof Task ? 'task' : 'job';
|
||||
const cache = getCache(sessionType);
|
||||
|
||||
if (cache.has(session)) {
|
||||
return cache.get(session).history.freeze(frozen);
|
||||
}
|
||||
|
||||
throw new DataError(
|
||||
'Collection has not been initialized yet. Call annotations.get() or annotations.clear(true) before',
|
||||
);
|
||||
}
|
||||
|
||||
export function clearActions(session) {
|
||||
const sessionType = session instanceof Task ? 'task' : 'job';
|
||||
const cache = getCache(sessionType);
|
||||
|
||||
if (cache.has(session)) {
|
||||
return cache.get(session).history.clear();
|
||||
}
|
||||
|
||||
throw new DataError(
|
||||
'Collection has not been initialized yet. Call annotations.get() or annotations.clear(true) before',
|
||||
);
|
||||
}
|
||||
|
||||
export function getActions(session) {
|
||||
const sessionType = session instanceof Task ? 'task' : 'job';
|
||||
const cache = getCache(sessionType);
|
||||
|
||||
if (cache.has(session)) {
|
||||
return cache.get(session).history.get();
|
||||
}
|
||||
|
||||
throw new DataError(
|
||||
'Collection has not been initialized yet. Call annotations.get() or annotations.clear(true) before',
|
||||
);
|
||||
}
|
||||
|
||||
@@ -33,39 +33,40 @@ import QualityConflict from './quality-conflict';
|
||||
import QualitySettings from './quality-settings';
|
||||
import { FramesMetaData } from './frames';
|
||||
import AnalyticsReport from './analytics-report';
|
||||
import CVATCore from '.';
|
||||
|
||||
export default function implementAPI(cvat) {
|
||||
cvat.plugins.list.implementation = PluginRegistry.list;
|
||||
cvat.plugins.register.implementation = PluginRegistry.register.bind(cvat);
|
||||
function implementationMixin(func: Function, implementation: Function): void {
|
||||
Object.assign(func, { implementation });
|
||||
}
|
||||
|
||||
cvat.lambda.list.implementation = lambdaManager.list.bind(lambdaManager);
|
||||
cvat.lambda.run.implementation = lambdaManager.run.bind(lambdaManager);
|
||||
cvat.lambda.call.implementation = lambdaManager.call.bind(lambdaManager);
|
||||
cvat.lambda.cancel.implementation = lambdaManager.cancel.bind(lambdaManager);
|
||||
cvat.lambda.listen.implementation = lambdaManager.listen.bind(lambdaManager);
|
||||
cvat.lambda.requests.implementation = lambdaManager.requests.bind(lambdaManager);
|
||||
export default function implementAPI(cvat: CVATCore): CVATCore {
|
||||
implementationMixin(cvat.plugins.list, PluginRegistry.list);
|
||||
implementationMixin(cvat.plugins.register, PluginRegistry.register.bind(cvat));
|
||||
|
||||
cvat.server.about.implementation = async () => {
|
||||
implementationMixin(cvat.lambda.list, lambdaManager.list.bind(lambdaManager));
|
||||
implementationMixin(cvat.lambda.run, lambdaManager.run.bind(lambdaManager));
|
||||
implementationMixin(cvat.lambda.call, lambdaManager.call.bind(lambdaManager));
|
||||
implementationMixin(cvat.lambda.cancel, lambdaManager.cancel.bind(lambdaManager));
|
||||
implementationMixin(cvat.lambda.listen, lambdaManager.listen.bind(lambdaManager));
|
||||
implementationMixin(cvat.lambda.requests, lambdaManager.requests.bind(lambdaManager));
|
||||
|
||||
implementationMixin(cvat.server.about, async () => {
|
||||
const result = await serverProxy.server.about();
|
||||
return result;
|
||||
};
|
||||
|
||||
cvat.server.share.implementation = async (directory: string, searchPrefix?: string) => {
|
||||
});
|
||||
implementationMixin(cvat.server.share, async (directory: string, searchPrefix?: string) => {
|
||||
const result = await serverProxy.server.share(directory, searchPrefix);
|
||||
return result.map((item) => ({ ...omit(item, 'mime_type'), mimeType: item.mime_type }));
|
||||
};
|
||||
|
||||
cvat.server.formats.implementation = async () => {
|
||||
});
|
||||
implementationMixin(cvat.server.formats, async () => {
|
||||
const result = await serverProxy.server.formats();
|
||||
return new AnnotationFormats(result);
|
||||
};
|
||||
|
||||
cvat.server.userAgreements.implementation = async () => {
|
||||
});
|
||||
implementationMixin(cvat.server.userAgreements, async () => {
|
||||
const result = await serverProxy.server.userAgreements();
|
||||
return result;
|
||||
};
|
||||
|
||||
cvat.server.register.implementation = async (
|
||||
});
|
||||
implementationMixin(cvat.server.register, async (
|
||||
username,
|
||||
firstName,
|
||||
lastName,
|
||||
@@ -83,34 +84,27 @@ export default function implementAPI(cvat) {
|
||||
);
|
||||
|
||||
return new User(user);
|
||||
};
|
||||
|
||||
cvat.server.login.implementation = async (username, password) => {
|
||||
});
|
||||
implementationMixin(cvat.server.login, async (username, password) => {
|
||||
await serverProxy.server.login(username, password);
|
||||
};
|
||||
|
||||
cvat.server.logout.implementation = async () => {
|
||||
});
|
||||
implementationMixin(cvat.server.logout, async () => {
|
||||
await serverProxy.server.logout();
|
||||
};
|
||||
|
||||
cvat.server.changePassword.implementation = async (oldPassword, newPassword1, newPassword2) => {
|
||||
});
|
||||
implementationMixin(cvat.server.changePassword, async (oldPassword, newPassword1, newPassword2) => {
|
||||
await serverProxy.server.changePassword(oldPassword, newPassword1, newPassword2);
|
||||
};
|
||||
|
||||
cvat.server.requestPasswordReset.implementation = async (email) => {
|
||||
});
|
||||
implementationMixin(cvat.server.requestPasswordReset, async (email) => {
|
||||
await serverProxy.server.requestPasswordReset(email);
|
||||
};
|
||||
|
||||
cvat.server.resetPassword.implementation = async (newPassword1, newPassword2, uid, token) => {
|
||||
});
|
||||
implementationMixin(cvat.server.resetPassword, async (newPassword1, newPassword2, uid, token) => {
|
||||
await serverProxy.server.resetPassword(newPassword1, newPassword2, uid, token);
|
||||
};
|
||||
|
||||
cvat.server.authorized.implementation = async () => {
|
||||
});
|
||||
implementationMixin(cvat.server.authorized, async () => {
|
||||
const result = await serverProxy.server.authorized();
|
||||
return result;
|
||||
};
|
||||
|
||||
cvat.server.healthCheck.implementation = async (
|
||||
});
|
||||
implementationMixin(cvat.server.healthCheck, async (
|
||||
maxRetries = 1,
|
||||
checkPeriod = 3000,
|
||||
requestTimeout = 5000,
|
||||
@@ -118,38 +112,34 @@ export default function implementAPI(cvat) {
|
||||
) => {
|
||||
const result = await serverProxy.server.healthCheck(maxRetries, checkPeriod, requestTimeout, progressCallback);
|
||||
return result;
|
||||
};
|
||||
|
||||
cvat.server.request.implementation = async (url, data, requestConfig) => {
|
||||
});
|
||||
implementationMixin(cvat.server.request, async (url, data, requestConfig) => {
|
||||
const result = await serverProxy.server.request(url, data, requestConfig);
|
||||
return result;
|
||||
};
|
||||
|
||||
cvat.server.setAuthData.implementation = async (response) => {
|
||||
});
|
||||
implementationMixin(cvat.server.setAuthData, async (response) => {
|
||||
const result = await serverProxy.server.setAuthData(response);
|
||||
return result;
|
||||
};
|
||||
|
||||
cvat.server.removeAuthData.implementation = async () => {
|
||||
});
|
||||
implementationMixin(cvat.server.removeAuthData, async () => {
|
||||
const result = await serverProxy.server.removeAuthData();
|
||||
return result;
|
||||
};
|
||||
|
||||
cvat.server.installedApps.implementation = async () => {
|
||||
});
|
||||
implementationMixin(cvat.server.installedApps, async () => {
|
||||
const result = await serverProxy.server.installedApps();
|
||||
return result;
|
||||
};
|
||||
});
|
||||
|
||||
cvat.assets.create.implementation = async (file: File, guideId: number): Promise<SerializedAsset> => {
|
||||
implementationMixin(cvat.assets.create, async (file: File, guideId: number): Promise<SerializedAsset> => {
|
||||
if (!(file instanceof File)) {
|
||||
throw new ArgumentError('Assets expect a file');
|
||||
}
|
||||
|
||||
const result = await serverProxy.assets.create(file, guideId);
|
||||
return result;
|
||||
};
|
||||
});
|
||||
|
||||
cvat.users.get.implementation = async (filter) => {
|
||||
implementationMixin(cvat.users.get, async (filter) => {
|
||||
checkFilter(filter, {
|
||||
id: isInteger,
|
||||
is_active: isBoolean,
|
||||
@@ -174,9 +164,9 @@ export default function implementAPI(cvat) {
|
||||
|
||||
users = users.map((user) => new User(user));
|
||||
return users;
|
||||
};
|
||||
});
|
||||
|
||||
cvat.jobs.get.implementation = async (query) => {
|
||||
implementationMixin(cvat.jobs.get, async (query) => {
|
||||
checkFilter(query, {
|
||||
page: isInteger,
|
||||
filter: isString,
|
||||
@@ -215,9 +205,9 @@ export default function implementAPI(cvat) {
|
||||
const jobs = jobsData.results.map((jobData) => new Job(jobData));
|
||||
jobs.count = jobsData.count;
|
||||
return jobs;
|
||||
};
|
||||
});
|
||||
|
||||
cvat.tasks.get.implementation = async (filter) => {
|
||||
implementationMixin(cvat.tasks.get, async (filter) => {
|
||||
checkFilter(filter, {
|
||||
page: isInteger,
|
||||
projectId: isInteger,
|
||||
@@ -264,9 +254,9 @@ export default function implementAPI(cvat) {
|
||||
|
||||
tasks.count = tasksData.count;
|
||||
return tasks;
|
||||
};
|
||||
});
|
||||
|
||||
cvat.projects.get.implementation = async (filter) => {
|
||||
implementationMixin(cvat.projects.get, async (filter) => {
|
||||
checkFilter(filter, {
|
||||
id: isInteger,
|
||||
page: isInteger,
|
||||
@@ -298,12 +288,12 @@ export default function implementAPI(cvat) {
|
||||
|
||||
projects.count = projectsData.count;
|
||||
return projects;
|
||||
};
|
||||
});
|
||||
|
||||
cvat.projects.searchNames
|
||||
.implementation = async (search, limit) => serverProxy.projects.searchNames(search, limit);
|
||||
implementationMixin(cvat.projects.searchNames,
|
||||
async (search, limit) => serverProxy.projects.searchNames(search, limit));
|
||||
|
||||
cvat.cloudStorages.get.implementation = async (filter) => {
|
||||
implementationMixin(cvat.cloudStorages.get, async (filter) => {
|
||||
checkFilter(filter, {
|
||||
page: isInteger,
|
||||
filter: isString,
|
||||
@@ -323,9 +313,9 @@ export default function implementAPI(cvat) {
|
||||
const cloudStorages = cloudStoragesData.map((cloudStorage) => new CloudStorage(cloudStorage));
|
||||
cloudStorages.count = cloudStoragesData.count;
|
||||
return cloudStorages;
|
||||
};
|
||||
});
|
||||
|
||||
cvat.organizations.get.implementation = async (filter) => {
|
||||
implementationMixin(cvat.organizations.get, async (filter) => {
|
||||
checkFilter(filter, {
|
||||
search: isString,
|
||||
filter: isString,
|
||||
@@ -334,24 +324,21 @@ export default function implementAPI(cvat) {
|
||||
const organizationsData = await serverProxy.organizations.get(filter);
|
||||
const organizations = organizationsData.map((organizationData) => new Organization(organizationData));
|
||||
return organizations;
|
||||
};
|
||||
|
||||
cvat.organizations.activate.implementation = (organization) => {
|
||||
});
|
||||
implementationMixin(cvat.organizations.activate, (organization) => {
|
||||
checkObjectType('organization', organization, null, Organization);
|
||||
config.organization = {
|
||||
organizationID: organization.id,
|
||||
organizationSlug: organization.slug,
|
||||
};
|
||||
};
|
||||
|
||||
cvat.organizations.deactivate.implementation = async () => {
|
||||
});
|
||||
implementationMixin(cvat.organizations.deactivate, async () => {
|
||||
config.organization = {
|
||||
organizationID: null,
|
||||
organizationSlug: null,
|
||||
};
|
||||
};
|
||||
|
||||
cvat.organizations.acceptInvitation.implementation = async (
|
||||
});
|
||||
implementationMixin(cvat.organizations.acceptInvitation, async (
|
||||
username,
|
||||
firstName,
|
||||
lastName,
|
||||
@@ -371,9 +358,9 @@ export default function implementAPI(cvat) {
|
||||
);
|
||||
|
||||
return orgSlug;
|
||||
};
|
||||
});
|
||||
|
||||
cvat.webhooks.get.implementation = async (filter) => {
|
||||
implementationMixin(cvat.webhooks.get, async (filter) => {
|
||||
checkFilter(filter, {
|
||||
page: isInteger,
|
||||
id: isInteger,
|
||||
@@ -391,9 +378,9 @@ export default function implementAPI(cvat) {
|
||||
const webhooks = webhooksData.map((webhookData) => new Webhook(webhookData));
|
||||
webhooks.count = webhooksData.count;
|
||||
return webhooks;
|
||||
};
|
||||
});
|
||||
|
||||
cvat.analytics.quality.reports.implementation = async (filter) => {
|
||||
implementationMixin(cvat.analytics.quality.reports, async (filter) => {
|
||||
let updatedParams: Record<string, string> = {};
|
||||
if ('taskId' in filter) {
|
||||
updatedParams = {
|
||||
@@ -412,9 +399,8 @@ export default function implementAPI(cvat) {
|
||||
const reportsData = await serverProxy.analytics.quality.reports(updatedParams);
|
||||
|
||||
return reportsData.map((report) => new QualityReport({ ...report }));
|
||||
};
|
||||
|
||||
cvat.analytics.quality.conflicts.implementation = async (filter) => {
|
||||
});
|
||||
implementationMixin(cvat.analytics.quality.conflicts, async (filter) => {
|
||||
let updatedParams: Record<string, string> = {};
|
||||
if ('reportId' in filter) {
|
||||
updatedParams = {
|
||||
@@ -425,19 +411,12 @@ export default function implementAPI(cvat) {
|
||||
const reportsData = await serverProxy.analytics.quality.conflicts(updatedParams);
|
||||
|
||||
return reportsData.map((conflict) => new QualityConflict({ ...conflict }));
|
||||
};
|
||||
|
||||
cvat.analytics.quality.settings.get.implementation = async (taskID: number) => {
|
||||
});
|
||||
implementationMixin(cvat.analytics.quality.settings.get, async (taskID: number) => {
|
||||
const settings = await serverProxy.analytics.quality.settings.get(taskID);
|
||||
return new QualitySettings({ ...settings });
|
||||
};
|
||||
|
||||
cvat.frames.getMeta.implementation = async (type, id) => {
|
||||
const result = await serverProxy.frames.getMeta(type, id);
|
||||
return new FramesMetaData({ ...result });
|
||||
};
|
||||
|
||||
cvat.analytics.performance.reports.implementation = async (filter) => {
|
||||
});
|
||||
implementationMixin(cvat.analytics.performance.reports, async (filter) => {
|
||||
checkFilter(filter, {
|
||||
jobID: isInteger,
|
||||
taskID: isInteger,
|
||||
@@ -468,7 +447,11 @@ export default function implementAPI(cvat) {
|
||||
|
||||
const reportData = await serverProxy.analytics.performance.reports(updatedParams);
|
||||
return new AnalyticsReport(reportData);
|
||||
};
|
||||
});
|
||||
implementationMixin(cvat.frames.getMeta, async (type, id) => {
|
||||
const result = await serverProxy.frames.getMeta(type, id);
|
||||
return new FramesMetaData({ ...result });
|
||||
});
|
||||
|
||||
return cvat;
|
||||
}
|
||||
|
||||
@@ -34,9 +34,10 @@ import pjson from '../package.json';
|
||||
import config from './config';
|
||||
|
||||
import implementAPI from './api-implementation';
|
||||
import CVATCore from '.';
|
||||
|
||||
function build() {
|
||||
const cvat = {
|
||||
function build(): CVATCore {
|
||||
const cvat: CVATCore = {
|
||||
server: {
|
||||
async about() {
|
||||
const result = await PluginRegistry.apiWrapper(cvat.server.about);
|
||||
|
||||
@@ -14,7 +14,7 @@ export interface RawCommentData {
|
||||
owner?: any;
|
||||
}
|
||||
|
||||
interface SerializedCommentData extends RawCommentData{
|
||||
interface SerializedCommentData extends RawCommentData {
|
||||
owner_id?: number;
|
||||
issue?: number;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// Copyright (C) 2022 Intel Corporation
|
||||
// Copyright (C) 2023 CVAT.ai Corporation
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
@@ -0,0 +1,150 @@
|
||||
// Copyright (C) 2023 CVAT.ai Corporation
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import PluginRegistry from './plugins';
|
||||
import serverProxy from './server-proxy';
|
||||
import lambdaManager from './lambda-manager';
|
||||
import { AnnotationFormats } from './annotation-formats';
|
||||
import loggerStorage from './logger-storage';
|
||||
import * as enums from './enums';
|
||||
import config from './config';
|
||||
import { mask2Rle, rle2Mask } from './object-utils';
|
||||
import User from './user';
|
||||
import Project from './project';
|
||||
import { Job, Task } from './session';
|
||||
import { EventLogger } from './log';
|
||||
import { Attribute, Label } from './labels';
|
||||
import Statistics from './statistics';
|
||||
import ObjectState from './object-state';
|
||||
import MLModel from './ml-model';
|
||||
import Issue from './issue';
|
||||
import Comment from './comment';
|
||||
import { FrameData } from './frames';
|
||||
import CloudStorage from './cloud-storage';
|
||||
import Organization from './organization';
|
||||
import Webhook from './webhook';
|
||||
import AnnotationGuide from './guide';
|
||||
import {
|
||||
ArgumentError, DataError, Exception, ScriptingError, ServerError,
|
||||
} from './exceptions';
|
||||
|
||||
export default interface CVATCore {
|
||||
plugins: {
|
||||
list: typeof PluginRegistry.list;
|
||||
register: typeof PluginRegistry.register;
|
||||
};
|
||||
lambda: {
|
||||
list: typeof lambdaManager.list;
|
||||
run: typeof lambdaManager.run;
|
||||
call: typeof lambdaManager.call;
|
||||
cancel: typeof lambdaManager.cancel;
|
||||
listen: typeof lambdaManager.listen;
|
||||
requests: typeof lambdaManager.requests;
|
||||
};
|
||||
server: {
|
||||
about: typeof serverProxy.server.about;
|
||||
share: (dir: string) => Promise<{
|
||||
mimeType: string;
|
||||
name: string;
|
||||
type: enums.ShareFileType;
|
||||
}[]>;
|
||||
formats: () => Promise<AnnotationFormats>;
|
||||
userAgreements: typeof serverProxy.server.userAgreements,
|
||||
register: any; // TODO: add types later
|
||||
login: any;
|
||||
logout: any;
|
||||
changePassword: any;
|
||||
requestPasswordReset: any;
|
||||
resetPassword: any;
|
||||
authorized: any;
|
||||
healthCheck: any;
|
||||
request: any;
|
||||
setAuthData: any;
|
||||
removeAuthData: any;
|
||||
installedApps: any;
|
||||
};
|
||||
assets: {
|
||||
create: any;
|
||||
};
|
||||
users: {
|
||||
get: any;
|
||||
};
|
||||
jobs: {
|
||||
get: any;
|
||||
};
|
||||
tasks: {
|
||||
get: any;
|
||||
}
|
||||
projects: {
|
||||
get: any;
|
||||
searchNames: any;
|
||||
};
|
||||
cloudStorages: {
|
||||
get: any;
|
||||
};
|
||||
organizations: {
|
||||
get: any;
|
||||
activate: any;
|
||||
deactivate: any;
|
||||
acceptInvitation: any;
|
||||
};
|
||||
webhooks: {
|
||||
get: any;
|
||||
};
|
||||
analytics: {
|
||||
quality: {
|
||||
reports: any;
|
||||
conflicts: any;
|
||||
settings: any;
|
||||
};
|
||||
performance: {
|
||||
reports: any;
|
||||
};
|
||||
};
|
||||
frames: {
|
||||
getMeta: any;
|
||||
};
|
||||
logger: typeof loggerStorage;
|
||||
config: {
|
||||
backendAPI: typeof config.backendAPI;
|
||||
origin: typeof config.origin;
|
||||
uploadChunkSize: typeof config.uploadChunkSize;
|
||||
removeUnderlyingMaskPixels: typeof config.removeUnderlyingMaskPixels;
|
||||
onOrganizationChange: typeof config.onOrganizationChange;
|
||||
},
|
||||
client: {
|
||||
version: string;
|
||||
};
|
||||
enums,
|
||||
exceptions: {
|
||||
Exception: typeof Exception,
|
||||
ArgumentError: typeof ArgumentError,
|
||||
DataError: typeof DataError,
|
||||
ScriptingError: typeof ScriptingError,
|
||||
ServerError: typeof ServerError,
|
||||
},
|
||||
classes: {
|
||||
User: typeof User;
|
||||
Project: typeof Project;
|
||||
Task: typeof Task;
|
||||
Job: typeof Job;
|
||||
EventLogger: typeof EventLogger;
|
||||
Attribute: typeof Attribute;
|
||||
Label: typeof Label;
|
||||
Statistics: typeof Statistics;
|
||||
ObjectState: typeof ObjectState;
|
||||
MLModel: typeof MLModel;
|
||||
Comment: typeof Comment;
|
||||
Issue: typeof Issue;
|
||||
FrameData: typeof FrameData;
|
||||
CloudStorage: typeof CloudStorage;
|
||||
Organization: typeof Organization;
|
||||
Webhook: typeof Webhook;
|
||||
AnnotationGuide: typeof AnnotationGuide;
|
||||
};
|
||||
utils: {
|
||||
mask2Rle: typeof mask2Rle;
|
||||
rle2Mask: typeof rle2Mask;
|
||||
};
|
||||
}
|
||||
@@ -60,7 +60,7 @@ export interface SerializedData {
|
||||
last: number | null;
|
||||
};
|
||||
elements?: SerializedData[];
|
||||
__internal: {
|
||||
__internal?: {
|
||||
save: (objectState: ObjectState) => ObjectState;
|
||||
delete: (frame: number, force: boolean) => boolean;
|
||||
};
|
||||
|
||||
@@ -33,7 +33,7 @@ export default class Project {
|
||||
public annotations: {
|
||||
exportDataset: CallableFunction;
|
||||
importDataset: CallableFunction;
|
||||
}
|
||||
};
|
||||
|
||||
constructor(initialData: SerializedProject & { labels?: SerializedLabel[] }) {
|
||||
const data = {
|
||||
|
||||
@@ -21,7 +21,6 @@ import { Storage } from './storage';
|
||||
import { RQStatus, StorageLocation, WebhookSourceType } from './enums';
|
||||
import { isEmail, isResourceURL } from './common';
|
||||
import config from './config';
|
||||
import DownloadWorker from './download.worker';
|
||||
import { ServerError } from './exceptions';
|
||||
import { SerializedQualityConflictData } from './quality-conflict';
|
||||
|
||||
@@ -192,8 +191,8 @@ function prepareData(details) {
|
||||
}
|
||||
|
||||
class WorkerWrappedAxios {
|
||||
constructor(requestInterseptor) {
|
||||
const worker = new DownloadWorker(requestInterseptor);
|
||||
constructor() {
|
||||
const worker = new Worker(new URL('./download.worker', import.meta.url));
|
||||
const requests = {};
|
||||
let requestId = 0;
|
||||
|
||||
|
||||
@@ -5,7 +5,8 @@
|
||||
import {
|
||||
ChunkType,
|
||||
DimensionType, JobStage, JobState, JobType, ProjectStatus,
|
||||
ShareFileType, TaskMode, TaskStatus, StorageLocation,
|
||||
ShapeType, StorageLocation,
|
||||
ShareFileType, Source, TaskMode, TaskStatus,
|
||||
} from 'enums';
|
||||
|
||||
export interface SerializedAnnotationImporter {
|
||||
@@ -239,3 +240,66 @@ export interface SerializedQualitySettingsData {
|
||||
panoptic_comparison?: boolean;
|
||||
compare_attributes?: boolean;
|
||||
}
|
||||
|
||||
export interface SerializedShape {
|
||||
id?: number;
|
||||
clientID?: number;
|
||||
label_id: number;
|
||||
group: number;
|
||||
frame: number;
|
||||
source: Source;
|
||||
attributes: { spec_id: number; value: string }[];
|
||||
elements: {
|
||||
id?: number;
|
||||
attributes: SerializedTrack['attributes'];
|
||||
label_id: number;
|
||||
occluded: boolean;
|
||||
outside: boolean;
|
||||
points: number[];
|
||||
type: ShapeType;
|
||||
}[];
|
||||
occluded: boolean;
|
||||
outside?: boolean; // only for skeleton elements
|
||||
points?: number[];
|
||||
rotation: number;
|
||||
z_order: number;
|
||||
type: ShapeType;
|
||||
}
|
||||
|
||||
export interface SerializedTrack {
|
||||
id?: number;
|
||||
clientID?: number;
|
||||
label_id: number;
|
||||
group: number;
|
||||
frame: number;
|
||||
source: Source;
|
||||
attributes: { spec_id: number; value: string }[];
|
||||
shapes: {
|
||||
attributes: SerializedTrack['attributes'];
|
||||
id?: number;
|
||||
points?: number[];
|
||||
frame: number;
|
||||
occluded: boolean;
|
||||
outside: boolean;
|
||||
rotation: number;
|
||||
type: ShapeType;
|
||||
z_order: number;
|
||||
}[];
|
||||
elements?: SerializedTrack[];
|
||||
}
|
||||
|
||||
export interface SerializedTag {
|
||||
id?: number;
|
||||
clientID?: number;
|
||||
label_id: number;
|
||||
frame: number;
|
||||
group: number;
|
||||
source: Source;
|
||||
attributes: { spec_id: number; value: string }[];
|
||||
}
|
||||
|
||||
export interface SerializedCollection {
|
||||
tags: SerializedTag[],
|
||||
shapes: SerializedShape[],
|
||||
tracks: SerializedTrack[],
|
||||
}
|
||||
|
||||
@@ -26,38 +26,30 @@ import { Label } from './labels';
|
||||
import { SerializedLabel } from './server-response-types';
|
||||
import { checkObjectType } from './common';
|
||||
import {
|
||||
getAnnotations, putAnnotations, saveAnnotations,
|
||||
hasUnsavedChanges, searchAnnotations, searchEmptyFrame,
|
||||
mergeAnnotations, splitAnnotations, groupAnnotations,
|
||||
joinAnnotations, sliceAnnotations, clearAnnotations, selectObject,
|
||||
annotationsStatistics, importCollection, exportCollection,
|
||||
importDataset, exportDataset, undoActions, redoActions,
|
||||
freezeHistory, clearActions, getActions,
|
||||
clearCache, getHistory,
|
||||
getCollection, getSaver, clearAnnotations, getAnnotations,
|
||||
importDataset, exportDataset, clearCache, getHistory,
|
||||
} from './annotations';
|
||||
import AnnotationGuide from './guide';
|
||||
|
||||
// must be called with task/job context
|
||||
async function deleteFrameWrapper(jobID, frame) {
|
||||
const history = getHistory(this);
|
||||
const redo = async () => {
|
||||
async function deleteFrameWrapper(jobID, frame): Promise<void> {
|
||||
const redo = async (): Promise<void> => {
|
||||
deleteFrame(jobID, frame);
|
||||
};
|
||||
|
||||
await redo();
|
||||
history.do(HistoryActions.REMOVED_FRAME, async () => {
|
||||
getHistory(this).do(HistoryActions.REMOVED_FRAME, async () => {
|
||||
restoreFrame(jobID, frame);
|
||||
}, redo, [], frame);
|
||||
}
|
||||
|
||||
async function restoreFrameWrapper(jobID, frame) {
|
||||
const history = getHistory(this);
|
||||
const redo = async () => {
|
||||
async function restoreFrameWrapper(jobID, frame): Promise<void> {
|
||||
const redo = async (): Promise<void> => {
|
||||
restoreFrame(jobID, frame);
|
||||
};
|
||||
|
||||
await redo();
|
||||
history.do(HistoryActions.RESTORED_FRAME, async () => {
|
||||
getHistory(this).do(HistoryActions.RESTORED_FRAME, async () => {
|
||||
deleteFrame(jobID, frame);
|
||||
}, redo, [], frame);
|
||||
}
|
||||
@@ -257,8 +249,7 @@ export function implementJob(Job) {
|
||||
throw new ArgumentError('The stop frame is out of the job');
|
||||
}
|
||||
|
||||
const result = searchAnnotations(this, filters, frameFrom, frameTo);
|
||||
return result;
|
||||
return getCollection(this).search(filters, frameFrom, frameTo);
|
||||
};
|
||||
|
||||
Job.prototype.annotations.searchEmpty.implementation = function (frameFrom, frameTo) {
|
||||
@@ -274,43 +265,35 @@ export function implementJob(Job) {
|
||||
throw new ArgumentError('The stop frame is out of the job');
|
||||
}
|
||||
|
||||
const result = searchEmptyFrame(this, frameFrom, frameTo);
|
||||
return result;
|
||||
return getCollection(this).searchEmpty(frameFrom, frameTo);
|
||||
};
|
||||
|
||||
Job.prototype.annotations.save.implementation = async function (onUpdate) {
|
||||
const result = await saveAnnotations(this, onUpdate);
|
||||
return result;
|
||||
return getSaver(this).save(onUpdate);
|
||||
};
|
||||
|
||||
Job.prototype.annotations.merge.implementation = async function (objectStates) {
|
||||
const result = await mergeAnnotations(this, objectStates);
|
||||
return result;
|
||||
return getCollection(this).merge(objectStates);
|
||||
};
|
||||
|
||||
Job.prototype.annotations.split.implementation = async function (objectState, frame) {
|
||||
const result = await splitAnnotations(this, objectState, frame);
|
||||
return result;
|
||||
return getCollection(this).split(objectState, frame);
|
||||
};
|
||||
|
||||
Job.prototype.annotations.group.implementation = async function (objectStates, reset) {
|
||||
const result = await groupAnnotations(this, objectStates, reset);
|
||||
return result;
|
||||
return getCollection(this).group(objectStates, reset);
|
||||
};
|
||||
|
||||
Job.prototype.annotations.join.implementation = async function (objectStates, points) {
|
||||
const result = await joinAnnotations(this, objectStates, points);
|
||||
return result;
|
||||
return getCollection(this).join(objectStates, points);
|
||||
};
|
||||
|
||||
Job.prototype.annotations.slice.implementation = async function (objectSTate, results) {
|
||||
const result = await sliceAnnotations(this, objectSTate, results);
|
||||
return result;
|
||||
Job.prototype.annotations.slice.implementation = async function (objectState, results) {
|
||||
return getCollection(this).slice(objectState, results);
|
||||
};
|
||||
|
||||
Job.prototype.annotations.hasUnsavedChanges.implementation = function () {
|
||||
const result = hasUnsavedChanges(this);
|
||||
return result;
|
||||
return getSaver(this).hasUnsavedChanges();
|
||||
};
|
||||
|
||||
Job.prototype.annotations.clear.implementation = async function (
|
||||
@@ -320,19 +303,16 @@ export function implementJob(Job) {
|
||||
return result;
|
||||
};
|
||||
|
||||
Job.prototype.annotations.select.implementation = function (frame, x, y) {
|
||||
const result = selectObject(this, frame, x, y);
|
||||
return result;
|
||||
Job.prototype.annotations.select.implementation = function (objectStates, x, y) {
|
||||
return getCollection(this).select(objectStates, x, y);
|
||||
};
|
||||
|
||||
Job.prototype.annotations.statistics.implementation = function () {
|
||||
const result = annotationsStatistics(this);
|
||||
return result;
|
||||
return getCollection(this).statistics({ jobID: this.id });
|
||||
};
|
||||
|
||||
Job.prototype.annotations.put.implementation = function (objectStates) {
|
||||
const result = putAnnotations(this, objectStates);
|
||||
return result;
|
||||
return getCollection(this).put(objectStates);
|
||||
};
|
||||
|
||||
Job.prototype.annotations.upload.implementation = async function (
|
||||
@@ -347,13 +327,11 @@ export function implementJob(Job) {
|
||||
};
|
||||
|
||||
Job.prototype.annotations.import.implementation = function (data) {
|
||||
const result = importCollection(this, data);
|
||||
return result;
|
||||
return getCollection(this).import(data);
|
||||
};
|
||||
|
||||
Job.prototype.annotations.export.implementation = function () {
|
||||
const result = exportCollection(this);
|
||||
return result;
|
||||
return getCollection(this).export();
|
||||
};
|
||||
|
||||
Job.prototype.annotations.exportDataset.implementation = async function (
|
||||
@@ -368,28 +346,23 @@ export function implementJob(Job) {
|
||||
};
|
||||
|
||||
Job.prototype.actions.undo.implementation = async function (count) {
|
||||
const result = await undoActions(this, count);
|
||||
return result;
|
||||
return getHistory(this).undo(count);
|
||||
};
|
||||
|
||||
Job.prototype.actions.redo.implementation = async function (count) {
|
||||
const result = await redoActions(this, count);
|
||||
return result;
|
||||
return getHistory(this).redo(count);
|
||||
};
|
||||
|
||||
Job.prototype.actions.freeze.implementation = function (frozen) {
|
||||
const result = freezeHistory(this, frozen);
|
||||
return result;
|
||||
return getHistory(this).freeze(frozen);
|
||||
};
|
||||
|
||||
Job.prototype.actions.clear.implementation = function () {
|
||||
const result = clearActions(this);
|
||||
return result;
|
||||
return getHistory(this).clear();
|
||||
};
|
||||
|
||||
Job.prototype.actions.get.implementation = function () {
|
||||
const result = getActions(this);
|
||||
return result;
|
||||
return getHistory(this).get();
|
||||
};
|
||||
|
||||
Job.prototype.logger.log.implementation = async function (logType, payload, wait) {
|
||||
@@ -714,7 +687,7 @@ export function implementTask(Task) {
|
||||
throw new ArgumentError(`Frame ${frame} does not exist in the task`);
|
||||
}
|
||||
|
||||
const result = await getAnnotations(this, frame, allTracks, filters);
|
||||
const result = await getAnnotations(this, frame, allTracks, filters, null);
|
||||
const deletedFrames = await getDeletedFrames('task', this.id);
|
||||
if (frame in deletedFrames) {
|
||||
return [];
|
||||
@@ -740,8 +713,7 @@ export function implementTask(Task) {
|
||||
throw new ArgumentError('The stop frame is out of the task');
|
||||
}
|
||||
|
||||
const result = searchAnnotations(this, filters, frameFrom, frameTo);
|
||||
return result;
|
||||
return getCollection(this).search(filters, frameFrom, frameTo);
|
||||
};
|
||||
|
||||
Task.prototype.annotations.searchEmpty.implementation = function (frameFrom, frameTo) {
|
||||
@@ -757,63 +729,54 @@ export function implementTask(Task) {
|
||||
throw new ArgumentError('The stop frame is out of the task');
|
||||
}
|
||||
|
||||
const result = searchEmptyFrame(this, frameFrom, frameTo);
|
||||
return result;
|
||||
return getCollection(this).searchEmpty(frameFrom, frameTo);
|
||||
};
|
||||
|
||||
Task.prototype.annotations.save.implementation = async function (onUpdate) {
|
||||
const result = await saveAnnotations(this, onUpdate);
|
||||
return result;
|
||||
return getSaver(this).save(onUpdate);
|
||||
};
|
||||
|
||||
Task.prototype.annotations.merge.implementation = async function (objectStates) {
|
||||
const result = await mergeAnnotations(this, objectStates);
|
||||
return result;
|
||||
return getCollection(this).merge(objectStates);
|
||||
};
|
||||
|
||||
Task.prototype.annotations.split.implementation = async function (objectState, frame) {
|
||||
const result = await splitAnnotations(this, objectState, frame);
|
||||
return result;
|
||||
return getCollection(this).split(objectState, frame);
|
||||
};
|
||||
|
||||
Task.prototype.annotations.group.implementation = async function (objectStates, reset) {
|
||||
const result = await groupAnnotations(this, objectStates, reset);
|
||||
return result;
|
||||
return getCollection(this).group(objectStates, reset);
|
||||
};
|
||||
|
||||
Task.prototype.annotations.join.implementation = async function (objectStates, points) {
|
||||
const result = await joinAnnotations(this, objectStates, points);
|
||||
return result;
|
||||
return getCollection(this).join(objectStates, points);
|
||||
};
|
||||
|
||||
Task.prototype.annotations.slice.implementation = async function (objectSTate, results) {
|
||||
const result = await sliceAnnotations(this, objectSTate, results);
|
||||
return result;
|
||||
Task.prototype.annotations.slice.implementation = async function (objectState, results) {
|
||||
return getCollection(this).slice(objectState, results);
|
||||
};
|
||||
|
||||
Task.prototype.annotations.hasUnsavedChanges.implementation = function () {
|
||||
const result = hasUnsavedChanges(this);
|
||||
return getSaver(this).hasUnsavedChanges();
|
||||
};
|
||||
|
||||
Task.prototype.annotations.clear.implementation = async function (
|
||||
reload, startframe, endframe, delTrackKeyframesOnly,
|
||||
) {
|
||||
const result = await clearAnnotations(this, reload, startframe, endframe, delTrackKeyframesOnly);
|
||||
return result;
|
||||
};
|
||||
|
||||
Task.prototype.annotations.clear.implementation = async function (reload) {
|
||||
const result = await clearAnnotations(this, reload);
|
||||
return result;
|
||||
};
|
||||
|
||||
Task.prototype.annotations.select.implementation = function (frame, x, y) {
|
||||
const result = selectObject(this, frame, x, y);
|
||||
return result;
|
||||
Task.prototype.annotations.select.implementation = function (objectStates, x, y) {
|
||||
return getCollection(this).select(objectStates, x, y);
|
||||
};
|
||||
|
||||
Task.prototype.annotations.statistics.implementation = function () {
|
||||
const result = annotationsStatistics(this);
|
||||
return result;
|
||||
return getCollection(this).statistics({});
|
||||
};
|
||||
|
||||
Task.prototype.annotations.put.implementation = function (objectStates) {
|
||||
const result = putAnnotations(this, objectStates);
|
||||
return result;
|
||||
return getCollection(this).put(objectStates);
|
||||
};
|
||||
|
||||
Task.prototype.annotations.upload.implementation = async function (
|
||||
@@ -828,13 +791,11 @@ export function implementTask(Task) {
|
||||
};
|
||||
|
||||
Task.prototype.annotations.import.implementation = function (data) {
|
||||
const result = importCollection(this, data);
|
||||
return result;
|
||||
return getCollection(this).import(data);
|
||||
};
|
||||
|
||||
Task.prototype.annotations.export.implementation = function () {
|
||||
const result = exportCollection(this);
|
||||
return result;
|
||||
return getCollection(this).export();
|
||||
};
|
||||
|
||||
Task.prototype.annotations.exportDataset.implementation = async function (
|
||||
@@ -848,29 +809,24 @@ export function implementTask(Task) {
|
||||
return result;
|
||||
};
|
||||
|
||||
Task.prototype.actions.undo.implementation = function (count) {
|
||||
const result = undoActions(this, count);
|
||||
return result;
|
||||
Task.prototype.actions.undo.implementation = async function (count) {
|
||||
return getHistory(this).undo(count);
|
||||
};
|
||||
|
||||
Task.prototype.actions.redo.implementation = function (count) {
|
||||
const result = redoActions(this, count);
|
||||
return result;
|
||||
Task.prototype.actions.redo.implementation = async function (count) {
|
||||
return getHistory(this).redo(count);
|
||||
};
|
||||
|
||||
Task.prototype.actions.freeze.implementation = function (frozen) {
|
||||
const result = freezeHistory(this, frozen);
|
||||
return result;
|
||||
return getHistory(this).freeze(frozen);
|
||||
};
|
||||
|
||||
Task.prototype.actions.clear.implementation = function () {
|
||||
const result = clearActions(this);
|
||||
return result;
|
||||
return getHistory(this).clear();
|
||||
};
|
||||
|
||||
Task.prototype.actions.get.implementation = function () {
|
||||
const result = getActions(this);
|
||||
return result;
|
||||
return getHistory(this).get();
|
||||
};
|
||||
|
||||
Task.prototype.logger.log.implementation = async function (logType, payload, wait) {
|
||||
|
||||
+81
-191
@@ -11,7 +11,7 @@ import {
|
||||
import { Storage } from './storage';
|
||||
|
||||
import PluginRegistry from './plugins';
|
||||
import { ArgumentError } from './exceptions';
|
||||
import { ArgumentError, ScriptingError } from './exceptions';
|
||||
import { Label } from './labels';
|
||||
import User from './user';
|
||||
import { FieldUpdateTrigger } from './common';
|
||||
@@ -308,58 +308,10 @@ function buildDuplicatedAPI(prototype) {
|
||||
},
|
||||
writable: true,
|
||||
}),
|
||||
events: Object.freeze({
|
||||
value: {
|
||||
async subscribe(evType, callback) {
|
||||
const result = await PluginRegistry.apiWrapper.call(
|
||||
this,
|
||||
prototype.events.subscribe,
|
||||
evType,
|
||||
callback,
|
||||
);
|
||||
return result;
|
||||
},
|
||||
async unsubscribe(evType, callback = null) {
|
||||
const result = await PluginRegistry.apiWrapper.call(
|
||||
this,
|
||||
prototype.events.unsubscribe,
|
||||
evType,
|
||||
callback,
|
||||
);
|
||||
return result;
|
||||
},
|
||||
},
|
||||
writable: true,
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
export class Session {}
|
||||
|
||||
export class Job extends Session {
|
||||
public assignee: User | null;
|
||||
public stage: JobStage;
|
||||
public state: JobState;
|
||||
public readonly id: number;
|
||||
public readonly startFrame: number;
|
||||
public readonly stopFrame: number;
|
||||
public readonly frameCount: number;
|
||||
public readonly projectId: number | null;
|
||||
public readonly guideId: number | null;
|
||||
public readonly taskId: number;
|
||||
public readonly dimension: DimensionType;
|
||||
public readonly dataChunkType: ChunkType;
|
||||
public readonly dataChunkSize: number;
|
||||
public readonly bugTracker: string | null;
|
||||
public readonly mode: TaskMode;
|
||||
public readonly labels: Label[];
|
||||
public readonly type: JobType;
|
||||
public readonly frameSelectionMethod: JobType;
|
||||
public readonly createdDate: string;
|
||||
public readonly updatedDate: string;
|
||||
public readonly sourceStorage: Storage;
|
||||
public readonly targetStorage: Storage;
|
||||
|
||||
export class Session {
|
||||
public annotations: {
|
||||
get: CallableFunction;
|
||||
put: CallableFunction;
|
||||
@@ -405,6 +357,85 @@ export class Job extends Session {
|
||||
log: CallableFunction;
|
||||
};
|
||||
|
||||
public constructor() {
|
||||
if (this.constructor === Session) {
|
||||
throw new ScriptingError('Can not initiate an instance of abstract class');
|
||||
}
|
||||
|
||||
// When we call a function, for example: task.annotations.get()
|
||||
// In the method get we lose the task context
|
||||
// So, we need return it
|
||||
this.annotations = {
|
||||
get: Object.getPrototypeOf(this).annotations.get.bind(this),
|
||||
put: Object.getPrototypeOf(this).annotations.put.bind(this),
|
||||
save: Object.getPrototypeOf(this).annotations.save.bind(this),
|
||||
merge: Object.getPrototypeOf(this).annotations.merge.bind(this),
|
||||
split: Object.getPrototypeOf(this).annotations.split.bind(this),
|
||||
group: Object.getPrototypeOf(this).annotations.group.bind(this),
|
||||
join: Object.getPrototypeOf(this).annotations.join.bind(this),
|
||||
slice: Object.getPrototypeOf(this).annotations.slice.bind(this),
|
||||
clear: Object.getPrototypeOf(this).annotations.clear.bind(this),
|
||||
search: Object.getPrototypeOf(this).annotations.search.bind(this),
|
||||
searchEmpty: Object.getPrototypeOf(this).annotations.searchEmpty.bind(this),
|
||||
upload: Object.getPrototypeOf(this).annotations.upload.bind(this),
|
||||
select: Object.getPrototypeOf(this).annotations.select.bind(this),
|
||||
import: Object.getPrototypeOf(this).annotations.import.bind(this),
|
||||
export: Object.getPrototypeOf(this).annotations.export.bind(this),
|
||||
statistics: Object.getPrototypeOf(this).annotations.statistics.bind(this),
|
||||
hasUnsavedChanges: Object.getPrototypeOf(this).annotations.hasUnsavedChanges.bind(this),
|
||||
exportDataset: Object.getPrototypeOf(this).annotations.exportDataset.bind(this),
|
||||
};
|
||||
|
||||
this.actions = {
|
||||
undo: Object.getPrototypeOf(this).actions.undo.bind(this),
|
||||
redo: Object.getPrototypeOf(this).actions.redo.bind(this),
|
||||
freeze: Object.getPrototypeOf(this).actions.freeze.bind(this),
|
||||
clear: Object.getPrototypeOf(this).actions.clear.bind(this),
|
||||
get: Object.getPrototypeOf(this).actions.get.bind(this),
|
||||
};
|
||||
|
||||
this.frames = {
|
||||
get: Object.getPrototypeOf(this).frames.get.bind(this),
|
||||
delete: Object.getPrototypeOf(this).frames.delete.bind(this),
|
||||
restore: Object.getPrototypeOf(this).frames.restore.bind(this),
|
||||
save: Object.getPrototypeOf(this).frames.save.bind(this),
|
||||
cachedChunks: Object.getPrototypeOf(this).frames.cachedChunks.bind(this),
|
||||
preview: Object.getPrototypeOf(this).frames.preview.bind(this),
|
||||
search: Object.getPrototypeOf(this).frames.search.bind(this),
|
||||
contextImage: Object.getPrototypeOf(this).frames.contextImage.bind(this),
|
||||
chunk: Object.getPrototypeOf(this).frames.chunk.bind(this),
|
||||
};
|
||||
|
||||
this.logger = {
|
||||
log: Object.getPrototypeOf(this).logger.log.bind(this),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export class Job extends Session {
|
||||
public assignee: User | null;
|
||||
public stage: JobStage;
|
||||
public state: JobState;
|
||||
public readonly id: number;
|
||||
public readonly startFrame: number;
|
||||
public readonly stopFrame: number;
|
||||
public readonly frameCount: number;
|
||||
public readonly projectId: number | null;
|
||||
public readonly guideId: number | null;
|
||||
public readonly taskId: number;
|
||||
public readonly dimension: DimensionType;
|
||||
public readonly dataChunkType: ChunkType;
|
||||
public readonly dataChunkSize: number;
|
||||
public readonly bugTracker: string | null;
|
||||
public readonly mode: TaskMode;
|
||||
public readonly labels: Label[];
|
||||
public readonly type: JobType;
|
||||
public readonly frameSelectionMethod: JobType;
|
||||
public readonly createdDate: string;
|
||||
public readonly updatedDate: string;
|
||||
public readonly sourceStorage: Storage;
|
||||
public readonly targetStorage: Storage;
|
||||
|
||||
constructor(initialData: Readonly<SerializedJob>) {
|
||||
super();
|
||||
const data = {
|
||||
@@ -595,54 +626,6 @@ export class Job extends Session {
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
// When we call a function, for example: task.annotations.get()
|
||||
// In the method get we lose the task context
|
||||
// So, we need return it
|
||||
this.annotations = {
|
||||
get: Object.getPrototypeOf(this).annotations.get.bind(this),
|
||||
put: Object.getPrototypeOf(this).annotations.put.bind(this),
|
||||
save: Object.getPrototypeOf(this).annotations.save.bind(this),
|
||||
merge: Object.getPrototypeOf(this).annotations.merge.bind(this),
|
||||
split: Object.getPrototypeOf(this).annotations.split.bind(this),
|
||||
group: Object.getPrototypeOf(this).annotations.group.bind(this),
|
||||
join: Object.getPrototypeOf(this).annotations.join.bind(this),
|
||||
slice: Object.getPrototypeOf(this).annotations.slice.bind(this),
|
||||
clear: Object.getPrototypeOf(this).annotations.clear.bind(this),
|
||||
search: Object.getPrototypeOf(this).annotations.search.bind(this),
|
||||
searchEmpty: Object.getPrototypeOf(this).annotations.searchEmpty.bind(this),
|
||||
upload: Object.getPrototypeOf(this).annotations.upload.bind(this),
|
||||
select: Object.getPrototypeOf(this).annotations.select.bind(this),
|
||||
import: Object.getPrototypeOf(this).annotations.import.bind(this),
|
||||
export: Object.getPrototypeOf(this).annotations.export.bind(this),
|
||||
statistics: Object.getPrototypeOf(this).annotations.statistics.bind(this),
|
||||
hasUnsavedChanges: Object.getPrototypeOf(this).annotations.hasUnsavedChanges.bind(this),
|
||||
exportDataset: Object.getPrototypeOf(this).annotations.exportDataset.bind(this),
|
||||
};
|
||||
|
||||
this.actions = {
|
||||
undo: Object.getPrototypeOf(this).actions.undo.bind(this),
|
||||
redo: Object.getPrototypeOf(this).actions.redo.bind(this),
|
||||
freeze: Object.getPrototypeOf(this).actions.freeze.bind(this),
|
||||
clear: Object.getPrototypeOf(this).actions.clear.bind(this),
|
||||
get: Object.getPrototypeOf(this).actions.get.bind(this),
|
||||
};
|
||||
|
||||
this.frames = {
|
||||
get: Object.getPrototypeOf(this).frames.get.bind(this),
|
||||
delete: Object.getPrototypeOf(this).frames.delete.bind(this),
|
||||
restore: Object.getPrototypeOf(this).frames.restore.bind(this),
|
||||
save: Object.getPrototypeOf(this).frames.save.bind(this),
|
||||
cachedChunks: Object.getPrototypeOf(this).frames.cachedChunks.bind(this),
|
||||
preview: Object.getPrototypeOf(this).frames.preview.bind(this),
|
||||
search: Object.getPrototypeOf(this).frames.search.bind(this),
|
||||
contextImage: Object.getPrototypeOf(this).frames.contextImage.bind(this),
|
||||
chunk: Object.getPrototypeOf(this).frames.chunk.bind(this),
|
||||
};
|
||||
|
||||
this.logger = {
|
||||
log: Object.getPrototypeOf(this).logger.log.bind(this),
|
||||
};
|
||||
}
|
||||
|
||||
async save(additionalData = {}) {
|
||||
@@ -712,51 +695,6 @@ export class Task extends Session {
|
||||
public readonly cloudStorageID: number;
|
||||
public readonly sortingMethod: string;
|
||||
|
||||
public annotations: {
|
||||
get: CallableFunction;
|
||||
put: CallableFunction;
|
||||
save: CallableFunction;
|
||||
merge: CallableFunction;
|
||||
split: CallableFunction;
|
||||
group: CallableFunction;
|
||||
join: CallableFunction;
|
||||
slice: CallableFunction;
|
||||
clear: CallableFunction;
|
||||
search: CallableFunction;
|
||||
searchEmpty: CallableFunction;
|
||||
upload: CallableFunction;
|
||||
select: CallableFunction;
|
||||
import: CallableFunction;
|
||||
export: CallableFunction;
|
||||
statistics: CallableFunction;
|
||||
hasUnsavedChanges: CallableFunction;
|
||||
exportDataset: CallableFunction;
|
||||
};
|
||||
|
||||
public actions: {
|
||||
undo: CallableFunction;
|
||||
redo: CallableFunction;
|
||||
freeze: CallableFunction;
|
||||
clear: CallableFunction;
|
||||
get: CallableFunction;
|
||||
};
|
||||
|
||||
public frames: {
|
||||
get: CallableFunction;
|
||||
delete: CallableFunction;
|
||||
restore: CallableFunction;
|
||||
save: CallableFunction;
|
||||
cachedChunks: CallableFunction;
|
||||
preview: CallableFunction;
|
||||
contextImage: CallableFunction;
|
||||
search: CallableFunction;
|
||||
chunk: CallableFunction;
|
||||
};
|
||||
|
||||
public logger: {
|
||||
log: CallableFunction;
|
||||
};
|
||||
|
||||
constructor(initialData: SerializedTask) {
|
||||
super();
|
||||
|
||||
@@ -1134,54 +1072,6 @@ export class Task extends Session {
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
// When we call a function, for example: task.annotations.get()
|
||||
// In the method get we lose the task context
|
||||
// So, we need return it
|
||||
this.annotations = {
|
||||
get: Object.getPrototypeOf(this).annotations.get.bind(this),
|
||||
put: Object.getPrototypeOf(this).annotations.put.bind(this),
|
||||
save: Object.getPrototypeOf(this).annotations.save.bind(this),
|
||||
merge: Object.getPrototypeOf(this).annotations.merge.bind(this),
|
||||
split: Object.getPrototypeOf(this).annotations.split.bind(this),
|
||||
group: Object.getPrototypeOf(this).annotations.group.bind(this),
|
||||
join: Object.getPrototypeOf(this).annotations.join.bind(this),
|
||||
slice: Object.getPrototypeOf(this).annotations.slice.bind(this),
|
||||
clear: Object.getPrototypeOf(this).annotations.clear.bind(this),
|
||||
search: Object.getPrototypeOf(this).annotations.search.bind(this),
|
||||
searchEmpty: Object.getPrototypeOf(this).annotations.searchEmpty.bind(this),
|
||||
upload: Object.getPrototypeOf(this).annotations.upload.bind(this),
|
||||
select: Object.getPrototypeOf(this).annotations.select.bind(this),
|
||||
import: Object.getPrototypeOf(this).annotations.import.bind(this),
|
||||
export: Object.getPrototypeOf(this).annotations.export.bind(this),
|
||||
statistics: Object.getPrototypeOf(this).annotations.statistics.bind(this),
|
||||
hasUnsavedChanges: Object.getPrototypeOf(this).annotations.hasUnsavedChanges.bind(this),
|
||||
exportDataset: Object.getPrototypeOf(this).annotations.exportDataset.bind(this),
|
||||
};
|
||||
|
||||
this.actions = {
|
||||
undo: Object.getPrototypeOf(this).actions.undo.bind(this),
|
||||
redo: Object.getPrototypeOf(this).actions.redo.bind(this),
|
||||
freeze: Object.getPrototypeOf(this).actions.freeze.bind(this),
|
||||
clear: Object.getPrototypeOf(this).actions.clear.bind(this),
|
||||
get: Object.getPrototypeOf(this).actions.get.bind(this),
|
||||
};
|
||||
|
||||
this.frames = {
|
||||
get: Object.getPrototypeOf(this).frames.get.bind(this),
|
||||
delete: Object.getPrototypeOf(this).frames.delete.bind(this),
|
||||
restore: Object.getPrototypeOf(this).frames.restore.bind(this),
|
||||
save: Object.getPrototypeOf(this).frames.save.bind(this),
|
||||
cachedChunks: Object.getPrototypeOf(this).frames.cachedChunks.bind(this),
|
||||
preview: Object.getPrototypeOf(this).frames.preview.bind(this),
|
||||
contextImage: Object.getPrototypeOf(this).frames.contextImage.bind(this),
|
||||
search: Object.getPrototypeOf(this).frames.search.bind(this),
|
||||
chunk: Object.getPrototypeOf(this).frames.chunk.bind(this),
|
||||
};
|
||||
|
||||
this.logger = {
|
||||
log: Object.getPrototypeOf(this).logger.log.bind(this),
|
||||
};
|
||||
}
|
||||
|
||||
async close(): Promise<Task> {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
// Copyright (C) 2020-2022 Intel Corporation
|
||||
// Copyright (C) 2022 CVAT.ai Corp
|
||||
// Copyright (C) 2022 CVAT.ai Corporation
|
||||
// Copyright (C) 2022-2023 CVAT.ai Corporation
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
@@ -8,28 +7,27 @@
|
||||
jest.mock('../../src/server-proxy', () => {
|
||||
return {
|
||||
__esModule: true,
|
||||
default: require('../mocks/server-proxy.mock'),
|
||||
default: require('../mocks/server-proxy.mock.cjs'),
|
||||
};
|
||||
});
|
||||
|
||||
// Initialize api
|
||||
window.cvat = require('../../src/api').default;
|
||||
const cvat = require('../../src/api').default;
|
||||
const serverProxy = require('../../src/server-proxy').default;
|
||||
|
||||
// Test cases
|
||||
describe('Feature: get annotations', () => {
|
||||
test('get annotations from a task', async () => {
|
||||
const task = (await window.cvat.tasks.get({ id: 100 }))[0];
|
||||
const task = (await cvat.tasks.get({ id: 100 }))[0];
|
||||
const annotations = await task.annotations.get(0);
|
||||
expect(Array.isArray(annotations)).toBeTruthy();
|
||||
expect(annotations).toHaveLength(12);
|
||||
for (const state of annotations) {
|
||||
expect(state).toBeInstanceOf(window.cvat.classes.ObjectState);
|
||||
expect(state).toBeInstanceOf(cvat.classes.ObjectState);
|
||||
}
|
||||
});
|
||||
|
||||
test('get annotations from a job', async () => {
|
||||
const job = (await window.cvat.jobs.get({ jobID: 101 }))[0];
|
||||
const job = (await cvat.jobs.get({ jobID: 101 }))[0];
|
||||
const annotations0 = await job.annotations.get(0);
|
||||
const annotations10 = await job.annotations.get(10);
|
||||
expect(Array.isArray(annotations0)).toBeTruthy();
|
||||
@@ -37,32 +35,32 @@ describe('Feature: get annotations', () => {
|
||||
expect(annotations0).toHaveLength(2);
|
||||
expect(annotations10).toHaveLength(3);
|
||||
for (const state of annotations0.concat(annotations10)) {
|
||||
expect(state).toBeInstanceOf(window.cvat.classes.ObjectState);
|
||||
expect(state).toBeInstanceOf(cvat.classes.ObjectState);
|
||||
}
|
||||
});
|
||||
|
||||
test('get annotations for frame out of task', async () => {
|
||||
const task = (await window.cvat.tasks.get({ id: 100 }))[0];
|
||||
const task = (await cvat.tasks.get({ id: 100 }))[0];
|
||||
|
||||
// Out of task
|
||||
expect(task.annotations.get(500)).rejects.toThrow(window.cvat.exceptions.ArgumentError);
|
||||
expect(task.annotations.get(500)).rejects.toThrow(cvat.exceptions.ArgumentError);
|
||||
|
||||
// Out of task
|
||||
expect(task.annotations.get(-1)).rejects.toThrow(window.cvat.exceptions.ArgumentError);
|
||||
expect(task.annotations.get(-1)).rejects.toThrow(cvat.exceptions.ArgumentError);
|
||||
});
|
||||
|
||||
test('get annotations for frame out of job', async () => {
|
||||
const job = (await window.cvat.jobs.get({ jobID: 101 }))[0];
|
||||
const job = (await cvat.jobs.get({ jobID: 101 }))[0];
|
||||
|
||||
// Out of segment
|
||||
expect(job.annotations.get(500)).rejects.toThrow(window.cvat.exceptions.ArgumentError);
|
||||
expect(job.annotations.get(500)).rejects.toThrow(cvat.exceptions.ArgumentError);
|
||||
|
||||
// Out of segment
|
||||
expect(job.annotations.get(-1)).rejects.toThrow(window.cvat.exceptions.ArgumentError);
|
||||
expect(job.annotations.get(-1)).rejects.toThrow(cvat.exceptions.ArgumentError);
|
||||
});
|
||||
|
||||
test('get only ellipses', async () => {
|
||||
const job = (await window.cvat.jobs.get({ jobID: 101 }))[0];
|
||||
const job = (await cvat.jobs.get({ jobID: 101 }))[0];
|
||||
const annotations = await job.annotations.get(5, false, JSON.parse('[{"and":[{"==":[{"var":"shape"},"ellipse"]}]}]'));
|
||||
expect(Array.isArray(annotations)).toBeTruthy();
|
||||
expect(annotations).toHaveLength(1);
|
||||
@@ -70,7 +68,7 @@ describe('Feature: get annotations', () => {
|
||||
});
|
||||
|
||||
test('get skeletons with a filter', async () => {
|
||||
const job = (await window.cvat.jobs.get({ jobID: 40 }))[0];
|
||||
const job = (await cvat.jobs.get({ jobID: 40 }))[0];
|
||||
const annotations = await job.annotations.get(0, false, JSON.parse('[{"and":[{"==":[{"var":"shape"},"skeleton"]}]}]'));
|
||||
expect(Array.isArray(annotations)).toBeTruthy();
|
||||
expect(annotations).toHaveLength(2);
|
||||
@@ -94,7 +92,7 @@ describe('Feature: get annotations', () => {
|
||||
|
||||
describe('Feature: get interpolated annotations', () => {
|
||||
test('get interpolated box', async () => {
|
||||
const task = (await window.cvat.tasks.get({ id: 101 }))[0];
|
||||
const task = (await cvat.tasks.get({ id: 101 }))[0];
|
||||
let annotations = await task.annotations.get(5);
|
||||
expect(Array.isArray(annotations)).toBeTruthy();
|
||||
expect(annotations).toHaveLength(2);
|
||||
@@ -123,7 +121,7 @@ describe('Feature: get interpolated annotations', () => {
|
||||
});
|
||||
|
||||
test('get interpolated ellipse', async () => {
|
||||
const task = (await window.cvat.tasks.get({ id: 101 }))[0];
|
||||
const task = (await cvat.tasks.get({ id: 101 }))[0];
|
||||
const annotations = await task.annotations.get(5);
|
||||
expect(Array.isArray(annotations)).toBeTruthy();
|
||||
expect(annotations).toHaveLength(2);
|
||||
@@ -138,14 +136,14 @@ describe('Feature: get interpolated annotations', () => {
|
||||
|
||||
describe('Feature: put annotations', () => {
|
||||
test('put a shape to a task', async () => {
|
||||
const task = (await window.cvat.tasks.get({ id: 101 }))[0];
|
||||
const task = (await cvat.tasks.get({ id: 101 }))[0];
|
||||
let annotations = await task.annotations.get(1);
|
||||
const { length } = annotations;
|
||||
|
||||
const state = new window.cvat.classes.ObjectState({
|
||||
const state = new cvat.classes.ObjectState({
|
||||
frame: 1,
|
||||
objectType: window.cvat.enums.ObjectType.SHAPE,
|
||||
shapeType: window.cvat.enums.ShapeType.POLYGON,
|
||||
objectType: cvat.enums.ObjectType.SHAPE,
|
||||
shapeType: cvat.enums.ShapeType.POLYGON,
|
||||
points: [0, 0, 100, 0, 100, 50],
|
||||
occluded: true,
|
||||
label: task.labels[0],
|
||||
@@ -160,14 +158,14 @@ describe('Feature: put annotations', () => {
|
||||
});
|
||||
|
||||
test('put a shape to a job', async () => {
|
||||
const job = (await window.cvat.jobs.get({ jobID: 100 }))[0];
|
||||
const job = (await cvat.jobs.get({ jobID: 100 }))[0];
|
||||
let annotations = await job.annotations.get(5);
|
||||
const { length } = annotations;
|
||||
|
||||
const state = new window.cvat.classes.ObjectState({
|
||||
const state = new cvat.classes.ObjectState({
|
||||
frame: 5,
|
||||
objectType: window.cvat.enums.ObjectType.SHAPE,
|
||||
shapeType: window.cvat.enums.ShapeType.RECTANGLE,
|
||||
objectType: cvat.enums.ObjectType.SHAPE,
|
||||
shapeType: cvat.enums.ShapeType.RECTANGLE,
|
||||
points: [0, 0, 100, 100],
|
||||
occluded: false,
|
||||
label: job.labels[0],
|
||||
@@ -182,14 +180,14 @@ describe('Feature: put annotations', () => {
|
||||
});
|
||||
|
||||
test('put an ellipse shape to a job', async () => {
|
||||
const job = (await window.cvat.jobs.get({ jobID: 100 }))[0];
|
||||
const job = (await cvat.jobs.get({ jobID: 100 }))[0];
|
||||
let annotations = await job.annotations.get(5);
|
||||
const { length } = annotations;
|
||||
|
||||
const state = new window.cvat.classes.ObjectState({
|
||||
const state = new cvat.classes.ObjectState({
|
||||
frame: 5,
|
||||
objectType: window.cvat.enums.ObjectType.SHAPE,
|
||||
shapeType: window.cvat.enums.ShapeType.ELLIPSE,
|
||||
objectType: cvat.enums.ObjectType.SHAPE,
|
||||
shapeType: cvat.enums.ShapeType.ELLIPSE,
|
||||
points: [500, 500, 800, 100],
|
||||
occluded: true,
|
||||
label: job.labels[0],
|
||||
@@ -204,14 +202,14 @@ describe('Feature: put annotations', () => {
|
||||
});
|
||||
|
||||
test('put a track to a task', async () => {
|
||||
const task = (await window.cvat.tasks.get({ id: 101 }))[0];
|
||||
const task = (await cvat.tasks.get({ id: 101 }))[0];
|
||||
let annotations = await task.annotations.get(1);
|
||||
const { length } = annotations;
|
||||
|
||||
const state = new window.cvat.classes.ObjectState({
|
||||
const state = new cvat.classes.ObjectState({
|
||||
frame: 1,
|
||||
objectType: window.cvat.enums.ObjectType.TRACK,
|
||||
shapeType: window.cvat.enums.ShapeType.POLYGON,
|
||||
objectType: cvat.enums.ObjectType.TRACK,
|
||||
shapeType: cvat.enums.ShapeType.POLYGON,
|
||||
points: [0, 0, 100, 0, 100, 50],
|
||||
occluded: true,
|
||||
label: task.labels[0],
|
||||
@@ -226,14 +224,14 @@ describe('Feature: put annotations', () => {
|
||||
});
|
||||
|
||||
test('put a track to a job', async () => {
|
||||
const job = (await window.cvat.jobs.get({ jobID: 100 }))[0];
|
||||
const job = (await cvat.jobs.get({ jobID: 100 }))[0];
|
||||
let annotations = await job.annotations.get(5);
|
||||
const { length } = annotations;
|
||||
|
||||
const state = new window.cvat.classes.ObjectState({
|
||||
const state = new cvat.classes.ObjectState({
|
||||
frame: 5,
|
||||
objectType: window.cvat.enums.ObjectType.TRACK,
|
||||
shapeType: window.cvat.enums.ShapeType.RECTANGLE,
|
||||
objectType: cvat.enums.ObjectType.TRACK,
|
||||
shapeType: cvat.enums.ShapeType.RECTANGLE,
|
||||
points: [0, 0, 100, 100],
|
||||
occluded: false,
|
||||
label: job.labels[0],
|
||||
@@ -248,25 +246,25 @@ describe('Feature: put annotations', () => {
|
||||
});
|
||||
|
||||
test('put object without objectType to a task', async () => {
|
||||
const task = (await window.cvat.tasks.get({ id: 101 }))[0];
|
||||
const task = (await cvat.tasks.get({ id: 101 }))[0];
|
||||
await task.annotations.clear(true);
|
||||
expect(() => new window.cvat.classes.ObjectState({
|
||||
expect(() => new cvat.classes.ObjectState({
|
||||
frame: 1,
|
||||
shapeType: window.cvat.enums.ShapeType.POLYGON,
|
||||
shapeType: cvat.enums.ShapeType.POLYGON,
|
||||
points: [0, 0, 100, 0, 100, 50],
|
||||
occluded: true,
|
||||
label: task.labels[0],
|
||||
zOrder: 0,
|
||||
})).toThrow(window.cvat.exceptions.ArgumentError);
|
||||
})).toThrow(cvat.exceptions.ArgumentError);
|
||||
});
|
||||
|
||||
test('put shape with bad attributes to a task', async () => {
|
||||
const task = (await window.cvat.tasks.get({ id: 101 }))[0];
|
||||
const task = (await cvat.tasks.get({ id: 101 }))[0];
|
||||
await task.annotations.clear(true);
|
||||
const state = new window.cvat.classes.ObjectState({
|
||||
const state = new cvat.classes.ObjectState({
|
||||
frame: 1,
|
||||
objectType: window.cvat.enums.ObjectType.SHAPE,
|
||||
shapeType: window.cvat.enums.ShapeType.POLYGON,
|
||||
objectType: cvat.enums.ObjectType.SHAPE,
|
||||
shapeType: cvat.enums.ShapeType.POLYGON,
|
||||
points: [0, 0, 100, 0, 100, 50],
|
||||
attributes: { 'bad key': 55 },
|
||||
occluded: true,
|
||||
@@ -274,16 +272,16 @@ describe('Feature: put annotations', () => {
|
||||
zOrder: 0,
|
||||
});
|
||||
|
||||
expect(task.annotations.put([state])).rejects.toThrow(window.cvat.exceptions.ArgumentError);
|
||||
expect(task.annotations.put([state])).rejects.toThrow(cvat.exceptions.ArgumentError);
|
||||
});
|
||||
|
||||
test('put shape with bad zOrder to a task', async () => {
|
||||
const task = (await window.cvat.tasks.get({ id: 101 }))[0];
|
||||
const task = (await cvat.tasks.get({ id: 101 }))[0];
|
||||
await task.annotations.clear(true);
|
||||
const state = new window.cvat.classes.ObjectState({
|
||||
const state = new cvat.classes.ObjectState({
|
||||
frame: 1,
|
||||
objectType: window.cvat.enums.ObjectType.SHAPE,
|
||||
shapeType: window.cvat.enums.ShapeType.POLYGON,
|
||||
objectType: cvat.enums.ObjectType.SHAPE,
|
||||
shapeType: cvat.enums.ShapeType.POLYGON,
|
||||
points: [0, 0, 100, 0, 100, 50],
|
||||
attributes: { 'bad key': 55 },
|
||||
occluded: true,
|
||||
@@ -291,12 +289,12 @@ describe('Feature: put annotations', () => {
|
||||
zOrder: 'bad value',
|
||||
});
|
||||
|
||||
expect(task.annotations.put([state])).rejects.toThrow(window.cvat.exceptions.ArgumentError);
|
||||
expect(task.annotations.put([state])).rejects.toThrow(cvat.exceptions.ArgumentError);
|
||||
|
||||
const state1 = new window.cvat.classes.ObjectState({
|
||||
const state1 = new cvat.classes.ObjectState({
|
||||
frame: 1,
|
||||
objectType: window.cvat.enums.ObjectType.SHAPE,
|
||||
shapeType: window.cvat.enums.ShapeType.POLYGON,
|
||||
objectType: cvat.enums.ObjectType.SHAPE,
|
||||
shapeType: cvat.enums.ShapeType.POLYGON,
|
||||
points: [0, 0, 100, 0, 100, 50],
|
||||
attributes: { 'bad key': 55 },
|
||||
occluded: true,
|
||||
@@ -304,94 +302,94 @@ describe('Feature: put annotations', () => {
|
||||
zOrder: NaN,
|
||||
});
|
||||
|
||||
expect(task.annotations.put([state1])).rejects.toThrow(window.cvat.exceptions.ArgumentError);
|
||||
expect(task.annotations.put([state1])).rejects.toThrow(cvat.exceptions.ArgumentError);
|
||||
});
|
||||
|
||||
test('put shape without points and with invalid points to a task', async () => {
|
||||
const task = (await window.cvat.tasks.get({ id: 101 }))[0];
|
||||
const task = (await cvat.tasks.get({ id: 101 }))[0];
|
||||
await task.annotations.clear(true);
|
||||
const state = new window.cvat.classes.ObjectState({
|
||||
const state = new cvat.classes.ObjectState({
|
||||
frame: 1,
|
||||
objectType: window.cvat.enums.ObjectType.SHAPE,
|
||||
shapeType: window.cvat.enums.ShapeType.POLYGON,
|
||||
objectType: cvat.enums.ObjectType.SHAPE,
|
||||
shapeType: cvat.enums.ShapeType.POLYGON,
|
||||
occluded: true,
|
||||
label: task.labels[0],
|
||||
zOrder: 0,
|
||||
});
|
||||
|
||||
expect(() => state.points = ['150,50 250,30']).toThrow(window.cvat.exceptions.ArgumentError);
|
||||
expect(() => state.points = ['150,50 250,30']).toThrow(cvat.exceptions.ArgumentError);
|
||||
|
||||
delete state.points;
|
||||
expect(task.annotations.put([state])).rejects.toThrow(window.cvat.exceptions.DataError);
|
||||
expect(task.annotations.put([state])).rejects.toThrow(cvat.exceptions.DataError);
|
||||
|
||||
state.points = [];
|
||||
expect(task.annotations.put([state])).rejects.toThrow(window.cvat.exceptions.DataError);
|
||||
expect(task.annotations.put([state])).rejects.toThrow(cvat.exceptions.DataError);
|
||||
});
|
||||
|
||||
test('put shape without type to a task', async () => {
|
||||
const task = (await window.cvat.tasks.get({ id: 101 }))[0];
|
||||
const task = (await cvat.tasks.get({ id: 101 }))[0];
|
||||
await task.annotations.clear(true);
|
||||
const state = new window.cvat.classes.ObjectState({
|
||||
const state = new cvat.classes.ObjectState({
|
||||
frame: 1,
|
||||
objectType: window.cvat.enums.ObjectType.SHAPE,
|
||||
objectType: cvat.enums.ObjectType.SHAPE,
|
||||
points: [0, 0, 100, 0, 100, 50],
|
||||
occluded: true,
|
||||
label: task.labels[0],
|
||||
zOrder: 0,
|
||||
});
|
||||
|
||||
expect(task.annotations.put([state])).rejects.toThrow(window.cvat.exceptions.ArgumentError);
|
||||
expect(task.annotations.put([state])).rejects.toThrow(cvat.exceptions.ArgumentError);
|
||||
});
|
||||
|
||||
test('put shape without label and with bad label to a task', async () => {
|
||||
const task = (await window.cvat.tasks.get({ id: 101 }))[0];
|
||||
const task = (await cvat.tasks.get({ id: 101 }))[0];
|
||||
await task.annotations.clear(true);
|
||||
const state = {
|
||||
frame: 1,
|
||||
objectType: window.cvat.enums.ObjectType.SHAPE,
|
||||
shapeType: window.cvat.enums.ShapeType.POLYGON,
|
||||
objectType: cvat.enums.ObjectType.SHAPE,
|
||||
shapeType: cvat.enums.ShapeType.POLYGON,
|
||||
points: [0, 0, 100, 0, 100, 50],
|
||||
occluded: true,
|
||||
zOrder: 0,
|
||||
};
|
||||
|
||||
expect(() => new window.cvat.classes.ObjectState(state))
|
||||
.toThrow(window.cvat.exceptions.ArgumentError);
|
||||
expect(() => new window.cvat.classes.ObjectState({ ...state, label: 'bad label' }))
|
||||
.toThrow(window.cvat.exceptions.ArgumentError);
|
||||
expect(() => new window.cvat.classes.ObjectState({ ...state, label: {} }))
|
||||
.toThrow(window.cvat.exceptions.ArgumentError);
|
||||
expect(() => new cvat.classes.ObjectState(state))
|
||||
.toThrow(cvat.exceptions.ArgumentError);
|
||||
expect(() => new cvat.classes.ObjectState({ ...state, label: 'bad label' }))
|
||||
.toThrow(cvat.exceptions.ArgumentError);
|
||||
expect(() => new cvat.classes.ObjectState({ ...state, label: {} }))
|
||||
.toThrow(cvat.exceptions.ArgumentError);
|
||||
});
|
||||
|
||||
test('put shape with bad frame to a task', async () => {
|
||||
const task = (await window.cvat.tasks.get({ id: 101 }))[0];
|
||||
const task = (await cvat.tasks.get({ id: 101 }))[0];
|
||||
await task.annotations.clear(true);
|
||||
expect(() => new window.cvat.classes.ObjectState({
|
||||
expect(() => new cvat.classes.ObjectState({
|
||||
frame: '5',
|
||||
objectType: window.cvat.enums.ObjectType.SHAPE,
|
||||
shapeType: window.cvat.enums.ShapeType.POLYGON,
|
||||
objectType: cvat.enums.ObjectType.SHAPE,
|
||||
shapeType: cvat.enums.ShapeType.POLYGON,
|
||||
points: [0, 0, 100, 0, 100, 50],
|
||||
occluded: true,
|
||||
label: task.labels[0],
|
||||
zOrder: 0,
|
||||
})).toThrow(window.cvat.exceptions.ArgumentError);
|
||||
})).toThrow(cvat.exceptions.ArgumentError);
|
||||
});
|
||||
|
||||
test('put a skeleton shape to a job', async() => {
|
||||
const job = (await window.cvat.jobs.get({ jobID: 40 }))[0];
|
||||
const job = (await cvat.jobs.get({ jobID: 40 }))[0];
|
||||
const label = job.labels[0];
|
||||
await job.annotations.clear(true);
|
||||
await job.annotations.clear();
|
||||
const skeleton = new window.cvat.classes.ObjectState({
|
||||
const skeleton = new cvat.classes.ObjectState({
|
||||
frame: 0,
|
||||
objectType: window.cvat.enums.ObjectType.SHAPE,
|
||||
shapeType: window.cvat.enums.ShapeType.SKELETON,
|
||||
objectType: cvat.enums.ObjectType.SHAPE,
|
||||
shapeType: cvat.enums.ShapeType.SKELETON,
|
||||
points: [],
|
||||
label,
|
||||
elements: label.structure.sublabels.map((sublabel, idx) => ({
|
||||
frame: 0,
|
||||
objectType: window.cvat.enums.ObjectType.SHAPE,
|
||||
shapeType: window.cvat.enums.ShapeType.POINTS,
|
||||
objectType: cvat.enums.ObjectType.SHAPE,
|
||||
shapeType: cvat.enums.ShapeType.POINTS,
|
||||
points: [idx * 10, idx * 10],
|
||||
label: sublabel,
|
||||
}))
|
||||
@@ -400,29 +398,29 @@ describe('Feature: put annotations', () => {
|
||||
await job.annotations.put([skeleton]);
|
||||
const annotations = await job.annotations.get(0);
|
||||
expect(annotations.length).toBe(1);
|
||||
expect(annotations[0].objectType).toBe(window.cvat.enums.ObjectType.SHAPE);
|
||||
expect(annotations[0].shapeType).toBe(window.cvat.enums.ShapeType.SKELETON);
|
||||
expect(annotations[0].objectType).toBe(cvat.enums.ObjectType.SHAPE);
|
||||
expect(annotations[0].shapeType).toBe(cvat.enums.ShapeType.SKELETON);
|
||||
for (const element of annotations[0].elements) {
|
||||
expect(element.objectType).toBe(window.cvat.enums.ObjectType.SHAPE);
|
||||
expect(element.shapeType).toBe(window.cvat.enums.ShapeType.POINTS);
|
||||
expect(element.objectType).toBe(cvat.enums.ObjectType.SHAPE);
|
||||
expect(element.shapeType).toBe(cvat.enums.ShapeType.POINTS);
|
||||
}
|
||||
});
|
||||
|
||||
test('put a skeleton track to a task', async() => {
|
||||
const task = (await window.cvat.tasks.get({ id: 40 }))[0];
|
||||
const task = (await cvat.tasks.get({ id: 40 }))[0];
|
||||
const label = task.labels[0];
|
||||
await task.annotations.clear(true);
|
||||
await task.annotations.clear();
|
||||
const skeleton = new window.cvat.classes.ObjectState({
|
||||
const skeleton = new cvat.classes.ObjectState({
|
||||
frame: 0,
|
||||
objectType: window.cvat.enums.ObjectType.TRACK,
|
||||
shapeType: window.cvat.enums.ShapeType.SKELETON,
|
||||
objectType: cvat.enums.ObjectType.TRACK,
|
||||
shapeType: cvat.enums.ShapeType.SKELETON,
|
||||
points: [],
|
||||
label,
|
||||
elements: label.structure.sublabels.map((sublabel, idx) => ({
|
||||
frame: 0,
|
||||
objectType: window.cvat.enums.ObjectType.TRACK,
|
||||
shapeType: window.cvat.enums.ShapeType.POINTS,
|
||||
objectType: cvat.enums.ObjectType.TRACK,
|
||||
shapeType: cvat.enums.ShapeType.POINTS,
|
||||
points: [idx * 10, idx * 10],
|
||||
label: sublabel,
|
||||
}))
|
||||
@@ -431,18 +429,19 @@ describe('Feature: put annotations', () => {
|
||||
await task.annotations.put([skeleton]);
|
||||
const annotations = await task.annotations.get(2);
|
||||
expect(annotations.length).toBe(1);
|
||||
expect(annotations[0].objectType).toBe(window.cvat.enums.ObjectType.TRACK);
|
||||
expect(annotations[0].shapeType).toBe(window.cvat.enums.ShapeType.SKELETON);
|
||||
expect(annotations[0].objectType).toBe(cvat.enums.ObjectType.TRACK);
|
||||
expect(annotations[0].shapeType).toBe(cvat.enums.ShapeType.SKELETON);
|
||||
for (const element of annotations[0].elements) {
|
||||
expect(element.objectType).toBe(window.cvat.enums.ObjectType.TRACK);
|
||||
expect(element.shapeType).toBe(window.cvat.enums.ShapeType.POINTS);
|
||||
expect(element.objectType).toBe(cvat.enums.ObjectType.TRACK);
|
||||
expect(element.shapeType).toBe(cvat.enums.ShapeType.POINTS);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('Feature: check unsaved changes', () => {
|
||||
test('check unsaved changes in a task', async () => {
|
||||
const task = (await window.cvat.tasks.get({ id: 101 }))[0];
|
||||
const task = (await cvat.tasks.get({ id: 101 }))[0];
|
||||
await task.annotations.get(0);
|
||||
expect(await task.annotations.hasUnsavedChanges()).toBe(false);
|
||||
const annotations = await task.annotations.get(0);
|
||||
|
||||
@@ -453,7 +452,8 @@ describe('Feature: check unsaved changes', () => {
|
||||
});
|
||||
|
||||
test('check unsaved changes in a job', async () => {
|
||||
const job = (await window.cvat.jobs.get({ jobID: 100 }))[0];
|
||||
const job = (await cvat.jobs.get({ jobID: 100 }))[0];
|
||||
await job.annotations.get(0);
|
||||
expect(await job.annotations.hasUnsavedChanges()).toBe(false);
|
||||
const annotations = await job.annotations.get(0);
|
||||
|
||||
@@ -466,12 +466,12 @@ describe('Feature: check unsaved changes', () => {
|
||||
|
||||
describe('Feature: save annotations', () => {
|
||||
test('create, save, undo, save, redo save', async () => {
|
||||
const task = (await window.cvat.tasks.get({ id: 101 }))[0];
|
||||
const task = (await cvat.tasks.get({ id: 101 }))[0];
|
||||
await task.annotations.get(0);
|
||||
const state = new window.cvat.classes.ObjectState({
|
||||
const state = new cvat.classes.ObjectState({
|
||||
frame: 0,
|
||||
objectType: window.cvat.enums.ObjectType.SHAPE,
|
||||
shapeType: window.cvat.enums.ShapeType.POLYGON,
|
||||
objectType: cvat.enums.ObjectType.SHAPE,
|
||||
shapeType: cvat.enums.ShapeType.POLYGON,
|
||||
points: [0, 0, 100, 0, 100, 50],
|
||||
occluded: true,
|
||||
label: task.labels[0],
|
||||
@@ -487,13 +487,13 @@ describe('Feature: save annotations', () => {
|
||||
});
|
||||
|
||||
test('create & save annotations for a task', async () => {
|
||||
const task = (await window.cvat.tasks.get({ id: 101 }))[0];
|
||||
const task = (await cvat.tasks.get({ id: 101 }))[0];
|
||||
let annotations = await task.annotations.get(0);
|
||||
const { length } = annotations;
|
||||
const state = new window.cvat.classes.ObjectState({
|
||||
const state = new cvat.classes.ObjectState({
|
||||
frame: 0,
|
||||
objectType: window.cvat.enums.ObjectType.SHAPE,
|
||||
shapeType: window.cvat.enums.ShapeType.POLYGON,
|
||||
objectType: cvat.enums.ObjectType.SHAPE,
|
||||
shapeType: cvat.enums.ShapeType.POLYGON,
|
||||
points: [0, 0, 100, 0, 100, 50],
|
||||
occluded: true,
|
||||
label: task.labels[0],
|
||||
@@ -510,7 +510,7 @@ describe('Feature: save annotations', () => {
|
||||
});
|
||||
|
||||
test('update & save annotations for a task', async () => {
|
||||
const task = (await window.cvat.tasks.get({ id: 101 }))[0];
|
||||
const task = (await cvat.tasks.get({ id: 101 }))[0];
|
||||
const annotations = await task.annotations.get(0);
|
||||
|
||||
expect(task.annotations.hasUnsavedChanges()).toBe(false);
|
||||
@@ -522,7 +522,7 @@ describe('Feature: save annotations', () => {
|
||||
});
|
||||
|
||||
test('delete & save annotations for a task', async () => {
|
||||
const task = (await window.cvat.tasks.get({ id: 101 }))[0];
|
||||
const task = (await cvat.tasks.get({ id: 101 }))[0];
|
||||
const annotations = await task.annotations.get(0);
|
||||
|
||||
expect(task.annotations.hasUnsavedChanges()).toBe(false);
|
||||
@@ -533,13 +533,13 @@ describe('Feature: save annotations', () => {
|
||||
});
|
||||
|
||||
test('create & save annotations for a job', async () => {
|
||||
const job = (await window.cvat.jobs.get({ jobID: 100 }))[0];
|
||||
const job = (await cvat.jobs.get({ jobID: 100 }))[0];
|
||||
let annotations = await job.annotations.get(0);
|
||||
const { length } = annotations;
|
||||
const state = new window.cvat.classes.ObjectState({
|
||||
const state = new cvat.classes.ObjectState({
|
||||
frame: 0,
|
||||
objectType: window.cvat.enums.ObjectType.SHAPE,
|
||||
shapeType: window.cvat.enums.ShapeType.POLYGON,
|
||||
objectType: cvat.enums.ObjectType.SHAPE,
|
||||
shapeType: cvat.enums.ShapeType.POLYGON,
|
||||
points: [0, 0, 100, 0, 100, 50],
|
||||
occluded: true,
|
||||
label: job.labels[0],
|
||||
@@ -556,7 +556,7 @@ describe('Feature: save annotations', () => {
|
||||
});
|
||||
|
||||
test('update & save annotations for a job', async () => {
|
||||
const job = (await window.cvat.jobs.get({ jobID: 100 }))[0];
|
||||
const job = (await cvat.jobs.get({ jobID: 100 }))[0];
|
||||
const annotations = await job.annotations.get(0);
|
||||
|
||||
expect(job.annotations.hasUnsavedChanges()).toBe(false);
|
||||
@@ -568,7 +568,7 @@ describe('Feature: save annotations', () => {
|
||||
});
|
||||
|
||||
test('delete & save annotations for a job', async () => {
|
||||
const job = (await window.cvat.jobs.get({ jobID: 100 }))[0];
|
||||
const job = (await cvat.jobs.get({ jobID: 100 }))[0];
|
||||
const annotations = await job.annotations.get(0);
|
||||
|
||||
expect(job.annotations.hasUnsavedChanges()).toBe(false);
|
||||
@@ -579,7 +579,7 @@ describe('Feature: save annotations', () => {
|
||||
});
|
||||
|
||||
test('delete & save annotations for a job when there are a track and a shape with the same id', async () => {
|
||||
const job = (await window.cvat.jobs.get({ jobID: 112 }))[0];
|
||||
const job = (await cvat.jobs.get({ jobID: 112 }))[0];
|
||||
const annotations = await job.annotations.get(0);
|
||||
let okay = false;
|
||||
|
||||
@@ -604,16 +604,16 @@ describe('Feature: save annotations', () => {
|
||||
|
||||
describe('Feature: merge annotations', () => {
|
||||
test('merge annotations in a task', async () => {
|
||||
const task = (await window.cvat.tasks.get({ id: 100 }))[0];
|
||||
const task = (await cvat.tasks.get({ id: 100 }))[0];
|
||||
const annotations0 = await task.annotations.get(0);
|
||||
const annotations1 = await task.annotations.get(1);
|
||||
const states = [annotations0[0], annotations1[0]];
|
||||
await task.annotations.merge(states);
|
||||
const merged0 = (await task.annotations.get(0)).filter(
|
||||
(state) => state.objectType === window.cvat.enums.ObjectType.TRACK,
|
||||
(state) => state.objectType === cvat.enums.ObjectType.TRACK,
|
||||
);
|
||||
const merged1 = (await task.annotations.get(1)).filter(
|
||||
(state) => state.objectType === window.cvat.enums.ObjectType.TRACK,
|
||||
(state) => state.objectType === cvat.enums.ObjectType.TRACK,
|
||||
);
|
||||
expect(merged0).toHaveLength(1);
|
||||
expect(merged1).toHaveLength(1);
|
||||
@@ -623,16 +623,16 @@ describe('Feature: merge annotations', () => {
|
||||
});
|
||||
|
||||
test('merge annotations in a job', async () => {
|
||||
const job = (await window.cvat.jobs.get({ jobID: 100 }))[0];
|
||||
const job = (await cvat.jobs.get({ jobID: 100 }))[0];
|
||||
const annotations0 = await job.annotations.get(0);
|
||||
const annotations1 = await job.annotations.get(1);
|
||||
const states = [annotations0[0], annotations1[0]];
|
||||
await job.annotations.merge(states);
|
||||
const merged0 = (await job.annotations.get(0)).filter(
|
||||
(state) => state.objectType === window.cvat.enums.ObjectType.TRACK,
|
||||
(state) => state.objectType === cvat.enums.ObjectType.TRACK,
|
||||
);
|
||||
const merged1 = (await job.annotations.get(1)).filter(
|
||||
(state) => state.objectType === window.cvat.enums.ObjectType.TRACK,
|
||||
(state) => state.objectType === cvat.enums.ObjectType.TRACK,
|
||||
);
|
||||
expect(merged0).toHaveLength(1);
|
||||
expect(merged1).toHaveLength(1);
|
||||
@@ -642,74 +642,74 @@ describe('Feature: merge annotations', () => {
|
||||
});
|
||||
|
||||
test('trying to merge not object state', async () => {
|
||||
const task = (await window.cvat.tasks.get({ id: 100 }))[0];
|
||||
const task = (await cvat.tasks.get({ id: 100 }))[0];
|
||||
const annotations0 = await task.annotations.get(0);
|
||||
const states = [annotations0[0], {}];
|
||||
|
||||
expect(task.annotations.merge(states)).rejects.toThrow(window.cvat.exceptions.ArgumentError);
|
||||
expect(task.annotations.merge(states)).rejects.toThrow(cvat.exceptions.ArgumentError);
|
||||
});
|
||||
|
||||
test('trying to merge object state which is not saved in a collection', async () => {
|
||||
const task = (await window.cvat.tasks.get({ id: 100 }))[0];
|
||||
const task = (await cvat.tasks.get({ id: 100 }))[0];
|
||||
const annotations0 = await task.annotations.get(0);
|
||||
|
||||
const state = new window.cvat.classes.ObjectState({
|
||||
const state = new cvat.classes.ObjectState({
|
||||
frame: 0,
|
||||
objectType: window.cvat.enums.ObjectType.SHAPE,
|
||||
shapeType: window.cvat.enums.ShapeType.POLYGON,
|
||||
objectType: cvat.enums.ObjectType.SHAPE,
|
||||
shapeType: cvat.enums.ShapeType.POLYGON,
|
||||
points: [0, 0, 100, 0, 100, 50],
|
||||
occluded: true,
|
||||
label: task.labels[0],
|
||||
});
|
||||
const states = [annotations0[0], state];
|
||||
|
||||
expect(task.annotations.merge(states)).rejects.toThrow(window.cvat.exceptions.ArgumentError);
|
||||
expect(task.annotations.merge(states)).rejects.toThrow(cvat.exceptions.ArgumentError);
|
||||
});
|
||||
|
||||
test('trying to merge with bad label', async () => {
|
||||
const task = (await window.cvat.tasks.get({ id: 100 }))[0];
|
||||
const task = (await cvat.tasks.get({ id: 100 }))[0];
|
||||
const annotations0 = await task.annotations.get(0);
|
||||
const annotations1 = await task.annotations.get(1);
|
||||
const states = [annotations0[0], annotations1[0]];
|
||||
states[0].label = new window.cvat.classes.Label({
|
||||
states[0].label = new cvat.classes.Label({
|
||||
id: 500,
|
||||
name: 'new_label',
|
||||
attributes: [],
|
||||
});
|
||||
|
||||
expect(task.annotations.merge(states)).rejects.toThrow(window.cvat.exceptions.ArgumentError);
|
||||
expect(task.annotations.merge(states)).rejects.toThrow(cvat.exceptions.ArgumentError);
|
||||
});
|
||||
|
||||
test('trying to merge with different shape types', async () => {
|
||||
const task = (await window.cvat.tasks.get({ id: 100 }))[0];
|
||||
const task = (await cvat.tasks.get({ id: 100 }))[0];
|
||||
const annotations0 = await task.annotations.get(0);
|
||||
const annotations1 = (await task.annotations.get(1)).filter(
|
||||
(state) => state.shapeType === window.cvat.enums.ShapeType.POLYGON,
|
||||
(state) => state.shapeType === cvat.enums.ShapeType.POLYGON,
|
||||
);
|
||||
const states = [annotations0[0], annotations1[0]];
|
||||
|
||||
expect(task.annotations.merge(states)).rejects.toThrow(window.cvat.exceptions.ArgumentError);
|
||||
expect(task.annotations.merge(states)).rejects.toThrow(cvat.exceptions.ArgumentError);
|
||||
});
|
||||
|
||||
test('trying to merge with different labels', async () => {
|
||||
const task = (await window.cvat.tasks.get({ id: 100 }))[0];
|
||||
const task = (await cvat.tasks.get({ id: 100 }))[0];
|
||||
const annotations0 = await task.annotations.get(0);
|
||||
const annotations1 = await task.annotations.get(1);
|
||||
const states = [annotations0[0], annotations1[0]];
|
||||
states[1].label = new window.cvat.classes.Label({
|
||||
states[1].label = new cvat.classes.Label({
|
||||
id: 500,
|
||||
name: 'new_label',
|
||||
attributes: [],
|
||||
});
|
||||
await states[1].save();
|
||||
|
||||
expect(task.annotations.merge(states)).rejects.toThrow(window.cvat.exceptions.ArgumentError);
|
||||
expect(task.annotations.merge(states)).rejects.toThrow(cvat.exceptions.ArgumentError);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Feature: split annotations', () => {
|
||||
test('split annotations in a task', async () => {
|
||||
const task = (await window.cvat.tasks.get({ id: 101 }))[0];
|
||||
const task = (await cvat.tasks.get({ id: 101 }))[0];
|
||||
const annotations4 = await task.annotations.get(4);
|
||||
const annotations5 = await task.annotations.get(5);
|
||||
|
||||
@@ -721,7 +721,7 @@ describe('Feature: split annotations', () => {
|
||||
});
|
||||
|
||||
test('split annotations in a job', async () => {
|
||||
const job = (await window.cvat.jobs.get({ jobID: 101 }))[0];
|
||||
const job = (await cvat.jobs.get({ jobID: 101 }))[0];
|
||||
const annotations4 = await job.annotations.get(4);
|
||||
const annotations5 = await job.annotations.get(5);
|
||||
|
||||
@@ -733,20 +733,20 @@ describe('Feature: split annotations', () => {
|
||||
});
|
||||
|
||||
test('split on a bad frame', async () => {
|
||||
const task = (await window.cvat.tasks.get({ id: 101 }))[0];
|
||||
const task = (await cvat.tasks.get({ id: 101 }))[0];
|
||||
const annotations4 = await task.annotations.get(4);
|
||||
const annotations5 = await task.annotations.get(5);
|
||||
|
||||
expect(annotations4[0].clientID).toBe(annotations5[0].clientID);
|
||||
expect(task.annotations.split(annotations5[0], 'bad frame')).rejects.toThrow(
|
||||
window.cvat.exceptions.ArgumentError,
|
||||
cvat.exceptions.ArgumentError,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Feature: group annotations', () => {
|
||||
test('group annotations in a task', async () => {
|
||||
const task = (await window.cvat.tasks.get({ id: 100 }))[0];
|
||||
const task = (await cvat.tasks.get({ id: 100 }))[0];
|
||||
let annotations = await task.annotations.get(0);
|
||||
const groupID = await task.annotations.group(annotations);
|
||||
expect(typeof groupID).toBe('number');
|
||||
@@ -757,7 +757,7 @@ describe('Feature: group annotations', () => {
|
||||
});
|
||||
|
||||
test('group annotations in a job', async () => {
|
||||
const job = (await window.cvat.jobs.get({ jobID: 100 }))[0];
|
||||
const job = (await cvat.jobs.get({ jobID: 100 }))[0];
|
||||
let annotations = await job.annotations.get(0);
|
||||
const groupID = await job.annotations.group(annotations);
|
||||
expect(typeof groupID).toBe('number');
|
||||
@@ -768,32 +768,32 @@ describe('Feature: group annotations', () => {
|
||||
});
|
||||
|
||||
test('trying to group object state which has not been saved in a collection', async () => {
|
||||
const task = (await window.cvat.tasks.get({ id: 100 }))[0];
|
||||
const task = (await cvat.tasks.get({ id: 100 }))[0];
|
||||
await task.annotations.clear(true);
|
||||
|
||||
const state = new window.cvat.classes.ObjectState({
|
||||
const state = new cvat.classes.ObjectState({
|
||||
frame: 0,
|
||||
objectType: window.cvat.enums.ObjectType.SHAPE,
|
||||
shapeType: window.cvat.enums.ShapeType.POLYGON,
|
||||
objectType: cvat.enums.ObjectType.SHAPE,
|
||||
shapeType: cvat.enums.ShapeType.POLYGON,
|
||||
points: [0, 0, 100, 0, 100, 50],
|
||||
occluded: true,
|
||||
label: task.labels[0],
|
||||
zOrder: 0,
|
||||
});
|
||||
|
||||
expect(task.annotations.group([state])).rejects.toThrow(window.cvat.exceptions.ArgumentError);
|
||||
expect(task.annotations.group([state])).rejects.toThrow(cvat.exceptions.ArgumentError);
|
||||
});
|
||||
|
||||
test('trying to group not object state', async () => {
|
||||
const task = (await window.cvat.tasks.get({ id: 100 }))[0];
|
||||
const task = (await cvat.tasks.get({ id: 100 }))[0];
|
||||
const annotations = await task.annotations.get(0);
|
||||
expect(task.annotations.group(annotations.concat({}))).rejects.toThrow(window.cvat.exceptions.ArgumentError);
|
||||
expect(task.annotations.group(annotations.concat({}))).rejects.toThrow(cvat.exceptions.ArgumentError);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Feature: clear annotations', () => {
|
||||
test('clear annotations in a task', async () => {
|
||||
const task = (await window.cvat.tasks.get({ id: 100 }))[0];
|
||||
const task = (await cvat.tasks.get({ id: 100 }))[0];
|
||||
let annotations = await task.annotations.get(0);
|
||||
expect(annotations).not.toHaveLength(0);
|
||||
await task.annotations.clear();
|
||||
@@ -802,7 +802,7 @@ describe('Feature: clear annotations', () => {
|
||||
});
|
||||
|
||||
test('clear annotations in a job', async () => {
|
||||
const job = (await window.cvat.jobs.get({ jobID: 100 }))[0];
|
||||
const job = (await cvat.jobs.get({ jobID: 100 }))[0];
|
||||
let annotations = await job.annotations.get(0);
|
||||
expect(annotations).not.toHaveLength(0);
|
||||
await job.annotations.clear();
|
||||
@@ -811,7 +811,7 @@ describe('Feature: clear annotations', () => {
|
||||
});
|
||||
|
||||
test('clear annotations with reload in a task', async () => {
|
||||
const task = (await window.cvat.tasks.get({ id: 100 }))[0];
|
||||
const task = (await cvat.tasks.get({ id: 100 }))[0];
|
||||
let annotations = await task.annotations.get(0);
|
||||
expect(annotations).not.toHaveLength(0);
|
||||
annotations[0].occluded = true;
|
||||
@@ -824,7 +824,7 @@ describe('Feature: clear annotations', () => {
|
||||
});
|
||||
|
||||
test('clear annotations with reload in a job', async () => {
|
||||
const job = (await window.cvat.jobs.get({ jobID: 100 }))[0];
|
||||
const job = (await cvat.jobs.get({ jobID: 100 }))[0];
|
||||
let annotations = await job.annotations.get(0);
|
||||
expect(annotations).not.toHaveLength(0);
|
||||
annotations[0].occluded = true;
|
||||
@@ -837,34 +837,34 @@ describe('Feature: clear annotations', () => {
|
||||
});
|
||||
|
||||
test('clear annotations with bad reload parameter', async () => {
|
||||
const task = (await window.cvat.tasks.get({ id: 100 }))[0];
|
||||
const task = (await cvat.tasks.get({ id: 100 }))[0];
|
||||
await task.annotations.clear(true);
|
||||
expect(task.annotations.clear('reload')).rejects.toThrow(window.cvat.exceptions.ArgumentError);
|
||||
expect(task.annotations.clear('reload')).rejects.toThrow(cvat.exceptions.ArgumentError);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Feature: get statistics', () => {
|
||||
test('get statistics from a task', async () => {
|
||||
const task = (await window.cvat.tasks.get({ id: 100 }))[0];
|
||||
const task = (await cvat.tasks.get({ id: 100 }))[0];
|
||||
await task.annotations.clear(true);
|
||||
const statistics = await task.annotations.statistics();
|
||||
expect(statistics).toBeInstanceOf(window.cvat.classes.Statistics);
|
||||
expect(statistics).toBeInstanceOf(cvat.classes.Statistics);
|
||||
expect(statistics.total.total).toBe(30);
|
||||
});
|
||||
|
||||
test('get statistics from a job', async () => {
|
||||
const job = (await window.cvat.jobs.get({ jobID: 101 }))[0];
|
||||
const job = (await cvat.jobs.get({ jobID: 101 }))[0];
|
||||
await job.annotations.clear(true);
|
||||
const statistics = await job.annotations.statistics();
|
||||
expect(statistics).toBeInstanceOf(window.cvat.classes.Statistics);
|
||||
expect(statistics).toBeInstanceOf(cvat.classes.Statistics);
|
||||
expect(statistics.total.total).toBe(1012);
|
||||
});
|
||||
|
||||
test('get statistics from a job with skeletons', async () => {
|
||||
const job = (await window.cvat.jobs.get({ jobID: 40 }))[0];
|
||||
const job = (await cvat.jobs.get({ jobID: 40 }))[0];
|
||||
await job.annotations.clear(true);
|
||||
const statistics = await job.annotations.statistics();
|
||||
expect(statistics).toBeInstanceOf(window.cvat.classes.Statistics);
|
||||
expect(statistics).toBeInstanceOf(cvat.classes.Statistics);
|
||||
expect(statistics.total.total).toBe(30);
|
||||
const labelName = job.labels[0].name;
|
||||
expect(statistics.label[labelName].skeleton.shape).toBe(1);
|
||||
@@ -875,7 +875,7 @@ describe('Feature: get statistics', () => {
|
||||
});
|
||||
|
||||
test('get statistics from a job with skeletons', async () => {
|
||||
const job = (await window.cvat.jobs.get({ jobID: 102 }))[0];
|
||||
const job = (await cvat.jobs.get({ jobID: 102 }))[0];
|
||||
await job.annotations.clear(true);
|
||||
let statistics = await job.annotations.statistics();
|
||||
expect(statistics.total.manually).toBe(5);
|
||||
@@ -900,61 +900,61 @@ describe('Feature: get statistics', () => {
|
||||
|
||||
describe('Feature: select object', () => {
|
||||
test('select object in a task', async () => {
|
||||
const task = (await window.cvat.tasks.get({ id: 100 }))[0];
|
||||
const task = (await cvat.tasks.get({ id: 100 }))[0];
|
||||
const annotations = await task.annotations.get(0);
|
||||
let result = await task.annotations.select(annotations, 1430, 765);
|
||||
expect(result.state.shapeType).toBe(window.cvat.enums.ShapeType.RECTANGLE);
|
||||
expect(result.state.shapeType).toBe(cvat.enums.ShapeType.RECTANGLE);
|
||||
result = await task.annotations.select(annotations, 1415, 765);
|
||||
expect(result.state.shapeType).toBe(window.cvat.enums.ShapeType.POLYGON);
|
||||
expect(result.state.shapeType).toBe(cvat.enums.ShapeType.POLYGON);
|
||||
expect(result.state.points).toHaveLength(10);
|
||||
result = await task.annotations.select(annotations, 1083, 543);
|
||||
expect(result.state.shapeType).toBe(window.cvat.enums.ShapeType.POINTS);
|
||||
expect(result.state.shapeType).toBe(cvat.enums.ShapeType.POINTS);
|
||||
expect(result.state.points).toHaveLength(16);
|
||||
result = await task.annotations.select(annotations, 613, 811);
|
||||
expect(result.state.shapeType).toBe(window.cvat.enums.ShapeType.POLYGON);
|
||||
expect(result.state.shapeType).toBe(cvat.enums.ShapeType.POLYGON);
|
||||
expect(result.state.points).toHaveLength(94);
|
||||
result = await task.annotations.select(annotations, 600, 900);
|
||||
expect(result.state.shapeType).toBe(window.cvat.enums.ShapeType.CUBOID);
|
||||
expect(result.state.shapeType).toBe(cvat.enums.ShapeType.CUBOID);
|
||||
expect(result.state.points).toHaveLength(16);
|
||||
});
|
||||
|
||||
test('select object in a job', async () => {
|
||||
const job = (await window.cvat.jobs.get({ jobID: 100 }))[0];
|
||||
const job = (await cvat.jobs.get({ jobID: 100 }))[0];
|
||||
const annotations = await job.annotations.get(0);
|
||||
let result = await job.annotations.select(annotations, 490, 540);
|
||||
expect(result.state.shapeType).toBe(window.cvat.enums.ShapeType.RECTANGLE);
|
||||
expect(result.state.shapeType).toBe(cvat.enums.ShapeType.RECTANGLE);
|
||||
result = await job.annotations.select(annotations, 430, 260);
|
||||
expect(result.state.shapeType).toBe(window.cvat.enums.ShapeType.POLYLINE);
|
||||
expect(result.state.shapeType).toBe(cvat.enums.ShapeType.POLYLINE);
|
||||
result = await job.annotations.select(annotations, 1473, 250);
|
||||
expect(result.state.shapeType).toBe(window.cvat.enums.ShapeType.RECTANGLE);
|
||||
expect(result.state.shapeType).toBe(cvat.enums.ShapeType.RECTANGLE);
|
||||
result = await job.annotations.select(annotations, 1490, 237);
|
||||
expect(result.state.shapeType).toBe(window.cvat.enums.ShapeType.POLYGON);
|
||||
expect(result.state.shapeType).toBe(cvat.enums.ShapeType.POLYGON);
|
||||
expect(result.state.points).toHaveLength(94);
|
||||
result = await job.annotations.select(annotations, 600, 900);
|
||||
expect(result.state.shapeType).toBe(window.cvat.enums.ShapeType.CUBOID);
|
||||
expect(result.state.shapeType).toBe(cvat.enums.ShapeType.CUBOID);
|
||||
expect(result.state.points).toHaveLength(16);
|
||||
});
|
||||
|
||||
test('trying to select from not object states', async () => {
|
||||
const task = (await window.cvat.tasks.get({ id: 100 }))[0];
|
||||
const task = (await cvat.tasks.get({ id: 100 }))[0];
|
||||
const annotations = await task.annotations.get(0);
|
||||
expect(task.annotations.select(annotations.concat({}), 500, 500)).rejects.toThrow(
|
||||
window.cvat.exceptions.ArgumentError,
|
||||
cvat.exceptions.ArgumentError,
|
||||
);
|
||||
});
|
||||
|
||||
test('trying to select with invalid coordinates', async () => {
|
||||
const task = (await window.cvat.tasks.get({ id: 100 }))[0];
|
||||
const task = (await cvat.tasks.get({ id: 100 }))[0];
|
||||
const annotations = await task.annotations.get(0);
|
||||
expect(task.annotations.select(annotations, null, null)).rejects.toThrow(window.cvat.exceptions.ArgumentError);
|
||||
expect(task.annotations.select(annotations, null, null)).rejects.toThrow(window.cvat.exceptions.ArgumentError);
|
||||
expect(task.annotations.select(annotations, '5', '10')).rejects.toThrow(window.cvat.exceptions.ArgumentError);
|
||||
expect(task.annotations.select(annotations, null, null)).rejects.toThrow(cvat.exceptions.ArgumentError);
|
||||
expect(task.annotations.select(annotations, null, null)).rejects.toThrow(cvat.exceptions.ArgumentError);
|
||||
expect(task.annotations.select(annotations, '5', '10')).rejects.toThrow(cvat.exceptions.ArgumentError);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Feature: search frame', () => {
|
||||
test('applying different filters', async () => {
|
||||
const job = (await window.cvat.jobs.get({ jobID: 102 }))[0];
|
||||
const job = (await cvat.jobs.get({ jobID: 102 }))[0];
|
||||
await job.annotations.clear(true);
|
||||
let frame = await job.annotations.search(JSON.parse('[{"and":[{"==":[{"var":"type"},"tag"]}]}]'), 495, 994);
|
||||
expect(frame).toBe(500);
|
||||
@@ -1,5 +1,5 @@
|
||||
// Copyright (C) 2021-2022 Intel Corporation
|
||||
// Copyright (C) 2022 CVAT.ai Corporation
|
||||
// Copyright (C) 2022-2023 CVAT.ai Corporation
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
@@ -11,15 +11,13 @@ jest.mock('../../src/server-proxy', () => {
|
||||
};
|
||||
});
|
||||
|
||||
// Initialize api
|
||||
window.cvat = require('../../src/api').default;
|
||||
|
||||
const cvat = require('../../src/api').default;
|
||||
const CloudStorage= require('../../src/cloud-storage').default;
|
||||
const { cloudStoragesDummyData } = require('../mocks/dummy-data.mock');
|
||||
const { cloudStoragesDummyData } = require('../mocks/dummy-data.mock.cjs');
|
||||
|
||||
describe('Feature: get cloud storages', () => {
|
||||
test('get all cloud storages', async () => {
|
||||
const result = await window.cvat.cloudStorages.get();
|
||||
const result = await cvat.cloudStorages.get();
|
||||
expect(Array.isArray(result)).toBeTruthy();
|
||||
expect(result).toHaveLength(cloudStoragesDummyData.count);
|
||||
for (const item of result) {
|
||||
@@ -28,7 +26,7 @@ describe('Feature: get cloud storages', () => {
|
||||
});
|
||||
|
||||
test('get cloud storage by id', async () => {
|
||||
const result = await window.cvat.cloudStorages.get({
|
||||
const result = await cvat.cloudStorages.get({
|
||||
id: 1,
|
||||
});
|
||||
const cloudStorage = result[0];
|
||||
@@ -48,7 +46,7 @@ describe('Feature: get cloud storages', () => {
|
||||
});
|
||||
|
||||
test('get a cloud storage by an unknown id', async () => {
|
||||
const result = await window.cvat.cloudStorages.get({
|
||||
const result = await cvat.cloudStorages.get({
|
||||
id: 10,
|
||||
});
|
||||
expect(Array.isArray(result)).toBeTruthy();
|
||||
@@ -57,10 +55,10 @@ describe('Feature: get cloud storages', () => {
|
||||
|
||||
test('get a cloud storage by an invalid id', async () => {
|
||||
expect(
|
||||
window.cvat.cloudStorages.get({
|
||||
cvat.cloudStorages.get({
|
||||
id: '1',
|
||||
}),
|
||||
).rejects.toThrow(window.cvat.exceptions.ArgumentError);
|
||||
).rejects.toThrow(cvat.exceptions.ArgumentError);
|
||||
});
|
||||
|
||||
test('get cloud storages by filters', async () => {
|
||||
@@ -74,22 +72,22 @@ describe('Feature: get cloud storages', () => {
|
||||
],
|
||||
};
|
||||
|
||||
const result = await window.cvat.cloudStorages.get({ filter: JSON.stringify(filter) });
|
||||
const result = await cvat.cloudStorages.get({ filter: JSON.stringify(filter) });
|
||||
expect(result).toBeInstanceOf(Array);
|
||||
});
|
||||
|
||||
test('get cloud storage by invalid filters', async () => {
|
||||
expect(
|
||||
window.cvat.cloudStorages.get({
|
||||
cvat.cloudStorages.get({
|
||||
unknown: '5',
|
||||
}),
|
||||
).rejects.toThrow(window.cvat.exceptions.ArgumentError);
|
||||
).rejects.toThrow(cvat.exceptions.ArgumentError);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Feature: create a cloud storage', () => {
|
||||
test('create new cloud storage without an id', async () => {
|
||||
const cloudStorage = new window.cvat.classes.CloudStorage({
|
||||
const cloudStorage = new cvat.classes.CloudStorage({
|
||||
display_name: 'new cloud storage',
|
||||
provider_type: 'AZURE_CONTAINER',
|
||||
resource: 'newcontainer',
|
||||
@@ -113,7 +111,7 @@ describe('Feature: update a cloud storage', () => {
|
||||
['specificAttributes', 'region=eu-west-1'],
|
||||
]);
|
||||
|
||||
let result = await window.cvat.cloudStorages.get({
|
||||
let result = await cvat.cloudStorages.get({
|
||||
id: 1,
|
||||
});
|
||||
|
||||
@@ -125,7 +123,7 @@ describe('Feature: update a cloud storage', () => {
|
||||
|
||||
cloudStorage.save();
|
||||
|
||||
result = await window.cvat.cloudStorages.get({
|
||||
result = await cvat.cloudStorages.get({
|
||||
id: 1,
|
||||
});
|
||||
[cloudStorage] = result;
|
||||
@@ -141,7 +139,7 @@ describe('Feature: update a cloud storage', () => {
|
||||
'sub2/manifest.jsonl',
|
||||
];
|
||||
|
||||
let result = await window.cvat.cloudStorages.get({
|
||||
let result = await cvat.cloudStorages.get({
|
||||
id: 1,
|
||||
});
|
||||
let [cloudStorage] = result;
|
||||
@@ -149,7 +147,7 @@ describe('Feature: update a cloud storage', () => {
|
||||
cloudStorage.manifests = newManifests;
|
||||
cloudStorage.save();
|
||||
|
||||
result = await window.cvat.cloudStorages.get({
|
||||
result = await cvat.cloudStorages.get({
|
||||
id: 1,
|
||||
});
|
||||
[cloudStorage] = result;
|
||||
@@ -160,12 +158,12 @@ describe('Feature: update a cloud storage', () => {
|
||||
|
||||
describe('Feature: delete a cloud storage', () => {
|
||||
test('delete a cloud storage', async () => {
|
||||
let result = await window.cvat.cloudStorages.get({
|
||||
let result = await cvat.cloudStorages.get({
|
||||
id: 2,
|
||||
});
|
||||
|
||||
await result[0].delete();
|
||||
result = await window.cvat.cloudStorages.get({
|
||||
result = await cvat.cloudStorages.get({
|
||||
id: 2,
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Copyright (C) 2020-2022 Intel Corporation
|
||||
// Copyright (C) 2022 CVAT.ai Corporation
|
||||
// Copyright (C) 2022-2023 CVAT.ai Corporation
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
@@ -7,48 +7,46 @@
|
||||
jest.mock('../../src/server-proxy', () => {
|
||||
return {
|
||||
__esModule: true,
|
||||
default: require('../mocks/server-proxy.mock'),
|
||||
default: require('../mocks/server-proxy.mock.cjs'),
|
||||
};
|
||||
});
|
||||
|
||||
// Initialize api
|
||||
window.cvat = require('../../src/api').default;
|
||||
|
||||
const cvat = require('../../src/api').default;
|
||||
const { FrameData } = require('../../src/frames');
|
||||
|
||||
describe('Feature: get frame meta', () => {
|
||||
test('get meta for a task', async () => {
|
||||
const task = (await window.cvat.tasks.get({ id: 100 }))[0];
|
||||
const task = (await cvat.tasks.get({ id: 100 }))[0];
|
||||
const frame = await task.frames.get(0);
|
||||
expect(frame).toBeInstanceOf(FrameData);
|
||||
});
|
||||
|
||||
test('get meta for a job', async () => {
|
||||
const job = (await window.cvat.jobs.get({ jobID: 100 }))[0];
|
||||
const job = (await cvat.jobs.get({ jobID: 100 }))[0];
|
||||
const frame = await job.frames.get(0);
|
||||
expect(frame).toBeInstanceOf(FrameData);
|
||||
});
|
||||
|
||||
test('pass frame number out of a task', async () => {
|
||||
const task = (await window.cvat.tasks.get({ id: 100 }))[0];
|
||||
expect(task.frames.get(100)).rejects.toThrow(window.cvat.exceptions.ArgumentError);
|
||||
expect(task.frames.get(-1)).rejects.toThrow(window.cvat.exceptions.ArgumentError);
|
||||
const task = (await cvat.tasks.get({ id: 100 }))[0];
|
||||
expect(task.frames.get(100)).rejects.toThrow(cvat.exceptions.ArgumentError);
|
||||
expect(task.frames.get(-1)).rejects.toThrow(cvat.exceptions.ArgumentError);
|
||||
});
|
||||
|
||||
test('pass bad frame number', async () => {
|
||||
const task = (await window.cvat.tasks.get({ id: 100 }))[0];
|
||||
expect(task.frames.get('5')).rejects.toThrow(window.cvat.exceptions.ArgumentError);
|
||||
const task = (await cvat.tasks.get({ id: 100 }))[0];
|
||||
expect(task.frames.get('5')).rejects.toThrow(cvat.exceptions.ArgumentError);
|
||||
});
|
||||
|
||||
test('do not pass any frame number', async () => {
|
||||
const task = (await window.cvat.tasks.get({ id: 100 }))[0];
|
||||
expect(task.frames.get()).rejects.toThrow(window.cvat.exceptions.ArgumentError);
|
||||
const task = (await cvat.tasks.get({ id: 100 }))[0];
|
||||
expect(task.frames.get()).rejects.toThrow(cvat.exceptions.ArgumentError);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Feature: delete/restore frame', () => {
|
||||
test('delete frame from job', async () => {
|
||||
const job = (await window.cvat.jobs.get({ jobID: 100 }))[0];
|
||||
const job = (await cvat.jobs.get({ jobID: 100 }))[0];
|
||||
await job.annotations.clear(true);
|
||||
let frame = await job.frames.get(0);
|
||||
expect(frame.deleted).toBe(false);
|
||||
@@ -58,7 +56,7 @@ describe('Feature: delete/restore frame', () => {
|
||||
});
|
||||
|
||||
test('restore frame from job', async () => {
|
||||
const job = (await window.cvat.jobs.get({ jobID: 100 }))[0];
|
||||
const job = (await cvat.jobs.get({ jobID: 100 }))[0];
|
||||
await job.annotations.clear(true);
|
||||
let frame = await job.frames.get(8);
|
||||
expect(frame.deleted).toBe(true);
|
||||
@@ -68,7 +66,7 @@ describe('Feature: delete/restore frame', () => {
|
||||
});
|
||||
|
||||
test('delete frame from task', async () => {
|
||||
const task = (await window.cvat.tasks.get({ id: 100 }))[0];
|
||||
const task = (await cvat.tasks.get({ id: 100 }))[0];
|
||||
await task.annotations.clear(true);
|
||||
let frame = await task.frames.get(1);
|
||||
expect(frame.deleted).toBe(false);
|
||||
@@ -78,7 +76,7 @@ describe('Feature: delete/restore frame', () => {
|
||||
});
|
||||
|
||||
test('restore frame from task', async () => {
|
||||
const task = (await window.cvat.tasks.get({ id: 100 }))[0];
|
||||
const task = (await cvat.tasks.get({ id: 100 }))[0];
|
||||
await task.annotations.clear(true);
|
||||
let frame = await task.frames.get(7);
|
||||
expect(frame.deleted).toBe(true);
|
||||
@@ -90,13 +88,13 @@ describe('Feature: delete/restore frame', () => {
|
||||
|
||||
describe('Feature: get frame preview', () => {
|
||||
test('get frame preview for a task', async () => {
|
||||
const task = (await window.cvat.tasks.get({ id: 100 }))[0];
|
||||
const task = (await cvat.tasks.get({ id: 100 }))[0];
|
||||
const frame = await task.frames.preview();
|
||||
expect(typeof frame).toBe('string');
|
||||
});
|
||||
|
||||
test('get frame preview for a job', async () => {
|
||||
const job = (await window.cvat.jobs.get({ jobID: 100 }))[0];
|
||||
const job = (await cvat.jobs.get({ jobID: 100 }))[0];
|
||||
const frame = await job.frames.preview();
|
||||
expect(typeof frame).toBe('string');
|
||||
});
|
||||
@@ -1,5 +1,5 @@
|
||||
// Copyright (C) 2020-2022 Intel Corporation
|
||||
// Copyright (C) 2022 CVAT.ai Corporation
|
||||
// Copyright (C) 2022-2023 CVAT.ai Corporation
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
@@ -7,19 +7,17 @@
|
||||
jest.mock('../../src/server-proxy', () => {
|
||||
return {
|
||||
__esModule: true,
|
||||
default: require('../mocks/server-proxy.mock'),
|
||||
default: require('../mocks/server-proxy.mock.cjs'),
|
||||
};
|
||||
});
|
||||
|
||||
// Initialize api
|
||||
window.cvat = require('../../src/api').default;
|
||||
|
||||
const cvat = require('../../src/api').default;
|
||||
const { Job } = require('../../src/session');
|
||||
|
||||
// Test cases
|
||||
describe('Feature: get a list of jobs', () => {
|
||||
test('get jobs by a task id', async () => {
|
||||
const result = await window.cvat.jobs.get({
|
||||
const result = await cvat.jobs.get({
|
||||
filter: JSON.stringify({ and: [{ '==': [{ var: 'task_id' }, 3] }] }),
|
||||
});
|
||||
expect(Array.isArray(result)).toBeTruthy();
|
||||
@@ -33,7 +31,7 @@ describe('Feature: get a list of jobs', () => {
|
||||
});
|
||||
|
||||
test('get jobs by an unknown task id', async () => {
|
||||
const result = await window.cvat.jobs.get({
|
||||
const result = await cvat.jobs.get({
|
||||
filter: JSON.stringify({ and: [{ '==': [{ var: 'task_id' }, 50] }] }),
|
||||
});
|
||||
expect(Array.isArray(result)).toBeTruthy();
|
||||
@@ -41,7 +39,7 @@ describe('Feature: get a list of jobs', () => {
|
||||
});
|
||||
|
||||
test('get jobs by a job id', async () => {
|
||||
const result = await window.cvat.jobs.get({
|
||||
const result = await cvat.jobs.get({
|
||||
jobID: 1,
|
||||
});
|
||||
expect(Array.isArray(result)).toBeTruthy();
|
||||
@@ -50,7 +48,7 @@ describe('Feature: get a list of jobs', () => {
|
||||
});
|
||||
|
||||
test('get jobs by an unknown job id', async () => {
|
||||
const result = await window.cvat.jobs.get({
|
||||
const result = await cvat.jobs.get({
|
||||
jobID: 50,
|
||||
});
|
||||
expect(Array.isArray(result)).toBeTruthy();
|
||||
@@ -59,41 +57,41 @@ describe('Feature: get a list of jobs', () => {
|
||||
|
||||
test('get jobs by invalid filter with both taskID and jobID', async () => {
|
||||
expect(
|
||||
window.cvat.jobs.get({
|
||||
cvat.jobs.get({
|
||||
taskID: 1,
|
||||
jobID: 1,
|
||||
}),
|
||||
).rejects.toThrow(window.cvat.exceptions.ArgumentError);
|
||||
).rejects.toThrow(cvat.exceptions.ArgumentError);
|
||||
});
|
||||
|
||||
test('get jobs by invalid job id', async () => {
|
||||
expect(
|
||||
window.cvat.jobs.get({
|
||||
cvat.jobs.get({
|
||||
jobID: '1',
|
||||
}),
|
||||
).rejects.toThrow(window.cvat.exceptions.ArgumentError);
|
||||
).rejects.toThrow(cvat.exceptions.ArgumentError);
|
||||
});
|
||||
|
||||
test('get jobs by invalid task id', async () => {
|
||||
expect(
|
||||
window.cvat.jobs.get({
|
||||
cvat.jobs.get({
|
||||
taskID: '1',
|
||||
}),
|
||||
).rejects.toThrow(window.cvat.exceptions.ArgumentError);
|
||||
).rejects.toThrow(cvat.exceptions.ArgumentError);
|
||||
});
|
||||
|
||||
test('get jobs by unknown filter', async () => {
|
||||
expect(
|
||||
window.cvat.jobs.get({
|
||||
cvat.jobs.get({
|
||||
unknown: 50,
|
||||
}),
|
||||
).rejects.toThrow(window.cvat.exceptions.ArgumentError);
|
||||
).rejects.toThrow(cvat.exceptions.ArgumentError);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Feature: save job', () => {
|
||||
test('save stage and state of a job', async () => {
|
||||
const result = await window.cvat.jobs.get({ jobID: 1 });
|
||||
const result = await cvat.jobs.get({ jobID: 1 });
|
||||
|
||||
result[0].stage = 'validation';
|
||||
result[0].state = 'new';
|
||||
@@ -104,15 +102,15 @@ describe('Feature: save job', () => {
|
||||
});
|
||||
|
||||
test('save invalid status of a job', async () => {
|
||||
const result = await window.cvat.jobs.get({
|
||||
const result = await cvat.jobs.get({
|
||||
jobID: 1,
|
||||
});
|
||||
|
||||
expect(() => {
|
||||
result[0].state = 'invalid';
|
||||
}).toThrow(window.cvat.exceptions.ArgumentError);
|
||||
}).toThrow(cvat.exceptions.ArgumentError);
|
||||
expect(() => {
|
||||
result[0].stage = 'invalid';
|
||||
}).toThrow(window.cvat.exceptions.ArgumentError);
|
||||
}).toThrow(cvat.exceptions.ArgumentError);
|
||||
});
|
||||
});
|
||||
@@ -1,5 +1,5 @@
|
||||
// Copyright (C) 2020-2022 Intel Corporation
|
||||
// Copyright (C) 2022 CVAT.ai Corporation
|
||||
// Copyright (C) 2022-2023 CVAT.ai Corporation
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
@@ -7,19 +7,18 @@
|
||||
jest.mock('../../src/server-proxy', () => {
|
||||
return {
|
||||
__esModule: true,
|
||||
default: require('../mocks/server-proxy.mock'),
|
||||
default: require('../mocks/server-proxy.mock.cjs'),
|
||||
};
|
||||
});
|
||||
|
||||
// Initialize api
|
||||
window.cvat = require('../../src/api').default;
|
||||
const cvat = require('../../src/api').default;
|
||||
|
||||
describe('Feature: set attributes for an object state', () => {
|
||||
test('set a valid value', () => {
|
||||
const state = new window.cvat.classes.ObjectState({
|
||||
label: new window.cvat.classes.Label({ name: 'test label', id: 1, color: '#000000', attributes: [] }),
|
||||
objectType: window.cvat.enums.ObjectType.SHAPE,
|
||||
shapeType: window.cvat.enums.ShapeType.RECTANGLE,
|
||||
const state = new cvat.classes.ObjectState({
|
||||
label: new cvat.classes.Label({ name: 'test label', id: 1, color: '#000000', attributes: [] }),
|
||||
objectType: cvat.enums.ObjectType.SHAPE,
|
||||
shapeType: cvat.enums.ShapeType.RECTANGLE,
|
||||
frame: 5,
|
||||
});
|
||||
|
||||
@@ -33,36 +32,36 @@ describe('Feature: set attributes for an object state', () => {
|
||||
});
|
||||
|
||||
test('trying to set a bad value', () => {
|
||||
const state = new window.cvat.classes.ObjectState({
|
||||
label: new window.cvat.classes.Label({ name: 'test label', id: 1, color: '#000000', attributes: [] }),
|
||||
objectType: window.cvat.enums.ObjectType.SHAPE,
|
||||
shapeType: window.cvat.enums.ShapeType.RECTANGLE,
|
||||
const state = new cvat.classes.ObjectState({
|
||||
label: new cvat.classes.Label({ name: 'test label', id: 1, color: '#000000', attributes: [] }),
|
||||
objectType: cvat.enums.ObjectType.SHAPE,
|
||||
shapeType: cvat.enums.ShapeType.RECTANGLE,
|
||||
frame: 5,
|
||||
});
|
||||
|
||||
let attributes = 'bad attribute';
|
||||
expect(() => {
|
||||
state.attributes = attributes;
|
||||
}).toThrow(window.cvat.exceptions.ArgumentError);
|
||||
}).toThrow(cvat.exceptions.ArgumentError);
|
||||
|
||||
attributes = 5;
|
||||
expect(() => {
|
||||
state.attributes = attributes;
|
||||
}).toThrow(window.cvat.exceptions.ArgumentError);
|
||||
}).toThrow(cvat.exceptions.ArgumentError);
|
||||
|
||||
attributes = false;
|
||||
expect(() => {
|
||||
state.attributes = attributes;
|
||||
}).toThrow(window.cvat.exceptions.ArgumentError);
|
||||
}).toThrow(cvat.exceptions.ArgumentError);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Feature: set points for an object state', () => {
|
||||
test('set a valid value', () => {
|
||||
const state = new window.cvat.classes.ObjectState({
|
||||
label: new window.cvat.classes.Label({ name: 'test label', id: 1, color: '#000000', attributes: [] }),
|
||||
objectType: window.cvat.enums.ObjectType.SHAPE,
|
||||
shapeType: window.cvat.enums.ShapeType.RECTANGLE,
|
||||
const state = new cvat.classes.ObjectState({
|
||||
label: new cvat.classes.Label({ name: 'test label', id: 1, color: '#000000', attributes: [] }),
|
||||
objectType: cvat.enums.ObjectType.SHAPE,
|
||||
shapeType: cvat.enums.ShapeType.RECTANGLE,
|
||||
frame: 5,
|
||||
});
|
||||
|
||||
@@ -72,48 +71,48 @@ describe('Feature: set points for an object state', () => {
|
||||
});
|
||||
|
||||
test('trying to set a bad value', () => {
|
||||
const state = new window.cvat.classes.ObjectState({
|
||||
label: new window.cvat.classes.Label({ name: 'test label', id: 1, color: '#000000', attributes: [] }),
|
||||
objectType: window.cvat.enums.ObjectType.SHAPE,
|
||||
shapeType: window.cvat.enums.ShapeType.RECTANGLE,
|
||||
const state = new cvat.classes.ObjectState({
|
||||
label: new cvat.classes.Label({ name: 'test label', id: 1, color: '#000000', attributes: [] }),
|
||||
objectType: cvat.enums.ObjectType.SHAPE,
|
||||
shapeType: cvat.enums.ShapeType.RECTANGLE,
|
||||
frame: 5,
|
||||
});
|
||||
|
||||
let points = 'bad points';
|
||||
expect(() => {
|
||||
state.points = points;
|
||||
}).toThrow(window.cvat.exceptions.ArgumentError);
|
||||
}).toThrow(cvat.exceptions.ArgumentError);
|
||||
|
||||
points = 5;
|
||||
expect(() => {
|
||||
state.points = points;
|
||||
}).toThrow(window.cvat.exceptions.ArgumentError);
|
||||
}).toThrow(cvat.exceptions.ArgumentError);
|
||||
|
||||
points = false;
|
||||
expect(() => {
|
||||
state.points = points;
|
||||
}).toThrow(window.cvat.exceptions.ArgumentError);
|
||||
}).toThrow(cvat.exceptions.ArgumentError);
|
||||
|
||||
points = {};
|
||||
expect(() => {
|
||||
state.points = points;
|
||||
}).toThrow(window.cvat.exceptions.ArgumentError);
|
||||
}).toThrow(cvat.exceptions.ArgumentError);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Feature: save object from its state', () => {
|
||||
test('save valid values for a shape', async () => {
|
||||
const task = (await window.cvat.tasks.get({ id: 100 }))[0];
|
||||
const task = (await cvat.tasks.get({ id: 100 }))[0];
|
||||
const annotations = await task.annotations.get(0);
|
||||
let state = annotations[0];
|
||||
expect(state.objectType).toBe(window.cvat.enums.ObjectType.SHAPE);
|
||||
expect(state.shapeType).toBe(window.cvat.enums.ShapeType.RECTANGLE);
|
||||
expect(state.objectType).toBe(cvat.enums.ObjectType.SHAPE);
|
||||
expect(state.shapeType).toBe(cvat.enums.ShapeType.RECTANGLE);
|
||||
state.points = [0, 0, 100, 100];
|
||||
state.occluded = true;
|
||||
[, state.label] = task.labels;
|
||||
state.lock = true;
|
||||
state = await state.save();
|
||||
expect(state).toBeInstanceOf(window.cvat.classes.ObjectState);
|
||||
expect(state).toBeInstanceOf(cvat.classes.ObjectState);
|
||||
expect(state.label.id).toBe(task.labels[1].id);
|
||||
expect(state.lock).toBe(true);
|
||||
expect(state.occluded).toBe(true);
|
||||
@@ -121,11 +120,11 @@ describe('Feature: save object from its state', () => {
|
||||
});
|
||||
|
||||
test('save valid values for a track', async () => {
|
||||
const task = (await window.cvat.tasks.get({ id: 101 }))[0];
|
||||
const task = (await cvat.tasks.get({ id: 101 }))[0];
|
||||
const annotations = await task.annotations.get(10);
|
||||
let state = annotations[1];
|
||||
expect(state.objectType).toBe(window.cvat.enums.ObjectType.TRACK);
|
||||
expect(state.shapeType).toBe(window.cvat.enums.ShapeType.RECTANGLE);
|
||||
expect(state.objectType).toBe(cvat.enums.ObjectType.TRACK);
|
||||
expect(state.shapeType).toBe(cvat.enums.ShapeType.RECTANGLE);
|
||||
|
||||
state.occluded = true;
|
||||
state.lock = true;
|
||||
@@ -138,7 +137,7 @@ describe('Feature: save object from its state', () => {
|
||||
};
|
||||
|
||||
state = await state.save();
|
||||
expect(state).toBeInstanceOf(window.cvat.classes.ObjectState);
|
||||
expect(state).toBeInstanceOf(cvat.classes.ObjectState);
|
||||
expect(state.lock).toBe(true);
|
||||
expect(state.occluded).toBe(true);
|
||||
expect(state.points).toEqual([100, 200, 200, 400]);
|
||||
@@ -163,63 +162,63 @@ describe('Feature: save object from its state', () => {
|
||||
});
|
||||
|
||||
test('save bad values for a shape', async () => {
|
||||
const task = (await window.cvat.tasks.get({ id: 100 }))[0];
|
||||
const task = (await cvat.tasks.get({ id: 100 }))[0];
|
||||
const annotations = await task.annotations.get(0);
|
||||
const state = annotations[0];
|
||||
|
||||
state.occluded = 'false';
|
||||
await expect(state.save()).rejects.toThrow(window.cvat.exceptions.ArgumentError);
|
||||
await expect(state.save()).rejects.toThrow(cvat.exceptions.ArgumentError);
|
||||
|
||||
state.occluded = false;
|
||||
expect(() => state.points = ['100', '50', '100', {}]).toThrow(window.cvat.exceptions.ArgumentError);
|
||||
expect(() => state.points = ['100', '50', '100', {}]).toThrow(cvat.exceptions.ArgumentError);
|
||||
|
||||
state.lock = 'true';
|
||||
await expect(state.save()).rejects.toThrow(window.cvat.exceptions.ArgumentError);
|
||||
await expect(state.save()).rejects.toThrow(cvat.exceptions.ArgumentError);
|
||||
|
||||
const oldLabel = state.label;
|
||||
state.lock = false;
|
||||
state.label = 1;
|
||||
await expect(state.save()).rejects.toThrow(window.cvat.exceptions.ArgumentError);
|
||||
await expect(state.save()).rejects.toThrow(cvat.exceptions.ArgumentError);
|
||||
|
||||
state.label = oldLabel;
|
||||
state.attributes = { 1: {}, 2: false, 3: () => {} };
|
||||
await expect(state.save()).rejects.toThrow(window.cvat.exceptions.ArgumentError);
|
||||
await expect(state.save()).rejects.toThrow(cvat.exceptions.ArgumentError);
|
||||
});
|
||||
|
||||
test('save bad values for a track', async () => {
|
||||
const task = (await window.cvat.tasks.get({ id: 101 }))[0];
|
||||
const task = (await cvat.tasks.get({ id: 101 }))[0];
|
||||
const annotations = await task.annotations.get(0);
|
||||
const state = annotations[0];
|
||||
|
||||
state.occluded = 'false';
|
||||
await expect(state.save()).rejects.toThrow(window.cvat.exceptions.ArgumentError);
|
||||
await expect(state.save()).rejects.toThrow(cvat.exceptions.ArgumentError);
|
||||
|
||||
state.occluded = false;
|
||||
expect(() => state.points = ['100', '50', '100', {}]).toThrow(window.cvat.exceptions.ArgumentError);
|
||||
expect(() => state.points = ['100', '50', '100', {}]).toThrow(cvat.exceptions.ArgumentError);
|
||||
|
||||
state.lock = 'true';
|
||||
await expect(state.save()).rejects.toThrow(window.cvat.exceptions.ArgumentError);
|
||||
await expect(state.save()).rejects.toThrow(cvat.exceptions.ArgumentError);
|
||||
|
||||
const oldLabel = state.label;
|
||||
state.lock = false;
|
||||
state.label = 1;
|
||||
await expect(state.save()).rejects.toThrow(window.cvat.exceptions.ArgumentError);
|
||||
await expect(state.save()).rejects.toThrow(cvat.exceptions.ArgumentError);
|
||||
|
||||
state.label = oldLabel;
|
||||
state.outside = 5;
|
||||
await expect(state.save()).rejects.toThrow(window.cvat.exceptions.ArgumentError);
|
||||
await expect(state.save()).rejects.toThrow(cvat.exceptions.ArgumentError);
|
||||
|
||||
state.outside = false;
|
||||
state.keyframe = '10';
|
||||
await expect(state.save()).rejects.toThrow(window.cvat.exceptions.ArgumentError);
|
||||
await expect(state.save()).rejects.toThrow(cvat.exceptions.ArgumentError);
|
||||
|
||||
state.keyframe = true;
|
||||
state.attributes = { 1: {}, 2: false, 3: () => {} };
|
||||
await expect(state.save()).rejects.toThrow(window.cvat.exceptions.ArgumentError);
|
||||
await expect(state.save()).rejects.toThrow(cvat.exceptions.ArgumentError);
|
||||
});
|
||||
|
||||
test('trying to change locked shape', async () => {
|
||||
const task = (await window.cvat.tasks.get({ id: 101 }))[0];
|
||||
const task = (await cvat.tasks.get({ id: 101 }))[0];
|
||||
const annotations = await task.annotations.get(0);
|
||||
let state = annotations[0];
|
||||
|
||||
@@ -233,7 +232,7 @@ describe('Feature: save object from its state', () => {
|
||||
});
|
||||
|
||||
test('trying to set too small area of a shape', async () => {
|
||||
const task = (await window.cvat.tasks.get({ id: 101 }))[0];
|
||||
const task = (await cvat.tasks.get({ id: 101 }))[0];
|
||||
const annotations = await task.annotations.get(0);
|
||||
let state = annotations[0];
|
||||
|
||||
@@ -244,7 +243,7 @@ describe('Feature: save object from its state', () => {
|
||||
});
|
||||
|
||||
test('trying to set too small area of a track', async () => {
|
||||
const task = (await window.cvat.tasks.get({ id: 101 }))[0];
|
||||
const task = (await cvat.tasks.get({ id: 101 }))[0];
|
||||
const annotations = await task.annotations.get(0);
|
||||
let state = annotations[0];
|
||||
|
||||
@@ -255,7 +254,7 @@ describe('Feature: save object from its state', () => {
|
||||
});
|
||||
|
||||
test('trying to set too small length of a shape', async () => {
|
||||
const task = (await window.cvat.tasks.get({ id: 100 }))[0];
|
||||
const task = (await cvat.tasks.get({ id: 100 }))[0];
|
||||
const annotations = await task.annotations.get(0);
|
||||
let state = annotations[8];
|
||||
|
||||
@@ -268,7 +267,7 @@ describe('Feature: save object from its state', () => {
|
||||
|
||||
describe('Feature: delete object', () => {
|
||||
test('delete a shape', async () => {
|
||||
const task = (await window.cvat.tasks.get({ id: 100 }))[0];
|
||||
const task = (await cvat.tasks.get({ id: 100 }))[0];
|
||||
const annotationsBefore = await task.annotations.get(0);
|
||||
const { length } = annotationsBefore;
|
||||
await annotationsBefore[0].delete(0);
|
||||
@@ -277,7 +276,7 @@ describe('Feature: delete object', () => {
|
||||
});
|
||||
|
||||
test('delete a track', async () => {
|
||||
const task = (await window.cvat.tasks.get({ id: 101 }))[0];
|
||||
const task = (await cvat.tasks.get({ id: 101 }))[0];
|
||||
const annotationsBefore = await task.annotations.get(0);
|
||||
const { length } = annotationsBefore;
|
||||
await annotationsBefore[0].delete(0);
|
||||
@@ -288,7 +287,7 @@ describe('Feature: delete object', () => {
|
||||
|
||||
describe('Feature: skeletons', () => {
|
||||
test('lock, hide, occluded, outside for skeletons', async () => {
|
||||
const job = (await window.cvat.jobs.get({ jobID: 40 }))[0];
|
||||
const job = (await cvat.jobs.get({ jobID: 40 }))[0];
|
||||
let [skeleton] = await job.annotations.get(0, false, JSON.parse('[{"and":[{"==":[{"var":"shape"},"skeleton"]}]}]'));
|
||||
expect(skeleton.shapeType).toBe('skeleton');
|
||||
skeleton.lock = true;
|
||||
@@ -1,93 +0,0 @@
|
||||
// Copyright (C) 2020-2022 Intel Corporation
|
||||
// Copyright (C) 2022 CVAT.ai Corporation
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
// Setup mock for a server
|
||||
jest.mock('../../src/server-proxy', () => {
|
||||
return {
|
||||
__esModule: true,
|
||||
default: require('../mocks/server-proxy.mock'),
|
||||
};
|
||||
});
|
||||
|
||||
// Initialize api
|
||||
window.cvat = require('../../src/api').default;
|
||||
|
||||
describe('Feature: dummy feature', () => {
|
||||
test('dummy test', async () => {
|
||||
// TODO: Write test after design of plugin system
|
||||
});
|
||||
});
|
||||
|
||||
/*
|
||||
const plugin = {
|
||||
name: 'Example Plugin',
|
||||
description: 'This example plugin demonstrates how plugin system in CVAT works',
|
||||
cvat: {
|
||||
server: {
|
||||
about: {
|
||||
async leave(self, result) {
|
||||
result.plugins = await self.internal.getPlugins();
|
||||
return result;
|
||||
},
|
||||
},
|
||||
},
|
||||
classes: {
|
||||
Job: {
|
||||
prototype: {
|
||||
annotations: {
|
||||
put: {
|
||||
enter(self, objects) {
|
||||
for (const obj of objects) {
|
||||
if (obj.type !== 'tag') {
|
||||
const points = obj.position.map((point) => {
|
||||
const roundPoint = {
|
||||
x: Math.round(point.x),
|
||||
y: Math.round(point.y),
|
||||
};
|
||||
return roundPoint;
|
||||
});
|
||||
obj.points = points;
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
internal: {
|
||||
async getPlugins() {
|
||||
const plugins = await window.cvat.plugins.list();
|
||||
return plugins.map((el) => {
|
||||
const obj = {
|
||||
name: el.name,
|
||||
description: el.description,
|
||||
};
|
||||
return obj;
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
async function test() {
|
||||
await window.cvat.plugins.register(plugin);
|
||||
await window.cvat.server.login('admin', 'nimda760');
|
||||
|
||||
try {
|
||||
console.log(JSON.stringify(await window.cvat.server.about()));
|
||||
console.log(await window.cvat.users.get({ self: false }));
|
||||
console.log(await window.cvat.users.get({ self: true }));
|
||||
console.log(JSON.stringify(await window.cvat.jobs.get({ taskID: 8 })));
|
||||
console.log(JSON.stringify(await window.cvat.jobs.get({ jobID: 10 })));
|
||||
console.log(await window.cvat.tasks.get());
|
||||
console.log(await window.cvat.tasks.get({ id: 8 }));
|
||||
console.log('Done.');
|
||||
} catch (exception) {
|
||||
console.log(exception.constructor.name);
|
||||
console.log(exception.message);
|
||||
}
|
||||
}
|
||||
*/
|
||||
@@ -1,5 +1,5 @@
|
||||
// Copyright (C) 2019-2022 Intel Corporation
|
||||
// Copyright (C) 2022 CVAT.ai Corporation
|
||||
// Copyright (C) 2022-2023 CVAT.ai Corporation
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
@@ -7,18 +7,16 @@
|
||||
jest.mock('../../src/server-proxy', () => {
|
||||
return {
|
||||
__esModule: true,
|
||||
default: require('../mocks/server-proxy.mock'),
|
||||
default: require('../mocks/server-proxy.mock.cjs'),
|
||||
};
|
||||
});
|
||||
|
||||
// Initialize api
|
||||
window.cvat = require('../../src/api').default;
|
||||
|
||||
const cvat = require('../../src/api').default;
|
||||
const Project = require('../../src/project').default;
|
||||
|
||||
describe('Feature: get projects', () => {
|
||||
test('get all projects', async () => {
|
||||
const result = await window.cvat.projects.get();
|
||||
const result = await cvat.projects.get();
|
||||
expect(Array.isArray(result)).toBeTruthy();
|
||||
expect(result).toHaveLength(2);
|
||||
for (const el of result) {
|
||||
@@ -27,7 +25,7 @@ describe('Feature: get projects', () => {
|
||||
});
|
||||
|
||||
test('get project by id', async () => {
|
||||
const result = await window.cvat.projects.get({
|
||||
const result = await cvat.projects.get({
|
||||
id: 2,
|
||||
});
|
||||
|
||||
@@ -38,7 +36,7 @@ describe('Feature: get projects', () => {
|
||||
});
|
||||
|
||||
test('get a project by an unknown id', async () => {
|
||||
const result = await window.cvat.projects.get({
|
||||
const result = await cvat.projects.get({
|
||||
id: 1,
|
||||
});
|
||||
expect(Array.isArray(result)).toBeTruthy();
|
||||
@@ -47,14 +45,14 @@ describe('Feature: get projects', () => {
|
||||
|
||||
test('get a project by an invalid id', async () => {
|
||||
expect(
|
||||
window.cvat.projects.get({
|
||||
cvat.projects.get({
|
||||
id: '1',
|
||||
}),
|
||||
).rejects.toThrow(window.cvat.exceptions.ArgumentError);
|
||||
).rejects.toThrow(cvat.exceptions.ArgumentError);
|
||||
});
|
||||
|
||||
test('get projects by filters', async () => {
|
||||
const result = await window.cvat.projects.get({
|
||||
const result = await cvat.projects.get({
|
||||
filter: '{"and":[{"==":[{"var":"status"},"completed"]}]}',
|
||||
});
|
||||
expect(result).toBeInstanceOf(Array);
|
||||
@@ -62,16 +60,16 @@ describe('Feature: get projects', () => {
|
||||
|
||||
test('get projects by invalid query', async () => {
|
||||
expect(
|
||||
window.cvat.projects.get({
|
||||
cvat.projects.get({
|
||||
unknown: '5',
|
||||
}),
|
||||
).rejects.toThrow(window.cvat.exceptions.ArgumentError);
|
||||
).rejects.toThrow(cvat.exceptions.ArgumentError);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Feature: save a project', () => {
|
||||
test('save some changed fields in a project', async () => {
|
||||
let result = await window.cvat.projects.get({
|
||||
let result = await cvat.projects.get({
|
||||
id: 2,
|
||||
});
|
||||
|
||||
@@ -80,7 +78,7 @@ describe('Feature: save a project', () => {
|
||||
|
||||
await result[0].save();
|
||||
|
||||
result = await window.cvat.projects.get({
|
||||
result = await cvat.projects.get({
|
||||
id: 2,
|
||||
});
|
||||
|
||||
@@ -89,12 +87,12 @@ describe('Feature: save a project', () => {
|
||||
});
|
||||
|
||||
test('save some new labels in a project', async () => {
|
||||
let result = await window.cvat.projects.get({
|
||||
let result = await cvat.projects.get({
|
||||
id: 6,
|
||||
});
|
||||
|
||||
const labelsLength = result[0].labels.length;
|
||||
const newLabel = new window.cvat.classes.Label({
|
||||
const newLabel = new cvat.classes.Label({
|
||||
name: "My boss's car",
|
||||
attributes: [
|
||||
{
|
||||
@@ -110,7 +108,7 @@ describe('Feature: save a project', () => {
|
||||
result[0].labels = [...result[0].labels, newLabel];
|
||||
await result[0].save();
|
||||
|
||||
result = await window.cvat.projects.get({
|
||||
result = await cvat.projects.get({
|
||||
id: 6,
|
||||
});
|
||||
|
||||
@@ -125,7 +123,7 @@ describe('Feature: save a project', () => {
|
||||
});
|
||||
|
||||
test('save new project without an id', async () => {
|
||||
const project = new window.cvat.classes.Project({
|
||||
const project = new cvat.classes.Project({
|
||||
name: 'New Empty Project',
|
||||
labels: [
|
||||
{
|
||||
@@ -151,12 +149,12 @@ describe('Feature: save a project', () => {
|
||||
|
||||
describe('Feature: delete a project', () => {
|
||||
test('delete a project', async () => {
|
||||
let result = await window.cvat.projects.get({
|
||||
let result = await cvat.projects.get({
|
||||
id: 6,
|
||||
});
|
||||
|
||||
await result[0].delete();
|
||||
result = await window.cvat.projects.get({
|
||||
result = await cvat.projects.get({
|
||||
id: 6,
|
||||
});
|
||||
|
||||
@@ -167,7 +165,7 @@ describe('Feature: delete a project', () => {
|
||||
|
||||
describe('Feature: delete a label', () => {
|
||||
test('delete a label', async () => {
|
||||
let result = await window.cvat.projects.get({
|
||||
let result = await cvat.projects.get({
|
||||
id: 2,
|
||||
});
|
||||
|
||||
@@ -175,7 +173,7 @@ describe('Feature: delete a label', () => {
|
||||
const deletedLabels = result[0].labels.filter((el) => el.name !== 'bicycle');
|
||||
result[0].labels = deletedLabels;
|
||||
result[0].save();
|
||||
result = await window.cvat.projects.get({
|
||||
result = await cvat.projects.get({
|
||||
id: 2,
|
||||
});
|
||||
expect(result[0].labels).toHaveLength(labelsLength - 1);
|
||||
@@ -1,5 +1,5 @@
|
||||
// Copyright (C) 2020-2022 Intel Corporation
|
||||
// Copyright (C) 2022 CVAT.ai Corporation
|
||||
// Copyright (C) 2022-2023 CVAT.ai Corporation
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
@@ -7,18 +7,17 @@
|
||||
jest.mock('../../src/server-proxy', () => {
|
||||
return {
|
||||
__esModule: true,
|
||||
default: require('../mocks/server-proxy.mock'),
|
||||
default: require('../mocks/server-proxy.mock.cjs'),
|
||||
};
|
||||
});
|
||||
|
||||
// Initialize api
|
||||
window.cvat = require('../../src/api').default;
|
||||
const cvat = require('../../src/api').default;
|
||||
const { AnnotationFormats, Loader, Dumper } = require('../../src/annotation-formats');
|
||||
|
||||
// Test cases
|
||||
describe('Feature: get info about cvat', () => {
|
||||
test('get info about server', async () => {
|
||||
const result = await window.cvat.server.about();
|
||||
const result = await cvat.server.about();
|
||||
expect(result).toBeInstanceOf(Object);
|
||||
expect('name' in result).toBeTruthy();
|
||||
expect('description' in result).toBeTruthy();
|
||||
@@ -28,32 +27,32 @@ describe('Feature: get info about cvat', () => {
|
||||
|
||||
// describe('Feature: get share storage info', () => {
|
||||
// test('get files in a root of a share storage', async () => {
|
||||
// const result = await window.cvat.server.share();
|
||||
// const result = await cvat.server.share();
|
||||
// expect(Array.isArray(result)).toBeTruthy();
|
||||
// expect(result).toHaveLength(5);
|
||||
// });
|
||||
|
||||
// test('get files in a some dir of a share storage', async () => {
|
||||
// const result = await window.cvat.server.share('images');
|
||||
// const result = await cvat.server.share('images');
|
||||
// expect(Array.isArray(result)).toBeTruthy();
|
||||
// expect(result).toHaveLength(8);
|
||||
// });
|
||||
|
||||
// test('get files in a some unknown dir of a share storage', async () => {
|
||||
// expect(window.cvat.server.share('Unknown Directory')).rejects.toThrow(window.cvat.exceptions.ServerError);
|
||||
// expect(cvat.server.share('Unknown Directory')).rejects.toThrow(cvat.exceptions.ServerError);
|
||||
// });
|
||||
// });
|
||||
|
||||
// describe('Feature: get annotation formats', () => {
|
||||
// test('get annotation formats from a server', async () => {
|
||||
// const result = await window.cvat.server.formats();
|
||||
// const result = await cvat.server.formats();
|
||||
// expect(result).toBeInstanceOf(AnnotationFormats);
|
||||
// });
|
||||
// });
|
||||
|
||||
// describe('Feature: get annotation loaders', () => {
|
||||
// test('get annotation formats from a server', async () => {
|
||||
// const result = await window.cvat.server.formats();
|
||||
// const result = await cvat.server.formats();
|
||||
// expect(result).toBeInstanceOf(AnnotationFormats);
|
||||
// const { loaders } = result;
|
||||
// expect(Array.isArray(loaders)).toBeTruthy();
|
||||
@@ -65,7 +64,7 @@ describe('Feature: get info about cvat', () => {
|
||||
|
||||
// describe('Feature: get annotation dumpers', () => {
|
||||
// test('get annotation formats from a server', async () => {
|
||||
// const result = await window.cvat.server.formats();
|
||||
// const result = await cvat.server.formats();
|
||||
// expect(result).toBeInstanceOf(AnnotationFormats);
|
||||
// const { dumpers } = result;
|
||||
// expect(Array.isArray(dumpers)).toBeTruthy();
|
||||
@@ -1,5 +1,5 @@
|
||||
// Copyright (C) 2020-2022 Intel Corporation
|
||||
// Copyright (C) 2022 CVAT.ai Corporation
|
||||
// Copyright (C) 2022-2023 CVAT.ai Corporation
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
@@ -7,19 +7,17 @@
|
||||
jest.mock('../../src/server-proxy', () => {
|
||||
return {
|
||||
__esModule: true,
|
||||
default: require('../mocks/server-proxy.mock'),
|
||||
default: require('../mocks/server-proxy.mock.cjs'),
|
||||
};
|
||||
});
|
||||
|
||||
// Initialize api
|
||||
window.cvat = require('../../src/api').default;
|
||||
|
||||
const cvat = require('../../src/api').default;
|
||||
const { Task } = require('../../src/session');
|
||||
|
||||
// Test cases
|
||||
describe('Feature: get a list of tasks', () => {
|
||||
test('get all tasks', async () => {
|
||||
const result = await window.cvat.tasks.get();
|
||||
const result = await cvat.tasks.get();
|
||||
expect(Array.isArray(result)).toBeTruthy();
|
||||
expect(result).toHaveLength(7);
|
||||
for (const el of result) {
|
||||
@@ -28,7 +26,7 @@ describe('Feature: get a list of tasks', () => {
|
||||
});
|
||||
|
||||
test('get a task by an id', async () => {
|
||||
const result = await window.cvat.tasks.get({
|
||||
const result = await cvat.tasks.get({
|
||||
id: 3,
|
||||
});
|
||||
expect(Array.isArray(result)).toBeTruthy();
|
||||
@@ -38,7 +36,7 @@ describe('Feature: get a list of tasks', () => {
|
||||
});
|
||||
|
||||
test('get a task with skeletons by an id', async () => {
|
||||
const result = await window.cvat.tasks.get({
|
||||
const result = await cvat.tasks.get({
|
||||
id: 40,
|
||||
});
|
||||
|
||||
@@ -49,7 +47,7 @@ describe('Feature: get a list of tasks', () => {
|
||||
expect(result[0].labels).toBeInstanceOf(Array);
|
||||
|
||||
for (const label of result[0].labels) {
|
||||
expect(label).toBeInstanceOf(window.cvat.classes.Label);
|
||||
expect(label).toBeInstanceOf(cvat.classes.Label);
|
||||
if (label.type === 'skeleton') {
|
||||
expect(label.hasParent).toBe(false);
|
||||
expect(label.structure.sublabels).toBeInstanceOf(Array);
|
||||
@@ -57,7 +55,7 @@ describe('Feature: get a list of tasks', () => {
|
||||
expect(label.structure.svg.length).not.toBe(0);
|
||||
|
||||
for (const sublabel of label.structure.sublabels) {
|
||||
expect(sublabel).toBeInstanceOf(window.cvat.classes.Label);
|
||||
expect(sublabel).toBeInstanceOf(cvat.classes.Label);
|
||||
expect(sublabel.hasParent).toBe(true);
|
||||
}
|
||||
}
|
||||
@@ -65,7 +63,7 @@ describe('Feature: get a list of tasks', () => {
|
||||
});
|
||||
|
||||
test('get a task by an unknown id', async () => {
|
||||
const result = await window.cvat.tasks.get({
|
||||
const result = await cvat.tasks.get({
|
||||
id: 50,
|
||||
});
|
||||
expect(Array.isArray(result)).toBeTruthy();
|
||||
@@ -74,14 +72,14 @@ describe('Feature: get a list of tasks', () => {
|
||||
|
||||
test('get a task by an invalid id', async () => {
|
||||
expect(
|
||||
window.cvat.tasks.get({
|
||||
cvat.tasks.get({
|
||||
id: '50',
|
||||
}),
|
||||
).rejects.toThrow(window.cvat.exceptions.ArgumentError);
|
||||
).rejects.toThrow(cvat.exceptions.ArgumentError);
|
||||
});
|
||||
|
||||
test('get tasks by filters', async () => {
|
||||
const result = await window.cvat.tasks.get({
|
||||
const result = await cvat.tasks.get({
|
||||
filter: '{"and":[{"==":[{"var":"filter"},"interpolation"]}]}',
|
||||
});
|
||||
expect(result).toBeInstanceOf(Array);
|
||||
@@ -89,16 +87,16 @@ describe('Feature: get a list of tasks', () => {
|
||||
|
||||
test('get tasks by invalid query', async () => {
|
||||
expect(
|
||||
window.cvat.tasks.get({
|
||||
cvat.tasks.get({
|
||||
unknown: '5',
|
||||
}),
|
||||
).rejects.toThrow(window.cvat.exceptions.ArgumentError);
|
||||
).rejects.toThrow(cvat.exceptions.ArgumentError);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Feature: save a task', () => {
|
||||
test('save some changed fields in a task', async () => {
|
||||
let result = await window.cvat.tasks.get({
|
||||
let result = await cvat.tasks.get({
|
||||
id: 2,
|
||||
});
|
||||
|
||||
@@ -106,7 +104,7 @@ describe('Feature: save a task', () => {
|
||||
result[0].name = 'New Task Name';
|
||||
result[0].save();
|
||||
|
||||
result = await window.cvat.tasks.get({
|
||||
result = await cvat.tasks.get({
|
||||
id: 2,
|
||||
});
|
||||
|
||||
@@ -115,12 +113,12 @@ describe('Feature: save a task', () => {
|
||||
});
|
||||
|
||||
test('save some new labels in a task', async () => {
|
||||
let result = await window.cvat.tasks.get({
|
||||
let result = await cvat.tasks.get({
|
||||
id: 2,
|
||||
});
|
||||
|
||||
const labelsLength = result[0].labels.length;
|
||||
const newLabel = new window.cvat.classes.Label({
|
||||
const newLabel = new cvat.classes.Label({
|
||||
name: "Another label",
|
||||
attributes: [
|
||||
{
|
||||
@@ -136,7 +134,7 @@ describe('Feature: save a task', () => {
|
||||
result[0].labels = [...result[0].labels, newLabel];
|
||||
await result[0].save();
|
||||
|
||||
result = await window.cvat.tasks.get({
|
||||
result = await cvat.tasks.get({
|
||||
id: 2,
|
||||
});
|
||||
|
||||
@@ -151,7 +149,7 @@ describe('Feature: save a task', () => {
|
||||
});
|
||||
|
||||
test('save new task without an id', async () => {
|
||||
const task = new window.cvat.classes.Task({
|
||||
const task = new cvat.classes.Task({
|
||||
name: 'New Task',
|
||||
labels: [
|
||||
{
|
||||
@@ -176,7 +174,7 @@ describe('Feature: save a task', () => {
|
||||
});
|
||||
|
||||
test('save new task in project', async () => {
|
||||
const task = new window.cvat.classes.Task({
|
||||
const task = new cvat.classes.Task({
|
||||
name: 'New Task',
|
||||
project_id: 2,
|
||||
bug_tracker: 'bug tracker value',
|
||||
@@ -201,7 +199,7 @@ describe('Feature: save a task', () => {
|
||||
<circle r="1.5" stroke="black" fill="#b3b3b3" cx="27.49163818359375" cy="39.504600524902344" stroke-width="0.1" data-type="element node" data-element-id="5" data-node-id="5" data-label-name="5"></circle>
|
||||
`;
|
||||
|
||||
const task = new window.cvat.classes.Task({
|
||||
const task = new cvat.classes.Task({
|
||||
name: 'task with skeletons',
|
||||
labels: [{
|
||||
name: 'star skeleton',
|
||||
@@ -240,12 +238,12 @@ describe('Feature: save a task', () => {
|
||||
|
||||
describe('Feature: delete a task', () => {
|
||||
test('delete a task', async () => {
|
||||
let result = await window.cvat.tasks.get({
|
||||
let result = await cvat.tasks.get({
|
||||
id: 3,
|
||||
});
|
||||
|
||||
await result[0].delete();
|
||||
result = await window.cvat.tasks.get({
|
||||
result = await cvat.tasks.get({
|
||||
id: 3,
|
||||
});
|
||||
|
||||
@@ -256,7 +254,7 @@ describe('Feature: delete a task', () => {
|
||||
|
||||
describe('Feature: delete a label', () => {
|
||||
test('delete a label', async () => {
|
||||
let result = await window.cvat.tasks.get({
|
||||
let result = await cvat.tasks.get({
|
||||
id: 100,
|
||||
});
|
||||
|
||||
@@ -264,7 +262,7 @@ describe('Feature: delete a label', () => {
|
||||
const deletedLabels = result[0].labels.filter((el) => el.name !== 'person');
|
||||
result[0].labels = deletedLabels;
|
||||
result[0].save();
|
||||
result = await window.cvat.tasks.get({
|
||||
result = await cvat.tasks.get({
|
||||
id: 100,
|
||||
});
|
||||
expect(result[0].labels).toHaveLength(labelsLength - 1);
|
||||
@@ -1,5 +1,5 @@
|
||||
// Copyright (C) 2020-2022 Intel Corporation
|
||||
// Copyright (C) 2022 CVAT.ai Corporation
|
||||
// Copyright (C) 2022-2023 CVAT.ai Corporation
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
@@ -7,19 +7,17 @@
|
||||
jest.mock('../../src/server-proxy', () => {
|
||||
return {
|
||||
__esModule: true,
|
||||
default: require('../mocks/server-proxy.mock'),
|
||||
default: require('../mocks/server-proxy.mock.cjs'),
|
||||
};
|
||||
});
|
||||
|
||||
// Initialize api
|
||||
window.cvat = require('../../src/api').default;
|
||||
|
||||
const cvat = require('../../src/api').default;
|
||||
const User = require('../../src/user').default;
|
||||
|
||||
// Test cases
|
||||
describe('Feature: get a list of users', () => {
|
||||
test('get all users', async () => {
|
||||
const result = await window.cvat.users.get();
|
||||
const result = await cvat.users.get();
|
||||
expect(Array.isArray(result)).toBeTruthy();
|
||||
expect(result).toHaveLength(2);
|
||||
for (const el of result) {
|
||||
@@ -28,7 +26,7 @@ describe('Feature: get a list of users', () => {
|
||||
});
|
||||
|
||||
test('get only self', async () => {
|
||||
const result = await window.cvat.users.get({
|
||||
const result = await cvat.users.get({
|
||||
self: true,
|
||||
});
|
||||
expect(Array.isArray(result)).toBeTruthy();
|
||||
@@ -38,17 +36,17 @@ describe('Feature: get a list of users', () => {
|
||||
|
||||
test('get users with unknown filter key', async () => {
|
||||
expect(
|
||||
window.cvat.users.get({
|
||||
cvat.users.get({
|
||||
unknown: '50',
|
||||
}),
|
||||
).rejects.toThrow(window.cvat.exceptions.ArgumentError);
|
||||
).rejects.toThrow(cvat.exceptions.ArgumentError);
|
||||
});
|
||||
|
||||
test('get users with invalid filter key', async () => {
|
||||
expect(
|
||||
window.cvat.users.get({
|
||||
cvat.users.get({
|
||||
self: 1,
|
||||
}),
|
||||
).rejects.toThrow(window.cvat.exceptions.ArgumentError);
|
||||
).rejects.toThrow(cvat.exceptions.ArgumentError);
|
||||
});
|
||||
});
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2022 CVAT.ai Corporation
|
||||
// Copyright (C) 2022-2023 CVAT.ai Corporation
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
@@ -10,16 +10,14 @@ jest.mock('../../src/server-proxy', () => {
|
||||
};
|
||||
});
|
||||
|
||||
// Initialize api
|
||||
window.cvat = require('../../src/api').default;
|
||||
|
||||
const cvat = require('../../src/api').default;
|
||||
const Webhook = require('../../src/webhook').default;
|
||||
const { webhooksDummyData, webhooksEventsDummyData } = require('../mocks/dummy-data.mock');
|
||||
const { webhooksDummyData, webhooksEventsDummyData } = require('../mocks/dummy-data.mock.cjs');
|
||||
const { WebhookSourceType } = require('../../src/enums');
|
||||
|
||||
describe('Feature: get webhooks', () => {
|
||||
test('get all webhooks', async () => {
|
||||
const result = await window.cvat.webhooks.get({});
|
||||
const result = await cvat.webhooks.get({});
|
||||
expect(Array.isArray(result)).toBeTruthy();
|
||||
expect(result).toHaveLength(webhooksDummyData.count);
|
||||
for (const item of result) {
|
||||
@@ -42,7 +40,7 @@ describe('Feature: get webhooks', () => {
|
||||
});
|
||||
|
||||
test('get webhook by id', async () => {
|
||||
const result = await window.cvat.webhooks.get({
|
||||
const result = await cvat.webhooks.get({
|
||||
id: 1,
|
||||
});
|
||||
const [webhook] = result;
|
||||
@@ -63,7 +61,7 @@ describe('Feature: get webhooks', () => {
|
||||
|
||||
describe('Feature: create a webhook', () => {
|
||||
test('create new webhook', async () => {
|
||||
const webhook = new window.cvat.classes.Webhook({
|
||||
const webhook = new cvat.classes.Webhook({
|
||||
description: 'New webhook',
|
||||
target_url: 'https://localhost:3001/hook',
|
||||
content_type: 'application/json',
|
||||
@@ -88,7 +86,7 @@ describe('Feature: update a webhook', () => {
|
||||
['targetURL', 'https://localhost:3001/new/url'],
|
||||
]);
|
||||
|
||||
let result = await window.cvat.webhooks.get({
|
||||
let result = await cvat.webhooks.get({
|
||||
id: 1,
|
||||
});
|
||||
let [webhook] = result;
|
||||
@@ -97,7 +95,7 @@ describe('Feature: update a webhook', () => {
|
||||
}
|
||||
webhook.save();
|
||||
|
||||
result = await window.cvat.webhooks.get({
|
||||
result = await cvat.webhooks.get({
|
||||
id: 1,
|
||||
});
|
||||
[webhook] = result;
|
||||
@@ -109,13 +107,13 @@ describe('Feature: update a webhook', () => {
|
||||
|
||||
describe('Feature: delete a webhook', () => {
|
||||
test('delete a webhook', async () => {
|
||||
let result = await window.cvat.webhooks.get({
|
||||
let result = await cvat.webhooks.get({
|
||||
id: 2,
|
||||
});
|
||||
const [webhook] = result;
|
||||
await webhook.delete();
|
||||
|
||||
result = await window.cvat.webhooks.get({
|
||||
result = await cvat.webhooks.get({
|
||||
id: 2,
|
||||
});
|
||||
expect(Array.isArray(result)).toBeTruthy();
|
||||
+1
-1
@@ -19,7 +19,7 @@ const {
|
||||
webhooksDummyData,
|
||||
webhooksEventsDummyData,
|
||||
jobsDummyData,
|
||||
} = require('./dummy-data.mock');
|
||||
} = require('./dummy-data.mock.cjs');
|
||||
|
||||
function QueryStringToJSON(query, ignoreList = []) {
|
||||
const pairs = [...new URLSearchParams(query).entries()];
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es2020",
|
||||
"target": "ESNext",
|
||||
"allowJs": true,
|
||||
"module": "commonjs",
|
||||
"module": "esnext",
|
||||
"moduleResolution": "node",
|
||||
"esModuleInterop": true,
|
||||
"isolatedModules": true,
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
// Copyright (C) 2020-2022 Intel Corporation
|
||||
// Copyright (C) 2023 CVAT.ai Corporation
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
const path = require('path');
|
||||
const CopyPlugin = require('copy-webpack-plugin');
|
||||
|
||||
const webConfig = {
|
||||
target: 'web',
|
||||
mode: 'production',
|
||||
devtool: 'source-map',
|
||||
entry: {
|
||||
'cvat-core': './src/api.ts',
|
||||
},
|
||||
output: {
|
||||
path: path.resolve(__dirname, 'dist'),
|
||||
filename: '[name].[contenthash].min.js',
|
||||
library: 'cvatCore',
|
||||
libraryTarget: 'window',
|
||||
},
|
||||
resolve: {
|
||||
extensions: ['.ts', '.js'],
|
||||
fallback: {
|
||||
url: false,
|
||||
},
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /.ts?$/,
|
||||
exclude: /node_modules/,
|
||||
use: {
|
||||
loader: 'babel-loader',
|
||||
options: {
|
||||
plugins: [
|
||||
'@babel/plugin-proposal-class-properties',
|
||||
'@babel/plugin-proposal-optional-chaining',
|
||||
],
|
||||
presets: ['@babel/preset-env', '@babel/typescript'],
|
||||
sourceType: 'unambiguous',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
plugins: [
|
||||
new CopyPlugin({
|
||||
patterns: [
|
||||
{
|
||||
from: '../cvat-data/src/ts/3rdparty/avc.wasm',
|
||||
to: 'assets/3rdparty/',
|
||||
},
|
||||
],
|
||||
}),
|
||||
],
|
||||
};
|
||||
|
||||
module.exports = webConfig;
|
||||
@@ -1,108 +0,0 @@
|
||||
// Copyright (C) 2020-2022 Intel Corporation
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
/* global
|
||||
__dirname:true
|
||||
*/
|
||||
|
||||
const path = require('path');
|
||||
|
||||
const nodeConfig = {
|
||||
target: 'node',
|
||||
mode: 'development',
|
||||
devtool: 'source-map',
|
||||
entry: './src/api.ts',
|
||||
output: {
|
||||
path: path.resolve(__dirname, 'dist'),
|
||||
filename: 'cvat-core.node.js',
|
||||
libraryTarget: 'commonjs',
|
||||
},
|
||||
resolve: {
|
||||
extensions: ['.ts', '.js'],
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /.ts?$/,
|
||||
exclude: /node_modules/,
|
||||
use: {
|
||||
loader: 'babel-loader',
|
||||
options: {
|
||||
plugins: [
|
||||
'@babel/plugin-proposal-class-properties',
|
||||
'@babel/plugin-proposal-optional-chaining',
|
||||
],
|
||||
presets: ['@babel/preset-env', '@babel/typescript'],
|
||||
sourceType: 'unambiguous',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
stats: {
|
||||
warnings: false,
|
||||
},
|
||||
};
|
||||
|
||||
const webConfig = {
|
||||
target: 'web',
|
||||
mode: 'production',
|
||||
devtool: 'source-map',
|
||||
entry: {
|
||||
'cvat-core': './src/api.ts',
|
||||
},
|
||||
output: {
|
||||
path: path.resolve(__dirname, 'dist'),
|
||||
filename: '[name].[contenthash].min.js',
|
||||
library: 'cvat-core.js',
|
||||
libraryTarget: 'window',
|
||||
},
|
||||
resolve: {
|
||||
extensions: ['.ts', '.js'],
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /.ts?$/,
|
||||
exclude: /node_modules/,
|
||||
use: {
|
||||
loader: 'babel-loader',
|
||||
options: {
|
||||
plugins: [
|
||||
'@babel/plugin-proposal-class-properties',
|
||||
'@babel/plugin-proposal-optional-chaining',
|
||||
],
|
||||
presets: ['@babel/preset-env', '@babel/typescript'],
|
||||
sourceType: 'unambiguous',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
test: /3rdparty\/.*\.worker\.js$/,
|
||||
use: {
|
||||
loader: 'worker-loader',
|
||||
options: {
|
||||
publicPath: '/static/engine/js/3rdparty/',
|
||||
filename: '[name].[contenthash].js',
|
||||
esModule: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
test: /\.worker\.js$/,
|
||||
exclude: /3rdparty/,
|
||||
use: {
|
||||
loader: 'worker-loader',
|
||||
options: {
|
||||
publicPath: '/static/engine/js/',
|
||||
filename: '[name].[contenthash].js',
|
||||
esModule: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = [nodeConfig, webConfig];
|
||||
@@ -1,11 +1,10 @@
|
||||
// Copyright (C) 2020-2022 Intel Corporation
|
||||
// Copyright (C) 2023 CVAT.ai Corporation
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
module.exports = {
|
||||
ignorePatterns: [
|
||||
'.eslintrc.js',
|
||||
'webpack.config.js',
|
||||
'src/3rdparty/**',
|
||||
'node_modules/**',
|
||||
'dist/**',
|
||||
@@ -1,12 +1,11 @@
|
||||
{
|
||||
"name": "cvat-data",
|
||||
"type": "module",
|
||||
"version": "2.0.0",
|
||||
"description": "",
|
||||
"main": "src/ts/cvat-data.ts",
|
||||
"scripts": {
|
||||
"patch": "cd src/ts && patch --dry-run --forward -p0 < 3rdparty_patch.diff >> /dev/null && patch -p0 < 3rdparty_patch.diff; true",
|
||||
"build": "yarn run patch; webpack --config ./webpack.config.js",
|
||||
"server": "yarn run patch; nodemon --watch config --exec 'webpack-dev-server --config ./webpack.config.js --mode=development --open'",
|
||||
"build": "webpack --config ./webpack.config.cjs",
|
||||
"type-check": "tsc --noEmit",
|
||||
"type-check:watch": "yarn run type-check --watch"
|
||||
},
|
||||
@@ -14,7 +13,7 @@
|
||||
"license": "MIT",
|
||||
"browserslist": [
|
||||
"Chrome >= 63",
|
||||
"Firefox > 58",
|
||||
"Firefox > 102",
|
||||
"not IE 11",
|
||||
"> 2%"
|
||||
],
|
||||
|
||||
Vendored
-888
File diff suppressed because one or more lines are too long
+1436
-860
File diff suppressed because one or more lines are too long
Vendored
+3
-26
@@ -1,7 +1,7 @@
|
||||
## 3rdparty components
|
||||
|
||||
These files are from the [Broadway.js](https://github.com/mbebenita/Broadway) repository:
|
||||
- Decoder.js
|
||||
- Decoder.worker.js
|
||||
- mp4.js
|
||||
- avc.wasm
|
||||
|
||||
@@ -16,7 +16,7 @@ For example there are issues with canvas using (webpack doesn't work with binary
|
||||
So, we have solved to write patch file for this library.
|
||||
It modifies source code a little to support our scenario of using.
|
||||
|
||||
### How to build awc.wasm and Decoder.js
|
||||
### How to build awc.wasm and Decoder.cjs
|
||||
1. Clone Emscripten SDK, install and activate the latest fastcomp SDK:
|
||||
```sh
|
||||
git clone https://github.com/emscripten-core/emsdk.git && cd emsdk
|
||||
@@ -58,31 +58,8 @@ It modifies source code a little to support our scenario of using.
|
||||
cd ..
|
||||
```
|
||||
```sh
|
||||
cp Player/avc.wasm Player/Decoder.js Player/mp4.js <CVAT_FOLDER>/cvat-data/src/
|
||||
cp Player/avc.wasm Player/Decoder.cjs Player/mp4.js <CVAT_FOLDER>/cvat-data/src/
|
||||
```
|
||||
```sh
|
||||
js/3rdparty
|
||||
```
|
||||
|
||||
### How work with a patch file
|
||||
```bash
|
||||
# from cvat-data/src/js
|
||||
cp -r 3rdparty 3rdparty_edited
|
||||
# change 3rdparty edited as we need
|
||||
diff -u 3rdparty 3rdparty_edited/ > 3rdparty_patch.diff
|
||||
patch -p0 < 3rdparty_patch.diff # apply patch from cvat-data/src/js
|
||||
```
|
||||
|
||||
Also these files have been added to ignore for git in all future revisions:
|
||||
```bash
|
||||
# from cvat-data dir
|
||||
git update-index --skip-worktree src/js/3rdparty/*.js
|
||||
```
|
||||
|
||||
This behaviour can be reset with:
|
||||
```bash
|
||||
# from cvat-data dir
|
||||
git update-index --no-skip-worktree src/js/3rdparty/*.js
|
||||
```
|
||||
|
||||
[Stackoverflow issue](https://stackoverflow.com/questions/4348590/how-can-i-make-git-ignore-future-revisions-to-a-file)
|
||||
|
||||
Vendored
+2
-11
@@ -1,15 +1,9 @@
|
||||
module.exports = (function(){
|
||||
|
||||
'use strict';
|
||||
|
||||
|
||||
function assert(condition, message) {
|
||||
if (!condition) {
|
||||
error(message);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Represents a 2-dimensional size value.
|
||||
*/
|
||||
@@ -964,14 +958,11 @@ var Broadway = (function broadway() {
|
||||
return constructor;
|
||||
})();
|
||||
|
||||
|
||||
return {
|
||||
export {
|
||||
Size,
|
||||
Track,
|
||||
MP4Reader,
|
||||
MP4Player,
|
||||
Bytestream,
|
||||
Broadway,
|
||||
}
|
||||
|
||||
})();
|
||||
};
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -5,8 +5,6 @@
|
||||
|
||||
import { Mutex } from 'async-mutex';
|
||||
import { MP4Reader, Bytestream } from './3rdparty/mp4';
|
||||
import ZipDecoder from './unzip_imgs.worker';
|
||||
import H264Decoder from './3rdparty/Decoder.worker';
|
||||
|
||||
export class RequestOutdatedError extends Error {}
|
||||
|
||||
@@ -28,7 +26,9 @@ export enum DimensionType {
|
||||
export function decodeContextImages(
|
||||
block: any, start: number, end: number,
|
||||
): Promise<Record<string, ImageBitmap>> {
|
||||
const decodeZipWorker = ((decodeContextImages as any).zipWorker || new (ZipDecoder as any)()) as Worker;
|
||||
const decodeZipWorker = (decodeContextImages as any).zipWorker || new Worker(
|
||||
new URL('./unzip_imgs.worker', import.meta.url),
|
||||
);
|
||||
(decodeContextImages as any).zipWorker = decodeZipWorker;
|
||||
return new Promise((resolve, reject) => {
|
||||
decodeContextImages.mutex.acquire().then((release) => {
|
||||
@@ -221,7 +221,9 @@ export class FrameDecoder {
|
||||
this.requestedChunkToDecode = null;
|
||||
|
||||
if (this.blockType === BlockType.MP4VIDEO) {
|
||||
const worker = new H264Decoder() as any as Worker;
|
||||
const worker = new Worker(
|
||||
new URL('./3rdparty/Decoder.worker', import.meta.url),
|
||||
);
|
||||
let index = start;
|
||||
|
||||
worker.onmessage = (e) => {
|
||||
@@ -286,7 +288,9 @@ export class FrameDecoder {
|
||||
});
|
||||
}
|
||||
} else {
|
||||
this.zipWorker = this.zipWorker || new (ZipDecoder as any)() as any as Worker;
|
||||
this.zipWorker = this.zipWorker || new Worker(
|
||||
new URL('./unzip_imgs.worker', import.meta.url),
|
||||
);
|
||||
let index = start;
|
||||
|
||||
this.zipWorker.onmessage = async (event) => {
|
||||
|
||||
@@ -3,12 +3,11 @@
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const JSZip = require('jszip');
|
||||
import JSZip from 'jszip';
|
||||
|
||||
onmessage = (e) => {
|
||||
let errored = false;
|
||||
function handleError(error) {
|
||||
function handleError(error): void {
|
||||
try {
|
||||
if (!errored) {
|
||||
postMessage({ error });
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es2020",
|
||||
"target": "ESNext",
|
||||
"allowJs": true,
|
||||
"module": "commonjs",
|
||||
"module": "esnext",
|
||||
"moduleResolution": "node",
|
||||
"esModuleInterop": true,
|
||||
"isolatedModules": true,
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
// Copyright (C) 2020-2022 Intel Corporation
|
||||
// Copyright (C) 2023 CVAT.ai Corporation
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
/* global
|
||||
__dirname:true
|
||||
*/
|
||||
|
||||
const path = require('path');
|
||||
const CopyPlugin = require('copy-webpack-plugin');
|
||||
|
||||
@@ -41,32 +38,18 @@ const cvatData = {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
test: /\.worker\.js$/,
|
||||
exclude: /3rdparty/,
|
||||
use: {
|
||||
loader: 'worker-loader',
|
||||
options: {
|
||||
publicPath: '/',
|
||||
filename: '[name].[contenthash].js',
|
||||
esModule: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
test: /3rdparty\/.*\.worker\.js$/,
|
||||
use: {
|
||||
loader: 'worker-loader',
|
||||
options: {
|
||||
publicPath: '/3rdparty/',
|
||||
filename: '3rdparty/[name].[contenthash].js',
|
||||
esModule: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
plugins: [new CopyPlugin({ patterns: ['./src/ts/3rdparty/avc.wasm'] })],
|
||||
plugins: [
|
||||
new CopyPlugin({
|
||||
patterns: [
|
||||
{
|
||||
from: '../cvat-data/src/ts/3rdparty/avc.wasm',
|
||||
to: 'assets/3rdparty/',
|
||||
},
|
||||
],
|
||||
}),
|
||||
],
|
||||
};
|
||||
|
||||
module.exports = cvatData;
|
||||
@@ -3,7 +3,7 @@
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
const globalConfig = require('../.eslintrc.js');
|
||||
const globalConfig = require('../.eslintrc.cjs');
|
||||
const { join } = require('path');
|
||||
|
||||
module.exports = {
|
||||
@@ -12,25 +12,26 @@ module.exports = {
|
||||
tsconfigRootDir: __dirname,
|
||||
},
|
||||
ignorePatterns: [
|
||||
'.eslintrc.js',
|
||||
'.eslintrc.cjs',
|
||||
'webpack.config.js',
|
||||
'src/assets/opencv*.js',
|
||||
'node_modules/**',
|
||||
'dist/**',
|
||||
],
|
||||
extends: ['airbnb-typescript'],
|
||||
extends: ['airbnb', 'airbnb-typescript'],
|
||||
rules: {
|
||||
...globalConfig.rules, // need to import rules again because they've been redefined by "airbnb-typescript"
|
||||
|
||||
'jsx-a11y/control-has-associated-label': 0, // new rule, conflicts with existing code
|
||||
'react/no-unused-class-component-methods': 0, // new rule, gives often false positives
|
||||
'react/no-unstable-nested-components': 0, // new rule, we have a lot of code conflicting with this
|
||||
'react/no-did-update-set-state': 0, // https://github.com/airbnb/javascript/issues/1875
|
||||
'react/require-default-props': 'off',
|
||||
'react/no-unused-prop-types': 'off',
|
||||
'react/no-array-index-key': 'off',
|
||||
'react/static-property-placement': ['error', 'static public field'],
|
||||
'react/jsx-indent': ['warn', 4],
|
||||
'react/jsx-indent-props': ['warn', 4],
|
||||
'react/jsx-props-no-spreading': 0,
|
||||
'jsx-quotes': ['error', 'prefer-single'],
|
||||
'react/static-property-placement': ['warn', 'static public field'],
|
||||
'import/no-extraneous-dependencies': [
|
||||
'error',
|
||||
{
|
||||
Vendored
-1
@@ -6,4 +6,3 @@
|
||||
import 'redux-thunk/extend-redux';
|
||||
|
||||
declare module '*.svg';
|
||||
declare module 'cvat-core/src/api';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "cvat-ui",
|
||||
"version": "1.59.1",
|
||||
"version": "1.60.0",
|
||||
"description": "CVAT single-page application",
|
||||
"main": "src/index.tsx",
|
||||
"scripts": {
|
||||
@@ -13,7 +13,7 @@
|
||||
},
|
||||
"browserslist": [
|
||||
"Chrome >= 63",
|
||||
"Firefox > 58",
|
||||
"Firefox > 102",
|
||||
"not IE 11",
|
||||
"> 2%"
|
||||
],
|
||||
|
||||
@@ -44,14 +44,12 @@ function Issues(props: Props): JSX.Element {
|
||||
}, []);
|
||||
|
||||
const bottomElement = (
|
||||
<>
|
||||
<Text type='secondary'>
|
||||
Resolved:
|
||||
{' '}
|
||||
{clampValue(resolvedIssues)}
|
||||
{resolvedIssues ? ` (${percent(resolvedIssues, issuesCount)})` : ''}
|
||||
</Text>
|
||||
</>
|
||||
<Text type='secondary'>
|
||||
Resolved:
|
||||
{' '}
|
||||
{clampValue(resolvedIssues)}
|
||||
{resolvedIssues ? ` (${percent(resolvedIssues, issuesCount)})` : ''}
|
||||
</Text>
|
||||
);
|
||||
|
||||
return (
|
||||
|
||||
@@ -122,15 +122,13 @@ const fitLayout = (type: DimensionType, layoutConfig: ItemLayout[]): ItemLayout[
|
||||
y: config.CANVAS_WORKSPACE_ROWS,
|
||||
w: Math.ceil(widthAvail / 3),
|
||||
h: helpfulCanvasViewHeight,
|
||||
},
|
||||
{
|
||||
}, {
|
||||
...side,
|
||||
x: Math.ceil(widthAvail / 3),
|
||||
y: config.CANVAS_WORKSPACE_ROWS,
|
||||
w: Math.ceil(widthAvail / 3),
|
||||
h: helpfulCanvasViewHeight,
|
||||
},
|
||||
{
|
||||
}, {
|
||||
...front,
|
||||
x: Math.ceil(widthAvail / 3) * 2,
|
||||
y: config.CANVAS_WORKSPACE_ROWS,
|
||||
|
||||
@@ -613,7 +613,7 @@ class CanvasWrapperComponent extends React.PureComponent<Props> {
|
||||
private onCanvasMessage = (event: CustomEvent<{ messages: CanvasHint[] | null, topic: string }>): void => {
|
||||
const { messages, topic } = event.detail;
|
||||
this.canvasTipsRef.current?.update(messages, topic);
|
||||
}
|
||||
};
|
||||
|
||||
private onCanvasShapeDrawn = (event: any): void => {
|
||||
const {
|
||||
|
||||
+109
-107
@@ -4,9 +4,7 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import './styles.scss';
|
||||
import React, {
|
||||
ReactElement, useEffect, useRef,
|
||||
} from 'react';
|
||||
import React, { useEffect, useRef } from 'react';
|
||||
import { connect, useSelector } from 'react-redux';
|
||||
import {
|
||||
ArrowDownOutlined, ArrowLeftOutlined, ArrowRightOutlined, ArrowUpOutlined,
|
||||
@@ -211,110 +209,114 @@ export const PerspectiveViewComponent = React.memo(
|
||||
ZOOM_OUT: () => {},
|
||||
};
|
||||
|
||||
const ArrowGroup = (): ReactElement => (
|
||||
<div className='cvat-canvas3d-perspective-arrow-directions'>
|
||||
<div>
|
||||
<CVATTooltip title={normalizedKeyMap.TILT_UP} placement='topRight'>
|
||||
<Button
|
||||
size='small'
|
||||
onClick={() => screenKeyControl(CameraAction.TILT_UP, false, true)}
|
||||
className='cvat-canvas3d-perspective-arrow-directions-icons-up'
|
||||
>
|
||||
<ArrowUpOutlined className='cvat-canvas3d-perspective-arrow-directions-icons-color' />
|
||||
</Button>
|
||||
</CVATTooltip>
|
||||
function ArrowGroup(): JSX.Element {
|
||||
return (
|
||||
<div className='cvat-canvas3d-perspective-arrow-directions'>
|
||||
<div>
|
||||
<CVATTooltip title={normalizedKeyMap.TILT_UP} placement='topRight'>
|
||||
<Button
|
||||
size='small'
|
||||
onClick={() => screenKeyControl(CameraAction.TILT_UP, false, true)}
|
||||
className='cvat-canvas3d-perspective-arrow-directions-icons-up'
|
||||
>
|
||||
<ArrowUpOutlined className='cvat-canvas3d-perspective-arrow-directions-icons-color' />
|
||||
</Button>
|
||||
</CVATTooltip>
|
||||
</div>
|
||||
<div>
|
||||
<CVATTooltip title={normalizedKeyMap.ROTATE_LEFT} placement='topRight'>
|
||||
<Button
|
||||
size='small'
|
||||
onClick={() => screenKeyControl(CameraAction.ROTATE_LEFT, false, true)}
|
||||
className='cvat-canvas3d-perspective-arrow-directions-icons-left'
|
||||
>
|
||||
<ArrowLeftOutlined className='cvat-canvas3d-perspective-arrow-directions-icons-color' />
|
||||
</Button>
|
||||
</CVATTooltip>
|
||||
<CVATTooltip title={normalizedKeyMap.TILT_DOWN} placement='topRight'>
|
||||
<Button
|
||||
size='small'
|
||||
onClick={() => screenKeyControl(CameraAction.TILT_DOWN, false, true)}
|
||||
className='cvat-canvas3d-perspective-arrow-directions-icons-bottom'
|
||||
>
|
||||
<ArrowDownOutlined className='cvat-canvas3d-perspective-arrow-directions-icons-color' />
|
||||
</Button>
|
||||
</CVATTooltip>
|
||||
<CVATTooltip title={normalizedKeyMap.ROTATE_RIGHT} placement='topRight'>
|
||||
<Button
|
||||
size='small'
|
||||
onClick={() => screenKeyControl(CameraAction.ROTATE_RIGHT, false, true)}
|
||||
className='cvat-canvas3d-perspective-arrow-directions-icons-right'
|
||||
>
|
||||
<ArrowRightOutlined className='cvat-canvas3d-perspective-arrow-directions-icons-color' />
|
||||
</Button>
|
||||
</CVATTooltip>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<CVATTooltip title={normalizedKeyMap.ROTATE_LEFT} placement='topRight'>
|
||||
<Button
|
||||
size='small'
|
||||
onClick={() => screenKeyControl(CameraAction.ROTATE_LEFT, false, true)}
|
||||
className='cvat-canvas3d-perspective-arrow-directions-icons-left'
|
||||
>
|
||||
<ArrowLeftOutlined className='cvat-canvas3d-perspective-arrow-directions-icons-color' />
|
||||
</Button>
|
||||
</CVATTooltip>
|
||||
<CVATTooltip title={normalizedKeyMap.TILT_DOWN} placement='topRight'>
|
||||
<Button
|
||||
size='small'
|
||||
onClick={() => screenKeyControl(CameraAction.TILT_DOWN, false, true)}
|
||||
className='cvat-canvas3d-perspective-arrow-directions-icons-bottom'
|
||||
>
|
||||
<ArrowDownOutlined className='cvat-canvas3d-perspective-arrow-directions-icons-color' />
|
||||
</Button>
|
||||
</CVATTooltip>
|
||||
<CVATTooltip title={normalizedKeyMap.ROTATE_RIGHT} placement='topRight'>
|
||||
<Button
|
||||
size='small'
|
||||
onClick={() => screenKeyControl(CameraAction.ROTATE_RIGHT, false, true)}
|
||||
className='cvat-canvas3d-perspective-arrow-directions-icons-right'
|
||||
>
|
||||
<ArrowRightOutlined className='cvat-canvas3d-perspective-arrow-directions-icons-color' />
|
||||
</Button>
|
||||
</CVATTooltip>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
);
|
||||
}
|
||||
|
||||
const ControlGroup = (): ReactElement => (
|
||||
<span className='cvat-canvas3d-perspective-directions'>
|
||||
<CVATTooltip title={normalizedKeyMap.MOVE_UP} placement='topLeft'>
|
||||
<Button
|
||||
size='small'
|
||||
onClick={() => screenKeyControl(CameraAction.MOVE_UP, true, false)}
|
||||
className='cvat-canvas3d-perspective-directions-icon cvat-canvas3d-perspective-shift-down'
|
||||
>
|
||||
U
|
||||
</Button>
|
||||
</CVATTooltip>
|
||||
<CVATTooltip title={normalizedKeyMap.ZOOM_IN} placement='topLeft'>
|
||||
<Button
|
||||
size='small'
|
||||
onClick={() => screenKeyControl(CameraAction.ZOOM_IN, true, false)}
|
||||
className='cvat-canvas3d-perspective-directions-icon cvat-canvas3d-perspective-zoom-in'
|
||||
>
|
||||
I
|
||||
</Button>
|
||||
</CVATTooltip>
|
||||
<CVATTooltip title={normalizedKeyMap.MOVE_DOWN} placement='topLeft'>
|
||||
<Button
|
||||
size='small'
|
||||
onClick={() => screenKeyControl(CameraAction.MOVE_DOWN, true, false)}
|
||||
className='cvat-canvas3d-perspective-directions-icon cvat-canvas3d-perspective-shift-up'
|
||||
>
|
||||
O
|
||||
</Button>
|
||||
</CVATTooltip>
|
||||
<br />
|
||||
<CVATTooltip title={normalizedKeyMap.MOVE_LEFT} placement='topLeft'>
|
||||
<Button
|
||||
size='small'
|
||||
onClick={() => screenKeyControl(CameraAction.MOVE_LEFT, true, false)}
|
||||
className='cvat-canvas3d-perspective-directions-icon cvat-canvas3d-perspective-shift-left'
|
||||
>
|
||||
J
|
||||
</Button>
|
||||
</CVATTooltip>
|
||||
<CVATTooltip title={normalizedKeyMap.ZOOM_OUT} placement='topLeft'>
|
||||
<Button
|
||||
size='small'
|
||||
onClick={() => screenKeyControl(CameraAction.ZOOM_OUT, true, false)}
|
||||
className='cvat-canvas3d-perspective-directions-icon cvat-canvas3d-perspective-zoom-out'
|
||||
>
|
||||
K
|
||||
</Button>
|
||||
</CVATTooltip>
|
||||
<CVATTooltip title={normalizedKeyMap.MOVE_RIGHT} placement='topLeft'>
|
||||
<Button
|
||||
size='small'
|
||||
onClick={() => screenKeyControl(CameraAction.MOVE_RIGHT, true, false)}
|
||||
className='cvat-canvas3d-perspective-directions-icon cvat-canvas3d-perspective-shift-right'
|
||||
>
|
||||
L
|
||||
</Button>
|
||||
</CVATTooltip>
|
||||
</span>
|
||||
);
|
||||
function ControlGroup(): JSX.Element {
|
||||
return (
|
||||
<span className='cvat-canvas3d-perspective-directions'>
|
||||
<CVATTooltip title={normalizedKeyMap.MOVE_UP} placement='topLeft'>
|
||||
<Button
|
||||
size='small'
|
||||
onClick={() => screenKeyControl(CameraAction.MOVE_UP, true, false)}
|
||||
className='cvat-canvas3d-perspective-directions-icon cvat-canvas3d-perspective-shift-down'
|
||||
>
|
||||
U
|
||||
</Button>
|
||||
</CVATTooltip>
|
||||
<CVATTooltip title={normalizedKeyMap.ZOOM_IN} placement='topLeft'>
|
||||
<Button
|
||||
size='small'
|
||||
onClick={() => screenKeyControl(CameraAction.ZOOM_IN, true, false)}
|
||||
className='cvat-canvas3d-perspective-directions-icon cvat-canvas3d-perspective-zoom-in'
|
||||
>
|
||||
I
|
||||
</Button>
|
||||
</CVATTooltip>
|
||||
<CVATTooltip title={normalizedKeyMap.MOVE_DOWN} placement='topLeft'>
|
||||
<Button
|
||||
size='small'
|
||||
onClick={() => screenKeyControl(CameraAction.MOVE_DOWN, true, false)}
|
||||
className='cvat-canvas3d-perspective-directions-icon cvat-canvas3d-perspective-shift-up'
|
||||
>
|
||||
O
|
||||
</Button>
|
||||
</CVATTooltip>
|
||||
<br />
|
||||
<CVATTooltip title={normalizedKeyMap.MOVE_LEFT} placement='topLeft'>
|
||||
<Button
|
||||
size='small'
|
||||
onClick={() => screenKeyControl(CameraAction.MOVE_LEFT, true, false)}
|
||||
className='cvat-canvas3d-perspective-directions-icon cvat-canvas3d-perspective-shift-left'
|
||||
>
|
||||
J
|
||||
</Button>
|
||||
</CVATTooltip>
|
||||
<CVATTooltip title={normalizedKeyMap.ZOOM_OUT} placement='topLeft'>
|
||||
<Button
|
||||
size='small'
|
||||
onClick={() => screenKeyControl(CameraAction.ZOOM_OUT, true, false)}
|
||||
className='cvat-canvas3d-perspective-directions-icon cvat-canvas3d-perspective-zoom-out'
|
||||
>
|
||||
K
|
||||
</Button>
|
||||
</CVATTooltip>
|
||||
<CVATTooltip title={normalizedKeyMap.MOVE_RIGHT} placement='topLeft'>
|
||||
<Button
|
||||
size='small'
|
||||
onClick={() => screenKeyControl(CameraAction.MOVE_RIGHT, true, false)}
|
||||
className='cvat-canvas3d-perspective-directions-icon cvat-canvas3d-perspective-shift-right'
|
||||
>
|
||||
L
|
||||
</Button>
|
||||
</CVATTooltip>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (ref.current) {
|
||||
@@ -412,7 +414,7 @@ export const FrontViewComponent = React.memo(
|
||||
},
|
||||
);
|
||||
|
||||
const Canvas3DWrapperComponent = React.memo((props: Props): ReactElement => {
|
||||
const Canvas3DWrapperComponent = React.memo((props: Props): null => {
|
||||
const animateId = useRef(0);
|
||||
|
||||
const {
|
||||
@@ -639,7 +641,7 @@ const Canvas3DWrapperComponent = React.memo((props: Props): ReactElement => {
|
||||
};
|
||||
}, [frameData, annotations, activeLabelID, contextMenuVisibility, activeObjectType]);
|
||||
|
||||
return <></>;
|
||||
return null;
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(Canvas3DWrapperComponent);
|
||||
|
||||
+1
-1
@@ -56,7 +56,7 @@ export default function ControlVisibilityObserver<P = {}>(
|
||||
): React.FunctionComponent<P> {
|
||||
let visibilityHeightThreshold = 0; // minimum value of height when element can be pushed to main panel
|
||||
|
||||
return (props: P): JSX.Element | null => {
|
||||
return function (props: P): JSX.Element | null {
|
||||
const ref = useRef<HTMLDivElement>(null);
|
||||
const [visible, setVisible] = useState(true);
|
||||
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@ interface OwnProps {
|
||||
}
|
||||
|
||||
export default function withVisibilityHandling(WrappedComponent: typeof Popover, popoverType: string) {
|
||||
return (props: OwnProps & PopoverProps): JSX.Element => {
|
||||
return function (props: OwnProps & PopoverProps): JSX.Element {
|
||||
const [visible, setVisible] = useState<boolean>(false);
|
||||
const { overlayClassName, onVisibleChange, ...rest } = props;
|
||||
const overlayClassNames = typeof overlayClassName === 'string' ? overlayClassName.split(/\s+/) : [];
|
||||
|
||||
+23
-25
@@ -737,33 +737,31 @@ class OpenCVControlComponent extends React.PureComponent<Props & DispatchToProps
|
||||
</Tabs.TabPane>
|
||||
</Tabs>
|
||||
) : (
|
||||
<>
|
||||
<Row justify='start' align='middle'>
|
||||
<Row justify='start' align='middle'>
|
||||
<Col>
|
||||
{
|
||||
initializationProgress >= 0 ?
|
||||
<Text>OpenCV is loading</Text> : (
|
||||
<Button
|
||||
className='cvat-opencv-initialization-button'
|
||||
onClick={() => { this.initializeOpenCV(); }}
|
||||
>
|
||||
Reload OpenCV
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
</Col>
|
||||
{initializationProgress >= 0 && (
|
||||
<Col>
|
||||
{
|
||||
initializationProgress >= 0 ?
|
||||
<Text>OpenCV is loading</Text> : (
|
||||
<Button
|
||||
className='cvat-opencv-initialization-button'
|
||||
onClick={() => { this.initializeOpenCV(); }}
|
||||
>
|
||||
Reload OpenCV
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
<Progress
|
||||
width={8 * 5}
|
||||
percent={initializationProgress}
|
||||
type='circle'
|
||||
status={initializationError ? 'exception' : undefined}
|
||||
/>
|
||||
</Col>
|
||||
{initializationProgress >= 0 && (
|
||||
<Col>
|
||||
<Progress
|
||||
width={8 * 5}
|
||||
percent={initializationProgress}
|
||||
type='circle'
|
||||
status={initializationError ? 'exception' : undefined}
|
||||
/>
|
||||
</Col>
|
||||
)}
|
||||
</Row>
|
||||
</>
|
||||
)}
|
||||
</Row>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
||||
+11
-10
@@ -374,8 +374,11 @@ export class ToolsControlComponent extends React.PureComponent<Props, State> {
|
||||
try {
|
||||
// run server request
|
||||
this.setState({ fetching: true });
|
||||
const response = await core.lambda.call(jobInstance.taskId, interactor,
|
||||
{ ...data, job: jobInstance.id });
|
||||
const response = await core.lambda.call(
|
||||
jobInstance.taskId,
|
||||
interactor,
|
||||
{ ...data, job: jobInstance.id },
|
||||
);
|
||||
|
||||
// if only mask presented, let's receive points
|
||||
if (response.mask && !response.points) {
|
||||
@@ -1405,14 +1408,12 @@ export class ToolsControlComponent extends React.PureComponent<Props, State> {
|
||||
const showDetectionContent = fetching && mode === 'detection';
|
||||
|
||||
const interactionContent: JSX.Element | null = showInteractionContent ? (
|
||||
<>
|
||||
<ApproximationAccuracy
|
||||
approxPolyAccuracy={approxPolyAccuracy}
|
||||
onChange={(value: number) => {
|
||||
this.setState({ approxPolyAccuracy: value });
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
<ApproximationAccuracy
|
||||
approxPolyAccuracy={approxPolyAccuracy}
|
||||
onChange={(value: number) => {
|
||||
this.setState({ approxPolyAccuracy: value });
|
||||
}}
|
||||
/>
|
||||
) : null;
|
||||
|
||||
const detectionContent: JSX.Element | null = showDetectionContent ? (
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Copyright (C) 2022 Intel Corporation
|
||||
// Copyright (C) CVAT.ai corp
|
||||
// Copyright (C) 2023 CVAT.ai Corporation
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
@@ -15,7 +15,7 @@ import { removeObjectAsync, removeObject as removeObjectAction } from 'actions/a
|
||||
export default function RemoveConfirmComponent(): JSX.Element | null {
|
||||
const [visible, setVisible] = useState(false);
|
||||
const [title, setTitle] = useState('');
|
||||
const [description, setDescription] = useState<JSX.Element>(<></>);
|
||||
const [description, setDescription] = useState<string | JSX.Element>('');
|
||||
const objectState = useSelector((state: CombinedState) => state.annotation.remove.objectState);
|
||||
const force = useSelector((state: CombinedState) => state.annotation.remove.force);
|
||||
const jobInstance = useSelector((state: CombinedState) => state.annotation.job.instance);
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
// Copyright (C) 2020-2022 Intel Corporation
|
||||
// Copyright (C) 2022 CVAT.ai Corporation
|
||||
// Copyright (C) 2022-2023 CVAT.ai Corporation
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
@@ -34,7 +34,7 @@ const defaultShortcutLabelMap = {
|
||||
0: '',
|
||||
} as ShortcutLabelMap;
|
||||
|
||||
const ShortcutsSelect = (props: Props): JSX.Element => {
|
||||
function ShortcutsSelect(props: Props): JSX.Element {
|
||||
const { labels, onShortcutPress } = props;
|
||||
const [shortcutLabelMap, setShortcutLabelMap] = useState(defaultShortcutLabelMap);
|
||||
|
||||
@@ -115,6 +115,6 @@ const ShortcutsSelect = (props: Props): JSX.Element => {
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
export default ShortcutsSelect;
|
||||
|
||||
@@ -25,7 +25,7 @@ interface Props {
|
||||
jobInstance: any;
|
||||
onClickMenu(params: MenuInfo): void;
|
||||
stopFrame: number;
|
||||
removeAnnotations(startnumber: number, endnumber: number, delTrackKeyframesOnly:boolean): void;
|
||||
removeAnnotations(startnumber: number | null, endnumber: number | null, delTrackKeyframesOnly: boolean): void;
|
||||
setForceExitAnnotationFlag(forceExit: boolean): void;
|
||||
saveAnnotations(jobInstance: any, afterSave?: () => void): void;
|
||||
}
|
||||
@@ -33,7 +33,7 @@ interface Props {
|
||||
export enum Actions {
|
||||
LOAD_JOB_ANNO = 'load_job_anno',
|
||||
EXPORT_JOB_DATASET = 'export_job_dataset',
|
||||
REMOVE_ANNO = 'remove_anno',
|
||||
REMOVE_ANNOTATIONS = 'remove_annotations',
|
||||
OPEN_TASK = 'open_task',
|
||||
FINISH_JOB = 'finish_job',
|
||||
RENEW_JOB = 'renew_job',
|
||||
@@ -84,9 +84,9 @@ function AnnotationMenuComponent(props: Props & RouteComponentProps): JSX.Elemen
|
||||
}
|
||||
}
|
||||
|
||||
if (params.key === Actions.REMOVE_ANNO) {
|
||||
let removeFrom: number;
|
||||
let removeUpTo: number;
|
||||
if (params.key === Actions.REMOVE_ANNOTATIONS) {
|
||||
let removeFrom: number | null;
|
||||
let removeUpTo: number | null;
|
||||
let removeOnlyKeyframes = false;
|
||||
const { Panel } = Collapse;
|
||||
Modal.confirm({
|
||||
@@ -111,7 +111,9 @@ function AnnotationMenuComponent(props: Props & RouteComponentProps): JSX.Elemen
|
||||
<InputNumber
|
||||
min={0}
|
||||
max={stopFrame}
|
||||
onChange={(value) => { removeUpTo = value; }}
|
||||
onChange={(value) => {
|
||||
removeUpTo = value;
|
||||
}}
|
||||
/>
|
||||
<CVATTooltip title='Applicable only for annotations in range'>
|
||||
<br />
|
||||
@@ -185,7 +187,7 @@ function AnnotationMenuComponent(props: Props & RouteComponentProps): JSX.Elemen
|
||||
<Menu onClick={(params: MenuInfo) => onClickMenuWrapper(params)} className='cvat-annotation-menu' selectable={false}>
|
||||
<Menu.Item key={Actions.LOAD_JOB_ANNO}>Upload annotations</Menu.Item>
|
||||
<Menu.Item key={Actions.EXPORT_JOB_DATASET}>Export job dataset</Menu.Item>
|
||||
<Menu.Item key={Actions.REMOVE_ANNO}>Remove annotations</Menu.Item>
|
||||
<Menu.Item key={Actions.REMOVE_ANNOTATIONS}>Remove annotations</Menu.Item>
|
||||
<Menu.Item key={Actions.OPEN_TASK}>
|
||||
<a
|
||||
href={`/tasks/${taskID}`}
|
||||
|
||||
@@ -71,16 +71,14 @@ function RightGroup(props: Props): JSX.Element {
|
||||
width: window.screen.availWidth - PADDING,
|
||||
className: 'cvat-annotation-view-markdown-guide-modal',
|
||||
content: (
|
||||
<>
|
||||
<MDEditor
|
||||
visibleDragbar={false}
|
||||
data-color-mode='light'
|
||||
height={window.screen.availHeight - PADDING}
|
||||
preview='preview'
|
||||
hideToolbar
|
||||
value={guide.markdown}
|
||||
/>
|
||||
</>
|
||||
<MDEditor
|
||||
visibleDragbar={false}
|
||||
data-color-mode='light'
|
||||
height={window.screen.availHeight - PADDING}
|
||||
preview='preview'
|
||||
hideToolbar
|
||||
value={guide.markdown}
|
||||
/>
|
||||
),
|
||||
});
|
||||
} catch (error: any) {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// Copyright (C) 2021-2022 Intel Corporation
|
||||
// Copyright (C) 2023 CVAT.ai Corporation
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
@@ -321,7 +322,7 @@ export default function CreateCloudStorageForm(props: Props): JSX.Element {
|
||||
className: 'cvat-cloud-storage-form-item',
|
||||
};
|
||||
|
||||
const credentialsBlok = (): JSX.Element => {
|
||||
const credentialsBlok = (): JSX.Element | null => {
|
||||
const internalCommonProps = {
|
||||
...commonProps,
|
||||
labelCol: { span: 8, offset: 2 },
|
||||
@@ -404,40 +405,36 @@ export default function CreateCloudStorageForm(props: Props): JSX.Element {
|
||||
|
||||
if (providerType === ProviderType.AZURE_CONTAINER && credentialsType === CredentialsType.ANONYMOUS_ACCESS) {
|
||||
return (
|
||||
<>
|
||||
<Form.Item
|
||||
label='Account name'
|
||||
name='account_name'
|
||||
rules={[{ required: true, message: 'Please, specify your account name' }]}
|
||||
{...internalCommonProps}
|
||||
>
|
||||
<Input.Password
|
||||
minLength={3}
|
||||
maxLength={24}
|
||||
visibilityToggle={accountNameVisibility}
|
||||
onChange={() => setAccountNameVisibility(true)}
|
||||
/>
|
||||
</Form.Item>
|
||||
</>
|
||||
<Form.Item
|
||||
label='Account name'
|
||||
name='account_name'
|
||||
rules={[{ required: true, message: 'Please, specify your account name' }]}
|
||||
{...internalCommonProps}
|
||||
>
|
||||
<Input.Password
|
||||
minLength={3}
|
||||
maxLength={24}
|
||||
visibilityToggle={accountNameVisibility}
|
||||
onChange={() => setAccountNameVisibility(true)}
|
||||
/>
|
||||
</Form.Item>
|
||||
);
|
||||
}
|
||||
|
||||
if (providerType === ProviderType.AZURE_CONTAINER && credentialsType === CredentialsType.CONNECTION_STRING) {
|
||||
return (
|
||||
<>
|
||||
<Form.Item
|
||||
label='Connection string'
|
||||
name='connection_string'
|
||||
rules={[{ required: true, message: 'Please, specify your connection string' }]}
|
||||
{...internalCommonProps}
|
||||
>
|
||||
<Input.Password
|
||||
maxLength={440}
|
||||
visibilityToggle={connectionStringVisibility}
|
||||
onChange={() => setConnectionStringVisibility(true)}
|
||||
/>
|
||||
</Form.Item>
|
||||
</>
|
||||
<Form.Item
|
||||
label='Connection string'
|
||||
name='connection_string'
|
||||
rules={[{ required: true, message: 'Please, specify your connection string' }]}
|
||||
{...internalCommonProps}
|
||||
>
|
||||
<Input.Password
|
||||
maxLength={440}
|
||||
visibilityToggle={connectionStringVisibility}
|
||||
onChange={() => setConnectionStringVisibility(true)}
|
||||
/>
|
||||
</Form.Item>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -489,10 +486,10 @@ export default function CreateCloudStorageForm(props: Props): JSX.Element {
|
||||
);
|
||||
}
|
||||
|
||||
return <></>;
|
||||
return null;
|
||||
};
|
||||
|
||||
const AWSS3Configuration = (): JSX.Element => {
|
||||
const awsS3Configuration = (): JSX.Element => {
|
||||
const internalCommonProps = {
|
||||
...commonProps,
|
||||
labelCol: { offset: 1 },
|
||||
@@ -540,7 +537,7 @@ export default function CreateCloudStorageForm(props: Props): JSX.Element {
|
||||
);
|
||||
};
|
||||
|
||||
const AzureBlobStorageConfiguration = (): JSX.Element => {
|
||||
const azureBlobStorageConfiguration = (): JSX.Element => {
|
||||
const internalCommonProps = {
|
||||
...commonProps,
|
||||
labelCol: { offset: 1 },
|
||||
@@ -577,7 +574,7 @@ export default function CreateCloudStorageForm(props: Props): JSX.Element {
|
||||
);
|
||||
};
|
||||
|
||||
const GoogleCloudStorageConfiguration = (): JSX.Element => {
|
||||
const googleCloudStorageConfiguration = (): JSX.Element => {
|
||||
const internalCommonProps = {
|
||||
...commonProps,
|
||||
labelCol: { span: 6, offset: 1 },
|
||||
@@ -677,9 +674,9 @@ export default function CreateCloudStorageForm(props: Props): JSX.Element {
|
||||
</Select.Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
{providerType === ProviderType.AWS_S3_BUCKET && AWSS3Configuration()}
|
||||
{providerType === ProviderType.AZURE_CONTAINER && AzureBlobStorageConfiguration()}
|
||||
{providerType === ProviderType.GOOGLE_CLOUD_STORAGE && GoogleCloudStorageConfiguration()}
|
||||
{providerType === ProviderType.AWS_S3_BUCKET && awsS3Configuration()}
|
||||
{providerType === ProviderType.AZURE_CONTAINER && azureBlobStorageConfiguration()}
|
||||
{providerType === ProviderType.GOOGLE_CLOUD_STORAGE && googleCloudStorageConfiguration()}
|
||||
<Form.Item
|
||||
label={(
|
||||
<CVATTooltip title='Prefix is used to filter bucket content'>
|
||||
|
||||
@@ -210,24 +210,22 @@ export class FileManager extends React.PureComponent<Props, State> {
|
||||
const { active } = this.state;
|
||||
|
||||
return (
|
||||
<>
|
||||
<Tabs
|
||||
type='card'
|
||||
activeKey={active}
|
||||
tabBarGutter={5}
|
||||
onChange={(activeKey: string): void => {
|
||||
onChangeActiveKey(activeKey);
|
||||
this.setState({
|
||||
active: activeKey as any,
|
||||
});
|
||||
}}
|
||||
>
|
||||
{this.renderLocalSelector()}
|
||||
{this.renderShareSelector()}
|
||||
{this.renderRemoteSelector()}
|
||||
{this.renderCloudStorageSelector()}
|
||||
</Tabs>
|
||||
</>
|
||||
<Tabs
|
||||
type='card'
|
||||
activeKey={active}
|
||||
tabBarGutter={5}
|
||||
onChange={(activeKey: string): void => {
|
||||
onChangeActiveKey(activeKey);
|
||||
this.setState({
|
||||
active: activeKey as any,
|
||||
});
|
||||
}}
|
||||
>
|
||||
{this.renderLocalSelector()}
|
||||
{this.renderShareSelector()}
|
||||
{this.renderRemoteSelector()}
|
||||
{this.renderCloudStorageSelector()}
|
||||
</Tabs>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -297,18 +297,16 @@ function RemoteBrowser(props: Props): JSX.Element {
|
||||
render: (name: string, node: Node) => {
|
||||
if (node.type === 'DIR') {
|
||||
return (
|
||||
<>
|
||||
<Button
|
||||
size='small'
|
||||
type='link'
|
||||
onClick={() => {
|
||||
setCurrentPath([...currentPath, name]);
|
||||
}}
|
||||
>
|
||||
<FolderOutlined />
|
||||
{name}
|
||||
</Button>
|
||||
</>
|
||||
<Button
|
||||
size='small'
|
||||
type='link'
|
||||
onClick={() => {
|
||||
setCurrentPath([...currentPath, name]);
|
||||
}}
|
||||
>
|
||||
<FolderOutlined />
|
||||
{name}
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ interface SettingsModalProps {
|
||||
onClose(): void;
|
||||
}
|
||||
|
||||
const SettingsModal = (props: SettingsModalProps): JSX.Element => {
|
||||
function SettingsModal(props: SettingsModalProps): JSX.Element {
|
||||
const { visible, onClose } = props;
|
||||
|
||||
const settings = useSelector((state: CombinedState) => state.settings);
|
||||
@@ -120,6 +120,6 @@ const SettingsModal = (props: SettingsModalProps): JSX.Element => {
|
||||
</div>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
export default React.memo(SettingsModal);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// Copyright (C) 2022 CVAT.ai Corporation
|
||||
// Copyright (C) 2023 CVAT.ai Corporation
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
@@ -138,42 +139,40 @@ function ImportBackupModal(): JSX.Element {
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Modal
|
||||
title={(
|
||||
<Text strong>
|
||||
{`Create ${instanceType} from backup`}
|
||||
</Text>
|
||||
)}
|
||||
visible={modalVisible}
|
||||
onCancel={closeModal}
|
||||
onOk={() => form.submit()}
|
||||
className='cvat-modal-import-backup'
|
||||
<Modal
|
||||
title={(
|
||||
<Text strong>
|
||||
{`Create ${instanceType} from backup`}
|
||||
</Text>
|
||||
)}
|
||||
visible={modalVisible}
|
||||
onCancel={closeModal}
|
||||
onOk={() => form.submit()}
|
||||
className='cvat-modal-import-backup'
|
||||
>
|
||||
<Form
|
||||
name={`Create ${instanceType} from backup file`}
|
||||
form={form}
|
||||
onFinish={handleImport}
|
||||
layout='vertical'
|
||||
initialValues={initialValues}
|
||||
>
|
||||
<Form
|
||||
name={`Create ${instanceType} from backup file`}
|
||||
form={form}
|
||||
onFinish={handleImport}
|
||||
layout='vertical'
|
||||
initialValues={initialValues}
|
||||
>
|
||||
<SourceStorageField
|
||||
instanceId={null}
|
||||
storageDescription='Specify source storage with backup'
|
||||
locationValue={selectedSourceStorage.location}
|
||||
onChangeStorage={(value: StorageData) => setSelectedSourceStorage(new Storage(value))}
|
||||
onChangeLocationValue={(value: StorageLocation) => {
|
||||
setSelectedSourceStorage({
|
||||
location: value,
|
||||
});
|
||||
}}
|
||||
<SourceStorageField
|
||||
instanceId={null}
|
||||
storageDescription='Specify source storage with backup'
|
||||
locationValue={selectedSourceStorage.location}
|
||||
onChangeStorage={(value: StorageData) => setSelectedSourceStorage(new Storage(value))}
|
||||
onChangeLocationValue={(value: StorageLocation) => {
|
||||
setSelectedSourceStorage({
|
||||
location: value,
|
||||
});
|
||||
}}
|
||||
|
||||
/>
|
||||
{selectedSourceStorage?.location === StorageLocation.CLOUD_STORAGE && renderCustomName()}
|
||||
{selectedSourceStorage?.location === StorageLocation.LOCAL && uploadLocalFile()}
|
||||
</Form>
|
||||
</Modal>
|
||||
</>
|
||||
/>
|
||||
{selectedSourceStorage?.location === StorageLocation.CLOUD_STORAGE && renderCustomName()}
|
||||
{selectedSourceStorage?.location === StorageLocation.LOCAL && uploadLocalFile()}
|
||||
</Form>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Copyright (C) 2021-2022 Intel Corporation
|
||||
// Copyright (C) 2022 CVAT.ai Corporation
|
||||
// Copyright (C) 2022-2023 CVAT.ai Corporation
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
@@ -234,12 +234,15 @@ function ImportDatasetModal(props: StateToProps): JSX.Element {
|
||||
|
||||
const onUpload = (): void => {
|
||||
if (uploadParams && uploadParams.resource) {
|
||||
dispatch(importDatasetAsync(
|
||||
instance, uploadParams.selectedFormat as string,
|
||||
uploadParams.useDefaultSettings, uploadParams.sourceStorage,
|
||||
uploadParams.file || uploadParams.fileName as string,
|
||||
uploadParams.convMaskToPoly,
|
||||
) as any);
|
||||
dispatch(
|
||||
importDatasetAsync(
|
||||
instance,
|
||||
uploadParams.selectedFormat as string,
|
||||
uploadParams.useDefaultSettings,
|
||||
uploadParams.sourceStorage,
|
||||
uploadParams.file || uploadParams.fileName as string,
|
||||
uploadParams.convMaskToPoly,
|
||||
));
|
||||
const resToPrint = uploadParams.resource.charAt(0).toUpperCase() + uploadParams.resource.slice(1);
|
||||
Notification.info({
|
||||
message: `${resToPrint} import started`,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// Copyright (C) 2020-2022 Intel Corporation
|
||||
// Copyright (C) 2023 CVAT.ai Corporation
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
|
||||
@@ -40,7 +40,8 @@ function LoginFormComponent(props: Props): JSX.Element {
|
||||
const [credential, setCredential] = useState('');
|
||||
const pluginsToRender = usePlugins(
|
||||
(state: CombinedState) => state.plugins.components.loginPage.loginForm,
|
||||
props, { credential },
|
||||
props,
|
||||
{ credential },
|
||||
);
|
||||
|
||||
const forgotPasswordLink = (
|
||||
|
||||
@@ -143,16 +143,14 @@ function DetectorRunner(props: Props): JSX.Element {
|
||||
</Col>
|
||||
</Row>
|
||||
{labelsMappingVisible && (
|
||||
<>
|
||||
<Row justify='start' align='middle'>
|
||||
<LabelsMapperComponent
|
||||
key={modelID} // rerender when model switched
|
||||
onUpdateMapping={(_mapping: FullMapping) => setMapping(_mapping)}
|
||||
modelLabels={modelLabels}
|
||||
taskLabels={taskLabels}
|
||||
/>
|
||||
</Row>
|
||||
</>
|
||||
<Row justify='start' align='middle'>
|
||||
<LabelsMapperComponent
|
||||
key={modelID} // rerender when model switched
|
||||
onUpdateMapping={(_mapping: FullMapping) => setMapping(_mapping)}
|
||||
modelLabels={modelLabels}
|
||||
taskLabels={taskLabels}
|
||||
/>
|
||||
</Row>
|
||||
)}
|
||||
{convertMasks2PolygonVisible && (
|
||||
<div className='detector-runner-convert-masks-to-polygons-wrapper'>
|
||||
|
||||
@@ -7,7 +7,7 @@ import { Dispatch, AnyAction } from 'redux';
|
||||
import { useDispatch } from 'react-redux';
|
||||
|
||||
import { PluginsActionTypes, pluginActions } from 'actions/plugins-actions';
|
||||
import { getCore, APIWrapperEnterOptions } from 'cvat-core-wrapper';
|
||||
import { getCore, CVATCore, APIWrapperEnterOptions } from 'cvat-core-wrapper';
|
||||
import { modelsActions } from 'actions/models-actions';
|
||||
|
||||
const core = getCore();
|
||||
@@ -27,7 +27,7 @@ export type ComponentBuilder = ({
|
||||
REGISTER_ACTION: PluginsActionTypes.ADD_UI_COMPONENT,
|
||||
REMOVE_ACTION: PluginsActionTypes.REMOVE_UI_COMPONENT,
|
||||
actionCreators: PluginActionCreators,
|
||||
core: any,
|
||||
core: CVATCore,
|
||||
}) => {
|
||||
name: string;
|
||||
destructor: CallableFunction;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2022 CVAT.ai Corporation
|
||||
// Copyright (C) 2022-2023 CVAT.ai Corporation
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
@@ -77,16 +77,14 @@ export default function StorageWithSwitchField(props: Props): JSX.Element {
|
||||
(!instanceId || !useDefaultStorage) && (
|
||||
<Form.Item
|
||||
label={(
|
||||
<>
|
||||
<Space>
|
||||
{storageLabel}
|
||||
<CVATTooltip title={storageDescription}>
|
||||
<QuestionCircleOutlined
|
||||
style={{ opacity: 0.5 }}
|
||||
/>
|
||||
</CVATTooltip>
|
||||
</Space>
|
||||
</>
|
||||
<Space>
|
||||
{storageLabel}
|
||||
<CVATTooltip title={storageDescription}>
|
||||
<QuestionCircleOutlined
|
||||
style={{ opacity: 0.5 }}
|
||||
/>
|
||||
</CVATTooltip>
|
||||
</Space>
|
||||
)}
|
||||
>
|
||||
<StorageField
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// Copyright (C) 2020-2022 Intel Corporation
|
||||
// Copyright (C) 2023 CVAT.ai Corporation
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
@@ -28,78 +29,76 @@ export default function AutomaticAnnotationProgress(props: Props): JSX.Element |
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Row justify='space-between' align='bottom'>
|
||||
<Col span={22} className='cvat-task-item-progress-wrapper'>
|
||||
<div>
|
||||
<Text
|
||||
type={activeInference.status === RQStatus.QUEUED ? undefined : textType}
|
||||
strong
|
||||
>
|
||||
{((): JSX.Element => {
|
||||
if (activeInference.status === RQStatus.QUEUED) {
|
||||
return (
|
||||
<>
|
||||
Automatic annotation request queued
|
||||
<LoadingOutlined />
|
||||
</>
|
||||
);
|
||||
}
|
||||
<Row justify='space-between' align='bottom'>
|
||||
<Col span={22} className='cvat-task-item-progress-wrapper'>
|
||||
<div>
|
||||
<Text
|
||||
type={activeInference.status === RQStatus.QUEUED ? undefined : textType}
|
||||
strong
|
||||
>
|
||||
{((): JSX.Element => {
|
||||
if (activeInference.status === RQStatus.QUEUED) {
|
||||
return (
|
||||
<>
|
||||
Automatic annotation request queued
|
||||
<LoadingOutlined />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
if (activeInference.status === RQStatus.STARTED) {
|
||||
return (
|
||||
<>
|
||||
Automatic annotation is in progress
|
||||
<LoadingOutlined />
|
||||
</>
|
||||
);
|
||||
}
|
||||
if (activeInference.status === RQStatus.STARTED) {
|
||||
return (
|
||||
<>
|
||||
Automatic annotation is in progress
|
||||
<LoadingOutlined />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
if (activeInference.status === RQStatus.FAILED) {
|
||||
return (<>Automatic annotation failed</>);
|
||||
}
|
||||
if (activeInference.status === RQStatus.FAILED) {
|
||||
return (<>Automatic annotation failed</>);
|
||||
}
|
||||
|
||||
if (activeInference.status === RQStatus.UNKNOWN) {
|
||||
return (<>Unknown status received</>);
|
||||
}
|
||||
if (activeInference.status === RQStatus.UNKNOWN) {
|
||||
return (<>Unknown status received</>);
|
||||
}
|
||||
|
||||
return <>Automatic annotation accomplisted</>;
|
||||
})()}
|
||||
</Text>
|
||||
</div>
|
||||
<Progress
|
||||
percent={Math.floor(activeInference.progress)}
|
||||
strokeColor={{
|
||||
from: '#108ee9',
|
||||
to: '#87d068',
|
||||
}}
|
||||
showInfo={false}
|
||||
strokeWidth={5}
|
||||
size='small'
|
||||
/>
|
||||
</Col>
|
||||
<Col span={1} className='close-auto-annotation-icon'>
|
||||
{ activeInference.status !== RQStatus.FAILED && (
|
||||
<CVATTooltip title='Cancel automatic annotation'>
|
||||
<CloseOutlined
|
||||
onClick={() => {
|
||||
Modal.confirm({
|
||||
title: 'You are going to cancel automatic annotation?',
|
||||
content: 'Reached progress will be lost. Continue?',
|
||||
okButtonProps: {
|
||||
type: 'primary',
|
||||
danger: true,
|
||||
},
|
||||
onOk() {
|
||||
cancelAutoAnnotation();
|
||||
},
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</CVATTooltip>
|
||||
)}
|
||||
</Col>
|
||||
</Row>
|
||||
</>
|
||||
return <>Automatic annotation accomplisted</>;
|
||||
})()}
|
||||
</Text>
|
||||
</div>
|
||||
<Progress
|
||||
percent={Math.floor(activeInference.progress)}
|
||||
strokeColor={{
|
||||
from: '#108ee9',
|
||||
to: '#87d068',
|
||||
}}
|
||||
showInfo={false}
|
||||
strokeWidth={5}
|
||||
size='small'
|
||||
/>
|
||||
</Col>
|
||||
<Col span={1} className='close-auto-annotation-icon'>
|
||||
{ activeInference.status !== RQStatus.FAILED && (
|
||||
<CVATTooltip title='Cancel automatic annotation'>
|
||||
<CloseOutlined
|
||||
onClick={() => {
|
||||
Modal.confirm({
|
||||
title: 'You are going to cancel automatic annotation?',
|
||||
content: 'Reached progress will be lost. Continue?',
|
||||
okButtonProps: {
|
||||
type: 'primary',
|
||||
danger: true,
|
||||
},
|
||||
onOk() {
|
||||
cancelAutoAnnotation();
|
||||
},
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</CVATTooltip>
|
||||
)}
|
||||
</Col>
|
||||
</Row>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -19,13 +19,11 @@ function EmptyWebhooksListComponent(props: Props): JSX.Element {
|
||||
return (
|
||||
<div className='cvat-empty-webhooks-list'>
|
||||
<Empty description={!query.filter && !query.search ? (
|
||||
<>
|
||||
<Row justify='center' align='middle'>
|
||||
<Col>
|
||||
<Text strong>No webhooks created yet ...</Text>
|
||||
</Col>
|
||||
</Row>
|
||||
</>
|
||||
<Row justify='center' align='middle'>
|
||||
<Col>
|
||||
<Text strong>No webhooks created yet ...</Text>
|
||||
</Col>
|
||||
</Row>
|
||||
) : (<Text>No results matched your search</Text>)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
+7
-2
@@ -1,4 +1,5 @@
|
||||
// Copyright (C) 2020-2022 Intel Corporation
|
||||
// Copyright (C) 2023 CVAT.ai Corporation
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
@@ -146,8 +147,12 @@ class DrawShapePopoverContainer extends React.PureComponent<Props, State> {
|
||||
});
|
||||
|
||||
onDrawStart(
|
||||
shapeType, selectedLabel.id, objectType,
|
||||
numberOfPoints, rectDrawingMethod, cuboidDrawingMethod,
|
||||
shapeType,
|
||||
selectedLabel.id,
|
||||
objectType,
|
||||
numberOfPoints,
|
||||
rectDrawingMethod,
|
||||
cuboidDrawingMethod,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -194,7 +194,7 @@ class ObjectItemContainer extends React.PureComponent<Props, State> {
|
||||
updateActiveControl(ActiveControl.EDIT);
|
||||
canvasInstance.edit({ enabled: true, state: objectState });
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private slice = async (): Promise<void> => {
|
||||
const {
|
||||
@@ -215,7 +215,7 @@ class ObjectItemContainer extends React.PureComponent<Props, State> {
|
||||
clientID: objectState.clientID as number,
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private remove = (): void => {
|
||||
const {
|
||||
|
||||
+1
-1
@@ -240,7 +240,7 @@ class ObjectsListContainer extends React.PureComponent<Props, State> {
|
||||
filteredStates,
|
||||
sortedStatesID: sortAndMap(filteredStates, statesOrdering),
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
private onChangeStatesOrdering = (statesOrdering: StatesOrdering): void => {
|
||||
const { filteredStates } = this.state;
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import CVATCore from 'cvat-core/src';
|
||||
import _cvat from 'cvat-core/src/api';
|
||||
|
||||
import ObjectState from 'cvat-core/src/object-state';
|
||||
import Webhook from 'cvat-core/src/webhook';
|
||||
import MLModel from 'cvat-core/src/ml-model';
|
||||
@@ -18,10 +20,11 @@ import Project from 'cvat-core/src/project';
|
||||
import QualityReport, { QualitySummary } from 'cvat-core/src/quality-report';
|
||||
import QualityConflict, { AnnotationConflict, ConflictSeverity } from 'cvat-core/src/quality-conflict';
|
||||
import QualitySettings from 'cvat-core/src/quality-settings';
|
||||
import { FramesMetaData } from 'cvat-core/src/frames';
|
||||
import { FramesMetaData, FrameData } from 'cvat-core/src/frames';
|
||||
import { ServerError } from 'cvat-core/src/exceptions';
|
||||
import {
|
||||
ShapeType, LabelType, ModelKind, ModelProviders, ModelReturnType, DimensionType, JobType,
|
||||
ShapeType, LabelType, ModelKind, ModelProviders,
|
||||
ModelReturnType, DimensionType, JobType,
|
||||
JobStage, JobState, RQStatus,
|
||||
} from 'cvat-core/src/enums';
|
||||
import { Storage, StorageData } from 'cvat-core/src/storage';
|
||||
@@ -35,7 +38,7 @@ import { Dumper } from 'cvat-core/src/annotation-formats';
|
||||
import { EventLogger } from 'cvat-core/src/log';
|
||||
import { APIWrapperEnterOptions } from 'cvat-core/src/plugins';
|
||||
|
||||
const cvat: any = _cvat;
|
||||
const cvat: CVATCore = _cvat;
|
||||
|
||||
cvat.config.backendAPI = '/api';
|
||||
cvat.config.origin = window.location.origin;
|
||||
@@ -44,7 +47,7 @@ cvat.config.origin = window.location.origin;
|
||||
cvat.config.uploadChunkSize = 2;
|
||||
(globalThis as any).cvat = cvat;
|
||||
|
||||
function getCore(): any {
|
||||
function getCore(): typeof cvat {
|
||||
return cvat;
|
||||
}
|
||||
|
||||
@@ -89,6 +92,7 @@ export {
|
||||
AnalyticsEntryViewType,
|
||||
ServerError,
|
||||
EventLogger,
|
||||
FrameData,
|
||||
};
|
||||
|
||||
export type {
|
||||
@@ -98,4 +102,5 @@ export type {
|
||||
ModelProvider,
|
||||
APIWrapperEnterOptions,
|
||||
QualitySummary,
|
||||
CVATCore,
|
||||
};
|
||||
|
||||
@@ -147,7 +147,7 @@ window.addEventListener('error', (errorEvent: ErrorEvent) => {
|
||||
const store = getCVATStore();
|
||||
const state: CombinedState = store.getState();
|
||||
const { pathname } = window.location;
|
||||
const re = RegExp(/\/tasks\/[0-9]+\/jobs\/[0-9]+$/);
|
||||
const re = /\/tasks\/[0-9]+\/jobs\/[0-9]+$/;
|
||||
const { instance: job } = state.annotation.job;
|
||||
if (re.test(pathname) && job) {
|
||||
job.logger.log(LogType.exception, logPayload);
|
||||
|
||||
@@ -49,6 +49,7 @@ export default function GlobalHotKeys(props: Props): JSX.Element {
|
||||
};
|
||||
});
|
||||
|
||||
// eslint-disable-next-line react/jsx-no-useless-fragment
|
||||
return children || <></>;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
import { BaseImageFilter, ImageProcessing } from 'utils/image-processing';
|
||||
|
||||
export interface HistogramEqualization extends ImageProcessing{
|
||||
export interface HistogramEqualization extends ImageProcessing {
|
||||
processImage: (src: ImageData, frameNumber: number) => ImageData;
|
||||
}
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ export class OpenCVWrapper {
|
||||
this.injectionProcess = null;
|
||||
}
|
||||
|
||||
private checkInitialization() {
|
||||
private checkInitialization(): void {
|
||||
if (!this.initialized) {
|
||||
throw new Error('Need to initialize OpenCV first');
|
||||
}
|
||||
@@ -189,8 +189,12 @@ export class OpenCVWrapper {
|
||||
cv.copyMakeBorder(src, expanded, 1, 1, 1, 1, cv.BORDER_CONSTANT);
|
||||
// morpth transform to get better contour including all the pixels
|
||||
cv.dilate(
|
||||
expanded, expanded, kernel,
|
||||
anchor, 1, cv.BORDER_CONSTANT,
|
||||
expanded,
|
||||
expanded,
|
||||
kernel,
|
||||
anchor,
|
||||
1,
|
||||
cv.BORDER_CONSTANT,
|
||||
cv.morphologyDefaultBorderValue(),
|
||||
);
|
||||
cv.findContours(expanded, contours, hierarchy, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_NONE);
|
||||
@@ -276,12 +280,12 @@ export class OpenCVWrapper {
|
||||
}
|
||||
|
||||
throw new Error(`Not implemented getContour for ${state.shapeType}`);
|
||||
}
|
||||
};
|
||||
|
||||
public getContourFromState = async (state: ObjectState): Promise<number[]> => {
|
||||
const contours = await this.getContoursFromState(state);
|
||||
return contours.length > 1 ? this.contours.convexHull(contours) : contours[0];
|
||||
}
|
||||
};
|
||||
|
||||
public get segmentation(): Segmentation {
|
||||
this.checkInitialization();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es2020",
|
||||
"target": "ESNext",
|
||||
"lib": ["dom", "dom.iterable", "esnext"],
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
|
||||
@@ -161,29 +161,6 @@ module.exports = (env) => {
|
||||
test: /\.(png|jpg|jpeg|gif)$/i,
|
||||
type: 'asset/resource',
|
||||
},
|
||||
{
|
||||
test: /3rdparty\/.*\.worker\.js$/,
|
||||
use: {
|
||||
loader: 'worker-loader',
|
||||
options: {
|
||||
publicPath: '/',
|
||||
filename: 'assets/3rdparty/[name].[contenthash].js',
|
||||
esModule: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
test: /\.worker\.js$/,
|
||||
exclude: /3rdparty/,
|
||||
use: {
|
||||
loader: 'worker-loader',
|
||||
options: {
|
||||
publicPath: '/',
|
||||
filename: 'assets/[name].[contenthash].js',
|
||||
esModule: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
parser: {
|
||||
javascript: {
|
||||
|
||||
@@ -26,12 +26,12 @@ module.exports = (stagedFiles) => {
|
||||
const mapping = {};
|
||||
const commands = [];
|
||||
mapping['npx stylelint --fix '] = scssFiles.join(' ');
|
||||
mapping['yarn run precommit:cvat-tests -- '] = tests.join(' ');
|
||||
mapping['yarn run precommit:cvat-ui -- '] = cvatUI.join(' ');
|
||||
mapping['yarn run precommit:cvat-data -- '] = cvatData.join(' ');
|
||||
mapping['yarn run precommit:cvat-core -- '] = cvatCore.join(' ');
|
||||
mapping['yarn run precommit:cvat-canvas -- '] = cvatCanvas.join(' ');
|
||||
mapping['yarn run precommit:cvat-canvas3d -- '] = cvatCanvas3d.join(' ');
|
||||
mapping['yarn run precommit:cvat-tests '] = tests.join(' ');
|
||||
mapping['yarn run precommit:cvat-ui '] = cvatUI.join(' ');
|
||||
mapping['yarn run precommit:cvat-data '] = cvatData.join(' ');
|
||||
mapping['yarn run precommit:cvat-core '] = cvatCore.join(' ');
|
||||
mapping['yarn run precommit:cvat-canvas '] = cvatCanvas.join(' ');
|
||||
mapping['yarn run precommit:cvat-canvas3d '] = cvatCanvas3d.join(' ');
|
||||
|
||||
for (const command of Object.keys(mapping)) {
|
||||
const files = mapping[command];
|
||||
|
||||
+12
-13
@@ -2,7 +2,7 @@
|
||||
"name": "cvat",
|
||||
"version": "1.0.0",
|
||||
"description": "Eslint && remarklint dependencies",
|
||||
"main": ".eslintrc.js",
|
||||
"main": ".eslintrc.cjs",
|
||||
"private": true,
|
||||
"directories": {
|
||||
"test": "tests"
|
||||
@@ -17,6 +17,7 @@
|
||||
"devDependencies": {
|
||||
"@babel/cli": "^7.13.16",
|
||||
"@babel/core": "^7.6.0",
|
||||
"@babel/eslint-parser": "^7.23.3",
|
||||
"@babel/plugin-proposal-class-properties": "^7.8.3",
|
||||
"@babel/plugin-proposal-optional-chaining": "^7.11.0",
|
||||
"@babel/preset-env": "^7.6.0",
|
||||
@@ -26,27 +27,26 @@
|
||||
"@istanbuljs/nyc-config-babel": "^3.0.0",
|
||||
"@types/mousetrap": "^1.6.5",
|
||||
"@types/node": "^18.0.3",
|
||||
"@typescript-eslint/eslint-plugin": "^5.30.5",
|
||||
"@typescript-eslint/parser": "^5.30.5",
|
||||
"@typescript-eslint/eslint-plugin": "^6.13.1",
|
||||
"@typescript-eslint/parser": "^6.13.1",
|
||||
"airbnb": "0.0.2",
|
||||
"babel-eslint": "^10.0.1",
|
||||
"babel-loader": "^8.0.6",
|
||||
"babel-plugin-import": "^1.12.2",
|
||||
"babel-plugin-istanbul": "^6.0.0",
|
||||
"bundle-declarations-webpack-plugin": "^3.1.0",
|
||||
"copy-webpack-plugin": "^11.0.0",
|
||||
"css-loader": "^6.8.1",
|
||||
"eslint": "^7.11.0",
|
||||
"eslint-config-airbnb": "^18.0.1",
|
||||
"eslint": "^8.54.0",
|
||||
"eslint-config-airbnb": "^19.0.4",
|
||||
"eslint-config-airbnb-base": "14.2.1",
|
||||
"eslint-config-airbnb-typescript": "^12.0.0",
|
||||
"eslint-config-airbnb-typescript": "^17.1.0",
|
||||
"eslint-plugin-cypress": "^2.11.2",
|
||||
"eslint-plugin-import": "^2.22.1",
|
||||
"eslint-plugin-jest": "^26.5.3",
|
||||
"eslint-plugin-jsx-a11y": "^6.3.1",
|
||||
"eslint-plugin-no-unsanitized": "^3.0.2",
|
||||
"eslint-plugin-react": "^7.21.5",
|
||||
"eslint-plugin-react-hooks": "^4.2.0",
|
||||
"eslint-plugin-react": "^7.33.2",
|
||||
"eslint-plugin-react-hooks": "^4.6.0",
|
||||
"eslint-plugin-security": "^1.4.0",
|
||||
"html-webpack-plugin": "^5.5.0",
|
||||
"husky": "^6.0.0",
|
||||
@@ -79,12 +79,11 @@
|
||||
"style-loader": "^1.0.0",
|
||||
"stylelint": "^15.10.2",
|
||||
"stylelint-config-standard-scss": "^10.0.0",
|
||||
"typescript": "^5.0.2",
|
||||
"typescript": "5.0.2",
|
||||
"vfile-reporter-json": "^2.0.2",
|
||||
"webpack": "^5.76.0",
|
||||
"webpack-cli": "^4.9.2",
|
||||
"webpack-dev-server": "4.9",
|
||||
"worker-loader": "^3.0.8"
|
||||
"webpack-cli": "^5.1.4",
|
||||
"webpack-dev-server": "4.15.1"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
|
||||
+2
-2
@@ -2,12 +2,12 @@
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
const globalConfig = require('../.eslintrc.js');
|
||||
const globalConfig = require('../.eslintrc.cjs');
|
||||
|
||||
module.exports = {
|
||||
root: true,
|
||||
parserOptions: {
|
||||
parser: 'babel-eslint',
|
||||
parser: '@babel/eslint-parser',
|
||||
sourceType: 'module',
|
||||
},
|
||||
ignorePatterns: [
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user