diff --git a/.dockerignore b/.dockerignore index f0532579e1e..afe7b64b36d 100644 --- a/.dockerignore +++ b/.dockerignore @@ -6,6 +6,5 @@ /.vscode /db.sqlite3 /keys -/cvat-canvas **/node_modules diff --git a/Dockerfile.ui b/Dockerfile.ui index a1010edfc78..f31b89da1ae 100644 --- a/Dockerfile.ui +++ b/Dockerfile.ui @@ -22,22 +22,28 @@ RUN apt update && apt install -yq nodejs npm curl && \ npm install -g n && n 10.16.3 # Create output directories -RUN mkdir /tmp/cvat-ui /tmp/cvat-core +RUN mkdir /tmp/cvat-ui /tmp/cvat-core /tmp/cvat-canvas # Install dependencies COPY cvat-core/package*.json /tmp/cvat-core/ +COPY cvat-canvas/package*.json /tmp/cvat-canvas/ COPY cvat-ui/package*.json /tmp/cvat-ui/ # Install cvat-core dependencies WORKDIR /tmp/cvat-core/ RUN npm install +# Install cvat-canvas dependencies +WORKDIR /tmp/cvat-canvas/ +RUN npm install + # Install cvat-ui dependencies WORKDIR /tmp/cvat-ui/ RUN npm install # Build source code COPY cvat-core/ /tmp/cvat-core/ +COPY cvat-canvas/ /tmp/cvat-canvas/ COPY cvat-ui/ /tmp/cvat-ui/ RUN npm run build diff --git a/cvat-canvas/README.md b/cvat-canvas/README.md index e35f47d397b..61d6f4bca91 100644 --- a/cvat-canvas/README.md +++ b/cvat-canvas/README.md @@ -74,6 +74,7 @@ Canvas itself handles: activate(clientID: number, attributeID?: number): void; rotate(rotation: Rotation, remember?: boolean): void; focus(clientID: number, padding?: number): void; + fitCanvas(): void; fit(): void; grid(stepX: number, stepY: number): void; @@ -99,7 +100,7 @@ Canvas itself handles: - Drawn texts have the class ```cvat_canvas_text``` - Tags have the class ```cvat_canvas_tag``` - Canvas image has ID ```cvat_canvas_image``` -- Grid on the canvas has ID ```cvat_canvas_grid_pattern``` +- Grid on the canvas has ID ```cvat_canvas_grid``` and ```cvat_canvas_grid_pattern``` - Crosshair during a draw has class ```cvat_canvas_crosshair``` ### Events @@ -126,6 +127,7 @@ Standard JS events are used. // Put canvas to a html container htmlContainer.appendChild(canvas.html()); + canvas.fitCanvas(); // Next you can use its API methods. For example: canvas.rotate(window.Canvas.Rotation.CLOCKWISE90); @@ -182,17 +184,18 @@ Than you can use it in TypeScript: ## API Reaction -| | IDLE | GROUPING | SPLITTING | DRAWING | MERGING | EDITING | -|------------|------|----------|-----------|---------|---------|---------| -| html() | + | + | + | + | + | + | -| setup() | + | + | + | + | + | - | -| activate() | + | - | - | - | - | - | -| rotate() | + | + | + | + | + | + | -| focus() | + | + | + | + | + | + | -| fit() | + | + | + | + | + | + | -| grid() | + | + | + | + | + | + | -| draw() | + | - | - | - | - | - | -| split() | + | - | + | - | - | - | -| group | + | + | - | - | - | - | -| merge() | + | - | - | - | + | - | -| cancel() | - | + | + | + | + | + | +| | IDLE | GROUPING | SPLITTING | DRAWING | MERGING | EDITING | +|-------------|------|----------|-----------|---------|---------|---------| +| html() | + | + | + | + | + | + | +| setup() | + | + | + | + | + | - | +| activate() | + | - | - | - | - | - | +| rotate() | + | + | + | + | + | + | +| focus() | + | + | + | + | + | + | +| fit() | + | + | + | + | + | + | +| fitCanvas() | + | + | + | + | + | + | +| grid() | + | + | + | + | + | + | +| draw() | + | - | - | - | - | - | +| split() | + | - | + | - | - | - | +| group | + | + | - | - | - | - | +| merge() | + | - | - | - | + | - | +| cancel() | - | + | + | + | + | + | diff --git a/cvat-canvas/package-lock.json b/cvat-canvas/package-lock.json index d4ca3ddea7e..46c12b74665 100644 --- a/cvat-canvas/package-lock.json +++ b/cvat-canvas/package-lock.json @@ -885,6 +885,12 @@ "to-fast-properties": "^2.0.0" } }, + "@csstools/convert-colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@csstools/convert-colors/-/convert-colors-1.4.0.tgz", + "integrity": "sha512-5a6wqoJV/xEdbRNKVo6I4hO3VjyDq//8q2f9I6PBAvMesJHFauXDorcNCsr9RzvsZnaWi5NYCcfyqP1QeFHFbw==", + "dev": true + }, "@types/detect-indent": { "version": "0.1.30", "resolved": "https://registry.npmjs.org/@types/detect-indent/-/detect-indent-0.1.30.tgz", @@ -1232,6 +1238,12 @@ "integrity": "sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==", "dev": true }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", + "dev": true + }, "ansi-align": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-2.0.0.tgz", @@ -1301,6 +1313,16 @@ "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", "dev": true }, + "are-we-there-yet": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", + "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", + "dev": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, "argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -1328,6 +1350,12 @@ "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", "dev": true }, + "array-find-index": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", + "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", + "dev": true + }, "array-flatten": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", @@ -1365,6 +1393,15 @@ "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", "dev": true }, + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "dev": true, + "requires": { + "safer-buffer": "~2.1.0" + } + }, "asn1.js": { "version": "4.10.1", "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", @@ -1403,6 +1440,12 @@ } } }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + }, "assign-symbols": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", @@ -1427,12 +1470,108 @@ "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", "dev": true }, + "async-foreach": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/async-foreach/-/async-foreach-0.1.3.tgz", + "integrity": "sha1-NhIfhFwFeBct5Bmpfb6x0W7DRUI=", + "dev": true + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, "atob": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", "dev": true }, + "autoprefixer": { + "version": "9.7.3", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.7.3.tgz", + "integrity": "sha512-8T5Y1C5Iyj6PgkPSFd0ODvK9DIleuPKUPYniNxybS47g2k2wFgLZ46lGQHlBuGKIAEV8fbCDfKCCRS1tvOgc3Q==", + "dev": true, + "requires": { + "browserslist": "^4.8.0", + "caniuse-lite": "^1.0.30001012", + "chalk": "^2.4.2", + "normalize-range": "^0.1.2", + "num2fraction": "^1.2.2", + "postcss": "^7.0.23", + "postcss-value-parser": "^4.0.2" + }, + "dependencies": { + "browserslist": { + "version": "4.8.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.8.2.tgz", + "integrity": "sha512-+M4oeaTplPm/f1pXDw84YohEv7B1i/2Aisei8s4s6k3QsoSHa7i5sz8u/cGQkkatCPxMASKxPualR4wwYgVboA==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001015", + "electron-to-chromium": "^1.3.322", + "node-releases": "^1.1.42" + } + }, + "caniuse-lite": { + "version": "1.0.30001016", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001016.tgz", + "integrity": "sha512-yYQ2QfotceRiH4U+h1Us86WJXtVHDmy3nEKIdYPsZCYnOV5/tMgGbmoIlrMzmh2VXlproqYtVaKeGDBkMZifFA==", + "dev": true + }, + "electron-to-chromium": { + "version": "1.3.322", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.322.tgz", + "integrity": "sha512-Tc8JQEfGQ1MzfSzI/bTlSr7btJv/FFO7Yh6tanqVmIWOuNCu6/D1MilIEgLtmWqIrsv+o4IjpLAhgMBr/ncNAA==", + "dev": true + }, + "node-releases": { + "version": "1.1.44", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.44.tgz", + "integrity": "sha512-NwbdvJyR7nrcGrXvKAvzc5raj/NkoJudkarh2yIpJ4t0NH4aqjUDz/486P+ynIW5eokKOfzGNRdYoLfBlomruw==", + "dev": true, + "requires": { + "semver": "^6.3.0" + } + }, + "postcss": { + "version": "7.0.25", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.25.tgz", + "integrity": "sha512-NXXVvWq9icrm/TgQC0O6YVFi4StfJz46M1iNd/h6B26Nvh/HKI+q4YZtFN/EjcInZliEscO/WL10BXnc1E5nwg==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "dev": true + }, + "aws4": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.9.0.tgz", + "integrity": "sha512-Uvq6hVe90D0B2WEnUqtdgY1bATGz3mw33nH9Y+dmA+w5DHvUmBgkr5rM/KCHpCsiFNRUfokW/szpPPgMK2hm4A==", + "dev": true + }, "babel-loader": { "version": "8.0.6", "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.0.6.tgz", @@ -1527,6 +1666,15 @@ "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=", "dev": true }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "dev": true, + "requires": { + "tweetnacl": "^0.14.3" + } + }, "big.js": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", @@ -1539,6 +1687,15 @@ "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", "dev": true }, + "block-stream": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", + "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", + "dev": true, + "requires": { + "inherits": "~2.0.0" + } + }, "bluebird": { "version": "3.5.5", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.5.tgz", @@ -1821,6 +1978,32 @@ "unset-value": "^1.0.0" } }, + "caller-callsite": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", + "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=", + "dev": true, + "requires": { + "callsites": "^2.0.0" + }, + "dependencies": { + "callsites": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", + "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=", + "dev": true + } + } + }, + "caller-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz", + "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=", + "dev": true, + "requires": { + "caller-callsite": "^2.0.0" + } + }, "callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -1833,6 +2016,24 @@ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true }, + "camelcase-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", + "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", + "dev": true, + "requires": { + "camelcase": "^2.0.0", + "map-obj": "^1.0.0" + }, + "dependencies": { + "camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", + "dev": true + } + } + }, "caniuse-lite": { "version": "1.0.30000985", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000985.tgz", @@ -1845,6 +2046,12 @@ "integrity": "sha512-mYQLZnx5Qt1JgB1WEiMCf2647plpGeQ2NMR/5L0HNZzGQo4fuSPnK+wjfPnKZV0aiJDgzmWqqkV/g7JD+DW0qw==", "dev": true }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "dev": true + }, "chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", @@ -1996,6 +2203,17 @@ } } }, + "clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + } + }, "code-point-at": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", @@ -2027,6 +2245,15 @@ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", "dev": true }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "requires": { + "delayed-stream": "~1.0.0" + } + }, "commander": { "version": "2.20.0", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", @@ -2139,6 +2366,12 @@ "date-now": "^0.1.4" } }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", + "dev": true + }, "constants-browserify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", @@ -2238,6 +2471,40 @@ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", "dev": true }, + "cosmiconfig": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", + "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", + "dev": true, + "requires": { + "import-fresh": "^2.0.0", + "is-directory": "^0.3.1", + "js-yaml": "^3.13.1", + "parse-json": "^4.0.0" + }, + "dependencies": { + "import-fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", + "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=", + "dev": true, + "requires": { + "caller-path": "^2.0.0", + "resolve-from": "^3.0.0" + } + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + } + } + }, "create-ecdh": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", @@ -2322,6 +2589,44 @@ "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=", "dev": true }, + "css-blank-pseudo": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/css-blank-pseudo/-/css-blank-pseudo-0.1.4.tgz", + "integrity": "sha512-LHz35Hr83dnFeipc7oqFDmsjHdljj3TQtxGGiNWSOsTLIAubSm4TEz8qCaKFpk7idaQ1GfWscF4E6mgpBysA1w==", + "dev": true, + "requires": { + "postcss": "^7.0.5" + } + }, + "css-has-pseudo": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/css-has-pseudo/-/css-has-pseudo-0.10.0.tgz", + "integrity": "sha512-Z8hnfsZu4o/kt+AuFzeGpLVhFOGO9mluyHBaA2bA8aCGTwah5sT3WV/fTHH8UNZUytOIImuGPrl/prlb4oX4qQ==", + "dev": true, + "requires": { + "postcss": "^7.0.6", + "postcss-selector-parser": "^5.0.0-rc.4" + }, + "dependencies": { + "cssesc": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-2.0.0.tgz", + "integrity": "sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg==", + "dev": true + }, + "postcss-selector-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz", + "integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==", + "dev": true, + "requires": { + "cssesc": "^2.0.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + } + } + }, "css-loader": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-3.2.0.tgz", @@ -2354,18 +2659,51 @@ } } }, + "css-prefers-color-scheme": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/css-prefers-color-scheme/-/css-prefers-color-scheme-3.1.1.tgz", + "integrity": "sha512-MTu6+tMs9S3EUqzmqLXEcgNRbNkkD/TGFvowpeoWJn5Vfq7FMgsmRQs9X5NXAURiOBmOxm/lLjsDNXDE6k9bhg==", + "dev": true, + "requires": { + "postcss": "^7.0.5" + } + }, + "cssdb": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/cssdb/-/cssdb-4.4.0.tgz", + "integrity": "sha512-LsTAR1JPEM9TpGhl/0p3nQecC2LJ0kD8X5YARu1hk/9I1gril5vDtMZyNxcEpxxDj34YNck/ucjuoUd66K03oQ==", + "dev": true + }, "cssesc": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", "dev": true }, + "currently-unhandled": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", + "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", + "dev": true, + "requires": { + "array-find-index": "^1.0.1" + } + }, "cyclist": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-0.2.2.tgz", "integrity": "sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA=", "dev": true }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, "date-now": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", @@ -2486,6 +2824,18 @@ "rimraf": "^2.6.3" } }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", + "dev": true + }, "depd": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", @@ -2672,6 +3022,16 @@ "stream-shift": "^1.0.0" } }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "dev": true, + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -3266,6 +3626,12 @@ } } }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, "extend-shallow": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", @@ -3363,6 +3729,12 @@ } } }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "dev": true + }, "fast-deep-equal": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", @@ -3501,6 +3873,12 @@ "integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==", "dev": true }, + "flatten": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.3.tgz", + "integrity": "sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg==", + "dev": true + }, "flush-write-stream": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", @@ -3543,6 +3921,23 @@ "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", "dev": true }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, "forwarded": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", @@ -4146,6 +4541,18 @@ } } }, + "fstream": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", + "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "inherits": "~2.0.0", + "mkdirp": ">=0.5 0", + "rimraf": "2" + } + }, "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", @@ -4158,6 +4565,53 @@ "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", "dev": true }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "dev": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + } + } + }, + "gaze": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz", + "integrity": "sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==", + "dev": true, + "requires": { + "globule": "^1.0.0" + } + }, "get-caller-file": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", @@ -4185,6 +4639,15 @@ "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", "dev": true }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, "glob": { "version": "7.1.4", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", @@ -4291,6 +4754,17 @@ } } }, + "globule": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/globule/-/globule-1.3.0.tgz", + "integrity": "sha512-YlD4kdMqRCQHrhVdonet4TdRtv1/sZKepvoxNT4Nrhrp5HI8XFfc8kFlGlBn2myBo80aGp8Eft259mbcUJhgSg==", + "dev": true, + "requires": { + "glob": "~7.1.1", + "lodash": "~4.17.10", + "minimatch": "~3.0.2" + } + }, "got": { "version": "6.7.1", "resolved": "https://registry.npmjs.org/got/-/got-6.7.1.tgz", @@ -4330,15 +4804,40 @@ "integrity": "sha512-d4sze1JNC454Wdo2fkuyzCr6aHcbL6PGGuFAz0Li/NcOm1tCHGnWDRmJP85dh9IhQErTc2svWFEX5xHIOo//kQ==", "dev": true }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "dev": true + }, + "har-validator": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", + "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "dev": true, + "requires": { + "ajv": "^6.5.5", + "har-schema": "^2.0.0" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", "dev": true, "requires": { "function-bind": "^1.1.1" } }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -4351,6 +4850,12 @@ "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", "dev": true }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", + "dev": true + }, "has-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", @@ -4506,6 +5011,17 @@ "micromatch": "^3.1.10" } }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, "https-browserify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", @@ -4554,6 +5070,15 @@ "integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk=", "dev": true }, + "import-cwd": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-cwd/-/import-cwd-2.1.0.tgz", + "integrity": "sha1-qmzzbnInYShcs3HsZRn1PiQ1sKk=", + "dev": true, + "requires": { + "import-from": "^2.1.0" + } + }, "import-fresh": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.1.0.tgz", @@ -4572,6 +5097,15 @@ } } }, + "import-from": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-from/-/import-from-2.1.0.tgz", + "integrity": "sha1-M1238qev/VOqpHHUuAId7ja387E=", + "dev": true, + "requires": { + "resolve-from": "^3.0.0" + } + }, "import-lazy": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", @@ -4594,6 +5128,21 @@ "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", "dev": true }, + "in-publish": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/in-publish/-/in-publish-2.0.0.tgz", + "integrity": "sha1-4g/146KvwmkDILbcVSaCqcf631E=", + "dev": true + }, + "indent-string": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", + "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", + "dev": true, + "requires": { + "repeating": "^2.0.0" + } + }, "indexes-of": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", @@ -4810,6 +5359,12 @@ } } }, + "is-directory": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", + "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=", + "dev": true + }, "is-extendable": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", @@ -4822,6 +5377,15 @@ "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", "dev": true }, + "is-finite": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", + "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, "is-fullwidth-code-point": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", @@ -4971,6 +5535,18 @@ "has-symbols": "^1.0.0" } }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, "is-windows": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", @@ -5001,6 +5577,18 @@ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", "dev": true }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true + }, + "js-base64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.5.1.tgz", + "integrity": "sha512-M7kLczedRMYX4L8Mdh4MzyAMM9O5osx+4FcOQuTvr3A9F2D9S5JXheN0ewNbrvK2UatkTRhL5ejGmGSjNMiZuw==", + "dev": true + }, "js-levenshtein": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.6.tgz", @@ -5023,6 +5611,12 @@ "esprima": "^4.0.0" } }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true + }, "jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", @@ -5035,6 +5629,12 @@ "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", "dev": true }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "dev": true + }, "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -5047,6 +5647,12 @@ "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", "dev": true }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, "json3": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.3.tgz", @@ -5062,6 +5668,18 @@ "minimist": "^1.2.0" } }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, "killable": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz", @@ -5155,6 +5773,31 @@ "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", "dev": true }, + "lodash._reinterpolate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", + "dev": true + }, + "lodash.template": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz", + "integrity": "sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==", + "dev": true, + "requires": { + "lodash._reinterpolate": "^3.0.0", + "lodash.templatesettings": "^4.0.0" + } + }, + "lodash.templatesettings": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz", + "integrity": "sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==", + "dev": true, + "requires": { + "lodash._reinterpolate": "^3.0.0" + } + }, "lodash.unescape": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/lodash.unescape/-/lodash.unescape-4.0.1.tgz", @@ -5176,6 +5819,16 @@ "js-tokens": "^3.0.0 || ^4.0.0" } }, + "loud-rejection": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", + "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", + "dev": true, + "requires": { + "currently-unhandled": "^0.4.1", + "signal-exit": "^3.0.0" + } + }, "lowercase-keys": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", @@ -5222,6 +5875,12 @@ "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", "dev": true }, + "map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", + "dev": true + }, "map-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", @@ -5269,6 +5928,105 @@ "readable-stream": "^2.0.1" } }, + "meow": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", + "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", + "dev": true, + "requires": { + "camelcase-keys": "^2.0.0", + "decamelize": "^1.1.2", + "loud-rejection": "^1.0.0", + "map-obj": "^1.0.1", + "minimist": "^1.1.3", + "normalize-package-data": "^2.3.4", + "object-assign": "^4.0.1", + "read-pkg-up": "^1.0.1", + "redent": "^1.0.0", + "trim-newlines": "^1.0.0" + }, + "dependencies": { + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + } + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "requires": { + "pinkie-promise": "^2.0.0" + } + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "dev": true, + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "dev": true, + "requires": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "^0.2.0" + } + } + } + }, "merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", @@ -5468,8 +6226,7 @@ "version": "2.14.0", "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", - "dev": true, - "optional": true + "dev": true }, "nanomatch": { "version": "1.2.13", @@ -5520,6 +6277,43 @@ "integrity": "sha512-MmbQJ2MTESTjt3Gi/3yG1wGpIMhUfcIypUCGtTizFR9IiccFwxSpfp0vtIZlkFclEqERemxfnSdZEMR9VqqEFQ==", "dev": true }, + "node-gyp": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.8.0.tgz", + "integrity": "sha512-3g8lYefrRRzvGeSowdJKAKyks8oUpLEd/DyPV4eMhVlhJ0aNaZqIrNUIPuEWWTAoPqyFkfGrM67MC69baqn6vA==", + "dev": true, + "requires": { + "fstream": "^1.0.0", + "glob": "^7.0.3", + "graceful-fs": "^4.1.2", + "mkdirp": "^0.5.0", + "nopt": "2 || 3", + "npmlog": "0 || 1 || 2 || 3 || 4", + "osenv": "0", + "request": "^2.87.0", + "rimraf": "2", + "semver": "~5.3.0", + "tar": "^2.0.0", + "which": "1" + }, + "dependencies": { + "nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "dev": true, + "requires": { + "abbrev": "1" + } + }, + "semver": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", + "dev": true + } + } + }, "node-libs-browser": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", @@ -5568,6 +6362,90 @@ "semver": "^5.3.0" } }, + "node-sass": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.13.0.tgz", + "integrity": "sha512-W1XBrvoJ1dy7VsvTAS5q1V45lREbTlZQqFbiHb3R3OTTCma0XBtuG6xZ6Z4506nR4lmHPTqVRwxT6KgtWC97CA==", + "dev": true, + "requires": { + "async-foreach": "^0.1.3", + "chalk": "^1.1.1", + "cross-spawn": "^3.0.0", + "gaze": "^1.0.0", + "get-stdin": "^4.0.1", + "glob": "^7.0.3", + "in-publish": "^2.0.0", + "lodash": "^4.17.15", + "meow": "^3.7.0", + "mkdirp": "^0.5.1", + "nan": "^2.13.2", + "node-gyp": "^3.8.0", + "npmlog": "^4.0.0", + "request": "^2.88.0", + "sass-graph": "^2.2.4", + "stdout-stream": "^1.4.0", + "true-case-path": "^1.0.2" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "cross-spawn": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-3.0.1.tgz", + "integrity": "sha1-ElYDfsufDF9549bvE14wdwGEuYI=", + "dev": true, + "requires": { + "lru-cache": "^4.0.1", + "which": "^1.2.9" + } + }, + "get-stdin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", + "dev": true + }, + "lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dev": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + } + } + }, "nodemon": { "version": "1.19.1", "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-1.19.1.tgz", @@ -5639,6 +6517,12 @@ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true }, + "normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", + "dev": true + }, "npm-run-path": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", @@ -5648,12 +6532,36 @@ "path-key": "^2.0.0" } }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dev": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "num2fraction": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", + "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=", + "dev": true + }, "number-is-nan": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", "dev": true }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "dev": true + }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -5836,6 +6744,12 @@ "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", "dev": true }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true + }, "os-locale": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", @@ -5853,6 +6767,16 @@ "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "dev": true }, + "osenv": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "dev": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, "output-file-sync": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/output-file-sync/-/output-file-sync-2.0.1.tgz", @@ -6078,6 +7002,12 @@ "sha.js": "^2.4.8" } }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", + "dev": true + }, "pify": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", @@ -6144,6 +7074,291 @@ } } }, + "postcss-attribute-case-insensitive": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-4.0.1.tgz", + "integrity": "sha512-L2YKB3vF4PetdTIthQVeT+7YiSzMoNMLLYxPXXppOOP7NoazEAy45sh2LvJ8leCQjfBcfkYQs8TtCcQjeZTp8A==", + "dev": true, + "requires": { + "postcss": "^7.0.2", + "postcss-selector-parser": "^5.0.0" + }, + "dependencies": { + "cssesc": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-2.0.0.tgz", + "integrity": "sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg==", + "dev": true + }, + "postcss-selector-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz", + "integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==", + "dev": true, + "requires": { + "cssesc": "^2.0.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + } + } + }, + "postcss-color-functional-notation": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/postcss-color-functional-notation/-/postcss-color-functional-notation-2.0.1.tgz", + "integrity": "sha512-ZBARCypjEDofW4P6IdPVTLhDNXPRn8T2s1zHbZidW6rPaaZvcnCS2soYFIQJrMZSxiePJ2XIYTlcb2ztr/eT2g==", + "dev": true, + "requires": { + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" + } + }, + "postcss-color-gray": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-color-gray/-/postcss-color-gray-5.0.0.tgz", + "integrity": "sha512-q6BuRnAGKM/ZRpfDascZlIZPjvwsRye7UDNalqVz3s7GDxMtqPY6+Q871liNxsonUw8oC61OG+PSaysYpl1bnw==", + "dev": true, + "requires": { + "@csstools/convert-colors": "^1.4.0", + "postcss": "^7.0.5", + "postcss-values-parser": "^2.0.0" + } + }, + "postcss-color-hex-alpha": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/postcss-color-hex-alpha/-/postcss-color-hex-alpha-5.0.3.tgz", + "integrity": "sha512-PF4GDel8q3kkreVXKLAGNpHKilXsZ6xuu+mOQMHWHLPNyjiUBOr75sp5ZKJfmv1MCus5/DWUGcK9hm6qHEnXYw==", + "dev": true, + "requires": { + "postcss": "^7.0.14", + "postcss-values-parser": "^2.0.1" + } + }, + "postcss-color-mod-function": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/postcss-color-mod-function/-/postcss-color-mod-function-3.0.3.tgz", + "integrity": "sha512-YP4VG+xufxaVtzV6ZmhEtc+/aTXH3d0JLpnYfxqTvwZPbJhWqp8bSY3nfNzNRFLgB4XSaBA82OE4VjOOKpCdVQ==", + "dev": true, + "requires": { + "@csstools/convert-colors": "^1.4.0", + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" + } + }, + "postcss-color-rebeccapurple": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-4.0.1.tgz", + "integrity": "sha512-aAe3OhkS6qJXBbqzvZth2Au4V3KieR5sRQ4ptb2b2O8wgvB3SJBsdG+jsn2BZbbwekDG8nTfcCNKcSfe/lEy8g==", + "dev": true, + "requires": { + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" + } + }, + "postcss-custom-media": { + "version": "7.0.8", + "resolved": "https://registry.npmjs.org/postcss-custom-media/-/postcss-custom-media-7.0.8.tgz", + "integrity": "sha512-c9s5iX0Ge15o00HKbuRuTqNndsJUbaXdiNsksnVH8H4gdc+zbLzr/UasOwNG6CTDpLFekVY4672eWdiiWu2GUg==", + "dev": true, + "requires": { + "postcss": "^7.0.14" + } + }, + "postcss-custom-properties": { + "version": "8.0.11", + "resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-8.0.11.tgz", + "integrity": "sha512-nm+o0eLdYqdnJ5abAJeXp4CEU1c1k+eB2yMCvhgzsds/e0umabFrN6HoTy/8Q4K5ilxERdl/JD1LO5ANoYBeMA==", + "dev": true, + "requires": { + "postcss": "^7.0.17", + "postcss-values-parser": "^2.0.1" + } + }, + "postcss-custom-selectors": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/postcss-custom-selectors/-/postcss-custom-selectors-5.1.2.tgz", + "integrity": "sha512-DSGDhqinCqXqlS4R7KGxL1OSycd1lydugJ1ky4iRXPHdBRiozyMHrdu0H3o7qNOCiZwySZTUI5MV0T8QhCLu+w==", + "dev": true, + "requires": { + "postcss": "^7.0.2", + "postcss-selector-parser": "^5.0.0-rc.3" + }, + "dependencies": { + "cssesc": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-2.0.0.tgz", + "integrity": "sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg==", + "dev": true + }, + "postcss-selector-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz", + "integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==", + "dev": true, + "requires": { + "cssesc": "^2.0.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + } + } + }, + "postcss-dir-pseudo-class": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-5.0.0.tgz", + "integrity": "sha512-3pm4oq8HYWMZePJY+5ANriPs3P07q+LW6FAdTlkFH2XqDdP4HeeJYMOzn0HYLhRSjBO3fhiqSwwU9xEULSrPgw==", + "dev": true, + "requires": { + "postcss": "^7.0.2", + "postcss-selector-parser": "^5.0.0-rc.3" + }, + "dependencies": { + "cssesc": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-2.0.0.tgz", + "integrity": "sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg==", + "dev": true + }, + "postcss-selector-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz", + "integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==", + "dev": true, + "requires": { + "cssesc": "^2.0.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + } + } + }, + "postcss-double-position-gradients": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/postcss-double-position-gradients/-/postcss-double-position-gradients-1.0.0.tgz", + "integrity": "sha512-G+nV8EnQq25fOI8CH/B6krEohGWnF5+3A6H/+JEpOncu5dCnkS1QQ6+ct3Jkaepw1NGVqqOZH6lqrm244mCftA==", + "dev": true, + "requires": { + "postcss": "^7.0.5", + "postcss-values-parser": "^2.0.0" + } + }, + "postcss-env-function": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/postcss-env-function/-/postcss-env-function-2.0.2.tgz", + "integrity": "sha512-rwac4BuZlITeUbiBq60h/xbLzXY43qOsIErngWa4l7Mt+RaSkT7QBjXVGTcBHupykkblHMDrBFh30zchYPaOUw==", + "dev": true, + "requires": { + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" + } + }, + "postcss-focus-visible": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-focus-visible/-/postcss-focus-visible-4.0.0.tgz", + "integrity": "sha512-Z5CkWBw0+idJHSV6+Bgf2peDOFf/x4o+vX/pwcNYrWpXFrSfTkQ3JQ1ojrq9yS+upnAlNRHeg8uEwFTgorjI8g==", + "dev": true, + "requires": { + "postcss": "^7.0.2" + } + }, + "postcss-focus-within": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-focus-within/-/postcss-focus-within-3.0.0.tgz", + "integrity": "sha512-W0APui8jQeBKbCGZudW37EeMCjDeVxKgiYfIIEo8Bdh5SpB9sxds/Iq8SEuzS0Q4YFOlG7EPFulbbxujpkrV2w==", + "dev": true, + "requires": { + "postcss": "^7.0.2" + } + }, + "postcss-font-variant": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-font-variant/-/postcss-font-variant-4.0.0.tgz", + "integrity": "sha512-M8BFYKOvCrI2aITzDad7kWuXXTm0YhGdP9Q8HanmN4EF1Hmcgs1KK5rSHylt/lUJe8yLxiSwWAHdScoEiIxztg==", + "dev": true, + "requires": { + "postcss": "^7.0.2" + } + }, + "postcss-gap-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-gap-properties/-/postcss-gap-properties-2.0.0.tgz", + "integrity": "sha512-QZSqDaMgXCHuHTEzMsS2KfVDOq7ZFiknSpkrPJY6jmxbugUPTuSzs/vuE5I3zv0WAS+3vhrlqhijiprnuQfzmg==", + "dev": true, + "requires": { + "postcss": "^7.0.2" + } + }, + "postcss-image-set-function": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/postcss-image-set-function/-/postcss-image-set-function-3.0.1.tgz", + "integrity": "sha512-oPTcFFip5LZy8Y/whto91L9xdRHCWEMs3e1MdJxhgt4jy2WYXfhkng59fH5qLXSCPN8k4n94p1Czrfe5IOkKUw==", + "dev": true, + "requires": { + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" + } + }, + "postcss-initial": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/postcss-initial/-/postcss-initial-3.0.2.tgz", + "integrity": "sha512-ugA2wKonC0xeNHgirR4D3VWHs2JcU08WAi1KFLVcnb7IN89phID6Qtg2RIctWbnvp1TM2BOmDtX8GGLCKdR8YA==", + "dev": true, + "requires": { + "lodash.template": "^4.5.0", + "postcss": "^7.0.2" + } + }, + "postcss-lab-function": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/postcss-lab-function/-/postcss-lab-function-2.0.1.tgz", + "integrity": "sha512-whLy1IeZKY+3fYdqQFuDBf8Auw+qFuVnChWjmxm/UhHWqNHZx+B99EwxTvGYmUBqe3Fjxs4L1BoZTJmPu6usVg==", + "dev": true, + "requires": { + "@csstools/convert-colors": "^1.4.0", + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" + } + }, + "postcss-load-config": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-2.1.0.tgz", + "integrity": "sha512-4pV3JJVPLd5+RueiVVB+gFOAa7GWc25XQcMp86Zexzke69mKf6Nx9LRcQywdz7yZI9n1udOxmLuAwTBypypF8Q==", + "dev": true, + "requires": { + "cosmiconfig": "^5.0.0", + "import-cwd": "^2.0.0" + } + }, + "postcss-loader": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-3.0.0.tgz", + "integrity": "sha512-cLWoDEY5OwHcAjDnkyRQzAXfs2jrKjXpO/HQFcc5b5u/r7aa471wdmChmwfnv7x2u840iat/wi0lQ5nbRgSkUA==", + "dev": true, + "requires": { + "loader-utils": "^1.1.0", + "postcss": "^7.0.0", + "postcss-load-config": "^2.0.0", + "schema-utils": "^1.0.0" + } + }, + "postcss-logical": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-logical/-/postcss-logical-3.0.0.tgz", + "integrity": "sha512-1SUKdJc2vuMOmeItqGuNaC+N8MzBWFWEkAnRnLpFYj1tGGa7NqyVBujfRtgNa2gXR+6RkGUiB2O5Vmh7E2RmiA==", + "dev": true, + "requires": { + "postcss": "^7.0.2" + } + }, + "postcss-media-minmax": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-media-minmax/-/postcss-media-minmax-4.0.0.tgz", + "integrity": "sha512-fo9moya6qyxsjbFAYl97qKO9gyre3qvbMnkOZeZwlsW6XYFsvs2DMGDlchVLfAd8LHPZDxivu/+qW2SMQeTHBw==", + "dev": true, + "requires": { + "postcss": "^7.0.2" + } + }, "postcss-modules-extract-imports": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz", @@ -6159,30 +7374,170 @@ "integrity": "sha512-jM/V8eqM4oJ/22j0gx4jrp63GSvDH6v86OqyTHHUvk4/k1vceipZsaymiZ5PvocqZOl5SFHiFJqjs3la0wnfIQ==", "dev": true, "requires": { - "icss-utils": "^4.1.1", - "postcss": "^7.0.16", - "postcss-selector-parser": "^6.0.2", - "postcss-value-parser": "^4.0.0" + "icss-utils": "^4.1.1", + "postcss": "^7.0.16", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.0.0" + } + }, + "postcss-modules-scope": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-2.1.0.tgz", + "integrity": "sha512-91Rjps0JnmtUB0cujlc8KIKCsJXWjzuxGeT/+Q2i2HXKZ7nBUeF9YQTZZTNvHVoNYj1AthsjnGLtqDUE0Op79A==", + "dev": true, + "requires": { + "postcss": "^7.0.6", + "postcss-selector-parser": "^6.0.0" + } + }, + "postcss-modules-values": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-3.0.0.tgz", + "integrity": "sha512-1//E5jCBrZ9DmRX+zCtmQtRSV6PV42Ix7Bzj9GbwJceduuf7IqP8MgeTXuRDHOWj2m0VzZD5+roFWDuU8RQjcg==", + "dev": true, + "requires": { + "icss-utils": "^4.0.0", + "postcss": "^7.0.6" + } + }, + "postcss-nesting": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-7.0.1.tgz", + "integrity": "sha512-FrorPb0H3nuVq0Sff7W2rnc3SmIcruVC6YwpcS+k687VxyxO33iE1amna7wHuRVzM8vfiYofXSBHNAZ3QhLvYg==", + "dev": true, + "requires": { + "postcss": "^7.0.2" + } + }, + "postcss-overflow-shorthand": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-overflow-shorthand/-/postcss-overflow-shorthand-2.0.0.tgz", + "integrity": "sha512-aK0fHc9CBNx8jbzMYhshZcEv8LtYnBIRYQD5i7w/K/wS9c2+0NSR6B3OVMu5y0hBHYLcMGjfU+dmWYNKH0I85g==", + "dev": true, + "requires": { + "postcss": "^7.0.2" + } + }, + "postcss-page-break": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-page-break/-/postcss-page-break-2.0.0.tgz", + "integrity": "sha512-tkpTSrLpfLfD9HvgOlJuigLuk39wVTbbd8RKcy8/ugV2bNBUW3xU+AIqyxhDrQr1VUj1RmyJrBn1YWrqUm9zAQ==", + "dev": true, + "requires": { + "postcss": "^7.0.2" + } + }, + "postcss-place": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-place/-/postcss-place-4.0.1.tgz", + "integrity": "sha512-Zb6byCSLkgRKLODj/5mQugyuj9bvAAw9LqJJjgwz5cYryGeXfFZfSXoP1UfveccFmeq0b/2xxwcTEVScnqGxBg==", + "dev": true, + "requires": { + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" + } + }, + "postcss-preset-env": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-6.7.0.tgz", + "integrity": "sha512-eU4/K5xzSFwUFJ8hTdTQzo2RBLbDVt83QZrAvI07TULOkmyQlnYlpwep+2yIK+K+0KlZO4BvFcleOCCcUtwchg==", + "dev": true, + "requires": { + "autoprefixer": "^9.6.1", + "browserslist": "^4.6.4", + "caniuse-lite": "^1.0.30000981", + "css-blank-pseudo": "^0.1.4", + "css-has-pseudo": "^0.10.0", + "css-prefers-color-scheme": "^3.1.1", + "cssdb": "^4.4.0", + "postcss": "^7.0.17", + "postcss-attribute-case-insensitive": "^4.0.1", + "postcss-color-functional-notation": "^2.0.1", + "postcss-color-gray": "^5.0.0", + "postcss-color-hex-alpha": "^5.0.3", + "postcss-color-mod-function": "^3.0.3", + "postcss-color-rebeccapurple": "^4.0.1", + "postcss-custom-media": "^7.0.8", + "postcss-custom-properties": "^8.0.11", + "postcss-custom-selectors": "^5.1.2", + "postcss-dir-pseudo-class": "^5.0.0", + "postcss-double-position-gradients": "^1.0.0", + "postcss-env-function": "^2.0.2", + "postcss-focus-visible": "^4.0.0", + "postcss-focus-within": "^3.0.0", + "postcss-font-variant": "^4.0.0", + "postcss-gap-properties": "^2.0.0", + "postcss-image-set-function": "^3.0.1", + "postcss-initial": "^3.0.0", + "postcss-lab-function": "^2.0.1", + "postcss-logical": "^3.0.0", + "postcss-media-minmax": "^4.0.0", + "postcss-nesting": "^7.0.0", + "postcss-overflow-shorthand": "^2.0.0", + "postcss-page-break": "^2.0.0", + "postcss-place": "^4.0.1", + "postcss-pseudo-class-any-link": "^6.0.0", + "postcss-replace-overflow-wrap": "^3.0.0", + "postcss-selector-matches": "^4.0.0", + "postcss-selector-not": "^4.0.0" + } + }, + "postcss-pseudo-class-any-link": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-6.0.0.tgz", + "integrity": "sha512-lgXW9sYJdLqtmw23otOzrtbDXofUdfYzNm4PIpNE322/swES3VU9XlXHeJS46zT2onFO7V1QFdD4Q9LiZj8mew==", + "dev": true, + "requires": { + "postcss": "^7.0.2", + "postcss-selector-parser": "^5.0.0-rc.3" + }, + "dependencies": { + "cssesc": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-2.0.0.tgz", + "integrity": "sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg==", + "dev": true + }, + "postcss-selector-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz", + "integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==", + "dev": true, + "requires": { + "cssesc": "^2.0.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + } + } + }, + "postcss-replace-overflow-wrap": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-3.0.0.tgz", + "integrity": "sha512-2T5hcEHArDT6X9+9dVSPQdo7QHzG4XKclFT8rU5TzJPDN7RIRTbO9c4drUISOVemLj03aezStHCR2AIcr8XLpw==", + "dev": true, + "requires": { + "postcss": "^7.0.2" } }, - "postcss-modules-scope": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-2.1.0.tgz", - "integrity": "sha512-91Rjps0JnmtUB0cujlc8KIKCsJXWjzuxGeT/+Q2i2HXKZ7nBUeF9YQTZZTNvHVoNYj1AthsjnGLtqDUE0Op79A==", + "postcss-selector-matches": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-matches/-/postcss-selector-matches-4.0.0.tgz", + "integrity": "sha512-LgsHwQR/EsRYSqlwdGzeaPKVT0Ml7LAT6E75T8W8xLJY62CE4S/l03BWIt3jT8Taq22kXP08s2SfTSzaraoPww==", "dev": true, "requires": { - "postcss": "^7.0.6", - "postcss-selector-parser": "^6.0.0" + "balanced-match": "^1.0.0", + "postcss": "^7.0.2" } }, - "postcss-modules-values": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-3.0.0.tgz", - "integrity": "sha512-1//E5jCBrZ9DmRX+zCtmQtRSV6PV42Ix7Bzj9GbwJceduuf7IqP8MgeTXuRDHOWj2m0VzZD5+roFWDuU8RQjcg==", + "postcss-selector-not": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-not/-/postcss-selector-not-4.0.0.tgz", + "integrity": "sha512-W+bkBZRhqJaYN8XAnbbZPLWMvZD1wKTu0UxtFKdhtGjWYmxhkUneoeOhRJKdAE5V7ZTlnbHfCR+6bNwK9e1dTQ==", "dev": true, "requires": { - "icss-utils": "^4.0.0", - "postcss": "^7.0.6" + "balanced-match": "^1.0.0", + "postcss": "^7.0.2" } }, "postcss-selector-parser": { @@ -6202,6 +7557,17 @@ "integrity": "sha512-LmeoohTpp/K4UiyQCwuGWlONxXamGzCMtFxLq4W1nZVGIQLYvMCJx3yAF9qyyuFpflABI9yVdtJAqbihOsCsJQ==", "dev": true }, + "postcss-values-parser": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/postcss-values-parser/-/postcss-values-parser-2.0.1.tgz", + "integrity": "sha512-2tLuBsA6P4rYTNKCXYG/71C7j1pU6pK503suYOmn4xYrQIzW+opD+7FAFNuGSdZC/3Qfy334QbeMu7MEb8gOxg==", + "dev": true, + "requires": { + "flatten": "^1.0.2", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + }, "prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", @@ -6266,6 +7632,12 @@ "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", "dev": true }, + "psl": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.6.0.tgz", + "integrity": "sha512-SYKKmVel98NCOYXpkwUqZqh0ahZeeKfmisiLIcEZdsb+WbLv02g/dI5BUmZnIyOe7RzZtLax81nnb2HbvC2tzA==", + "dev": true + }, "pstree.remy": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.7.tgz", @@ -6498,6 +7870,16 @@ "readable-stream": "^2.0.2" } }, + "redent": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", + "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", + "dev": true, + "requires": { + "indent-string": "^2.1.0", + "strip-indent": "^1.0.1" + } + }, "regenerate": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", @@ -6618,6 +8000,51 @@ "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", "dev": true }, + "repeating": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "dev": true, + "requires": { + "is-finite": "^1.0.0" + } + }, + "request": { + "version": "2.88.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", + "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", + "dev": true, + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.0", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.4.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "dependencies": { + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "dev": true + } + } + }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -6778,6 +8205,233 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true }, + "sass-graph": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-2.2.4.tgz", + "integrity": "sha1-E/vWPNHK8JCLn9k0dq1DpR0eC0k=", + "dev": true, + "requires": { + "glob": "^7.0.0", + "lodash": "^4.0.0", + "scss-tokenizer": "^0.2.3", + "yargs": "^7.0.0" + }, + "dependencies": { + "camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", + "dev": true + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + } + }, + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true, + "requires": { + "invert-kv": "^1.0.0" + } + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + } + }, + "os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "dev": true, + "requires": { + "lcid": "^1.0.0" + } + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "requires": { + "pinkie-promise": "^2.0.0" + } + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "dev": true, + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "dev": true, + "requires": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "^0.2.0" + } + }, + "which-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", + "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", + "dev": true + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true + }, + "yargs": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.0.tgz", + "integrity": "sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg=", + "dev": true, + "requires": { + "camelcase": "^3.0.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^1.4.0", + "read-pkg-up": "^1.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^1.0.2", + "which-module": "^1.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^5.0.0" + } + }, + "yargs-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0.tgz", + "integrity": "sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo=", + "dev": true, + "requires": { + "camelcase": "^3.0.0" + } + } + } + }, + "sass-loader": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-8.0.0.tgz", + "integrity": "sha512-+qeMu563PN7rPdit2+n5uuYVR0SSVwm0JsOUsaJXzgYcClWSlmX0iHDnmeOobPkf5kUglVot3QS6SyLyaQoJ4w==", + "dev": true, + "requires": { + "clone-deep": "^4.0.1", + "loader-utils": "^1.2.3", + "neo-async": "^2.6.1", + "schema-utils": "^2.1.0", + "semver": "^6.3.0" + }, + "dependencies": { + "schema-utils": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.6.1.tgz", + "integrity": "sha512-0WXHDs1VDJyo+Zqs9TKLKyD/h7yDpHUhEFsM2CzkICFdoX1av+GBq/J2xRTFfsQO5kBfhZzANf2VcIm84jqDbg==", + "dev": true, + "requires": { + "ajv": "^6.10.2", + "ajv-keywords": "^3.4.1" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, "schema-utils": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", @@ -6789,6 +8443,27 @@ "ajv-keywords": "^3.1.0" } }, + "scss-tokenizer": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz", + "integrity": "sha1-jrBtualyMzOCTT9VMGQRSYR85dE=", + "dev": true, + "requires": { + "js-base64": "^2.1.8", + "source-map": "^0.4.2" + }, + "dependencies": { + "source-map": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "dev": true, + "requires": { + "amdefine": ">=0.0.4" + } + } + } + }, "select-hose": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", @@ -6958,6 +8633,15 @@ "safe-buffer": "^5.0.1" } }, + "shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dev": true, + "requires": { + "kind-of": "^6.0.2" + } + }, "shebang-command": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", @@ -7321,6 +9005,23 @@ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", "dev": true }, + "sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "dev": true, + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, "ssri": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", @@ -7357,6 +9058,15 @@ "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", "dev": true }, + "stdout-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/stdout-stream/-/stdout-stream-1.4.1.tgz", + "integrity": "sha512-j4emi03KXqJWcIeF8eIXkjMFN1Cmb8gUlDYGeBALLPo5qdyTfA9bOtl8m33lRoC+vFMkP3gl0WsDr6+gzxbbTA==", + "dev": true, + "requires": { + "readable-stream": "^2.0.1" + } + }, "stream-browserify": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", @@ -7453,6 +9163,23 @@ "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", "dev": true }, + "strip-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", + "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", + "dev": true, + "requires": { + "get-stdin": "^4.0.1" + }, + "dependencies": { + "get-stdin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", + "dev": true + } + } + }, "strip-json-comments": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", @@ -7584,6 +9311,17 @@ "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", "dev": true }, + "tar": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.2.tgz", + "integrity": "sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==", + "dev": true, + "requires": { + "block-stream": "*", + "fstream": "^1.0.12", + "inherits": "2" + } + }, "term-size": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/term-size/-/term-size-1.2.0.tgz", @@ -7809,12 +9547,45 @@ "nopt": "~1.0.10" } }, + "tough-cookie": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", + "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", + "dev": true, + "requires": { + "psl": "^1.1.24", + "punycode": "^1.4.1" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + } + } + }, + "trim-newlines": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", + "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", + "dev": true + }, "trim-right": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", "dev": true }, + "true-case-path": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/true-case-path/-/true-case-path-1.0.3.tgz", + "integrity": "sha512-m6s2OdQe5wgpFMC+pAJ+q9djG82O2jcHPOI6RNg1yy9rCYR+WD6Nbpl32fDpfC56nirdRy+opFa/Vk7HYhqaew==", + "dev": true, + "requires": { + "glob": "^7.1.2" + } + }, "tslib": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", @@ -7836,6 +9607,21 @@ "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", "dev": true }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dev": true, + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true + }, "type-check": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", @@ -8140,6 +9926,17 @@ "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", "dev": true }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, "vm-browserify": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.0.tgz", @@ -8449,6 +10246,15 @@ "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", "dev": true }, + "wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "dev": true, + "requires": { + "string-width": "^1.0.2 || 2" + } + }, "widest-line": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.1.tgz", diff --git a/cvat-canvas/package.json b/cvat-canvas/package.json index a9b19472d7e..e56e2637552 100644 --- a/cvat-canvas/package.json +++ b/cvat-canvas/package.json @@ -31,7 +31,11 @@ "eslint-config-airbnb-typescript": "^4.0.1", "eslint-config-typescript-recommended": "^1.4.17", "eslint-plugin-import": "^2.18.2", + "node-sass": "^4.13.0", "nodemon": "^1.19.1", + "postcss-loader": "^3.0.0", + "postcss-preset-env": "^6.7.0", + "sass-loader": "^8.0.0", "style-loader": "^1.0.0", "typescript": "^3.5.3", "webpack": "^4.36.1", diff --git a/cvat-canvas/postcss.config.js b/cvat-canvas/postcss.config.js new file mode 100644 index 00000000000..862995fdd8f --- /dev/null +++ b/cvat-canvas/postcss.config.js @@ -0,0 +1,9 @@ +/* eslint-disable */ +module.exports = { + parser: false, + plugins: { + 'postcss-preset-env': { + browsers: '> 2.5%', // https://github.com/browserslist/browserslist + }, + }, +}; diff --git a/cvat-canvas/src/css/canvas.css b/cvat-canvas/src/scss/canvas.scss similarity index 98% rename from cvat-canvas/src/css/canvas.css rename to cvat-canvas/src/scss/canvas.scss index 4d931ed0a54..7cf72018b66 100644 --- a/cvat-canvas/src/css/canvas.css +++ b/cvat-canvas/src/scss/canvas.scss @@ -78,8 +78,9 @@ polyline.cvat_canvas_shape_merging { } #cvat_canvas_wrapper { - width: 100%; - height: 93%; + width: 98%; + height: 98%; + margin: 10px; border-radius: 5px; background-color: white; overflow: hidden; diff --git a/cvat-canvas/src/typescript/canvas.ts b/cvat-canvas/src/typescript/canvas.ts index e934b41b6c7..1f9e04465d6 100644 --- a/cvat-canvas/src/typescript/canvas.ts +++ b/cvat-canvas/src/typescript/canvas.ts @@ -27,9 +27,7 @@ import { CanvasViewImpl, } from './canvasView'; - -import '../css/canvas.css'; - +import '../scss/canvas.scss'; interface Canvas { html(): HTMLDivElement; @@ -68,6 +66,13 @@ class CanvasImpl implements Canvas { this.model.setup(frameData, objectStates); } + public fitCanvas(): void { + this.model.fitCanvas( + this.view.html().clientWidth, + this.view.html().clientHeight, + ); + } + public activate(clientID: number, attributeID: number = null): void { this.model.activate(clientID, attributeID); } diff --git a/cvat-canvas/src/typescript/canvasModel.ts b/cvat-canvas/src/typescript/canvasModel.ts index 5fbb2ab15ea..d4959af81f2 100644 --- a/cvat-canvas/src/typescript/canvasModel.ts +++ b/cvat-canvas/src/typescript/canvasModel.ts @@ -3,9 +3,6 @@ * SPDX-License-Identifier: MIT */ -// Disable till full implementation -/* eslint class-methods-use-this: "off" */ - import { MasterImpl } from './master'; @@ -81,6 +78,7 @@ export enum UpdateReasons { OBJECTS = 'objects', ZOOM = 'zoom', FIT = 'fit', + FIT_CANVAS = 'fit_canvas', MOVE = 'move', GRID = 'grid', FOCUS = 'focus', @@ -126,6 +124,7 @@ export interface CanvasModel { rotate(rotation: Rotation, remember: boolean): void; focus(clientID: number, padding: number): void; fit(): void; + fitCanvas(width: number, height: number): void; grid(stepX: number, stepY: number): void; draw(drawData: DrawData): void; @@ -242,6 +241,19 @@ export class CanvasModelImpl extends MasterImpl implements CanvasModel { this.notify(UpdateReasons.MOVE); } + public fitCanvas(width: number, height: number): void { + this.data.canvasSize.height = height; + this.data.canvasSize.width = width; + + this.data.imageOffset = Math.floor(Math.max( + this.data.canvasSize.height / FrameZoom.MIN, + this.data.canvasSize.width / FrameZoom.MIN, + )); + + this.notify(UpdateReasons.FIT_CANVAS); + this.notify(UpdateReasons.OBJECTS); + } + public setup(frameData: any, objectStates: any[]): void { frameData.data( (): void => { diff --git a/cvat-canvas/src/typescript/canvasView.ts b/cvat-canvas/src/typescript/canvasView.ts index d9c57233e16..5af68f30a9e 100644 --- a/cvat-canvas/src/typescript/canvasView.ts +++ b/cvat-canvas/src/typescript/canvasView.ts @@ -396,24 +396,7 @@ export class CanvasViewImpl implements CanvasView, Listener { this.canvas.appendChild(this.content); - // A little hack to get size after first mounting - // http://www.backalleycoder.com/2012/04/25/i-want-a-damnodeinserted/ const self = this; - const canvasFirstMounted = (event: AnimationEvent): void => { - if (event.animationName === 'loadingAnimation') { - const { geometry } = this.controller; - geometry.canvas = { - height: self.canvas.clientHeight, - width: self.canvas.clientWidth, - }; - - this.controller.geometry = geometry; - this.geometry = geometry; - self.canvas.removeEventListener('animationstart', canvasFirstMounted); - } - }; - - this.canvas.addEventListener('animationstart', canvasFirstMounted); // Setup API handlers this.drawHandler = new DrawHandlerImpl( @@ -667,6 +650,9 @@ export class CanvasViewImpl implements CanvasView, Listener { resize.call(this); transform.call(this); } + } else if (reason === UpdateReasons.FIT_CANVAS) { + move.call(this); + resize.call(this); } else if (reason === UpdateReasons.ZOOM || reason === UpdateReasons.FIT) { move.call(this); transform.call(this); diff --git a/cvat-canvas/webpack.config.js b/cvat-canvas/webpack.config.js index aa68cf6169c..69d97b125ae 100644 --- a/cvat-canvas/webpack.config.js +++ b/cvat-canvas/webpack.config.js @@ -1,3 +1,8 @@ +/* + * Copyright (C) 2019 Intel Corporation + * SPDX-License-Identifier: MIT +*/ + /* eslint-disable */ const path = require('path'); const DtsBundleWebpack = require('dts-bundle-webpack') @@ -70,15 +75,23 @@ const webConfig = { loader: 'babel-loader', options: { presets: [ - ['@babel/preset-env'], + ['@babel/preset-env', { + targets: '> 2.5%', // https://github.com/browserslist/browserslist + }], ['@babel/typescript'], ], sourceType: 'unambiguous', }, }, }, { - test: /\.css$/, - use: ['style-loader', 'css-loader'] + test: /\.scss$/, + exclude: /node_modules/, + use: ['style-loader', { + loader: 'css-loader', + options: { + importLoaders: 2, + }, + }, 'postcss-loader', 'sass-loader'] }], }, plugins: [ diff --git a/cvat-core/package.json b/cvat-core/package.json index deab3a7ff3d..8e2088f614c 100644 --- a/cvat-core/package.json +++ b/cvat-core/package.json @@ -18,7 +18,6 @@ "airbnb": "0.0.2", "babel-eslint": "^10.0.1", "babel-loader": "^8.0.6", - "core-js": "^3.0.1", "coveralls": "^3.0.5", "eslint": "6.1.0", "eslint-config-airbnb-base": "14.0.0", diff --git a/cvat-core/src/annotations-objects.js b/cvat-core/src/annotations-objects.js index 366f33ce286..ba4508dffda 100644 --- a/cvat-core/src/annotations-objects.js +++ b/cvat-core/src/annotations-objects.js @@ -480,20 +480,18 @@ // Method is used to construct ObjectState objects get(frame) { if (!(frame in this.cache)) { - const interpolation = Object.assign( - {}, this.getPosition(frame), - { - attributes: this.getAttributes(frame), - group: this.group, - objectType: ObjectType.TRACK, - shapeType: this.shapeType, - clientID: this.clientID, - serverID: this.serverID, - lock: this.lock, - color: this.color, - visibility: this.visibility, - }, - ); + const interpolation = { + ...this.getPosition(frame), + attributes: this.getAttributes(frame), + group: this.group, + objectType: ObjectType.TRACK, + shapeType: this.shapeType, + clientID: this.clientID, + serverID: this.serverID, + lock: this.lock, + color: this.color, + visibility: this.visibility, + }; this.cache[frame] = interpolation; } @@ -504,7 +502,7 @@ } neighborsFrames(targetFrame) { - const frames = Object.keys(this.shapes).map(frame => +frame); + const frames = Object.keys(this.shapes).map((frame) => +frame); let lDiff = Number.MAX_SAFE_INTEGER; let rDiff = Number.MAX_SAFE_INTEGER; @@ -773,13 +771,14 @@ } if (rightPosition && leftPosition) { - return Object.assign({}, this.interpolatePosition( - leftPosition, - rightPosition, - (targetFrame - leftFrame) / (rightFrame - leftFrame), - ), { + return { + ...this.interpolatePosition( + leftPosition, + rightPosition, + (targetFrame - leftFrame) / (rightFrame - leftFrame), + ), keyframe: false, - }); + }; } if (rightPosition) { @@ -858,7 +857,7 @@ clientID: this.clientID, serverID: this.serverID, lock: this.lock, - attributes: Object.assign({}, this.attributes), + attributes: { ...this.attributes }, label: this.label, group: this.group, }; @@ -888,7 +887,7 @@ if (updated.attributes) { const labelAttributes = copy.label - .attributes.map(attr => `${attr.id}`); + .attributes.map((attr) => `${attr.id}`); for (const attrID of Object.keys(data.attributes)) { if (labelAttributes.includes(attrID)) { @@ -1399,8 +1398,8 @@ // some points from source and target can absent in mapping // source, target - arrays of points. Target array size >= sourse array size appendMapping(mapping, source, target) { - const targetMatched = Object.values(mapping).map(x => +x); - const sourceMatched = Object.keys(mapping).map(x => +x); + const targetMatched = Object.values(mapping).map((x) => +x); + const sourceMatched = Object.keys(mapping).map((x) => +x); const orderForReceive = []; function findNeighbors(point) { diff --git a/cvat-core/src/frames.js b/cvat-core/src/frames.js index 7778077e5b2..e60d7a8db90 100644 --- a/cvat-core/src/frames.js +++ b/cvat-core/src/frames.js @@ -127,8 +127,9 @@ async function getFrame(taskID, mode, frame) { if (!(taskID in frameDataCache)) { - frameDataCache[taskID] = {}; - frameDataCache[taskID].meta = await serverProxy.frames.getMeta(taskID); + frameDataCache[taskID] = { + meta: await serverProxy.frames.getMeta(taskID), + }; frameCache[taskID] = {}; } diff --git a/cvat-core/src/labels.js b/cvat-core/src/labels.js index dc0235ffd9b..2730e6e3544 100644 --- a/cvat-core/src/labels.js +++ b/cvat-core/src/labels.js @@ -192,7 +192,7 @@ toJSON() { const object = { name: this.name, - attributes: [...this.attributes.map(el => el.toJSON())], + attributes: [...this.attributes.map((el) => el.toJSON())], }; if (typeof (this.id) !== 'undefined') { diff --git a/cvat-core/src/plugins.js b/cvat-core/src/plugins.js index 595e6cbc41e..eea06ee4f98 100644 --- a/cvat-core/src/plugins.js +++ b/cvat-core/src/plugins.js @@ -17,7 +17,7 @@ const pluginList = await PluginRegistry.list(); for (const plugin of pluginList) { const pluginDecorators = plugin.functions - .filter(obj => obj.callback === wrappedFunc)[0]; + .filter((obj) => obj.callback === wrappedFunc)[0]; if (pluginDecorators && pluginDecorators.enter) { try { await pluginDecorators.enter.call(this, plugin, ...args); @@ -35,7 +35,7 @@ for (const plugin of pluginList) { const pluginDecorators = plugin.functions - .filter(obj => obj.callback === wrappedFunc)[0]; + .filter((obj) => obj.callback === wrappedFunc)[0]; if (pluginDecorators && pluginDecorators.leave) { try { result = await pluginDecorators.leave.call(this, plugin, result, ...args); diff --git a/cvat-core/webpack.config.js b/cvat-core/webpack.config.js index fab1147f1bd..be9464f50e2 100644 --- a/cvat-core/webpack.config.js +++ b/cvat-core/webpack.config.js @@ -46,16 +46,7 @@ const webConfig = { options: { presets: [ ['@babel/preset-env', { - targets: { - chrome: 58, - }, - useBuiltIns: 'usage', - corejs: 3, - loose: false, - spec: false, - debug: false, - include: [], - exclude: [], + targets: '> 2.5%', // https://github.com/browserslist/browserslist }], ], sourceType: 'unambiguous', diff --git a/cvat-ui/postcss.config.js b/cvat-ui/postcss.config.js index 543f8754145..862995fdd8f 100644 --- a/cvat-ui/postcss.config.js +++ b/cvat-ui/postcss.config.js @@ -3,7 +3,7 @@ module.exports = { parser: false, plugins: { 'postcss-preset-env': { - browsers: '> 2%', // https://github.com/browserslist/browserslist + browsers: '> 2.5%', // https://github.com/browserslist/browserslist }, }, }; diff --git a/cvat-ui/src/actions/annotation-actions.ts b/cvat-ui/src/actions/annotation-actions.ts new file mode 100644 index 00000000000..904fa2a89ec --- /dev/null +++ b/cvat-ui/src/actions/annotation-actions.ts @@ -0,0 +1,132 @@ +import { AnyAction, Dispatch, ActionCreator } from 'redux'; +import { ThunkAction } from 'redux-thunk'; + +import { + CombinedState, + Task, +} from '../reducers/interfaces'; + +import getCore from '../core'; +import { getCVATStore } from '../store'; + +const cvat = getCore(); + +export enum AnnotationActionTypes { + GET_JOB = 'GET_JOB', + GET_JOB_SUCCESS = 'GET_JOB_SUCCESS', + GET_JOB_FAILED = 'GET_JOB_FAILED', + CHANGE_FRAME = 'CHANGE_FRAME', + CHANGE_FRAME_SUCCESS = 'CHANGE_FRAME_SUCCESS', + CHANGE_FRAME_FAILED = 'CHANGE_FRAME_FAILED', + SWITCH_PLAY = 'SWITCH_PLAY', + CONFIRM_CANVAS_READY = 'CONFIRM_CANVAS_READY', +} + +export function switchPlay(playing: boolean): AnyAction { + return { + type: AnnotationActionTypes.SWITCH_PLAY, + payload: { + playing, + }, + }; +} + +export function changeFrameAsync(toFrame: number, playing: boolean): +ThunkAction, {}, {}, AnyAction> { + return async (dispatch: ActionCreator): Promise => { + const store = getCVATStore(); + const state: CombinedState = store.getState(); + const { jobInstance } = state.annotation; + const currentFrame = state.annotation.frame; + + const frame = Math.max( + Math.min(toFrame, jobInstance.stopFrame), + jobInstance.startFrame, + ); + + // !playing || state.annotation.playing prevents changing frame on the latest setTimeout + // after playing had become false + if (frame !== currentFrame && (!playing || state.annotation.playing)) { + dispatch({ + type: AnnotationActionTypes.CHANGE_FRAME, + payload: {}, + }); + + try { + const frameData = await jobInstance.frames.get(frame); + const annotations = await jobInstance.annotations.get(frame); + dispatch({ + type: AnnotationActionTypes.CHANGE_FRAME_SUCCESS, + payload: { + frame, + frameData, + annotations, + }, + }); + } catch (error) { + dispatch({ + type: AnnotationActionTypes.CHANGE_FRAME_FAILED, + payload: { + frame, + error, + }, + }); + } + } + }; +} + +export function confirmCanvasReady(): AnyAction { + return { + type: AnnotationActionTypes.CONFIRM_CANVAS_READY, + payload: {}, + }; +} + +export function getJobAsync(tid: number, jid: number): +ThunkAction, {}, {}, AnyAction> { + return async (dispatch: ActionCreator): Promise => { + dispatch({ + type: AnnotationActionTypes.GET_JOB, + payload: {}, + }); + + try { + const store = getCVATStore(); + const state: CombinedState = store.getState(); + let task = state.tasks.current + .filter((_task: Task) => _task.instance.id === tid) + .map((_task: Task) => _task.instance)[0]; + if (!task) { + [task] = await cvat.tasks.get({ id: tid }); + } + + const job = task.jobs + .filter((_job: any) => _job.id === jid)[0]; + if (!job) { + throw new Error('Job with specified id does not exist'); + } + + const frame = Math.min(0, job.startFrame); + const frameData = await job.frames.get(frame); + const annotations = await job.annotations.get(frame); + + dispatch({ + type: AnnotationActionTypes.GET_JOB_SUCCESS, + payload: { + jobInstance: job, + frameData, + annotations, + frame, + }, + }); + } catch (error) { + dispatch({ + type: AnnotationActionTypes.GET_JOB_FAILED, + payload: { + error, + }, + }); + } + }; +} diff --git a/cvat-ui/src/actions/settings-actions.ts b/cvat-ui/src/actions/settings-actions.ts new file mode 100644 index 00000000000..6371f70f1fc --- /dev/null +++ b/cvat-ui/src/actions/settings-actions.ts @@ -0,0 +1,57 @@ +import { AnyAction } from 'redux'; +import { + GridColor, +} from '../reducers/interfaces'; + +export enum SettingsActionTypes { + SWITCH_ROTATE_ALL = 'SWITCH_ROTATE_ALL', + SWITCH_GRID = 'SWITCH_GRID', + CHANGE_GRID_SIZE = 'CHANGE_GRID_SIZE', + CHANGE_GRID_COLOR = 'CHANGE_GRID_COLOR', + CHANGE_GRID_OPACITY = 'CHANGE_GRID_OPACITY', +} + +export function switchRotateAll(rotateAll: boolean): AnyAction { + return { + type: SettingsActionTypes.SWITCH_ROTATE_ALL, + payload: { + rotateAll, + }, + }; +} + +export function switchGrid(grid: boolean): AnyAction { + return { + type: SettingsActionTypes.SWITCH_GRID, + payload: { + grid, + }, + }; +} + +export function changeGridSize(gridSize: number): AnyAction { + return { + type: SettingsActionTypes.CHANGE_GRID_SIZE, + payload: { + gridSize, + }, + }; +} + +export function changeGridColor(gridColor: GridColor): AnyAction { + return { + type: SettingsActionTypes.CHANGE_GRID_COLOR, + payload: { + gridColor, + }, + }; +} + +export function changeGridOpacity(gridOpacity: number): AnyAction { + return { + type: SettingsActionTypes.CHANGE_GRID_OPACITY, + payload: { + gridOpacity, + }, + }; +} diff --git a/cvat-ui/src/assets/playcontrol-pause-icon.svg b/cvat-ui/src/assets/playcontrol-pause-icon.svg new file mode 100644 index 00000000000..58e161d0112 --- /dev/null +++ b/cvat-ui/src/assets/playcontrol-pause-icon.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/cvat-ui/src/canvas.ts b/cvat-ui/src/canvas.ts new file mode 100644 index 00000000000..f68c1c2a804 --- /dev/null +++ b/cvat-ui/src/canvas.ts @@ -0,0 +1,9 @@ +import { + Canvas, + Rotation, +} from '../../cvat-canvas/src/typescript/canvas'; + +export { + Canvas, + Rotation, +}; diff --git a/cvat-ui/src/components/annotation-page/annotation-page.tsx b/cvat-ui/src/components/annotation-page/annotation-page.tsx index 12d0b92833e..bf6155c8dc5 100644 --- a/cvat-ui/src/components/annotation-page/annotation-page.tsx +++ b/cvat-ui/src/components/annotation-page/annotation-page.tsx @@ -7,8 +7,8 @@ import { Result, } from 'antd'; -import AnnotationTopBarComponent from './top-bar/top-bar'; -import StandardWorkspaceComponent from './standard-workspace/standard-workspace'; +import AnnotationTopBarContainer from '../../containers/annotation-page/top-bar/top-bar'; +import StandardWorkspaceContainer from '../../containers/annotation-page/standard-workspace/standard-workspace'; interface Props { jobInstance: any | null | undefined; @@ -44,8 +44,8 @@ export default function AnnotationPageComponent(props: Props): JSX.Element { return ( - - + + ); } diff --git a/cvat-ui/src/components/annotation-page/standard-workspace/canvas-wrapper-component.tsx b/cvat-ui/src/components/annotation-page/standard-workspace/canvas-wrapper-component.tsx deleted file mode 100644 index bb8283d65c3..00000000000 --- a/cvat-ui/src/components/annotation-page/standard-workspace/canvas-wrapper-component.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import React from 'react'; - -import { - Layout, -} from 'antd'; - -export default function CanvasWrapperComponent(): JSX.Element { - return ( - - main content - - ); -} diff --git a/cvat-ui/src/components/annotation-page/standard-workspace/canvas-wrapper.tsx b/cvat-ui/src/components/annotation-page/standard-workspace/canvas-wrapper.tsx new file mode 100644 index 00000000000..abd5dbc2bb2 --- /dev/null +++ b/cvat-ui/src/components/annotation-page/standard-workspace/canvas-wrapper.tsx @@ -0,0 +1,139 @@ +import React from 'react'; + +import { + Layout, +} from 'antd'; + +import { + GridColor, +} from '../../../reducers/interfaces'; + +import { Canvas } from '../../../canvas'; + +interface Props { + canvasInstance: Canvas; + jobInstance: any; + annotations: any[]; + frameData: any; + grid: boolean; + gridSize: number; + gridColor: GridColor; + gridOpacity: number; + onSetupCanvas: () => void; +} + +export default class CanvasWrapperComponent extends React.PureComponent { + public componentDidMount(): void { + const { + canvasInstance, + } = this.props; + + // It's awful approach from the point of view React + // But we do not have another way because cvat-canvas returns regular DOM element + const [wrapper] = window.document + .getElementsByClassName('cvat-annotation-page-canvas-container'); + wrapper.appendChild(canvasInstance.html()); + + this.initialSetup(); + this.updateCanvas(); + } + + public componentDidUpdate(prevProps: Props): void { + const { + grid, + gridSize, + gridColor, + gridOpacity, + canvasInstance, + } = this.props; + + if (prevProps.grid !== grid) { + const gridElement = window.document.getElementById('cvat_canvas_grid'); + if (gridElement) { + gridElement.style.display = grid ? 'block' : 'none'; + } + } + + if (prevProps.gridSize !== gridSize) { + canvasInstance.grid(gridSize, gridSize); + } + + if (prevProps.gridColor !== gridColor) { + const gridPattern = window.document.getElementById('cvat_canvas_grid_pattern'); + if (gridPattern) { + gridPattern.style.stroke = gridColor.toLowerCase(); + } + } + + if (prevProps.gridOpacity !== gridOpacity) { + const gridPattern = window.document.getElementById('cvat_canvas_grid_pattern'); + if (gridPattern) { + gridPattern.style.opacity = `${gridOpacity / 100}`; + } + } + + this.updateCanvas(); + } + + private initialSetup(): void { + const { + grid, + gridSize, + gridColor, + gridOpacity, + canvasInstance, + jobInstance, + onSetupCanvas, + } = this.props; + + // Size + canvasInstance.fitCanvas(); + + // Grid + const gridElement = window.document.getElementById('cvat_canvas_grid'); + const gridPattern = window.document.getElementById('cvat_canvas_grid_pattern'); + if (gridElement) { + gridElement.style.display = grid ? 'block' : 'none'; + } + if (gridPattern) { + gridPattern.style.stroke = gridColor.toLowerCase(); + gridPattern.style.opacity = `${gridOpacity / 100}`; + } + canvasInstance.grid(gridSize, gridSize); + + // Events + canvasInstance.html().addEventListener('canvas.setup', (): void => { + onSetupCanvas(); + if (jobInstance.task.mode === 'annotation') { + canvasInstance.fit(); + } + }); + + canvasInstance.html().addEventListener('canvas.setup', () => { + canvasInstance.fit(); + }, { once: true }); + } + + private updateCanvas(): void { + const { + annotations, + frameData, + canvasInstance, + } = this.props; + + if (frameData !== null) { + canvasInstance.setup(frameData, annotations); + } + } + + public render(): JSX.Element { + return ( + // This element doesn't have any props + // So, React isn't going to rerender it + // And it's a reason why cvat-canvas appended in mount function works + + ); + } +} diff --git a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar.tsx b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar.tsx index 24e20a39390..2abb67addb9 100644 --- a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar.tsx +++ b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar.tsx @@ -4,6 +4,7 @@ import { Icon, Layout, Tooltip, + Popover, } from 'antd'; import { @@ -22,8 +23,22 @@ import { SplitIcon, } from '../../../icons'; +import { + Canvas, + Rotation, +} from '../../../canvas'; + +interface Props { + canvasInstance: Canvas; + rotateAll: boolean; +} + +export default function ControlsSideBarComponent(props: Props): JSX.Element { + const { + rotateAll, + canvasInstance, + } = props; -export default function ControlsSideBarComponent(): JSX.Element { return ( - - - + + canvasInstance + .rotate(Rotation.ANTICLOCKWISE90, rotateAll)} + component={RotateIcon} + /> + canvasInstance + .rotate(Rotation.CLOCKWISE90, rotateAll)} + component={RotateIcon} + /> + + )} + trigger='hover' + > + + + +
diff --git a/cvat-ui/src/components/annotation-page/standard-workspace/objects-side-bar/objects-side-bar.tsx b/cvat-ui/src/components/annotation-page/standard-workspace/objects-side-bar/objects-side-bar.tsx index 8a764551217..ee4ea82478c 100644 --- a/cvat-ui/src/components/annotation-page/standard-workspace/objects-side-bar/objects-side-bar.tsx +++ b/cvat-ui/src/components/annotation-page/standard-workspace/objects-side-bar/objects-side-bar.tsx @@ -5,11 +5,15 @@ import { Layout, } from 'antd'; +interface Props { + onSidebarFoldUnfold(): void; +} + interface State { collapsed: boolean; } -export default class StandardWorkspaceComponent extends React.PureComponent<{}, State> { +export default class StandardWorkspaceComponent extends React.PureComponent { public constructor(props: any) { super(props); this.state = { @@ -19,6 +23,8 @@ export default class StandardWorkspaceComponent extends React.PureComponent<{}, public render(): JSX.Element { const { collapsed } = this.state; + const { onSidebarFoldUnfold } = this.props; + return ( this.setState( + onClick={(): void => { + this.setState( (prevState: State): State => ({ collapsed: !prevState.collapsed, }), - ) - } + ); + + const [sidebar] = window.document + .getElementsByClassName('cvat-annotation-page-objects-sidebar'); + sidebar.addEventListener('transitionend', () => { + onSidebarFoldUnfold(); + }, { once: true }); + }} > {collapsed ? : } diff --git a/cvat-ui/src/components/annotation-page/standard-workspace/standard-workspace.tsx b/cvat-ui/src/components/annotation-page/standard-workspace/standard-workspace.tsx index 0e11a7bcf32..09b490b7597 100644 --- a/cvat-ui/src/components/annotation-page/standard-workspace/standard-workspace.tsx +++ b/cvat-ui/src/components/annotation-page/standard-workspace/standard-workspace.tsx @@ -5,16 +5,30 @@ import { Layout, } from 'antd'; -import ControlsSideBarComponent from './controls-side-bar'; -import CanvasWrapperComponent from './canvas-wrapper-component'; +import { Canvas } from '../../../canvas'; + +import CanvasWrapperContainer from '../../../containers/annotation-page/standard-workspace/canvas-wrapper'; +import ControlsSideBarContainer from '../../../containers/annotation-page/standard-workspace/controls-side-bar'; import ObjectSideBarComponent from './objects-side-bar/objects-side-bar'; -export default function StandardWorkspaceComponent(): JSX.Element { +interface Props { + canvasInstance: Canvas; +} + +export default function StandardWorkspaceComponent(props: Props): JSX.Element { + const { + canvasInstance, + } = props; + return ( - - - - + + + + { + canvasInstance.fitCanvas(); + }} + /> ); } diff --git a/cvat-ui/src/components/annotation-page/standard-workspace/styles.scss b/cvat-ui/src/components/annotation-page/standard-workspace/styles.scss index 5cdab33559a..3814e9178dc 100644 --- a/cvat-ui/src/components/annotation-page/standard-workspace/styles.scss +++ b/cvat-ui/src/components/annotation-page/standard-workspace/styles.scss @@ -10,6 +10,7 @@ left: auto; background-color: $background-color-2; border-left: 1px solid $border-color-1; + z-index: 2; } .cvat-annotation-page-controls-sidebar { @@ -37,3 +38,28 @@ } } } + +.cvat-annotation-page-controls-rotate-left, +.cvat-annotation-page-controls-rotate-right { + transform: scale(0.65); + border-radius: 5px; + + &:hover { + background: $header-color; + transform: scale(0.75); + } + &:active { + transform: scale(0.65); + } +} + +.cvat-annotation-page-controls-rotate > +.ant-popover-content > +.ant-popover-inner > div > +.ant-popover-inner-content { + padding: 0px; +} + +.cvat-annotation-page-controls-rotate-right > svg { + transform: scaleX(-1); +} \ No newline at end of file diff --git a/cvat-ui/src/components/annotation-page/top-bar/top-bar.tsx b/cvat-ui/src/components/annotation-page/top-bar/top-bar.tsx index 1e1f25c485a..2b948517ab9 100644 --- a/cvat-ui/src/components/annotation-page/top-bar/top-bar.tsx +++ b/cvat-ui/src/components/annotation-page/top-bar/top-bar.tsx @@ -11,6 +11,7 @@ import { Select, } from 'antd'; +import { SliderValue } from 'antd/lib/slider'; import Text from 'antd/lib/typography/Text'; import { @@ -22,6 +23,7 @@ import { PlaycontrolBackJumpIcon, PlaycontrolPreviousIcon, PlaycontrolPlayIcon, + PlaycontrolPauseIcon, PlaycontrolNextIcon, PlaycontrolForwardJumpIcon, PlaycontrolLastIcon, @@ -29,7 +31,37 @@ import { FullscreenIcon, } from '../../../icons'; -export default function AnnotationPageComponent(): JSX.Element { +interface Props { + jobInstance: any; + frame: number; + frameStep: number; + playing: boolean; + canvasIsReady: boolean; + onChangeFrame(frame: number, playing: boolean): void; + onSwitchPlay(playing: boolean): void; +} + +export default function AnnotationTopBarComponent(props: Props): JSX.Element { + const { + jobInstance, + frame, + frameStep, + playing, + canvasIsReady, + onChangeFrame, + onSwitchPlay, + } = props; + + if (playing && canvasIsReady) { + if (frame < jobInstance.stopFrame) { + setTimeout(() => { + onChangeFrame(frame + 1, true); + }, 30); + } else { + onSwitchPlay(false); + } + } + return ( @@ -54,18 +86,120 @@ export default function AnnotationPageComponent(): JSX.Element { - - - - - - - + + { + if (jobInstance.startFrame !== frame) { + onSwitchPlay(false); + onChangeFrame(jobInstance.startFrame, false); + } + }} + /> + + + { + const newFrame = Math + .max(jobInstance.startFrame, frame - frameStep); + if (newFrame !== frame) { + onSwitchPlay(false); + onChangeFrame(newFrame, false); + } + }} + /> + + + { + const newFrame = Math + .max(jobInstance.startFrame, frame - 1); + if (newFrame !== frame) { + onSwitchPlay(false); + onChangeFrame(newFrame, false); + } + }} + /> + + + {!playing + ? ( + + { + if (frame < jobInstance.stopFrame) { + onSwitchPlay(true); + } + }} + /> + + ) + : ( + + { + onSwitchPlay(false); + }} + /> + + ) + } + + + { + const newFrame = Math + .min(jobInstance.stopFrame, frame + 1); + if (newFrame !== frame) { + onSwitchPlay(false); + onChangeFrame(newFrame, false); + } + }} + /> + + + { + const newFrame = Math + .min(jobInstance.stopFrame, frame + frameStep); + if (newFrame !== frame) { + onSwitchPlay(false); + onChangeFrame(newFrame, false); + } + }} + /> + + + { + if (jobInstance.stopFrame !== frame) { + onSwitchPlay(false); + onChangeFrame(jobInstance.stopFrame, false); + } + }} + /> + - + { + onSwitchPlay(false); + onChangeFrame(value as number, false); + }} + /> @@ -77,7 +211,16 @@ export default function AnnotationPageComponent(): JSX.Element { - + ): void => { + onSwitchPlay(false); + onChangeFrame(+e.target.value, false); + }} + /> diff --git a/cvat-ui/src/components/cvat-app.tsx b/cvat-ui/src/components/cvat-app.tsx index a1e76e490a4..e8eabc3d7c1 100644 --- a/cvat-ui/src/components/cvat-app.tsx +++ b/cvat-ui/src/components/cvat-app.tsx @@ -13,6 +13,7 @@ import { notification, } from 'antd'; +import SettingsPageComponent from './settings-page/settings-page'; import TasksPageContainer from '../containers/tasks-page/tasks-page'; import CreateTaskPageContainer from '../containers/create-task-page/create-task-page'; import TaskPageContainer from '../containers/task-page/task-page'; @@ -259,6 +260,7 @@ export default class CVATApplication extends React.PureComponent { + diff --git a/cvat-ui/src/components/header/header.tsx b/cvat-ui/src/components/header/header.tsx index 71817fdcc14..29dc680f33f 100644 --- a/cvat-ui/src/components/header/header.tsx +++ b/cvat-ui/src/components/header/header.tsx @@ -52,7 +52,11 @@ function HeaderContainer(props: Props): JSX.Element { const menu = ( - + props.history.push('/settings') + } + > Settings diff --git a/cvat-ui/src/components/settings-page/player-settings.tsx b/cvat-ui/src/components/settings-page/player-settings.tsx new file mode 100644 index 00000000000..8a4c3af5783 --- /dev/null +++ b/cvat-ui/src/components/settings-page/player-settings.tsx @@ -0,0 +1,217 @@ +import React from 'react'; + +import { + Row, + Col, + Checkbox, + Slider, + Select, + InputNumber, + Icon, +} from 'antd'; + +import Text from 'antd/lib/typography/Text'; +import { CheckboxChangeEvent } from 'antd/lib/checkbox'; + +import { + PlaycontrolBackJumpIcon, + PlaycontrolForwardJumpIcon, +} from '../../icons'; + +import { + FrameSpeed, + GridColor, +} from '../../reducers/interfaces'; + +interface Props { + frameStep: number; + frameSpeed: FrameSpeed; + resetZoom: boolean; + rotateAll: boolean; + grid: boolean; + gridSize: number; + gridColor: GridColor; + gridOpacity: number; + brightnessLevel: number; + contrastLevel: number; + saturationLevel: number; + onChangeFrameStep(step: number): void; + onChangeFrameSpeed(speed: FrameSpeed): void; + onSwitchResetZoom(enabled: boolean): void; + onSwitchRotateAll(rotateAll: boolean): void; + onSwitchGrid(grid: boolean): void; + onChangeGridSize(gridSize: number): void; + onChangeGridColor(gridColor: GridColor): void; + onChangeGridOpacity(gridOpacity: number): void; + onChangeBrightnessLevel(level: number): void; + onChangeContrastLevel(level: number): void; + onChangeSaturationLevel(level: number): void; +} + +export default function PlayerSettingsComponent(props: Props): JSX.Element { + const { + frameStep, + frameSpeed, + resetZoom, + rotateAll, + grid, + gridSize, + gridColor, + gridOpacity, + brightnessLevel, + contrastLevel, + saturationLevel, + onSwitchRotateAll, + onSwitchGrid, + onChangeGridSize, + onChangeGridColor, + onChangeGridOpacity, + } = props; + + return ( +
+ + + Player step + + + + + Number of frames skipped when selecting + + or + + + + + + + Player speed + + + + + + { + onSwitchGrid(event.target.checked); + }} + > + Show grid + + + + + + Grid size + { + if (value) { + onChangeGridSize(value); + } + }} + /> + + + Grid color + + + + Grid opacity + { + onChangeGridOpacity(value as number); + }} + /> + {`${gridOpacity} %`} + + + + + + + + Reset zoom + + + + Fit image after changing frame + + + + + + + { + onSwitchRotateAll(event.target.checked); + }} + > + Rotate all images + + + + Rotate all images simultaneously + + + + + + + Brightness + + + + + + + + Contrast + + + + + + + + Saturation + + + + + +
+ ); +} diff --git a/cvat-ui/src/components/settings-page/settings-page.tsx b/cvat-ui/src/components/settings-page/settings-page.tsx new file mode 100644 index 00000000000..702ba39ed76 --- /dev/null +++ b/cvat-ui/src/components/settings-page/settings-page.tsx @@ -0,0 +1,79 @@ +import './styles.scss'; +import React from 'react'; +import { + Row, + Col, + Tabs, + Icon, + Button, +} from 'antd'; + +import Text from 'antd/lib/typography/Text'; + +import { RouteComponentProps } from 'react-router'; +import { withRouter } from 'react-router-dom'; + +import WorkspaceSettingsContainer from '../../containers/settings-page/workspace-settings'; +import PlayerSettingsContainer from '../../containers/settings-page/player-settings'; + +function SettingsPage(props: RouteComponentProps): JSX.Element { + return ( +
+ + + Settings + + + + + + + + Player + + ) + } + key='player' + > + + + + + Workspace + + ) + } + key='workspace' + > + + + + + + + + + + +
+ ); +} + +export default withRouter(SettingsPage); diff --git a/cvat-ui/src/components/settings-page/styles.scss b/cvat-ui/src/components/settings-page/styles.scss new file mode 100644 index 00000000000..3e9669652e6 --- /dev/null +++ b/cvat-ui/src/components/settings-page/styles.scss @@ -0,0 +1,86 @@ +@import '../../base.scss'; + +.cvat-settings-page { + > div:nth-child(1) { + margin-top: 30px; + margin-bottom: 10px; + } +} + +.cvat-workspace-settings, .cvat-player-settings { + width: 100%; + height: max-content; + background: $background-color-1; + padding: 50px; +} + +.cvat-player-settings-grid, +.cvat-workspace-settings-auto-save, +.cvat-workspace-settings-show-interpolated-checkbox { + margin-bottom: 10px; +} + +.cvat-player-settings-grid-size, +.cvat-player-settings-grid-color, +.cvat-player-settings-grid-opacity, +.cvat-player-settings-step, +.cvat-player-settings-speed, +.cvat-player-settings-reset-zoom, +.cvat-player-settings-rotate-all, +.cvat-workspace-settings-show-interpolated, +.cvat-workspace-settings-aam-zoom-margin, +.cvat-workspace-settings-auto-save-interval { + margin-bottom: 25px; +} + +.cvat-player-settings-grid-size, +.cvat-player-settings-grid-color, +.cvat-player-settings-grid-opacity { + display: grid; + justify-items: start; +} + +.cvat-player-settings-grid-color { + > .ant-select { + width: 150px; + } +} + +.cvat-player-settings-grid-opacity { + > .ant-slider { + width: 150px; + } +} + +.cvat-player-settings-step, +.cvat-player-settings-speed { + > div { + display: grid; + justify-items: start; + } +} + +.cvat-player-settings-step > div > span > i { + vertical-align: -1em; + transform: scale(0.3); +} + +.cvat-player-settings-speed > div > .ant-select { + width: 90px; +} + +.cvat-player-settings-brightness, +.cvat-player-settings-contrast, +.cvat-player-settings-saturation { + width: 40%; +} + +.cvat-settings-page-back-button { + width: 100px; + margin-top: 15px; +} + +.cvat-settings-page-back-button-wrapper { + display: flex; + justify-content: flex-end; +} \ No newline at end of file diff --git a/cvat-ui/src/components/settings-page/workspace-settings.tsx b/cvat-ui/src/components/settings-page/workspace-settings.tsx new file mode 100644 index 00000000000..3fd6d10be6a --- /dev/null +++ b/cvat-ui/src/components/settings-page/workspace-settings.tsx @@ -0,0 +1,76 @@ +import React from 'react'; + +import { + Row, + Col, + Checkbox, + InputNumber, +} from 'antd'; + +import Text from 'antd/lib/typography/Text'; + +interface Props { + autoSave: boolean; + autoSaveInterval: number; + aamZoomMargin: number; + showAllInterpolationTracks: boolean; + onSwitchAutoSave(enabled: boolean): void; + onChangeAutoSaveInterval(interval: number): void; + onChangeAAMZoomMargin(margin: number): void; + onSwitchShowingInterpolatedTracks(enabled: boolean): void; +} + +export default function WorkspaceSettingsComponent(props: Props): JSX.Element { + const { + autoSave, + autoSaveInterval, + aamZoomMargin, + showAllInterpolationTracks, + } = props; + + return ( +
+ + + + Enable auto save + + + + + + Auto save every + + minutes + + + + + + Show all interpolation tracks + + + + Show hidden interpolated objects in the side panel + + + + + Attribute annotation mode (AAM) zoom margin + + + +
+ ); +} diff --git a/cvat-ui/src/components/task-page/task-page.tsx b/cvat-ui/src/components/task-page/task-page.tsx index 0804551cc39..ec252e9c182 100644 --- a/cvat-ui/src/components/task-page/task-page.tsx +++ b/cvat-ui/src/components/task-page/task-page.tsx @@ -27,8 +27,6 @@ interface TaskPageComponentProps { type Props = TaskPageComponentProps & RouteComponentProps<{id: string}>; class TaskPageComponent extends React.PureComponent { - private attempts = 0; - public componentDidUpdate(): void { const { deleteActivity, diff --git a/cvat-ui/src/containers/annotation-page/annotation-page.tsx b/cvat-ui/src/containers/annotation-page/annotation-page.tsx index 44da61a73f4..b6343c40832 100644 --- a/cvat-ui/src/containers/annotation-page/annotation-page.tsx +++ b/cvat-ui/src/containers/annotation-page/annotation-page.tsx @@ -4,11 +4,10 @@ import { withRouter } from 'react-router-dom'; import { RouteComponentProps } from 'react-router'; import AnnotationPageComponent from '../../components/annotation-page/annotation-page'; -import { getTasksAsync } from '../../actions/tasks-actions'; +import { getJobAsync } from '../../actions/annotation-actions'; import { CombinedState, - Task, } from '../../reducers/interfaces'; type OwnProps = RouteComponentProps<{ @@ -25,46 +24,23 @@ interface DispatchToProps { getJob(): void; } -function mapStateToProps(state: CombinedState, own: OwnProps): StateToProps { - const { tasks } = state; - const { - gettingQuery, - current, - } = tasks; - const { params } = own.match; - const taskID = +params.tid; - const jobID = +params.jid; - - const filteredTasks = current - .filter((_task: Task) => _task.instance.id === taskID); - const task = filteredTasks[0] || (gettingQuery.id === taskID || Number.isNaN(taskID) - ? undefined : null); - - const job = task ? task.instance.jobs - .filter((_job: any) => _job.id === jobID)[0] : task; +function mapStateToProps(state: CombinedState): StateToProps { + const { annotation } = state; return { - jobInstance: job, - fetching: tasks.fetching, + jobInstance: annotation.jobInstance, + fetching: annotation.jobFetching, }; } function mapDispatchToProps(dispatch: any, own: OwnProps): DispatchToProps { const { params } = own.match; const taskID = +params.tid; + const jobID = +params.jid; return { getJob(): void { - dispatch(getTasksAsync({ - id: taskID, - page: 1, - search: null, - owner: null, - assignee: null, - name: null, - status: null, - mode: null, - })); + dispatch(getJobAsync(taskID, jobID)); }, }; } diff --git a/cvat-ui/src/containers/annotation-page/standard-workspace/canvas-wrapper.tsx b/cvat-ui/src/containers/annotation-page/standard-workspace/canvas-wrapper.tsx new file mode 100644 index 00000000000..36251baf32b --- /dev/null +++ b/cvat-ui/src/containers/annotation-page/standard-workspace/canvas-wrapper.tsx @@ -0,0 +1,75 @@ +import React from 'react'; +import { connect } from 'react-redux'; + +import CanvasWrapperComponent from '../../../components/annotation-page/standard-workspace/canvas-wrapper'; + +import { + confirmCanvasReady, +} from '../../../actions/annotation-actions'; +import { + GridColor, + CombinedState, +} from '../../../reducers/interfaces'; + +import { Canvas } from '../../../canvas'; + +interface StateToProps { + canvasInstance: Canvas; + jobInstance: any; + annotations: any[]; + frameData: any; + grid: boolean; + gridSize: number; + gridColor: GridColor; + gridOpacity: number; +} + +interface DispatchToProps { + onSetupCanvas(): void; +} + +function mapStateToProps(state: CombinedState): StateToProps { + const { + canvasInstance, + jobInstance, + frameData, + annotations, + } = state.annotation; + + const { + grid, + gridSize, + gridColor, + gridOpacity, + } = state.settings.player; + + return { + canvasInstance, + jobInstance, + frameData, + annotations, + grid, + gridSize, + gridColor, + gridOpacity, + }; +} + +function mapDispatchToProps(dispatch: any): DispatchToProps { + return { + onSetupCanvas(): void { + dispatch(confirmCanvasReady()); + }, + }; +} + +function CanvasWrapperContainer(props: StateToProps & DispatchToProps): JSX.Element { + return ( + + ); +} + +export default connect( + mapStateToProps, + mapDispatchToProps, +)(CanvasWrapperContainer); diff --git a/cvat-ui/src/containers/annotation-page/standard-workspace/controls-side-bar.tsx b/cvat-ui/src/containers/annotation-page/standard-workspace/controls-side-bar.tsx new file mode 100644 index 00000000000..bc8bf1d9a73 --- /dev/null +++ b/cvat-ui/src/containers/annotation-page/standard-workspace/controls-side-bar.tsx @@ -0,0 +1,35 @@ +import React from 'react'; +import { connect } from 'react-redux'; + +import { Canvas } from '../../../canvas'; + +import ControlsSideBarComponent from '../../../components/annotation-page/standard-workspace/controls-side-bar'; +import { CombinedState } from '../../../reducers/interfaces'; + + +interface StateToProps { + canvasInstance: Canvas; + rotateAll: boolean; +} + +function mapStateToProps(state: CombinedState): StateToProps { + const { + annotation, + settings, + } = state; + + return { + rotateAll: settings.player.rotateAll, + canvasInstance: annotation.canvasInstance, + }; +} + +function StandardWorkspaceContainer(props: StateToProps): JSX.Element { + return ( + + ); +} + +export default connect( + mapStateToProps, +)(StandardWorkspaceContainer); diff --git a/cvat-ui/src/containers/annotation-page/standard-workspace/standard-workspace.tsx b/cvat-ui/src/containers/annotation-page/standard-workspace/standard-workspace.tsx new file mode 100644 index 00000000000..a9835c5b3b6 --- /dev/null +++ b/cvat-ui/src/containers/annotation-page/standard-workspace/standard-workspace.tsx @@ -0,0 +1,35 @@ +import React from 'react'; +import { connect } from 'react-redux'; + +import { Canvas } from '../../../canvas'; + +import StandardWorkspaceComponent from '../../../components/annotation-page/standard-workspace/standard-workspace'; +import { CombinedState } from '../../../reducers/interfaces'; + + +interface StateToProps { + canvasInstance: Canvas; +} + +function mapStateToProps(state: CombinedState): StateToProps { + const { annotation } = state; + return { + canvasInstance: annotation.canvasInstance, + }; +} + +function StandardWorkspaceContainer(props: StateToProps): JSX.Element { + const { + canvasInstance, + } = props; + + return ( + + ); +} + +export default connect( + mapStateToProps, +)(StandardWorkspaceContainer); diff --git a/cvat-ui/src/containers/annotation-page/top-bar/top-bar.tsx b/cvat-ui/src/containers/annotation-page/top-bar/top-bar.tsx new file mode 100644 index 00000000000..a1f8bc88064 --- /dev/null +++ b/cvat-ui/src/containers/annotation-page/top-bar/top-bar.tsx @@ -0,0 +1,78 @@ +import React from 'react'; +import { connect } from 'react-redux'; + +import { + changeFrameAsync, + switchPlay as switchPlayAction, +} from '../../../actions/annotation-actions'; + +import AnnotationTopBarComponent from '../../../components/annotation-page/top-bar/top-bar'; +import { CombinedState } from '../../../reducers/interfaces'; + +interface StateToProps { + jobInstance: any; + frame: number; + frameStep: number; + playing: boolean; + canvasIsReady: boolean; +} + +interface DispatchToProps { + onChangeFrame(frame: number, playing: boolean): void; + onSwitchPlay(playing: boolean): void; +} + +function mapStateToProps(state: CombinedState): StateToProps { + const { + annotation, + settings, + } = state; + + return { + jobInstance: annotation.jobInstance, + frame: annotation.frame as number, // is number when jobInstance specified + frameStep: settings.player.frameStep, + playing: annotation.playing, + canvasIsReady: annotation.canvasIsReady, + }; +} + +function mapDispatchToProps(dispatch: any): DispatchToProps { + return { + onChangeFrame(frame: number, playing: boolean): void { + dispatch(changeFrameAsync(frame, playing)); + }, + onSwitchPlay(playing: boolean): void { + dispatch(switchPlayAction(playing)); + }, + }; +} + +function AnnotationTopBarContainer(props: StateToProps & DispatchToProps): JSX.Element { + const { + jobInstance, + frame, + frameStep, + playing, + canvasIsReady, + onChangeFrame, + onSwitchPlay, + } = props; + + return ( + + ); +} + +export default connect( + mapStateToProps, + mapDispatchToProps, +)(AnnotationTopBarContainer); diff --git a/cvat-ui/src/containers/settings-page/player-settings.tsx b/cvat-ui/src/containers/settings-page/player-settings.tsx new file mode 100644 index 00000000000..be52e3dd429 --- /dev/null +++ b/cvat-ui/src/containers/settings-page/player-settings.tsx @@ -0,0 +1,114 @@ +import React from 'react'; +import { connect } from 'react-redux'; + +import PlayerSettingsComponent from '../../components/settings-page/player-settings'; + +import { + switchRotateAll, + switchGrid, + changeGridSize, + changeGridColor, + changeGridOpacity, +} from '../../actions/settings-actions'; + +import { + CombinedState, + FrameSpeed, + GridColor, +} from '../../reducers/interfaces'; + +interface StateToProps { + frameStep: number; + frameSpeed: FrameSpeed; + resetZoom: boolean; + rotateAll: boolean; + grid: boolean; + gridSize: number; + gridColor: GridColor; + gridOpacity: number; + brightnessLevel: number; + contrastLevel: number; + saturationLevel: number; +} + +interface DispatchToProps { + onChangeFrameStep(step: number): void; + onChangeFrameSpeed(speed: FrameSpeed): void; + onSwitchResetZoom(enabled: boolean): void; + onSwitchRotateAll(rotateAll: boolean): void; + onSwitchGrid(grid: boolean): void; + onChangeGridSize(gridSize: number): void; + onChangeGridColor(gridColor: GridColor): void; + onChangeGridOpacity(gridOpacity: number): void; + onChangeBrightnessLevel(level: number): void; + onChangeContrastLevel(level: number): void; + onChangeSaturationLevel(level: number): void; +} + +function mapStateToProps(state: CombinedState): StateToProps { + const { player } = state.settings; + return { + ...player, + }; +} + +function mapDispatchToProps(dispatch: any): DispatchToProps { + return { + // will be implemented + // eslint-disable-next-line + onChangeFrameStep(step: number): void { + + }, + // will be implemented + // eslint-disable-next-line + onChangeFrameSpeed(speed: FrameSpeed): void { + + }, + // will be implemented + // eslint-disable-next-line + onSwitchResetZoom(enabled: boolean): void { + + }, + onSwitchRotateAll(rotateAll: boolean): void { + dispatch(switchRotateAll(rotateAll)); + }, + onSwitchGrid(grid: boolean): void { + dispatch(switchGrid(grid)); + }, + onChangeGridSize(gridSize: number): void { + dispatch(changeGridSize(gridSize)); + }, + onChangeGridColor(gridColor: GridColor): void { + dispatch(changeGridColor(gridColor)); + }, + onChangeGridOpacity(gridOpacity: number): void { + dispatch(changeGridOpacity(gridOpacity)); + }, + // will be implemented + // eslint-disable-next-line + onChangeBrightnessLevel(level: number): void { + + }, + // will be implemented + // eslint-disable-next-line + onChangeContrastLevel(level: number): void { + + }, + // will be implemented + // eslint-disable-next-line + onChangeSaturationLevel(level: number): void { + + }, + }; +} + +function PlayerSettingsContainer(props: StateToProps & DispatchToProps): JSX.Element { + return ( + + ); +} + +export default connect( + mapStateToProps, + mapDispatchToProps, +)(PlayerSettingsContainer); diff --git a/cvat-ui/src/containers/settings-page/workspace-settings.tsx b/cvat-ui/src/containers/settings-page/workspace-settings.tsx new file mode 100644 index 00000000000..48eac3cc125 --- /dev/null +++ b/cvat-ui/src/containers/settings-page/workspace-settings.tsx @@ -0,0 +1,75 @@ +import React from 'react'; +import { connect } from 'react-redux'; + +import { + CombinedState, +} from '../../reducers/interfaces'; + +import WorkspaceSettingsComponent from '../../components/settings-page/workspace-settings'; + +interface StateToProps { + autoSave: boolean; + autoSaveInterval: number; + aamZoomMargin: number; + showAllInterpolationTracks: boolean; +} + +interface DispatchToProps { + onSwitchAutoSave(enabled: boolean): void; + onChangeAutoSaveInterval(interval: number): void; + onChangeAAMZoomMargin(margin: number): void; + onSwitchShowingInterpolatedTracks(enabled: boolean): void; +} + +function mapStateToProps(state: CombinedState): StateToProps { + const { workspace } = state.settings; + const { + autoSave, + autoSaveInterval, + aamZoomMargin, + showAllInterpolationTracks, + } = workspace; + + return { + autoSave, + autoSaveInterval, + aamZoomMargin, + showAllInterpolationTracks, + }; +} + +function mapDispatchToProps(): DispatchToProps { + return { + // will be implemented + // eslint-disable-next-line + onSwitchAutoSave(enabled: boolean): void { + + }, + // will be implemented + // eslint-disable-next-line + onChangeAutoSaveInterval(interval: number): void { + + }, + // will be implemented + // eslint-disable-next-line + onChangeAAMZoomMargin(margin: number): void { + + }, + // will be implemented + // eslint-disable-next-line + onSwitchShowingInterpolatedTracks(enabled: boolean): void { + + }, + }; +} + +function WorkspaceSettingsContainer(props: StateToProps & DispatchToProps): JSX.Element { + return ( + + ); +} + +export default connect( + mapStateToProps, + mapDispatchToProps, +)(WorkspaceSettingsContainer); diff --git a/cvat-ui/src/icons.tsx b/cvat-ui/src/icons.tsx index 642870efc4c..d2a346086c1 100644 --- a/cvat-ui/src/icons.tsx +++ b/cvat-ui/src/icons.tsx @@ -25,13 +25,13 @@ import SVGPlaycontrolFirstIcon from './assets/playcontrol-first-icon.svg'; import SVGPlaycontrolBackJumpIcon from './assets/playcontrol-back-jump-icon.svg'; import SVGPlaycontrolPreviousIcon from './assets/playcontrol-previous-icon.svg'; import SVGPlaycontrolPlayIcon from './assets/playcontrol-play-icon.svg'; +import SVGPlaycontrolPauseIcon from './assets/playcontrol-pause-icon.svg'; import SVGPlaycontrolNextIcon from './assets/playcontrol-next-icon.svg'; import SVGPlaycontrolForwardJumpIcon from './assets/playcontrol-forward-jump-icon.svg'; import SVGPlaycontrolLastIcon from './assets/playcontrol-last-icon.svg'; import SVGInfoIcon from './assets/info-icon.svg'; import SVGFullscreenIcon from './assets/fullscreen-icon.svg'; - export const CVATLogo = (): JSX.Element => ; export const AccountIcon = (): JSX.Element => ; export const EmptyTasksIcon = (): JSX.Element => ; @@ -56,6 +56,7 @@ export const RedoIcon = (): JSX.Element => ; export const PlaycontrolFirstIcon = (): JSX.Element => ; export const PlaycontrolBackJumpIcon = (): JSX.Element => ; export const PlaycontrolPreviousIcon = (): JSX.Element => ; +export const PlaycontrolPauseIcon = (): JSX.Element => ; export const PlaycontrolPlayIcon = (): JSX.Element => ; export const PlaycontrolNextIcon = (): JSX.Element => ; export const PlaycontrolForwardJumpIcon = (): JSX.Element => ; diff --git a/cvat-ui/src/reducers/annotation-reducer.ts b/cvat-ui/src/reducers/annotation-reducer.ts new file mode 100644 index 00000000000..b4c1f91797f --- /dev/null +++ b/cvat-ui/src/reducers/annotation-reducer.ts @@ -0,0 +1,87 @@ +import { AnyAction } from 'redux'; + +import { Canvas } from '../canvas'; + +import { AnnotationState } from './interfaces'; +import { AnnotationActionTypes } from '../actions/annotation-actions'; + +const defaultState: AnnotationState = { + canvasInstance: new Canvas(), + canvasIsReady: false, + jobInstance: null, + frame: 0, + playing: false, + annotations: [], + frameData: null, + dataFetching: false, + jobFetching: false, +}; + +export default (state = defaultState, action: AnyAction): AnnotationState => { + switch (action.type) { + case AnnotationActionTypes.GET_JOB: { + return { + ...defaultState, + jobFetching: true, + }; + } + case AnnotationActionTypes.GET_JOB_SUCCESS: { + return { + ...defaultState, + jobFetching: false, + jobInstance: action.payload.jobInstance, + frame: action.payload.frame, + frameData: action.payload.frameData, + annotations: action.payload.annotations, + }; + } + case AnnotationActionTypes.GET_JOB_FAILED: { + return { + ...state, + jobInstance: undefined, + jobFetching: false, + }; + } + case AnnotationActionTypes.CHANGE_FRAME: { + return { + ...state, + frameData: null, + annotations: [], + dataFetching: true, + canvasIsReady: false, + }; + } + case AnnotationActionTypes.CHANGE_FRAME_SUCCESS: { + return { + ...state, + frame: action.payload.frame, + annotations: action.payload.annotations, + frameData: action.payload.frameData, + dataFetching: false, + }; + } + case AnnotationActionTypes.CHANGE_FRAME_FAILED: { + return { + ...state, + dataFetching: false, + }; // add notification if failed + } + case AnnotationActionTypes.SWITCH_PLAY: { + return { + ...state, + playing: action.payload.playing, + }; + } + case AnnotationActionTypes.CONFIRM_CANVAS_READY: { + return { + ...state, + canvasIsReady: true, + }; + } + default: { + return { + ...state, + }; + } + } +}; diff --git a/cvat-ui/src/reducers/interfaces.ts b/cvat-ui/src/reducers/interfaces.ts index 138c0bce7d8..7a3d70dbe04 100644 --- a/cvat-ui/src/reducers/interfaces.ts +++ b/cvat-ui/src/reducers/interfaces.ts @@ -1,3 +1,5 @@ +import { Canvas } from '../canvas'; + export interface AuthState { initialized: boolean; fetching: boolean; @@ -197,6 +199,61 @@ export interface NotificationsState { }; } +export interface AnnotationState { + canvasInstance: Canvas; + canvasIsReady: boolean; + jobInstance: any | null | undefined; + frameData: any | null; + frame: number; + playing: boolean; + annotations: any[]; + jobFetching: boolean; + dataFetching: boolean; +} + +export enum GridColor { + White = 'White', + Black = 'Black', + Red = 'Red', + Green = 'Green', + Blue = 'Blue', +} + +export enum FrameSpeed { + Fastest = 100, + Fast = 50, + Usual = 25, + Slow = 15, + Slower = 12, + Slowest = 1, +} + +export interface PlayerSettingsState { + frameStep: number; + frameSpeed: FrameSpeed; + resetZoom: boolean; + rotateAll: boolean; + grid: boolean; + gridSize: number; + gridColor: GridColor; + gridOpacity: number; // in % + brightnessLevel: number; + contrastLevel: number; + saturationLevel: number; +} + +export interface WorkspaceSettingsState { + autoSave: boolean; + autoSaveInterval: number; // in ms + aamZoomMargin: number; + showAllInterpolationTracks: boolean; +} + +export interface SettingsState { + workspace: WorkspaceSettingsState; + player: PlayerSettingsState; +} + export interface CombinedState { auth: AuthState; tasks: TasksState; @@ -206,4 +263,6 @@ export interface CombinedState { plugins: PluginsState; models: ModelsState; notifications: NotificationsState; + annotation: AnnotationState; + settings: SettingsState; } diff --git a/cvat-ui/src/reducers/root-reducer.ts b/cvat-ui/src/reducers/root-reducer.ts index 52d0723b921..de12c6b55db 100644 --- a/cvat-ui/src/reducers/root-reducer.ts +++ b/cvat-ui/src/reducers/root-reducer.ts @@ -7,6 +7,8 @@ import formatsReducer from './formats-reducer'; import pluginsReducer from './plugins-reducer'; import modelsReducer from './models-reducer'; import notificationsReducer from './notifications-reducer'; +import annotationReducer from './annotation-reducer'; +import settingsReducer from './settings-reducer'; export default function createRootReducer(): Reducer { return combineReducers({ @@ -18,5 +20,7 @@ export default function createRootReducer(): Reducer { plugins: pluginsReducer, models: modelsReducer, notifications: notificationsReducer, + annotation: annotationReducer, + settings: settingsReducer, }); } diff --git a/cvat-ui/src/reducers/settings-reducer.ts b/cvat-ui/src/reducers/settings-reducer.ts new file mode 100644 index 00000000000..07e226936d3 --- /dev/null +++ b/cvat-ui/src/reducers/settings-reducer.ts @@ -0,0 +1,85 @@ +import { AnyAction } from 'redux'; +import { SettingsActionTypes } from '../actions/settings-actions'; + +import { + SettingsState, + GridColor, + FrameSpeed, +} from './interfaces'; + +const defaultState: SettingsState = { + workspace: { + autoSave: false, + autoSaveInterval: 15 * 60 * 1000, + aamZoomMargin: 100, + showAllInterpolationTracks: false, + }, + player: { + frameStep: 10, + frameSpeed: FrameSpeed.Usual, + resetZoom: false, + rotateAll: false, + grid: false, + gridSize: 100, + gridColor: GridColor.White, + gridOpacity: 0, + brightnessLevel: 50, + contrastLevel: 50, + saturationLevel: 50, + }, +}; + +export default (state = defaultState, action: AnyAction): SettingsState => { + switch (action.type) { + case SettingsActionTypes.SWITCH_ROTATE_ALL: { + return { + ...state, + player: { + ...state.player, + rotateAll: action.payload.rotateAll, + }, + }; + } + case SettingsActionTypes.SWITCH_GRID: { + return { + ...state, + player: { + ...state.player, + grid: action.payload.grid, + }, + }; + } + case SettingsActionTypes.CHANGE_GRID_SIZE: { + return { + ...state, + player: { + ...state.player, + gridSize: action.payload.gridSize, + }, + }; + } + case SettingsActionTypes.CHANGE_GRID_COLOR: { + return { + ...state, + player: { + ...state.player, + gridColor: action.payload.gridColor, + }, + }; + } + case SettingsActionTypes.CHANGE_GRID_OPACITY: { + return { + ...state, + player: { + ...state.player, + gridOpacity: action.payload.gridOpacity, + }, + }; + } + default: { + return { + ...state, + }; + } + } +}; diff --git a/cvat-ui/webpack.config.js b/cvat-ui/webpack.config.js index ba1e2dbb650..721b14e204d 100644 --- a/cvat-ui/webpack.config.js +++ b/cvat-ui/webpack.config.js @@ -39,7 +39,7 @@ module.exports = { }]], presets: [ ['@babel/preset-env', { - targets: '> 3%', // https://github.com/browserslist/browserslist + targets: '> 2.5%', // https://github.com/browserslist/browserslist }], ['@babel/preset-react'], ['@babel/typescript'], @@ -92,4 +92,4 @@ module.exports = { }), ], node: { fs: 'empty' }, -}; \ No newline at end of file +};