Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Markdown documentation for tasks/projects #6191

Merged
merged 67 commits into from
Jun 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
67 commits
Select commit Hold shift + click to select a range
7ebf2e5
Initial commit
bsekachev May 22, 2023
520aad1
Some fixes, guide works for tasks
bsekachev May 23, 2023
2d4ea90
Create/update for a project
bsekachev May 23, 2023
08a085d
Attaching assets basic implementation
bsekachev May 23, 2023
a0d863e
Assignment assets to guides and removing unnecessary assets
bsekachev May 23, 2023
6313e51
Aborted unnecessary changes
bsekachev May 23, 2023
ecab185
Added icons on annotation view
bsekachev May 24, 2023
c460380
Showing guide on annotaion view
bsekachev May 24, 2023
d54ea00
Fixed eslint errors
bsekachev May 24, 2023
9e78d71
Some size adjustments
bsekachev May 24, 2023
ce9bfe3
Improved markdown editor page
bsekachev May 24, 2023
388771f
Some code refactoring
bsekachev May 24, 2023
a9cd369
Minor fixes
bsekachev May 26, 2023
e7268b3
Added more plugins
bsekachev May 28, 2023
155312b
added missed migration file
bsekachev May 30, 2023
33d466e
Implemented basic rules for sandbox
bsekachev Jun 8, 2023
32d29c4
Added create permissions
bsekachev Jun 8, 2023
1465428
Implemented permissions for annotator
bsekachev Jun 8, 2023
6643533
Update mixing -> PartialUpdate
bsekachev Jun 8, 2023
bb19139
Squashed migrations
bsekachev Jun 8, 2023
1c5e3ee
Assets always associated with a guide
bsekachev Jun 8, 2023
348f0ca
Assets permissions
bsekachev Jun 8, 2023
5eb2166
Removed guide owner (useless field), added opa rules for organizations
bsekachev Jun 8, 2023
5080b38
Improved some code
bsekachev Jun 8, 2023
655ea29
Some code refactored
bsekachev Jun 8, 2023
0a790d9
Merged develop
bsekachev Jun 8, 2023
4fb8850
Org permissions
bsekachev Jun 8, 2023
9f3d05e
Merged develop
bsekachev Jun 13, 2023
05f2496
Added limits, updated migrations
bsekachev Jun 13, 2023
802cc43
Implemented plugin for tags
bsekachev Jun 13, 2023
a2aa250
Fixed permission
bsekachev Jun 14, 2023
7f3c23d
Added missed settings
bsekachev Jun 14, 2023
749ae39
Implemented backup for tasks and projects
bsekachev Jun 14, 2023
eb16f1b
Simplified backup code
bsekachev Jun 14, 2023
7299c9f
Improved write code
bsekachev Jun 15, 2023
8f4d227
Added restore functionality
bsekachev Jun 15, 2023
a5d1a4f
Minor fixes
bsekachev Jun 15, 2023
70ec0e0
Update task or project when guide was changed
bsekachev Jun 15, 2023
3dc7d84
Some styles fixes
bsekachev Jun 16, 2023
667f7d4
Merge branch 'develop' into bs/md
bsekachev Jun 16, 2023
d0d6275
License headers, aborted extra changes in base.py
bsekachev Jun 16, 2023
83a494e
Fixed client warning
bsekachev Jun 16, 2023
2ea127c
Updated version & changelog
bsekachev Jun 16, 2023
844392f
Merged develop
bsekachev Jun 19, 2023
a8d0bc6
Fixed eslint issues
bsekachev Jun 19, 2023
69c0e83
Fixed pylint issues
bsekachev Jun 19, 2023
ded0cfd
Updated schema yml
bsekachev Jun 19, 2023
5d3b02b
Fixed e2e test and unit tests
bsekachev Jun 19, 2023
64dc246
Added guide_id to rest api tests
bsekachev Jun 19, 2023
77ba562
Applied comments
bsekachev Jun 20, 2023
0dadf33
Applied comments
bsekachev Jun 20, 2023
e50b713
Added API scheme description
bsekachev Jun 20, 2023
a3ae8da
Fixed pylint
bsekachev Jun 20, 2023
8fc4926
Updated schema
bsekachev Jun 20, 2023
69bb060
Added OPA tests
bsekachev Jun 21, 2023
d7f827f
Applied comments
bsekachev Jun 21, 2023
f3bba90
Added missed rules for admin
bsekachev Jun 21, 2023
b20724f
Updated schema
bsekachev Jun 21, 2023
fa2a335
Merge branch 'develop' into bs/md
bsekachev Jun 22, 2023
3ed3e36
Using target property
bsekachev Jun 22, 2023
e83b808
Updated permissions
bsekachev Jun 22, 2023
a69369c
Updated schema
bsekachev Jun 22, 2023
abdf402
Updated generator
bsekachev Jun 22, 2023
cb1d9cf
Removed outdated code
bsekachev Jun 23, 2023
8ef072c
Removed old code
bsekachev Jun 23, 2023
5753e7a
Updated is job staff method
bsekachev Jun 23, 2023
5b68998
Fixed unused report
bsekachev Jun 23, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## \[Unreleased]
### Added
- TDB
- Now CVAT supports project/task markdown description with additional assets
(png, jpeg, gif, webp images and pdf files) (<https://github.com/opencv/cvat/pull/6191>)

### Changed
- TDB
Expand Down
2 changes: 1 addition & 1 deletion cvat-core/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "cvat-core",
"version": "9.1.3",
"version": "9.2.0",
"description": "Part of Computer Vision Tool which presents an interface for client-side integration",
"main": "src/api.ts",
"scripts": {
Expand Down
11 changes: 11 additions & 0 deletions cvat-core/src/api-implementation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
import CloudStorage from './cloud-storage';
import Organization from './organization';
import Webhook from './webhook';
import { ArgumentError } from './exceptions';
import { SerializedAsset } from './server-response-types';

export default function implementAPI(cvat) {
cvat.plugins.list.implementation = PluginRegistry.list;
Expand Down Expand Up @@ -133,6 +135,15 @@
return result;
};

cvat.assets.create.implementation = async (file: File, guideId: number): Promise<SerializedAsset> => {
if (!(file instanceof File)) {
throw new ArgumentError('Assets expect a file');

Check warning on line 140 in cvat-core/src/api-implementation.ts

View check run for this annotation

Codecov / codecov/patch

cvat-core/src/api-implementation.ts#L140

Added line #L140 was not covered by tests
}

const result = await serverProxy.assets.create(file, guideId);
return result;

Check warning on line 144 in cvat-core/src/api-implementation.ts

View check run for this annotation

Codecov / codecov/patch

cvat-core/src/api-implementation.ts#L143-L144

Added lines #L143 - L144 were not covered by tests
};

cvat.users.get.implementation = async (filter) => {
checkFilter(filter, {
id: isInteger,
Expand Down
13 changes: 8 additions & 5 deletions cvat-core/src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,6 @@
//
// SPDX-License-Identifier: MIT

/**
* External API which should be used by for development
* @module API
*/

import PluginRegistry from './plugins';
import loggerStorage from './logger-storage';
import { EventLogger } from './log';
Expand All @@ -25,6 +20,7 @@
import CloudStorage from './cloud-storage';
import Organization from './organization';
import Webhook from './webhook';
import AnnotationGuide from './guide';

import * as enums from './enums';

Expand Down Expand Up @@ -147,6 +143,12 @@
return result;
},
},
assets: {
async create(file: File, guideId: number) {
const result = await PluginRegistry.apiWrapper(cvat.assets.create, file, guideId);
return result;

Check warning on line 149 in cvat-core/src/api.ts

View check run for this annotation

Codecov / codecov/patch

cvat-core/src/api.ts#L147-L149

Added lines #L147 - L149 were not covered by tests
},
},
jobs: {
async get(filter = {}) {
const result = await PluginRegistry.apiWrapper(cvat.jobs.get, filter);
Expand Down Expand Up @@ -287,6 +289,7 @@
CloudStorage,
Organization,
Webhook,
AnnotationGuide,
},
};

Expand Down
92 changes: 92 additions & 0 deletions cvat-core/src/guide.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// Copyright (C) 2023 CVAT.ai Corporation
//
// SPDX-License-Identifier: MIT

import { SerializedGuide } from './server-response-types';
import { ArgumentError, DataError } from './exceptions';
import PluginRegistry from './plugins';
import serverProxy from './server-proxy';

class AnnotationGuide {
#id: AnnotationGuide['id'];
#taskId: AnnotationGuide['taskId'];
#projectId: AnnotationGuide['projectId'];
#createdDate?: AnnotationGuide['createdDate'];
#updatedDate?: AnnotationGuide['updatedDate'];
#markdown: AnnotationGuide['markdown'];

Check warning on line 16 in cvat-core/src/guide.ts

View check run for this annotation

Codecov / codecov/patch

cvat-core/src/guide.ts#L11-L16

Added lines #L11 - L16 were not covered by tests

constructor(initialData: Partial<SerializedGuide>) {
this.#id = initialData.id;

Check warning on line 19 in cvat-core/src/guide.ts

View check run for this annotation

Codecov / codecov/patch

cvat-core/src/guide.ts#L18-L19

Added lines #L18 - L19 were not covered by tests
this.#taskId = initialData.task_id || null;
this.#projectId = initialData.project_id || null;
this.#createdDate = initialData.created_date;
this.#updatedDate = initialData.updated_date;

Check warning on line 23 in cvat-core/src/guide.ts

View check run for this annotation

Codecov / codecov/patch

cvat-core/src/guide.ts#L22-L23

Added lines #L22 - L23 were not covered by tests
this.#markdown = initialData.markdown || '';
}

public get id(): number | undefined {
return this.#id;

Check warning on line 28 in cvat-core/src/guide.ts

View check run for this annotation

Codecov / codecov/patch

cvat-core/src/guide.ts#L27-L28

Added lines #L27 - L28 were not covered by tests
}

public get taskId(): number | null {
return this.#taskId;

Check warning on line 32 in cvat-core/src/guide.ts

View check run for this annotation

Codecov / codecov/patch

cvat-core/src/guide.ts#L31-L32

Added lines #L31 - L32 were not covered by tests
}

public get projectId(): number | null {
return this.#projectId;

Check warning on line 36 in cvat-core/src/guide.ts

View check run for this annotation

Codecov / codecov/patch

cvat-core/src/guide.ts#L35-L36

Added lines #L35 - L36 were not covered by tests
}

public get createdDate(): string | undefined {
return this.#createdDate;

Check warning on line 40 in cvat-core/src/guide.ts

View check run for this annotation

Codecov / codecov/patch

cvat-core/src/guide.ts#L39-L40

Added lines #L39 - L40 were not covered by tests
}

public get updatedDate(): string | undefined {
return this.#updatedDate;

Check warning on line 44 in cvat-core/src/guide.ts

View check run for this annotation

Codecov / codecov/patch

cvat-core/src/guide.ts#L43-L44

Added lines #L43 - L44 were not covered by tests
}

public get markdown(): string {
return this.#markdown;

Check warning on line 48 in cvat-core/src/guide.ts

View check run for this annotation

Codecov / codecov/patch

cvat-core/src/guide.ts#L47-L48

Added lines #L47 - L48 were not covered by tests
}

public set markdown(value: string) {

Check warning on line 51 in cvat-core/src/guide.ts

View check run for this annotation

Codecov / codecov/patch

cvat-core/src/guide.ts#L51

Added line #L51 was not covered by tests
if (typeof value !== 'string') {
throw new ArgumentError(`Markdown value must be a string, ${typeof value} received`);

Check warning on line 53 in cvat-core/src/guide.ts

View check run for this annotation

Codecov / codecov/patch

cvat-core/src/guide.ts#L53

Added line #L53 was not covered by tests
}
this.#markdown = value;

Check warning on line 55 in cvat-core/src/guide.ts

View check run for this annotation

Codecov / codecov/patch

cvat-core/src/guide.ts#L55

Added line #L55 was not covered by tests
}

async save(): Promise<AnnotationGuide> {
const result = await PluginRegistry.apiWrapper.call(this, AnnotationGuide.prototype.save);
return result;

Check warning on line 60 in cvat-core/src/guide.ts

View check run for this annotation

Codecov / codecov/patch

cvat-core/src/guide.ts#L58-L60

Added lines #L58 - L60 were not covered by tests
}
}

Object.defineProperties(AnnotationGuide.prototype.save, {
implementation: {
writable: false,
enumerable: false,
value: async function implementation(this: AnnotationGuide) {

Check warning on line 68 in cvat-core/src/guide.ts

View check run for this annotation

Codecov / codecov/patch

cvat-core/src/guide.ts#L68

Added line #L68 was not covered by tests
if (Number.isInteger(this.id)) {
const result = await serverProxy.guides.update(this.id, { markdown: this.markdown });
return new AnnotationGuide(result);

Check warning on line 71 in cvat-core/src/guide.ts

View check run for this annotation

Codecov / codecov/patch

cvat-core/src/guide.ts#L70-L71

Added lines #L70 - L71 were not covered by tests
}

if (this.projectId === null && this.taskId === null) {
throw new DataError('One of projectId or taskId must be specified for a guide');

Check warning on line 75 in cvat-core/src/guide.ts

View check run for this annotation

Codecov / codecov/patch

cvat-core/src/guide.ts#L75

Added line #L75 was not covered by tests
}

if (this.projectId !== null && this.taskId !== null) {
throw new DataError('Both projectId and taskId must not be presented for a guide');

Check warning on line 79 in cvat-core/src/guide.ts

View check run for this annotation

Codecov / codecov/patch

cvat-core/src/guide.ts#L79

Added line #L79 was not covered by tests
}

const result = await serverProxy.guides.create({

Check warning on line 82 in cvat-core/src/guide.ts

View check run for this annotation

Codecov / codecov/patch

cvat-core/src/guide.ts#L82

Added line #L82 was not covered by tests
task_id: this.taskId,
project_id: this.projectId,
markdown: this.markdown,
});
return new AnnotationGuide(result);

Check warning on line 87 in cvat-core/src/guide.ts

View check run for this annotation

Codecov / codecov/patch

cvat-core/src/guide.ts#L87

Added line #L87 was not covered by tests
},
},
});

export default AnnotationGuide;
10 changes: 10 additions & 0 deletions cvat-core/src/project-implementation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import { exportDataset, importDataset } from './annotations';
import { SerializedLabel } from './server-response-types';
import { Label } from './labels';
import AnnotationGuide from './guide';

export default function implementProject(projectClass) {
projectClass.prototype.save.implementation = async function () {
Expand Down Expand Up @@ -125,5 +126,14 @@
return result;
};

projectClass.prototype.guide.implementation = async function guide() {
if (this.guideId === null) {
return null;

Check warning on line 131 in cvat-core/src/project-implementation.ts

View check run for this annotation

Codecov / codecov/patch

cvat-core/src/project-implementation.ts#L131

Added line #L131 was not covered by tests
}

const result = await serverProxy.guides.get(this.guideId);
return new AnnotationGuide(result);

Check warning on line 135 in cvat-core/src/project-implementation.ts

View check run for this annotation

Codecov / codecov/patch

cvat-core/src/project-implementation.ts#L134-L135

Added lines #L134 - L135 were not covered by tests
};

return projectClass;
}
11 changes: 11 additions & 0 deletions cvat-core/src/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,15 @@
import { Label } from './labels';
import User from './user';
import { FieldUpdateTrigger } from './common';
import AnnotationGuide from './guide';

export default class Project {
public readonly id: number;
public name: string;
public assignee: User;
public bugTracker: string;
public readonly status: ProjectStatus;
public readonly guideId: number | null;
public readonly organization: string | null;
public readonly owner: User;
public readonly createdDate: string;
Expand All @@ -39,6 +41,7 @@
name: undefined,
status: undefined,
assignee: undefined,
guide_id: undefined,
organization: undefined,
owner: undefined,
bug_tracker: undefined,
Expand Down Expand Up @@ -98,6 +101,9 @@
owner: {
get: () => data.owner,
},
guideId: {
get: () => data.guide_id,

Check warning on line 105 in cvat-core/src/project.ts

View check run for this annotation

Codecov / codecov/patch

cvat-core/src/project.ts#L105

Added line #L105 was not covered by tests
},
organization: {
get: () => data.organization,
},
Expand Down Expand Up @@ -230,6 +236,11 @@
const result = await PluginRegistry.apiWrapper.call(this, Project.restore, storage, file);
return result;
}

async guide(): Promise<AnnotationGuide | null> {
const result = await PluginRegistry.apiWrapper.call(this, Project.prototype.guide);
return result;

Check warning on line 242 in cvat-core/src/project.ts

View check run for this annotation

Codecov / codecov/patch

cvat-core/src/project.ts#L240-L242

Added lines #L240 - L242 were not covered by tests
}
}

Object.defineProperties(
Expand Down
63 changes: 62 additions & 1 deletion cvat-core/src/server-proxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
SerializedLabel, SerializedAnnotationFormats, ProjectsFilter,
SerializedProject, SerializedTask, TasksFilter, SerializedUser,
SerializedAbout, SerializedRemoteFile, SerializedUserAgreement,
SerializedRegister, JobsFilter, SerializedJob,
SerializedRegister, JobsFilter, SerializedJob, SerializedGuide, SerializedAsset,
} from 'server-response-types';
import { Storage } from './storage';
import { StorageLocation, WebhookSourceType } from './enums';
Expand Down Expand Up @@ -2167,6 +2167,57 @@
}
}

