From aab6a124ed83e153e568a0ba4d90bd80f130efde Mon Sep 17 00:00:00 2001 From: Boris Sekachev <40690378+bsekachev@users.noreply.github.com> Date: Wed, 7 Aug 2019 15:43:17 +0300 Subject: [PATCH] Integration of tslint static analyser for cvat-canvas (#624) --- cvat-canvas/.eslintrc.js | 52 ------------------------ cvat-canvas/README.md | 18 ++++----- cvat-canvas/dist/canvas.css | 20 ++++----- cvat-canvas/dist/index.html | 16 -------- cvat-canvas/dist/index.js | 28 ------------- cvat-canvas/package.json | 3 +- cvat-canvas/src/canvas.ts | 5 ++- cvat-canvas/src/canvasController.ts | 3 +- cvat-canvas/src/canvasModel.ts | 49 ++++++++++------------ cvat-canvas/src/canvasView.ts | 63 +++++++++++++++-------------- cvat-canvas/tslint.config.js | 34 ++++++++++++++++ 11 files changed, 114 insertions(+), 177 deletions(-) delete mode 100644 cvat-canvas/.eslintrc.js delete mode 100644 cvat-canvas/dist/index.html delete mode 100644 cvat-canvas/dist/index.js create mode 100644 cvat-canvas/tslint.config.js diff --git a/cvat-canvas/.eslintrc.js b/cvat-canvas/.eslintrc.js deleted file mode 100644 index 9d123380..00000000 --- a/cvat-canvas/.eslintrc.js +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2018 Intel Corporation - * - * SPDX-License-Identifier: MIT - */ - - module.exports = { - 'env': { - 'node': true, - 'browser': true, - 'es6': true, - }, - 'parserOptions': { - 'parser': '@typescript-eslint/parser', - 'sourceType': 'module', - 'ecmaVersion': 6, - }, - 'plugins': [ - 'security', - 'no-unsanitized', - 'no-unsafe-innerhtml', - '@typescript-eslint', - ], - 'extends': [ - 'eslint:recommended', - 'plugin:security/recommended', - 'plugin:no-unsanitized/DOM', - 'plugin:@typescript-eslint/recommended', - 'airbnb', - ], - 'rules': { - 'no-new': [0], - 'class-methods-use-this': [0], - 'no-plusplus': [0], - 'no-restricted-syntax': [0, {'selector': 'ForOfStatement'}], - 'no-continue': [0], - 'security/detect-object-injection': 0, - 'indent': ['warn', 4], - 'no-useless-constructor': 0, - 'func-names': [0], - 'no-console': [0], // this rule deprecates console.log, console.warn etc. because 'it is not good in production code' - '@typescript-eslint/no-explicit-any': [0], - 'lines-between-class-members': [0], - }, - 'settings': { - 'import/resolver': { - 'node': { - 'extensions': ['.ts', '.js', '.json'], - }, - }, - }, -}; diff --git a/cvat-canvas/README.md b/cvat-canvas/README.md index 911aaaff..369effa2 100644 --- a/cvat-canvas/README.md +++ b/cvat-canvas/README.md @@ -68,15 +68,15 @@ All methods are sync. ### CSS Classes/IDs -- Each drawn object (tag, shape, track) has id ```canvas_object_{objectState.id}``` -- Drawn shapes and tracks have classes ```canvas_shape```, - ```canvas_shape_activated```, - ```canvas_shape_grouping```, - ```canvas_shape_merging```, - ```canvas_shape_drawing``` -- Tags has a class ```canvas_tag``` -- Canvas image has ID ```canvas_image``` -- Grid on the canvas has ID ```canvas_grid_pattern``` +- Each drawn object (tag, shape, track) has id ```cvat_canvas_object_{objectState.id}``` +- Drawn shapes and tracks have classes ```cvat_canvas_shape```, + ```cvat_canvas_shape_activated```, + ```cvat_canvas_shape_grouping```, + ```cvat_canvas_shape_merging```, + ```cvat_canvas_shape_drawing``` +- Tags has a class ```cvat_canvas_tag``` +- Canvas image has ID ```cvat_canvas_image``` +- Grid on the canvas has ID ```cvat_canvas_grid_pattern``` ### Events diff --git a/cvat-canvas/dist/canvas.css b/cvat-canvas/dist/canvas.css index db6093c4..cdb35074 100644 --- a/cvat-canvas/dist/canvas.css +++ b/cvat-canvas/dist/canvas.css @@ -1,8 +1,8 @@ -.canvas_hidden { +.cvat_canvas_hidden { display: none; } -#canvas_wrapper { +#cvat_canvas_wrapper { width: 100%; height: 80%; border: 1px black solid; @@ -12,13 +12,13 @@ position: relative; } -#canvas_rotation_wrapper { +#cvat_canvas_rotation_wrapper { width: 100%; height: 100%; position: relative; } -#canvas_loading_animation { +#cvat_canvas_loading_animation { z-index: 1; position: absolute; width: 100%; @@ -26,7 +26,7 @@ transform-origin: top left; } -#canvas_loading_circle { +#cvat_canvas_loading_circle { fill-opacity: 0; stroke: #09c; stroke-width: 3px; @@ -34,7 +34,7 @@ animation: loadingAnimation 1s linear infinite; } -#canvas_text_content { +#cvat_canvas_text_content { position: absolute; z-index: 3; transform-origin: center center; @@ -43,7 +43,7 @@ height: 100%; } -#canvas_background { +#cvat_canvas_background { position: absolute; z-index: 0; background-repeat: no-repeat; @@ -52,7 +52,7 @@ height: 100%; } -#canvas_grid { +#cvat_canvas_grid { position: absolute; z-index: 2; transform-origin: top left; @@ -61,12 +61,12 @@ height: 100%; } -#canvas_grid_pattern { +#cvat_canvas_grid_pattern { opacity: 1; stroke: white; } -#canvas_content { +#cvat_canvas_content { position: absolute; z-index: 2; outline: 10px solid black; diff --git a/cvat-canvas/dist/index.html b/cvat-canvas/dist/index.html deleted file mode 100644 index ac996e9d..00000000 --- a/cvat-canvas/dist/index.html +++ /dev/null @@ -1,16 +0,0 @@ - - - - - CVAT-CANVAS Dev Server - - - - - - -
- -
- - \ No newline at end of file diff --git a/cvat-canvas/dist/index.js b/cvat-canvas/dist/index.js deleted file mode 100644 index b13d7c6d..00000000 --- a/cvat-canvas/dist/index.js +++ /dev/null @@ -1,28 +0,0 @@ -window.addEventListener('DOMContentLoaded', async () => { - await window.cvat.server.login('admin', 'nimda760'); - const [job] = (await window.cvat.jobs.get({ jobID: 21 })); - const canvas = new window.canvas.Canvas(); - const htmlContainer = window.document.getElementById('htmlContainer'); - - - htmlContainer.appendChild(canvas.html()); - - let frame = 0; - const callback = async () => { - canvas.fit(); - const frameData = await job.frames.get(frame); - canvas.setup(frameData, []); - frame += 1; - - if (frame > 50) { - frame = 0; - } - }; - - canvas.html().addEventListener('canvas.setup', async () => { - setTimeout(callback, 30); - }); - - const frameData = await job.frames.get(frame); - canvas.setup(frameData, []); -}); diff --git a/cvat-canvas/package.json b/cvat-canvas/package.json index e6b980f3..99838df5 100644 --- a/cvat-canvas/package.json +++ b/cvat-canvas/package.json @@ -21,8 +21,9 @@ "@typescript-eslint/eslint-plugin": "^1.13.0", "@typescript-eslint/parser": "^1.13.0", "babel-loader": "^8.0.6", - "eslint": "^6.1.0", "nodemon": "^1.19.1", + "tslint": "^5.18.0", + "tslint-config-airbnb": "^5.11.1", "typescript": "^3.5.3", "webpack": "^4.36.1", "webpack-cli": "^3.3.6", diff --git a/cvat-canvas/src/canvas.ts b/cvat-canvas/src/canvas.ts index f2d47abe..f48f0155 100644 --- a/cvat-canvas/src/canvas.ts +++ b/cvat-canvas/src/canvas.ts @@ -3,8 +3,8 @@ * SPDX-License-Identifier: MIT */ -import { CanvasModel, CanvasModelImpl, Rotation } from './canvasModel'; import { CanvasController, CanvasControllerImpl } from './canvasController'; +import { CanvasModel, CanvasModelImpl, Rotation } from './canvasModel'; import { CanvasView, CanvasViewImpl } from './canvasView'; interface Canvas { @@ -63,7 +63,8 @@ class CanvasImpl implements Canvas { this.model.grid(stepX, stepY); } - public draw(enabled: boolean = false, shapeType: string = '', numberOfPoints: number = 0, initialState: any = null): any { + public draw(enabled: boolean = false, shapeType: string = '', + numberOfPoints: number = 0, initialState: any = null): any { return this.model.draw(enabled, shapeType, numberOfPoints, initialState); } diff --git a/cvat-canvas/src/canvasController.ts b/cvat-canvas/src/canvasController.ts index 4e2d9892..3c4db0a5 100644 --- a/cvat-canvas/src/canvasController.ts +++ b/cvat-canvas/src/canvasController.ts @@ -6,11 +6,10 @@ import { CanvasModel, Geometry, - Size, Position, + Size, } from './canvasModel'; - export interface CanvasController { readonly geometry: Geometry; canvasSize: Size; diff --git a/cvat-canvas/src/canvasModel.ts b/cvat-canvas/src/canvasModel.ts index 05eda925..cf24e06e 100644 --- a/cvat-canvas/src/canvasModel.ts +++ b/cvat-canvas/src/canvasModel.ts @@ -80,19 +80,19 @@ export class CanvasModelImpl extends MasterImpl implements CanvasModel { super(); this.data = { + canvasSize: { + height: 0, + width: 0, + }, image: '', + imageOffset: 0, imageSize: { - width: 0, height: 0, - }, - canvasSize: { width: 0, - height: 0, }, - imageOffset: 0, + left: 0, scale: 1, top: 0, - left: 0, }; } @@ -112,7 +112,6 @@ export class CanvasModelImpl extends MasterImpl implements CanvasModel { this.notify(UpdateReasons.MOVE); } - public setup(frameData: any, objectStates: any[]): void { frameData.data( (): void => { @@ -121,8 +120,8 @@ export class CanvasModelImpl extends MasterImpl implements CanvasModel { }, ).then((data: string): void => { this.data.imageSize = { - width: (frameData.width as number), height: (frameData.height as number), + width: (frameData.width as number), }; this.data.image = data; @@ -170,12 +169,12 @@ export class CanvasModelImpl extends MasterImpl implements CanvasModel { } public draw(enabled: boolean, shapeType: string, - numberOfPoints: number, initialState: any): any { + numberOfPoints: number, initialState: any): any { return { enabled, - shapeType, - numberOfPoints, initialState, + numberOfPoints, + shapeType, }; } @@ -192,23 +191,23 @@ export class CanvasModelImpl extends MasterImpl implements CanvasModel { } public cancel(): void { - + console.log('hello'); } public get geometry(): Geometry { return { - image: { - width: this.data.imageSize.width, - height: this.data.imageSize.height, - }, canvas: { - width: this.data.canvasSize.width, height: this.data.canvasSize.height, + width: this.data.canvasSize.width, + }, + image: { + height: this.data.imageSize.height, + width: this.data.imageSize.width, }, - top: this.data.top, left: this.data.left, - scale: this.data.scale, offset: this.data.imageOffset, + scale: this.data.scale, + top: this.data.top, }; } @@ -218,22 +217,22 @@ export class CanvasModelImpl extends MasterImpl implements CanvasModel { public set imageSize(value: Size) { this.data.imageSize = { - width: value.width, height: value.height, + width: value.width, }; } public get imageSize(): Size { return { - width: this.data.imageSize.width, height: this.data.imageSize.height, + width: this.data.imageSize.width, }; } public set canvasSize(value: Size) { this.data.canvasSize = { - width: value.width, height: value.height, + width: value.width, }; this.data.imageOffset = Math.floor(Math.max( @@ -244,12 +243,8 @@ export class CanvasModelImpl extends MasterImpl implements CanvasModel { public get canvasSize(): Size { return { - width: this.data.canvasSize.width, height: this.data.canvasSize.height, + width: this.data.canvasSize.width, }; } } - -// TODO List: -// 2) Rotate image -// 3) Draw objects diff --git a/cvat-canvas/src/canvasView.ts b/cvat-canvas/src/canvasView.ts index dc7d3c80..2dd82b30 100644 --- a/cvat-canvas/src/canvasView.ts +++ b/cvat-canvas/src/canvasView.ts @@ -3,9 +3,9 @@ * SPDX-License-Identifier: MIT */ -import { CanvasModel, UpdateReasons, Geometry } from './canvasModel'; -import { Listener, Master } from './master'; import { CanvasController } from './canvasController'; +import { CanvasModel, Geometry, UpdateReasons } from './canvasModel'; +import { Listener, Master } from './master'; export interface CanvasView { html(): HTMLDivElement; @@ -15,7 +15,6 @@ interface HTMLAttribute { [index: string]: string; } - function translateToSVG(svg: SVGSVGElement, points: number[]): number[] { const output = []; const transformationMatrix = svg.getScreenCTM().inverse(); @@ -59,7 +58,8 @@ export class CanvasViewImpl implements CanvasView, Listener { this.controller = controller; // Create HTML elements - this.loadingAnimation = window.document.createElementNS('http://www.w3.org/2000/svg', 'svg'); + this.loadingAnimation = window.document + .createElementNS('http://www.w3.org/2000/svg', 'svg'); this.text = window.document.createElementNS('http://www.w3.org/2000/svg', 'svg'); this.background = window.document.createElementNS('http://www.w3.org/2000/svg', 'svg'); @@ -70,41 +70,44 @@ export class CanvasViewImpl implements CanvasView, Listener { this.rotationWrapper = window.document.createElement('div'); this.canvas = window.document.createElement('div'); - const loadingCircle: SVGCircleElement = window.document.createElementNS('http://www.w3.org/2000/svg', 'circle'); - const gridDefs: SVGDefsElement = window.document.createElementNS('http://www.w3.org/2000/svg', 'defs'); - const gridPattern: SVGPatternElement = window.document.createElementNS('http://www.w3.org/2000/svg', 'pattern'); - const gridRect: SVGRectElement = window.document.createElementNS('http://www.w3.org/2000/svg', 'rect'); + const loadingCircle: SVGCircleElement = window.document + .createElementNS('http://www.w3.org/2000/svg', 'circle'); + const gridDefs: SVGDefsElement = window.document + .createElementNS('http://www.w3.org/2000/svg', 'defs'); + const gridPattern: SVGPatternElement = window.document + .createElementNS('http://www.w3.org/2000/svg', 'pattern'); + const gridRect: SVGRectElement = window.document + .createElementNS('http://www.w3.org/2000/svg', 'rect'); // Setup loading animation - this.loadingAnimation.setAttribute('id', 'canvas_loading_animation'); - loadingCircle.setAttribute('id', 'canvas_loading_circle'); + this.loadingAnimation.setAttribute('id', 'cvat_canvas_loading_animation'); + loadingCircle.setAttribute('id', 'cvat_canvas_loading_circle'); loadingCircle.setAttribute('r', '30'); loadingCircle.setAttribute('cx', '50%'); loadingCircle.setAttribute('cy', '50%'); // Setup grid - this.grid.setAttribute('id', 'canvas_grid'); + this.grid.setAttribute('id', 'cvat_canvas_grid'); this.grid.setAttribute('version', '2'); this.gridPath.setAttribute('d', 'M 1000 0 L 0 0 0 1000'); this.gridPath.setAttribute('fill', 'none'); this.gridPath.setAttribute('stroke-width', '1.5'); - gridPattern.setAttribute('id', 'canvas_grid_pattern'); + gridPattern.setAttribute('id', 'cvat_canvas_grid_pattern'); gridPattern.setAttribute('width', '100'); gridPattern.setAttribute('height', '100'); gridPattern.setAttribute('patternUnits', 'userSpaceOnUse'); gridRect.setAttribute('width', '100%'); gridRect.setAttribute('height', '100%'); - gridRect.setAttribute('fill', 'url(#canvas_grid_pattern)'); - + gridRect.setAttribute('fill', 'url(#cvat_canvas_grid_pattern)'); // Setup content - this.text.setAttribute('id', 'canvas_text_content'); - this.background.setAttribute('id', 'canvas_background'); - this.content.setAttribute('id', 'canvas_content'); + this.text.setAttribute('id', 'cvat_canvas_text_content'); + this.background.setAttribute('id', 'cvat_canvas_background'); + this.content.setAttribute('id', 'cvat_canvas_content'); // Setup wrappers - this.rotationWrapper.setAttribute('id', 'canvas_rotation_wrapper'); - this.canvas.setAttribute('id', 'canvas_wrapper'); + this.rotationWrapper.setAttribute('id', 'cvat_canvas_rotation_wrapper'); + this.canvas.setAttribute('id', 'cvat_canvas_wrapper'); // Unite created HTML elements together this.loadingAnimation.appendChild(loadingCircle); @@ -128,8 +131,8 @@ export class CanvasViewImpl implements CanvasView, Listener { const canvasFirstMounted = (event: AnimationEvent): void => { if (event.animationName === 'loadingAnimation') { self.controller.canvasSize = { - width: self.rotationWrapper.clientWidth, height: self.rotationWrapper.clientHeight, + width: self.rotationWrapper.clientWidth, }; self.rotationWrapper.removeEventListener('animationstart', canvasFirstMounted); @@ -171,25 +174,25 @@ export class CanvasViewImpl implements CanvasView, Listener { function resize(geometry: Geometry): void { for (const obj of [this.background, this.grid, this.loadingAnimation]) { - obj.style.width = `${geometry.image.width}`; - obj.style.height = `${geometry.image.height}`; + obj.style.width = `${geometry.image.width}px`; + obj.style.height = `${geometry.image.height}px`; } for (const obj of [this.content, this.text]) { - obj.style.width = `${geometry.image.width + geometry.offset * 2}`; - obj.style.height = `${geometry.image.height + geometry.offset * 2}`; + obj.style.width = `${geometry.image.width + geometry.offset * 2}px`; + obj.style.height = `${geometry.image.height + geometry.offset * 2}px`; } } function move(geometry: Geometry): void { for (const obj of [this.background, this.grid, this.loadingAnimation]) { - obj.style.top = `${geometry.top}`; - obj.style.left = `${geometry.left}`; + obj.style.top = `${geometry.top}px`; + obj.style.left = `${geometry.left}px`; } for (const obj of [this.content, this.text]) { - obj.style.top = `${geometry.top - geometry.offset * geometry.scale}`; - obj.style.left = `${geometry.left - geometry.offset * geometry.scale}`; + obj.style.top = `${geometry.top - geometry.offset * geometry.scale}px`; + obj.style.left = `${geometry.left - geometry.offset * geometry.scale}px`; } this.content.style.transform = `scale(${geometry.scale})`; @@ -198,9 +201,9 @@ export class CanvasViewImpl implements CanvasView, Listener { const { geometry } = this.controller; if (reason === UpdateReasons.IMAGE) { if (!model.image.length) { - this.loadingAnimation.classList.remove('canvas_hidden'); + this.loadingAnimation.classList.remove('cvat_canvas_hidden'); } else { - this.loadingAnimation.classList.add('canvas_hidden'); + this.loadingAnimation.classList.add('cvat_canvas_hidden'); this.background.style.backgroundImage = `url("${model.image}")`; move.call(this, geometry); resize.call(this, geometry); diff --git a/cvat-canvas/tslint.config.js b/cvat-canvas/tslint.config.js new file mode 100644 index 00000000..c237ed26 --- /dev/null +++ b/cvat-canvas/tslint.config.js @@ -0,0 +1,34 @@ +/* +* Copyright (C) 2018 Intel Corporation +* SPDX-License-Identifier: MIT +*/ + +/* eslint-disable */ + +module.exports = { + defaultSeverity: 'error', + extends: [ + 'tslint:recommended', + 'tslint-config-airbnb' + ], + jsRules: {}, + rulesDirectory: [], + rules: { + 'ter-indent': ['warn', 4], + // TypeScript guildline prevents interfaces names started with I + // https://github.com/Microsoft/TypeScript/wiki/Coding-guidelines#names + 'interface-name': false, + 'no-console': false, + // Arrow functions doesn't use closure context, but sometimes we need it + // At the same time typescript non-arrow functions are forbidden in TS + // So, we forced to disable this rule + 'no-this-assignment': false, + // Just a strange rule + 'no-shadowed-variable': false, + // Don't prevent ++ and -- operations (the same like in eslint) + 'no-increment-decrement': false, + }, + linterOptions: { + include: ['src/*.ts'] + } +}