async function getGuide(id: number): Promise<SerializedGuide> {
const { backendAPI } = config;

Check warning on line 2171 in cvat-core/src/server-proxy.ts

View check run for this annotation

Codecov / codecov/patch

cvat-core/src/server-proxy.ts#L2170-L2171

Added lines #L2170 - L2171 were not covered by tests

try {
const response = await Axios.get(`${backendAPI}/guides/${id}`);
return response.data;

Check warning on line 2175 in cvat-core/src/server-proxy.ts

View check run for this annotation

Codecov / codecov/patch

cvat-core/src/server-proxy.ts#L2173-L2175

Added lines #L2173 - L2175 were not covered by tests
} catch (errorData) {
throw generateError(errorData);

Check warning on line 2177 in cvat-core/src/server-proxy.ts

View check run for this annotation

Codecov / codecov/patch

cvat-core/src/server-proxy.ts#L2177

Added line #L2177 was not covered by tests
}
}

async function createGuide(data: Partial<SerializedGuide>): Promise<SerializedGuide> {
const { backendAPI } = config;

Check warning on line 2182 in cvat-core/src/server-proxy.ts

View check run for this annotation

Codecov / codecov/patch

cvat-core/src/server-proxy.ts#L2181-L2182

Added lines #L2181 - L2182 were not covered by tests

try {
const response = await Axios.post(`${backendAPI}/guides`, data);
return response.data;

Check warning on line 2186 in cvat-core/src/server-proxy.ts

View check run for this annotation

Codecov / codecov/patch

cvat-core/src/server-proxy.ts#L2184-L2186

Added lines #L2184 - L2186 were not covered by tests
} catch (errorData) {
throw generateError(errorData);

Check warning on line 2188 in cvat-core/src/server-proxy.ts

View check run for this annotation

Codecov / codecov/patch

cvat-core/src/server-proxy.ts#L2188

Added line #L2188 was not covered by tests
}
}

async function updateGuide(id: number, data: Partial<SerializedGuide>): Promise<SerializedGuide> {
const { backendAPI } = config;

Check warning on line 2193 in cvat-core/src/server-proxy.ts

View check run for this annotation

Codecov / codecov/patch

cvat-core/src/server-proxy.ts#L2192-L2193

Added lines #L2192 - L2193 were not covered by tests

try {
const response = await Axios.patch(`${backendAPI}/guides/${id}`, data);
return response.data;

Check warning on line 2197 in cvat-core/src/server-proxy.ts

View check run for this annotation

Codecov / codecov/patch

cvat-core/src/server-proxy.ts#L2195-L2197

Added lines #L2195 - L2197 were not covered by tests
} catch (errorData) {
throw generateError(errorData);

Check warning on line 2199 in cvat-core/src/server-proxy.ts

View check run for this annotation

Codecov / codecov/patch

cvat-core/src/server-proxy.ts#L2199

Added line #L2199 was not covered by tests
}
}

async function createAsset(file: File, guideId: number): Promise<SerializedAsset> {
const { backendAPI } = config;
const form = new FormData();
form.append('file', file);
form.append('guide_id', guideId);

Check warning on line 2207 in cvat-core/src/server-proxy.ts

View check run for this annotation

Codecov / codecov/patch

cvat-core/src/server-proxy.ts#L2203-L2207

Added lines #L2203 - L2207 were not covered by tests

try {
const response = await Axios.post(`${backendAPI}/assets`, form, {

Check warning on line 2210 in cvat-core/src/server-proxy.ts

View check run for this annotation

Codecov / codecov/patch

cvat-core/src/server-proxy.ts#L2209-L2210

Added lines #L2209 - L2210 were not covered by tests
headers: {
'Content-Type': 'multipart/form-data',
},
});
return response.data;

Check warning on line 2215 in cvat-core/src/server-proxy.ts

View check run for this annotation

Codecov / codecov/patch

cvat-core/src/server-proxy.ts#L2215

Added line #L2215 was not covered by tests
} catch (errorData) {
throw generateError(errorData);

Check warning on line 2217 in cvat-core/src/server-proxy.ts

View check run for this annotation

Codecov / codecov/patch

cvat-core/src/server-proxy.ts#L2217

Added line #L2217 was not covered by tests
}
}

export default Object.freeze({
server: Object.freeze({
setAuthData,
Expand Down Expand Up @@ -2310,4 +2361,14 @@
ping: pingWebhook,
events: receiveWebhookEvents,
}),

guides: Object.freeze({
get: getGuide,
create: createGuide,
update: updateGuide,
}),

assets: Object.freeze({
create: createAsset,
}),
});
25 changes: 23 additions & 2 deletions cvat-core/src/server-response-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ export interface SerializedProject {
dimension: DimensionType;
name: string;
organization: number | null;
guide_id: number | null;
owner: SerializedUser;
source_storage: { id: number; location: 'local' | 'cloud'; cloud_storage_id: null };
target_storage: { id: number; location: 'local' | 'cloud'; cloud_storage_id: null };
Expand Down Expand Up @@ -94,6 +95,7 @@ export interface SerializedTask {
overlap: number | null;
owner: SerializedUser;
project_id: number | null;
guide_id: number | null;
segment_size: number;
size: number;
source_storage: { id: number; location: 'local' | 'cloud'; cloud_storage_id: null };
Expand All @@ -115,10 +117,11 @@ export interface SerializedJob {
labels: { count: number; url: string };
mode: TaskMode;
project_id: number | null;
guide_id: number | null;
stage: JobStage;
state: JobState;
startFrame: number;
stopFrame: number;
start_frame: number;
stop_frame: number;
task_id: number;
updated_date: string;
url: string;
Expand Down Expand Up @@ -174,3 +177,21 @@ export interface SerializedRegister {
last_name: string;
username: string;
}

export interface SerializedGuide {
id?: number;
task_id: number | null;
project_id: number | null;
owner: SerializedUser;
created_date: string;
updated_date: string;
markdown: string;
}

export interface SerializedAsset {
uuid?: string;
guide?: number;
filename: string;
created_date: string;
owner: SerializedUser;
}
Loading
Loading