diff --git a/.eslintrc b/.eslintrc deleted file mode 100644 index ff93f926..00000000 --- a/.eslintrc +++ /dev/null @@ -1,27 +0,0 @@ -{ - "globals": { - "JsDiff": true - }, - "plugins": [ - "ember", - "mirego" - ], - "extends": [ - "plugin:mirego/recommended", - "prettier" - ], - "env": { - "es6": true - }, - "rules": { - "no-irregular-whitespace": 0, - "ember/jquery-ember-run": 2, - "ember/use-brace-expansion": 2, - "ember/no-side-effects": 2, - "ember/order-in-routes": 2, - "ember/order-in-models": 2, - "ember/order-in-controllers": 2, - "ember/no-empty-attrs": 2, - "ember/closure-actions": 2 - } -} diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 00000000..20a8e593 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,231 @@ +module.exports = { + root: true, + overrides: [ + { + files: ['webapp/app/**/*', 'webapp/tests/**/*', 'webapp/types/**/*'], + parser: '@typescript-eslint/parser', + parserOptions: { + project: './webapp/tsconfig.json' + }, + plugins: ['@typescript-eslint', 'ember', 'mirego'], + extends: [ + 'plugin:mirego/recommended', + 'prettier', + 'prettier/@typescript-eslint', + 'typestrict' + ], + env: { + es6: true, + browser: true + }, + globals: { + JsDiff: true + }, + rules: { + 'complexity': 0, + 'no-irregular-whitespace': 0, + 'ember/closure-actions': 2, + 'ember/named-functions-in-promises': 0, + 'ember/new-module-imports': 2, + 'ember/no-global-jquery': 2, + 'ember/no-on-calls-in-components': 2, + 'ember/no-duplicate-dependent-keys': 2, + 'ember/no-side-effects': 2, + 'ember/require-super-in-init': 2, + 'ember/avoid-leaking-state-in-ember-objects': 2, + 'ember/use-brace-expansion': 2, + 'ember/jquery-ember-run': 2, + 'ember/order-in-routes': 2, + 'ember/order-in-controllers': 2, + 'ember/no-empty-attrs': 2, + '@typescript-eslint/adjacent-overload-signatures': 2, + '@typescript-eslint/array-type': [2, {default: 'array-simple'}], + '@typescript-eslint/await-thenable': 2, + '@typescript-eslint/ban-ts-ignore': 2, + '@typescript-eslint/consistent-type-assertions': [ + 2, + {assertionStyle: 'as'} + ], + '@typescript-eslint/consistent-type-definitions': [2, 'interface'], + '@typescript-eslint/member-delimiter-style': [ + 2, + { + multiline: { + delimiter: 'semi', + requireLast: true + }, + singleline: { + delimiter: 'semi', + requireLast: false + } + } + ], + '@typescript-eslint/member-ordering': 2, + '@typescript-eslint/no-empty-interface': 2, + '@typescript-eslint/no-floating-promises': 2, + '@typescript-eslint/no-misused-new': 2, + '@typescript-eslint/no-misused-promises': 2, + '@typescript-eslint/no-non-null-assertion': 2, + '@typescript-eslint/no-parameter-properties': 2, + '@typescript-eslint/no-require-imports': 2, + '@typescript-eslint/no-unnecessary-type-assertion': 2, + '@typescript-eslint/promise-function-async': 2, + '@typescript-eslint/require-await': 2, + '@typescript-eslint/type-annotation-spacing': 2, + '@typescript-eslint/unified-signatures': 2, + 'no-unused-vars': 0, + 'no-invalid-this': 0, + '@typescript-eslint/no-unused-vars': 2, + } + }, + { + files: [ + 'webapp/.ember-cli.js', + 'webapp/.eslintrc.js', + 'webapp/.template-lintrc.js', + 'webapp/ember-cli-build.js', + 'webapp/testem.js', + 'webapp/config/**/*.js', + 'webapp/lib/*/index.js', + 'webapp/scripts/**/*.js', + 'webapp/node-server/**/*.js' + ], + parserOptions: { + sourceType: 'script', + ecmaVersion: 2015 + }, + env: { + browser: false, + node: true + }, + plugins: ['node'], + rules: { + '@typescript-eslint/no-require-imports': 0, + + // this can be removed once the following is fixed + // https://github.com/mysticatea/eslint-plugin-node/issues/77 + 'node/no-unpublished-require': 'off' + }, + extends: ['plugin:node/recommended'] + }, + { + files: ['cli/**/*'], + env: { + es6: true + }, + globals: { + process: true + }, + parser: '@typescript-eslint/parser', + parserOptions: { + project: './cli/tsconfig.json' + }, + plugins: ['@typescript-eslint', 'mirego'], + extends: [ + 'plugin:mirego/recommended', + 'prettier', + 'prettier/@typescript-eslint' + ], + rules: { + 'complexity': 0, + 'no-irregular-whitespace': 0, + 'no-unused-vars': 0, + 'no-console': 0, + 'max-nested-callbacks': [2, {max: 3}], + '@typescript-eslint/adjacent-overload-signatures': 2, + '@typescript-eslint/array-type': [2, {default: 'array-simple'}], + '@typescript-eslint/await-thenable': 2, + '@typescript-eslint/ban-ts-ignore': 2, + '@typescript-eslint/consistent-type-assertions': [ + 2, + {assertionStyle: 'as'} + ], + '@typescript-eslint/consistent-type-definitions': [2, 'interface'], + '@typescript-eslint/member-delimiter-style': [ + 2, + { + multiline: { + delimiter: 'semi', + requireLast: true + }, + singleline: { + delimiter: 'semi', + requireLast: false + } + } + ], + '@typescript-eslint/member-ordering': 2, + '@typescript-eslint/no-empty-interface': 2, + '@typescript-eslint/no-floating-promises': 2, + '@typescript-eslint/no-misused-new': 2, + '@typescript-eslint/no-misused-promises': 2, + '@typescript-eslint/no-non-null-assertion': 0, + '@typescript-eslint/no-parameter-properties': 2, + '@typescript-eslint/no-require-imports': 2, + '@typescript-eslint/no-unnecessary-type-assertion': 2, + '@typescript-eslint/promise-function-async': 2, + '@typescript-eslint/require-await': 2, + '@typescript-eslint/type-annotation-spacing': 2, + '@typescript-eslint/unified-signatures': 2, + '@typescript-eslint/no-unused-vars': 2 + } + }, + { + files: ['jipt/**/*'], + env: { + es6: true + }, + parser: '@typescript-eslint/parser', + parserOptions: { + project: './jipt/tsconfig.json' + }, + plugins: ['@typescript-eslint', 'mirego'], + extends: [ + 'plugin:mirego/recommended', + 'prettier', + 'prettier/@typescript-eslint' + ], + rules: { + 'complexity': 0, + 'no-irregular-whitespace': 0, + 'no-unused-vars': 0, + '@typescript-eslint/adjacent-overload-signatures': 2, + '@typescript-eslint/array-type': [2, {default: 'array-simple'}], + '@typescript-eslint/await-thenable': 2, + '@typescript-eslint/ban-ts-ignore': 2, + '@typescript-eslint/consistent-type-assertions': [ + 2, + {assertionStyle: 'as'} + ], + '@typescript-eslint/consistent-type-definitions': [2, 'interface'], + '@typescript-eslint/member-delimiter-style': [ + 2, + { + multiline: { + delimiter: 'semi', + requireLast: true + }, + singleline: { + delimiter: 'semi', + requireLast: false + } + } + ], + '@typescript-eslint/member-ordering': 2, + '@typescript-eslint/no-empty-interface': 2, + '@typescript-eslint/no-floating-promises': 2, + '@typescript-eslint/no-misused-new': 2, + '@typescript-eslint/no-misused-promises': 2, + '@typescript-eslint/no-non-null-assertion': 2, + '@typescript-eslint/no-parameter-properties': 2, + '@typescript-eslint/no-require-imports': 2, + '@typescript-eslint/no-unnecessary-type-assertion': 2, + '@typescript-eslint/promise-function-async': 2, + '@typescript-eslint/require-await': 2, + '@typescript-eslint/type-annotation-spacing': 2, + '@typescript-eslint/unified-signatures': 2, + '@typescript-eslint/no-unused-vars': 2 + } + } + ] +}; diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 253ffd41..1b2a4413 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,38 +1,48 @@ name: CI + on: [push, pull_request] + jobs: test: - env: - MIX_ENV: test runs-on: ubuntu-latest + services: db: image: postgres:10 - ports: ['5432:5432'] - options: >- - --health-cmd pg_isready - --health-interval 10s - --health-timeout 5s - --health-retries 5 + env: + POSTGRES_DB: accent_test + POSTGRES_PASSWORD: password + ports: ["5432:5432"] + options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 + + env: + MIX_ENV: test + DATABASE_URL: postgres://postgres:password@localhost/accent_test + steps: - - uses: actions/checkout@v1 - - uses: actions/setup-elixir@v1.0.0 + - uses: actions/checkout@v2 + + - uses: actions/setup-elixir@v1 with: otp-version: 22.x elixir-version: 1.9.x + - uses: actions/setup-node@v1 with: node-version: 10.14.x + - name: Install System Dependencies run: | sudo apt-get update sudo apt-get install -y gcc libyaml-dev python-yaml + - name: Install Elixir Dependencies run: | mix local.rebar --force mix local.hex --force mix deps.get mix deps.compile + - name: Install NodeJS Dependencies run: | npm config set spin false @@ -40,15 +50,18 @@ jobs: npm i --prefix webapp --no-audit --no-color npm i --prefix cli --no-audit --no-color npm i --prefix jipt --no-audit --no-color + - name: Build webapp production run: npm run build-production-inline --prefix webapp + - name: Run Tests run: | - DATABASE_URL=postgresql://postgres:postgres@localhost:5432/accent_test mix ecto.setup - DATABASE_URL=postgresql://postgres:postgres@localhost:5432/accent_test ./priv/scripts/ci-check.sh + mix ecto.setup + ./priv/scripts/ci-check.sh + - name: Build CLI run: npm --prefix cli run build - name: Build JIPT run: npm --prefix jipt run build-production-inline - name: Coverage report - run: DATABASE_URL=postgresql://postgres:postgres@localhost:5432/accent_test mix coveralls.post --token ${{ secrets.COVERALLS_REPO_TOKEN }} --name 'github-actions' --branch ${{ github.ref }} --committer ${{ github.actor }} --sha ${{ github.sha }} + run: mix coveralls.post --token ${{ secrets.COVERALLS_REPO_TOKEN }} --name 'github-actions' --branch ${{ github.ref }} --committer ${{ github.actor }} --sha ${{ github.sha }} diff --git a/Makefile b/Makefile index 21018627..245b5459 100644 --- a/Makefile +++ b/Makefile @@ -71,7 +71,7 @@ compose-build: ## Build the Docker image from the docker-compose.yml file # ---------- .PHONY: lint -lint: lint-compile lint-format lint-credo lint-eslint lint-prettier lint-tslint lint-template-hbs ## Run lint tools on the code +lint: lint-compile lint-format lint-credo lint-eslint lint-prettier lint-template-hbs ## Run lint tools on the code .PHONY: lint-compile lint-compile: @@ -87,19 +87,19 @@ lint-credo: .PHONY: lint-eslint lint-eslint: - ./node_modules/.bin/eslint webapp/app/. webapp/tests/. cli/. jipt/. - -.PHONY: lint-tslint -lint-tslint: - ./node_modules/.bin/tslint -c tslint.json '{cli,jipt}/src/**/*.{js,ts,json}' + npx eslint --ext .js,.ts ./webapp/app ./cli ./jipt .PHONY: lint-prettier lint-prettier: - ./node_modules/.bin/prettier --check './{webapp,jipt,cli}/!(node_modules)/**/*.{js,ts,json,svg,scss,md}' '*.md' + npx prettier --check './{webapp,jipt,cli}/!(node_modules)/**/*.{js,ts,json,svg,scss,md}' '*.md' .PHONY: lint-template-hbs lint-template-hbs: - ./node_modules/.bin/ember-template-lint './webapp/app/**/*.hbs' --config-path './webapp/.template-lintrc' + npx ember-template-lint './webapp/app/**/*.hbs' --config-path './webapp/.template-lintrc' + +.PHONY: type-check +type-check: ## Type-check typescript files + cd webapp && npx tsc .PHONY: test test: ## Run the test suite @@ -118,7 +118,7 @@ format-elixir: .PHONY: format-prettier format-prettier: - ./node_modules/.bin/prettier --write --single-quote --no-bracket-spacing '{webapp,jipt,cli}/*.{js,json}' 'webapp/{app,config}/**/*.{js,ts,json,scss}' 'jipt/src/**/*.{js,ts,json,gql}' 'cli/{examples,src}/**/*.{js,ts,json,gql}' 'README.md' + npx prettier --write --single-quote --no-bracket-spacing './{webapp,jipt,cli}/!(node_modules)/**/*.{js,ts,json,svg,scss,md}' '*.md' # Development targets # ------------------- diff --git a/cli/package-lock.json b/cli/package-lock.json index 09f1eefb..a1720557 100644 --- a/cli/package-lock.json +++ b/cli/package-lock.json @@ -4,29 +4,6 @@ "lockfileVersion": 1, "requires": true, "dependencies": { - "@fimbul/bifrost": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/@fimbul/bifrost/-/bifrost-0.17.0.tgz", - "integrity": "sha512-gVTkJAOef5HtN6LPmrtt5fAUmBywwlgmObsU3FBhPoNeXPLaIl2zywXkJEtvvVLQnaFmtff3x+wIj5lHRCDE3Q==", - "dev": true, - "requires": { - "@fimbul/ymir": "^0.17.0", - "get-caller-file": "^2.0.0", - "tslib": "^1.8.1", - "tsutils": "^3.5.0" - } - }, - "@fimbul/ymir": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/@fimbul/ymir/-/ymir-0.17.0.tgz", - "integrity": "sha512-xMXM9KTXRLHLVS6dnX1JhHNEkmWHcAVCQ/4+DA1KKwC/AFnGHzu/7QfQttEPgw3xplT+ILf9e3i64jrFwB3JtA==", - "dev": true, - "requires": { - "inversify": "^5.0.0", - "reflect-metadata": "^0.1.12", - "tslib": "^1.8.1" - } - }, "@mrmlnc/readdir-enhanced": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz", @@ -565,16 +542,6 @@ "fancy-test": "^1.0.1" } }, - "@oclif/tslint": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@oclif/tslint/-/tslint-3.1.1.tgz", - "integrity": "sha512-B1ZWbgzwxDhNZLzVnn+JjyFf9u+J9wNwsz/ZX9YvA9edRYcdiJz9JikCttGPi35V0NU0TUV4UqTqo/q/wQ06jQ==", - "dev": true, - "requires": { - "tslint-eslint-rules": "^5.4.0", - "tslint-xo": "^0.9.0" - } - }, "@types/chai": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.1.2.tgz", @@ -673,15 +640,6 @@ "resolved": "https://registry.npmjs.org/ansicolors/-/ansicolors-0.3.2.tgz", "integrity": "sha1-ZlWX3oap/+Oqm/vmyuXG6kJrSXk=" }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, "arr-diff": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", @@ -750,65 +708,6 @@ "integrity": "sha1-GcenYEc3dEaPILLS0DNyrX1Mv10=", "dev": true }, - "babel-code-frame": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", - "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "esutils": "^2.0.2", - "js-tokens": "^3.0.2" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "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" - } - }, - "esutils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", - "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", - "dev": true - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "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 - } - } - }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", @@ -1364,16 +1263,6 @@ "path-type": "^3.0.0" } }, - "doctrine": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-0.7.2.tgz", - "integrity": "sha1-fLhgNZujvpDgQLJrcpzkv6ZUxSM=", - "dev": true, - "requires": { - "esutils": "^1.1.6", - "isarray": "0.0.1" - } - }, "end-of-stream": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", @@ -1402,12 +1291,6 @@ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==" }, - "esutils": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-1.1.6.tgz", - "integrity": "sha1-wBzKqa5LiXxtDD4hCuUvPHqEQ3U=", - "dev": true - }, "execa": { "version": "0.10.0", "resolved": "https://registry.npmjs.org/execa/-/execa-0.10.0.tgz", @@ -1693,12 +1576,6 @@ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, - "get-caller-file": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.1.tgz", - "integrity": "sha512-SpOZHfz845AH0wJYVuZk2jWDqFmu7Xubsx+ldIpwzy5pDUpu7OJHK7QYNSA2NPlDSKQwM1GFaAkciOWjjW92Sg==", - "dev": true - }, "get-func-name": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", @@ -1783,23 +1660,6 @@ "integrity": "sha512-hKlsbA5Vu3xsh1Cg3J7jSmX/WaW6A5oBeqzM88oNbCRQFz+zUaXm6yxS4RVytp1scBoJzSYl4YAEOQIt6O8V1Q==", "dev": true }, - "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" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - } - } - }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -1898,12 +1758,6 @@ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" }, - "inversify": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/inversify/-/inversify-5.0.1.tgz", - "integrity": "sha512-Ieh06s48WnEYGcqHepdsJUIJUXpwH5o5vodAX+DK2JA/gjy4EbEcQZxw+uFfzysmKjiLXGYwNG3qDZsKVMcINQ==", - "dev": true - }, "is-accessor-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", @@ -2055,12 +1909,6 @@ "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=" }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -2072,22 +1920,6 @@ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", "dev": true }, - "js-tokens": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", - "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", - "dev": true - }, - "js-yaml": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz", - "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, "json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", @@ -2553,12 +2385,6 @@ "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" }, - "path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", - "dev": true - }, "path-type": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", @@ -2676,12 +2502,6 @@ "esprima": "~4.0.0" } }, - "reflect-metadata": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", - "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==", - "dev": true - }, "regex-not": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", @@ -2704,15 +2524,6 @@ "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", "dev": true }, - "resolve": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz", - "integrity": "sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==", - "dev": true, - "requires": { - "path-parse": "^1.0.5" - } - }, "resolve-url": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", @@ -3030,12 +2841,6 @@ "extend-shallow": "^3.0.0" } }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, "static-extend": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", @@ -3303,129 +3108,6 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==" }, - "tslint": { - "version": "5.11.0", - "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.11.0.tgz", - "integrity": "sha1-mPMMAurjzecAYgHkwzywi0hYHu0=", - "dev": true, - "requires": { - "babel-code-frame": "^6.22.0", - "builtin-modules": "^1.1.1", - "chalk": "^2.3.0", - "commander": "^2.12.1", - "diff": "^3.2.0", - "glob": "^7.1.1", - "js-yaml": "^3.7.0", - "minimatch": "^3.0.4", - "resolve": "^1.3.2", - "semver": "^5.3.0", - "tslib": "^1.8.0", - "tsutils": "^2.27.2" - }, - "dependencies": { - "commander": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz", - "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==", - "dev": true - }, - "tsutils": { - "version": "2.29.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", - "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", - "dev": true, - "requires": { - "tslib": "^1.8.1" - } - } - } - }, - "tslint-config-prettier": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/tslint-config-prettier/-/tslint-config-prettier-1.17.0.tgz", - "integrity": "sha512-NKWNkThwqE4Snn4Cm6SZB7lV5RMDDFsBwz6fWUkTxOKGjMx8ycOHnjIbhn7dZd5XmssW3CwqUjlANR6EhP9YQw==" - }, - "tslint-consistent-codestyle": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/tslint-consistent-codestyle/-/tslint-consistent-codestyle-1.15.0.tgz", - "integrity": "sha512-6BNDBbZh2K0ibRXe70Mkl9gfVttxQ3t3hqV1BRDfpIcjrUoOgD946iH4SrXp+IggDgeMs3dJORjD5tqL5j4jXg==", - "dev": true, - "requires": { - "@fimbul/bifrost": "^0.17.0", - "tslib": "^1.7.1", - "tsutils": "^2.29.0" - }, - "dependencies": { - "tsutils": { - "version": "2.29.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", - "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", - "dev": true, - "requires": { - "tslib": "^1.8.1" - } - } - } - }, - "tslint-eslint-rules": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/tslint-eslint-rules/-/tslint-eslint-rules-5.4.0.tgz", - "integrity": "sha512-WlSXE+J2vY/VPgIcqQuijMQiel+UtmXS+4nvK4ZzlDiqBfXse8FAvkNnTcYhnQyOTW5KFM+uRRGXxYhFpuBc6w==", - "dev": true, - "requires": { - "doctrine": "0.7.2", - "tslib": "1.9.0", - "tsutils": "^3.0.0" - }, - "dependencies": { - "tslib": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.0.tgz", - "integrity": "sha512-f/qGG2tUkrISBlQZEjEqoZ3B2+npJjIf04H1wuAv9iA8i04Icp+61KRXxFdha22670NJopsZCIjhC3SnjPRKrQ==", - "dev": true - } - } - }, - "tslint-microsoft-contrib": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/tslint-microsoft-contrib/-/tslint-microsoft-contrib-5.2.1.tgz", - "integrity": "sha512-PDYjvpo0gN9IfMULwKk0KpVOPMhU6cNoT9VwCOLeDl/QS8v8W2yspRpFFuUS7/c5EIH/n8ApMi8TxJAz1tfFUA==", - "dev": true, - "requires": { - "tsutils": "^2.27.2 <2.29.0" - }, - "dependencies": { - "tsutils": { - "version": "2.28.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.28.0.tgz", - "integrity": "sha512-bh5nAtW0tuhvOJnx1GLRn5ScraRLICGyJV5wJhtRWOLsxW70Kk5tZtpK3O/hW6LDnqKS9mlUMPZj9fEMJ0gxqA==", - "dev": true, - "requires": { - "tslib": "^1.8.1" - } - } - } - }, - "tslint-xo": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/tslint-xo/-/tslint-xo-0.9.0.tgz", - "integrity": "sha512-Zk5jBdQVUaHEmR9TUoh1TJOjjCr7/nRplA+jDZBvucyBMx65pt0unTr6H/0HvrtSlucFvOMYsyBZE1W8b4AOig==", - "dev": true, - "requires": { - "tslint-consistent-codestyle": "^1.11.0", - "tslint-eslint-rules": "^5.3.1", - "tslint-microsoft-contrib": "^5.0.2" - } - }, - "tsutils": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.7.0.tgz", - "integrity": "sha512-n+e+3q7Jx2kfZw7tjfI9axEIWBY0sFMOlC+1K70X0SeXpO/UYSB+PN+E9tIJNqViB7oiXQdqD7dNchnvoneZew==", - "dev": true, - "requires": { - "tslib": "^1.8.1" - } - }, "tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", diff --git a/cli/package.json b/cli/package.json index d5e8ccdb..34e60d48 100644 --- a/cli/package.json +++ b/cli/package.json @@ -23,13 +23,11 @@ "form-data": "2.3.3", "glob": "7.1.3", "node-fetch": "2.3.0", - "tslib": "1.9.3", - "tslint-config-prettier": "1.17.0" + "tslib": "1.9.3" }, "devDependencies": { "@oclif/dev-cli": "1.21.0", "@oclif/test": "1.0.1", - "@oclif/tslint": "3.1.1", "@types/chai": "4.1.2", "@types/mkdirp": "0.5.2", "@types/mocha": "5.0.0", @@ -38,7 +36,6 @@ "globby": "8.0.1", "mocha": "5.0.5", "ts-node": "7.0.1", - "tslint": "5.11.0", "typescript": "3.2.2" }, "engines": { diff --git a/cli/src/base.ts b/cli/src/base.ts index b719deb2..a8c7f779 100644 --- a/cli/src/base.ts +++ b/cli/src/base.ts @@ -11,7 +11,7 @@ import ProjectFetcher from './services/project-fetcher'; // Types import {Project} from './types/project'; -const sleep = (ms: number) => +const sleep = async (ms: number) => new Promise((resolve: () => void) => setTimeout(resolve, ms)); export default abstract class extends Command { diff --git a/cli/src/commands/export.ts b/cli/src/commands/export.ts index fb894443..ee4f72f9 100644 --- a/cli/src/commands/export.ts +++ b/cli/src/commands/export.ts @@ -24,8 +24,8 @@ export default class Export extends Command { 'order-by': flags.string({ default: 'index', description: 'Will be used in the export call as the order of the keys', - options: ['index', 'key-asc'] - }) + options: ['index', 'key-asc'], + }), }; async run() { @@ -43,9 +43,9 @@ export default class Export extends Command { const targets = new DocumentPathsFetcher().fetch(this.project!, document); await Promise.all( - targets.map(({path, language, documentPath}) => { + targets.map(async ({path, language, documentPath}) => { const localFile = document.fetchLocalFile(documentPath, path); - if (!localFile) return new Promise(resolve => resolve()); + if (!localFile) return new Promise((resolve) => resolve()); formatter.log(localFile); return document.export(localFile, language, documentPath, flags); diff --git a/cli/src/commands/jipt.ts b/cli/src/commands/jipt.ts index c9e15d4e..6ab4b537 100644 --- a/cli/src/commands/jipt.ts +++ b/cli/src/commands/jipt.ts @@ -22,8 +22,8 @@ export default class Jipt extends Command { { description: 'The pseudo language for in-place-translation-editing', name: 'pseudoLanguageName', - required: true - } + required: true, + }, ]; static flags = {}; @@ -45,7 +45,7 @@ export default class Jipt extends Command { ); await Promise.all( - targets.map(({path, documentPath}) => { + targets.map(async ({path, documentPath}) => { formatter.log(path); return document.exportJipt(path, documentPath); diff --git a/cli/src/commands/stats.ts b/cli/src/commands/stats.ts index ed1af223..c1d1986d 100644 --- a/cli/src/commands/stats.ts +++ b/cli/src/commands/stats.ts @@ -9,9 +9,11 @@ export default class Stats extends Command { static examples = [`$ accent stats`]; + /* eslint-disable @typescript-eslint/require-await */ async run() { const formatter = new Formatter(this.project!); formatter.log(); } + /* eslint-enable @typescript-eslint/require-await */ } diff --git a/cli/src/commands/sync.ts b/cli/src/commands/sync.ts index 3830b597..a7d4bc13 100644 --- a/cli/src/commands/sync.ts +++ b/cli/src/commands/sync.ts @@ -32,28 +32,29 @@ export default class Sync extends Command { static flags = { 'add-translations': flags.boolean({ description: - 'Add translations in Accent to help translators if you already have translated strings' + 'Add translations in Accent to help translators if you already have translated strings', }), 'dry-run': flags.boolean({ default: false, - description: 'Do not write the file from the export _after_ the operation' + description: + 'Do not write the file from the export _after_ the operation', }), 'merge-type': flags.string({ default: 'smart', description: 'Will be used in the add translations call as the "merge_type" param', - options: ['smart', 'passive', 'force'] + options: ['smart', 'passive', 'force'], }), 'order-by': flags.string({ default: 'index', description: 'Will be used in the export call as the order of the keys', - options: ['index', 'key-asc'] + options: ['index', 'key-asc'], }), 'sync-type': flags.string({ default: 'smart', description: 'Will be used in the sync call as the "sync_type" param', - options: ['smart', 'passive'] - }) + options: ['smart', 'passive'], + }), }; async run() { @@ -98,9 +99,9 @@ export default class Sync extends Command { const targets = new DocumentPathsFetcher().fetch(this.project!, document); await Promise.all( - targets.map(({path, language, documentPath}) => { + targets.map(async ({path, language, documentPath}) => { const localFile = document.fetchLocalFile(documentPath, path); - if (!localFile) return new Promise(resolve => resolve()); + if (!localFile) return new Promise((resolve) => resolve()); formatter.log(localFile); @@ -116,7 +117,7 @@ export default class Sync extends Command { const {flags} = this.parse(Sync); const formatter = new CommitOperationFormatter(); - return document.paths.map(async path => { + return document.paths.map(async (path) => { const operations = await document.sync(this.project!, path, flags); const documentPath = document.parseDocumentName(path, document.config); diff --git a/cli/src/services/config.ts b/cli/src/services/config.ts index 632631db..abfad103 100644 --- a/cli/src/services/config.ts +++ b/cli/src/services/config.ts @@ -35,7 +35,7 @@ export default class ConfigFetcher { files(): Document[] { return this.config.files.map( - documentConfig => new Document(documentConfig, this.config) + (documentConfig) => new Document(documentConfig, this.config) ); } } diff --git a/cli/src/services/document-jipt-paths-fetcher.ts b/cli/src/services/document-jipt-paths-fetcher.ts index 9e28f548..b73446b0 100644 --- a/cli/src/services/document-jipt-paths-fetcher.ts +++ b/cli/src/services/document-jipt-paths-fetcher.ts @@ -11,7 +11,7 @@ export default class DocumentJiptPathsFetcher { ): DocumentPath[] { return project.documents.entries .map(({path}) => path) - .map(path => { + .map((path) => { const parsedTarget = document.target .replace('%slug%', pseudoLanguageName) .replace('%original_file_name%', path); @@ -19,7 +19,7 @@ export default class DocumentJiptPathsFetcher { return { documentPath: path, language: pseudoLanguageName, - path: parsedTarget + path: parsedTarget, }; }); } diff --git a/cli/src/services/document-paths-fetcher.ts b/cli/src/services/document-paths-fetcher.ts index 995fff53..a82f806d 100644 --- a/cli/src/services/document-paths-fetcher.ts +++ b/cli/src/services/document-paths-fetcher.ts @@ -10,7 +10,7 @@ export default class DocumentPathsFetcher { const documentPaths = project.documents.entries.map(({path}) => path); return languageSlugs.reduce((memo: DocumentPath[], slug) => { - documentPaths.forEach(path => { + documentPaths.forEach((path) => { const parsedTarget = document.target .replace('%slug%', slug) .replace('%original_file_name%', path) diff --git a/cli/src/services/document.ts b/cli/src/services/document.ts index aa269fcb..b766c295 100644 --- a/cli/src/services/document.ts +++ b/cli/src/services/document.ts @@ -17,9 +17,11 @@ import {Project} from '../types/project'; const enum OperationName { Sync = 'sync', - AddTranslation = 'addTranslations' + AddTranslation = 'addTranslations', } +const ERROR_THRESHOLD_STATUS_CODE = 400; + export default class Document { paths: string[]; readonly apiKey: string; @@ -40,7 +42,7 @@ export default class Document { } async sync(project: Project, file: string, options: any) { - const masterLanguage = fetchFromRevision(project!.masterRevision); + const masterLanguage = fetchFromRevision(project.masterRevision); const formData = new FormData(); formData.append('file', fs.createReadStream(file)); formData.append('document_path', this.parseDocumentName(file, this.config)); @@ -56,7 +58,7 @@ export default class Document { const response = await fetch(url, { body: formData, headers: this.authorizationHeader(), - method: 'POST' + method: 'POST', }); return this.handleResponse(response, options, OperationName.Sync); @@ -84,7 +86,7 @@ export default class Document { const response = await fetch(url, { body: formData, headers: this.authorizationHeader(), - method: 'POST' + method: 'POST', }); return this.handleResponse(response, options, OperationName.AddTranslation); @@ -110,12 +112,12 @@ export default class Document { ['document_path', documentPath], ['document_format', this.config.format], ['order_by', options['order-by']], - ['language', language] + ['language', language], ]; const url = `${this.apiUrl}/export?${this.encodeQuery(query)}`; const response = await fetch(url, { - headers: this.authorizationHeader() + headers: this.authorizationHeader(), }); return this.writeResponseToFile(response, file); @@ -124,12 +126,12 @@ export default class Document { async exportJipt(file: string, documentPath: string) { const query = [ ['document_path', documentPath], - ['document_format', this.config.format] + ['document_format', this.config.format], ]; const url = `${this.apiUrl}/jipt-export?${this.encodeQuery(query)}`; const response = await fetch(url, { - headers: this.authorizationHeader() + headers: this.authorizationHeader(), }); return this.writeResponseToFile(response, file); @@ -182,7 +184,7 @@ export default class Document { return config; } - private writeResponseToFile(response: Response, file: string) { + private async writeResponseToFile(response: Response, file: string) { return new Promise((resolve, reject) => { mkdirp.sync(path.dirname(file)); @@ -199,7 +201,7 @@ export default class Document { operationName: OperationName ): Promise { if (!options['dry-run']) { - if (response.status >= 400) { + if (response.status >= ERROR_THRESHOLD_STATUS_CODE) { return {[operationName]: {success: false}, peek: false}; } diff --git a/cli/src/services/formatters/hook-runner.ts b/cli/src/services/formatters/hook-runner.ts index e61ee612..55879adc 100644 --- a/cli/src/services/formatters/hook-runner.ts +++ b/cli/src/services/formatters/hook-runner.ts @@ -9,7 +9,7 @@ export default class HookRunnerFomatter { log(name: string, commands: string[]) { const operation = capitalizeFirstLetter(decamelize(name, ' ')); console.log(chalk.yellow('➤ '), chalk.bold(chalk.yellow(`${operation}:`))); - commands.forEach(command => { + commands.forEach((command) => { console.log(' ', chalk.yellow(command)); }); console.log(''); diff --git a/cli/src/services/formatters/project-add-translations.ts b/cli/src/services/formatters/project-add-translations.ts index 232d38db..1bc8e920 100644 --- a/cli/src/services/formatters/project-add-translations.ts +++ b/cli/src/services/formatters/project-add-translations.ts @@ -11,7 +11,7 @@ export default class ProjectAddTranslationsFormatter { log(project: Project) { const languages = project.revisions .filter( - revision => + (revision) => fetchFromRevision(revision) !== fetchFromRevision(project.masterRevision) ) diff --git a/cli/src/services/formatters/project-stats.ts b/cli/src/services/formatters/project-stats.ts index 52b78036..e472e6c6 100644 --- a/cli/src/services/formatters/project-stats.ts +++ b/cli/src/services/formatters/project-stats.ts @@ -7,7 +7,7 @@ import {Document, Project, Revision} from '../../types/project'; // Services import { fetchFromRevision, - fetchNameFromRevision + fetchNameFromRevision, } from '../revision-slug-fetcher'; export default class ProjectStatsFormatter { diff --git a/cli/src/services/hook-runner.ts b/cli/src/services/hook-runner.ts index 8aa0f60c..cbb0bc19 100644 --- a/cli/src/services/hook-runner.ts +++ b/cli/src/services/hook-runner.ts @@ -17,6 +17,7 @@ export default class HookRunner { this.hooks = document.config.hooks; } + /* eslint-disable @typescript-eslint/require-await */ async run(name: Hooks) { if (!this.hooks) return null; const hooks = this.hooks[name]; @@ -29,4 +30,5 @@ export default class HookRunner { return this.document.refreshPaths(); } + /* eslint-disable @typescript-eslint/require-await */ } diff --git a/cli/src/services/project-fetcher.ts b/cli/src/services/project-fetcher.ts index 97c843f8..c9abc15d 100644 --- a/cli/src/services/project-fetcher.ts +++ b/cli/src/services/project-fetcher.ts @@ -18,7 +18,7 @@ export default class ProjectFetcher { return data.data && data.data.viewer.project; } - private graphql(config: Config) { + private async graphql(config: Config) { const query = `query ProjectDetails($project_id: ID!) { viewer { project(id: $project_id) { @@ -68,9 +68,9 @@ export default class ProjectFetcher { body: JSON.stringify({query}), headers: { 'Content-Type': 'application/json', - authorization: `Bearer ${config.apiKey}` + authorization: `Bearer ${config.apiKey}`, }, - method: 'POST' + method: 'POST', }); } } diff --git a/cli/src/types/document-config.ts b/cli/src/types/document-config.ts index bdf0fb7d..ac014ca2 100644 --- a/cli/src/types/document-config.ts +++ b/cli/src/types/document-config.ts @@ -4,13 +4,13 @@ export enum Hooks { beforeExport = 'beforeExport', afterExport = 'afterExport', beforeSync = 'beforeSync', - afterSync = 'afterSync' + afterSync = 'afterSync', } export enum NamePattern { file = 'file', fileWithSlugSuffix = 'fileWithSlugSuffix', - parentDirectory = 'parentDirectory' + parentDirectory = 'parentDirectory', } export interface HookConfig { diff --git a/cli/src/types/operation-response.ts b/cli/src/types/operation-response.ts index 594b2b74..df46b21e 100644 --- a/cli/src/types/operation-response.ts +++ b/cli/src/types/operation-response.ts @@ -1,4 +1,4 @@ export interface OperationResponse { - peek: any; [x: string]: any; + peek: any; } diff --git a/jipt/index.ts b/jipt/index.ts index 2ca7575b..b0bf546c 100644 --- a/jipt/index.ts +++ b/jipt/index.ts @@ -1,3 +1,3 @@ import Accent from './src/accent'; -window['accent'].q.forEach(([fun, args]) => Accent[fun](args)); +window['accent'].q.forEach(([fun, args]) => Accent[fun](args)); // eslint-disable-line dot-notation diff --git a/jipt/package-lock.json b/jipt/package-lock.json index 7fcbad05..96af1423 100644 --- a/jipt/package-lock.json +++ b/jipt/package-lock.json @@ -10,7 +10,7 @@ "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", "dev": true, "requires": { - "@babel/highlight": "7.0.0" + "@babel/highlight": "^7.0.0" } }, "@babel/core": { @@ -19,20 +19,20 @@ "integrity": "sha512-w445QGI2qd0E0GlSnq6huRZWPMmQGCp5gd5ZWS4hagn0EiwzxD5QMFkpchyusAyVC1n27OKXzQ0/88aVU9n4xQ==", "dev": true, "requires": { - "@babel/code-frame": "7.0.0", - "@babel/generator": "7.3.3", - "@babel/helpers": "7.3.1", - "@babel/parser": "7.3.3", - "@babel/template": "7.2.2", - "@babel/traverse": "7.2.3", - "@babel/types": "7.3.3", - "convert-source-map": "1.6.0", - "debug": "4.1.1", - "json5": "2.1.0", - "lodash": "4.17.11", - "resolve": "1.10.0", - "semver": "5.6.0", - "source-map": "0.5.7" + "@babel/code-frame": "^7.0.0", + "@babel/generator": "^7.3.3", + "@babel/helpers": "^7.2.0", + "@babel/parser": "^7.3.3", + "@babel/template": "^7.2.2", + "@babel/traverse": "^7.2.2", + "@babel/types": "^7.3.3", + "convert-source-map": "^1.1.0", + "debug": "^4.1.0", + "json5": "^2.1.0", + "lodash": "^4.17.11", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" }, "dependencies": { "json5": { @@ -41,7 +41,7 @@ "integrity": "sha512-8Mh9h6xViijj36g7Dxi+Y4S6hNGV96vcJZr/SrlHh1LR/pEn/8j/+qIBbs44YKl69Lrfctp4QD+AdWLTMqEZAQ==", "dev": true, "requires": { - "minimist": "1.2.0" + "minimist": "^1.2.0" } }, "source-map": { @@ -58,11 +58,11 @@ "integrity": "sha512-aEADYwRRZjJyMnKN7llGIlircxTCofm3dtV5pmY6ob18MSIuipHpA2yZWkPlycwu5HJcx/pADS3zssd8eY7/6A==", "dev": true, "requires": { - "@babel/types": "7.3.3", - "jsesc": "2.5.2", - "lodash": "4.17.11", - "source-map": "0.5.7", - "trim-right": "1.0.1" + "@babel/types": "^7.3.3", + "jsesc": "^2.5.1", + "lodash": "^4.17.11", + "source-map": "^0.5.0", + "trim-right": "^1.0.1" }, "dependencies": { "source-map": { @@ -79,7 +79,7 @@ "integrity": "sha512-3UYcJUj9kvSLbLbUIfQTqzcy5VX7GRZ/CCDrnOaZorFFM01aXp1+GJwuFGV4NDDoAS+mOUyHcO6UD/RfqOks3Q==", "dev": true, "requires": { - "@babel/types": "7.3.3" + "@babel/types": "^7.0.0" } }, "@babel/helper-builder-binary-assignment-operator-visitor": { @@ -88,8 +88,8 @@ "integrity": "sha512-qNSR4jrmJ8M1VMM9tibvyRAHXQs2PmaksQF7c1CGJNipfe3D8p+wgNwgso/P2A2r2mdgBWAXljNWR0QRZAMW8w==", "dev": true, "requires": { - "@babel/helper-explode-assignable-expression": "7.1.0", - "@babel/types": "7.3.3" + "@babel/helper-explode-assignable-expression": "^7.1.0", + "@babel/types": "^7.0.0" } }, "@babel/helper-builder-react-jsx": { @@ -98,8 +98,8 @@ "integrity": "sha512-MjA9KgwCuPEkQd9ncSXvSyJ5y+j2sICHyrI0M3L+6fnS4wMSNDc1ARXsbTfbb2cXHn17VisSnU/sHFTCxVxSMw==", "dev": true, "requires": { - "@babel/types": "7.3.3", - "esutils": "2.0.2" + "@babel/types": "^7.3.0", + "esutils": "^2.0.0" } }, "@babel/helper-call-delegate": { @@ -108,9 +108,9 @@ "integrity": "sha512-YEtYZrw3GUK6emQHKthltKNZwszBcHK58Ygcis+gVUrF4/FmTVr5CCqQNSfmvg2y+YDEANyYoaLz/SHsnusCwQ==", "dev": true, "requires": { - "@babel/helper-hoist-variables": "7.0.0", - "@babel/traverse": "7.2.3", - "@babel/types": "7.3.3" + "@babel/helper-hoist-variables": "^7.0.0", + "@babel/traverse": "^7.1.0", + "@babel/types": "^7.0.0" } }, "@babel/helper-define-map": { @@ -119,9 +119,9 @@ "integrity": "sha512-yPPcW8dc3gZLN+U1mhYV91QU3n5uTbx7DUdf8NnPbjS0RMwBuHi9Xt2MUgppmNz7CJxTBWsGczTiEp1CSOTPRg==", "dev": true, "requires": { - "@babel/helper-function-name": "7.1.0", - "@babel/types": "7.3.3", - "lodash": "4.17.11" + "@babel/helper-function-name": "^7.1.0", + "@babel/types": "^7.0.0", + "lodash": "^4.17.10" } }, "@babel/helper-explode-assignable-expression": { @@ -130,8 +130,8 @@ "integrity": "sha512-NRQpfHrJ1msCHtKjbzs9YcMmJZOg6mQMmGRB+hbamEdG5PNpaSm95275VD92DvJKuyl0s2sFiDmMZ+EnnvufqA==", "dev": true, "requires": { - "@babel/traverse": "7.2.3", - "@babel/types": "7.3.3" + "@babel/traverse": "^7.1.0", + "@babel/types": "^7.0.0" } }, "@babel/helper-function-name": { @@ -140,9 +140,9 @@ "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==", "dev": true, "requires": { - "@babel/helper-get-function-arity": "7.0.0", - "@babel/template": "7.2.2", - "@babel/types": "7.3.3" + "@babel/helper-get-function-arity": "^7.0.0", + "@babel/template": "^7.1.0", + "@babel/types": "^7.0.0" } }, "@babel/helper-get-function-arity": { @@ -151,7 +151,7 @@ "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==", "dev": true, "requires": { - "@babel/types": "7.3.3" + "@babel/types": "^7.0.0" } }, "@babel/helper-hoist-variables": { @@ -160,7 +160,7 @@ "integrity": "sha512-Ggv5sldXUeSKsuzLkddtyhyHe2YantsxWKNi7A+7LeD12ExRDWTRk29JCXpaHPAbMaIPZSil7n+lq78WY2VY7w==", "dev": true, "requires": { - "@babel/types": "7.3.3" + "@babel/types": "^7.0.0" } }, "@babel/helper-member-expression-to-functions": { @@ -169,7 +169,7 @@ "integrity": "sha512-avo+lm/QmZlv27Zsi0xEor2fKcqWG56D5ae9dzklpIaY7cQMK5N8VSpaNVPPagiqmy7LrEjK1IWdGMOqPu5csg==", "dev": true, "requires": { - "@babel/types": "7.3.3" + "@babel/types": "^7.0.0" } }, "@babel/helper-module-imports": { @@ -178,7 +178,7 @@ "integrity": "sha512-aP/hlLq01DWNEiDg4Jn23i+CXxW/owM4WpDLFUbpjxe4NS3BhLVZQ5i7E0ZrxuQ/vwekIeciyamgB1UIYxxM6A==", "dev": true, "requires": { - "@babel/types": "7.3.3" + "@babel/types": "^7.0.0" } }, "@babel/helper-module-transforms": { @@ -187,12 +187,12 @@ "integrity": "sha512-YRD7I6Wsv+IHuTPkAmAS4HhY0dkPobgLftHp0cRGZSdrRvmZY8rFvae/GVu3bD00qscuvK3WPHB3YdNpBXUqrA==", "dev": true, "requires": { - "@babel/helper-module-imports": "7.0.0", - "@babel/helper-simple-access": "7.1.0", - "@babel/helper-split-export-declaration": "7.0.0", - "@babel/template": "7.2.2", - "@babel/types": "7.3.3", - "lodash": "4.17.11" + "@babel/helper-module-imports": "^7.0.0", + "@babel/helper-simple-access": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.0.0", + "@babel/template": "^7.2.2", + "@babel/types": "^7.2.2", + "lodash": "^4.17.10" } }, "@babel/helper-optimise-call-expression": { @@ -201,7 +201,7 @@ "integrity": "sha512-u8nd9NQePYNQV8iPWu/pLLYBqZBa4ZaY1YWRFMuxrid94wKI1QNt67NEZ7GAe5Kc/0LLScbim05xZFWkAdrj9g==", "dev": true, "requires": { - "@babel/types": "7.3.3" + "@babel/types": "^7.0.0" } }, "@babel/helper-plugin-utils": { @@ -216,7 +216,7 @@ "integrity": "sha512-TR0/N0NDCcUIUEbqV6dCO+LptmmSQFQ7q70lfcEB4URsjD0E1HzicrwUH+ap6BAQ2jhCX9Q4UqZy4wilujWlkg==", "dev": true, "requires": { - "lodash": "4.17.11" + "lodash": "^4.17.10" } }, "@babel/helper-remap-async-to-generator": { @@ -225,11 +225,11 @@ "integrity": "sha512-3fOK0L+Fdlg8S5al8u/hWE6vhufGSn0bN09xm2LXMy//REAF8kDCrYoOBKYmA8m5Nom+sV9LyLCwrFynA8/slg==", "dev": true, "requires": { - "@babel/helper-annotate-as-pure": "7.0.0", - "@babel/helper-wrap-function": "7.2.0", - "@babel/template": "7.2.2", - "@babel/traverse": "7.2.3", - "@babel/types": "7.3.3" + "@babel/helper-annotate-as-pure": "^7.0.0", + "@babel/helper-wrap-function": "^7.1.0", + "@babel/template": "^7.1.0", + "@babel/traverse": "^7.1.0", + "@babel/types": "^7.0.0" } }, "@babel/helper-replace-supers": { @@ -238,10 +238,10 @@ "integrity": "sha512-GyieIznGUfPXPWu0yLS6U55Mz67AZD9cUk0BfirOWlPrXlBcan9Gz+vHGz+cPfuoweZSnPzPIm67VtQM0OWZbA==", "dev": true, "requires": { - "@babel/helper-member-expression-to-functions": "7.0.0", - "@babel/helper-optimise-call-expression": "7.0.0", - "@babel/traverse": "7.2.3", - "@babel/types": "7.3.3" + "@babel/helper-member-expression-to-functions": "^7.0.0", + "@babel/helper-optimise-call-expression": "^7.0.0", + "@babel/traverse": "^7.2.3", + "@babel/types": "^7.0.0" } }, "@babel/helper-simple-access": { @@ -250,8 +250,8 @@ "integrity": "sha512-Vk+78hNjRbsiu49zAPALxTb+JUQCz1aolpd8osOF16BGnLtseD21nbHgLPGUwrXEurZgiCOUmvs3ExTu4F5x6w==", "dev": true, "requires": { - "@babel/template": "7.2.2", - "@babel/types": "7.3.3" + "@babel/template": "^7.1.0", + "@babel/types": "^7.0.0" } }, "@babel/helper-split-export-declaration": { @@ -260,7 +260,7 @@ "integrity": "sha512-MXkOJqva62dfC0w85mEf/LucPPS/1+04nmmRMPEBUB++hiiThQ2zPtX/mEWQ3mtzCEjIJvPY8nuwxXtQeQwUag==", "dev": true, "requires": { - "@babel/types": "7.3.3" + "@babel/types": "^7.0.0" } }, "@babel/helper-wrap-function": { @@ -269,10 +269,10 @@ "integrity": "sha512-o9fP1BZLLSrYlxYEYyl2aS+Flun5gtjTIG8iln+XuEzQTs0PLagAGSXUcqruJwD5fM48jzIEggCKpIfWTcR7pQ==", "dev": true, "requires": { - "@babel/helper-function-name": "7.1.0", - "@babel/template": "7.2.2", - "@babel/traverse": "7.2.3", - "@babel/types": "7.3.3" + "@babel/helper-function-name": "^7.1.0", + "@babel/template": "^7.1.0", + "@babel/traverse": "^7.1.0", + "@babel/types": "^7.2.0" } }, "@babel/helpers": { @@ -281,9 +281,9 @@ "integrity": "sha512-Q82R3jKsVpUV99mgX50gOPCWwco9Ec5Iln/8Vyu4osNIOQgSrd9RFrQeUvmvddFNoLwMyOUWU+5ckioEKpDoGA==", "dev": true, "requires": { - "@babel/template": "7.2.2", - "@babel/traverse": "7.2.3", - "@babel/types": "7.3.3" + "@babel/template": "^7.1.2", + "@babel/traverse": "^7.1.5", + "@babel/types": "^7.3.0" } }, "@babel/highlight": { @@ -292,9 +292,9 @@ "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", "dev": true, "requires": { - "chalk": "2.4.2", - "esutils": "2.0.2", - "js-tokens": "4.0.0" + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" } }, "@babel/parser": { @@ -309,9 +309,9 @@ "integrity": "sha512-+Dfo/SCQqrwx48ptLVGLdE39YtWRuKc/Y9I5Fy0P1DDBB9lsAHpjcEJQt+4IifuSOSTLBKJObJqMvaO1pIE8LQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "7.0.0", - "@babel/helper-remap-async-to-generator": "7.1.0", - "@babel/plugin-syntax-async-generators": "7.2.0" + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-remap-async-to-generator": "^7.1.0", + "@babel/plugin-syntax-async-generators": "^7.2.0" } }, "@babel/plugin-proposal-json-strings": { @@ -320,8 +320,8 @@ "integrity": "sha512-MAFV1CA/YVmYwZG0fBQyXhmj0BHCB5egZHCKWIFVv/XCxAeVGIHfos3SwDck4LvCllENIAg7xMKOG5kH0dzyUg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "7.0.0", - "@babel/plugin-syntax-json-strings": "7.2.0" + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-syntax-json-strings": "^7.2.0" } }, "@babel/plugin-proposal-object-rest-spread": { @@ -330,8 +330,8 @@ "integrity": "sha512-DjeMS+J2+lpANkYLLO+m6GjoTMygYglKmRe6cDTbFv3L9i6mmiE8fe6B8MtCSLZpVXscD5kn7s6SgtHrDoBWoA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "7.0.0", - "@babel/plugin-syntax-object-rest-spread": "7.2.0" + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-syntax-object-rest-spread": "^7.2.0" } }, "@babel/plugin-proposal-optional-catch-binding": { @@ -340,8 +340,8 @@ "integrity": "sha512-mgYj3jCcxug6KUcX4OBoOJz3CMrwRfQELPQ5560F70YQUBZB7uac9fqaWamKR1iWUzGiK2t0ygzjTScZnVz75g==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "7.0.0", - "@babel/plugin-syntax-optional-catch-binding": "7.2.0" + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-syntax-optional-catch-binding": "^7.2.0" } }, "@babel/plugin-proposal-unicode-property-regex": { @@ -350,9 +350,9 @@ "integrity": "sha512-LvRVYb7kikuOtIoUeWTkOxQEV1kYvL5B6U3iWEGCzPNRus1MzJweFqORTj+0jkxozkTSYNJozPOddxmqdqsRpw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "7.0.0", - "@babel/helper-regex": "7.0.0", - "regexpu-core": "4.4.0" + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-regex": "^7.0.0", + "regexpu-core": "^4.2.0" } }, "@babel/plugin-syntax-async-generators": { @@ -361,7 +361,7 @@ "integrity": "sha512-1ZrIRBv2t0GSlcwVoQ6VgSLpLgiN/FVQUzt9znxo7v2Ov4jJrs8RY8tv0wvDmFN3qIdMKWrmMMW6yZ0G19MfGg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "7.0.0" + "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-syntax-flow": { @@ -370,7 +370,7 @@ "integrity": "sha512-r6YMuZDWLtLlu0kqIim5o/3TNRAlWb073HwT3e2nKf9I8IIvOggPrnILYPsrrKilmn/mYEMCf/Z07w3yQJF6dg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "7.0.0" + "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-syntax-json-strings": { @@ -379,7 +379,7 @@ "integrity": "sha512-5UGYnMSLRE1dqqZwug+1LISpA403HzlSfsg6P9VXU6TBjcSHeNlw4DxDx7LgpF+iKZoOG/+uzqoRHTdcUpiZNg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "7.0.0" + "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-syntax-jsx": { @@ -388,7 +388,7 @@ "integrity": "sha512-VyN4QANJkRW6lDBmENzRszvZf3/4AXaj9YR7GwrWeeN9tEBPuXbmDYVU9bYBN0D70zCWVwUy0HWq2553VCb6Hw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "7.0.0" + "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-syntax-object-rest-spread": { @@ -397,7 +397,7 @@ "integrity": "sha512-t0JKGgqk2We+9may3t0xDdmneaXmyxq0xieYcKHxIsrJO64n1OiMWNUtc5gQK1PA0NpdCRrtZp4z+IUaKugrSA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "7.0.0" + "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-syntax-optional-catch-binding": { @@ -406,7 +406,7 @@ "integrity": "sha512-bDe4xKNhb0LI7IvZHiA13kff0KEfaGX/Hv4lMA9+7TEc63hMNvfKo6ZFpXhKuEp+II/q35Gc4NoMeDZyaUbj9w==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "7.0.0" + "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-transform-arrow-functions": { @@ -415,7 +415,7 @@ "integrity": "sha512-ER77Cax1+8/8jCB9fo4Ud161OZzWN5qawi4GusDuRLcDbDG+bIGYY20zb2dfAFdTRGzrfq2xZPvF0R64EHnimg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "7.0.0" + "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-transform-async-to-generator": { @@ -424,9 +424,9 @@ "integrity": "sha512-CEHzg4g5UraReozI9D4fblBYABs7IM6UerAVG7EJVrTLC5keh00aEuLUT+O40+mJCEzaXkYfTCUKIyeDfMOFFQ==", "dev": true, "requires": { - "@babel/helper-module-imports": "7.0.0", - "@babel/helper-plugin-utils": "7.0.0", - "@babel/helper-remap-async-to-generator": "7.1.0" + "@babel/helper-module-imports": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-remap-async-to-generator": "^7.1.0" } }, "@babel/plugin-transform-block-scoped-functions": { @@ -435,7 +435,7 @@ "integrity": "sha512-ntQPR6q1/NKuphly49+QiQiTN0O63uOwjdD6dhIjSWBI5xlrbUFh720TIpzBhpnrLfv2tNH/BXvLIab1+BAI0w==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "7.0.0" + "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-transform-block-scoping": { @@ -444,8 +444,8 @@ "integrity": "sha512-vDTgf19ZEV6mx35yiPJe4fS02mPQUUcBNwWQSZFXSzTSbsJFQvHt7DqyS3LK8oOWALFOsJ+8bbqBgkirZteD5Q==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "7.0.0", - "lodash": "4.17.11" + "@babel/helper-plugin-utils": "^7.0.0", + "lodash": "^4.17.10" } }, "@babel/plugin-transform-classes": { @@ -454,14 +454,14 @@ "integrity": "sha512-n0CLbsg7KOXsMF4tSTLCApNMoXk0wOPb0DYfsOO1e7SfIb9gOyfbpKI2MZ+AXfqvlfzq2qsflJ1nEns48Caf2w==", "dev": true, "requires": { - "@babel/helper-annotate-as-pure": "7.0.0", - "@babel/helper-define-map": "7.1.0", - "@babel/helper-function-name": "7.1.0", - "@babel/helper-optimise-call-expression": "7.0.0", - "@babel/helper-plugin-utils": "7.0.0", - "@babel/helper-replace-supers": "7.2.3", - "@babel/helper-split-export-declaration": "7.0.0", - "globals": "11.11.0" + "@babel/helper-annotate-as-pure": "^7.0.0", + "@babel/helper-define-map": "^7.1.0", + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-optimise-call-expression": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-replace-supers": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.0.0", + "globals": "^11.1.0" } }, "@babel/plugin-transform-computed-properties": { @@ -470,7 +470,7 @@ "integrity": "sha512-kP/drqTxY6Xt3NNpKiMomfgkNn4o7+vKxK2DDKcBG9sHj51vHqMBGy8wbDS/J4lMxnqs153/T3+DmCEAkC5cpA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "7.0.0" + "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-transform-destructuring": { @@ -479,7 +479,7 @@ "integrity": "sha512-Lrj/u53Ufqxl/sGxyjsJ2XNtNuEjDyjpqdhMNh5aZ+XFOdThL46KBj27Uem4ggoezSYBxKWAil6Hu8HtwqesYw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "7.0.0" + "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-transform-dotall-regex": { @@ -488,9 +488,9 @@ "integrity": "sha512-sKxnyHfizweTgKZf7XsXu/CNupKhzijptfTM+bozonIuyVrLWVUvYjE2bhuSBML8VQeMxq4Mm63Q9qvcvUcciQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "7.0.0", - "@babel/helper-regex": "7.0.0", - "regexpu-core": "4.4.0" + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-regex": "^7.0.0", + "regexpu-core": "^4.1.3" } }, "@babel/plugin-transform-duplicate-keys": { @@ -499,7 +499,7 @@ "integrity": "sha512-q+yuxW4DsTjNceUiTzK0L+AfQ0zD9rWaTLiUqHA8p0gxx7lu1EylenfzjeIWNkPy6e/0VG/Wjw9uf9LueQwLOw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "7.0.0" + "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-transform-exponentiation-operator": { @@ -508,8 +508,8 @@ "integrity": "sha512-umh4hR6N7mu4Elq9GG8TOu9M0bakvlsREEC+ialrQN6ABS4oDQ69qJv1VtR3uxlKMCQMCvzk7vr17RHKcjx68A==", "dev": true, "requires": { - "@babel/helper-builder-binary-assignment-operator-visitor": "7.1.0", - "@babel/helper-plugin-utils": "7.0.0" + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.1.0", + "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-transform-flow-strip-types": { @@ -518,8 +518,8 @@ "integrity": "sha512-xnt7UIk9GYZRitqCnsVMjQK1O2eKZwFB3CvvHjf5SGx6K6vr/MScCKQDnf1DxRaj501e3pXjti+inbSXX2ZUoQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "7.0.0", - "@babel/plugin-syntax-flow": "7.2.0" + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-syntax-flow": "^7.2.0" } }, "@babel/plugin-transform-for-of": { @@ -528,7 +528,7 @@ "integrity": "sha512-Kz7Mt0SsV2tQk6jG5bBv5phVbkd0gd27SgYD4hH1aLMJRchM0dzHaXvrWhVZ+WxAlDoAKZ7Uy3jVTW2mKXQ1WQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "7.0.0" + "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-transform-function-name": { @@ -537,8 +537,8 @@ "integrity": "sha512-kWgksow9lHdvBC2Z4mxTsvc7YdY7w/V6B2vy9cTIPtLEE9NhwoWivaxdNM/S37elu5bqlLP/qOY906LukO9lkQ==", "dev": true, "requires": { - "@babel/helper-function-name": "7.1.0", - "@babel/helper-plugin-utils": "7.0.0" + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-transform-literals": { @@ -547,7 +547,7 @@ "integrity": "sha512-2ThDhm4lI4oV7fVQ6pNNK+sx+c/GM5/SaML0w/r4ZB7sAneD/piDJtwdKlNckXeyGK7wlwg2E2w33C/Hh+VFCg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "7.0.0" + "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-transform-modules-amd": { @@ -556,8 +556,8 @@ "integrity": "sha512-mK2A8ucqz1qhrdqjS9VMIDfIvvT2thrEsIQzbaTdc5QFzhDjQv2CkJJ5f6BXIkgbmaoax3zBr2RyvV/8zeoUZw==", "dev": true, "requires": { - "@babel/helper-module-transforms": "7.2.2", - "@babel/helper-plugin-utils": "7.0.0" + "@babel/helper-module-transforms": "^7.1.0", + "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-transform-modules-commonjs": { @@ -566,9 +566,9 @@ "integrity": "sha512-V6y0uaUQrQPXUrmj+hgnks8va2L0zcZymeU7TtWEgdRLNkceafKXEduv7QzgQAE4lT+suwooG9dC7LFhdRAbVQ==", "dev": true, "requires": { - "@babel/helper-module-transforms": "7.2.2", - "@babel/helper-plugin-utils": "7.0.0", - "@babel/helper-simple-access": "7.1.0" + "@babel/helper-module-transforms": "^7.1.0", + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-simple-access": "^7.1.0" } }, "@babel/plugin-transform-modules-systemjs": { @@ -577,8 +577,8 @@ "integrity": "sha512-aYJwpAhoK9a+1+O625WIjvMY11wkB/ok0WClVwmeo3mCjcNRjt+/8gHWrB5i+00mUju0gWsBkQnPpdvQ7PImmQ==", "dev": true, "requires": { - "@babel/helper-hoist-variables": "7.0.0", - "@babel/helper-plugin-utils": "7.0.0" + "@babel/helper-hoist-variables": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-transform-modules-umd": { @@ -587,8 +587,8 @@ "integrity": "sha512-BV3bw6MyUH1iIsGhXlOK6sXhmSarZjtJ/vMiD9dNmpY8QXFFQTj+6v92pcfy1iqa8DeAfJFwoxcrS/TUZda6sw==", "dev": true, "requires": { - "@babel/helper-module-transforms": "7.2.2", - "@babel/helper-plugin-utils": "7.0.0" + "@babel/helper-module-transforms": "^7.1.0", + "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-transform-named-capturing-groups-regex": { @@ -597,7 +597,7 @@ "integrity": "sha512-NxIoNVhk9ZxS+9lSoAQ/LM0V2UEvARLttEHUrRDGKFaAxOYQcrkN/nLRE+BbbicCAvZPl7wMP0X60HsHE5DtQw==", "dev": true, "requires": { - "regexp-tree": "0.1.5" + "regexp-tree": "^0.1.0" } }, "@babel/plugin-transform-new-target": { @@ -606,7 +606,7 @@ "integrity": "sha512-yin069FYjah+LbqfGeTfzIBODex/e++Yfa0rH0fpfam9uTbuEeEOx5GLGr210ggOV77mVRNoeqSYqeuaqSzVSw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "7.0.0" + "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-transform-object-super": { @@ -615,8 +615,8 @@ "integrity": "sha512-VMyhPYZISFZAqAPVkiYb7dUe2AsVi2/wCT5+wZdsNO31FojQJa9ns40hzZ6U9f50Jlq4w6qwzdBB2uwqZ00ebg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "7.0.0", - "@babel/helper-replace-supers": "7.2.3" + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-replace-supers": "^7.1.0" } }, "@babel/plugin-transform-parameters": { @@ -625,9 +625,9 @@ "integrity": "sha512-IrIP25VvXWu/VlBWTpsjGptpomtIkYrN/3aDp4UKm7xK6UxZY88kcJ1UwETbzHAlwN21MnNfwlar0u8y3KpiXw==", "dev": true, "requires": { - "@babel/helper-call-delegate": "7.1.0", - "@babel/helper-get-function-arity": "7.0.0", - "@babel/helper-plugin-utils": "7.0.0" + "@babel/helper-call-delegate": "^7.1.0", + "@babel/helper-get-function-arity": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-transform-react-jsx": { @@ -636,9 +636,9 @@ "integrity": "sha512-a/+aRb7R06WcKvQLOu4/TpjKOdvVEKRLWFpKcNuHhiREPgGRB4TQJxq07+EZLS8LFVYpfq1a5lDUnuMdcCpBKg==", "dev": true, "requires": { - "@babel/helper-builder-react-jsx": "7.3.0", - "@babel/helper-plugin-utils": "7.0.0", - "@babel/plugin-syntax-jsx": "7.2.0" + "@babel/helper-builder-react-jsx": "^7.3.0", + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-syntax-jsx": "^7.2.0" } }, "@babel/plugin-transform-regenerator": { @@ -647,7 +647,7 @@ "integrity": "sha512-sj2qzsEx8KDVv1QuJc/dEfilkg3RRPvPYx/VnKLtItVQRWt1Wqf5eVCOLZm29CiGFfYYsA3VPjfizTCV0S0Dlw==", "dev": true, "requires": { - "regenerator-transform": "0.13.4" + "regenerator-transform": "^0.13.3" } }, "@babel/plugin-transform-shorthand-properties": { @@ -656,7 +656,7 @@ "integrity": "sha512-QP4eUM83ha9zmYtpbnyjTLAGKQritA5XW/iG9cjtuOI8s1RuL/3V6a3DeSHfKutJQ+ayUfeZJPcnCYEQzaPQqg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "7.0.0" + "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-transform-spread": { @@ -665,7 +665,7 @@ "integrity": "sha512-KWfky/58vubwtS0hLqEnrWJjsMGaOeSBn90Ezn5Jeg9Z8KKHmELbP1yGylMlm5N6TPKeY9A2+UaSYLdxahg01w==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "7.0.0" + "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-transform-sticky-regex": { @@ -674,8 +674,8 @@ "integrity": "sha512-KKYCoGaRAf+ckH8gEL3JHUaFVyNHKe3ASNsZ+AlktgHevvxGigoIttrEJb8iKN03Q7Eazlv1s6cx2B2cQ3Jabw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "7.0.0", - "@babel/helper-regex": "7.0.0" + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-regex": "^7.0.0" } }, "@babel/plugin-transform-template-literals": { @@ -684,8 +684,8 @@ "integrity": "sha512-FkPix00J9A/XWXv4VoKJBMeSkyY9x/TqIh76wzcdfl57RJJcf8CehQ08uwfhCDNtRQYtHQKBTwKZDEyjE13Lwg==", "dev": true, "requires": { - "@babel/helper-annotate-as-pure": "7.0.0", - "@babel/helper-plugin-utils": "7.0.0" + "@babel/helper-annotate-as-pure": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-transform-typeof-symbol": { @@ -694,7 +694,7 @@ "integrity": "sha512-2LNhETWYxiYysBtrBTqL8+La0jIoQQnIScUJc74OYvUGRmkskNY4EzLCnjHBzdmb38wqtTaixpo1NctEcvMDZw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "7.0.0" + "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-transform-unicode-regex": { @@ -703,9 +703,9 @@ "integrity": "sha512-m48Y0lMhrbXEJnVUaYly29jRXbQ3ksxPrS1Tg8t+MHqzXhtBYAvI51euOBaoAlZLPHsieY9XPVMf80a5x0cPcA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "7.0.0", - "@babel/helper-regex": "7.0.0", - "regexpu-core": "4.4.0" + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-regex": "^7.0.0", + "regexpu-core": "^4.1.3" } }, "@babel/preset-env": { @@ -714,49 +714,49 @@ "integrity": "sha512-FHKrD6Dxf30e8xgHQO0zJZpUPfVZg+Xwgz5/RdSWCbza9QLNk4Qbp40ctRoqDxml3O8RMzB1DU55SXeDG6PqHQ==", "dev": true, "requires": { - "@babel/helper-module-imports": "7.0.0", - "@babel/helper-plugin-utils": "7.0.0", - "@babel/plugin-proposal-async-generator-functions": "7.2.0", - "@babel/plugin-proposal-json-strings": "7.2.0", - "@babel/plugin-proposal-object-rest-spread": "7.3.2", - "@babel/plugin-proposal-optional-catch-binding": "7.2.0", - "@babel/plugin-proposal-unicode-property-regex": "7.2.0", - "@babel/plugin-syntax-async-generators": "7.2.0", - "@babel/plugin-syntax-json-strings": "7.2.0", - "@babel/plugin-syntax-object-rest-spread": "7.2.0", - "@babel/plugin-syntax-optional-catch-binding": "7.2.0", - "@babel/plugin-transform-arrow-functions": "7.2.0", - "@babel/plugin-transform-async-to-generator": "7.2.0", - "@babel/plugin-transform-block-scoped-functions": "7.2.0", - "@babel/plugin-transform-block-scoping": "7.2.0", - "@babel/plugin-transform-classes": "7.3.3", - "@babel/plugin-transform-computed-properties": "7.2.0", - "@babel/plugin-transform-destructuring": "7.3.2", - "@babel/plugin-transform-dotall-regex": "7.2.0", - "@babel/plugin-transform-duplicate-keys": "7.2.0", - "@babel/plugin-transform-exponentiation-operator": "7.2.0", - "@babel/plugin-transform-for-of": "7.2.0", - "@babel/plugin-transform-function-name": "7.2.0", - "@babel/plugin-transform-literals": "7.2.0", - "@babel/plugin-transform-modules-amd": "7.2.0", - "@babel/plugin-transform-modules-commonjs": "7.2.0", - "@babel/plugin-transform-modules-systemjs": "7.2.0", - "@babel/plugin-transform-modules-umd": "7.2.0", - "@babel/plugin-transform-named-capturing-groups-regex": "7.3.0", - "@babel/plugin-transform-new-target": "7.0.0", - "@babel/plugin-transform-object-super": "7.2.0", - "@babel/plugin-transform-parameters": "7.3.3", - "@babel/plugin-transform-regenerator": "7.0.0", - "@babel/plugin-transform-shorthand-properties": "7.2.0", - "@babel/plugin-transform-spread": "7.2.2", - "@babel/plugin-transform-sticky-regex": "7.2.0", - "@babel/plugin-transform-template-literals": "7.2.0", - "@babel/plugin-transform-typeof-symbol": "7.2.0", - "@babel/plugin-transform-unicode-regex": "7.2.0", - "browserslist": "4.4.2", - "invariant": "2.2.4", - "js-levenshtein": "1.1.6", - "semver": "5.6.0" + "@babel/helper-module-imports": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-proposal-async-generator-functions": "^7.2.0", + "@babel/plugin-proposal-json-strings": "^7.2.0", + "@babel/plugin-proposal-object-rest-spread": "^7.3.1", + "@babel/plugin-proposal-optional-catch-binding": "^7.2.0", + "@babel/plugin-proposal-unicode-property-regex": "^7.2.0", + "@babel/plugin-syntax-async-generators": "^7.2.0", + "@babel/plugin-syntax-json-strings": "^7.2.0", + "@babel/plugin-syntax-object-rest-spread": "^7.2.0", + "@babel/plugin-syntax-optional-catch-binding": "^7.2.0", + "@babel/plugin-transform-arrow-functions": "^7.2.0", + "@babel/plugin-transform-async-to-generator": "^7.2.0", + "@babel/plugin-transform-block-scoped-functions": "^7.2.0", + "@babel/plugin-transform-block-scoping": "^7.2.0", + "@babel/plugin-transform-classes": "^7.2.0", + "@babel/plugin-transform-computed-properties": "^7.2.0", + "@babel/plugin-transform-destructuring": "^7.2.0", + "@babel/plugin-transform-dotall-regex": "^7.2.0", + "@babel/plugin-transform-duplicate-keys": "^7.2.0", + "@babel/plugin-transform-exponentiation-operator": "^7.2.0", + "@babel/plugin-transform-for-of": "^7.2.0", + "@babel/plugin-transform-function-name": "^7.2.0", + "@babel/plugin-transform-literals": "^7.2.0", + "@babel/plugin-transform-modules-amd": "^7.2.0", + "@babel/plugin-transform-modules-commonjs": "^7.2.0", + "@babel/plugin-transform-modules-systemjs": "^7.2.0", + "@babel/plugin-transform-modules-umd": "^7.2.0", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.3.0", + "@babel/plugin-transform-new-target": "^7.0.0", + "@babel/plugin-transform-object-super": "^7.2.0", + "@babel/plugin-transform-parameters": "^7.2.0", + "@babel/plugin-transform-regenerator": "^7.0.0", + "@babel/plugin-transform-shorthand-properties": "^7.2.0", + "@babel/plugin-transform-spread": "^7.2.0", + "@babel/plugin-transform-sticky-regex": "^7.2.0", + "@babel/plugin-transform-template-literals": "^7.2.0", + "@babel/plugin-transform-typeof-symbol": "^7.2.0", + "@babel/plugin-transform-unicode-regex": "^7.2.0", + "browserslist": "^4.3.4", + "invariant": "^2.2.2", + "js-levenshtein": "^1.1.3", + "semver": "^5.3.0" } }, "@babel/runtime": { @@ -765,7 +765,7 @@ "integrity": "sha512-7jGW8ppV0ant637pIqAcFfQDDH1orEPGJb8aXfUozuCU3QqX7rX4DA8iwrbPrR1hcH0FTTHz47yQnk+bl5xHQA==", "dev": true, "requires": { - "regenerator-runtime": "0.12.1" + "regenerator-runtime": "^0.12.0" } }, "@babel/template": { @@ -774,9 +774,9 @@ "integrity": "sha512-zRL0IMM02AUDwghf5LMSSDEz7sBCO2YnNmpg3uWTZj/v1rcG2BmQUvaGU8GhU8BvfMh1k2KIAYZ7Ji9KXPUg7g==", "dev": true, "requires": { - "@babel/code-frame": "7.0.0", - "@babel/parser": "7.3.3", - "@babel/types": "7.3.3" + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.2.2", + "@babel/types": "^7.2.2" } }, "@babel/traverse": { @@ -785,15 +785,15 @@ "integrity": "sha512-Z31oUD/fJvEWVR0lNZtfgvVt512ForCTNKYcJBGbPb1QZfve4WGH8Wsy7+Mev33/45fhP/hwQtvgusNdcCMgSw==", "dev": true, "requires": { - "@babel/code-frame": "7.0.0", - "@babel/generator": "7.3.3", - "@babel/helper-function-name": "7.1.0", - "@babel/helper-split-export-declaration": "7.0.0", - "@babel/parser": "7.3.3", - "@babel/types": "7.3.3", - "debug": "4.1.1", - "globals": "11.11.0", - "lodash": "4.17.11" + "@babel/code-frame": "^7.0.0", + "@babel/generator": "^7.2.2", + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.0.0", + "@babel/parser": "^7.2.3", + "@babel/types": "^7.2.2", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.10" } }, "@babel/types": { @@ -802,9 +802,9 @@ "integrity": "sha512-2tACZ80Wg09UnPg5uGAOUvvInaqLk3l/IAhQzlxLQOIXacr6bMsra5SH6AWw/hIDRCSbCdHP2KzSOD+cT7TzMQ==", "dev": true, "requires": { - "esutils": "2.0.2", - "lodash": "4.17.11", - "to-fast-properties": "2.0.0" + "esutils": "^2.0.2", + "lodash": "^4.17.11", + "to-fast-properties": "^2.0.0" } }, "@iarna/toml": { @@ -819,8 +819,8 @@ "integrity": "sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==", "dev": true, "requires": { - "call-me-maybe": "1.0.1", - "glob-to-regexp": "0.3.0" + "call-me-maybe": "^1.0.1", + "glob-to-regexp": "^0.3.0" } }, "@nodelib/fs.stat": { @@ -835,9 +835,9 @@ "integrity": "sha512-86RyEqULbbVoeo8OLcv+LQ1Vq2PKBAvWTU9fCgALxuCTbbs5Ppcvll4Vr+Ko1AnmMzja/k++SzNAwJfeQXVlpA==", "dev": true, "requires": { - "@parcel/utils": "1.11.0", - "mkdirp": "0.5.1", - "rimraf": "2.6.3" + "@parcel/utils": "^1.11.0", + "mkdirp": "^0.5.1", + "rimraf": "^2.6.2" } }, "@parcel/logger": { @@ -846,11 +846,11 @@ "integrity": "sha512-lIRfDg+junbFUUeU0QtHX00gKCgEsYHZydFKwrJ8dc0D+WE2SYT1FcVCgpPAfKYgtg0QQMns8E9vzT9UjH92PQ==", "dev": true, "requires": { - "@parcel/workers": "1.11.0", - "chalk": "2.4.2", - "grapheme-breaker": "0.3.2", - "ora": "2.1.0", - "strip-ansi": "4.0.0" + "@parcel/workers": "^1.11.0", + "chalk": "^2.1.0", + "grapheme-breaker": "^0.3.2", + "ora": "^2.1.0", + "strip-ansi": "^4.0.0" }, "dependencies": { "ansi-regex": { @@ -865,7 +865,7 @@ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, "requires": { - "ansi-regex": "3.0.0" + "ansi-regex": "^3.0.0" } } } @@ -882,8 +882,8 @@ "integrity": "sha512-1ySF0sH06jyhpaErW1UWC7BNgkAl6PJyBjuu2cLTW1o71J2iQqgGt95cbuqmfmjI3l0xYN+nauDFqHERaj7Z8A==", "dev": true, "requires": { - "@parcel/utils": "1.11.0", - "chokidar": "2.1.2" + "@parcel/utils": "^1.11.0", + "chokidar": "^2.0.3" } }, "@parcel/workers": { @@ -892,8 +892,8 @@ "integrity": "sha512-USSjRAAQYsZFlv43FUPdD+jEGML5/8oLF0rUzPQTtK4q9kvaXr49F5ZplyLz5lox78cLZ0TxN2bIDQ1xhOkulQ==", "dev": true, "requires": { - "@parcel/utils": "1.11.0", - "physical-cpu-count": "2.0.0" + "@parcel/utils": "^1.11.0", + "physical-cpu-count": "^2.0.0" } }, "@types/node": { @@ -950,7 +950,7 @@ "integrity": "sha512-znsY3gvsk4CiApWu1yVYF8Nx5Vy0FEe8B0YwyxdbCdErJu5lfKlRHB2twtUjR+dxR4WewTk2OP8XqTmWYnImOg==", "dev": true, "requires": { - "entities": "1.1.2" + "entities": "^1.1.1" } }, "anymatch": { @@ -959,8 +959,8 @@ "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", "dev": true, "requires": { - "micromatch": "3.1.10", - "normalize-path": "2.1.1" + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" }, "dependencies": { "normalize-path": { @@ -969,7 +969,7 @@ "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", "dev": true, "requires": { - "remove-trailing-separator": "1.1.0" + "remove-trailing-separator": "^1.0.1" } } } @@ -980,7 +980,7 @@ "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "dev": true, "requires": { - "sprintf-js": "1.0.3" + "sprintf-js": "~1.0.2" } }, "arr-diff": { @@ -1013,9 +1013,9 @@ "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", "dev": true, "requires": { - "bn.js": "4.11.8", - "inherits": "2.0.3", - "minimalistic-assert": "1.0.1" + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" } }, "assert": { @@ -1074,12 +1074,12 @@ "integrity": "sha1-Hb0cg1ZY41zj+ZhAmdsAWFx4IBQ=", "dev": true, "requires": { - "browserslist": "1.7.7", - "caniuse-db": "1.0.30000939", - "normalize-range": "0.1.2", - "num2fraction": "1.2.2", - "postcss": "5.2.18", - "postcss-value-parser": "3.3.1" + "browserslist": "^1.7.6", + "caniuse-db": "^1.0.30000634", + "normalize-range": "^0.1.2", + "num2fraction": "^1.2.2", + "postcss": "^5.2.16", + "postcss-value-parser": "^3.2.3" }, "dependencies": { "browserslist": { @@ -1088,8 +1088,8 @@ "integrity": "sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk=", "dev": true, "requires": { - "caniuse-db": "1.0.30000939", - "electron-to-chromium": "1.3.113" + "caniuse-db": "^1.0.30000639", + "electron-to-chromium": "^1.2.7" } }, "chalk": { @@ -1098,11 +1098,11 @@ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" + "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" }, "dependencies": { "supports-color": { @@ -1125,10 +1125,10 @@ "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", "dev": true, "requires": { - "chalk": "1.1.3", - "js-base64": "2.5.1", - "source-map": "0.5.7", - "supports-color": "3.2.3" + "chalk": "^1.1.3", + "js-base64": "^2.1.9", + "source-map": "^0.5.6", + "supports-color": "^3.2.3" } }, "source-map": { @@ -1143,51 +1143,19 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "1.0.0" + "has-flag": "^1.0.0" } } } }, - "babel-code-frame": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", - "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", - "dev": true, - "requires": { - "chalk": "1.1.3", - "esutils": "2.0.2", - "js-tokens": "3.0.2" - }, - "dependencies": { - "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.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" - } - }, - "js-tokens": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", - "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", - "dev": true - } - } - }, "babel-runtime": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", "dev": true, "requires": { - "core-js": "2.6.5", - "regenerator-runtime": "0.11.1" + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" }, "dependencies": { "regenerator-runtime": { @@ -1204,10 +1172,10 @@ "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", "dev": true, "requires": { - "babel-runtime": "6.26.0", - "esutils": "2.0.2", - "lodash": "4.17.11", - "to-fast-properties": "1.0.3" + "babel-runtime": "^6.26.0", + "esutils": "^2.0.2", + "lodash": "^4.17.4", + "to-fast-properties": "^1.0.3" }, "dependencies": { "to-fast-properties": { @@ -1224,9 +1192,9 @@ "integrity": "sha1-OxWl3btIKni0zpwByLoYFwLZ1s4=", "dev": true, "requires": { - "babel-runtime": "6.26.0", - "babel-types": "6.26.0", - "lodash.clone": "4.5.0" + "babel-runtime": "^6.11.6", + "babel-types": "^6.15.0", + "lodash.clone": "^4.5.0" } }, "balanced-match": { @@ -1241,13 +1209,13 @@ "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", "dev": true, "requires": { - "cache-base": "1.0.1", - "class-utils": "0.3.6", - "component-emitter": "1.2.1", - "define-property": "1.0.0", - "isobject": "3.0.1", - "mixin-deep": "1.3.1", - "pascalcase": "0.1.1" + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" }, "dependencies": { "define-property": { @@ -1256,7 +1224,7 @@ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", "dev": true, "requires": { - "is-descriptor": "1.0.2" + "is-descriptor": "^1.0.0" } }, "is-accessor-descriptor": { @@ -1265,7 +1233,7 @@ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", "dev": true, "requires": { - "kind-of": "6.0.2" + "kind-of": "^6.0.0" } }, "is-data-descriptor": { @@ -1274,7 +1242,7 @@ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", "dev": true, "requires": { - "kind-of": "6.0.2" + "kind-of": "^6.0.0" } }, "is-descriptor": { @@ -1283,9 +1251,9 @@ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", "dev": true, "requires": { - "is-accessor-descriptor": "1.0.0", - "is-data-descriptor": "1.0.0", - "kind-of": "6.0.2" + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" } } } @@ -1326,7 +1294,7 @@ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "requires": { - "balanced-match": "1.0.0", + "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, @@ -1336,16 +1304,16 @@ "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", "dev": true, "requires": { - "arr-flatten": "1.1.0", - "array-unique": "0.3.2", - "extend-shallow": "2.0.1", - "fill-range": "4.0.0", - "isobject": "3.0.1", - "repeat-element": "1.1.3", - "snapdragon": "0.8.2", - "snapdragon-node": "2.1.1", - "split-string": "3.1.0", - "to-regex": "3.0.2" + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" }, "dependencies": { "extend-shallow": { @@ -1354,7 +1322,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "0.1.1" + "is-extendable": "^0.1.0" } } } @@ -1365,10 +1333,10 @@ "integrity": "sha512-OfZpABRQQf+Xsmju8XE9bDjs+uU4vLREGolP7bDgcpsI17QREyZ4Bl+2KLxxx1kCgA0fAIhKQBaBYh+PEcCqYQ==", "dev": true, "requires": { - "quote-stream": "1.0.2", - "resolve": "1.10.0", - "static-module": "2.2.5", - "through2": "2.0.5" + "quote-stream": "^1.0.1", + "resolve": "^1.1.5", + "static-module": "^2.2.0", + "through2": "^2.0.0" } }, "brorand": { @@ -1383,12 +1351,12 @@ "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", "dev": true, "requires": { - "buffer-xor": "1.0.3", - "cipher-base": "1.0.4", - "create-hash": "1.2.0", - "evp_bytestokey": "1.0.3", - "inherits": "2.0.3", - "safe-buffer": "5.1.2" + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" } }, "browserify-cipher": { @@ -1397,9 +1365,9 @@ "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", "dev": true, "requires": { - "browserify-aes": "1.2.0", - "browserify-des": "1.0.2", - "evp_bytestokey": "1.0.3" + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" } }, "browserify-des": { @@ -1408,10 +1376,10 @@ "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", "dev": true, "requires": { - "cipher-base": "1.0.4", - "des.js": "1.0.0", - "inherits": "2.0.3", - "safe-buffer": "5.1.2" + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" } }, "browserify-rsa": { @@ -1420,8 +1388,8 @@ "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", "dev": true, "requires": { - "bn.js": "4.11.8", - "randombytes": "2.1.0" + "bn.js": "^4.1.0", + "randombytes": "^2.0.1" } }, "browserify-sign": { @@ -1430,13 +1398,13 @@ "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", "dev": true, "requires": { - "bn.js": "4.11.8", - "browserify-rsa": "4.0.1", - "create-hash": "1.2.0", - "create-hmac": "1.1.7", - "elliptic": "6.4.1", - "inherits": "2.0.3", - "parse-asn1": "5.1.4" + "bn.js": "^4.1.1", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.2", + "elliptic": "^6.0.0", + "inherits": "^2.0.1", + "parse-asn1": "^5.0.0" } }, "browserify-zlib": { @@ -1445,7 +1413,7 @@ "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", "dev": true, "requires": { - "pako": "1.0.8" + "pako": "~1.0.5" }, "dependencies": { "pako": { @@ -1462,9 +1430,9 @@ "integrity": "sha512-ISS/AIAiHERJ3d45Fz0AVYKkgcy+F/eJHzKEvv1j0wwKGKD9T3BrwKr/5g45L+Y4XIK5PlTqefHciRFcfE1Jxg==", "dev": true, "requires": { - "caniuse-lite": "1.0.30000939", - "electron-to-chromium": "1.3.113", - "node-releases": "1.1.8" + "caniuse-lite": "^1.0.30000939", + "electron-to-chromium": "^1.3.113", + "node-releases": "^1.1.8" } }, "buffer": { @@ -1473,9 +1441,9 @@ "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", "dev": true, "requires": { - "base64-js": "1.3.0", - "ieee754": "1.1.12", - "isarray": "1.0.0" + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" } }, "buffer-equal": { @@ -1496,12 +1464,6 @@ "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", "dev": true }, - "builtin-modules": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", - "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", - "dev": true - }, "builtin-status-codes": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", @@ -1514,15 +1476,15 @@ "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", "dev": true, "requires": { - "collection-visit": "1.0.0", - "component-emitter": "1.2.1", - "get-value": "2.0.6", - "has-value": "1.0.0", - "isobject": "3.0.1", - "set-value": "2.0.0", - "to-object-path": "0.3.0", - "union-value": "1.0.0", - "unset-value": "1.0.0" + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" } }, "call-me-maybe": { @@ -1537,7 +1499,7 @@ "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=", "dev": true, "requires": { - "callsites": "2.0.0" + "callsites": "^2.0.0" } }, "caller-path": { @@ -1546,7 +1508,7 @@ "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=", "dev": true, "requires": { - "caller-callsite": "2.0.0" + "caller-callsite": "^2.0.0" } }, "callsites": { @@ -1561,10 +1523,10 @@ "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", "dev": true, "requires": { - "browserslist": "4.4.2", - "caniuse-lite": "1.0.30000939", - "lodash.memoize": "4.1.2", - "lodash.uniq": "4.5.0" + "browserslist": "^4.0.0", + "caniuse-lite": "^1.0.0", + "lodash.memoize": "^4.1.2", + "lodash.uniq": "^4.5.0" } }, "caniuse-db": { @@ -1585,9 +1547,9 @@ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { - "ansi-styles": "3.2.1", - "escape-string-regexp": "1.0.5", - "supports-color": "5.5.0" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" }, "dependencies": { "ansi-styles": { @@ -1596,7 +1558,7 @@ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "requires": { - "color-convert": "1.9.3" + "color-convert": "^1.9.0" } }, "supports-color": { @@ -1605,7 +1567,7 @@ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, "requires": { - "has-flag": "3.0.0" + "has-flag": "^3.0.0" } } } @@ -1616,18 +1578,18 @@ "integrity": "sha512-IwXUx0FXc5ibYmPC2XeEj5mpXoV66sR+t3jqu2NS2GYwCktt3KF1/Qqjws/NkegajBA4RbZ5+DDwlOiJsxDHEg==", "dev": true, "requires": { - "anymatch": "2.0.0", - "async-each": "1.0.1", - "braces": "2.3.2", - "fsevents": "1.2.7", - "glob-parent": "3.1.0", - "inherits": "2.0.3", - "is-binary-path": "1.0.1", - "is-glob": "4.0.0", - "normalize-path": "3.0.0", - "path-is-absolute": "1.0.1", - "readdirp": "2.2.1", - "upath": "1.1.0" + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "fsevents": "^1.2.7", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.0" } }, "cipher-base": { @@ -1636,8 +1598,8 @@ "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", "dev": true, "requires": { - "inherits": "2.0.3", - "safe-buffer": "5.1.2" + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" } }, "clap": { @@ -1646,7 +1608,7 @@ "integrity": "sha512-4CoL/A3hf90V3VIEjeuhSvlGFEHKzOz+Wfc2IVZc+FaUgU0ZQafJTP49fvnULipOPcAfqhyI2duwQyns6xqjYA==", "dev": true, "requires": { - "chalk": "1.1.3" + "chalk": "^1.1.3" }, "dependencies": { "chalk": { @@ -1655,11 +1617,11 @@ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" + "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" } } } @@ -1670,10 +1632,10 @@ "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", "dev": true, "requires": { - "arr-union": "3.1.0", - "define-property": "0.2.5", - "isobject": "3.0.1", - "static-extend": "0.1.2" + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" }, "dependencies": { "define-property": { @@ -1682,7 +1644,7 @@ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "is-descriptor": "0.1.6" + "is-descriptor": "^0.1.0" } } } @@ -1693,7 +1655,7 @@ "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", "dev": true, "requires": { - "restore-cursor": "2.0.0" + "restore-cursor": "^2.0.0" } }, "cli-spinners": { @@ -1720,9 +1682,9 @@ "integrity": "sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA==", "dev": true, "requires": { - "@types/q": "1.5.1", - "chalk": "2.4.2", - "q": "1.5.1" + "@types/q": "^1.5.1", + "chalk": "^2.4.1", + "q": "^1.1.2" } }, "collection-visit": { @@ -1731,8 +1693,8 @@ "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", "dev": true, "requires": { - "map-visit": "1.0.0", - "object-visit": "1.0.1" + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" } }, "color": { @@ -1741,8 +1703,8 @@ "integrity": "sha512-CwyopLkuRYO5ei2EpzpIh6LqJMt6Mt+jZhO5VI5f/wJLZriXQE32/SSqzmrh+QB+AZT81Cj8yv+7zwToW8ahZg==", "dev": true, "requires": { - "color-convert": "1.9.3", - "color-string": "1.5.3" + "color-convert": "^1.9.1", + "color-string": "^1.5.2" } }, "color-convert": { @@ -1766,8 +1728,8 @@ "integrity": "sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw==", "dev": true, "requires": { - "color-name": "1.1.3", - "simple-swizzle": "0.2.2" + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" } }, "colormin": { @@ -1776,9 +1738,9 @@ "integrity": "sha1-6i90IKcrlogaOKrlnsEkpvcpgTM=", "dev": true, "requires": { - "color": "0.11.4", + "color": "^0.11.0", "css-color-names": "0.0.4", - "has": "1.0.3" + "has": "^1.0.1" }, "dependencies": { "clone": { @@ -1793,9 +1755,9 @@ "integrity": "sha1-bXtcdPtl6EHNSHkq0e1eB7kE12Q=", "dev": true, "requires": { - "clone": "1.0.4", - "color-convert": "1.9.3", - "color-string": "0.3.0" + "clone": "^1.0.2", + "color-convert": "^1.3.0", + "color-string": "^0.3.0" } }, "color-string": { @@ -1804,7 +1766,7 @@ "integrity": "sha1-J9RvtnAlxcL6JZk7+/V55HhBuZE=", "dev": true, "requires": { - "color-name": "1.1.3" + "color-name": "^1.0.0" } } } @@ -1845,10 +1807,10 @@ "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", "dev": true, "requires": { - "buffer-from": "1.1.1", - "inherits": "2.0.3", - "readable-stream": "2.3.6", - "typedarray": "0.0.6" + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" } }, "config-chain": { @@ -1857,8 +1819,8 @@ "integrity": "sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA==", "dev": true, "requires": { - "ini": "1.3.5", - "proto-list": "1.2.4" + "ini": "^1.3.4", + "proto-list": "~1.2.1" } }, "console-browserify": { @@ -1867,7 +1829,7 @@ "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", "dev": true, "requires": { - "date-now": "0.1.4" + "date-now": "^0.1.4" } }, "constants-browserify": { @@ -1882,7 +1844,7 @@ "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==", "dev": true, "requires": { - "safe-buffer": "5.1.2" + "safe-buffer": "~5.1.1" } }, "copy-descriptor": { @@ -1909,11 +1871,11 @@ "integrity": "sha512-kCNPvthka8gvLtzAxQXvWo4FxqRB+ftRZyPZNuab5ngvM9Y7yw7hbEysglptLgpkGX9nAOKTBVkHUAe8xtYR6Q==", "dev": true, "requires": { - "import-fresh": "2.0.0", - "is-directory": "0.3.1", - "js-yaml": "3.12.1", - "lodash.get": "4.4.2", - "parse-json": "4.0.0" + "import-fresh": "^2.0.0", + "is-directory": "^0.3.1", + "js-yaml": "^3.9.0", + "lodash.get": "^4.4.2", + "parse-json": "^4.0.0" } }, "create-ecdh": { @@ -1922,8 +1884,8 @@ "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==", "dev": true, "requires": { - "bn.js": "4.11.8", - "elliptic": "6.4.1" + "bn.js": "^4.1.0", + "elliptic": "^6.0.0" } }, "create-hash": { @@ -1932,11 +1894,11 @@ "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", "dev": true, "requires": { - "cipher-base": "1.0.4", - "inherits": "2.0.3", - "md5.js": "1.3.5", - "ripemd160": "2.0.2", - "sha.js": "2.4.11" + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" } }, "create-hmac": { @@ -1945,12 +1907,12 @@ "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", "dev": true, "requires": { - "cipher-base": "1.0.4", - "create-hash": "1.2.0", - "inherits": "2.0.3", - "ripemd160": "2.0.2", - "safe-buffer": "5.1.2", - "sha.js": "2.4.11" + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" } }, "cross-spawn": { @@ -1959,11 +1921,11 @@ "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", "dev": true, "requires": { - "nice-try": "1.0.5", - "path-key": "2.0.1", - "semver": "5.6.0", - "shebang-command": "1.2.0", - "which": "1.3.1" + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" } }, "crypto-browserify": { @@ -1972,17 +1934,17 @@ "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", "dev": true, "requires": { - "browserify-cipher": "1.0.1", - "browserify-sign": "4.0.4", - "create-ecdh": "4.0.3", - "create-hash": "1.2.0", - "create-hmac": "1.1.7", - "diffie-hellman": "5.0.3", - "inherits": "2.0.3", - "pbkdf2": "3.0.17", - "public-encrypt": "4.0.3", - "randombytes": "2.1.0", - "randomfill": "1.0.4" + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" } }, "css-color-names": { @@ -1997,8 +1959,8 @@ "integrity": "sha512-BcxQSKTSEEQUftYpBVnsH4SF05NTuBokb19/sBt6asXGKZ/6VP7PLG1CBCkFDYOnhXhPh0jMhO6xZ71oYHXHBA==", "dev": true, "requires": { - "postcss": "7.0.14", - "timsort": "0.3.0" + "postcss": "^7.0.1", + "timsort": "^0.3.0" } }, "css-select": { @@ -2007,10 +1969,10 @@ "integrity": "sha512-dSpYaDVoWaELjvZ3mS6IKZM/y2PMPa/XYoEfYNZePL4U/XgyxZNroHEHReDx/d+VgXh9VbCTtFqLkFbmeqeaRQ==", "dev": true, "requires": { - "boolbase": "1.0.0", - "css-what": "2.1.3", - "domutils": "1.7.0", - "nth-check": "1.0.2" + "boolbase": "^1.0.0", + "css-what": "^2.1.2", + "domutils": "^1.7.0", + "nth-check": "^1.0.2" } }, "css-select-base-adapter": { @@ -2025,8 +1987,8 @@ "integrity": "sha512-joNNW1gCp3qFFzj4St6zk+Wh/NBv0vM5YbEreZk0SD4S23S+1xBKb6cLDg2uj4P4k/GUMlIm6cKIDqIG+vdt0w==", "dev": true, "requires": { - "mdn-data": "1.1.4", - "source-map": "0.5.7" + "mdn-data": "~1.1.0", + "source-map": "^0.5.3" }, "dependencies": { "source-map": { @@ -2067,10 +2029,10 @@ "integrity": "sha512-5wny+F6H4/8RgNlaqab4ktc3e0/blKutmq8yNlBFXA//nSFFAqAngjNVRzUvCgYROULmZZUoosL/KSoZo5aUaQ==", "dev": true, "requires": { - "cosmiconfig": "5.1.0", - "cssnano-preset-default": "4.0.7", - "is-resolvable": "1.1.0", - "postcss": "7.0.14" + "cosmiconfig": "^5.0.0", + "cssnano-preset-default": "^4.0.7", + "is-resolvable": "^1.0.0", + "postcss": "^7.0.0" } }, "cssnano-preset-default": { @@ -2079,36 +2041,36 @@ "integrity": "sha512-x0YHHx2h6p0fCl1zY9L9roD7rnlltugGu7zXSKQx6k2rYw0Hi3IqxcoAGF7u9Q5w1nt7vK0ulxV8Lo+EvllGsA==", "dev": true, "requires": { - "css-declaration-sorter": "4.0.1", - "cssnano-util-raw-cache": "4.0.1", - "postcss": "7.0.14", - "postcss-calc": "7.0.1", - "postcss-colormin": "4.0.3", - "postcss-convert-values": "4.0.1", - "postcss-discard-comments": "4.0.2", - "postcss-discard-duplicates": "4.0.2", - "postcss-discard-empty": "4.0.1", - "postcss-discard-overridden": "4.0.1", - "postcss-merge-longhand": "4.0.11", - "postcss-merge-rules": "4.0.3", - "postcss-minify-font-values": "4.0.2", - "postcss-minify-gradients": "4.0.2", - "postcss-minify-params": "4.0.2", - "postcss-minify-selectors": "4.0.2", - "postcss-normalize-charset": "4.0.1", - "postcss-normalize-display-values": "4.0.2", - "postcss-normalize-positions": "4.0.2", - "postcss-normalize-repeat-style": "4.0.2", - "postcss-normalize-string": "4.0.2", - "postcss-normalize-timing-functions": "4.0.2", - "postcss-normalize-unicode": "4.0.1", - "postcss-normalize-url": "4.0.1", - "postcss-normalize-whitespace": "4.0.2", - "postcss-ordered-values": "4.1.2", - "postcss-reduce-initial": "4.0.3", - "postcss-reduce-transforms": "4.0.2", - "postcss-svgo": "4.0.2", - "postcss-unique-selectors": "4.0.1" + "css-declaration-sorter": "^4.0.1", + "cssnano-util-raw-cache": "^4.0.1", + "postcss": "^7.0.0", + "postcss-calc": "^7.0.1", + "postcss-colormin": "^4.0.3", + "postcss-convert-values": "^4.0.1", + "postcss-discard-comments": "^4.0.2", + "postcss-discard-duplicates": "^4.0.2", + "postcss-discard-empty": "^4.0.1", + "postcss-discard-overridden": "^4.0.1", + "postcss-merge-longhand": "^4.0.11", + "postcss-merge-rules": "^4.0.3", + "postcss-minify-font-values": "^4.0.2", + "postcss-minify-gradients": "^4.0.2", + "postcss-minify-params": "^4.0.2", + "postcss-minify-selectors": "^4.0.2", + "postcss-normalize-charset": "^4.0.1", + "postcss-normalize-display-values": "^4.0.2", + "postcss-normalize-positions": "^4.0.2", + "postcss-normalize-repeat-style": "^4.0.2", + "postcss-normalize-string": "^4.0.2", + "postcss-normalize-timing-functions": "^4.0.2", + "postcss-normalize-unicode": "^4.0.1", + "postcss-normalize-url": "^4.0.1", + "postcss-normalize-whitespace": "^4.0.2", + "postcss-ordered-values": "^4.1.2", + "postcss-reduce-initial": "^4.0.3", + "postcss-reduce-transforms": "^4.0.2", + "postcss-svgo": "^4.0.2", + "postcss-unique-selectors": "^4.0.1" } }, "cssnano-util-get-arguments": { @@ -2129,7 +2091,7 @@ "integrity": "sha512-qLuYtWK2b2Dy55I8ZX3ky1Z16WYsx544Q0UWViebptpwn/xDBmog2TLg4f+DBMg1rJ6JDWtn96WHbOKDWt1WQA==", "dev": true, "requires": { - "postcss": "7.0.14" + "postcss": "^7.0.0" } }, "cssnano-util-same-parent": { @@ -2153,8 +2115,8 @@ "integrity": "sha512-sRNb1XydwkW9IOci6iB2xmy8IGCj6r/fr+JWitvJ2JxQRPzN3T4AGGVWCMlVmVwM1gtgALJRmGIlWv5ppnGGkg==", "dev": true, "requires": { - "mdn-data": "1.1.4", - "source-map": "0.5.7" + "mdn-data": "~1.1.0", + "source-map": "^0.5.3" } }, "source-map": { @@ -2177,8 +2139,8 @@ "integrity": "sha512-wN8sIuEqIwyQh72AG7oY6YQODCxIp1eXzEZlZznBuwDF8Q03Tdy9QNp1BNZXeadXoklNrw+Ip1fch+KXo/+ASw==", "dev": true, "requires": { - "bindings": "1.2.1", - "node-addon-api": "1.6.2" + "bindings": "~1.2.1", + "node-addon-api": "^1.6.0" } }, "debug": { @@ -2187,7 +2149,7 @@ "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "dev": true, "requires": { - "ms": "2.1.1" + "ms": "^2.1.1" } }, "decamelize": { @@ -2214,7 +2176,7 @@ "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", "dev": true, "requires": { - "clone": "1.0.4" + "clone": "^1.0.2" }, "dependencies": { "clone": { @@ -2231,7 +2193,7 @@ "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", "dev": true, "requires": { - "object-keys": "1.1.0" + "object-keys": "^1.0.12" } }, "define-property": { @@ -2240,8 +2202,8 @@ "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", "dev": true, "requires": { - "is-descriptor": "1.0.2", - "isobject": "3.0.1" + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" }, "dependencies": { "is-accessor-descriptor": { @@ -2250,7 +2212,7 @@ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", "dev": true, "requires": { - "kind-of": "6.0.2" + "kind-of": "^6.0.0" } }, "is-data-descriptor": { @@ -2259,7 +2221,7 @@ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", "dev": true, "requires": { - "kind-of": "6.0.2" + "kind-of": "^6.0.0" } }, "is-descriptor": { @@ -2268,9 +2230,9 @@ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", "dev": true, "requires": { - "is-accessor-descriptor": "1.0.0", - "is-data-descriptor": "1.0.0", - "kind-of": "6.0.2" + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" } } } @@ -2293,8 +2255,8 @@ "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", "dev": true, "requires": { - "inherits": "2.0.3", - "minimalistic-assert": "1.0.1" + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" } }, "destroy": { @@ -2303,21 +2265,15 @@ "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", "dev": true }, - "diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", - "dev": true - }, "diffie-hellman": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", "dev": true, "requires": { - "bn.js": "4.11.8", - "miller-rabin": "4.0.1", - "randombytes": "2.1.0" + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" } }, "dom-serializer": { @@ -2326,8 +2282,8 @@ "integrity": "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==", "dev": true, "requires": { - "domelementtype": "1.3.1", - "entities": "1.1.2" + "domelementtype": "^1.3.0", + "entities": "^1.1.1" } }, "domain-browser": { @@ -2348,7 +2304,7 @@ "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", "dev": true, "requires": { - "domelementtype": "1.3.1" + "domelementtype": "1" } }, "domutils": { @@ -2357,8 +2313,8 @@ "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", "dev": true, "requires": { - "dom-serializer": "0.1.1", - "domelementtype": "1.3.1" + "dom-serializer": "0", + "domelementtype": "1" } }, "dot-prop": { @@ -2367,7 +2323,7 @@ "integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==", "dev": true, "requires": { - "is-obj": "1.0.1" + "is-obj": "^1.0.0" } }, "dotenv": { @@ -2388,7 +2344,7 @@ "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", "dev": true, "requires": { - "readable-stream": "2.3.6" + "readable-stream": "^2.0.2" } }, "editorconfig": { @@ -2397,12 +2353,12 @@ "integrity": "sha512-GWjSI19PVJAM9IZRGOS+YKI8LN+/sjkSjNyvxL5ucqP9/IqtYNXBaQ/6c/hkPNYQHyOHra2KoXZI/JVpuqwmcQ==", "dev": true, "requires": { - "@types/node": "10.12.27", - "@types/semver": "5.5.0", - "commander": "2.19.0", - "lru-cache": "4.1.5", - "semver": "5.6.0", - "sigmund": "1.0.1" + "@types/node": "^10.11.7", + "@types/semver": "^5.5.0", + "commander": "^2.19.0", + "lru-cache": "^4.1.3", + "semver": "^5.6.0", + "sigmund": "^1.0.1" } }, "ee-first": { @@ -2423,13 +2379,13 @@ "integrity": "sha512-BsXLz5sqX8OHcsh7CqBMztyXARmGQ3LWPtGjJi6DiJHq5C/qvi9P3OqgswKSDftbu8+IoI/QDTAm2fFnQ9SZSQ==", "dev": true, "requires": { - "bn.js": "4.11.8", - "brorand": "1.1.0", - "hash.js": "1.1.7", - "hmac-drbg": "1.0.1", - "inherits": "2.0.3", - "minimalistic-assert": "1.0.1", - "minimalistic-crypto-utils": "1.0.1" + "bn.js": "^4.4.0", + "brorand": "^1.0.1", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.0" } }, "encodeurl": { @@ -2450,7 +2406,7 @@ "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", "dev": true, "requires": { - "is-arrayish": "0.2.1" + "is-arrayish": "^0.2.1" } }, "es-abstract": { @@ -2459,12 +2415,12 @@ "integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==", "dev": true, "requires": { - "es-to-primitive": "1.2.0", - "function-bind": "1.1.1", - "has": "1.0.3", - "is-callable": "1.1.4", - "is-regex": "1.0.4", - "object-keys": "1.1.0" + "es-to-primitive": "^1.2.0", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "is-callable": "^1.1.4", + "is-regex": "^1.0.4", + "object-keys": "^1.0.12" } }, "es-to-primitive": { @@ -2473,9 +2429,9 @@ "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", "dev": true, "requires": { - "is-callable": "1.1.4", - "is-date-object": "1.0.1", - "is-symbol": "1.0.2" + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" } }, "escape-html": { @@ -2496,11 +2452,11 @@ "integrity": "sha512-6hTjO1NAWkHnDk3OqQ4YrCuwwmGHL9S3nPlzBOUG/R44rda3wLNrfvQ5fkSGjyhHFKM7ALPKcKGrwvCLe0lC7Q==", "dev": true, "requires": { - "esprima": "3.1.3", - "estraverse": "4.2.0", - "esutils": "2.0.2", - "optionator": "0.8.2", - "source-map": "0.6.1" + "esprima": "^3.1.3", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" }, "dependencies": { "esprima": { @@ -2547,8 +2503,8 @@ "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", "dev": true, "requires": { - "md5.js": "1.3.5", - "safe-buffer": "5.1.2" + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" } }, "expand-brackets": { @@ -2557,13 +2513,13 @@ "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", "dev": true, "requires": { - "debug": "2.6.9", - "define-property": "0.2.5", - "extend-shallow": "2.0.1", - "posix-character-classes": "0.1.1", - "regex-not": "1.0.2", - "snapdragon": "0.8.2", - "to-regex": "3.0.2" + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" }, "dependencies": { "debug": { @@ -2581,7 +2537,7 @@ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "is-descriptor": "0.1.6" + "is-descriptor": "^0.1.0" } }, "extend-shallow": { @@ -2590,7 +2546,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "0.1.1" + "is-extendable": "^0.1.0" } }, "ms": { @@ -2607,8 +2563,8 @@ "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", "dev": true, "requires": { - "assign-symbols": "1.0.0", - "is-extendable": "1.0.1" + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" }, "dependencies": { "is-extendable": { @@ -2617,7 +2573,7 @@ "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", "dev": true, "requires": { - "is-plain-object": "2.0.4" + "is-plain-object": "^2.0.4" } } } @@ -2628,14 +2584,14 @@ "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", "dev": true, "requires": { - "array-unique": "0.3.2", - "define-property": "1.0.0", - "expand-brackets": "2.1.4", - "extend-shallow": "2.0.1", - "fragment-cache": "0.2.1", - "regex-not": "1.0.2", - "snapdragon": "0.8.2", - "to-regex": "3.0.2" + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" }, "dependencies": { "define-property": { @@ -2644,7 +2600,7 @@ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", "dev": true, "requires": { - "is-descriptor": "1.0.2" + "is-descriptor": "^1.0.0" } }, "extend-shallow": { @@ -2653,7 +2609,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "0.1.1" + "is-extendable": "^0.1.0" } }, "is-accessor-descriptor": { @@ -2662,7 +2618,7 @@ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", "dev": true, "requires": { - "kind-of": "6.0.2" + "kind-of": "^6.0.0" } }, "is-data-descriptor": { @@ -2671,7 +2627,7 @@ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", "dev": true, "requires": { - "kind-of": "6.0.2" + "kind-of": "^6.0.0" } }, "is-descriptor": { @@ -2680,9 +2636,9 @@ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", "dev": true, "requires": { - "is-accessor-descriptor": "1.0.0", - "is-data-descriptor": "1.0.0", - "kind-of": "6.0.2" + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" } } } @@ -2693,10 +2649,10 @@ "integrity": "sha1-lrsXdh2rqU9G0AFzizzt86Z/4Gw=", "dev": true, "requires": { - "acorn": "5.7.3", - "foreach": "2.0.5", + "acorn": "^5.0.0", + "foreach": "^2.0.5", "isarray": "0.0.1", - "object-keys": "1.1.0" + "object-keys": "^1.0.6" }, "dependencies": { "isarray": { @@ -2713,12 +2669,12 @@ "integrity": "sha512-0BvMaZc1k9F+MeWWMe8pL6YltFzZYcJsYU7D4JyDA6PAczaXvxqQQ/z+mDF7/4Mw01DeUc+i3CTKajnkANkV4w==", "dev": true, "requires": { - "@mrmlnc/readdir-enhanced": "2.2.1", - "@nodelib/fs.stat": "1.1.3", - "glob-parent": "3.1.0", - "is-glob": "4.0.0", - "merge2": "1.2.3", - "micromatch": "3.1.10" + "@mrmlnc/readdir-enhanced": "^2.2.1", + "@nodelib/fs.stat": "^1.1.2", + "glob-parent": "^3.1.0", + "is-glob": "^4.0.0", + "merge2": "^1.2.3", + "micromatch": "^3.1.10" } }, "fast-levenshtein": { @@ -2739,10 +2695,10 @@ "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", "dev": true, "requires": { - "extend-shallow": "2.0.1", - "is-number": "3.0.0", - "repeat-string": "1.6.1", - "to-regex-range": "2.1.1" + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" }, "dependencies": { "extend-shallow": { @@ -2751,7 +2707,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "0.1.1" + "is-extendable": "^0.1.0" } } } @@ -2780,7 +2736,7 @@ "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", "dev": true, "requires": { - "map-cache": "0.2.2" + "map-cache": "^0.2.2" } }, "fresh": { @@ -2802,8 +2758,8 @@ "dev": true, "optional": true, "requires": { - "nan": "2.12.1", - "node-pre-gyp": "0.10.3" + "nan": "^2.9.2", + "node-pre-gyp": "^0.10.0" }, "dependencies": { "abbrev": { @@ -2815,7 +2771,8 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "aproba": { "version": "1.2.0", @@ -2829,21 +2786,23 @@ "dev": true, "optional": true, "requires": { - "delegates": "1.0.0", - "readable-stream": "2.3.6" + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" } }, "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, + "optional": true, "requires": { - "balanced-match": "1.0.0", + "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, @@ -2856,17 +2815,20 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -2907,7 +2869,7 @@ "dev": true, "optional": true, "requires": { - "minipass": "2.3.5" + "minipass": "^2.2.1" } }, "fs.realpath": { @@ -2922,14 +2884,14 @@ "dev": true, "optional": true, "requires": { - "aproba": "1.2.0", - "console-control-strings": "1.1.0", - "has-unicode": "2.0.1", - "object-assign": "4.1.1", - "signal-exit": "3.0.2", - "string-width": "1.0.2", - "strip-ansi": "3.0.1", - "wide-align": "1.1.3" + "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" } }, "glob": { @@ -2938,12 +2900,12 @@ "dev": true, "optional": true, "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" } }, "has-unicode": { @@ -2958,7 +2920,7 @@ "dev": true, "optional": true, "requires": { - "safer-buffer": "2.1.2" + "safer-buffer": ">= 2.1.2 < 3" } }, "ignore-walk": { @@ -2967,7 +2929,7 @@ "dev": true, "optional": true, "requires": { - "minimatch": "3.0.4" + "minimatch": "^3.0.4" } }, "inflight": { @@ -2976,14 +2938,15 @@ "dev": true, "optional": true, "requires": { - "once": "1.4.0", - "wrappy": "1.0.2" + "once": "^1.3.0", + "wrappy": "1" } }, "inherits": { "version": "2.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "ini": { "version": "1.3.5", @@ -2995,8 +2958,9 @@ "version": "1.0.0", "bundled": true, "dev": true, + "optional": true, "requires": { - "number-is-nan": "1.0.1" + "number-is-nan": "^1.0.0" } }, "isarray": { @@ -3009,22 +2973,25 @@ "version": "3.0.4", "bundled": true, "dev": true, + "optional": true, "requires": { - "brace-expansion": "1.1.11" + "brace-expansion": "^1.1.7" } }, "minimist": { "version": "0.0.8", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "minipass": { "version": "2.3.5", "bundled": true, "dev": true, + "optional": true, "requires": { - "safe-buffer": "5.1.2", - "yallist": "3.0.3" + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" } }, "minizlib": { @@ -3033,13 +3000,14 @@ "dev": true, "optional": true, "requires": { - "minipass": "2.3.5" + "minipass": "^2.2.1" } }, "mkdirp": { "version": "0.5.1", "bundled": true, "dev": true, + "optional": true, "requires": { "minimist": "0.0.8" } @@ -3056,9 +3024,9 @@ "dev": true, "optional": true, "requires": { - "debug": "2.6.9", - "iconv-lite": "0.4.24", - "sax": "1.2.4" + "debug": "^2.1.2", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" } }, "node-pre-gyp": { @@ -3067,16 +3035,16 @@ "dev": true, "optional": true, "requires": { - "detect-libc": "1.0.3", - "mkdirp": "0.5.1", - "needle": "2.2.4", - "nopt": "4.0.1", - "npm-packlist": "1.2.0", - "npmlog": "4.1.2", - "rc": "1.2.8", - "rimraf": "2.6.3", - "semver": "5.6.0", - "tar": "4.4.8" + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.1", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.2.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4" } }, "nopt": { @@ -3085,8 +3053,8 @@ "dev": true, "optional": true, "requires": { - "abbrev": "1.1.1", - "osenv": "0.1.5" + "abbrev": "1", + "osenv": "^0.1.4" } }, "npm-bundled": { @@ -3101,8 +3069,8 @@ "dev": true, "optional": true, "requires": { - "ignore-walk": "3.0.1", - "npm-bundled": "1.0.5" + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" } }, "npmlog": { @@ -3111,16 +3079,17 @@ "dev": true, "optional": true, "requires": { - "are-we-there-yet": "1.1.5", - "console-control-strings": "1.1.0", - "gauge": "2.7.4", - "set-blocking": "2.0.0" + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" } }, "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "object-assign": { "version": "4.1.1", @@ -3132,8 +3101,9 @@ "version": "1.4.0", "bundled": true, "dev": true, + "optional": true, "requires": { - "wrappy": "1.0.2" + "wrappy": "1" } }, "os-homedir": { @@ -3154,8 +3124,8 @@ "dev": true, "optional": true, "requires": { - "os-homedir": "1.0.2", - "os-tmpdir": "1.0.2" + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" } }, "path-is-absolute": { @@ -3176,10 +3146,10 @@ "dev": true, "optional": true, "requires": { - "deep-extend": "0.6.0", - "ini": "1.3.5", - "minimist": "1.2.0", - "strip-json-comments": "2.0.1" + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" }, "dependencies": { "minimist": { @@ -3196,13 +3166,13 @@ "dev": true, "optional": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "2.0.0", - "safe-buffer": "5.1.2", - "string_decoder": "1.1.1", - "util-deprecate": "1.0.2" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } }, "rimraf": { @@ -3211,13 +3181,14 @@ "dev": true, "optional": true, "requires": { - "glob": "7.1.3" + "glob": "^7.1.3" } }, "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "safer-buffer": { "version": "2.1.2", @@ -3253,10 +3224,11 @@ "version": "1.0.2", "bundled": true, "dev": true, + "optional": true, "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" } }, "string_decoder": { @@ -3265,15 +3237,16 @@ "dev": true, "optional": true, "requires": { - "safe-buffer": "5.1.2" + "safe-buffer": "~5.1.0" } }, "strip-ansi": { "version": "3.0.1", "bundled": true, "dev": true, + "optional": true, "requires": { - "ansi-regex": "2.1.1" + "ansi-regex": "^2.0.0" } }, "strip-json-comments": { @@ -3288,13 +3261,13 @@ "dev": true, "optional": true, "requires": { - "chownr": "1.1.1", - "fs-minipass": "1.2.5", - "minipass": "2.3.5", - "minizlib": "1.2.1", - "mkdirp": "0.5.1", - "safe-buffer": "5.1.2", - "yallist": "3.0.3" + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.3.4", + "minizlib": "^1.1.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.2" } }, "util-deprecate": { @@ -3309,18 +3282,20 @@ "dev": true, "optional": true, "requires": { - "string-width": "1.0.2" + "string-width": "^1.0.2 || 2" } }, "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "yallist": { "version": "3.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true } } }, @@ -3348,12 +3323,12 @@ "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", "dev": true, "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" } }, "glob-parent": { @@ -3362,8 +3337,8 @@ "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", "dev": true, "requires": { - "is-glob": "3.1.0", - "path-dirname": "1.0.2" + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" }, "dependencies": { "is-glob": { @@ -3372,7 +3347,7 @@ "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", "dev": true, "requires": { - "is-extglob": "2.1.1" + "is-extglob": "^2.1.0" } } } @@ -3401,8 +3376,8 @@ "integrity": "sha1-W55reMODJFLSuiuxy4MPlidkEKw=", "dev": true, "requires": { - "brfs": "1.6.1", - "unicode-trie": "0.3.1" + "brfs": "^1.2.0", + "unicode-trie": "^0.3.1" } }, "has": { @@ -3411,7 +3386,7 @@ "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", "dev": true, "requires": { - "function-bind": "1.1.1" + "function-bind": "^1.1.1" } }, "has-ansi": { @@ -3420,7 +3395,7 @@ "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", "dev": true, "requires": { - "ansi-regex": "2.1.1" + "ansi-regex": "^2.0.0" } }, "has-flag": { @@ -3441,9 +3416,9 @@ "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", "dev": true, "requires": { - "get-value": "2.0.6", - "has-values": "1.0.0", - "isobject": "3.0.1" + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" } }, "has-values": { @@ -3452,8 +3427,8 @@ "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", "dev": true, "requires": { - "is-number": "3.0.0", - "kind-of": "4.0.0" + "is-number": "^3.0.0", + "kind-of": "^4.0.0" }, "dependencies": { "kind-of": { @@ -3462,7 +3437,7 @@ "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "^1.1.5" } } } @@ -3473,8 +3448,8 @@ "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", "dev": true, "requires": { - "inherits": "2.0.3", - "safe-buffer": "5.1.2" + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" } }, "hash.js": { @@ -3483,8 +3458,8 @@ "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", "dev": true, "requires": { - "inherits": "2.0.3", - "minimalistic-assert": "1.0.1" + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" } }, "hex-color-regex": { @@ -3499,9 +3474,9 @@ "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", "dev": true, "requires": { - "hash.js": "1.1.7", - "minimalistic-assert": "1.0.1", - "minimalistic-crypto-utils": "1.0.1" + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" } }, "hsl-regex": { @@ -3528,12 +3503,12 @@ "integrity": "sha512-eTEUzz8VdWYp+w/KUdb99kwao4reR64epUySyZkQeepcyzPQ2n2EPWzibf6QDxmkGy10Kr+CKxYqI3izSbmhJQ==", "dev": true, "requires": { - "cssnano": "3.10.0", - "object-assign": "4.1.1", - "posthtml": "0.11.3", - "posthtml-render": "1.1.4", - "svgo": "1.2.0", - "terser": "3.16.1" + "cssnano": "^3.4.0", + "object-assign": "^4.0.1", + "posthtml": "^0.11.3", + "posthtml-render": "^1.1.4", + "svgo": "^1.0.5", + "terser": "^3.8.1" }, "dependencies": { "browserslist": { @@ -3542,8 +3517,8 @@ "integrity": "sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk=", "dev": true, "requires": { - "caniuse-db": "1.0.30000939", - "electron-to-chromium": "1.3.113" + "caniuse-db": "^1.0.30000639", + "electron-to-chromium": "^1.2.7" } }, "caniuse-api": { @@ -3552,10 +3527,10 @@ "integrity": "sha1-tTTnxzTE+B7F++isoq0kNUuWLGw=", "dev": true, "requires": { - "browserslist": "1.7.7", - "caniuse-db": "1.0.30000939", - "lodash.memoize": "4.1.2", - "lodash.uniq": "4.5.0" + "browserslist": "^1.3.6", + "caniuse-db": "^1.0.30000529", + "lodash.memoize": "^4.1.2", + "lodash.uniq": "^4.5.0" } }, "chalk": { @@ -3564,11 +3539,11 @@ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" + "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" }, "dependencies": { "supports-color": { @@ -3585,7 +3560,7 @@ "integrity": "sha1-qe8VNmDWqGqL3sAomlxoTSF0Mv0=", "dev": true, "requires": { - "q": "1.5.1" + "q": "^1.1.2" } }, "cssnano": { @@ -3594,38 +3569,38 @@ "integrity": "sha1-Tzj2zqK5sX+gFJDyPx3GjqZcHDg=", "dev": true, "requires": { - "autoprefixer": "6.7.7", - "decamelize": "1.2.0", - "defined": "1.0.0", - "has": "1.0.3", - "object-assign": "4.1.1", - "postcss": "5.2.18", - "postcss-calc": "5.3.1", - "postcss-colormin": "2.2.2", - "postcss-convert-values": "2.6.1", - "postcss-discard-comments": "2.0.4", - "postcss-discard-duplicates": "2.1.0", - "postcss-discard-empty": "2.1.0", - "postcss-discard-overridden": "0.1.1", - "postcss-discard-unused": "2.2.3", - "postcss-filter-plugins": "2.0.3", - "postcss-merge-idents": "2.1.7", - "postcss-merge-longhand": "2.0.2", - "postcss-merge-rules": "2.1.2", - "postcss-minify-font-values": "1.0.5", - "postcss-minify-gradients": "1.0.5", - "postcss-minify-params": "1.2.2", - "postcss-minify-selectors": "2.1.1", - "postcss-normalize-charset": "1.1.1", - "postcss-normalize-url": "3.0.8", - "postcss-ordered-values": "2.2.3", - "postcss-reduce-idents": "2.4.0", - "postcss-reduce-initial": "1.0.1", - "postcss-reduce-transforms": "1.0.4", - "postcss-svgo": "2.1.6", - "postcss-unique-selectors": "2.0.2", - "postcss-value-parser": "3.3.1", - "postcss-zindex": "2.2.0" + "autoprefixer": "^6.3.1", + "decamelize": "^1.1.2", + "defined": "^1.0.0", + "has": "^1.0.1", + "object-assign": "^4.0.1", + "postcss": "^5.0.14", + "postcss-calc": "^5.2.0", + "postcss-colormin": "^2.1.8", + "postcss-convert-values": "^2.3.4", + "postcss-discard-comments": "^2.0.4", + "postcss-discard-duplicates": "^2.0.1", + "postcss-discard-empty": "^2.0.1", + "postcss-discard-overridden": "^0.1.1", + "postcss-discard-unused": "^2.2.1", + "postcss-filter-plugins": "^2.0.0", + "postcss-merge-idents": "^2.1.5", + "postcss-merge-longhand": "^2.0.1", + "postcss-merge-rules": "^2.0.3", + "postcss-minify-font-values": "^1.0.2", + "postcss-minify-gradients": "^1.0.1", + "postcss-minify-params": "^1.0.4", + "postcss-minify-selectors": "^2.0.4", + "postcss-normalize-charset": "^1.1.0", + "postcss-normalize-url": "^3.0.7", + "postcss-ordered-values": "^2.1.0", + "postcss-reduce-idents": "^2.2.2", + "postcss-reduce-initial": "^1.0.0", + "postcss-reduce-transforms": "^1.0.3", + "postcss-svgo": "^2.1.1", + "postcss-unique-selectors": "^2.0.2", + "postcss-value-parser": "^3.2.3", + "postcss-zindex": "^2.0.1" } }, "csso": { @@ -3634,8 +3609,8 @@ "integrity": "sha1-3dUsWHAz9J6Utx/FVWnyUuj/X4U=", "dev": true, "requires": { - "clap": "1.2.3", - "source-map": "0.5.7" + "clap": "^1.0.9", + "source-map": "^0.5.3" } }, "esprima": { @@ -3656,7 +3631,7 @@ "integrity": "sha1-z2EJDaDZ77yrhyLeum8DIgjbsOk=", "dev": true, "requires": { - "html-comment-regex": "1.1.2" + "html-comment-regex": "^1.1.0" } }, "js-yaml": { @@ -3665,8 +3640,8 @@ "integrity": "sha1-XJZ93YN6m/3KXy3oQlOr6KHAO4A=", "dev": true, "requires": { - "argparse": "1.0.10", - "esprima": "2.7.3" + "argparse": "^1.0.7", + "esprima": "^2.6.0" } }, "normalize-url": { @@ -3675,10 +3650,10 @@ "integrity": "sha1-LMDWazHqIwNkWENuNiDYWVTGbDw=", "dev": true, "requires": { - "object-assign": "4.1.1", - "prepend-http": "1.0.4", - "query-string": "4.3.4", - "sort-keys": "1.1.2" + "object-assign": "^4.0.1", + "prepend-http": "^1.0.0", + "query-string": "^4.1.0", + "sort-keys": "^1.0.0" } }, "postcss": { @@ -3687,10 +3662,10 @@ "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", "dev": true, "requires": { - "chalk": "1.1.3", - "js-base64": "2.5.1", - "source-map": "0.5.7", - "supports-color": "3.2.3" + "chalk": "^1.1.3", + "js-base64": "^2.1.9", + "source-map": "^0.5.6", + "supports-color": "^3.2.3" } }, "postcss-calc": { @@ -3699,9 +3674,9 @@ "integrity": "sha1-d7rnypKK2FcW4v2kLyYb98HWW14=", "dev": true, "requires": { - "postcss": "5.2.18", - "postcss-message-helpers": "2.0.0", - "reduce-css-calc": "1.3.0" + "postcss": "^5.0.2", + "postcss-message-helpers": "^2.0.0", + "reduce-css-calc": "^1.2.6" } }, "postcss-colormin": { @@ -3710,9 +3685,9 @@ "integrity": "sha1-ZjFBfV8OkJo9fsJrJMio0eT5bks=", "dev": true, "requires": { - "colormin": "1.1.2", - "postcss": "5.2.18", - "postcss-value-parser": "3.3.1" + "colormin": "^1.0.5", + "postcss": "^5.0.13", + "postcss-value-parser": "^3.2.3" } }, "postcss-convert-values": { @@ -3721,8 +3696,8 @@ "integrity": "sha1-u9hZPFwf0uPRwyK7kl3K6Nrk1i0=", "dev": true, "requires": { - "postcss": "5.2.18", - "postcss-value-parser": "3.3.1" + "postcss": "^5.0.11", + "postcss-value-parser": "^3.1.2" } }, "postcss-discard-comments": { @@ -3731,7 +3706,7 @@ "integrity": "sha1-vv6J+v1bPazlzM5Rt2uBUUvgDj0=", "dev": true, "requires": { - "postcss": "5.2.18" + "postcss": "^5.0.14" } }, "postcss-discard-duplicates": { @@ -3740,7 +3715,7 @@ "integrity": "sha1-uavye4isGIFYpesSq8riAmO5GTI=", "dev": true, "requires": { - "postcss": "5.2.18" + "postcss": "^5.0.4" } }, "postcss-discard-empty": { @@ -3749,7 +3724,7 @@ "integrity": "sha1-0rS9nVztXr2Nyt52QMfXzX9PkrU=", "dev": true, "requires": { - "postcss": "5.2.18" + "postcss": "^5.0.14" } }, "postcss-discard-overridden": { @@ -3758,7 +3733,7 @@ "integrity": "sha1-ix6vVU9ob7KIzYdMVWZ7CqNmjVg=", "dev": true, "requires": { - "postcss": "5.2.18" + "postcss": "^5.0.16" } }, "postcss-merge-longhand": { @@ -3767,7 +3742,7 @@ "integrity": "sha1-I9kM0Sewp3mUkVMyc5A0oaTz1lg=", "dev": true, "requires": { - "postcss": "5.2.18" + "postcss": "^5.0.4" } }, "postcss-merge-rules": { @@ -3776,11 +3751,11 @@ "integrity": "sha1-0d9d+qexrMO+VT8OnhDofGG19yE=", "dev": true, "requires": { - "browserslist": "1.7.7", - "caniuse-api": "1.6.1", - "postcss": "5.2.18", - "postcss-selector-parser": "2.2.3", - "vendors": "1.0.2" + "browserslist": "^1.5.2", + "caniuse-api": "^1.5.2", + "postcss": "^5.0.4", + "postcss-selector-parser": "^2.2.2", + "vendors": "^1.0.0" } }, "postcss-minify-font-values": { @@ -3789,9 +3764,9 @@ "integrity": "sha1-S1jttWZB66fIR0qzUmyv17vey2k=", "dev": true, "requires": { - "object-assign": "4.1.1", - "postcss": "5.2.18", - "postcss-value-parser": "3.3.1" + "object-assign": "^4.0.1", + "postcss": "^5.0.4", + "postcss-value-parser": "^3.0.2" } }, "postcss-minify-gradients": { @@ -3800,8 +3775,8 @@ "integrity": "sha1-Xb2hE3NwP4PPtKPqOIHY11/15uE=", "dev": true, "requires": { - "postcss": "5.2.18", - "postcss-value-parser": "3.3.1" + "postcss": "^5.0.12", + "postcss-value-parser": "^3.3.0" } }, "postcss-minify-params": { @@ -3810,10 +3785,10 @@ "integrity": "sha1-rSzgcTc7lDs9kwo/pZo1jCjW8fM=", "dev": true, "requires": { - "alphanum-sort": "1.0.2", - "postcss": "5.2.18", - "postcss-value-parser": "3.3.1", - "uniqs": "2.0.0" + "alphanum-sort": "^1.0.1", + "postcss": "^5.0.2", + "postcss-value-parser": "^3.0.2", + "uniqs": "^2.0.0" } }, "postcss-minify-selectors": { @@ -3822,10 +3797,10 @@ "integrity": "sha1-ssapjAByz5G5MtGkllCBFDEXNb8=", "dev": true, "requires": { - "alphanum-sort": "1.0.2", - "has": "1.0.3", - "postcss": "5.2.18", - "postcss-selector-parser": "2.2.3" + "alphanum-sort": "^1.0.2", + "has": "^1.0.1", + "postcss": "^5.0.14", + "postcss-selector-parser": "^2.0.0" } }, "postcss-normalize-charset": { @@ -3834,7 +3809,7 @@ "integrity": "sha1-757nEhLX/nWceO0WL2HtYrXLk/E=", "dev": true, "requires": { - "postcss": "5.2.18" + "postcss": "^5.0.5" } }, "postcss-normalize-url": { @@ -3843,10 +3818,10 @@ "integrity": "sha1-EI90s/L82viRov+j6kWSJ5/HgiI=", "dev": true, "requires": { - "is-absolute-url": "2.1.0", - "normalize-url": "1.9.1", - "postcss": "5.2.18", - "postcss-value-parser": "3.3.1" + "is-absolute-url": "^2.0.0", + "normalize-url": "^1.4.0", + "postcss": "^5.0.14", + "postcss-value-parser": "^3.2.3" } }, "postcss-ordered-values": { @@ -3855,8 +3830,8 @@ "integrity": "sha1-7sbCpntsQSqNsgQud/6NpD+VwR0=", "dev": true, "requires": { - "postcss": "5.2.18", - "postcss-value-parser": "3.3.1" + "postcss": "^5.0.4", + "postcss-value-parser": "^3.0.1" } }, "postcss-reduce-initial": { @@ -3865,7 +3840,7 @@ "integrity": "sha1-aPgGlfBF0IJjqHmtJA343WT2ROo=", "dev": true, "requires": { - "postcss": "5.2.18" + "postcss": "^5.0.4" } }, "postcss-reduce-transforms": { @@ -3874,9 +3849,9 @@ "integrity": "sha1-/3b02CEkN7McKYpC0uFEQCV3GuE=", "dev": true, "requires": { - "has": "1.0.3", - "postcss": "5.2.18", - "postcss-value-parser": "3.3.1" + "has": "^1.0.1", + "postcss": "^5.0.8", + "postcss-value-parser": "^3.0.1" } }, "postcss-selector-parser": { @@ -3885,9 +3860,9 @@ "integrity": "sha1-+UN3iGBsPJrO4W/+jYsWKX8nu5A=", "dev": true, "requires": { - "flatten": "1.0.2", - "indexes-of": "1.0.1", - "uniq": "1.0.1" + "flatten": "^1.0.2", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" } }, "postcss-svgo": { @@ -3896,10 +3871,10 @@ "integrity": "sha1-tt8YqmE7Zm4TPwittSGcJoSsEI0=", "dev": true, "requires": { - "is-svg": "2.1.0", - "postcss": "5.2.18", - "postcss-value-parser": "3.3.1", - "svgo": "0.7.2" + "is-svg": "^2.0.0", + "postcss": "^5.0.14", + "postcss-value-parser": "^3.2.3", + "svgo": "^0.7.0" }, "dependencies": { "svgo": { @@ -3908,13 +3883,13 @@ "integrity": "sha1-n1dyQTlSE1xv779Ar+ak+qiLS7U=", "dev": true, "requires": { - "coa": "1.0.4", - "colors": "1.1.2", - "csso": "2.3.2", - "js-yaml": "3.7.0", - "mkdirp": "0.5.1", - "sax": "1.2.4", - "whet.extend": "0.9.9" + "coa": "~1.0.1", + "colors": "~1.1.2", + "csso": "~2.3.1", + "js-yaml": "~3.7.0", + "mkdirp": "~0.5.1", + "sax": "~1.2.1", + "whet.extend": "~0.9.9" } } } @@ -3925,9 +3900,9 @@ "integrity": "sha1-mB1X0p3csz57Hf4f1DuGSfkzyh0=", "dev": true, "requires": { - "alphanum-sort": "1.0.2", - "postcss": "5.2.18", - "uniqs": "2.0.0" + "alphanum-sort": "^1.0.1", + "postcss": "^5.0.4", + "uniqs": "^2.0.0" } }, "source-map": { @@ -3942,7 +3917,7 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "1.0.0" + "has-flag": "^1.0.0" } } } @@ -3953,12 +3928,12 @@ "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==", "dev": true, "requires": { - "domelementtype": "1.3.1", - "domhandler": "2.4.2", - "domutils": "1.7.0", - "entities": "1.1.2", - "inherits": "2.0.3", - "readable-stream": "3.1.1" + "domelementtype": "^1.3.1", + "domhandler": "^2.3.0", + "domutils": "^1.5.1", + "entities": "^1.1.1", + "inherits": "^2.0.1", + "readable-stream": "^3.1.1" }, "dependencies": { "readable-stream": { @@ -3967,9 +3942,9 @@ "integrity": "sha512-DkN66hPyqDhnIQ6Jcsvx9bFjhw214O4poMBcIMgPVpQvNy9a0e0Uhg5SqySyDKAmUlwt8LonTBz1ezOnM8pUdA==", "dev": true, "requires": { - "inherits": "2.0.3", - "string_decoder": "1.1.1", - "util-deprecate": "1.0.2" + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" } } } @@ -3980,10 +3955,10 @@ "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", "dev": true, "requires": { - "depd": "1.1.2", + "depd": "~1.1.2", "inherits": "2.0.3", "setprototypeof": "1.1.0", - "statuses": "1.4.0" + "statuses": ">= 1.4.0 < 2" } }, "https-browserify": { @@ -4004,8 +3979,8 @@ "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=", "dev": true, "requires": { - "caller-path": "2.0.0", - "resolve-from": "3.0.0" + "caller-path": "^2.0.0", + "resolve-from": "^3.0.0" } }, "indexes-of": { @@ -4026,8 +4001,8 @@ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "dev": true, "requires": { - "once": "1.4.0", - "wrappy": "1.0.2" + "once": "^1.3.0", + "wrappy": "1" } }, "inherits": { @@ -4048,7 +4023,7 @@ "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", "dev": true, "requires": { - "loose-envify": "1.4.0" + "loose-envify": "^1.0.0" } }, "is-absolute-url": { @@ -4063,7 +4038,7 @@ "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", "dev": true, "requires": { - "kind-of": "3.2.2" + "kind-of": "^3.0.2" }, "dependencies": { "kind-of": { @@ -4072,7 +4047,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "^1.1.5" } } } @@ -4089,7 +4064,7 @@ "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", "dev": true, "requires": { - "binary-extensions": "1.13.0" + "binary-extensions": "^1.0.0" } }, "is-buffer": { @@ -4110,12 +4085,12 @@ "integrity": "sha1-z/9HGu5N1cnhWFmPvhKWe1za00U=", "dev": true, "requires": { - "css-color-names": "0.0.4", - "hex-color-regex": "1.1.0", - "hsl-regex": "1.0.0", - "hsla-regex": "1.0.0", - "rgb-regex": "1.0.1", - "rgba-regex": "1.0.0" + "css-color-names": "^0.0.4", + "hex-color-regex": "^1.1.0", + "hsl-regex": "^1.0.0", + "hsla-regex": "^1.0.0", + "rgb-regex": "^1.0.1", + "rgba-regex": "^1.0.0" } }, "is-data-descriptor": { @@ -4124,7 +4099,7 @@ "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", "dev": true, "requires": { - "kind-of": "3.2.2" + "kind-of": "^3.0.2" }, "dependencies": { "kind-of": { @@ -4133,7 +4108,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "^1.1.5" } } } @@ -4150,9 +4125,9 @@ "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", "dev": true, "requires": { - "is-accessor-descriptor": "0.1.6", - "is-data-descriptor": "0.1.4", - "kind-of": "5.1.0" + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" }, "dependencies": { "kind-of": { @@ -4187,7 +4162,7 @@ "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", "dev": true, "requires": { - "is-extglob": "2.1.1" + "is-extglob": "^2.1.1" } }, "is-number": { @@ -4196,7 +4171,7 @@ "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", "dev": true, "requires": { - "kind-of": "3.2.2" + "kind-of": "^3.0.2" }, "dependencies": { "kind-of": { @@ -4205,7 +4180,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "^1.1.5" } } } @@ -4228,7 +4203,7 @@ "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", "dev": true, "requires": { - "isobject": "3.0.1" + "isobject": "^3.0.1" } }, "is-regex": { @@ -4237,7 +4212,7 @@ "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", "dev": true, "requires": { - "has": "1.0.3" + "has": "^1.0.1" } }, "is-resolvable": { @@ -4252,7 +4227,7 @@ "integrity": "sha512-gi4iHK53LR2ujhLVVj+37Ykh9GLqYHX6JOVXbLAucaG/Cqw9xwdFOjDM2qeifLs1sF1npXXFvDu0r5HNgCMrzQ==", "dev": true, "requires": { - "html-comment-regex": "1.1.2" + "html-comment-regex": "^1.1.0" } }, "is-symbol": { @@ -4261,7 +4236,7 @@ "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", "dev": true, "requires": { - "has-symbols": "1.0.0" + "has-symbols": "^1.0.0" } }, "is-url": { @@ -4312,11 +4287,11 @@ "integrity": "sha512-MwPmLywK9RSX0SPsUJjN7i+RQY9w/yC17Lbrq9ViEefpLRgqAR2BgrMN2AbifkUuhDV8tRauLhLda/9+bE0YQA==", "dev": true, "requires": { - "config-chain": "1.1.12", - "editorconfig": "0.15.2", - "glob": "7.1.3", - "mkdirp": "0.5.1", - "nopt": "4.0.1" + "config-chain": "^1.1.12", + "editorconfig": "^0.15.2", + "glob": "^7.1.3", + "mkdirp": "~0.5.0", + "nopt": "~4.0.1" } }, "js-levenshtein": { @@ -4337,8 +4312,8 @@ "integrity": "sha512-um46hB9wNOKlwkHgiuyEVAybXBjwFUV0Z/RaHJblRd9DXltue9FTYvzCr9ErQrK9Adz5MU4gHWVaNUfdmrC8qA==", "dev": true, "requires": { - "argparse": "1.0.10", - "esprima": "4.0.1" + "argparse": "^1.0.7", + "esprima": "^4.0.0" } }, "jsesc": { @@ -4359,7 +4334,7 @@ "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", "dev": true, "requires": { - "minimist": "1.2.0" + "minimist": "^1.2.0" } }, "kind-of": { @@ -4374,8 +4349,8 @@ "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", "dev": true, "requires": { - "prelude-ls": "1.1.2", - "type-check": "0.3.2" + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" } }, "lodash": { @@ -4414,7 +4389,7 @@ "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", "dev": true, "requires": { - "chalk": "2.4.2" + "chalk": "^2.0.1" } }, "loose-envify": { @@ -4423,7 +4398,7 @@ "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", "dev": true, "requires": { - "js-tokens": "4.0.0" + "js-tokens": "^3.0.0 || ^4.0.0" } }, "lru-cache": { @@ -4432,8 +4407,8 @@ "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", "dev": true, "requires": { - "pseudomap": "1.0.2", - "yallist": "2.1.2" + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" } }, "magic-string": { @@ -4442,7 +4417,7 @@ "integrity": "sha512-oreip9rJZkzvA8Qzk9HFs8fZGF/u7H/gtrE8EN6RjKJ9kh2HlC+yQ2QezifqTZfGyiuAV0dRv5a+y/8gBb1m9w==", "dev": true, "requires": { - "vlq": "0.2.3" + "vlq": "^0.2.2" } }, "map-cache": { @@ -4457,7 +4432,7 @@ "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", "dev": true, "requires": { - "object-visit": "1.0.1" + "object-visit": "^1.0.0" } }, "math-expression-evaluator": { @@ -4472,9 +4447,9 @@ "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", "dev": true, "requires": { - "hash-base": "3.0.4", - "inherits": "2.0.3", - "safe-buffer": "5.1.2" + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" } }, "mdn-data": { @@ -4489,7 +4464,7 @@ "integrity": "sha1-pd5GU42uhNQRTMXqArR3KmNGcB8=", "dev": true, "requires": { - "source-map": "0.5.7" + "source-map": "^0.5.6" }, "dependencies": { "source-map": { @@ -4512,19 +4487,19 @@ "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", "dev": true, "requires": { - "arr-diff": "4.0.0", - "array-unique": "0.3.2", - "braces": "2.3.2", - "define-property": "2.0.2", - "extend-shallow": "3.0.2", - "extglob": "2.0.4", - "fragment-cache": "0.2.1", - "kind-of": "6.0.2", - "nanomatch": "1.2.13", - "object.pick": "1.3.0", - "regex-not": "1.0.2", - "snapdragon": "0.8.2", - "to-regex": "3.0.2" + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" } }, "miller-rabin": { @@ -4533,8 +4508,8 @@ "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", "dev": true, "requires": { - "bn.js": "4.11.8", - "brorand": "1.1.0" + "bn.js": "^4.0.0", + "brorand": "^1.0.1" } }, "mime": { @@ -4567,7 +4542,7 @@ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "requires": { - "brace-expansion": "1.1.11" + "brace-expansion": "^1.1.7" } }, "minimist": { @@ -4582,8 +4557,8 @@ "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", "dev": true, "requires": { - "for-in": "1.0.2", - "is-extendable": "1.0.1" + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" }, "dependencies": { "is-extendable": { @@ -4592,7 +4567,7 @@ "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", "dev": true, "requires": { - "is-plain-object": "2.0.4" + "is-plain-object": "^2.0.4" } } } @@ -4633,17 +4608,17 @@ "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", "dev": true, "requires": { - "arr-diff": "4.0.0", - "array-unique": "0.3.2", - "define-property": "2.0.2", - "extend-shallow": "3.0.2", - "fragment-cache": "0.2.1", - "is-windows": "1.0.2", - "kind-of": "6.0.2", - "object.pick": "1.3.0", - "regex-not": "1.0.2", - "snapdragon": "0.8.2", - "to-regex": "3.0.2" + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" } }, "nice-try": { @@ -4670,28 +4645,28 @@ "integrity": "sha512-5MQunG/oyOaBdttrL40dA7bUfPORLRWMUJLQtMg7nluxUvk5XwnLdL9twQHFAjRx/y7mIMkLKT9++qPbbk6BZA==", "dev": true, "requires": { - "assert": "1.4.1", - "browserify-zlib": "0.2.0", - "buffer": "4.9.1", - "console-browserify": "1.1.0", - "constants-browserify": "1.0.0", - "crypto-browserify": "3.12.0", - "domain-browser": "1.2.0", - "events": "3.0.0", - "https-browserify": "1.0.0", - "os-browserify": "0.3.0", + "assert": "^1.1.1", + "browserify-zlib": "^0.2.0", + "buffer": "^4.3.0", + "console-browserify": "^1.1.0", + "constants-browserify": "^1.0.0", + "crypto-browserify": "^3.11.0", + "domain-browser": "^1.1.1", + "events": "^3.0.0", + "https-browserify": "^1.0.0", + "os-browserify": "^0.3.0", "path-browserify": "0.0.0", - "process": "0.11.10", - "punycode": "1.4.1", - "querystring-es3": "0.2.1", - "readable-stream": "2.3.6", - "stream-browserify": "2.0.2", - "stream-http": "2.8.3", - "string_decoder": "1.1.1", - "timers-browserify": "2.0.10", + "process": "^0.11.10", + "punycode": "^1.2.4", + "querystring-es3": "^0.2.0", + "readable-stream": "^2.3.3", + "stream-browserify": "^2.0.1", + "stream-http": "^2.7.2", + "string_decoder": "^1.0.0", + "timers-browserify": "^2.0.4", "tty-browserify": "0.0.0", - "url": "0.11.0", - "util": "0.11.1", + "url": "^0.11.0", + "util": "^0.11.0", "vm-browserify": "0.0.4" } }, @@ -4701,7 +4676,7 @@ "integrity": "sha512-gQm+K9mGCiT/NXHy+V/ZZS1N/LOaGGqRAAJJs3X9Ah1g+CIbRcBgNyoNYQ+SEtcyAtB9KqDruu+fF7nWjsqRaA==", "dev": true, "requires": { - "semver": "5.6.0" + "semver": "^5.3.0" } }, "nopt": { @@ -4710,8 +4685,8 @@ "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", "dev": true, "requires": { - "abbrev": "1.1.1", - "osenv": "0.1.5" + "abbrev": "1", + "osenv": "^0.1.4" } }, "normalize-path": { @@ -4738,7 +4713,7 @@ "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", "dev": true, "requires": { - "boolbase": "1.0.0" + "boolbase": "~1.0.0" } }, "num2fraction": { @@ -4759,9 +4734,9 @@ "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", "dev": true, "requires": { - "copy-descriptor": "0.1.1", - "define-property": "0.2.5", - "kind-of": "3.2.2" + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" }, "dependencies": { "define-property": { @@ -4770,7 +4745,7 @@ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "is-descriptor": "0.1.6" + "is-descriptor": "^0.1.0" } }, "kind-of": { @@ -4779,7 +4754,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "^1.1.5" } } } @@ -4802,7 +4777,7 @@ "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", "dev": true, "requires": { - "isobject": "3.0.1" + "isobject": "^3.0.0" } }, "object.getownpropertydescriptors": { @@ -4811,8 +4786,8 @@ "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=", "dev": true, "requires": { - "define-properties": "1.1.3", - "es-abstract": "1.13.0" + "define-properties": "^1.1.2", + "es-abstract": "^1.5.1" } }, "object.pick": { @@ -4821,7 +4796,7 @@ "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", "dev": true, "requires": { - "isobject": "3.0.1" + "isobject": "^3.0.1" } }, "object.values": { @@ -4830,10 +4805,10 @@ "integrity": "sha512-8mf0nKLAoFX6VlNVdhGj31SVYpaNFtUnuoOXWyFEstsWRgU837AK+JYM0iAxwkSzGRbwn8cbFmgbyxj1j4VbXg==", "dev": true, "requires": { - "define-properties": "1.1.3", - "es-abstract": "1.13.0", - "function-bind": "1.1.1", - "has": "1.0.3" + "define-properties": "^1.1.3", + "es-abstract": "^1.12.0", + "function-bind": "^1.1.1", + "has": "^1.0.3" } }, "on-finished": { @@ -4851,7 +4826,7 @@ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, "requires": { - "wrappy": "1.0.2" + "wrappy": "1" } }, "onetime": { @@ -4860,7 +4835,7 @@ "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", "dev": true, "requires": { - "mimic-fn": "1.2.0" + "mimic-fn": "^1.0.0" } }, "opn": { @@ -4869,7 +4844,7 @@ "integrity": "sha512-YF9MNdVy/0qvJvDtunAOzFw9iasOQHpVthTCvGzxt61Il64AYSGdK+rYwld7NAfk9qJ7dt+hymBNSc9LNYS+Sw==", "dev": true, "requires": { - "is-wsl": "1.1.0" + "is-wsl": "^1.1.0" } }, "optionator": { @@ -4878,12 +4853,12 @@ "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", "dev": true, "requires": { - "deep-is": "0.1.3", - "fast-levenshtein": "2.0.6", - "levn": "0.3.0", - "prelude-ls": "1.1.2", - "type-check": "0.3.2", - "wordwrap": "1.0.0" + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.4", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "wordwrap": "~1.0.0" } }, "ora": { @@ -4892,12 +4867,12 @@ "integrity": "sha512-hNNlAd3gfv/iPmsNxYoAPLvxg7HuPozww7fFonMZvL84tP6Ox5igfk5j/+a9rtJJwqMgKK+JgWsAQik5o0HTLA==", "dev": true, "requires": { - "chalk": "2.4.2", - "cli-cursor": "2.1.0", - "cli-spinners": "1.3.1", - "log-symbols": "2.2.0", - "strip-ansi": "4.0.0", - "wcwidth": "1.0.1" + "chalk": "^2.3.1", + "cli-cursor": "^2.1.0", + "cli-spinners": "^1.1.0", + "log-symbols": "^2.2.0", + "strip-ansi": "^4.0.0", + "wcwidth": "^1.0.1" }, "dependencies": { "ansi-regex": { @@ -4912,7 +4887,7 @@ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, "requires": { - "ansi-regex": "3.0.0" + "ansi-regex": "^3.0.0" } } } @@ -4941,8 +4916,8 @@ "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", "dev": true, "requires": { - "os-homedir": "1.0.2", - "os-tmpdir": "1.0.2" + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" } }, "pako": { @@ -4957,62 +4932,62 @@ "integrity": "sha512-H0w/Obx76vWiG+UtofznfcHZJBmd6JA5iCn7zrGBINyVAh+Nt/JLD6QDROghHLXfJkO4XyczsB+fO+nPbXlFfA==", "dev": true, "requires": { - "@babel/code-frame": "7.0.0", - "@babel/core": "7.3.3", - "@babel/generator": "7.3.3", - "@babel/parser": "7.3.3", - "@babel/plugin-transform-flow-strip-types": "7.2.3", - "@babel/plugin-transform-modules-commonjs": "7.2.0", - "@babel/plugin-transform-react-jsx": "7.3.0", - "@babel/preset-env": "7.3.1", - "@babel/runtime": "7.3.1", - "@babel/template": "7.2.2", - "@babel/traverse": "7.2.3", - "@babel/types": "7.3.3", - "@iarna/toml": "2.2.3", - "@parcel/fs": "1.11.0", - "@parcel/logger": "1.11.0", - "@parcel/utils": "1.11.0", - "@parcel/watcher": "1.11.0", - "@parcel/workers": "1.11.0", - "ansi-to-html": "0.6.10", - "babylon-walk": "1.0.2", - "browserslist": "4.4.2", - "chalk": "2.4.2", - "clone": "2.1.2", - "command-exists": "1.2.8", - "commander": "2.19.0", - "cross-spawn": "6.0.5", - "cssnano": "4.1.10", - "deasync": "0.1.14", - "dotenv": "5.0.1", - "dotenv-expand": "4.2.0", - "fast-glob": "2.2.6", - "filesize": "3.6.1", - "get-port": "3.2.0", - "htmlnano": "0.1.10", - "is-glob": "4.0.0", - "is-url": "1.2.4", - "js-yaml": "3.12.1", - "json5": "1.0.1", - "micromatch": "3.1.10", - "mkdirp": "0.5.1", - "node-forge": "0.7.6", - "node-libs-browser": "2.2.0", - "opn": "5.4.0", - "postcss": "7.0.14", - "postcss-value-parser": "3.3.1", - "posthtml": "0.11.3", - "posthtml-parser": "0.4.1", - "posthtml-render": "1.1.4", - "resolve": "1.10.0", - "semver": "5.6.0", - "serialize-to-js": "1.2.2", - "serve-static": "1.13.2", + "@babel/code-frame": "^7.0.0", + "@babel/core": "^7.0.0", + "@babel/generator": "^7.0.0", + "@babel/parser": "^7.0.0", + "@babel/plugin-transform-flow-strip-types": "^7.0.0", + "@babel/plugin-transform-modules-commonjs": "^7.0.0", + "@babel/plugin-transform-react-jsx": "^7.0.0", + "@babel/preset-env": "^7.0.0", + "@babel/runtime": "^7.0.0", + "@babel/template": "^7.0.0", + "@babel/traverse": "^7.0.0", + "@babel/types": "^7.0.0", + "@iarna/toml": "^2.2.0", + "@parcel/fs": "^1.11.0", + "@parcel/logger": "^1.11.0", + "@parcel/utils": "^1.11.0", + "@parcel/watcher": "^1.11.0", + "@parcel/workers": "^1.11.0", + "ansi-to-html": "^0.6.4", + "babylon-walk": "^1.0.2", + "browserslist": "^4.1.0", + "chalk": "^2.1.0", + "clone": "^2.1.1", + "command-exists": "^1.2.6", + "commander": "^2.11.0", + "cross-spawn": "^6.0.4", + "cssnano": "^4.0.0", + "deasync": "^0.1.14", + "dotenv": "^5.0.0", + "dotenv-expand": "^4.2.0", + "fast-glob": "^2.2.2", + "filesize": "^3.6.0", + "get-port": "^3.2.0", + "htmlnano": "^0.1.9", + "is-glob": "^4.0.0", + "is-url": "^1.2.2", + "js-yaml": "^3.10.0", + "json5": "^1.0.1", + "micromatch": "^3.0.4", + "mkdirp": "^0.5.1", + "node-forge": "^0.7.1", + "node-libs-browser": "^2.0.0", + "opn": "^5.1.0", + "postcss": "^7.0.5", + "postcss-value-parser": "^3.3.1", + "posthtml": "^0.11.2", + "posthtml-parser": "^0.4.0", + "posthtml-render": "^1.1.3", + "resolve": "^1.4.0", + "semver": "^5.4.1", + "serialize-to-js": "^1.1.1", + "serve-static": "^1.12.4", "source-map": "0.6.1", - "terser": "3.16.1", - "v8-compile-cache": "2.0.2", - "ws": "5.2.2" + "terser": "^3.7.3", + "v8-compile-cache": "^2.0.0", + "ws": "^5.1.1" } }, "parse-asn1": { @@ -5021,12 +4996,12 @@ "integrity": "sha512-Qs5duJcuvNExRfFZ99HDD3z4mAi3r9Wl/FOjEOijlxwCZs7E7mW2vjTpgQ4J8LpTF8x5v+1Vn5UQFejmWT11aw==", "dev": true, "requires": { - "asn1.js": "4.10.1", - "browserify-aes": "1.2.0", - "create-hash": "1.2.0", - "evp_bytestokey": "1.0.3", - "pbkdf2": "3.0.17", - "safe-buffer": "5.1.2" + "asn1.js": "^4.0.0", + "browserify-aes": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3", + "safe-buffer": "^5.1.1" } }, "parse-json": { @@ -5035,8 +5010,8 @@ "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", "dev": true, "requires": { - "error-ex": "1.3.2", - "json-parse-better-errors": "1.0.2" + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" } }, "parseurl": { @@ -5087,11 +5062,11 @@ "integrity": "sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA==", "dev": true, "requires": { - "create-hash": "1.2.0", - "create-hmac": "1.1.7", - "ripemd160": "2.0.2", - "safe-buffer": "5.1.2", - "sha.js": "2.4.11" + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" } }, "physical-cpu-count": { @@ -5112,9 +5087,9 @@ "integrity": "sha512-NsbD6XUUMZvBxtQAJuWDJeeC4QFsmWsfozWxCJPWf3M55K9iu2iMDaKqyoOdTJ1R4usBXuxlVFAIo8rZPQD4Bg==", "dev": true, "requires": { - "chalk": "2.4.2", - "source-map": "0.6.1", - "supports-color": "6.1.0" + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" }, "dependencies": { "supports-color": { @@ -5123,7 +5098,7 @@ "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", "dev": true, "requires": { - "has-flag": "3.0.0" + "has-flag": "^3.0.0" } } } @@ -5134,10 +5109,10 @@ "integrity": "sha512-oXqx0m6tb4N3JGdmeMSc/i91KppbYsFZKdH0xMOqK8V1rJlzrKlTdokz8ozUXLVejydRN6u2IddxpcijRj2FqQ==", "dev": true, "requires": { - "css-unit-converter": "1.1.1", - "postcss": "7.0.14", - "postcss-selector-parser": "5.0.0", - "postcss-value-parser": "3.3.1" + "css-unit-converter": "^1.1.1", + "postcss": "^7.0.5", + "postcss-selector-parser": "^5.0.0-rc.4", + "postcss-value-parser": "^3.3.1" } }, "postcss-colormin": { @@ -5146,11 +5121,11 @@ "integrity": "sha512-WyQFAdDZpExQh32j0U0feWisZ0dmOtPl44qYmJKkq9xFWY3p+4qnRzCHeNrkeRhwPHz9bQ3mo0/yVkaply0MNw==", "dev": true, "requires": { - "browserslist": "4.4.2", - "color": "3.1.0", - "has": "1.0.3", - "postcss": "7.0.14", - "postcss-value-parser": "3.3.1" + "browserslist": "^4.0.0", + "color": "^3.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" } }, "postcss-convert-values": { @@ -5159,8 +5134,8 @@ "integrity": "sha512-Kisdo1y77KUC0Jmn0OXU/COOJbzM8cImvw1ZFsBgBgMgb1iL23Zs/LXRe3r+EZqM3vGYKdQ2YJVQ5VkJI+zEJQ==", "dev": true, "requires": { - "postcss": "7.0.14", - "postcss-value-parser": "3.3.1" + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" } }, "postcss-discard-comments": { @@ -5169,7 +5144,7 @@ "integrity": "sha512-RJutN259iuRf3IW7GZyLM5Sw4GLTOH8FmsXBnv8Ab/Tc2k4SR4qbV4DNbyyY4+Sjo362SyDmW2DQ7lBSChrpkg==", "dev": true, "requires": { - "postcss": "7.0.14" + "postcss": "^7.0.0" } }, "postcss-discard-duplicates": { @@ -5178,7 +5153,7 @@ "integrity": "sha512-ZNQfR1gPNAiXZhgENFfEglF93pciw0WxMkJeVmw8eF+JZBbMD7jp6C67GqJAXVZP2BWbOztKfbsdmMp/k8c6oQ==", "dev": true, "requires": { - "postcss": "7.0.14" + "postcss": "^7.0.0" } }, "postcss-discard-empty": { @@ -5187,7 +5162,7 @@ "integrity": "sha512-B9miTzbznhDjTfjvipfHoqbWKwd0Mj+/fL5s1QOz06wufguil+Xheo4XpOnc4NqKYBCNqqEzgPv2aPBIJLox0w==", "dev": true, "requires": { - "postcss": "7.0.14" + "postcss": "^7.0.0" } }, "postcss-discard-overridden": { @@ -5196,7 +5171,7 @@ "integrity": "sha512-IYY2bEDD7g1XM1IDEsUT4//iEYCxAmP5oDSFMVU/JVvT7gh+l4fmjciLqGgwjdWpQIdb0Che2VX00QObS5+cTg==", "dev": true, "requires": { - "postcss": "7.0.14" + "postcss": "^7.0.0" } }, "postcss-discard-unused": { @@ -5205,8 +5180,8 @@ "integrity": "sha1-vOMLLMWR/8Y0Mitfs0ZLbZNPRDM=", "dev": true, "requires": { - "postcss": "5.2.18", - "uniqs": "2.0.0" + "postcss": "^5.0.14", + "uniqs": "^2.0.0" }, "dependencies": { "chalk": { @@ -5215,11 +5190,11 @@ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" + "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" }, "dependencies": { "supports-color": { @@ -5242,10 +5217,10 @@ "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", "dev": true, "requires": { - "chalk": "1.1.3", - "js-base64": "2.5.1", - "source-map": "0.5.7", - "supports-color": "3.2.3" + "chalk": "^1.1.3", + "js-base64": "^2.1.9", + "source-map": "^0.5.6", + "supports-color": "^3.2.3" } }, "source-map": { @@ -5260,7 +5235,7 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "1.0.0" + "has-flag": "^1.0.0" } } } @@ -5271,7 +5246,7 @@ "integrity": "sha512-T53GVFsdinJhgwm7rg1BzbeBRomOg9y5MBVhGcsV0CxurUdVj1UlPdKtn7aqYA/c/QVkzKMjq2bSV5dKG5+AwQ==", "dev": true, "requires": { - "postcss": "5.2.18" + "postcss": "^5.0.4" }, "dependencies": { "chalk": { @@ -5280,11 +5255,11 @@ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" + "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" }, "dependencies": { "supports-color": { @@ -5307,10 +5282,10 @@ "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", "dev": true, "requires": { - "chalk": "1.1.3", - "js-base64": "2.5.1", - "source-map": "0.5.7", - "supports-color": "3.2.3" + "chalk": "^1.1.3", + "js-base64": "^2.1.9", + "source-map": "^0.5.6", + "supports-color": "^3.2.3" } }, "source-map": { @@ -5325,7 +5300,7 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "1.0.0" + "has-flag": "^1.0.0" } } } @@ -5336,9 +5311,9 @@ "integrity": "sha1-TFUwMTwI4dWzu/PSu8dH4njuonA=", "dev": true, "requires": { - "has": "1.0.3", - "postcss": "5.2.18", - "postcss-value-parser": "3.3.1" + "has": "^1.0.1", + "postcss": "^5.0.10", + "postcss-value-parser": "^3.1.1" }, "dependencies": { "chalk": { @@ -5347,11 +5322,11 @@ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" + "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" }, "dependencies": { "supports-color": { @@ -5374,10 +5349,10 @@ "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", "dev": true, "requires": { - "chalk": "1.1.3", - "js-base64": "2.5.1", - "source-map": "0.5.7", - "supports-color": "3.2.3" + "chalk": "^1.1.3", + "js-base64": "^2.1.9", + "source-map": "^0.5.6", + "supports-color": "^3.2.3" } }, "source-map": { @@ -5392,7 +5367,7 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "1.0.0" + "has-flag": "^1.0.0" } } } @@ -5404,9 +5379,9 @@ "dev": true, "requires": { "css-color-names": "0.0.4", - "postcss": "7.0.14", - "postcss-value-parser": "3.3.1", - "stylehacks": "4.0.3" + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0", + "stylehacks": "^4.0.0" } }, "postcss-merge-rules": { @@ -5415,12 +5390,12 @@ "integrity": "sha512-U7e3r1SbvYzO0Jr3UT/zKBVgYYyhAz0aitvGIYOYK5CPmkNih+WDSsS5tvPrJ8YMQYlEMvsZIiqmn7HdFUaeEQ==", "dev": true, "requires": { - "browserslist": "4.4.2", - "caniuse-api": "3.0.0", - "cssnano-util-same-parent": "4.0.1", - "postcss": "7.0.14", - "postcss-selector-parser": "3.1.1", - "vendors": "1.0.2" + "browserslist": "^4.0.0", + "caniuse-api": "^3.0.0", + "cssnano-util-same-parent": "^4.0.0", + "postcss": "^7.0.0", + "postcss-selector-parser": "^3.0.0", + "vendors": "^1.0.0" }, "dependencies": { "postcss-selector-parser": { @@ -5429,9 +5404,9 @@ "integrity": "sha1-T4dfSvsMllc9XPTXQBGu4lCn6GU=", "dev": true, "requires": { - "dot-prop": "4.2.0", - "indexes-of": "1.0.1", - "uniq": "1.0.1" + "dot-prop": "^4.1.1", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" } } } @@ -5448,8 +5423,8 @@ "integrity": "sha512-j85oO6OnRU9zPf04+PZv1LYIYOprWm6IA6zkXkrJXyRveDEuQggG6tvoy8ir8ZwjLxLuGfNkCZEQG7zan+Hbtg==", "dev": true, "requires": { - "postcss": "7.0.14", - "postcss-value-parser": "3.3.1" + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" } }, "postcss-minify-gradients": { @@ -5458,10 +5433,10 @@ "integrity": "sha512-qKPfwlONdcf/AndP1U8SJ/uzIJtowHlMaSioKzebAXSG4iJthlWC9iSWznQcX4f66gIWX44RSA841HTHj3wK+Q==", "dev": true, "requires": { - "cssnano-util-get-arguments": "4.0.0", - "is-color-stop": "1.1.0", - "postcss": "7.0.14", - "postcss-value-parser": "3.3.1" + "cssnano-util-get-arguments": "^4.0.0", + "is-color-stop": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" } }, "postcss-minify-params": { @@ -5470,12 +5445,12 @@ "integrity": "sha512-G7eWyzEx0xL4/wiBBJxJOz48zAKV2WG3iZOqVhPet/9geefm/Px5uo1fzlHu+DOjT+m0Mmiz3jkQzVHe6wxAWg==", "dev": true, "requires": { - "alphanum-sort": "1.0.2", - "browserslist": "4.4.2", - "cssnano-util-get-arguments": "4.0.0", - "postcss": "7.0.14", - "postcss-value-parser": "3.3.1", - "uniqs": "2.0.0" + "alphanum-sort": "^1.0.0", + "browserslist": "^4.0.0", + "cssnano-util-get-arguments": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0", + "uniqs": "^2.0.0" } }, "postcss-minify-selectors": { @@ -5484,10 +5459,10 @@ "integrity": "sha512-D5S1iViljXBj9kflQo4YutWnJmwm8VvIsU1GeXJGiG9j8CIg9zs4voPMdQDUmIxetUOh60VilsNzCiAFTOqu3g==", "dev": true, "requires": { - "alphanum-sort": "1.0.2", - "has": "1.0.3", - "postcss": "7.0.14", - "postcss-selector-parser": "3.1.1" + "alphanum-sort": "^1.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-selector-parser": "^3.0.0" }, "dependencies": { "postcss-selector-parser": { @@ -5496,9 +5471,9 @@ "integrity": "sha1-T4dfSvsMllc9XPTXQBGu4lCn6GU=", "dev": true, "requires": { - "dot-prop": "4.2.0", - "indexes-of": "1.0.1", - "uniq": "1.0.1" + "dot-prop": "^4.1.1", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" } } } @@ -5509,7 +5484,7 @@ "integrity": "sha512-gMXCrrlWh6G27U0hF3vNvR3w8I1s2wOBILvA87iNXaPvSNo5uZAMYsZG7XjCUf1eVxuPfyL4TJ7++SGZLc9A3g==", "dev": true, "requires": { - "postcss": "7.0.14" + "postcss": "^7.0.0" } }, "postcss-normalize-display-values": { @@ -5518,9 +5493,9 @@ "integrity": "sha512-3F2jcsaMW7+VtRMAqf/3m4cPFhPD3EFRgNs18u+k3lTJJlVe7d0YPO+bnwqo2xg8YiRpDXJI2u8A0wqJxMsQuQ==", "dev": true, "requires": { - "cssnano-util-get-match": "4.0.0", - "postcss": "7.0.14", - "postcss-value-parser": "3.3.1" + "cssnano-util-get-match": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" } }, "postcss-normalize-positions": { @@ -5529,10 +5504,10 @@ "integrity": "sha512-Dlf3/9AxpxE+NF1fJxYDeggi5WwV35MXGFnnoccP/9qDtFrTArZ0D0R+iKcg5WsUd8nUYMIl8yXDCtcrT8JrdA==", "dev": true, "requires": { - "cssnano-util-get-arguments": "4.0.0", - "has": "1.0.3", - "postcss": "7.0.14", - "postcss-value-parser": "3.3.1" + "cssnano-util-get-arguments": "^4.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" } }, "postcss-normalize-repeat-style": { @@ -5541,10 +5516,10 @@ "integrity": "sha512-qvigdYYMpSuoFs3Is/f5nHdRLJN/ITA7huIoCyqqENJe9PvPmLhNLMu7QTjPdtnVf6OcYYO5SHonx4+fbJE1+Q==", "dev": true, "requires": { - "cssnano-util-get-arguments": "4.0.0", - "cssnano-util-get-match": "4.0.0", - "postcss": "7.0.14", - "postcss-value-parser": "3.3.1" + "cssnano-util-get-arguments": "^4.0.0", + "cssnano-util-get-match": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" } }, "postcss-normalize-string": { @@ -5553,9 +5528,9 @@ "integrity": "sha512-RrERod97Dnwqq49WNz8qo66ps0swYZDSb6rM57kN2J+aoyEAJfZ6bMx0sx/F9TIEX0xthPGCmeyiam/jXif0eA==", "dev": true, "requires": { - "has": "1.0.3", - "postcss": "7.0.14", - "postcss-value-parser": "3.3.1" + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" } }, "postcss-normalize-timing-functions": { @@ -5564,9 +5539,9 @@ "integrity": "sha512-acwJY95edP762e++00Ehq9L4sZCEcOPyaHwoaFOhIwWCDfik6YvqsYNxckee65JHLKzuNSSmAdxwD2Cud1Z54A==", "dev": true, "requires": { - "cssnano-util-get-match": "4.0.0", - "postcss": "7.0.14", - "postcss-value-parser": "3.3.1" + "cssnano-util-get-match": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" } }, "postcss-normalize-unicode": { @@ -5575,9 +5550,9 @@ "integrity": "sha512-od18Uq2wCYn+vZ/qCOeutvHjB5jm57ToxRaMeNuf0nWVHaP9Hua56QyMF6fs/4FSUnVIw0CBPsU0K4LnBPwYwg==", "dev": true, "requires": { - "browserslist": "4.4.2", - "postcss": "7.0.14", - "postcss-value-parser": "3.3.1" + "browserslist": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" } }, "postcss-normalize-url": { @@ -5586,10 +5561,10 @@ "integrity": "sha512-p5oVaF4+IHwu7VpMan/SSpmpYxcJMtkGppYf0VbdH5B6hN8YNmVyJLuY9FmLQTzY3fag5ESUUHDqM+heid0UVA==", "dev": true, "requires": { - "is-absolute-url": "2.1.0", - "normalize-url": "3.3.0", - "postcss": "7.0.14", - "postcss-value-parser": "3.3.1" + "is-absolute-url": "^2.0.0", + "normalize-url": "^3.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" } }, "postcss-normalize-whitespace": { @@ -5598,8 +5573,8 @@ "integrity": "sha512-tO8QIgrsI3p95r8fyqKV+ufKlSHh9hMJqACqbv2XknufqEDhDvbguXGBBqxw9nsQoXWf0qOqppziKJKHMD4GtA==", "dev": true, "requires": { - "postcss": "7.0.14", - "postcss-value-parser": "3.3.1" + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" } }, "postcss-ordered-values": { @@ -5608,9 +5583,9 @@ "integrity": "sha512-2fCObh5UanxvSxeXrtLtlwVThBvHn6MQcu4ksNT2tsaV2Fg76R2CV98W7wNSlX+5/pFwEyaDwKLLoEV7uRybAw==", "dev": true, "requires": { - "cssnano-util-get-arguments": "4.0.0", - "postcss": "7.0.14", - "postcss-value-parser": "3.3.1" + "cssnano-util-get-arguments": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" } }, "postcss-reduce-idents": { @@ -5619,8 +5594,8 @@ "integrity": "sha1-wsbSDMlYKE9qv75j92Cb9AkFmtM=", "dev": true, "requires": { - "postcss": "5.2.18", - "postcss-value-parser": "3.3.1" + "postcss": "^5.0.4", + "postcss-value-parser": "^3.0.2" }, "dependencies": { "chalk": { @@ -5629,11 +5604,11 @@ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" + "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" }, "dependencies": { "supports-color": { @@ -5656,10 +5631,10 @@ "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", "dev": true, "requires": { - "chalk": "1.1.3", - "js-base64": "2.5.1", - "source-map": "0.5.7", - "supports-color": "3.2.3" + "chalk": "^1.1.3", + "js-base64": "^2.1.9", + "source-map": "^0.5.6", + "supports-color": "^3.2.3" } }, "source-map": { @@ -5674,7 +5649,7 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "1.0.0" + "has-flag": "^1.0.0" } } } @@ -5685,10 +5660,10 @@ "integrity": "sha512-gKWmR5aUulSjbzOfD9AlJiHCGH6AEVLaM0AV+aSioxUDd16qXP1PCh8d1/BGVvpdWn8k/HiK7n6TjeoXN1F7DA==", "dev": true, "requires": { - "browserslist": "4.4.2", - "caniuse-api": "3.0.0", - "has": "1.0.3", - "postcss": "7.0.14" + "browserslist": "^4.0.0", + "caniuse-api": "^3.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0" } }, "postcss-reduce-transforms": { @@ -5697,10 +5672,10 @@ "integrity": "sha512-EEVig1Q2QJ4ELpJXMZR8Vt5DQx8/mo+dGWSR7vWXqcob2gQLyQGsionYcGKATXvQzMPn6DSN1vTN7yFximdIAg==", "dev": true, "requires": { - "cssnano-util-get-match": "4.0.0", - "has": "1.0.3", - "postcss": "7.0.14", - "postcss-value-parser": "3.3.1" + "cssnano-util-get-match": "^4.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" } }, "postcss-selector-parser": { @@ -5709,9 +5684,9 @@ "integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==", "dev": true, "requires": { - "cssesc": "2.0.0", - "indexes-of": "1.0.1", - "uniq": "1.0.1" + "cssesc": "^2.0.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" } }, "postcss-svgo": { @@ -5720,10 +5695,10 @@ "integrity": "sha512-C6wyjo3VwFm0QgBy+Fu7gCYOkCmgmClghO+pjcxvrcBKtiKt0uCF+hvbMO1fyv5BMImRK90SMb+dwUnfbGd+jw==", "dev": true, "requires": { - "is-svg": "3.0.0", - "postcss": "7.0.14", - "postcss-value-parser": "3.3.1", - "svgo": "1.2.0" + "is-svg": "^3.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0", + "svgo": "^1.0.0" } }, "postcss-unique-selectors": { @@ -5732,9 +5707,9 @@ "integrity": "sha512-+JanVaryLo9QwZjKrmJgkI4Fn8SBgRO6WXQBJi7KiAVPlmxikB5Jzc4EvXMT2H0/m0RjrVVm9rGNhZddm/8Spg==", "dev": true, "requires": { - "alphanum-sort": "1.0.2", - "postcss": "7.0.14", - "uniqs": "2.0.0" + "alphanum-sort": "^1.0.0", + "postcss": "^7.0.0", + "uniqs": "^2.0.0" } }, "postcss-value-parser": { @@ -5749,9 +5724,9 @@ "integrity": "sha1-0hCd3AVbka9n/EyzsCWUZjnSryI=", "dev": true, "requires": { - "has": "1.0.3", - "postcss": "5.2.18", - "uniqs": "2.0.0" + "has": "^1.0.1", + "postcss": "^5.0.4", + "uniqs": "^2.0.0" }, "dependencies": { "chalk": { @@ -5760,11 +5735,11 @@ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" + "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" }, "dependencies": { "supports-color": { @@ -5787,10 +5762,10 @@ "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", "dev": true, "requires": { - "chalk": "1.1.3", - "js-base64": "2.5.1", - "source-map": "0.5.7", - "supports-color": "3.2.3" + "chalk": "^1.1.3", + "js-base64": "^2.1.9", + "source-map": "^0.5.6", + "supports-color": "^3.2.3" } }, "source-map": { @@ -5805,7 +5780,7 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "1.0.0" + "has-flag": "^1.0.0" } } } @@ -5816,9 +5791,9 @@ "integrity": "sha512-quMHnDckt2DQ9lRi6bYLnuyBDnVzK+McHa8+ar4kTdYbWEo/92hREOu3h70ZirudOOp/my2b3r0m5YtxY52yrA==", "dev": true, "requires": { - "object-assign": "4.1.1", - "posthtml-parser": "0.3.3", - "posthtml-render": "1.1.4" + "object-assign": "^4.1.1", + "posthtml-parser": "^0.3.3", + "posthtml-render": "^1.1.0" }, "dependencies": { "isobject": { @@ -5836,9 +5811,9 @@ "integrity": "sha512-H/Z/yXGwl49A7hYQLV1iQ3h87NE0aZ/PMZhFwhw3lKeCAN+Ti4idrHvVvh4/GX10I7u77aQw+QB4vV5/Lzvv5A==", "dev": true, "requires": { - "htmlparser2": "3.10.1", - "isobject": "2.1.0", - "object-assign": "4.1.1" + "htmlparser2": "^3.9.2", + "isobject": "^2.1.0", + "object-assign": "^4.1.1" } } } @@ -5849,8 +5824,8 @@ "integrity": "sha512-h7vXIQ21Ikz2w5wPClPakNP6mJeJCK6BT0GpqnQrNNABdR7/TchNlFyryL1Bz6Ww53YWCKkr6tdZuHlxY1AVdQ==", "dev": true, "requires": { - "htmlparser2": "3.10.1", - "object-assign": "4.1.1" + "htmlparser2": "^3.9.2", + "object-assign": "^4.1.1" } }, "posthtml-render": { @@ -5907,12 +5882,12 @@ "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", "dev": true, "requires": { - "bn.js": "4.11.8", - "browserify-rsa": "4.0.1", - "create-hash": "1.2.0", - "parse-asn1": "5.1.4", - "randombytes": "2.1.0", - "safe-buffer": "5.1.2" + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" } }, "punycode": { @@ -5933,8 +5908,8 @@ "integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=", "dev": true, "requires": { - "object-assign": "4.1.1", - "strict-uri-encode": "1.1.0" + "object-assign": "^4.1.0", + "strict-uri-encode": "^1.0.0" } }, "querystring": { @@ -5956,8 +5931,8 @@ "dev": true, "requires": { "buffer-equal": "0.0.1", - "minimist": "1.2.0", - "through2": "2.0.5" + "minimist": "^1.1.3", + "through2": "^2.0.0" } }, "randombytes": { @@ -5966,7 +5941,7 @@ "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", "dev": true, "requires": { - "safe-buffer": "5.1.2" + "safe-buffer": "^5.1.0" } }, "randomfill": { @@ -5975,8 +5950,8 @@ "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", "dev": true, "requires": { - "randombytes": "2.1.0", - "safe-buffer": "5.1.2" + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" } }, "range-parser": { @@ -5991,13 +5966,13 @@ "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "2.0.0", - "safe-buffer": "5.1.2", - "string_decoder": "1.1.1", - "util-deprecate": "1.0.2" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } }, "readdirp": { @@ -6006,9 +5981,9 @@ "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", "dev": true, "requires": { - "graceful-fs": "4.1.15", - "micromatch": "3.1.10", - "readable-stream": "2.3.6" + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" } }, "reduce-css-calc": { @@ -6017,9 +5992,9 @@ "integrity": "sha1-dHyRTgSWFKTJz7umKYca0dKSdxY=", "dev": true, "requires": { - "balanced-match": "0.4.2", - "math-expression-evaluator": "1.2.17", - "reduce-function-call": "1.0.2" + "balanced-match": "^0.4.2", + "math-expression-evaluator": "^1.2.14", + "reduce-function-call": "^1.0.1" }, "dependencies": { "balanced-match": { @@ -6036,7 +6011,7 @@ "integrity": "sha1-WiAL+S4ON3UXUv5FsKszD9S2vpk=", "dev": true, "requires": { - "balanced-match": "0.4.2" + "balanced-match": "^0.4.2" }, "dependencies": { "balanced-match": { @@ -6059,7 +6034,7 @@ "integrity": "sha512-s5NGghCE4itSlUS+0WUj88G6cfMVMmH8boTPNvABf8od+2dhT9WDlWu8n01raQAJZMOK8Ch6jSexaRO7swd6aw==", "dev": true, "requires": { - "regenerate": "1.4.0" + "regenerate": "^1.4.0" } }, "regenerator-runtime": { @@ -6074,7 +6049,7 @@ "integrity": "sha512-T0QMBjK3J0MtxjPmdIMXm72Wvj2Abb0Bd4HADdfijwMdoIsyQZ6fWC7kDFhk2YinBBEMZDL7Y7wh0J1sGx3S4A==", "dev": true, "requires": { - "private": "0.1.8" + "private": "^0.1.6" } }, "regex-not": { @@ -6083,8 +6058,8 @@ "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", "dev": true, "requires": { - "extend-shallow": "3.0.2", - "safe-regex": "1.1.0" + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" } }, "regexp-tree": { @@ -6099,12 +6074,12 @@ "integrity": "sha512-eDDWElbwwI3K0Lo6CqbQbA6FwgtCz4kYTarrri1okfkRLZAqstU+B3voZBCjg8Fl6iq0gXrJG6MvRgLthfvgOA==", "dev": true, "requires": { - "regenerate": "1.4.0", - "regenerate-unicode-properties": "7.0.0", - "regjsgen": "0.5.0", - "regjsparser": "0.6.0", - "unicode-match-property-ecmascript": "1.0.4", - "unicode-match-property-value-ecmascript": "1.0.2" + "regenerate": "^1.4.0", + "regenerate-unicode-properties": "^7.0.0", + "regjsgen": "^0.5.0", + "regjsparser": "^0.6.0", + "unicode-match-property-ecmascript": "^1.0.4", + "unicode-match-property-value-ecmascript": "^1.0.2" } }, "regjsgen": { @@ -6119,7 +6094,7 @@ "integrity": "sha512-RQ7YyokLiQBomUJuUG8iGVvkgOLxwyZM8k6d3q5SAXpg4r5TZJZigKFvC6PpD+qQ98bCDC5YelPeA3EucDoNeQ==", "dev": true, "requires": { - "jsesc": "0.5.0" + "jsesc": "~0.5.0" }, "dependencies": { "jsesc": { @@ -6154,7 +6129,7 @@ "integrity": "sha512-3sUr9aq5OfSg2S9pNtPA9hL1FVEAjvfOC4leW0SNf/mpnaakz2a9femSd6LqAww2RaFctwyf1lCqnTHuF1rxDg==", "dev": true, "requires": { - "path-parse": "1.0.6" + "path-parse": "^1.0.6" } }, "resolve-from": { @@ -6175,8 +6150,8 @@ "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", "dev": true, "requires": { - "onetime": "2.0.1", - "signal-exit": "3.0.2" + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" } }, "ret": { @@ -6203,7 +6178,7 @@ "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", "dev": true, "requires": { - "glob": "7.1.3" + "glob": "^7.1.3" } }, "ripemd160": { @@ -6212,8 +6187,8 @@ "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", "dev": true, "requires": { - "hash-base": "3.0.4", - "inherits": "2.0.3" + "hash-base": "^3.0.0", + "inherits": "^2.0.1" } }, "safe-buffer": { @@ -6228,7 +6203,7 @@ "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", "dev": true, "requires": { - "ret": "0.1.15" + "ret": "~0.1.10" } }, "safer-eval": { @@ -6237,7 +6212,7 @@ "integrity": "sha512-4qkBS8VzJatFR7F0eZfKoJyjqo43jY1jBvRhB5WXM0eJNjx9fiSmph5NApJefqKqpASKWPfaIJCJMMeWePSzfw==", "dev": true, "requires": { - "clones": "1.2.0" + "clones": "^1.2.0" } }, "sax": { @@ -6259,18 +6234,18 @@ "dev": true, "requires": { "debug": "2.6.9", - "depd": "1.1.2", - "destroy": "1.0.4", - "encodeurl": "1.0.2", - "escape-html": "1.0.3", - "etag": "1.8.1", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", "fresh": "0.5.2", - "http-errors": "1.6.3", + "http-errors": "~1.6.2", "mime": "1.4.1", "ms": "2.0.0", - "on-finished": "2.3.0", - "range-parser": "1.2.0", - "statuses": "1.4.0" + "on-finished": "~2.3.0", + "range-parser": "~1.2.0", + "statuses": "~1.4.0" }, "dependencies": { "debug": { @@ -6296,8 +6271,8 @@ "integrity": "sha512-mUc8vA5iJghe+O+3s0YDGFLMJcqitVFk787YKiv8a4sf6RX5W0u81b+gcHrp15O0fFa010dRBVZvwcKXOWsL9Q==", "dev": true, "requires": { - "js-beautify": "1.8.9", - "safer-eval": "1.3.0" + "js-beautify": "^1.8.9", + "safer-eval": "^1.3.0" } }, "serve-static": { @@ -6306,9 +6281,9 @@ "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", "dev": true, "requires": { - "encodeurl": "1.0.2", - "escape-html": "1.0.3", - "parseurl": "1.3.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.2", "send": "0.16.2" } }, @@ -6318,10 +6293,10 @@ "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", "dev": true, "requires": { - "extend-shallow": "2.0.1", - "is-extendable": "0.1.1", - "is-plain-object": "2.0.4", - "split-string": "3.1.0" + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" }, "dependencies": { "extend-shallow": { @@ -6330,7 +6305,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "0.1.1" + "is-extendable": "^0.1.0" } } } @@ -6353,8 +6328,8 @@ "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", "dev": true, "requires": { - "inherits": "2.0.3", - "safe-buffer": "5.1.2" + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" } }, "shallow-copy": { @@ -6369,7 +6344,7 @@ "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", "dev": true, "requires": { - "shebang-regex": "1.0.0" + "shebang-regex": "^1.0.0" } }, "shebang-regex": { @@ -6396,7 +6371,7 @@ "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", "dev": true, "requires": { - "is-arrayish": "0.3.2" + "is-arrayish": "^0.3.1" }, "dependencies": { "is-arrayish": { @@ -6413,14 +6388,14 @@ "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", "dev": true, "requires": { - "base": "0.11.2", - "debug": "2.6.9", - "define-property": "0.2.5", - "extend-shallow": "2.0.1", - "map-cache": "0.2.2", - "source-map": "0.5.7", - "source-map-resolve": "0.5.2", - "use": "3.1.1" + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" }, "dependencies": { "debug": { @@ -6438,7 +6413,7 @@ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "is-descriptor": "0.1.6" + "is-descriptor": "^0.1.0" } }, "extend-shallow": { @@ -6447,7 +6422,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "0.1.1" + "is-extendable": "^0.1.0" } }, "ms": { @@ -6470,9 +6445,9 @@ "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", "dev": true, "requires": { - "define-property": "1.0.0", - "isobject": "3.0.1", - "snapdragon-util": "3.0.1" + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" }, "dependencies": { "define-property": { @@ -6481,7 +6456,7 @@ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", "dev": true, "requires": { - "is-descriptor": "1.0.2" + "is-descriptor": "^1.0.0" } }, "is-accessor-descriptor": { @@ -6490,7 +6465,7 @@ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", "dev": true, "requires": { - "kind-of": "6.0.2" + "kind-of": "^6.0.0" } }, "is-data-descriptor": { @@ -6499,7 +6474,7 @@ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", "dev": true, "requires": { - "kind-of": "6.0.2" + "kind-of": "^6.0.0" } }, "is-descriptor": { @@ -6508,9 +6483,9 @@ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", "dev": true, "requires": { - "is-accessor-descriptor": "1.0.0", - "is-data-descriptor": "1.0.0", - "kind-of": "6.0.2" + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" } } } @@ -6521,7 +6496,7 @@ "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", "dev": true, "requires": { - "kind-of": "3.2.2" + "kind-of": "^3.2.0" }, "dependencies": { "kind-of": { @@ -6530,7 +6505,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "^1.1.5" } } } @@ -6541,7 +6516,7 @@ "integrity": "sha1-RBttTTRnmPG05J6JIK37oOVD+a0=", "dev": true, "requires": { - "is-plain-obj": "1.1.0" + "is-plain-obj": "^1.0.0" } }, "source-map": { @@ -6556,11 +6531,11 @@ "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", "dev": true, "requires": { - "atob": "2.1.2", - "decode-uri-component": "0.2.0", - "resolve-url": "0.2.1", - "source-map-url": "0.4.0", - "urix": "0.1.0" + "atob": "^2.1.1", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" } }, "source-map-support": { @@ -6569,8 +6544,8 @@ "integrity": "sha512-YfQ3tQFTK/yzlGJuX8pTwa4tifQj4QS2Mj7UegOu8jAz59MqIiMGPXxQhVQiIMNzayuUSF/jEuVnfFF5JqybmQ==", "dev": true, "requires": { - "buffer-from": "1.1.1", - "source-map": "0.6.1" + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" } }, "source-map-url": { @@ -6585,7 +6560,7 @@ "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", "dev": true, "requires": { - "extend-shallow": "3.0.2" + "extend-shallow": "^3.0.0" } }, "sprintf-js": { @@ -6606,7 +6581,7 @@ "integrity": "sha512-1JJ8ADJ7UB//CRqocI6j4WxGvSqQHX14Fz0gXDNvRA6Y1JIAI/lMNdqn1lpnaA6ugQ0fMH0uBB955DkwhKActw==", "dev": true, "requires": { - "escodegen": "1.9.1" + "escodegen": "^1.8.1" } }, "static-extend": { @@ -6615,8 +6590,8 @@ "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", "dev": true, "requires": { - "define-property": "0.2.5", - "object-copy": "0.1.0" + "define-property": "^0.2.5", + "object-copy": "^0.1.0" }, "dependencies": { "define-property": { @@ -6625,7 +6600,7 @@ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "is-descriptor": "0.1.6" + "is-descriptor": "^0.1.0" } } } @@ -6636,20 +6611,20 @@ "integrity": "sha512-D8vv82E/Kpmz3TXHKG8PPsCPg+RAX6cbCOyvjM6x04qZtQ47EtJFVwRsdov3n5d6/6ynrOY9XB4JkaZwB2xoRQ==", "dev": true, "requires": { - "concat-stream": "1.6.2", - "convert-source-map": "1.6.0", - "duplexer2": "0.1.4", - "escodegen": "1.9.1", - "falafel": "2.1.0", - "has": "1.0.3", - "magic-string": "0.22.5", + "concat-stream": "~1.6.0", + "convert-source-map": "^1.5.1", + "duplexer2": "~0.1.4", + "escodegen": "~1.9.0", + "falafel": "^2.1.0", + "has": "^1.0.1", + "magic-string": "^0.22.4", "merge-source-map": "1.0.4", - "object-inspect": "1.4.1", - "quote-stream": "1.0.2", - "readable-stream": "2.3.6", - "shallow-copy": "0.0.1", - "static-eval": "2.0.1", - "through2": "2.0.5" + "object-inspect": "~1.4.0", + "quote-stream": "~1.0.2", + "readable-stream": "~2.3.3", + "shallow-copy": "~0.0.1", + "static-eval": "^2.0.0", + "through2": "~2.0.3" } }, "statuses": { @@ -6664,8 +6639,8 @@ "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", "dev": true, "requires": { - "inherits": "2.0.3", - "readable-stream": "2.3.6" + "inherits": "~2.0.1", + "readable-stream": "^2.0.2" } }, "stream-http": { @@ -6674,11 +6649,11 @@ "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", "dev": true, "requires": { - "builtin-status-codes": "3.0.0", - "inherits": "2.0.3", - "readable-stream": "2.3.6", - "to-arraybuffer": "1.0.1", - "xtend": "4.0.1" + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.3.6", + "to-arraybuffer": "^1.0.0", + "xtend": "^4.0.0" } }, "strict-uri-encode": { @@ -6693,7 +6668,7 @@ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "requires": { - "safe-buffer": "5.1.2" + "safe-buffer": "~5.1.0" } }, "strip-ansi": { @@ -6702,7 +6677,7 @@ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "requires": { - "ansi-regex": "2.1.1" + "ansi-regex": "^2.0.0" } }, "stylehacks": { @@ -6711,9 +6686,9 @@ "integrity": "sha512-7GlLk9JwlElY4Y6a/rmbH2MhVlTyVmiJd1PfTCqFaIBEGMYNsrO/v3SeGTdhBThLg4Z+NbOk/qFMwCa+J+3p/g==", "dev": true, "requires": { - "browserslist": "4.4.2", - "postcss": "7.0.14", - "postcss-selector-parser": "3.1.1" + "browserslist": "^4.0.0", + "postcss": "^7.0.0", + "postcss-selector-parser": "^3.0.0" }, "dependencies": { "postcss-selector-parser": { @@ -6722,9 +6697,9 @@ "integrity": "sha1-T4dfSvsMllc9XPTXQBGu4lCn6GU=", "dev": true, "requires": { - "dot-prop": "4.2.0", - "indexes-of": "1.0.1", - "uniq": "1.0.1" + "dot-prop": "^4.1.1", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" } } } @@ -6741,20 +6716,20 @@ "integrity": "sha512-xBfxJxfk4UeVN8asec9jNxHiv3UAMv/ujwBWGYvQhhMb2u3YTGKkiybPcLFDLq7GLLWE9wa73e0/m8L5nTzQbw==", "dev": true, "requires": { - "chalk": "2.4.2", - "coa": "2.0.2", - "css-select": "2.0.2", - "css-select-base-adapter": "0.1.1", + "chalk": "^2.4.1", + "coa": "^2.0.2", + "css-select": "^2.0.0", + "css-select-base-adapter": "^0.1.1", "css-tree": "1.0.0-alpha.28", - "css-url-regex": "1.1.0", - "csso": "3.5.1", - "js-yaml": "3.12.1", - "mkdirp": "0.5.1", - "object.values": "1.1.0", - "sax": "1.2.4", - "stable": "0.1.8", - "unquote": "1.1.1", - "util.promisify": "1.0.0" + "css-url-regex": "^1.1.0", + "csso": "^3.5.1", + "js-yaml": "^3.12.0", + "mkdirp": "~0.5.1", + "object.values": "^1.1.0", + "sax": "~1.2.4", + "stable": "^0.1.8", + "unquote": "~1.1.1", + "util.promisify": "~1.0.0" } }, "terser": { @@ -6763,9 +6738,9 @@ "integrity": "sha512-JDJjgleBROeek2iBcSNzOHLKsB/MdDf+E/BOAJ0Tk9r7p9/fVobfv7LMJ/g/k3v9SXdmjZnIlFd5nfn/Rt0Xow==", "dev": true, "requires": { - "commander": "2.17.1", - "source-map": "0.6.1", - "source-map-support": "0.5.10" + "commander": "~2.17.1", + "source-map": "~0.6.1", + "source-map-support": "~0.5.9" }, "dependencies": { "commander": { @@ -6782,8 +6757,8 @@ "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", "dev": true, "requires": { - "readable-stream": "2.3.6", - "xtend": "4.0.1" + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" } }, "timers-browserify": { @@ -6792,7 +6767,7 @@ "integrity": "sha512-YvC1SV1XdOUaL6gx5CoGroT3Gu49pK9+TZ38ErPldOWW4j49GI1HKs9DV+KGq/w6y+LZ72W1c8cKz2vzY+qpzg==", "dev": true, "requires": { - "setimmediate": "1.0.5" + "setimmediate": "^1.0.4" } }, "timsort": { @@ -6825,7 +6800,7 @@ "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", "dev": true, "requires": { - "kind-of": "3.2.2" + "kind-of": "^3.0.2" }, "dependencies": { "kind-of": { @@ -6834,7 +6809,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "^1.1.5" } } } @@ -6845,10 +6820,10 @@ "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", "dev": true, "requires": { - "define-property": "2.0.2", - "extend-shallow": "3.0.2", - "regex-not": "1.0.2", - "safe-regex": "1.1.0" + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" } }, "to-regex-range": { @@ -6857,8 +6832,8 @@ "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", "dev": true, "requires": { - "is-number": "3.0.0", - "repeat-string": "1.6.1" + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" } }, "trim-right": { @@ -6867,41 +6842,6 @@ "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", "dev": true }, - "tslib": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", - "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==", - "dev": true - }, - "tslint": { - "version": "5.12.1", - "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.12.1.tgz", - "integrity": "sha512-sfodBHOucFg6egff8d1BvuofoOQ/nOeYNfbp7LDlKBcLNrL3lmS5zoiDGyOMdT7YsEXAwWpTdAHwOGOc8eRZAw==", - "dev": true, - "requires": { - "babel-code-frame": "6.26.0", - "builtin-modules": "1.1.1", - "chalk": "2.4.2", - "commander": "2.19.0", - "diff": "3.5.0", - "glob": "7.1.3", - "js-yaml": "3.12.1", - "minimatch": "3.0.4", - "resolve": "1.10.0", - "semver": "5.6.0", - "tslib": "1.9.3", - "tsutils": "2.29.0" - } - }, - "tsutils": { - "version": "2.29.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", - "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", - "dev": true, - "requires": { - "tslib": "1.9.3" - } - }, "tty-browserify": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", @@ -6914,7 +6854,7 @@ "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", "dev": true, "requires": { - "prelude-ls": "1.1.2" + "prelude-ls": "~1.1.2" } }, "typedarray": { @@ -6941,8 +6881,8 @@ "integrity": "sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==", "dev": true, "requires": { - "unicode-canonical-property-names-ecmascript": "1.0.4", - "unicode-property-aliases-ecmascript": "1.0.4" + "unicode-canonical-property-names-ecmascript": "^1.0.4", + "unicode-property-aliases-ecmascript": "^1.0.4" } }, "unicode-match-property-value-ecmascript": { @@ -6963,8 +6903,8 @@ "integrity": "sha1-1nHd3YkQGgi6w3tqUWEBBgIFIIU=", "dev": true, "requires": { - "pako": "0.2.9", - "tiny-inflate": "1.0.2" + "pako": "^0.2.5", + "tiny-inflate": "^1.0.0" } }, "union-value": { @@ -6973,10 +6913,10 @@ "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", "dev": true, "requires": { - "arr-union": "3.1.0", - "get-value": "2.0.6", - "is-extendable": "0.1.1", - "set-value": "0.4.3" + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^0.4.3" }, "dependencies": { "extend-shallow": { @@ -6985,7 +6925,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "0.1.1" + "is-extendable": "^0.1.0" } }, "set-value": { @@ -6994,10 +6934,10 @@ "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", "dev": true, "requires": { - "extend-shallow": "2.0.1", - "is-extendable": "0.1.1", - "is-plain-object": "2.0.4", - "to-object-path": "0.3.0" + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.1", + "to-object-path": "^0.3.0" } } } @@ -7026,8 +6966,8 @@ "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", "dev": true, "requires": { - "has-value": "0.3.1", - "isobject": "3.0.1" + "has-value": "^0.3.1", + "isobject": "^3.0.0" }, "dependencies": { "has-value": { @@ -7036,9 +6976,9 @@ "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", "dev": true, "requires": { - "get-value": "2.0.6", - "has-values": "0.1.4", - "isobject": "2.1.0" + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" }, "dependencies": { "isobject": { @@ -7117,8 +7057,8 @@ "integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==", "dev": true, "requires": { - "define-properties": "1.1.3", - "object.getownpropertydescriptors": "2.0.3" + "define-properties": "^1.1.2", + "object.getownpropertydescriptors": "^2.0.3" } }, "v8-compile-cache": { @@ -7154,7 +7094,7 @@ "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", "dev": true, "requires": { - "defaults": "1.0.3" + "defaults": "^1.0.3" } }, "whet.extend": { @@ -7169,7 +7109,7 @@ "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, "requires": { - "isexe": "2.0.0" + "isexe": "^2.0.0" } }, "wordwrap": { @@ -7190,7 +7130,7 @@ "integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==", "dev": true, "requires": { - "async-limiter": "1.0.0" + "async-limiter": "~1.0.0" } }, "xtend": { diff --git a/jipt/src/accent.ts b/jipt/src/accent.ts index 0a3fd1a6..d4a4ecf8 100644 --- a/jipt/src/accent.ts +++ b/jipt/src/accent.ts @@ -14,7 +14,7 @@ export interface Config { const state = new State({ nodes: new WeakMap(), projectTranslations: {}, - refs: new Map() + refs: new Map(), }); const liveNode = new LiveNode(state); @@ -39,7 +39,7 @@ export const Accent = { const mutation = new Mutation(liveNode); mutation.bindEvents(); - } + }, }; export default Accent; diff --git a/jipt/src/frame-listener.ts b/jipt/src/frame-listener.ts index 7e6ca4aa..5c956773 100644 --- a/jipt/src/frame-listener.ts +++ b/jipt/src/frame-listener.ts @@ -10,7 +10,7 @@ const enum ACTIONS { redirectIfEmbedded = 'redirectIfEmbedded', login = 'login', loggedIn = 'loggedIn', - changeText = 'changeText' + changeText = 'changeText', } interface Props { diff --git a/jipt/src/mutation/live-node.ts b/jipt/src/mutation/live-node.ts index 6b40ced9..fa019cf4 100644 --- a/jipt/src/mutation/live-node.ts +++ b/jipt/src/mutation/live-node.ts @@ -24,7 +24,7 @@ export default class LiveNode { } matchAttributes(node: Element) { - Array.from(node.attributes).forEach(attribute => { + Array.from(node.attributes).forEach((attribute) => { const translation = this.findTranslationByValue(attribute.value); if (!translation || !translation.text) return; @@ -34,7 +34,7 @@ export default class LiveNode { attribute.value = newAttribute; this.state.addReference(node, translation, { - attributeName: attribute.name + attributeName: attribute.name, }); }); } diff --git a/jipt/src/mutation/mutation.ts b/jipt/src/mutation/mutation.ts index 89cdebbf..3ac3e6a1 100644 --- a/jipt/src/mutation/mutation.ts +++ b/jipt/src/mutation/mutation.ts @@ -12,6 +12,12 @@ interface Translation { window nodes on mutation and messages FROM the Accent client. */ export default class Mutation { + private readonly liveNode: LiveNode; + + constructor(liveNode: LiveNode) { + this.liveNode = liveNode; + } + static nodeChange(node: Element, meta: any, text: string) { this.textNodeChange(node, meta, text); this.attributeNodeChange(node, meta, text); @@ -55,12 +61,6 @@ export default class Mutation { }, NODE_UPDATE_STYLE_TIMEOUT); } - private readonly liveNode: LiveNode; - - constructor(liveNode: LiveNode) { - this.liveNode = liveNode; - } - bindEvents() { const onMutation = (instance: MutationRecord[]) => { return instance.forEach(this.handleNodeMutation.bind(this)); @@ -71,7 +71,7 @@ export default class Mutation { characterData: true, characterDataOldValue: true, childList: true, - subtree: true + subtree: true, }); } diff --git a/jipt/src/ui/pin.ts b/jipt/src/ui/pin.ts index 1e89bb65..4645be29 100644 --- a/jipt/src/ui/pin.ts +++ b/jipt/src/ui/pin.ts @@ -10,6 +10,8 @@ interface Props { state: State; } +const CENTER_OFFSET = 6; + /* The Pin component serves as the entrypoint for the user. The element it creates is responsible to sending messages to the Accent UI. @@ -34,7 +36,7 @@ export default class Pin { } bindEvents() { - this.element.addEventListener('click', event => { + this.element.addEventListener('click', (event) => { const target = event.target as HTMLElement; if (target.dataset.id) { @@ -47,7 +49,7 @@ export default class Pin { } }); - document.addEventListener('mouseover', event => { + document.addEventListener('mouseover', (event) => { const node = event.target as HTMLElement; if (this.liveNode.isLive(node)) this.showFor(node); @@ -61,7 +63,9 @@ export default class Pin { ); styles.set( this.element, - `top: ${top + height - 6}px; left: ${left - 6}px; ${styles.pin}` + `top: ${top + height - CENTER_OFFSET}px; left: ${ + left - CENTER_OFFSET + }px; ${styles.pin}` ); const ids = keys diff --git a/jipt/src/ui/random-class.ts b/jipt/src/ui/random-class.ts index cefaa830..dc06ac1c 100644 --- a/jipt/src/ui/random-class.ts +++ b/jipt/src/ui/random-class.ts @@ -1,5 +1,5 @@ +const BASE = 36; +const LENGTH = 8; + /* Random class that should not conflict with the parent window styles */ -export default () => - `acc_${Math.random() - .toString(36) - .substring(8)}`; +export default () => `acc_${Math.random().toString(BASE).substring(LENGTH)}`; diff --git a/jipt/src/ui/styles.ts b/jipt/src/ui/styles.ts index 3a250609..490e569a 100644 --- a/jipt/src/ui/styles.ts +++ b/jipt/src/ui/styles.ts @@ -52,5 +52,5 @@ export default { set, translationNode, translationNodeConflicted, - translationNodeUpdated + translationNodeUpdated, }; diff --git a/jipt/src/ui/ui.ts b/jipt/src/ui/ui.ts index a21fbe2d..73cdb60b 100644 --- a/jipt/src/ui/ui.ts +++ b/jipt/src/ui/ui.ts @@ -144,9 +144,7 @@ export default class UI { element.innerHTML = `
×
-
×
+
×
`; return element; diff --git a/lib/accent/schemas/project.ex b/lib/accent/schemas/project.ex index 6ba46413..75fa8675 100644 --- a/lib/accent/schemas/project.ex +++ b/lib/accent/schemas/project.ex @@ -8,6 +8,10 @@ defmodule Accent.Project do field(:last_synced_at, :utc_datetime) field(:locked_file_operations, :boolean, default: false) + field(:translations_count, :integer, virtual: true, default: :not_loaded) + field(:reviewed_count, :integer, virtual: true, default: :not_loaded) + field(:conflicts_count, :integer, virtual: true, default: :not_loaded) + has_many(:integrations, Accent.Integration) has_many(:revisions, Accent.Revision) has_many(:target_revisions, Accent.Revision, where: [master: false]) diff --git a/lib/accent/scopes/project.ex b/lib/accent/scopes/project.ex index 8bea19c1..884bc0a4 100644 --- a/lib/accent/scopes/project.ex +++ b/lib/accent/scopes/project.ex @@ -1,4 +1,6 @@ defmodule Accent.Scopes.Project do + import Ecto.Query + @doc """ ## Examples @@ -15,4 +17,35 @@ defmodule Accent.Scopes.Project do def from_search(query, term) do Accent.Scopes.Search.from_search(query, term, :name) end + + @doc """ + Fill `translations_count`, `conflicts_count` and `reviewed_count` for projects. + """ + @spec with_stats(Ecto.Queryable.t()) :: Ecto.Queryable.t() + def with_stats(query) do + translations = + from( + t in Accent.Translation, + inner_join: revisions in assoc(t, :revision), + select: %{field_id: revisions.project_id, count: count(t)}, + where: [removed: false, locked: false], + where: is_nil(t.version_id), + group_by: revisions.project_id + ) + + reviewed = from(translations, where: [conflicted: false]) + + from( + projects in query, + left_join: translations in subquery(translations), + on: translations.field_id == projects.id, + left_join: reviewed in subquery(reviewed), + on: reviewed.field_id == projects.id, + select_merge: %{ + translations_count: coalesce(translations.count, 0), + reviewed_count: coalesce(reviewed.count, 0), + conflicts_count: coalesce(translations.count, 0) - coalesce(reviewed.count, 0) + } + ) + end end diff --git a/lib/accent/scopes/revision.ex b/lib/accent/scopes/revision.ex index 2e51884e..8cf2aec8 100644 --- a/lib/accent/scopes/revision.ex +++ b/lib/accent/scopes/revision.ex @@ -62,7 +62,7 @@ defmodule Accent.Scopes.Revision do end @doc """ - Fill `translations_count`, `conflicts_count` and `reviewed_count` for documents. + Fill `translations_count`, `conflicts_count` and `reviewed_count` for revisions. """ @spec with_stats(Ecto.Queryable.t()) :: Ecto.Queryable.t() def with_stats(query) do diff --git a/lib/accent/scopes/translations_count.ex b/lib/accent/scopes/translations_count.ex index 7eab186c..93c86255 100644 --- a/lib/accent/scopes/translations_count.ex +++ b/lib/accent/scopes/translations_count.ex @@ -3,12 +3,29 @@ defmodule Accent.Scopes.TranslationsCount do def with_stats(query, column, options \\ []) do exclude_empty_translations = Keyword.get(options, :exclude_empty_translations, false) - translations = countable_translations_query(column) - query - |> count_translations(translations, exclude_empty_translations) - |> count_reviewed(translations) - |> merge_select() + translations = + from( + t in Accent.Translation, + select: %{field_id: field(t, ^column), count: count(t)}, + where: [removed: false, locked: false], + where: is_nil(t.version_id), + group_by: field(t, ^column) + ) + + query = + query + |> count_translations(translations, exclude_empty_translations) + |> count_reviewed(translations) + + from( + [translations: t, reviewed: r] in query, + select_merge: %{ + translations_count: coalesce(t.count, 0), + reviewed_count: coalesce(r.count, 0), + conflicts_count: coalesce(t.count, 0) - coalesce(r.count, 0) + } + ) end defp count_translations(query, translations, _exclude_empty_translations = true) do @@ -23,25 +40,4 @@ defmodule Accent.Scopes.TranslationsCount do reviewed = from(translations, where: [conflicted: false]) from(q in query, left_join: translations in subquery(reviewed), as: :reviewed, on: translations.field_id == q.id) end - - defp merge_select(query) do - from( - [translations: t, reviewed: r] in query, - select_merge: %{ - translations_count: coalesce(t.count, 0), - reviewed_count: coalesce(r.count, 0), - conflicts_count: coalesce(t.count, 0) - coalesce(r.count, 0) - } - ) - end - - defp countable_translations_query(column) do - from( - t in Accent.Translation, - select: %{field_id: field(t, ^column), count: count(t)}, - where: [removed: false, locked: false], - where: is_nil(t.version_id), - group_by: field(t, ^column) - ) - end end diff --git a/lib/graphql/resolvers/project.ex b/lib/graphql/resolvers/project.ex index 03faf6a8..faeae423 100644 --- a/lib/graphql/resolvers/project.ex +++ b/lib/graphql/resolvers/project.ex @@ -78,6 +78,7 @@ defmodule Accent.GraphQL.Resolvers.Project do |> Query.where([_, c], c.user_id == ^viewer.id) |> Query.order_by([p, _], asc: p.name) |> ProjectScope.from_search(args[:query]) + |> ProjectScope.with_stats() |> Repo.paginate(page: args[:page]) |> Paginated.format() |> (&{:ok, &1}).() @@ -86,6 +87,7 @@ defmodule Accent.GraphQL.Resolvers.Project do @spec show_viewer(any(), %{id: String.t()}, GraphQLContext.t()) :: {:ok, Project.t() | nil} def show_viewer(_, %{id: id}, _) do Project + |> ProjectScope.with_stats() |> Repo.get(id) |> (&{:ok, &1}).() end diff --git a/lib/graphql/types/project.ex b/lib/graphql/types/project.ex index e5d3e7c7..4b45d2cb 100644 --- a/lib/graphql/types/project.ex +++ b/lib/graphql/types/project.ex @@ -16,6 +16,11 @@ defmodule Accent.GraphQL.Types.Project do field(:main_color, :string) field(:last_synced_at, :datetime) field(:logo, :string) + + field(:translations_count, non_null(:integer)) + field(:conflicts_count, non_null(:integer)) + field(:reviewed_count, non_null(:integer)) + field(:last_activity, :activity, resolve: &Accent.GraphQL.Resolvers.Project.last_activity/3) field(:is_file_operations_locked, non_null(:boolean), resolve: field_alias(:locked_file_operations)) diff --git a/mix.lock b/mix.lock index dd3d15a0..bff26898 100644 --- a/mix.lock +++ b/mix.lock @@ -1,74 +1,73 @@ %{ - "absinthe": {:hex, :absinthe, "1.4.16", "0933e4d9f12652b12115d5709c0293a1bf78a22578032e9ad0dad4efee6b9eb1", [:mix], [{:dataloader, "~> 1.0.0", [hex: :dataloader, repo: "hexpm", optional: true]}, {:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm"}, - "absinthe_error_payload": {:hex, :absinthe_error_payload, "1.1.1", "48c89baaff23c8fdf93313a3e2637648456a60f010e5cde34b1ed3309feceabc", [:make, :mix], [{:absinthe, "~> 1.3", [hex: :absinthe, repo: "hexpm", optional: false]}, {:ecto, "~> 3.1", [hex: :ecto, repo: "hexpm", optional: false]}], "hexpm"}, - "absinthe_plug": {:hex, :absinthe_plug, "1.4.7", "939b6b9e1c7abc6b399a5b49faa690a1fbb55b195c670aa35783b14b08ccec7a", [:mix], [{:absinthe, "~> 1.4.11", [hex: :absinthe, repo: "hexpm", optional: false]}, {:plug, "~> 1.3.2 or ~> 1.4", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"}, - "bamboo": {:hex, :bamboo, "1.4.0", "7b9201c49a843e4802061cf45692405b2c00efcf1cebf8b7b64f015ead072392", [:mix], [{:hackney, ">= 1.13.0", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"}, - "bamboo_smtp": {:hex, :bamboo_smtp, "2.1.0", "4be58f3c51d9f7875dc169ae58a1d2f08e5b718bf3895f70d130548c0598f422", [:mix], [{:bamboo, "~> 1.2", [hex: :bamboo, repo: "hexpm", optional: false]}, {:gen_smtp, "~> 0.15.0", [hex: :gen_smtp, repo: "hexpm", optional: false]}], "hexpm"}, - "bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm"}, - "canada": {:hex, :canada, "1.0.2", "040e4c47609b0a67d5773ac1fbe5e99f840cef173d69b739beda7c98453e0770", [:mix], [], "hexpm"}, - "canary": {:hex, :canary, "1.1.1", "4138d5e05db8497c477e4af73902eb9ae06e49dceaa13c2dd9f0b55525ded48b", [:mix], [{:canada, "~> 1.0.1", [hex: :canada, repo: "hexpm", optional: false]}, {:ecto, ">= 1.1.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"}, - "certifi": {:hex, :certifi, "2.5.1", "867ce347f7c7d78563450a18a6a28a8090331e77fa02380b4a21962a65d36ee5", [:rebar3], [{:parse_trans, "~>3.3", [hex: :parse_trans, repo: "hexpm", optional: false]}], "hexpm"}, - "connection": {:hex, :connection, "1.0.4", "a1cae72211f0eef17705aaededacac3eb30e6625b04a6117c1b2db6ace7d5976", [:mix], [], "hexpm"}, - "corsica": {:hex, :corsica, "1.1.3", "5f1de40bc9285753aa03afbdd10c364dac79b2ddbf2ba9c5c9c47b397ec06f40", [:mix], [{:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"}, - "cowboy": {:hex, :cowboy, "2.7.0", "91ed100138a764355f43316b1d23d7ff6bdb0de4ea618cb5d8677c93a7a2f115", [:rebar3], [{:cowlib, "~> 2.8.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "~> 1.7.1", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm"}, - "cowlib": {:hex, :cowlib, "2.8.0", "fd0ff1787db84ac415b8211573e9a30a3ebe71b5cbff7f720089972b2319c8a4", [:rebar3], [], "hexpm"}, - "credo": {:hex, :credo, "1.3.1", "082e8d9268a489becf8e7aa75671a7b9088b1277cd6c1b13f40a55554b3f5126", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm"}, - "credo_envvar": {:hex, :credo_envvar, "0.1.4", "40817c10334e400f031012c0510bfa0d8725c19d867e4ae39cf14f2cbebc3b20", [:mix], [{:credo, "~> 1.0", [hex: :credo, repo: "hexpm", optional: false]}], "hexpm"}, - "csv": {:hex, :csv, "2.3.1", "9ce11eff5a74a07baf3787b2b19dd798724d29a9c3a492a41df39f6af686da0e", [:mix], [{:parallel_stream, "~> 1.0.4", [hex: :parallel_stream, repo: "hexpm", optional: false]}], "hexpm"}, - "dataloader": {:hex, :dataloader, "1.0.7", "58351b335673cf40601429bfed6c11fece6ce7ad169b2ac0f0fe83e716587391", [:mix], [{:ecto, ">= 0.0.0", [hex: :ecto, repo: "hexpm", optional: true]}], "hexpm"}, - "db_connection": {:hex, :db_connection, "2.2.1", "caee17725495f5129cb7faebde001dc4406796f12a62b8949f4ac69315080566", [:mix], [{:connection, "~> 1.0.2", [hex: :connection, repo: "hexpm", optional: false]}], "hexpm"}, - "decimal": {:hex, :decimal, "1.8.1", "a4ef3f5f3428bdbc0d35374029ffcf4ede8533536fa79896dd450168d9acdf3c", [:mix], [], "hexpm"}, - "dialyxir": {:hex, :dialyxir, "1.0.0", "6a1fa629f7881a9f5aaf3a78f094b2a51a0357c843871b8bc98824e7342d00a5", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm"}, - "ecto": {:hex, :ecto, "3.4.0", "a7a83ab8359bf816ce729e5e65981ce25b9fc5adfc89c2ea3980f4fed0bfd7c1", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm"}, - "ecto_sql": {:hex, :ecto_sql, "3.4.1", "3c9136ba138f9b74d31286c73c61232a92bd19385f7c5607bdeb3a4587ef91f5", [:mix], [{:db_connection, "~> 2.2", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.4.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.3.0 or ~> 0.4.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.15.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.0", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm"}, - "erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm"}, - "erlsom": {:hex, :erlsom, "1.5.0", "c5a5cdd0ee0e8dca62bcc4b13ff08da24fdefc16ccd8b25282a2fda2ba1be24a", [:rebar3], [], "hexpm"}, - "ex_brace_expansion": {:hex, :ex_brace_expansion, "0.0.2", "7574fd9497f3f045346dfd9517f10f237f4d39137bf42142b0fbdcd4bacbc6ed", [:mix], [], "hexpm"}, - "ex_minimatch": {:hex, :ex_minimatch, "0.0.1", "4b41726183c104ac227c5996f083ec370f97bd38c2232d74a847888c1bb715bc", [:mix], [{:ex_brace_expansion, "~> 0.0.1", [hex: :ex_brace_expansion, repo: "hexpm", optional: false]}], "hexpm"}, - "excoveralls": {:hex, :excoveralls, "0.12.3", "2142be7cb978a3ae78385487edda6d1aff0e482ffc6123877bb7270a8ffbcfe0", [:mix], [{:hackney, "~> 1.0", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm"}, + "absinthe": {:hex, :absinthe, "1.4.16", "0933e4d9f12652b12115d5709c0293a1bf78a22578032e9ad0dad4efee6b9eb1", [:mix], [{:dataloader, "~> 1.0.0", [hex: :dataloader, repo: "hexpm", optional: true]}, {:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "076b8bd9552f4966ba1242f412f6c439b731169a36a0ddaaffcd3893828f5bf6"}, + "absinthe_error_payload": {:hex, :absinthe_error_payload, "1.0.1", "0696314517f2d42a4e942cdeaf0c42a05db4135c6e9257607b4b13ebc83f894f", [:make, :mix], [{:absinthe, "~> 1.3", [hex: :absinthe, repo: "hexpm", optional: false]}, {:ecto, "~> 3.1", [hex: :ecto, repo: "hexpm", optional: false]}], "hexpm", "03b300138a2fd4b0c012401ce4e1d038f89d22f3aa49f8066c959208902469b7"}, + "absinthe_plug": {:hex, :absinthe_plug, "1.4.7", "939b6b9e1c7abc6b399a5b49faa690a1fbb55b195c670aa35783b14b08ccec7a", [:mix], [{:absinthe, "~> 1.4.11", [hex: :absinthe, repo: "hexpm", optional: false]}, {:plug, "~> 1.3.2 or ~> 1.4", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "c6ecb0e56a963287ac252d0563e5b33b84b300ce8203d3d1410dddb5dc6d08e9"}, + "bamboo": {:hex, :bamboo, "1.3.0", "9ab7c054f1c3435464efcba939396c29c5e1b28f73c34e1f169e0881297a3141", [:mix], [{:hackney, ">= 1.13.0", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "e1197188512d4a4458eaaad9a1659ce9eeb54a1b41574a9cd7507217b33e0f3e"}, + "bamboo_smtp": {:hex, :bamboo_smtp, "2.1.0", "4be58f3c51d9f7875dc169ae58a1d2f08e5b718bf3895f70d130548c0598f422", [:mix], [{:bamboo, "~> 1.2", [hex: :bamboo, repo: "hexpm", optional: false]}, {:gen_smtp, "~> 0.15.0", [hex: :gen_smtp, repo: "hexpm", optional: false]}], "hexpm", "0aad00ef93d0e0c83a0e1ca6998fea070c8a720a990fbda13ce834136215ee49"}, + "bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm", "7af5c7e09fe1d40f76c8e4f9dd2be7cebd83909f31fee7cd0e9eadc567da8353"}, + "canada": {:hex, :canada, "1.0.2", "040e4c47609b0a67d5773ac1fbe5e99f840cef173d69b739beda7c98453e0770", [:mix], [], "hexpm", "4269f74153fe89583fe50bd4d5de57bfe01f31258a6b676d296f3681f1483c68"}, + "canary": {:hex, :canary, "1.1.1", "4138d5e05db8497c477e4af73902eb9ae06e49dceaa13c2dd9f0b55525ded48b", [:mix], [{:canada, "~> 1.0.1", [hex: :canada, repo: "hexpm", optional: false]}, {:ecto, ">= 1.1.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "f348d9848693c830a65b707bba9e4dfdd6434e8c356a8d4477e4535afb0d653b"}, + "certifi": {:hex, :certifi, "2.5.1", "867ce347f7c7d78563450a18a6a28a8090331e77fa02380b4a21962a65d36ee5", [:rebar3], [{:parse_trans, "~>3.3", [hex: :parse_trans, repo: "hexpm", optional: false]}], "hexpm", "805abd97539caf89ec6d4732c91e62ba9da0cda51ac462380bbd28ee697a8c42"}, + "connection": {:hex, :connection, "1.0.4", "a1cae72211f0eef17705aaededacac3eb30e6625b04a6117c1b2db6ace7d5976", [:mix], [], "hexpm", "4a0850c9be22a43af9920a71ab17c051f5f7d45c209e40269a1938832510e4d9"}, + "corsica": {:hex, :corsica, "1.1.2", "5ad8b9dcbeeda4762d78a57c0c8c2f88e1eef8741508517c98cb79e0db1f107d", [:mix], [{:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "b7ae4485dc782266cab8d72fc7bb528f2393a4accf3a944834f86978c85fd8fa"}, + "cowboy": {:hex, :cowboy, "2.7.0", "91ed100138a764355f43316b1d23d7ff6bdb0de4ea618cb5d8677c93a7a2f115", [:rebar3], [{:cowlib, "~> 2.8.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "~> 1.7.1", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "04fd8c6a39edc6aaa9c26123009200fc61f92a3a94f3178c527b70b767c6e605"}, + "cowlib": {:hex, :cowlib, "2.8.0", "fd0ff1787db84ac415b8211573e9a30a3ebe71b5cbff7f720089972b2319c8a4", [:rebar3], [], "hexpm", "79f954a7021b302186a950a32869dbc185523d99d3e44ce430cd1f3289f41ed4"}, + "credo": {:hex, :credo, "1.1.5", "caec7a3cadd2e58609d7ee25b3931b129e739e070539ad1a0cd7efeeb47014f4", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "d0bbd3222607ccaaac5c0340f7f525c627ae4d7aee6c8c8c108922620c5b6446"}, + "credo_envvar": {:hex, :credo_envvar, "0.1.4", "40817c10334e400f031012c0510bfa0d8725c19d867e4ae39cf14f2cbebc3b20", [:mix], [{:credo, "~> 1.0", [hex: :credo, repo: "hexpm", optional: false]}], "hexpm", "5055cdb4bcbaf7d423bc2bb3ac62b4e2d825e2b1e816884c468dee59d0363009"}, + "csv": {:hex, :csv, "2.3.1", "9ce11eff5a74a07baf3787b2b19dd798724d29a9c3a492a41df39f6af686da0e", [:mix], [{:parallel_stream, "~> 1.0.4", [hex: :parallel_stream, repo: "hexpm", optional: false]}], "hexpm", "86626e1c89a4ad9a96d0d9c638f9e88c2346b89b4ba1611988594ebe72b5d5ee"}, + "dataloader": {:hex, :dataloader, "1.0.6", "fb724d6d3fb6acb87d27e3b32dea3a307936ad2d245faf9cf5221d1323d6a4ba", [:mix], [{:ecto, ">= 0.0.0", [hex: :ecto, repo: "hexpm", optional: true]}], "hexpm", "d16b82bc004038243236c73b76bef39be634828a4f4f4f9d637fb498ff886a10"}, + "db_connection": {:hex, :db_connection, "2.1.1", "a51e8a2ee54ef2ae6ec41a668c85787ed40cb8944928c191280fe34c15b76ae5", [:mix], [{:connection, "~> 1.0.2", [hex: :connection, repo: "hexpm", optional: false]}], "hexpm", "5a0e8c1c722dbcd31c0cbd1906b1d1074c863d335c295e4b994849b65a1fbe47"}, + "decimal": {:hex, :decimal, "1.8.0", "ca462e0d885f09a1c5a342dbd7c1dcf27ea63548c65a65e67334f4b61803822e", [:mix], [], "hexpm", "52694ef56e60108e5012f8af9673874c66ed58ac1c4fae9b5b7ded31786663f5"}, + "dialyxir": {:hex, :dialyxir, "0.5.1", "b331b091720fd93e878137add264bac4f644e1ddae07a70bf7062c7862c4b952", [:mix], [], "hexpm", "6c32a70ed5d452c6650916555b1f96c79af5fc4bf286997f8b15f213de786f73"}, + "ecto": {:hex, :ecto, "3.2.5", "76c864b77948a479e18e69cc1d0f0f4ee7cced1148ffe6a093ff91eba644f0b5", [:mix], [{:decimal, "~> 1.6", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "01251d9b28081b7e0af02a1875f9b809b057f064754ca3b274949d5216ea6f5f"}, + "ecto_sql": {:hex, :ecto_sql, "3.2.2", "d10845bc147b9f61ef485cbf0973c0a337237199bd9bd30dd9542db00aadc26b", [:mix], [{:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.2.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.2.0 or ~> 0.3.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.15.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "4a68f58cd12f3df73ea37c253f9b957c81313e532e60191890f71066840c714e"}, + "erlsom": {:hex, :erlsom, "1.5.0", "c5a5cdd0ee0e8dca62bcc4b13ff08da24fdefc16ccd8b25282a2fda2ba1be24a", [:rebar3], [], "hexpm", "55a9dbf9cfa77fcfc108bd8e2c4f9f784dea228a8f4b06ea10b684944946955a"}, + "ex_brace_expansion": {:hex, :ex_brace_expansion, "0.0.2", "7574fd9497f3f045346dfd9517f10f237f4d39137bf42142b0fbdcd4bacbc6ed", [:mix], [], "hexpm", "d7470a00cffe4425f89e83d7288c24b641c3f6cbde136a08089e7420467cd237"}, + "ex_minimatch": {:hex, :ex_minimatch, "0.0.1", "4b41726183c104ac227c5996f083ec370f97bd38c2232d74a847888c1bb715bc", [:mix], [{:ex_brace_expansion, "~> 0.0.1", [hex: :ex_brace_expansion, repo: "hexpm", optional: false]}], "hexpm", "3255bb8496635d3ef5d86ec6829958a3573ff730ca01534b0fead9c2e3af7de4"}, + "excoveralls": {:hex, :excoveralls, "0.12.1", "a553c59f6850d0aff3770e4729515762ba7c8e41eedde03208182a8dc9d0ce07", [:mix], [{:hackney, "~> 1.0", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "5c1f717066a299b1b732249e736c5da96bb4120d1e55dc2e6f442d251e18a812"}, "fast_yaml": {:git, "https://github.com/processone/fast_yaml.git", "e789f68895f71b7ad31057177810ca0161bf790e", [ref: "e789f68895f71b7ad31057177810ca0161bf790e"]}, - "file_system": {:hex, :file_system, "0.2.8", "f632bd287927a1eed2b718f22af727c5aeaccc9a98d8c2bd7bff709e851dc986", [:mix], [], "hexpm"}, - "gen_smtp": {:hex, :gen_smtp, "0.15.0", "9f51960c17769b26833b50df0b96123605a8024738b62db747fece14eb2fbfcc", [:rebar3], [], "hexpm"}, - "gen_stage": {:hex, :gen_stage, "0.14.3", "d0c66f1c87faa301c1a85a809a3ee9097a4264b2edf7644bf5c123237ef732bf", [:mix], [], "hexpm"}, - "gettext": {:hex, :gettext, "0.17.4", "f13088e1ec10ce01665cf25f5ff779e7df3f2dc71b37084976cf89d1aa124d5c", [:mix], [], "hexpm"}, - "hackney": {:hex, :hackney, "1.15.2", "07e33c794f8f8964ee86cebec1a8ed88db5070e52e904b8f12209773c1036085", [:rebar3], [{:certifi, "2.5.1", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "6.0.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~>1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.5", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm"}, - "httpoison": {:hex, :httpoison, "1.6.2", "ace7c8d3a361cebccbed19c283c349b3d26991eff73a1eaaa8abae2e3c8089b6", [:mix], [{:hackney, "~> 1.15 and >= 1.15.2", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm"}, - "idna": {:hex, :idna, "6.0.0", "689c46cbcdf3524c44d5f3dde8001f364cd7608a99556d8fbd8239a5798d4c10", [:rebar3], [{:unicode_util_compat, "0.4.1", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm"}, - "jason": {:hex, :jason, "1.2.0", "10043418c42d2493d0ee212d3fddd25d7ffe484380afad769a0a38795938e448", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm"}, - "jsone": {:hex, :jsone, "1.5.2", "87adea283c9cf24767b4deed44602989a5331156df5d60a2660e9c9114d54046", [:rebar3], [], "hexpm"}, - "meck": {:hex, :meck, "0.8.13", "ffedb39f99b0b99703b8601c6f17c7f76313ee12de6b646e671e3188401f7866", [:rebar3], [], "hexpm"}, - "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm"}, - "mime": {:hex, :mime, "1.3.1", "30ce04ab3175b6ad0bdce0035cba77bba68b813d523d1aac73d9781b4d193cf8", [:mix], [], "hexpm"}, - "mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm"}, - "mochiweb": {:hex, :mochiweb, "2.20.1", "e4dbd0ed716f076366ecf62ada5755a844e1d95c781e8c77df1d4114be868cdf", [:rebar3], [], "hexpm"}, - "mock": {:hex, :mock, "0.3.4", "c5862eb3b8c64237f45f586cf00c9d892ba07bb48305a43319d428ce3c2897dd", [:mix], [{:meck, "~> 0.8.13", [hex: :meck, repo: "hexpm", optional: false]}], "hexpm"}, - "mox": {:hex, :mox, "0.5.2", "55a0a5ba9ccc671518d068c8dddd20eeb436909ea79d1799e2209df7eaa98b6c", [:mix], [], "hexpm"}, - "oauth2": {:hex, :oauth2, "2.0.0", "338382079fe16c514420fa218b0903f8ad2d4bfc0ad0c9f988867dfa246731b0", [:mix], [{:hackney, "~> 1.13", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm"}, - "p1_utils": {:hex, :p1_utils, "1.0.15", "731f76ae1f31f4554afb2ae629cb5589d53bd13efc72b11f5a7c3b1242f91046", [:rebar3], [], "hexpm"}, - "parallel_stream": {:hex, :parallel_stream, "1.0.6", "b967be2b23f0f6787fab7ed681b4c45a215a81481fb62b01a5b750fa8f30f76c", [:mix], [], "hexpm"}, - "parse_trans": {:hex, :parse_trans, "3.3.0", "09765507a3c7590a784615cfd421d101aec25098d50b89d7aa1d66646bc571c1", [:rebar3], [], "hexpm"}, - "phoenix": {:hex, :phoenix, "1.4.16", "2cbbe0c81e6601567c44cc380c33aa42a1372ac1426e3de3d93ac448a7ec4308", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 1.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:plug, "~> 1.8.1 or ~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 1.0 or ~> 2.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm"}, - "phoenix_ecto": {:hex, :phoenix_ecto, "4.1.0", "a044d0756d0464c5a541b4a0bf4bcaf89bffcaf92468862408290682c73ae50d", [:mix], [{:ecto, "~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.9", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"}, - "phoenix_html": {:hex, :phoenix_html, "2.14.1", "7dabafadedb552db142aacbd1f11de1c0bbaa247f90c449ca549d5e30bbc66b4", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"}, - "phoenix_live_reload": {:hex, :phoenix_live_reload, "1.2.1", "274a4b07c4adbdd7785d45a8b0bb57634d0b4f45b18d2c508b26c0344bd59b8f", [:mix], [{:file_system, "~> 0.2.1 or ~> 0.3", [hex: :file_system, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.4", [hex: :phoenix, repo: "hexpm", optional: false]}], "hexpm"}, - "phoenix_pubsub": {:hex, :phoenix_pubsub, "1.1.2", "496c303bdf1b2e98a9d26e89af5bba3ab487ba3a3735f74bf1f4064d2a845a3e", [:mix], [], "hexpm"}, - "php_assoc_map": {:hex, :php_assoc_map, "0.5.2", "8b55283c2ffa762f8703cb30ef40085bf5c06ee08d5a82e38405fa4b949b2a6b", [:mix], [], "hexpm"}, - "plug": {:hex, :plug, "1.10.0", "6508295cbeb4c654860845fb95260737e4a8838d34d115ad76cd487584e2fc4d", [:mix], [{:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm"}, - "plug_assign": {:hex, :plug_assign, "1.0.2", "da31479ac1e048af7c0630fe4b2a6d993b12cdd148405639fc1ad20c38eaf31b", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"}, - "plug_cowboy": {:hex, :plug_cowboy, "2.1.2", "8b0addb5908c5238fac38e442e81b6fcd32788eaa03246b4d55d147c47c5805e", [:mix], [{:cowboy, "~> 2.5", [hex: :cowboy, repo: "hexpm", optional: false]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"}, - "plug_crypto": {:hex, :plug_crypto, "1.1.2", "bdd187572cc26dbd95b87136290425f2b580a116d3fb1f564216918c9730d227", [:mix], [], "hexpm"}, - "postgrex": {:hex, :postgrex, "0.15.3", "5806baa8a19a68c4d07c7a624ccdb9b57e89cbc573f1b98099e3741214746ae4", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm"}, - "ranch": {:hex, :ranch, "1.7.1", "6b1fab51b49196860b733a49c07604465a47bdb78aa10c1c16a3d199f7f8c881", [:rebar3], [], "hexpm"}, - "scrivener": {:hex, :scrivener, "2.7.0", "fa94cdea21fad0649921d8066b1833d18d296217bfdf4a5389a2f45ee857b773", [:mix], [], "hexpm"}, - "scrivener_ecto": {:hex, :scrivener_ecto, "2.3.0", "057f9dd3c77315f0a470263c3565353860d0294404aed611b3524c6df9044189", [:mix], [{:ecto, "~> 3.3", [hex: :ecto, repo: "hexpm", optional: false]}, {:scrivener, "~> 2.4", [hex: :scrivener, repo: "hexpm", optional: false]}], "hexpm"}, - "sentry": {:hex, :sentry, "7.2.4", "b5bc90b594d40c2e653581e797a5fd2fdf994f2568f6bd66b7fa4971598be8d5", [:mix], [{:hackney, "~> 1.8 or 1.6.5", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.3", [hex: :phoenix, repo: "hexpm", optional: true]}, {:plug, "~> 1.6", [hex: :plug, repo: "hexpm", optional: true]}, {:plug_cowboy, "~> 1.0 or ~> 2.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}], "hexpm"}, - "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.5", "6eaf7ad16cb568bb01753dbbd7a95ff8b91c7979482b95f38443fe2c8852a79b", [:make, :mix, :rebar3], [], "hexpm"}, - "telemetry": {:hex, :telemetry, "0.4.1", "ae2718484892448a24470e6aa341bc847c3277bfb8d4e9289f7474d752c09c7f", [:rebar3], [], "hexpm"}, - "ueberauth": {:hex, :ueberauth, "0.6.3", "d42ace28b870e8072cf30e32e385579c57b9cc96ec74fa1f30f30da9c14f3cc0", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"}, - "ueberauth_discord": {:hex, :ueberauth_discord, "0.4.0", "737951cbdeaadc882de33b4058e92afaa3d024c7d1858c3ee0c1826c52401aed", [:mix], [{:oauth2, "~> 0.8", [hex: :oauth2, repo: "hexpm", optional: false]}, {:ueberauth, "~> 0.4", [hex: :ueberauth, repo: "hexpm", optional: false]}], "hexpm"}, - "ueberauth_github": {:hex, :ueberauth_github, "0.8.0", "2216c8cdacee0de6245b422fb397921b64a29416526985304e345dab6a799d17", [:mix], [{:oauth2, "~> 1.0 or ~> 2.0", [hex: :oauth2, repo: "hexpm", optional: false]}, {:ueberauth, "~> 0.6.0", [hex: :ueberauth, repo: "hexpm", optional: false]}], "hexpm"}, - "ueberauth_google": {:hex, :ueberauth_google, "0.9.0", "e098e1d6df647696b858b0289eae7e4dc8c662abee9e309d64bc115192c51bf5", [:mix], [{:oauth2, "~> 1.0 or ~> 2.0", [hex: :oauth2, repo: "hexpm", optional: false]}, {:ueberauth, "~> 0.6.0", [hex: :ueberauth, repo: "hexpm", optional: false]}], "hexpm"}, + "file_system": {:hex, :file_system, "0.2.7", "e6f7f155970975789f26e77b8b8d8ab084c59844d8ecfaf58cbda31c494d14aa", [:mix], [], "hexpm", "b4cfa2d69c7f0b18fd06db222b2398abeef743a72504e6bd7df9c52f171b047f"}, + "gen_smtp": {:hex, :gen_smtp, "0.15.0", "9f51960c17769b26833b50df0b96123605a8024738b62db747fece14eb2fbfcc", [:rebar3], [], "hexpm", "29bd14a88030980849c7ed2447b8db6d6c9278a28b11a44cafe41b791205440f"}, + "gen_stage": {:hex, :gen_stage, "0.14.3", "d0c66f1c87faa301c1a85a809a3ee9097a4264b2edf7644bf5c123237ef732bf", [:mix], [], "hexpm", "8453e2289d94c3199396eb517d65d6715ef26bcae0ee83eb5ff7a84445458d76"}, + "gettext": {:hex, :gettext, "0.17.1", "8baab33482df4907b3eae22f719da492cee3981a26e649b9c2be1c0192616962", [:mix], [], "hexpm", "f7d97341e536f95b96eef2988d6d4230f7262cf239cda0e2e63123ee0b717222"}, + "hackney": {:hex, :hackney, "1.15.2", "07e33c794f8f8964ee86cebec1a8ed88db5070e52e904b8f12209773c1036085", [:rebar3], [{:certifi, "2.5.1", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "6.0.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~>1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.5", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm", "e0100f8ef7d1124222c11ad362c857d3df7cb5f4204054f9f0f4a728666591fc"}, + "httpoison": {:hex, :httpoison, "1.6.2", "ace7c8d3a361cebccbed19c283c349b3d26991eff73a1eaaa8abae2e3c8089b6", [:mix], [{:hackney, "~> 1.15 and >= 1.15.2", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "aa2c74bd271af34239a3948779612f87df2422c2fdcfdbcec28d9c105f0773fe"}, + "idna": {:hex, :idna, "6.0.0", "689c46cbcdf3524c44d5f3dde8001f364cd7608a99556d8fbd8239a5798d4c10", [:rebar3], [{:unicode_util_compat, "0.4.1", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "4bdd305eb64e18b0273864920695cb18d7a2021f31a11b9c5fbcd9a253f936e2"}, + "jason": {:hex, :jason, "1.1.2", "b03dedea67a99223a2eaf9f1264ce37154564de899fd3d8b9a21b1a6fd64afe7", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "fdf843bca858203ae1de16da2ee206f53416bbda5dc8c9e78f43243de4bc3afe"}, + "jsone": {:hex, :jsone, "1.5.2", "87adea283c9cf24767b4deed44602989a5331156df5d60a2660e9c9114d54046", [:rebar3], [], "hexpm", "170c171ce7f6dd70c858065154a3305b8564833c6dcca17e10b676ca31ea976f"}, + "meck": {:hex, :meck, "0.8.13", "ffedb39f99b0b99703b8601c6f17c7f76313ee12de6b646e671e3188401f7866", [:rebar3], [], "hexpm", "d34f013c156db51ad57cc556891b9720e6a1c1df5fe2e15af999c84d6cebeb1a"}, + "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"}, + "mime": {:hex, :mime, "1.3.1", "30ce04ab3175b6ad0bdce0035cba77bba68b813d523d1aac73d9781b4d193cf8", [:mix], [], "hexpm", "6cbe761d6a0ca5a31a0931bf4c63204bceb64538e664a8ecf784a9a6f3b875f1"}, + "mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm", "f278585650aa581986264638ebf698f8bb19df297f66ad91b18910dfc6e19323"}, + "mochiweb": {:hex, :mochiweb, "2.18.0", "eb55f1db3e6e960fac4e6db4e2db9ec3602cc9f30b86cd1481d56545c3145d2e", [:rebar3], [], "hexpm", "b93e2b1e564bdbadfecc297277f9e6d0902da645b417d6c9210f6038ac63489a"}, + "mock": {:hex, :mock, "0.3.3", "42a433794b1291a9cf1525c6d26b38e039e0d3a360732b5e467bfc77ef26c914", [:mix], [{:meck, "~> 0.8.13", [hex: :meck, repo: "hexpm", optional: false]}], "hexpm", "a280d1f7b6f4bbcbd9282616e57502721781c66ee5b540720efabeaf627cc7eb"}, + "mox": {:hex, :mox, "0.5.1", "f86bb36026aac1e6f924a4b6d024b05e9adbed5c63e8daa069bd66fb3292165b", [:mix], [], "hexpm", "052346cf322311c49a0f22789f3698eea030eec09b8c47367f0686ef2634ae14"}, + "oauth2": {:hex, :oauth2, "2.0.0", "338382079fe16c514420fa218b0903f8ad2d4bfc0ad0c9f988867dfa246731b0", [:mix], [{:hackney, "~> 1.13", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "881b8364ac7385f9fddc7949379cbe3f7081da37233a1aa7aab844670a91e7e7"}, + "p1_utils": {:hex, :p1_utils, "1.0.15", "731f76ae1f31f4554afb2ae629cb5589d53bd13efc72b11f5a7c3b1242f91046", [:rebar3], [], "hexpm", "1d308c3f37d7f770fb39abe3b86701b82d54414bc2499d9499edde3cb50bcf19"}, + "parallel_stream": {:hex, :parallel_stream, "1.0.6", "b967be2b23f0f6787fab7ed681b4c45a215a81481fb62b01a5b750fa8f30f76c", [:mix], [], "hexpm", "639b2e8749e11b87b9eb42f2ad325d161c170b39b288ac8d04c4f31f8f0823eb"}, + "parse_trans": {:hex, :parse_trans, "3.3.0", "09765507a3c7590a784615cfd421d101aec25098d50b89d7aa1d66646bc571c1", [:rebar3], [], "hexpm", "17ef63abde837ad30680ea7f857dd9e7ced9476cdd7b0394432af4bfc241b960"}, + "phoenix": {:hex, :phoenix, "1.4.11", "d112c862f6959f98e6e915c3b76c7a87ca3efd075850c8daa7c3c7a609014b0d", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 1.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:plug, "~> 1.8.1 or ~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 1.0 or ~> 2.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "ef19d737ca23b66f7333eaa873cbfc5e6fa6427ef5a0ffd358de1ba8e1a4b2f4"}, + "phoenix_ecto": {:hex, :phoenix_ecto, "4.1.0", "a044d0756d0464c5a541b4a0bf4bcaf89bffcaf92468862408290682c73ae50d", [:mix], [{:ecto, "~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.9", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "c5e666a341ff104d0399d8f0e4ff094559b2fde13a5985d4cb5023b2c2ac558b"}, + "phoenix_html": {:hex, :phoenix_html, "2.13.3", "850e292ff6e204257f5f9c4c54a8cb1f6fbc16ed53d360c2b780a3d0ba333867", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "8b01b3d6d39731ab18aa548d928b5796166d2500755f553725cfe967bafba7d9"}, + "phoenix_live_reload": {:hex, :phoenix_live_reload, "1.2.1", "274a4b07c4adbdd7785d45a8b0bb57634d0b4f45b18d2c508b26c0344bd59b8f", [:mix], [{:file_system, "~> 0.2.1 or ~> 0.3", [hex: :file_system, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.4", [hex: :phoenix, repo: "hexpm", optional: false]}], "hexpm", "41b4103a2fa282cfd747d377233baf213c648fdcc7928f432937676532490eee"}, + "phoenix_pubsub": {:hex, :phoenix_pubsub, "1.1.2", "496c303bdf1b2e98a9d26e89af5bba3ab487ba3a3735f74bf1f4064d2a845a3e", [:mix], [], "hexpm", "1f13f9f0f3e769a667a6b6828d29dec37497a082d195cc52dbef401a9b69bf38"}, + "php_assoc_map": {:hex, :php_assoc_map, "0.5.2", "8b55283c2ffa762f8703cb30ef40085bf5c06ee08d5a82e38405fa4b949b2a6b", [:mix], [], "hexpm", "c95f27f74075cdd5908e4217db96887709334a9fe1da30fc98706c225f3ceafd"}, + "plug": {:hex, :plug, "1.8.3", "12d5f9796dc72e8ac9614e94bda5e51c4c028d0d428e9297650d09e15a684478", [:mix], [{:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "164baaeb382d19beee0ec484492aa82a9c8685770aee33b24ec727a0971b34d0"}, + "plug_assign": {:hex, :plug_assign, "1.0.2", "da31479ac1e048af7c0630fe4b2a6d993b12cdd148405639fc1ad20c38eaf31b", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "341944464b45d44964b2946a0dad8226788481a49c1a95f60e236536b40979ce"}, + "plug_cowboy": {:hex, :plug_cowboy, "2.1.0", "b75768153c3a8a9e8039d4b25bb9b14efbc58e9c4a6e6a270abff1cd30cbe320", [:mix], [{:cowboy, "~> 2.5", [hex: :cowboy, repo: "hexpm", optional: false]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "6cd8ddd1bd1fbfa54d3fc61d4719c2057dae67615395d58d40437a919a46f132"}, + "plug_crypto": {:hex, :plug_crypto, "1.0.0", "18e49317d3fa343f24620ed22795ec29d4a5e602d52d1513ccea0b07d8ea7d4d", [:mix], [], "hexpm", "73c1682f0e414cfb5d9b95c8e8cd6ffcfdae699e3b05e1db744e58b7be857759"}, + "postgrex": {:hex, :postgrex, "0.15.1", "23ce3417de70f4c0e9e7419ad85bdabcc6860a6925fe2c6f3b1b5b1e8e47bf2f", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "12cd418e207b8ed787dfe0f520fccd6c001f58d9108233feae7df36462593d1f"}, + "ranch": {:hex, :ranch, "1.7.1", "6b1fab51b49196860b733a49c07604465a47bdb78aa10c1c16a3d199f7f8c881", [:rebar3], [], "hexpm", "451d8527787df716d99dc36162fca05934915db0b6141bbdac2ea8d3c7afc7d7"}, + "scrivener": {:hex, :scrivener, "2.7.0", "fa94cdea21fad0649921d8066b1833d18d296217bfdf4a5389a2f45ee857b773", [:mix], [], "hexpm", "30da36a427f2519cf75993271fb7c5aad1759682a70f90d880a85c3d743d2c57"}, + "scrivener_ecto": {:hex, :scrivener_ecto, "2.2.0", "53d5f1ba28f35f17891cf526ee102f8f225b7024d1cdaf8984875467158c9c5e", [:mix], [{:ecto, "~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:scrivener, "~> 2.4", [hex: :scrivener, repo: "hexpm", optional: false]}], "hexpm", "3eadfc0a762db4ba8acceee3450404f6ce5e710e52ccf04aae69fca5afe0cd2f"}, + "sentry": {:hex, :sentry, "7.2.0", "37a367ae58b112cc548e17aa8640e5e329eb1d19b71bc368fcb7ccad919d5dac", [:mix], [{:hackney, "~> 1.8 or 1.6.5", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.3", [hex: :phoenix, repo: "hexpm", optional: true]}, {:plug, "~> 1.6", [hex: :plug, repo: "hexpm", optional: true]}, {:plug_cowboy, "~> 1.0 or ~> 2.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}], "hexpm", "0bea1c16bc9d26173847e43535750d0da90a718b27b2781d648980c53ed20baf"}, + "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.5", "6eaf7ad16cb568bb01753dbbd7a95ff8b91c7979482b95f38443fe2c8852a79b", [:make, :mix, :rebar3], [], "hexpm", "13104d7897e38ed7f044c4de953a6c28597d1c952075eb2e328bc6d6f2bfc496"}, + "telemetry": {:hex, :telemetry, "0.4.1", "ae2718484892448a24470e6aa341bc847c3277bfb8d4e9289f7474d752c09c7f", [:rebar3], [], "hexpm", "4738382e36a0a9a2b6e25d67c960e40e1a2c95560b9f936d8e29de8cd858480f"}, + "ueberauth": {:hex, :ueberauth, "0.6.2", "25a31111249d60bad8b65438b2306a4dc91f3208faa62f5a8c33e8713989b2e8", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "db9fbfb5ac707bc4f85a297758406340bf0358b4af737a88113c1a9eee120ac7"}, + "ueberauth_discord": {:hex, :ueberauth_discord, "0.4.0", "737951cbdeaadc882de33b4058e92afaa3d024c7d1858c3ee0c1826c52401aed", [:mix], [{:oauth2, "~> 0.8", [hex: :oauth2, repo: "hexpm", optional: false]}, {:ueberauth, "~> 0.4", [hex: :ueberauth, repo: "hexpm", optional: false]}], "hexpm", "ff2e030ec61551e372cda422cbf694201e88a55d488ded57c66cbbf2d1fe258f"}, + "ueberauth_github": {:hex, :ueberauth_github, "0.8.0", "2216c8cdacee0de6245b422fb397921b64a29416526985304e345dab6a799d17", [:mix], [{:oauth2, "~> 1.0 or ~> 2.0", [hex: :oauth2, repo: "hexpm", optional: false]}, {:ueberauth, "~> 0.6.0", [hex: :ueberauth, repo: "hexpm", optional: false]}], "hexpm", "b65ccc001a7b0719ba069452f3333d68891f4613ae787a340cce31e2a43307a3"}, + "ueberauth_google": {:hex, :ueberauth_google, "0.9.0", "e098e1d6df647696b858b0289eae7e4dc8c662abee9e309d64bc115192c51bf5", [:mix], [{:oauth2, "~> 1.0 or ~> 2.0", [hex: :oauth2, repo: "hexpm", optional: false]}, {:ueberauth, "~> 0.6.0", [hex: :ueberauth, repo: "hexpm", optional: false]}], "hexpm", "5453ba074df7ee14fb5b121bb04a64cda5266cd23b28af8a2fdf02dd40959ab4"}, "ueberauth_slack": {:git, "https://github.com/ueberauth/ueberauth_slack.git", "525594c870f959aba67acc759d5c1a588ee75e9e", [ref: "525594c870f959ab"]}, - "unicode_util_compat": {:hex, :unicode_util_compat, "0.4.1", "d869e4c68901dd9531385bb0c8c40444ebf624e60b6962d95952775cac5e90cd", [:rebar3], [], "hexpm"}, - "xml_builder": {:hex, :xml_builder, "2.1.2", "90cb9ad382958934c78c6ddfbe6d385a8ce147d84b61cbfa83ec93a169d0feab", [:mix], [], "hexpm"}, + "unicode_util_compat": {:hex, :unicode_util_compat, "0.4.1", "d869e4c68901dd9531385bb0c8c40444ebf624e60b6962d95952775cac5e90cd", [:rebar3], [], "hexpm", "1d1848c40487cdb0b30e8ed975e34e025860c02e419cb615d255849f3427439d"}, + "xml_builder": {:hex, :xml_builder, "2.1.2", "90cb9ad382958934c78c6ddfbe6d385a8ce147d84b61cbfa83ec93a169d0feab", [:mix], [], "hexpm", "b89046041da2fbc1d51d31493ba31b9d5fc6223c93384bf513a1a9e1df9ec081"}, } diff --git a/package-lock.json b/package-lock.json index fc9c35a7..0909398c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -107,6 +107,12 @@ "to-fast-properties": "^2.0.0" } }, + "@ember-data/rfc395-data": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/@ember-data/rfc395-data/-/rfc395-data-0.0.4.tgz", + "integrity": "sha512-tGRdvgC9/QMQSuSuJV45xoyhI0Pzjm7A9o/MVVA3HakXIImJbbzx/k/6dO9CUEQXIyS2y0fW6C1XaYOG7rY0FQ==", + "dev": true + }, "@glimmer/interfaces": { "version": "0.44.0", "resolved": "https://registry.npmjs.org/@glimmer/interfaces/-/interfaces-0.44.0.tgz", @@ -147,6 +153,12 @@ "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==", "dev": true }, + "@types/eslint-visitor-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", + "integrity": "sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag==", + "dev": true + }, "@types/events": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz", @@ -164,6 +176,12 @@ "@types/node": "*" } }, + "@types/json-schema": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.4.tgz", + "integrity": "sha512-8+KAKzEvSUdeo+kmqnKrqgeE+LcA0tjYWFY7RPProVYwnqDjukzO+3b6dLD56rYX5TdWejnEOLJYOIeh4CXKuA==", + "dev": true + }, "@types/minimatch": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", @@ -176,64 +194,240 @@ "integrity": "sha512-u/SJDyXwuihpwjXy7hOOghagLEV1KdAST6syfnOk6QZAMzZuWZqXy5aYYZbh8Jdpd4escVFP0MvftHNDb9pruA==", "dev": true }, - "acorn": { - "version": "5.7.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", - "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==", - "dev": true - }, - "acorn-jsx": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", - "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", + "@typescript-eslint/eslint-plugin": { + "version": "2.25.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.25.0.tgz", + "integrity": "sha512-W2YyMtjmlrOjtXc+FtTelVs9OhuR6OlYc4XKIslJ8PUJOqgYYAPRJhAqkYRQo3G4sjvG8jSodsNycEn4W2gHUw==", "dev": true, "requires": { - "acorn": "^3.0.4" + "@typescript-eslint/experimental-utils": "2.25.0", + "functional-red-black-tree": "^1.0.1", + "regexpp": "^3.0.0", + "tsutils": "^3.17.1" }, "dependencies": { - "acorn": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", - "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", + "@typescript-eslint/experimental-utils": { + "version": "2.25.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-2.25.0.tgz", + "integrity": "sha512-0IZ4ZR5QkFYbaJk+8eJ2kYeA+1tzOE1sBjbwwtSV85oNWYUBep+EyhlZ7DLUCyhMUGuJpcCCFL0fDtYAP1zMZw==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.3", + "@typescript-eslint/typescript-estree": "2.25.0", + "eslint-scope": "^5.0.0", + "eslint-utils": "^2.0.0" + } + }, + "@typescript-eslint/typescript-estree": { + "version": "2.25.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-2.25.0.tgz", + "integrity": "sha512-VUksmx5lDxSi6GfmwSK7SSoIKSw9anukWWNitQPqt58LuYrKalzsgeuignbqnB+rK/xxGlSsCy8lYnwFfB6YJg==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "eslint-visitor-keys": "^1.1.0", + "glob": "^7.1.6", + "is-glob": "^4.0.1", + "lodash": "^4.17.15", + "semver": "^6.3.0", + "tsutils": "^3.17.1" + } + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "eslint-scope": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.0.0.tgz", + "integrity": "sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "eslint-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.0.0.tgz", + "integrity": "sha512-0HCPuJv+7Wv1bACm8y5/ECVfYdfsAm9xmVb7saeFlxjPYALefjhbYoCkBjPdPzGH8wWyTpAez82Fh3VKYEZ8OA==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + } + }, + "eslint-visitor-keys": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz", + "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==", + "dev": true + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } + } + }, + "@typescript-eslint/experimental-utils": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-2.16.0.tgz", + "integrity": "sha512-bXTmAztXpqxliDKZgvWkl+5dHeRN+jqXVZ16peKKFzSXVzT6mz8kgBpHiVzEKO2NZ8OCU7dG61K9sRS/SkUUFQ==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.3", + "@typescript-eslint/typescript-estree": "2.16.0", + "eslint-scope": "^5.0.0" + }, + "dependencies": { + "eslint-scope": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.0.0.tgz", + "integrity": "sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + } + } + }, + "@typescript-eslint/parser": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-2.16.0.tgz", + "integrity": "sha512-+w8dMaYETM9v6il1yYYkApMSiwgnqXWJbXrA94LAWN603vXHACsZTirJduyeBOJjA9wT6xuXe5zZ1iCUzoxCfw==", + "dev": true, + "requires": { + "@types/eslint-visitor-keys": "^1.0.0", + "@typescript-eslint/experimental-utils": "2.16.0", + "@typescript-eslint/typescript-estree": "2.16.0", + "eslint-visitor-keys": "^1.1.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz", + "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==", "dev": true } } }, - "ajv": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", - "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "@typescript-eslint/typescript-estree": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-2.16.0.tgz", + "integrity": "sha512-hyrCYjFHISos68Bk5KjUAXw0pP/455qq9nxqB1KkT67Pxjcfw+r6Yhcmqnp8etFL45UexCHUMrADHH7dI/m2WQ==", "dev": true, "requires": { - "co": "^4.6.0", - "fast-deep-equal": "^1.0.0", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.3.0" + "debug": "^4.1.1", + "eslint-visitor-keys": "^1.1.0", + "glob": "^7.1.6", + "is-glob": "^4.0.1", + "lodash": "^4.17.15", + "semver": "^6.3.0", + "tsutils": "^3.17.1" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "eslint-visitor-keys": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz", + "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==", + "dev": true + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "tsutils": { + "version": "3.17.1", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.17.1.tgz", + "integrity": "sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } + } } }, - "ajv-keywords": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz", - "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=", + "acorn": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.0.tgz", + "integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==", "dev": true }, + "acorn-jsx": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.1.0.tgz", + "integrity": "sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw==", + "dev": true + }, + "ajv": { + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", + "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", + "dev": true, + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, "ansi-escapes": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", - "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", - "dev": true + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.0.tgz", + "integrity": "sha512-EiYhwo0v255HUL6eDyuLrXEkTi7WwVCLAw+SeOQ7M7qdun1z1pum4DEm/nuqIVbPvi9RPPc9k9LbyBv6H0DwVg==", + "dev": true, + "requires": { + "type-fest": "^0.8.1" + } }, "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", "dev": true }, "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } }, "argparse": { "version": "1.0.10", @@ -289,47 +483,18 @@ "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", "dev": true }, + "astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "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 }, - "babel-code-frame": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", - "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "esutils": "^2.0.2", - "js-tokens": "^3.0.2" - }, - "dependencies": { - "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" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - } - } - }, "babel-eslint": { "version": "8.2.3", "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-8.2.3.tgz", @@ -450,18 +615,6 @@ } } }, - "buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", - "dev": true - }, - "builtin-modules": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", - "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", - "dev": true - }, "cache-base": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", @@ -485,19 +638,10 @@ "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=", "dev": true }, - "caller-path": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", - "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", - "dev": true, - "requires": { - "callsites": "^0.2.0" - } - }, "callsites": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", - "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true }, "chalk": { @@ -532,15 +676,9 @@ } }, "chardet": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", - "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=", - "dev": true - }, - "circular-json": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", - "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", "dev": true }, "class-utils": { @@ -567,12 +705,12 @@ } }, "cli-cursor": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", - "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", "dev": true, "requires": { - "restore-cursor": "^2.0.0" + "restore-cursor": "^3.1.0" } }, "cli-width": { @@ -581,12 +719,6 @@ "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", "dev": true }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", - "dev": true - }, "collection-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", @@ -612,12 +744,6 @@ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", "dev": true }, - "commander": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz", - "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==", - "dev": true - }, "component-emitter": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", @@ -630,39 +756,31 @@ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true }, - "concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } - }, "copy-descriptor": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", "dev": true }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true - }, "cross-spawn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", "dev": true, "requires": { - "lru-cache": "^4.0.1", + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", "shebang-command": "^1.2.0", "which": "^1.2.9" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } } }, "debug": { @@ -727,12 +845,6 @@ } } }, - "diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", - "dev": true - }, "dir-glob": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.2.tgz", @@ -743,18 +855,36 @@ } }, "doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", "dev": true, "requires": { "esutils": "^2.0.2" } }, + "dot-case": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.3.tgz", + "integrity": "sha512-7hwEmg6RiSQfm/GwPL4AAWXKy3YNNZA3oFv2Pdiey0mwkRCPZ9x6SZbkLcn8Ma5PYeVokzoD4Twv2n7LKp5WeA==", + "dev": true, + "requires": { + "no-case": "^3.0.3", + "tslib": "^1.10.0" + }, + "dependencies": { + "tslib": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==", + "dev": true + } + } + }, "ember-rfc176-data": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/ember-rfc176-data/-/ember-rfc176-data-0.2.7.tgz", - "integrity": "sha512-pJE2w+sI22UDsYmudI4nCp3WcImpUzXwe9qHfpOcEu3yM/HD1nGpDRt6kZD0KUnDmqkLeik/nYyzEwN/NU6xxA==", + "version": "0.3.12", + "resolved": "https://registry.npmjs.org/ember-rfc176-data/-/ember-rfc176-data-0.3.12.tgz", + "integrity": "sha512-g9HeZj/gU5bfIIrGXkP7MhS2b3Vu5DfNUrYr14hy99TgIvtZETO+96QF4WOEUXGjIJdfTRjerVnQlqngPQSv1g==", "dev": true }, "ember-template-lint": { @@ -771,6 +901,12 @@ "strip-bom": "^3.0.0" } }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", @@ -778,69 +914,178 @@ "dev": true }, "eslint": { - "version": "4.19.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.19.0.tgz", - "integrity": "sha512-r83L5CuqaocDvfwdojbz68b6tCUk8KJkqfppO+gmSAQqYCzTr0bCSMu6A6yFCLKG65j5eKcKUw4Cw4Yl4gfWkg==", + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.8.0.tgz", + "integrity": "sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig==", "dev": true, "requires": { - "ajv": "^5.3.0", - "babel-code-frame": "^6.22.0", + "@babel/code-frame": "^7.0.0", + "ajv": "^6.10.0", "chalk": "^2.1.0", - "concat-stream": "^1.6.0", - "cross-spawn": "^5.1.0", - "debug": "^3.1.0", - "doctrine": "^2.1.0", - "eslint-scope": "^3.7.1", - "eslint-visitor-keys": "^1.0.0", - "espree": "^3.5.4", - "esquery": "^1.0.0", + "cross-spawn": "^6.0.5", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "eslint-scope": "^5.0.0", + "eslint-utils": "^1.4.3", + "eslint-visitor-keys": "^1.1.0", + "espree": "^6.1.2", + "esquery": "^1.0.1", "esutils": "^2.0.2", - "file-entry-cache": "^2.0.0", + "file-entry-cache": "^5.0.1", "functional-red-black-tree": "^1.0.1", - "glob": "^7.1.2", - "globals": "^11.0.1", - "ignore": "^3.3.3", + "glob-parent": "^5.0.0", + "globals": "^12.1.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", - "inquirer": "^3.0.6", - "is-resolvable": "^1.0.0", - "js-yaml": "^3.9.1", + "inquirer": "^7.0.0", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.3.0", - "lodash": "^4.17.4", - "minimatch": "^3.0.2", + "lodash": "^4.17.14", + "minimatch": "^3.0.4", "mkdirp": "^0.5.1", "natural-compare": "^1.4.0", - "optionator": "^0.8.2", - "path-is-inside": "^1.0.2", - "pluralize": "^7.0.0", + "optionator": "^0.8.3", "progress": "^2.0.0", - "regexpp": "^1.0.1", - "require-uncached": "^1.0.3", - "semver": "^5.3.0", - "strip-ansi": "^4.0.0", - "strip-json-comments": "~2.0.1", - "table": "4.0.2", - "text-table": "~0.2.0" + "regexpp": "^2.0.1", + "semver": "^6.1.2", + "strip-ansi": "^5.2.0", + "strip-json-comments": "^3.0.1", + "table": "^5.2.3", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", + "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", + "dev": true, + "requires": { + "@babel/highlight": "^7.8.3" + } + }, + "@babel/highlight": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz", + "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "eslint-scope": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.0.0.tgz", + "integrity": "sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "eslint-visitor-keys": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz", + "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==", + "dev": true + }, + "glob-parent": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.0.tgz", + "integrity": "sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "globals": { + "version": "12.3.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-12.3.0.tgz", + "integrity": "sha512-wAfjdLgFsPZsklLJvOBUBmzYE8/CwhEqSBEMRXA3qxIiNtyqvjYurAtIfDh6chlEPUfmTY3MnZh5Hfh4q0UlIw==", + "dev": true, + "requires": { + "type-fest": "^0.8.1" + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "regexpp": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", + "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", + "dev": true + } } }, "eslint-config-prettier": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-2.9.0.tgz", - "integrity": "sha512-ag8YEyBXsm3nmOv1Hz991VtNNDMRa+MNy8cY47Pl4bw6iuzqKbJajXdqUpiw13STdLLrznxgm1hj9NhxeOYq0A==", + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-6.9.0.tgz", + "integrity": "sha512-k4E14HBtcLv0uqThaI6I/n1LEqROp8XaPu6SO9Z32u5NlGRC07Enu1Bh2KEFw4FNHbekH8yzbIU9kUGxbiGmCA==", "dev": true, "requires": { - "get-stdin": "^5.0.1" + "get-stdin": "^6.0.0" } }, + "eslint-config-typestrict": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-typestrict/-/eslint-config-typestrict-1.0.0.tgz", + "integrity": "sha512-mC3wdJwrYp9O27w4oDU9q0xKdqivSBXSltc31hk8zsiSyDgOwadSEvFPeRjS8uxl9qKUhgS+8MAcX/SJ52fWpA==", + "dev": true + }, "eslint-plugin-ember": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-ember/-/eslint-plugin-ember-5.1.0.tgz", - "integrity": "sha512-n7U3Jic4WSHziXs+Gf+41dyNr4KzKBH+Cs95ahAmvXQOMbvElpk/YjdVE0NThr+SXXZYGaXkqP/7IDVhFedieg==", + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-ember/-/eslint-plugin-ember-7.7.2.tgz", + "integrity": "sha512-Ua7+xePz8m0BrqSHfYibkRXWQMMb5RBsH9ohZy2a7ri+s6+UQre9x3BxPpawCLZMzQzIG4vQh93YiVGCSv3XYA==", "dev": true, "requires": { - "ember-rfc176-data": "^0.2.7", - "require-folder-tree": "^1.4.5", - "snake-case": "^2.1.0" + "@ember-data/rfc395-data": "^0.0.4", + "ember-rfc176-data": "^0.3.12", + "snake-case": "^3.0.2" + } + }, + "eslint-plugin-es": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-3.0.0.tgz", + "integrity": "sha512-6/Jb/J/ZvSebydwbBJO1R9E5ky7YeElfK56Veh7e4QGFHCXoIXGH9HhVz+ibJLM3XJ1XjP+T7rKBLUa/Y7eIng==", + "dev": true, + "requires": { + "eslint-utils": "^2.0.0", + "regexpp": "^3.0.0" + }, + "dependencies": { + "eslint-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.0.0.tgz", + "integrity": "sha512-0HCPuJv+7Wv1bACm8y5/ECVfYdfsAm9xmVb7saeFlxjPYALefjhbYoCkBjPdPzGH8wWyTpAez82Fh3VKYEZ8OA==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + } + }, + "eslint-visitor-keys": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz", + "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==", + "dev": true + } } }, "eslint-plugin-mirego": { @@ -849,6 +1094,58 @@ "integrity": "sha512-15W3oqjCruSHu1i26e5Hf1AIo4A0rj+NlmUIeIN1BbGiku7eIH45qDWKDfXt3ARlhXsg1r1oinzoo8GzQWAc6Q==", "dev": true }, + "eslint-plugin-node": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-11.0.0.tgz", + "integrity": "sha512-chUs/NVID+sknFiJzxoN9lM7uKSOEta8GC8365hw1nDfwIPIjjpRSwwPvQanWv8dt/pDe9EV4anmVSwdiSndNg==", + "dev": true, + "requires": { + "eslint-plugin-es": "^3.0.0", + "eslint-utils": "^2.0.0", + "ignore": "^5.1.1", + "minimatch": "^3.0.4", + "resolve": "^1.10.1", + "semver": "^6.1.0" + }, + "dependencies": { + "eslint-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.0.0.tgz", + "integrity": "sha512-0HCPuJv+7Wv1bACm8y5/ECVfYdfsAm9xmVb7saeFlxjPYALefjhbYoCkBjPdPzGH8wWyTpAez82Fh3VKYEZ8OA==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + } + }, + "eslint-visitor-keys": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz", + "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==", + "dev": true + }, + "ignore": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.4.tgz", + "integrity": "sha512-MzbUSahkTW1u7JpKKjY7LCARd1fU5W2rLdxlM4kdkayuCwZImjkpluF9CM1aLewYJguPDqewLam18Y6AU69A8A==", + "dev": true + }, + "resolve": { + "version": "1.14.2", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.14.2.tgz", + "integrity": "sha512-EjlOBLBO1kxsUxsKjLt7TAECyKW6fOh1VRkykQkKGzcBbjjPIxBqGh0jf7GJ3k/f5mxMqW3htMD3WdTUVtW8HQ==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + } + } + }, + "eslint-plugin-sonarjs": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-sonarjs/-/eslint-plugin-sonarjs-0.5.0.tgz", + "integrity": "sha512-XW5MnzlRjhXpIdbULC/qAdJYHWw3rRLws/DyawdlPU/IdVr9AmRK1r2LaCvabwKOAW2XYYSo3kDX58E4MrB7PQ==", + "dev": true + }, "eslint-scope": { "version": "3.7.3", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.3.tgz", @@ -859,6 +1156,23 @@ "estraverse": "^4.1.1" } }, + "eslint-utils": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz", + "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz", + "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==", + "dev": true + } + } + }, "eslint-visitor-keys": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", @@ -866,13 +1180,22 @@ "dev": true }, "espree": { - "version": "3.5.4", - "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz", - "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==", + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/espree/-/espree-6.1.2.tgz", + "integrity": "sha512-2iUPuuPP+yW1PZaMSDM9eyVf8D5P0Hi8h83YtZ5bPc/zHYjII5khoixIUTMO794NOY8F/ThF1Bo8ncZILarUTA==", "dev": true, "requires": { - "acorn": "^5.5.0", - "acorn-jsx": "^3.0.0" + "acorn": "^7.1.0", + "acorn-jsx": "^5.1.0", + "eslint-visitor-keys": "^1.1.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz", + "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==", + "dev": true + } } }, "esprima": { @@ -983,13 +1306,13 @@ } }, "external-editor": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", - "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", "dev": true, "requires": { - "chardet": "^0.4.0", - "iconv-lite": "^0.4.17", + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", "tmp": "^0.0.33" } }, @@ -1059,9 +1382,9 @@ } }, "fast-deep-equal": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", - "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", "dev": true }, "fast-glob": { @@ -1079,9 +1402,9 @@ } }, "fast-json-stable-stringify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "dev": true }, "fast-levenshtein": { @@ -1091,22 +1414,21 @@ "dev": true }, "figures": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", - "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.1.0.tgz", + "integrity": "sha512-ravh8VRXqHuMvZt/d8GblBeqDMkdJMBdv/2KntFH+ra5MXkO7nxNKpzQ3n6QD/2da1kH0aWmNISdvhM7gl2gVg==", "dev": true, "requires": { "escape-string-regexp": "^1.0.5" } }, "file-entry-cache": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", - "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", + "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", "dev": true, "requires": { - "flat-cache": "^1.2.1", - "object-assign": "^4.0.1" + "flat-cache": "^2.0.1" } }, "fill-range": { @@ -1133,17 +1455,22 @@ } }, "flat-cache": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.4.tgz", - "integrity": "sha512-VwyB3Lkgacfik2vhqR4uv2rvebqmDvFu4jlN/C1RzWoJEo8I7z4Q404oiqYCkq41mni8EzQnm95emU9seckwtg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", + "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", "dev": true, "requires": { - "circular-json": "^0.3.1", - "graceful-fs": "^4.1.2", - "rimraf": "~2.6.2", - "write": "^0.2.1" + "flatted": "^2.0.0", + "rimraf": "2.6.3", + "write": "1.0.3" } }, + "flatted": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.1.tgz", + "integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==", + "dev": true + }, "for-in": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", @@ -1172,9 +1499,9 @@ "dev": true }, "get-stdin": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-5.0.1.tgz", - "integrity": "sha1-Ei4WFZHiH/TFJTAwVpPyDmOTo5g=", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz", + "integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==", "dev": true }, "get-value": { @@ -1254,12 +1581,6 @@ } } }, - "graceful-fs": { - "version": "4.1.15", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", - "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", - "dev": true - }, "handlebars": { "version": "4.5.3", "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.5.3.tgz", @@ -1280,15 +1601,6 @@ } } }, - "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", @@ -1337,11 +1649,21 @@ } }, "ignore": { - "version": "3.3.10", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", - "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", "dev": true }, + "import-fresh": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz", + "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", @@ -1365,24 +1687,23 @@ "dev": true }, "inquirer": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", - "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.0.3.tgz", + "integrity": "sha512-+OiOVeVydu4hnCGLCSX+wedovR/Yzskv9BFqUNNKq9uU2qg7LCcCo3R86S2E7WLo0y/x2pnEZfZe1CoYnORUAw==", "dev": true, "requires": { - "ansi-escapes": "^3.0.0", - "chalk": "^2.0.0", - "cli-cursor": "^2.1.0", + "ansi-escapes": "^4.2.1", + "chalk": "^2.4.2", + "cli-cursor": "^3.1.0", "cli-width": "^2.0.0", - "external-editor": "^2.0.4", - "figures": "^2.0.0", - "lodash": "^4.3.0", - "mute-stream": "0.0.7", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.15", + "mute-stream": "0.0.8", "run-async": "^2.2.0", - "rx-lite": "^4.0.8", - "rx-lite-aggregates": "^4.0.8", - "string-width": "^2.1.0", - "strip-ansi": "^4.0.0", + "rxjs": "^6.5.3", + "string-width": "^4.1.0", + "strip-ansi": "^5.1.0", "through": "^2.3.6" } }, @@ -1473,9 +1794,9 @@ "dev": true }, "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", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true }, "is-glob": { @@ -1522,12 +1843,6 @@ "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", "dev": true }, - "is-resolvable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", - "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", - "dev": true - }, "is-windows": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", @@ -1575,9 +1890,9 @@ "dev": true }, "json-schema-traverse": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", - "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true }, "json-stable-stringify-without-jsonify": { @@ -1618,19 +1933,20 @@ } }, "lower-case": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz", - "integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw=", - "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==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.1.tgz", + "integrity": "sha512-LiWgfDLLb1dwbFQZsSglpRj+1ctGnayXz3Uv0/WO8n558JycT5fg6zkNcnW0G68Nn0aEldTFeEfmjCfmqry/rQ==", "dev": true, "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" + "tslib": "^1.10.0" + }, + "dependencies": { + "tslib": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==", + "dev": true + } } }, "map-cache": { @@ -1676,9 +1992,9 @@ } }, "mimic-fn": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", - "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "dev": true }, "minimatch": { @@ -1733,9 +2049,9 @@ "dev": true }, "mute-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", - "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", "dev": true }, "nanomatch": { @@ -1769,21 +2085,30 @@ "integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==", "dev": true }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, "no-case": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz", - "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.3.tgz", + "integrity": "sha512-ehY/mVQCf9BL0gKfsJBvFJen+1V//U+0HQMPrWct40ixE4jnv0bfvxDbWtAHL9EcaPEOJHVVYKoQn1TlZUB8Tw==", "dev": true, "requires": { - "lower-case": "^1.1.1" + "lower-case": "^2.0.1", + "tslib": "^1.10.0" + }, + "dependencies": { + "tslib": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==", + "dev": true + } } }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true - }, "object-copy": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", @@ -1843,12 +2168,12 @@ } }, "onetime": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", - "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.0.tgz", + "integrity": "sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q==", "dev": true, "requires": { - "mimic-fn": "^1.0.0" + "mimic-fn": "^2.1.0" } }, "optimist": { @@ -1870,17 +2195,17 @@ } }, "optionator": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", - "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", "dev": true, "requires": { "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.4", + "fast-levenshtein": "~2.0.6", "levn": "~0.3.0", "prelude-ls": "~1.1.2", "type-check": "~0.3.2", - "wordwrap": "~1.0.0" + "word-wrap": "~1.2.3" } }, "os-tmpdir": { @@ -1889,6 +2214,15 @@ "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "dev": true }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, "pascalcase": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", @@ -1907,10 +2241,10 @@ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true }, - "path-is-inside": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", "dev": true }, "path-parse": { @@ -1942,12 +2276,6 @@ "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", "dev": true }, - "pluralize": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", - "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==", - "dev": true - }, "posix-character-classes": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", @@ -1961,15 +2289,9 @@ "dev": true }, "prettier": { - "version": "1.16.4", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.16.4.tgz", - "integrity": "sha512-ZzWuos7TI5CKUeQAtFd6Zhm2s6EpAD/ZLApIhsF9pRvRtM1RFo61dM/4MSRUA0SuLugA/zgrZD8m0BaY46Og7g==", - "dev": true - }, - "process-nextick-args": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.0.2.tgz", + "integrity": "sha512-5xJQIPT8BraI7ZnaDwSbu5zLrB6vvi8hVV58yHQ+QK64qrY40dULy0HSRlQ2/2IdzeBpjhDkqdcFBnFeDEMVdg==", "dev": true }, "progress": { @@ -1978,27 +2300,12 @@ "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", "dev": true }, - "pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", "dev": true }, - "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, "regex-not": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", @@ -2010,9 +2317,9 @@ } }, "regexpp": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-1.1.0.tgz", - "integrity": "sha512-LOPw8FpgdQF9etWMaAfG/WRthIdXJGYp4mJ2Jgn/2lpkbod9jPn0t9UqN7AxBOKNfzRbYyVfgc7Vk4t/MpnXgw==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.0.0.tgz", + "integrity": "sha512-Z+hNr7RAVWxznLPuA7DIh8UNX1j9CDrUQxskw9IrBE1Dxue2lyXT+shqEIeLUjrokxIP8CMy1WkjgG3rTsd5/g==", "dev": true }, "repeat-element": { @@ -2027,25 +2334,6 @@ "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", "dev": true }, - "require-folder-tree": { - "version": "1.4.7", - "resolved": "https://registry.npmjs.org/require-folder-tree/-/require-folder-tree-1.4.7.tgz", - "integrity": "sha512-8nkJYEUuMzYdWQcNdMBe04jloJc5RQ6gnHJC7+aHYFFbkqljsxfpPGSy+9NBtw5rSRcXI/2khC+V48atKd0bUQ==", - "dev": true, - "requires": { - "lodash": "^4.17.11" - } - }, - "require-uncached": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", - "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", - "dev": true, - "requires": { - "caller-path": "^0.1.0", - "resolve-from": "^1.0.0" - } - }, "resolve": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.10.0.tgz", @@ -2056,9 +2344,9 @@ } }, "resolve-from": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", - "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true }, "resolve-url": { @@ -2068,12 +2356,12 @@ "dev": true }, "restore-cursor": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", - "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", "dev": true, "requires": { - "onetime": "^2.0.0", + "onetime": "^5.1.0", "signal-exit": "^3.0.2" } }, @@ -2101,27 +2389,15 @@ "is-promise": "^2.1.0" } }, - "rx-lite": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", - "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=", - "dev": true - }, - "rx-lite-aggregates": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", - "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", + "rxjs": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.4.tgz", + "integrity": "sha512-naMQXcgEo3csAEGvw/NydRA0fuS2nDZJiw1YUWFKU7aPPAPGZEsD4Iimit96qwCieH6y614MCLYwdkrWx7z/7Q==", "dev": true, "requires": { - "rx-lite": "*" + "tslib": "^1.9.0" } }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, "safe-regex": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", @@ -2138,9 +2414,9 @@ "dev": true }, "semver": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", - "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true }, "set-value": { @@ -2200,21 +2476,40 @@ "dev": true }, "slice-ansi": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", - "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", + "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", "dev": true, "requires": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", "is-fullwidth-code-point": "^2.0.0" + }, + "dependencies": { + "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", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + } } }, "snake-case": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-2.1.0.tgz", - "integrity": "sha1-Qb2xtz8w7GagTU4srRt2OH1NbZ8=", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.3.tgz", + "integrity": "sha512-WM1sIXEO+rsAHBKjGf/6R1HBBcgbncKS08d2Aqec/mrDSpU80SiOU41hO7ny6DToHSyrlwTYzQBIK1FPSx4Y3Q==", "dev": true, "requires": { - "no-case": "^2.2.0" + "dot-case": "^3.0.3", + "tslib": "^1.10.0" + }, + "dependencies": { + "tslib": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==", + "dev": true + } } }, "snapdragon": { @@ -2401,37 +2696,40 @@ } }, "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", "dev": true, "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + } } }, "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", "dev": true, "requires": { - "ansi-regex": "^3.0.0" + "ansi-regex": "^4.1.0" }, "dependencies": { "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", "dev": true } } @@ -2443,29 +2741,46 @@ "dev": true }, "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", - "dev": true - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.0.1.tgz", + "integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==", "dev": true }, "table": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz", - "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==", + "version": "5.4.6", + "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", + "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", "dev": true, "requires": { - "ajv": "^5.2.3", - "ajv-keywords": "^2.1.0", - "chalk": "^2.1.0", - "lodash": "^4.17.4", - "slice-ansi": "1.0.0", - "string-width": "^2.1.1" + "ajv": "^6.10.2", + "lodash": "^4.17.14", + "slice-ansi": "^2.1.0", + "string-width": "^3.0.0" + }, + "dependencies": { + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "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", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + } } }, "text-table": { @@ -2549,36 +2864,10 @@ "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==", "dev": true }, - "tslint": { - "version": "5.12.1", - "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.12.1.tgz", - "integrity": "sha512-sfodBHOucFg6egff8d1BvuofoOQ/nOeYNfbp7LDlKBcLNrL3lmS5zoiDGyOMdT7YsEXAwWpTdAHwOGOc8eRZAw==", - "dev": true, - "requires": { - "babel-code-frame": "^6.22.0", - "builtin-modules": "^1.1.1", - "chalk": "^2.3.0", - "commander": "^2.12.1", - "diff": "^3.2.0", - "glob": "^7.1.1", - "js-yaml": "^3.7.0", - "minimatch": "^3.0.4", - "resolve": "^1.3.2", - "semver": "^5.3.0", - "tslib": "^1.8.0", - "tsutils": "^2.27.2" - } - }, - "tslint-config-prettier": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/tslint-config-prettier/-/tslint-config-prettier-1.17.0.tgz", - "integrity": "sha512-NKWNkThwqE4Snn4Cm6SZB7lV5RMDDFsBwz6fWUkTxOKGjMx8ycOHnjIbhn7dZd5XmssW3CwqUjlANR6EhP9YQw==", - "dev": true - }, "tsutils": { - "version": "2.29.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", - "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", + "version": "3.17.1", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.17.1.tgz", + "integrity": "sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g==", "dev": true, "requires": { "tslib": "^1.8.1" @@ -2593,16 +2882,16 @@ "prelude-ls": "~1.1.2" } }, - "typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", "dev": true }, "typescript": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.2.2.tgz", - "integrity": "sha512-VCj5UiSyHBjwfYacmDuc/NOk4QQixbE+Wn7MFJuS0nRuPQbof132Pw4u53dm264O8LPc2MVsc7RJNml5szurkg==", + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.8.3.tgz", + "integrity": "sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w==", "dev": true }, "uglify-js": { @@ -2684,6 +2973,15 @@ } } }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, "urix": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", @@ -2696,10 +2994,10 @@ "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", "dev": true }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "v8-compile-cache": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz", + "integrity": "sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g==", "dev": true }, "which": { @@ -2711,10 +3009,10 @@ "isexe": "^2.0.0" } }, - "wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", "dev": true }, "wrappy": { @@ -2724,19 +3022,13 @@ "dev": true }, "write": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", - "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", + "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", "dev": true, "requires": { "mkdirp": "^0.5.1" } - }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true } } } diff --git a/package.json b/package.json index a1c68042..e39c4986 100644 --- a/package.json +++ b/package.json @@ -8,15 +8,19 @@ "node": ">= 8.5.0" }, "devDependencies": { + "@typescript-eslint/eslint-plugin": "2.25.0", + "@typescript-eslint/parser": "2.16.0", "babel-eslint": "8.2.3", "ember-template-lint": "1.8.2", - "eslint": "4.19.0", - "eslint-config-prettier": "2.9.0", - "eslint-plugin-ember": "5.1.0", + "eslint": "6.8.0", + "eslint-config-prettier": "6.9.0", + "eslint-config-typestrict": "1.0.0", + "eslint-plugin-ember": "7.7.2", "eslint-plugin-mirego": "0.0.1", - "prettier": "1.16.4", - "tslint": "5.12.1", - "tslint-config-prettier": "1.17.0", - "typescript": "3.2.2" - } + "eslint-plugin-node": "11.0.0", + "eslint-plugin-sonarjs": "0.5.0", + "prettier": "2.0.2", + "typescript": "3.8.3" + }, + "dependencies": {} } diff --git a/priv/scripts/ci-check.sh b/priv/scripts/ci-check.sh index 4c801422..b03c2bfc 100755 --- a/priv/scripts/ci-check.sh +++ b/priv/scripts/ci-check.sh @@ -43,8 +43,11 @@ run make lint-prettier header "Eslint code lint…" run make lint-eslint -header "Tslint code lint…" -run make lint-tslint +header "Handlebar template code lint…" +run make lint-template-hbs + +header "Type check Typescript files…" +run make type-check if [ ${error_status} -ne 0 ]; then echo "\n\n${YELLOW}▶▶ One of the checks ${RED_BOLD}failed${YELLOW}. Please fix it before committing.${NO_COLOR}" diff --git a/test/graphql/requests/projects_request_test.exs b/test/graphql/requests/projects_request_test.exs index f0d3f184..8f99588e 100644 --- a/test/graphql/requests/projects_request_test.exs +++ b/test/graphql/requests/projects_request_test.exs @@ -7,6 +7,7 @@ defmodule AccentTest.GraphQL.Requests.Projects do Project, Repo, Revision, + Translation, User } @@ -18,12 +19,16 @@ defmodule AccentTest.GraphQL.Requests.Projects do project = %Project{main_color: "#f00", name: "My project", last_synced_at: DateTime.from_naive!(~N[2017-01-01T00:00:00], "Etc/UTC")} |> Repo.insert!() %Collaborator{project_id: project.id, user_id: user.id, role: "admin"} |> Repo.insert!() - %Revision{language_id: french_language.id, project_id: project.id, master: true} |> Repo.insert!() + revision = %Revision{language_id: french_language.id, project_id: project.id, master: true} |> Repo.insert!() - {:ok, [user: user, project: project, language: french_language]} + {:ok, [user: user, project: project, language: french_language, revision: revision]} end - test "list projects", %{user: user, project: project} do + test "list projects", %{user: user, project: project, revision: revision} do + %Translation{revision_id: revision.id, key: "A", conflicted: true} |> Repo.insert!() + %Translation{revision_id: revision.id, key: "B", conflicted: true} |> Repo.insert!() + %Translation{revision_id: revision.id, key: "C", conflicted: false} |> Repo.insert!() + {:ok, data} = """ query { @@ -33,6 +38,9 @@ defmodule AccentTest.GraphQL.Requests.Projects do id name lastSyncedAt + translationsCount + conflictsCount + reviewedCount } } } @@ -43,5 +51,8 @@ defmodule AccentTest.GraphQL.Requests.Projects do assert get_in(data, [:data, "viewer", "projects", "entries", Access.at(0), "id"]) === project.id assert get_in(data, [:data, "viewer", "projects", "entries", Access.at(0), "name"]) === project.name assert get_in(data, [:data, "viewer", "projects", "entries", Access.at(0), "lastSyncedAt"]) === "2017-01-01T00:00:00Z" + assert get_in(data, [:data, "viewer", "projects", "entries", Access.at(0), "translationsCount"]) === 3 + assert get_in(data, [:data, "viewer", "projects", "entries", Access.at(0), "reviewedCount"]) === 1 + assert get_in(data, [:data, "viewer", "projects", "entries", Access.at(0), "conflictsCount"]) === 2 end end diff --git a/tslint.json b/tslint.json deleted file mode 100644 index 97a5f47e..00000000 --- a/tslint.json +++ /dev/null @@ -1,77 +0,0 @@ -{ - "extends": ["tslint:latest", "tslint-config-prettier"], - "rules": { - "adjacent-overload-signatures": true, - "arrow-return-shorthand": true, - "ban-comma-operator": true, - "class-name": true, - "comment-format": [true, "check-space"], - "curly": [true, "ignore-same-line"], - "encoding": true, - "interface-name": false, - "max-classes-per-file": false, - "member-access": [true, "no-public"], - "newline-before-return": true, - "no-arg": true, - "no-conditional-assignment": true, - "no-console": false, - "no-consecutive-blank-lines": true, - "no-debugger": true, - "no-duplicate-imports": true, - "no-duplicate-super": true, - "no-duplicate-switch-case": true, - "no-duplicate-variable": [true, "check-parameters"], - "no-empty-interface": false, - "no-empty": false, - "no-eval": true, - "no-implicit-dependencies": false, - "no-non-null-assertion": false, - "no-parameter-reassignment": true, - "no-return-await": true, - "no-shadowed-variable": false, - "no-string-literal": true, - "no-string-throw": true, - "no-submodule-imports": false, - "no-switch-case-fall-through": true, - "no-this-assignment": [true, {"allow-destructuring": true}], - "no-unsafe-finally": true, - "no-unused-expression": [true, "allow-fast-null-checks"], - "no-var-keyword": true, - "number-literal-format": true, - "object-literal-key-quotes": [true, "as-needed"], - "one-variable-per-declaration": [true, "ignore-for-loop"], - "prefer-conditional-expression": true, - "prefer-const": true, - "prefer-for-of": true, - "prefer-object-spread": true, - "prefer-template": true, - "radix": true, - "triple-equals": [true, "allow-undefined-check", "allow-null-check"], - "typedef-whitespace": [ - true, - { - "call-signature": "nospace", - "index-signature": "nospace", - "parameter": "nospace", - "property-declaration": "nospace", - "variable-declaration": "nospace" - }, - { - "call-signature": "onespace", - "index-signature": "onespace", - "parameter": "onespace", - "property-declaration": "onespace", - "variable-declaration": "onespace" - } - ], - "unified-signatures": true, - "use-isnan": true, - "variable-name": [ - true, - "ban-keywords", - "check-format", - "allow-leading-underscore", - "allow-pascal-case" - ] - } -} diff --git a/webapp/.template-lintrc.js b/webapp/.template-lintrc.js index 755fbc2a..4611ccef 100644 --- a/webapp/.template-lintrc.js +++ b/webapp/.template-lintrc.js @@ -11,6 +11,9 @@ module.exports = { 'link-rel-noopener': true, 'no-abstract-roles': true, 'no-bare-strings': true, + 'no-curly-component-invocation': { + allow: ['inline-svg', 't', 'string-diff', 'time-ago-in-words'], + }, 'no-debugger': true, 'no-element-event-actions': true, 'no-duplicate-attributes': true, @@ -26,10 +29,11 @@ module.exports = { 'no-triple-curlies': false, 'no-unused-block-params': true, quotes: 'double', + 'require-valid-alt-text': false, 'self-closing-void-elements': true, 'simple-unless': false, 'style-concatenation': true, 'table-groups': true, - 'template-length': [true, {min: 1, max: 200}] - } + 'template-length': [true, {min: 1, max: 200}], + }, }; diff --git a/webapp/app/app.js b/webapp/app/app.js index eefa26cb..b892c75a 100644 --- a/webapp/app/app.js +++ b/webapp/app/app.js @@ -4,11 +4,12 @@ import loadInitializers from 'ember-load-initializers'; import config from './config/environment'; const {modulePrefix, podModulePrefix} = config; -const App = Application.extend({ - modulePrefix, - podModulePrefix, - Resolver -}); + +class App extends Application { + modulePrefix = modulePrefix; + podModulePrefix = podModulePrefix; + Resolver = Resolver; +} loadInitializers(App, modulePrefix); diff --git a/webapp/app/component-helpers/percentage.js b/webapp/app/component-helpers/percentage.ts similarity index 76% rename from webapp/app/component-helpers/percentage.js rename to webapp/app/component-helpers/percentage.ts index a1a37226..c961cb13 100644 --- a/webapp/app/component-helpers/percentage.js +++ b/webapp/app/component-helpers/percentage.ts @@ -1,4 +1,4 @@ -export default (count, total) => { +export default (count: number, total: number) => { const percentage = (count / total) * 100; if (percentage) { diff --git a/webapp/app/computed-macros/field-error.js b/webapp/app/computed-macros/field-error.js deleted file mode 100644 index cea9522b..00000000 --- a/webapp/app/computed-macros/field-error.js +++ /dev/null @@ -1,9 +0,0 @@ -import {computed} from '@ember/object'; - -export default (errorsKey, property) => { - return computed(errorsKey, function() { - const errors = this.get(errorsKey); - - return errors && errors.find(({field}) => field === property); - }); -}; diff --git a/webapp/app/computed-macros/field-error.ts b/webapp/app/computed-macros/field-error.ts new file mode 100644 index 00000000..19310e7c --- /dev/null +++ b/webapp/app/computed-macros/field-error.ts @@ -0,0 +1,6 @@ +interface Error { + field: String; +} + +export default (errors: [Error], property: String): Error | undefined => + errors && errors.find(({field}) => field === property); diff --git a/webapp/app/computed-macros/parsed-key.js b/webapp/app/computed-macros/parsed-key.js deleted file mode 100644 index 13d396c3..00000000 --- a/webapp/app/computed-macros/parsed-key.js +++ /dev/null @@ -1,17 +0,0 @@ -import EmberObject, {computed} from '@ember/object'; - -export default property => { - return computed(property, function() { - const key = this.get(property); - - if (!key) return EmberObject.create({value: '', prefix: ''}); - - const splittedKey = key.split('|'); - const isSplitted = !!splittedKey[1]; - - return EmberObject.create({ - value: isSplitted ? splittedKey[1] : key, - prefix: isSplitted ? splittedKey[0] : '' - }); - }); -}; diff --git a/webapp/app/computed-macros/parsed-key.ts b/webapp/app/computed-macros/parsed-key.ts new file mode 100644 index 00000000..436e93ce --- /dev/null +++ b/webapp/app/computed-macros/parsed-key.ts @@ -0,0 +1,16 @@ +interface ParsedKey { + value: String; + prefix: String; +} + +export default (key: String): ParsedKey => { + if (!key) return {value: '', prefix: ''}; + + const splittedKey = key.split('|'); + const isSplitted = !!splittedKey[1]; + + return { + value: isSplitted ? splittedKey[1] : key, + prefix: isSplitted ? splittedKey[0] : '', + }; +}; diff --git a/webapp/app/config/environment.d.ts b/webapp/app/config/environment.d.ts new file mode 100644 index 00000000..3f73d8bd --- /dev/null +++ b/webapp/app/config/environment.d.ts @@ -0,0 +1,70 @@ +/** + * Type declarations for + * import config from './config/environment' + * + * For now these need to be managed by the developer + * since different ember addons can materialize new entries. + */ +declare const config: { + environment: any; + modulePrefix: string; + podModulePrefix: string; + locationType: string; + rootURL: string; + + EmberENV: { + EXTEND_PROTOTYPES: boolean; + LOG_VERSION: boolean; + }; + + APP: { + LOCAL_STORAGE: { + SESSION_NAMESPACE: string; + }; + }; + + API: { + WS_HOST: string; + HOST: string; + AUTHENTICATION_PATH: string; + HOOKS_PATH: string; + PROJECT_PATH: string; + SYNC_PEEK_PROJECT_PATH: string; + SYNC_PROJECT_PATH: string; + MERGE_PEEK_PROJECT_PATH: string; + MERGE_REVISION_PATH: string; + EXPORT_DOCUMENT: string; + JIPT_EXPORT_DOCUMENT: string; + PERCENTAGE_REVIEWED_BADGE_SVG_PROJECT_PATH: string; + JIPT_SCRIPT_PATH: string; + }; + + SENTRY: { + DSN: string; + }; + + contentSecurityPolicy: { + 'default-src': string | string[]; + 'script-src': string | string[]; + 'font-src': string | string[]; + 'connect-src': string | string[]; + 'img-src': string | string[]; + 'style-src': string | string[]; + 'media-src': string | string[]; + 'frame-src': string | string[]; + }; + + flashMessageDefaults: { + timeout: number; + destroyOnClick: boolean; + extendedTimeout: number; + priority: number; + sticky: boolean; + showProgress: boolean; + type: string; + types: string[]; + injectionFactories: []; + }; +}; + +export default config; diff --git a/webapp/app/formats.js b/webapp/app/formats.js index 5087de7d..5144c1d6 100644 --- a/webapp/app/formats.js +++ b/webapp/app/formats.js @@ -3,22 +3,22 @@ export default { hhmmss: { hour: 'numeric', minute: 'numeric', - second: 'numeric' - } + second: 'numeric', + }, }, date: { hhmmss: { hour: 'numeric', minute: 'numeric', - second: 'numeric' - } + second: 'numeric', + }, }, number: { USD: { style: 'currency', currency: 'USD', minimumFractionDigits: 2, - maximumFractionDigits: 2 - } - } + maximumFractionDigits: 2, + }, + }, }; diff --git a/webapp/app/helpers/string-diff.js b/webapp/app/helpers/string-diff.js deleted file mode 100644 index 6074a094..00000000 --- a/webapp/app/helpers/string-diff.js +++ /dev/null @@ -1,31 +0,0 @@ -import Ember from 'ember'; -import {helper} from '@ember/component/helper'; -import {htmlSafe} from '@ember/string'; -import Diff from 'diff'; - -const { - Handlebars: { - Utils: {escapeExpression} - } -} = Ember; - -const REMOVED_TAG_TEMPLATE = value => `${value}`; -const ADDED_TAG_TEMPLATE = value => `${value}`; - -const stringDiff = ([text1, text2]) => { - const diff = Diff.diffWords(text2 || '', text1 || ''); - - return htmlSafe( - diff - .map(part => { - const value = escapeExpression(part.value); - if (part.removed) return REMOVED_TAG_TEMPLATE(value); - if (part.added) return ADDED_TAG_TEMPLATE(value); - - return value; - }) - .join('') - ); -}; - -export default helper(stringDiff); diff --git a/webapp/app/helpers/string-diff.ts b/webapp/app/helpers/string-diff.ts new file mode 100644 index 00000000..da3b8000 --- /dev/null +++ b/webapp/app/helpers/string-diff.ts @@ -0,0 +1,64 @@ +import {helper} from '@ember/component/helper'; +import {htmlSafe} from '@ember/string'; +import Diff from 'diff'; + +const badChars = /[&<>"'`=]/g; +const possible = /[&<>"'`=]/; +const escape = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''', + '`': '`', + '=': '=', +}; + +const escapeChar = (chr: keyof typeof escape) => { + return escape[chr]; +}; + +const escapeExpression = (string: any): string => { + if (typeof string !== 'string') { + // don't escape SafeStrings, since they're already safe + if (string && string.toHTML) { + return string.toHTML(); + } else if (string === null || string === undefined) { + return ''; + } else if (!string) { + return String(string); + } + + // Force a string conversion as this will be done by the append regardless and + // the regex test will do this transparently behind the scenes, causing issues if + // an object's to string has escaped characters in it. + string = String(string); + } + + if (!possible.test(string)) return string; + + return string.replace(badChars, escapeChar); +}; + +const REMOVED_TAG_TEMPLATE = (value: string) => + `${value}`; +const ADDED_TAG_TEMPLATE = (value: string) => + `${value}`; + +const stringDiff = ([text1, text2]: [string, string]) => { + const diff = Diff.diffWords(text2 || '', text1 || ''); + + return htmlSafe( + diff + .map((part: {value: string; removed: string; added: string}) => { + const value = escapeExpression(part.value); + if (part.removed) return REMOVED_TAG_TEMPLATE(value); + if (part.added) return ADDED_TAG_TEMPLATE(value); + + return value; + }) + .join('') + ); +}; + +export default helper(stringDiff); diff --git a/webapp/app/helpers/time-ago-in-words.js b/webapp/app/helpers/time-ago-in-words.ts similarity index 81% rename from webapp/app/helpers/time-ago-in-words.js rename to webapp/app/helpers/time-ago-in-words.ts index fe8e5551..50cf96b1 100644 --- a/webapp/app/helpers/time-ago-in-words.js +++ b/webapp/app/helpers/time-ago-in-words.ts @@ -4,10 +4,10 @@ import formatDistanceToNow from 'date-fns/formatDistanceToNow'; const OPTIONS = { addSuffix: true, - includeSeconds: false + includeSeconds: false, }; -const timeAgoInWords = ([date]) => { +const timeAgoInWords = ([date]: [string]) => { if (isBlank(date)) return ''; return formatDistanceToNow(new Date(date), OPTIONS); diff --git a/webapp/app/instance-initializers/raven-setup.js b/webapp/app/instance-initializers/raven-setup.js index 31fdf631..83885b8a 100644 --- a/webapp/app/instance-initializers/raven-setup.js +++ b/webapp/app/instance-initializers/raven-setup.js @@ -1,7 +1,7 @@ import Raven from 'raven-js'; import config from 'accent-webapp/config/environment'; -export const initialize = application => { +export const initialize = (application) => { if (config.SENTRY.DSN) { Raven.config(config.SENTRY.DSN).install(); @@ -15,5 +15,5 @@ export const initialize = application => { export default { name: 'raven-setup', - initialize + initialize, }; diff --git a/webapp/app/locales/en-us.json b/webapp/app/locales/en-us.json index 0110323d..8803902b 100644 --- a/webapp/app/locales/en-us.json +++ b/webapp/app/locales/en-us.json @@ -177,8 +177,8 @@ } }, "date_tag": { - "formatted_date_time_format": "yyyy-MM-ddTHH:mm:ss", - "humanized_date_title_format": "MMMM Do yyyy, HH:mm:ss" + "formatted_date_time_format": "yyyy-MM-dd'T'HH:mm:ss", + "humanized_date_title_format": "EEEE, MMMM do yyyy, H:mm a" }, "versions_list": { "export": "Export", @@ -199,7 +199,7 @@ "save_button": "Save", "cancel_button": "Cancel", "item": { - "deleting_label": "Deleting", + "deleting_label": "Deleting {path}.{extension}…", "path_label": "Path", "path_help": "Used to scope your strings. The path will be used to export all your languages (en/path.format, fr/path.format)" } @@ -621,8 +621,8 @@ "translations_link_title": "All strings" }, "time_ago_in_words_tag": { - "formatted_date_time_format": "yyyy-MM-ddTHH:mm:ss", - "humanized_date_title_format": "dddd, MMMM Do yyyy, H:mm a" + "formatted_date_time_format": "yyyy-MM-dd'T'HH:mm:ss", + "humanized_date_title_format": "EEEE, MMMM do yyyy, H:mm a" }, "translation_activities_list_item": { "action_text": { diff --git a/webapp/app/mixins/apollo-route.js b/webapp/app/mixins/apollo-route.js deleted file mode 100644 index cb8e38ea..00000000 --- a/webapp/app/mixins/apollo-route.js +++ /dev/null @@ -1,78 +0,0 @@ -import {inject as service} from '@ember/service'; -import Mixin from '@ember/object/mixin'; -import EmberObject, {setProperties} from '@ember/object'; - -const PROPS_FN = data => data; - -export default Mixin.create({ - apollo: service('apollo'), - - graphql(query, {options, props}) { - props = props || PROPS_FN; - const graphqlObject = () => this.modelFor(this.routeName); - - this._createQuery(query, options); - this._createSubscription(props, graphqlObject); - - return this._currentResult(props); - }, - - deactivate() { - this._super(...arguments); - - this._clearSubscription(); - }, - - _currentResult(props) { - const queryObservable = this.queryObservable; - const result = queryObservable.currentResult(); - const mappedResult = this._mapResult(result, props); - - return EmberObject.create(mappedResult); - }, - - _createQuery(query, options = {}) { - this._clearSubscription(); - - const queryObservable = this.apollo.client.watchQuery({ - query, - ...options - }); - setProperties(this, {queryObservable}); - }, - - _createSubscription(props, graphqlObject) { - const next = result => { - const o = graphqlObject(); - if (!o) return; - - const mappedResult = this._mapResult(result, props); - setProperties(o, mappedResult); - }; - - const querySubscription = this.queryObservable.subscribe({next}); - setProperties(this, {querySubscription}); - }, - - _clearSubscription() { - const subscription = this.querySubscription; - if (subscription) subscription.unsubscribe(); - }, - - _mapResult(result, props) { - if (result.data && Object.keys(result.data).length) { - const data = props(result.data); - - return { - ...data, - loading: result.loading, - refetch: this.queryObservable.refetch, - fetchMore: this.queryObservable.fetchMore, - startPolling: this.queryObservable.startPolling, - stopPolling: this.queryObservable.stopPolling - }; - } else { - return result; - } - } -}); diff --git a/webapp/app/mixins/authenticated-route.js b/webapp/app/mixins/authenticated-route.js deleted file mode 100644 index a7f088a9..00000000 --- a/webapp/app/mixins/authenticated-route.js +++ /dev/null @@ -1,12 +0,0 @@ -import {inject as service} from '@ember/service'; -import Mixin from '@ember/object/mixin'; - -export default Mixin.create({ - session: service(), - - redirect() { - if (!this.session.isAuthenticated) { - this.transitionTo('login'); - } - } -}); diff --git a/webapp/app/mixins/reset-scroll.js b/webapp/app/mixins/reset-scroll.js deleted file mode 100644 index 7f9a0723..00000000 --- a/webapp/app/mixins/reset-scroll.js +++ /dev/null @@ -1,9 +0,0 @@ -import Mixin from '@ember/object/mixin'; - -export default Mixin.create({ - activate() { - this._super(); - - window.scrollTo(0, 0); - } -}); diff --git a/webapp/app/pods/application/route.js b/webapp/app/pods/application/route.js deleted file mode 100644 index 9f0f26f0..00000000 --- a/webapp/app/pods/application/route.js +++ /dev/null @@ -1,32 +0,0 @@ -import {inject as service} from '@ember/service'; -import Route from '@ember/routing/route'; -import raven from 'raven-js'; -import config from 'accent-webapp/config/environment'; - -export default Route.extend({ - session: service('session'), - intl: service('intl'), - - beforeModel() { - this._super(...arguments); - this.intl.setLocale(['en-us']); - - raven.config(config.SENTRY.DSN).install(); - - this._tryLoginAfterRedirect(); - }, - - _tryLoginAfterRedirect() { - const match = window.location.search - .substring(window.location.search.indexOf('?') + 1) - .split('&') - .find(segment => segment.split('=')[0] === 'token'); - const token = match && match.split('=')[1]; - - if (!token) return; - - this.session.login({token}).then(data => { - if (data && data.user) this.transitionTo('logged-in.projects'); - }); - } -}); diff --git a/webapp/app/pods/application/route.ts b/webapp/app/pods/application/route.ts new file mode 100644 index 00000000..1a907533 --- /dev/null +++ b/webapp/app/pods/application/route.ts @@ -0,0 +1,43 @@ +import {inject as service} from '@ember/service'; +import Route from '@ember/routing/route'; +import raven from 'raven-js'; +import config from 'accent-webapp/config/environment'; +import Session from 'accent-webapp/services/session'; +import IntlService from 'ember-intl/services/intl'; +import RouterService from '@ember/routing/router-service'; + +export default class ApplicationRoute extends Route { + @service('session') + session: Session; + + @service('intl') + intl: IntlService; + + @service('router') + router: RouterService; + + async beforeModel() { + this.intl.setLocale('en-us'); + + raven.config(config.SENTRY.DSN).install(); + + await this.tryLoginAfterRedirect(); + } + + private async tryLoginAfterRedirect() { + const match = window.location.search + .substring(window.location.search.indexOf('?') + 1) + .split('&') + .find((segment) => segment.split('=')[0] === 'token'); + + const token = match && match.split('=')[1]; + + if (!token) return; + + const data = await this.session.login({token}); + + if (data && data.user) { + this.router.transitionTo('logged-in.projects'); + } + } +} diff --git a/webapp/app/pods/components/acc-avatar-img/component.ts b/webapp/app/pods/components/acc-avatar-img/component.ts new file mode 100644 index 00000000..d19cd485 --- /dev/null +++ b/webapp/app/pods/components/acc-avatar-img/component.ts @@ -0,0 +1,13 @@ +import Component from '@glimmer/component'; + +const FALLBACK_SOURCE = + 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAABGdBTUEAALGPC/xhBQAAADhlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAAqACAAQAAAABAAAAMKADAAQAAAABAAAAMAAAAAD4/042AAACj0lEQVRoBdVaPUsDQRCNCuIX+C0ELGy0sBD9AxIjiI2VoFhZ5e+IlVbWgo2gIFhE0EKshZRiIXZWJoqCGt87cmcSzO1uZpLsDTx2Lzc7895OdrN3mkr9WRe6OeAOKAJlz0BO5EaO5FpjaVzlAd9IN+JDruQcGNUkiXwoipyDSrAk4YdJa3M9IH8ATANJtCmWgItjKInswblEAfzaJNa6E8u8QrwVAm4RexdYAkaBEWAR4Ge8p25aO88LmGUs2K3Ah75aeVUCPYHQnAX50GUWnWdAQ4RKkM2QmUO77YuAGwfS9a5cE6IqaCzi03pWDtfnDr7/umoI4AmxWVPZlUQlBPPhZtljHE+UovwaFegTCOgXjA2GagiQnKMGfRAwISAxKRirVoFlAQnJWDUBqwIBWcHYaKhoF0CUN6A3imbfGYDrJyDKr7GISWTdnnfkuYFeM8KjAGFHNAMIwvEXYTCHVutFgqyEFQHfaOcdyC9UxmlMnooAEjl2EHDiowBWYcZCBH3oqzH7ZY1FHHJmrK3wIqbls4NaXrVAFcJ8y2EyGx9TjJr7KqVExEfA5mgwDr8HQCuvOFARZPYBErO1MTjuAa+ASAjLyQAuRv974Bq4Ai6BD6AZ41F8DcgCGYDbq/NXzHYGSHQH4Oy1yhibOZjLlpfR8QvB+Aah3caczG0SYnQ4bDfzqnzMHSvAZhs9qwrY7q5V7liFYCx54pIK5rYcy8+mAu9SFoLxfNaINZttlCI5C50w5ua5qaHZVKDh4Dbc+DHlsKmAKUZH7/teAePkUEDJ6OWvQ4kCCv7yMzIrUMCR0c1fh4A7F3IeiP3B8PA+OUcn13TCRJA8OdcY1fD/JvgHCz6k+FYRciI3coxm/hfolUaVtS+2pQAAAABJRU5ErkJggg=='; + +export default class AccAvatarImg extends Component { + fallbackImage(event: ErrorEvent) { + const target = event.target as HTMLImageElement; + + target.src = FALLBACK_SOURCE; + target.style.opacity = '0.15'; + } +} diff --git a/webapp/app/pods/components/acc-avatar-img/template.hbs b/webapp/app/pods/components/acc-avatar-img/template.hbs new file mode 100644 index 00000000..c4d7abf1 --- /dev/null +++ b/webapp/app/pods/components/acc-avatar-img/template.hbs @@ -0,0 +1,2 @@ +{{!-- template-lint-disable no-invalid-interactive --}} + diff --git a/webapp/app/pods/components/acc-badge/component.js b/webapp/app/pods/components/acc-badge/component.js deleted file mode 100644 index 1dbbf605..00000000 --- a/webapp/app/pods/components/acc-badge/component.js +++ /dev/null @@ -1,5 +0,0 @@ -import Component from '@ember/component'; - -export default Component.extend({ - classNameBindings: ['link', 'primary', 'danger'] -}); diff --git a/webapp/app/pods/components/acc-badge/component.ts b/webapp/app/pods/components/acc-badge/component.ts new file mode 100644 index 00000000..456929de --- /dev/null +++ b/webapp/app/pods/components/acc-badge/component.ts @@ -0,0 +1,9 @@ +import Component from '@glimmer/component'; + +interface Args { + link?: boolean; + primary?: boolean; + danger?: boolean; +} + +export default class Badge extends Component {} diff --git a/webapp/app/pods/components/acc-badge/styles.scss b/webapp/app/pods/components/acc-badge/styles.scss index f8e6d612..c2c1786a 100644 --- a/webapp/app/pods/components/acc-badge/styles.scss +++ b/webapp/app/pods/components/acc-badge/styles.scss @@ -1,54 +1,57 @@ -& { - transition: $transition-speed $transition-easing; +@value transition-speed, transition-easing from 'accent-webapp/styles/variables/transitions'; +@value color-grey, color-green, color-error from 'accent-webapp/styles/variables/colors'; + +.badge { + transition: transition-speed transition-easing; transition-property: background; display: inline-block; padding: 1px 6px 1px 5px; - background: lighten($color-grey, 28%); + background: lighten(color-grey, 28%); border-radius: 3px; - color: darken($color-grey, 10%); + color: darken(color-grey, 10%); font-size: 11px; font-weight: 600; text-transform: uppercase; text-decoration: none; } -&.primary { - background: $color-green; +.primary { + background: color-green; background: var(--color-primary); color: #fff; } -&.danger { - background: $color-error; +.danger { + background: color-error; color: #fff; } -&.link { +.link { padding: 0; &:focus, &:hover { - background: lighten($color-grey, 26%); + background: lighten(color-grey, 26%); } } -&.link.primary { +.link.primary { padding: 0; &:focus, &:hover { - background: darken($color-green, 3%); + background: darken(color-green, 3%); background: var(--color-primary-darken-10); } } -&.link a { +.link a { display: inline-block; padding: 1px 6px 1px 5px; color: lighten(#000, 50%); text-decoration: none; } -&.link.primary a { +.link.primary a { color: #fff; } diff --git a/webapp/app/pods/components/acc-badge/template.hbs b/webapp/app/pods/components/acc-badge/template.hbs new file mode 100644 index 00000000..573f1e4e --- /dev/null +++ b/webapp/app/pods/components/acc-badge/template.hbs @@ -0,0 +1,3 @@ +
+ {{yield}} +
diff --git a/webapp/app/pods/components/acc-emoji-picker/component.js b/webapp/app/pods/components/acc-emoji-picker/component.js deleted file mode 100644 index 816c54f7..00000000 --- a/webapp/app/pods/components/acc-emoji-picker/component.js +++ /dev/null @@ -1,17 +0,0 @@ -import Component from '@ember/component'; -import EmojiButton from '@joeattardi/emoji-button'; - -export default Component.extend({ - didInsertElement() { - const button = this.element; - const picker = new EmojiButton({ - showPreview: false - }); - - picker.on('emoji', this.onPicked); - - button.addEventListener('click', () => { - picker.pickerVisible ? picker.hidePicker() : picker.showPicker(button); - }); - } -}); diff --git a/webapp/app/pods/components/acc-emoji-picker/component.ts b/webapp/app/pods/components/acc-emoji-picker/component.ts new file mode 100644 index 00000000..0042d07c --- /dev/null +++ b/webapp/app/pods/components/acc-emoji-picker/component.ts @@ -0,0 +1,37 @@ +import Component from '@glimmer/component'; +import {action} from '@ember/object'; +import EmojiButton from '@joeattardi/emoji-button'; + +interface Args { + onPicked: () => string; +} + +export default class EmojiPicker extends Component { + picker: EmojiButton; + element: HTMLDivElement; + + clickCallback = this.onClick.bind(this); + + @action + initializePicker(element: HTMLDivElement) { + this.element = element; + + this.picker = new EmojiButton({ + showPreview: false, + }); + + this.picker.on('emoji', this.args.onPicked); + } + + @action + destroyPicker() { + this.picker.off('emoji', this.args.onPicked); + } + + @action + onClick() { + this.picker.pickerVisible + ? this.picker.hidePicker() + : this.picker.showPicker(this.element); + } +} diff --git a/webapp/app/pods/components/acc-emoji-picker/template.hbs b/webapp/app/pods/components/acc-emoji-picker/template.hbs index 889d9eea..b47062c3 100644 --- a/webapp/app/pods/components/acc-emoji-picker/template.hbs +++ b/webapp/app/pods/components/acc-emoji-picker/template.hbs @@ -1 +1,11 @@ -{{yield}} + + diff --git a/webapp/app/pods/components/acc-flash-message/component.js b/webapp/app/pods/components/acc-flash-message/component.js deleted file mode 100644 index 2d463dcf..00000000 --- a/webapp/app/pods/components/acc-flash-message/component.js +++ /dev/null @@ -1,31 +0,0 @@ -import {computed} from '@ember/object'; -import {readOnly} from '@ember/object/computed'; -import Component from '@ember/component'; - -export default Component.extend({ - classNameBindings: ['isExiting', 'type'], - - isExiting: readOnly('flash.exiting'), - type: readOnly('flash.type'), - - iconPath: computed('type', function() { - switch (this.type) { - case 'success': - return 'assets/check.svg'; - case 'error': - return 'assets/x.svg'; - case 'socket': - return 'assets/activity.svg'; - default: - null; - } - }), - - actions: { - close() { - const flash = this.flash; - - if (flash) flash.destroyMessage(); - } - } -}); diff --git a/webapp/app/pods/components/acc-flash-message/component.ts b/webapp/app/pods/components/acc-flash-message/component.ts new file mode 100644 index 00000000..e64ea238 --- /dev/null +++ b/webapp/app/pods/components/acc-flash-message/component.ts @@ -0,0 +1,39 @@ +import Component from '@glimmer/component'; +import {action} from '@ember/object'; +import {readOnly} from '@ember/object/computed'; + +interface Args { + flash: { + exiting: boolean; + type: string; + destroyMessage: () => void; + }; +} + +export default class FlashMessage extends Component { + @readOnly('args.flash.exiting') + isExiting: boolean; + + @readOnly('args.flash.type') + type: 'info' | 'success' | 'error' | 'socket'; + + get iconPath() { + switch (this.type) { + case 'success': + return 'assets/check.svg'; + case 'error': + return 'assets/x.svg'; + case 'socket': + return 'assets/activity.svg'; + default: + return null; + } + } + + @action + close() { + const flash = this.args.flash; + + if (flash) flash.destroyMessage(); + } +} diff --git a/webapp/app/pods/components/acc-flash-message/styles.scss b/webapp/app/pods/components/acc-flash-message/styles.scss index 71682ab7..531b62f7 100644 --- a/webapp/app/pods/components/acc-flash-message/styles.scss +++ b/webapp/app/pods/components/acc-flash-message/styles.scss @@ -1,4 +1,6 @@ -& { +@value color-green, color-socket, color-error from 'accent-webapp/styles/variables/colors'; + +.flash { position: relative; margin-bottom: 10px; width: 400px; @@ -8,35 +10,37 @@ text-shadow: 0 1px 1px rgba(#000, 0.1); color: #fff; font-weight: bold; - animation: 0.3s flash-message-in ease; + animation: 0.3s ease; + animation-name: flash-message-in; pointer-events: all; &.is-exiting { - animation: 0.3s flash-message-out forwards ease-in-out; + animation: 0.3s forwards ease-in-out; + animation-name: flash-message-out; } } -&.success { - background: $color-green; +.flash.success { + background: color-green; .icon { - stroke: lighten($color-green, 35%); + stroke: lighten(color-green, 35%); } } -&.socket { - background: $color-socket; +.flash.socket { + background: color-socket; .icon { - stroke: lighten($color-socket, 35%); + stroke: lighten(color-socket, 35%); } } -&.error { - background: $color-error; +.flash.error { + background: color-error; .icon { - stroke: lighten($color-error, 35%); + stroke: lighten(color-error, 35%); } } diff --git a/webapp/app/pods/components/acc-flash-message/template.hbs b/webapp/app/pods/components/acc-flash-message/template.hbs index e77c1e32..f77ced21 100644 --- a/webapp/app/pods/components/acc-flash-message/template.hbs +++ b/webapp/app/pods/components/acc-flash-message/template.hbs @@ -1,14 +1,16 @@ - +
+ -
- {{#if iconPath}} -
- {{inline-svg iconPath class="icon"}} -
- {{/if}} -

- {{flash.message}} -

+
+ {{#if this.iconPath}} +
+ {{inline-svg this.iconPath}} +
+ {{/if}} +

+ {{@flash.message}} +

+
diff --git a/webapp/app/pods/components/acc-modal/component.js b/webapp/app/pods/components/acc-modal/component.js deleted file mode 100644 index c95eeb4c..00000000 --- a/webapp/app/pods/components/acc-modal/component.js +++ /dev/null @@ -1,9 +0,0 @@ -import Component from '@ember/component'; - -export default Component.extend({ - actions: { - close() { - this.onClose(); - } - } -}); diff --git a/webapp/app/pods/components/acc-modal/component.ts b/webapp/app/pods/components/acc-modal/component.ts new file mode 100644 index 00000000..46dc02d4 --- /dev/null +++ b/webapp/app/pods/components/acc-modal/component.ts @@ -0,0 +1,8 @@ +import Component from '@glimmer/component'; + +interface Args { + small: boolean; + onClose: () => void; +} + +export default class Modal extends Component {} diff --git a/webapp/app/pods/components/acc-modal/template.hbs b/webapp/app/pods/components/acc-modal/template.hbs index 9d068074..fb15cfcc 100644 --- a/webapp/app/pods/components/acc-modal/template.hbs +++ b/webapp/app/pods/components/acc-modal/template.hbs @@ -1,7 +1,7 @@
-
- diff --git a/webapp/app/pods/components/acc-select/component.js b/webapp/app/pods/components/acc-select/component.js deleted file mode 100644 index cbfd5011..00000000 --- a/webapp/app/pods/components/acc-select/component.js +++ /dev/null @@ -1,3 +0,0 @@ -import Component from '@ember/component'; - -export default Component.extend(); diff --git a/webapp/app/pods/components/acc-select/component.ts b/webapp/app/pods/components/acc-select/component.ts new file mode 100644 index 00000000..4e6ad106 --- /dev/null +++ b/webapp/app/pods/components/acc-select/component.ts @@ -0,0 +1,15 @@ +import Component from '@glimmer/component'; + +interface Args { + searchEnabled: boolean; + selected: any; + options: any[]; + onchange: (value: any) => void; + placeholder: string; + search: (term: string) => Promise; + searchPlaceholder: string; + matchTriggerWidth: boolean; + renderInPlace: boolean; +} + +export default class Select extends Component {} diff --git a/webapp/app/pods/components/acc-select/template.hbs b/webapp/app/pods/components/acc-select/template.hbs index d3a1438b..e62a123c 100644 --- a/webapp/app/pods/components/acc-select/template.hbs +++ b/webapp/app/pods/components/acc-select/template.hbs @@ -1,12 +1,13 @@ {{option.label}} diff --git a/webapp/app/pods/components/activity-item/component.js b/webapp/app/pods/components/activity-item/component.js deleted file mode 100644 index f609c43b..00000000 --- a/webapp/app/pods/components/activity-item/component.js +++ /dev/null @@ -1,178 +0,0 @@ -import {computed} from '@ember/object'; -import {inject as service} from '@ember/service'; -import {readOnly, reads, equal} from '@ember/object/computed'; -import Component from '@ember/component'; -import {underscore, dasherize} from '@ember/string'; - -import parsedKeyProperty from 'accent-webapp/computed-macros/parsed-key'; - -/* eslint camelcase:0 */ -const ACTIONS_ICON_PATHS = { - version_new: 'assets/tag.svg', - add_to_version: 'assets/tag.svg', - create_version: 'assets/tag.svg', - sync: 'assets/sync.svg', - merge: 'assets/merge.svg', - rollback: 'assets/revert.svg', - update: 'assets/pencil.svg', - correct_conflict: 'assets/check.svg', - correct_all: 'assets/check.svg', - uncorrect_all: 'assets/revert.svg', - uncorrect_conflict: 'assets/revert.svg', - conflict_on_slave: 'assets/x.svg', - conflict_on_corrected: 'assets/x.svg', - conflict_on_proposed: 'assets/x.svg', - remove: 'assets/x.svg', - new_comment: 'assets/bubble.svg', - new_slave: 'assets/language.svg', - document_delete: 'assets/file.svg' -}; - -// Attributes: -// project: Object -// permissions: Ember Object containing -// showTranslationLink: Boolean -// activity: Object -// componentTranslationPrefix: String -export default Component.extend({ - intl: service('intl'), - - classNameBindings: ['compact', 'activityItemClassName', 'rollbacked'], - - action: readOnly('activity.action'), - rollbacked: reads('activity.isRollbacked'), - rollbackedOperationHasEmptyText: equal( - 'activity.rollbackedOperation.valueType', - 'EMPTY' - ), - hasEmptyText: equal('activity.valueType', 'EMPTY'), - - translationKey: parsedKeyProperty('activity.translation.key'), - - activityItemClassName: computed('activity.action', function() { - return dasherize(this.activity.action); - }), - - actionText: computed('action', function() { - return this._getActionText(this.action); - }), - - rollbackedOperationActionText: computed( - 'activity.rollbackedOperation.action', - function() { - return this._getActionText(this.activity.rollbackedOperation.action); - } - ), - - showFromOperationTranslationLink: computed( - 'showTranslationLink', - 'activity.rollbackedOperation.translation.id', - function() { - return ( - this.showTranslationLink && - this.activity.rollbackedOperation && - this.activity.rollbackedOperation.translation && - this.activity.rollbackedOperation.translation.id - ); - } - ), - - showStats: computed('activity.stats.[]', function() { - return this.activity.stats; - }), - - localizedStats: computed('activity.stats.[]', function() { - return this.activity.stats.map(stat => { - const text = this.intl.t( - `components.${this.componentTranslationPrefix}.stats_text.${underscore( - stat.action - )}` - ); - const count = stat.count; - - return {text, count}; - }); - }), - - statsLabel: computed('componentTranslationPrefix', function() { - return this.intl.t( - `components.${this.componentTranslationPrefix}.stats_label_text` - ); - }), - - showDocumentInfo: computed('action', 'activity.document.path', function() { - const action = this.action; - const actionsWithDocument = ['sync', 'document_delete', 'merge']; - - return ( - actionsWithDocument.includes(action) && readOnly('activity.document.path') - ); - }), - - showVersionInfo: readOnly('activity.version.id'), - - revisionName: computed('activity.revision.{name,language.name}', function() { - return this.activity.revision.name || this.activity.revision.language.name; - }), - - showRevisionInfo: computed( - 'action', - 'activity.revision.language.id', - function() { - if (!this.activity.revision) return false; - - const actionsWithRevision = [ - 'new', - 'remove', - 'renew', - 'new_slave', - 'merge', - 'uncorrect_all', - 'correct_all', - 'batch_correct_conflict', - 'batch_update', - 'conflict_on_slave' - ]; - - return ( - actionsWithRevision.includes(this.action) && - this.activity.revision.language.id - ); - } - ), - - showFromOperationDocumentInfo: computed( - 'activity.rollbackedOperation.{action,document.path}', - function() { - const action = this.activity.rollbackedOperation.action; - const actionsWithDocument = ['sync', 'document_delete', 'merge']; - - return ( - actionsWithDocument.includes(action) && - readOnly('activity.rollbackedOperation.document.path') - ); - } - ), - - isShowingTranslationLink: computed( - 'showTranslationLink', - 'activity.{action,translation}', - function() { - return ( - this.showTranslationLink && - this.activity.translation && - this.activity.action !== 'rollback' - ); - } - ), - - iconPath: computed('action', function() { - return ACTIONS_ICON_PATHS[this.action] || 'assets/add.svg'; - }), - - _getActionText(action) { - return this.intl.t( - `components.${this.componentTranslationPrefix}.action_text.${action}` - ); - } -}); diff --git a/webapp/app/pods/components/activity-item/component.ts b/webapp/app/pods/components/activity-item/component.ts new file mode 100644 index 00000000..ca96e248 --- /dev/null +++ b/webapp/app/pods/components/activity-item/component.ts @@ -0,0 +1,176 @@ +import {inject as service} from '@ember/service'; +import {readOnly, equal} from '@ember/object/computed'; +import Component from '@glimmer/component'; +import {underscore, dasherize} from '@ember/string'; + +import parsedKeyProperty from 'accent-webapp/computed-macros/parsed-key'; +import IntlService from 'ember-intl/services/intl'; + +/* eslint camelcase:0 */ +const ACTIONS_ICON_PATHS = { + version_new: 'assets/tag.svg', + add_to_version: 'assets/tag.svg', + create_version: 'assets/tag.svg', + sync: 'assets/sync.svg', + merge: 'assets/merge.svg', + rollback: 'assets/revert.svg', + update: 'assets/pencil.svg', + correct_conflict: 'assets/check.svg', + correct_all: 'assets/check.svg', + uncorrect_all: 'assets/revert.svg', + uncorrect_conflict: 'assets/revert.svg', + conflict_on_slave: 'assets/x.svg', + conflict_on_corrected: 'assets/x.svg', + conflict_on_proposed: 'assets/x.svg', + remove: 'assets/x.svg', + new_comment: 'assets/bubble.svg', + new_slave: 'assets/language.svg', + document_delete: 'assets/file.svg', +}; + +interface Args { + compact: boolean; + permissions: Record; + showTranslationLink: boolean; + componentTranslationPrefix: string; + activity: any; + project: any; +} + +export default class ActivityItem extends Component { + @service('intl') + intl: IntlService; + + @readOnly('args.activity.action') + action: keyof typeof ACTIONS_ICON_PATHS; + + @readOnly('args.activity.isRollbacked') + rollbacked: boolean; + + @equal('args.activity.rollbackedOperation.valueType', 'EMPTY') + rollbackedOperationHasEmptyText: boolean; + + @equal('args.activity.fromOperation.text', 'EMPTY') + fromOperationHasEmptyText: boolean; + + @equal('args.activity.valueType', 'EMPTY') + hasEmptyText: boolean; + + @readOnly('args.activity.version.id') + showVersionInfo: boolean; + + translationKey = parsedKeyProperty(this.args.activity.translation?.key); + + get activityItemClassName() { + return dasherize(this.args.activity.action); + } + + get actionText() { + return this.getActionText(this.action); + } + + get rollbackedOperationActionText() { + return this.getActionText(this.args.activity.rollbackedOperation.action); + } + + get showFromOperationTranslationLink() { + return ( + this.args.showTranslationLink && + this.args.activity.rollbackedOperation && + this.args.activity.rollbackedOperation.translation && + this.args.activity.rollbackedOperation.translation.id + ); + } + + get showStats() { + return this.args.activity.stats; + } + + get localizedStats() { + return this.args.activity.stats.map((stat: any) => { + const text = this.intl.t( + `components.${ + this.args.componentTranslationPrefix + }.stats_text.${underscore(stat.action)}` + ); + + const count = stat.count; + + return {text, count}; + }); + } + + get statsLabel() { + return this.intl.t( + `components.${this.args.componentTranslationPrefix}.stats_label_text` + ); + } + + get showDocumentInfo() { + const action = this.action; + const actionsWithDocument = ['sync', 'document_delete', 'merge']; + + return ( + actionsWithDocument.includes(action) && + this.args.activity.document && + this.args.activity.document.path + ); + } + + get revisionName() { + return ( + this.args.activity.revision.name || + this.args.activity.revision.language.name + ); + } + + get showRevisionInfo() { + if (!this.args.activity.revision) return false; + + const actionsWithRevision = [ + 'new', + 'remove', + 'renew', + 'new_slave', + 'merge', + 'uncorrect_all', + 'correct_all', + 'batch_correct_conflict', + 'batch_update', + 'conflict_on_slave', + ]; + + return ( + actionsWithRevision.includes(this.action) && + this.args.activity.revision.language.id + ); + } + + get showFromOperationDocumentInfo() { + const action = this.args.activity.rollbackedOperation.action; + const actionsWithDocument = ['sync', 'document_delete', 'merge']; + + return ( + actionsWithDocument.includes(action) && + this.args.activity.rollbackedOperation.document.path + ); + } + + get isShowingTranslationLink() { + return ( + this.args.showTranslationLink && + this.args.activity.translation && + this.args.activity.action !== 'rollback' + ); + } + + get iconPath() { + return ACTIONS_ICON_PATHS[this.action] || 'assets/add.svg'; + } + + private getActionText(action: keyof typeof ACTIONS_ICON_PATHS) { + return this.intl.t( + `components.${this.args.componentTranslationPrefix}.action_text.${action}` + ); + } +} diff --git a/webapp/app/pods/components/activity-item/styles.scss b/webapp/app/pods/components/activity-item/styles.scss index c0a4d72f..ff62fa3c 100644 --- a/webapp/app/pods/components/activity-item/styles.scss +++ b/webapp/app/pods/components/activity-item/styles.scss @@ -1,4 +1,8 @@ -& { +@value transition-speed, transition-easing from 'accent-webapp/styles/variables/transitions'; +@value color-border, color-light-background, color-green, color-grey, color-error, color-success, color-warning, color-black from 'accent-webapp/styles/variables/colors'; +@value font-monospace from 'accent-webapp/styles/variables/fonts'; + +.item { display: flex; position: relative; margin: 25px 0; @@ -10,17 +14,17 @@ } } -&.rollback, -&.merge, -&.new-slave, -&.uncorrect-all, -&.correct-all, -&.sync { - left: 9px; +.item.rollback, +.item.merge, +.item.new-slave, +.item.uncorrect-all, +.item.correct-all, +.item.sync { + left: 8px; width: calc(100% + -9px); padding: 5px; background: #fff; - border: 1px solid rgba($color-border, 0.5); + border: 1px solid rgba(color-border, 0.5); .item-iconContainer { top: 3px; @@ -29,29 +33,35 @@ .item-content { width: 100%; - padding: 5px 5px 0; + padding: 5px 5px 0 2px; margin-left: -21px; background: #fff; border-bottom: 0; } } -&.sync { +.item.sync { + position: relative; padding: 6px 10px 5px; - background: $color-light-background; border-color: transparent; - border-left-color: $color-green; - border-left-color: var(--color-primary); - &.compact { - .item-content { - padding-left: 0; - } + &:before { + display: block; + position: absolute; + top: 0; + left: 0; + content: ''; + width: 100%; + height: 100%; + background: var(--color-primary); + box-shadow: 0 1px 10px var(--color-primary); + opacity: 0.16; + pointer-events: none; } .item-iconContainer { left: -21px; - background: $color-green; + background: color-green; background: var(--color-primary); border-color: transparent; box-shadow: none; @@ -63,63 +73,52 @@ .item-stats { padding: 0; - background: lighten($color-green, 46%); - background: var(--color-primary-lighten-99); - color: darken($color-green, 25%); + background: transparent; + color: darken(color-green, 25%); color: var(--color-primary-darken-50); } .item-date { - color: $color-grey; + color: rgba(#000, 0.3); } .item-details-link { - color: $color-green; + color: color-green; color: var(--color-primary); } .item-content { background: var(--color-primary-lighten-95); - font-size: 14px; } .item-documentPath { - color: darken($color-green, 25%); + color: darken(color-green, 25%); color: var(--color-primary-darken-30); - font-size: 13px; } .item-user, .item-header-content { - color: darken($color-green, 25%); + color: darken(color-green, 25%); color: var(--color-primary-darken-30); - font-size: 13px; - } - - .item-user.item-user--bot { - padding-left: 23px; - } - - .item-user.item-user--pictureUrl { - padding-left: 28px; } .item-user-icon { - stroke: darken($color-green, 25%); + stroke: darken(color-green, 25%); stroke: var(--color-primary); - width: 17px; - height: 17px; - } - - .item-user-picture { - top: -1px; - width: 21px; - height: 21px; + color: rgba(color-black, 0.9); } &.compact { + .item-content { + padding-left: 0; + } + + .item-header { + margin-bottom: 0; + } + .item-iconContainer-icon { - stroke: $color-green; + stroke: color-green; stroke: var(--color-primary); } @@ -139,9 +138,9 @@ } } -&.rollback { - background: $color-light-background; - border: 1px solid rgba($color-border, 0.3); +.item.rollback { + background: color-light-background; + border: 1px solid rgba(color-border, 0.3); .item-header { margin-bottom: 4px; @@ -158,14 +157,14 @@ .item-content { padding: 5px 0 0; margin: 0; - background: $color-light-background; + background: color-light-background; border-bottom: 0; } } -&.uncorrect-all { +.item.uncorrect-all { .item-iconContainer { - background: $color-error; + background: color-error; border-color: transparent; } @@ -175,20 +174,20 @@ &.compact { .item-iconContainer-icon { - stroke: $color-error; + stroke: color-error; } } } -&.correct-all { +.item.correct-all { &.compact { .item-iconContainer-icon { - stroke: $color-success; + stroke: color-success; } } .item-iconContainer { - background: $color-success; + background: color-success; border-color: transparent; } @@ -197,11 +196,11 @@ } } -&.document-delete { - border-color: lighten($color-error, 35%); +.item.document-delete { + border-color: lighten(color-error, 35%); .item-iconContainer { - background: $color-error; + background: color-error; border-color: transparent; } @@ -211,57 +210,57 @@ &.compact { .item-iconContainer-icon { - stroke: $color-error; + stroke: color-error; } } } -&.correct-conflict { +.item.correct-conflict { .item-iconContainer { - border-color: rgba($color-success, 0.4); + border-color: rgba(color-success, 0.4); } .item-iconContainer-icon { - stroke: $color-success; + stroke: color-success; } } -&.uncorrect-conflict { +.item.uncorrect-conflict { .item-iconContainer { - border-color: rgba($color-error, 0.2); + border-color: rgba(color-error, 0.2); } .item-iconContainer-icon { - stroke: $color-error; + stroke: color-error; } } -&.conflict-on-corrected { +.item.conflict-on-corrected { .item-iconContainer { - border-color: lighten($color-error, 35%); + border-color: lighten(color-error, 35%); } .item-iconContainer-icon { - stroke: $color-error; + stroke: color-error; } } -&.conflict-on-proposed { +.item.conflict-on-proposed { .item-iconContainer { - border-color: lighten($color-warning, 25%); + border-color: lighten(color-warning, 25%); } .item-iconContainer-icon { - stroke: $color-warning; + stroke: color-warning; } } -&.rollbacked { +.item.rollbacked { .item-stats, .item-translationText, .item-actions, .item-header { - opacity: 0.4; + opacity: 0.6; font-size: 12px; } @@ -272,13 +271,13 @@ .item-iconContainer { background: #fff; - border-color: rgba($color-grey, 0.4); + border-color: rgba(color-grey, 0.4); } .item-iconContainer-icon { width: 11px; height: 11px; - stroke: rgba($color-grey, 0.5); + stroke: rgba(color-grey, 0.5); } &.rollback, @@ -286,7 +285,7 @@ &.new-slave, &.uncorrect-all, &.correct-all { - border-color: $color-border; + border-color: color-border; .item-iconContainer { left: -19px; @@ -295,7 +294,11 @@ } &.sync { - border-color: rgba($color-green, 0.1); + border-color: rgba(color-green, 0.1); + + &:before { + display: none; + } .item-iconContainer { left: -19px; @@ -304,7 +307,7 @@ } } -&.rollback.compact { +.item.rollback.compact { .item-iconContainer { top: -2px; left: -17px; @@ -316,8 +319,8 @@ } } -&.rollbacked.compact, -&.compact { +.item.rollbacked.compact, +.item.compact { width: 100%; margin: 12px 0 2px; border-color: transparent; @@ -395,6 +398,10 @@ width: 15px; height: 15px; } + + .item-details-link { + color: rgba(color-black, 0.4); + } } .item-wrapper { @@ -406,7 +413,7 @@ display: inline-flex; align-items: baseline; font-size: 12px; - font-family: $font-monospace; + font-family: font-monospace; color: #aaa; } @@ -421,7 +428,7 @@ height: 21px; margin-right: 10px; border-radius: 50%; - border: 1px solid $color-grey; + border: 1px solid color-grey; box-shadow: 0 0 0 5px #fff; background: #fff; } @@ -430,7 +437,7 @@ width: 11px; height: 11px; flex: 0 0 11px; - stroke: $color-grey; + stroke: color-grey; } .item-content { @@ -438,7 +445,7 @@ font-size: 13px; } -&.compact { +.item.compact { .item-header { flex-direction: column; } @@ -498,7 +505,7 @@ margin-left: 2px; width: 14px; height: 14px; - color: #565656; + color: rgba(color-black, 0.6); } .item-translationFromOperationText, @@ -506,7 +513,7 @@ .item-translationText { margin: 5px 0 10px; padding: 8px; - background: $color-light-background; + background: color-light-background; font-size: 12px; font-style: italic; } @@ -536,7 +543,7 @@ .item-documentPath { display: inline-block; - color: $color-black; + color: color-black; color: var(--color-black); font-weight: bold; font-size: 12px; @@ -555,12 +562,12 @@ text-decoration: none; font-size: 12px; font-weight: bold; - transition: $transition-speed $transition-easing; + transition: transition-speed transition-easing; transition-property: color; &:hover, &:focus { - color: $color-green; + color: color-green; color: var(--color-primary); } @@ -579,7 +586,7 @@ .item-revisionLink { display: inline-block; text-decoration: none; - color: $color-green; + color: color-green; color: var(--color-primary); &:hover, @@ -596,7 +603,7 @@ } .item-date { - color: $color-grey; + color: rgba(#000, 0.3); font-size: 11px; } @@ -606,18 +613,18 @@ } .item-rollback { - transition: $transition-speed $transition-easing; + transition: transition-speed transition-easing; transition-property: opacity, color; opacity: 0; background: none; padding: 0; margin: 0 0 0 5px; - color: $color-grey; + color: color-grey; font-size: 11px; &:focus, &:hover { - color: darken($color-grey, 25%); + color: darken(color-grey, 25%); text-decoration: underline; } } @@ -649,21 +656,21 @@ margin-left: 5px; border-left: 1px solid #ddd; text-decoration: none; - color: $color-grey; + color: color-grey; font-size: 11px; font-weight: 500; &:focus, &:hover { text-decoration: underline; - color: $color-green; + color: color-green; color: var(--color-primary); } } .item-content-rollbacked { margin-bottom: 6px; - color: $color-error; + color: color-error; font-size: 12px; font-weight: 500; } diff --git a/webapp/app/pods/components/activity-item/template.hbs b/webapp/app/pods/components/activity-item/template.hbs index 432aa116..8305d81a 100644 --- a/webapp/app/pods/components/activity-item/template.hbs +++ b/webapp/app/pods/components/activity-item/template.hbs @@ -1,219 +1,219 @@ -
  • - - {{inline-svg iconPath class="item-iconContainer-icon"}} - -
    - {{#if activity.isRollbacked}} -
    - {{t "components.activity_item.rollbacked"}} - -
    - {{/if}} - -
    -
    - {{#if activity.user.isBot}} - - {{inline-svg "assets/bot.svg" class="item-user-icon"}} - {{activity.user.fullname}} +
    +
  • + + {{inline-svg this.iconPath local-class="item-iconContainer-icon"}} + +
    + {{#if @activity.isRollbacked}} +
    + {{t "components.activity_item.rollbacked"}} + + - {{else}} - - {{#if activity.user.pictureUrl}} - - {{/if}} - {{activity.user.fullname}} - - {{/if}} +
    + {{/if}} - {{actionText}} - - {{#if showDocumentInfo}} - - {{activity.document.path}} - - {{/if}} - - {{#if showVersionInfo}} - - {{activity.version.tag}} - - {{/if}} - - {{#if showRevisionInfo}} - - {{revisionName}} - - {{/if}} - - {{#if isShowingTranslationLink}} - {{#if activity.translation.isRemoved}} - - - {{#if translationKey.prefix}} - {{translationKey.prefix}} - {{else}} - {{translation.document.path}} - {{/if}} - - {{translationKey.value}} - +
    +
    + {{#if @activity.user.isBot}} + + {{inline-svg "assets/bot.svg" local-class="item-user-icon"}} + {{@activity.user.fullname}} + {{else}} - - - {{#if translationKey.prefix}} - {{translationKey.prefix}} - {{else}} - {{translation.document.path}} - {{/if}} - - {{translationKey.value}} + {{#if @activity.user.pictureUrl}} + + {{/if}} + {{@activity.user.fullname}} + + {{/if}} + + {{this.actionText}} + + {{#if this.showDocumentInfo}} + + {{@activity.document.path}} {{/if}} - {{/if}} -
    -
    - - - {{t "components.activity_item.details"}} - -
    -
    + {{#if this.showVersionInfo}} + + {{@activity.version.tag}} + + {{/if}} - {{#if activity.rollbackedOperation}} -
    -
    - - {{activity.rollbackedOperation.user.fullname}} - - {{rollbackedOperationActionText}} + {{#if this.showRevisionInfo}} + + {{this.revisionName}} + + {{/if}} - {{#if showFromOperationTranslationLink}} - {{#if activity.rollbackedOperation.translation.isRemoved}} + {{#if this.isShowingTranslationLink}} + {{#if @activity.translation.isRemoved}} - {{activity.rollbackedOperation.translation.key}} + + {{#if this.translationKey.prefix}} + {{this.translationKey.prefix}} + {{else}} + {{@activity.document.path}} + {{/if}} + + {{this.translationKey.value}} {{else}} - {{activity.rollbackedOperation.translation.key}} + + {{#if this.translationKey.prefix}} + {{this.translationKey.prefix}} + {{else}} + {{@activity.document.path}} + {{/if}} + + {{this.translationKey.value}} {{/if}} {{/if}} - - {{#if activity.fromOperation.text}} -
    - {{activity.fromOperation.text}} -
    - {{else if fromOperationHasEmptyText}} -
    - - {{t "components.activity_item.empty_text"}} - -
    - {{/if}} - - {{#if showFromOperationDocumentInfo}} - - {{activity.rollbackedOperation.document.path}} - - {{/if}}
    - {{#unless compact}} - +
    + {{t "components.activity_item.details"}} - {{/unless}} +
    - {{/if}} - {{#if activity.text}} -
    -
    {{activity.text}}
    -
    - {{else if hasEmptyText}} -
    - - {{t "components.activity_item.empty_text"}} - -
    - {{/if}} + {{#if @activity.rollbackedOperation}} +
    +
    + + {{@activity.rollbackedOperation.user.fullname}} + + {{this.rollbackedOperationActionText}} - {{#if showStats}} -
      - - {{statsLabel}} - - {{#each localizedStats as |stat|}} -
    • - {{stat.text}} - : - - {{stat.count}} - -
    • - {{/each}} -
    - {{/if}} -
    -
  • + {{#if this.showFromOperationTranslationLink}} + {{#if @activity.rollbackedOperation.translation.isRemoved}} + + {{@activity.rollbackedOperation.translation.key}} + + {{else}} + + {{@activity.rollbackedOperation.translation.key}} + + {{/if}} + {{/if}} + + {{#if @activity.fromOperation.text}} +
    + {{@activity.fromOperation.text}} +
    + {{else if this.fromOperationHasEmptyText}} +
    + + {{t "components.activity_item.empty_text"}} + +
    + {{/if}} + + {{#if this.showFromOperationDocumentInfo}} + + {{@activity.rollbackedOperation.document.path}} + + {{/if}} +
    + + {{#unless @compact}} + + + + + {{t "components.activity_item.details"}} + + {{/unless}} +
    + {{/if}} + + {{#if @activity.text}} +
    +
    {{@activity.text}}
    +
    + {{else if this.hasEmptyText}} +
    + + {{t "components.activity_item.empty_text"}} + +
    + {{/if}} + + {{#if this.showStats}} +
      + + {{this.statsLabel}} + + {{#each this.localizedStats as |stat|}} +
    • + {{stat.text}} + : + + {{stat.count}} + +
    • + {{/each}} +
    + {{/if}} + + + diff --git a/webapp/app/pods/components/application-footer/component.js b/webapp/app/pods/components/application-footer/component.js deleted file mode 100644 index ce31d269..00000000 --- a/webapp/app/pods/components/application-footer/component.js +++ /dev/null @@ -1,5 +0,0 @@ -import Component from '@ember/component'; - -export default Component.extend({ - tagName: 'footer' -}); diff --git a/webapp/app/pods/components/application-footer/component.ts b/webapp/app/pods/components/application-footer/component.ts new file mode 100644 index 00000000..13c8e9ab --- /dev/null +++ b/webapp/app/pods/components/application-footer/component.ts @@ -0,0 +1,3 @@ +import Component from '@glimmer/component'; + +export default class ApplicationFooter extends Component {} diff --git a/webapp/app/pods/components/application-footer/styles.scss b/webapp/app/pods/components/application-footer/styles.scss index db4a414b..71b742eb 100644 --- a/webapp/app/pods/components/application-footer/styles.scss +++ b/webapp/app/pods/components/application-footer/styles.scss @@ -1,8 +1,10 @@ -& { +@value color-light-background, color-grey from 'accent-webapp/styles/variables/colors'; + +.footer { padding: 10px; margin-top: 40px; - background: $color-light-background; - color: $color-grey; + background: color-light-background; + color: color-grey; font-size: 12px; text-align: right; } diff --git a/webapp/app/pods/components/application-footer/template.hbs b/webapp/app/pods/components/application-footer/template.hbs index 80f5b408..f56bceaa 100644 --- a/webapp/app/pods/components/application-footer/template.hbs +++ b/webapp/app/pods/components/application-footer/template.hbs @@ -1,8 +1,10 @@ -
    -
    - {{t "components.application_footer.text"}} - - {{t "general.company_name"}} - +
    + diff --git a/webapp/app/pods/components/async-button/component.js b/webapp/app/pods/components/async-button/component.js deleted file mode 100644 index 9c780078..00000000 --- a/webapp/app/pods/components/async-button/component.js +++ /dev/null @@ -1,18 +0,0 @@ -import {reads} from '@ember/object/computed'; -import Component from '@ember/component'; - -export default Component.extend({ - classNameBindings: [':button', 'loading:button--loading'], - tagName: 'button', - attributeBindings: ['disabled', 'type'], - - disabled: reads('loading'), - loading: false, - - click() { - if (this.disabled) return; - const click = this.onClick; - - if (typeof click === 'function') click(); - } -}); diff --git a/webapp/app/pods/components/async-button/component.ts b/webapp/app/pods/components/async-button/component.ts new file mode 100644 index 00000000..c4688ec9 --- /dev/null +++ b/webapp/app/pods/components/async-button/component.ts @@ -0,0 +1,21 @@ +import Component from '@glimmer/component'; +import {action} from '@ember/object'; + +interface Args { + onClick: () => void; + loading?: boolean; + disabled?: boolean; +} + +export default class AsyncButton extends Component { + get disabled() { + return this.args.disabled || this.args.loading; + } + + @action + onClick() { + if (this.args.disabled) return; + + if (typeof this.args.onClick === 'function') this.args.onClick(); + } +} diff --git a/webapp/app/pods/components/async-button/styles.scss b/webapp/app/pods/components/async-button/styles.scss index 9d4e959b..cf5f2ec9 100644 --- a/webapp/app/pods/components/async-button/styles.scss +++ b/webapp/app/pods/components/async-button/styles.scss @@ -1,5 +1,8 @@ -& { - padding: 0; +@value transition-speed, transition-easing from 'accent-webapp/styles/variables/transitions'; +@value color-black from 'accent-webapp/styles/variables/colors'; + +.button { + padding: 0 !important; &.button--loading { cursor: default; @@ -14,13 +17,13 @@ } } - &.button--filled { + &:global(.button--filled) { .loading { fill: #fff; } } - &.button--small { + &:global(.button--small) { &.button--loading { .loading { width: 14px; @@ -40,7 +43,7 @@ } .label { - transition: $transition-speed $transition-easing; + transition: transition-speed transition-easing; transition-property: transform; transform: translate3d(0, 0, 0); display: flex; @@ -49,12 +52,12 @@ } .loading { - transition: $transition-speed $transition-easing; + transition: transition-speed transition-easing; transition-property: left; will-change: left; width: 15px; position: absolute; top: calc(50% - 8px); left: 100%; - fill: $color-black; + fill: color-black; } diff --git a/webapp/app/pods/components/async-button/template.hbs b/webapp/app/pods/components/async-button/template.hbs index 6853941d..47e286c8 100644 --- a/webapp/app/pods/components/async-button/template.hbs +++ b/webapp/app/pods/components/async-button/template.hbs @@ -1,5 +1,13 @@ -
    - {{yield}} +
    + diff --git a/webapp/app/pods/components/commit-file/component.js b/webapp/app/pods/components/commit-file/component.js deleted file mode 100644 index cff23717..00000000 --- a/webapp/app/pods/components/commit-file/component.js +++ /dev/null @@ -1,267 +0,0 @@ -import {computed} from '@ember/object'; -import {inject as service} from '@ember/service'; -import {equal} from '@ember/object/computed'; -import Component from '@ember/component'; - -const DEFAULT_PROPERTIES = { - isFileReading: false, - isFileRead: false, - isPeeking: false, - isPeekingDone: false, - isPeekingError: false, - isCommiting: false, - isCommitingDone: false, - isCommitingError: false, - - file: null, - fileSource: null, - documentPath: null, - documentFormat: 'json' -}; - -// Attributes -// permissions: Ember Object containing -// revisions: Array of -// documents: Array of -// commitButtonText: String -// onFileCancel: Function -// onPeek: Function -// onCommit: Function -export default Component.extend({ - intl: service('intl'), - globalState: service('global-state'), - - init(...args) { - this._super(...args); - - this._initProperties(); - }, - - mergeTypes: ['smart', 'passive', 'force'], - syncTypes: ['smart', 'passive'], - - syncType: computed('mappedSyncTypes.[]', function() { - return this.mappedSyncTypes[0]; - }), - mergeType: computed('mappedMergeTypes.[]', function() { - return this.mappedMergeTypes[0]; - }), - - revisionValue: computed('revision', 'mappedRevisions.[]', function() { - return ( - this.mappedRevisions.find(({value}) => value === this.revision) || - this.mappedRevisions[0] - ); - }), - - mappedMergeTypes: computed('mergeTypes.[]', function() { - return this.mergeTypes.map(name => ({ - label: name, - value: name - })); - }), - - mappedSyncTypes: computed('syncTypes.[]', function() { - return this.syncTypes.map(name => ({ - label: name, - value: name - })); - }), - - mappedRevisions: computed('revisions.[]', function() { - return this.revisions.map(({id, language}) => ({ - label: language.name, - value: id - })); - }), - - revision: computed('revisions.[]', function() { - return this.revisions.find(revision => revision.isMaster); - }), - - isMerge: equal('commitAction', 'merge'), - isSync: equal('commitAction', 'sync'), - - documentFormatValue: computed( - 'documentFormat', - 'documentFormatOptions', - function() { - return this.documentFormatOptions.find( - ({value}) => value === this.documentFormat - ); - } - ), - - documentFormatOptions: computed('globalState.documentFormats', function() { - if (!this.globalState.documentFormats) return []; - - return this.globalState.documentFormats.map(({slug, name}) => ({ - value: slug, - label: name - })); - }), - - existingDocumentPath: computed( - 'documentPath', - 'documents.[].path', - function() { - if (!this.documentPath) return false; - if (!this.documents) return false; - - const path = this.documentPath.replace(/\..+/, ''); - - return this.documents.find(document => document.path === path); - } - ), - - actions: { - onSelectMergeType(mergeType) { - this.set('mergeType', mergeType); - }, - - onSelectSyncType(syncType) { - this.set('syncType', syncType); - }, - - onSelectRevision(revision) { - this.set( - 'revision', - this.revisions.find(({id}) => id === revision.value) - ); - this.set('revisionValue', revision); - }, - - commit() { - this._onCommiting(); - - this.onCommit( - this.getProperties( - 'fileSource', - 'documentPath', - 'documentFormat', - 'revision', - 'mergeType', - 'syncType' - ) - ) - .then(this._onCommitingDone.bind(this)) - .catch(this._onCommitingError.bind(this)); - }, - - peek() { - this._onPeeking(); - - this.onPeek( - this.getProperties( - 'fileSource', - 'documentPath', - 'documentFormat', - 'revision', - 'mergeType', - 'syncType' - ) - ) - .then(this._onPeekingDone.bind(this)) - .catch(this._onPeekingError.bind(this)); - }, - - fileChange(files) { - const fileSource = files[0]; - const filename = fileSource.name.split('.'); - const fileExtension = filename.pop(); - - const documentPath = filename.join('.'); - const documentFormat = this._formatFromExtension(fileExtension); - const isFileReading = true; - const isFileRead = false; - const reader = new FileReader(); - - this.setProperties({ - fileSource, - documentPath, - isFileReading, - isFileRead, - documentFormat - }); - - reader.onload = this._fileRead.bind(this); - reader.readAsText(files[0]); - }, - - fileCancel() { - this.onFileCancel(); - - this._initProperties(); - } - }, - - _formatFromExtension(fileExtension) { - if (!this.globalState.documentFormats) return null; - - const documentFormatItem = this.globalState.documentFormats.find( - ({extension}) => extension === fileExtension - ); - - return documentFormatItem - ? documentFormatItem.slug - : this.globalState.documentFormats[0].slug; - }, - - /** - * Called after a file is read. - * - * @private - * @method - * @param {ProgressEvent} result Native progress event containing the file raw content and infos - */ - _fileRead(file) { - const isFileReading = false; - const isFileRead = true; - - this.setProperties({ - isFileReading, - isFileRead, - file - }); - - this.send('peek'); - }, - - _onCommiting() { - this.setProperties({ - isCommiting: true, - isCommitingDone: false, - isCommitingError: false, - isPeekingError: false - }); - }, - - _onCommitingDone() { - this.setProperties({isCommiting: false, isCommitingDone: true}); - }, - - _onCommitingError() { - this.setProperties({isCommiting: false, isCommitingError: true}); - }, - - _onPeeking() { - this.setProperties({ - isPeeking: true, - isPeekingDone: false, - isPeekingError: false, - isCommitingError: false - }); - }, - - _onPeekingDone() { - this.setProperties({isPeeking: false, isPeekingDone: true}); - }, - - _onPeekingError() { - this.setProperties({isPeeking: false, isPeekingError: true}); - }, - - _initProperties() { - this.setProperties(DEFAULT_PROPERTIES); - } -}); diff --git a/webapp/app/pods/components/commit-file/component.ts b/webapp/app/pods/components/commit-file/component.ts new file mode 100644 index 00000000..046e7cf8 --- /dev/null +++ b/webapp/app/pods/components/commit-file/component.ts @@ -0,0 +1,328 @@ +import {action} from '@ember/object'; +import {inject as service} from '@ember/service'; +import {equal} from '@ember/object/computed'; +import Component from '@glimmer/component'; +import IntlService from 'ember-intl/services/intl'; +import GlobalState from 'accent-webapp/services/global-state'; +import {tracked} from '@glimmer/tracking'; + +const DEFAULT_PROPERTIES = { + isFileReading: false, + isFileRead: false, + isPeeking: false, + isPeekingDone: false, + isPeekingError: false, + isCommiting: false, + isCommitingDone: false, + isCommitingError: false, + + file: null, + fileSource: null, + documentPath: null, + documentFormat: 'json', +}; + +interface Args { + permissions: Record; + revisions: any; + documents: any; + canCommit: boolean; + commitAction: 'merge' | 'sync'; + peekAction: 'peek_merge' | 'peek_sync'; + commitButtonText: string; + onFileCancel: () => void; + onPeek: (options: { + fileSource: any; + documentPath: string | null; + documentFormat: any; + revision: any; + mergeType: string; + syncType: string; + }) => Promise; + onCommit: (options: { + fileSource: any; + documentPath: string | null; + documentFormat: any; + revision: any; + mergeType: string; + syncType: string; + }) => Promise; +} + +export default class CommitFile extends Component { + @service('intl') + intl: IntlService; + + @service('global-state') + globalState: GlobalState; + + @equal('args.commitAction', 'merge') + isMerge: boolean; + + @equal('args.commitAction', 'sync') + isSync: boolean; + + mergeTypes = ['smart', 'passive', 'force']; + syncTypes = ['smart', 'passive']; + + @tracked + isFileReading = DEFAULT_PROPERTIES.isFileReading; + + @tracked + isFileRead = DEFAULT_PROPERTIES.isFileRead; + + @tracked + isPeeking = DEFAULT_PROPERTIES.isPeeking; + + @tracked + isPeekingDone = DEFAULT_PROPERTIES.isPeekingDone; + + @tracked + isPeekingError = DEFAULT_PROPERTIES.isPeekingError; + + @tracked + isCommiting = DEFAULT_PROPERTIES.isCommiting; + + @tracked + isCommitingDone = DEFAULT_PROPERTIES.isCommitingDone; + + @tracked + isCommitingError = DEFAULT_PROPERTIES.isCommitingError; + + @tracked + file: ProgressEvent | null = DEFAULT_PROPERTIES.file; + + @tracked + fileSource: File | null = DEFAULT_PROPERTIES.fileSource; + + @tracked + documentPath: string | null = DEFAULT_PROPERTIES.documentPath; + + @tracked + documentFormat: string | null = DEFAULT_PROPERTIES.documentFormat; + + @tracked + mergeType = this.mappedMergeTypes[0]; + + @tracked + syncType = this.mappedSyncTypes[0]; + + @tracked + revisionValue = + this.mappedRevisions.find(({value}) => value === this.revision) || + this.mappedRevisions[0]; + + @tracked + revision = this.args.revisions.find((revision: any) => revision.isMaster); + + get mappedMergeTypes() { + return this.mergeTypes.map((name) => ({ + label: name, + value: name, + })); + } + + get mappedSyncTypes() { + return this.syncTypes.map((name) => ({ + label: name, + value: name, + })); + } + + get mappedRevisions(): Array<{label: string; value: string}> { + return this.args.revisions.map( + ({id, language}: {id: string; language: {name: string}}) => ({ + label: language.name, + value: id, + }) + ); + } + + get documentFormatValue() { + return this.documentFormatOptions.find(({value}) => { + return value === this.documentFormat; + }); + } + + get documentFormatOptions(): Array<{value: string; label: string}> { + if (!this.globalState.documentFormats) return []; + + return this.globalState.documentFormats.map(({slug, name}) => ({ + value: slug, + label: name, + })); + } + + get existingDocumentPath() { + if (!this.documentPath) return false; + if (!this.args.documents) return false; + + const path = this.documentPath.replace(/\..+/, ''); + + return this.args.documents.find((document: any) => document.path === path); + } + + @action + onSelectMergeType(mergeType: {label: string; value: string}) { + this.mergeType = mergeType; + } + + @action + onSelectSyncType(syncType: {label: string; value: string}) { + this.syncType = syncType; + } + + @action + onSelectRevision(revision: {label: string; value: string}) { + this.revision = this.args.revisions.find( + ({id}: {id: string}) => id === revision.value + ); + + this.revisionValue = revision; + } + + @action + onSelectDocumentFormat(documentFormat: {label: string; value: string}) { + this.documentFormat = documentFormat.value; + } + + @action + async commit() { + this.onCommiting(); + + try { + await this.args.onCommit({ + fileSource: this.fileSource, + documentPath: this.documentPath, + documentFormat: this.documentFormat, + revision: this.revision, + mergeType: this.mergeType.value, + syncType: this.syncType.value, + }); + + this.onCommitingDone(); + } catch (error) { + this.onCommitingError(); + } + } + + @action + async peek() { + this.onPeeking(); + + try { + await this.args.onPeek({ + fileSource: this.fileSource, + documentPath: this.documentPath, + documentFormat: this.documentFormat, + revision: this.revision, + mergeType: this.mergeType.value, + syncType: this.syncType.value, + }); + + this.onPeekingDone(); + } catch (error) { + this.onPeekingError(); + } + } + + @action + fileChange(files: File[]) { + const fileSource = files[0]; + const filename = fileSource.name.split('.'); + const fileExtension = filename.pop(); + + const documentPath = filename.join('.'); + const documentFormat = this.formatFromExtension(fileExtension); + const isFileReading = true; + const isFileRead = false; + const reader = new FileReader(); + + this.fileSource = fileSource; + this.documentPath = documentPath; + this.isFileReading = isFileReading; + this.isFileRead = isFileRead; + this.documentFormat = documentFormat; + + reader.onload = this.fileRead.bind(this); + reader.readAsText(files[0]); + } + + @action + fileCancel() { + this.args.onFileCancel(); + + this.initProperties(); + } + + private formatFromExtension(fileExtension?: string) { + if (!this.globalState.documentFormats) return null; + + const documentFormatItem = this.globalState.documentFormats.find( + ({extension}) => { + return extension === fileExtension; + } + ); + + return documentFormatItem + ? documentFormatItem.slug + : this.globalState.documentFormats[0].slug; + } + + private async fileRead(event: ProgressEvent) { + this.isFileReading = false; + this.isFileRead = true; + this.file = event; + + await this.peek(); + } + + private onCommiting() { + this.isCommiting = true; + this.isCommitingDone = false; + this.isCommitingError = false; + this.isPeekingError = false; + } + + private onCommitingDone() { + this.isCommiting = false; + this.isCommitingDone = true; + } + + private onCommitingError() { + this.isCommiting = false; + this.isCommitingError = true; + } + + private onPeeking() { + this.isPeeking = true; + this.isPeekingDone = false; + this.isPeekingError = false; + this.isCommitingError = false; + } + + private onPeekingDone() { + this.isPeeking = false; + this.isPeekingDone = true; + } + + private onPeekingError() { + this.isPeeking = false; + this.isPeekingError = true; + } + + private initProperties() { + this.isFileReading = DEFAULT_PROPERTIES.isFileReading; + this.isFileRead = DEFAULT_PROPERTIES.isFileRead; + this.isPeeking = DEFAULT_PROPERTIES.isPeeking; + this.isPeekingDone = DEFAULT_PROPERTIES.isPeekingDone; + this.isPeekingError = DEFAULT_PROPERTIES.isPeekingError; + this.isCommiting = DEFAULT_PROPERTIES.isCommiting; + this.isCommitingDone = DEFAULT_PROPERTIES.isCommitingDone; + this.isCommitingError = DEFAULT_PROPERTIES.isCommitingError; + this.file = DEFAULT_PROPERTIES.file; + this.fileSource = DEFAULT_PROPERTIES.fileSource; + this.documentPath = DEFAULT_PROPERTIES.documentPath; + this.documentFormat = DEFAULT_PROPERTIES.documentFormat; + } +} diff --git a/webapp/app/pods/components/commit-file/styles.scss b/webapp/app/pods/components/commit-file/styles.scss index 1b2daca8..3f757a16 100644 --- a/webapp/app/pods/components/commit-file/styles.scss +++ b/webapp/app/pods/components/commit-file/styles.scss @@ -1,15 +1,32 @@ -.separator { - display: block; - margin: 10px 0; - background: #eee; - height: 1px; - width: 100%; +@value color-grey, color-green, color-black, color-error from 'accent-webapp/styles/variables/colors'; +@value font-monospace from 'accent-webapp/styles/variables/fonts'; + +.commit-file { + :global(.textInput) { + @extend %textInput; + margin-bottom: 8px; + padding: 5px; + outline: 0; + border: 1px solid lighten(color-grey, 20%); + box-shadow: inset 0 2px 6px rgba(color-black, 0.05); + background: #fff; + font-family: font-monospace; + font-size: 12px; + } + + :global(.ember-power-select-trigger) { + padding: 6px 10px; + border: 1px solid rgba(color-black, 0.1); + color: rgba(color-black, 0.8); + color: var(--color-black-opacity-70); + background: #fafafa; + } } .textHelper { margin-bottom: 3px; width: 80%; - color: $color-grey; + color: color-grey; font-size: 12px; } @@ -18,30 +35,18 @@ margin-bottom: 7px; padding: 2px 4px 3px; border-radius: 4px; - background: lighten($color-green, 48%); + background: lighten(color-green, 48%); background: var(--color-primary-opacity-10); - color: $color-green; + color: color-green; color: var(--color-primary); font-size: 11px; &.documentHelper--new { - background: lighten($color-green, 48%); - color: $color-green; + background: lighten(color-green, 48%); + color: color-green; } } -.textInput { - @extend %textInput; - margin-bottom: 8px; - padding: 5px; - outline: 0; - border: 1px solid lighten($color-grey, 20%); - box-shadow: inset 0 2px 6px rgba($color-black, 0.05); - background: #fff; - font-family: $font-monospace; - font-size: 12px; -} - .options { display: flex; padding: 0; @@ -84,7 +89,7 @@ width: 15px; height: 15px; margin-right: 10px; - stroke: $color-black; + stroke: color-black; stroke: var(--color-black); } @@ -92,7 +97,7 @@ display: flex; align-items: center; margin: 0 0 6px; - color: $color-black; + color: color-black; color: var(--color-black); } @@ -101,16 +106,16 @@ margin: 0 0 10px; font-size: 14px; font-weight: 300; - color: rgba($color-black, 0.7); + color: rgba(color-black, 0.7); color: var(--color-black-opacity-70); } .fileButton { - margin-top: 7px; - padding: 9px 30px; + margin-top: 7px !important; + padding: 9px 30px !important; .button-icon { - margin-right: 10px; + margin-right: 10px !important; } } @@ -134,7 +139,7 @@ margin-bottom: 5px; font-size: 13px; font-weight: bold; - color: $color-black; + color: color-black; color: var(--color-black); } @@ -142,13 +147,13 @@ .instructions-text { margin-bottom: 18px; font-size: 13px; - color: rgba($color-black, 0.5); + color: rgba(color-black, 0.5); color: var(--color-black); em { font-style: normal; font-weight: bold; - color: rgba($color-green, 0.8); + color: rgba(color-green, 0.8); color: var(--color-primary); } } @@ -164,12 +169,12 @@ } .peekButton { - margin-top: 7px; + margin-top: 7px !important; } .errorMessage { margin: 10px 0; - color: $color-error; + color: color-error; font-size: 13px; font-weight: bold; } @@ -178,14 +183,6 @@ @extend %textInput; padding: 6px 10px; font-size: 12px; - font-family: $font-monospace; + font-family: font-monospace; color: #444; } - -.ember-power-select-trigger { - padding: 6px 10px; - border: 1px solid rgba($color-black, 0.1); - color: rgba($color-black, 0.8); - color: var(--color-black-opacity-70); - background: #fafafa; -} diff --git a/webapp/app/pods/components/commit-file/template.hbs b/webapp/app/pods/components/commit-file/template.hbs index 8cf73b72..cd6dab16 100644 --- a/webapp/app/pods/components/commit-file/template.hbs +++ b/webapp/app/pods/components/commit-file/template.hbs @@ -1,185 +1,185 @@ -
    - {{#if isPeekingError}} -
    +
    + {{#if this.isPeekingError}} +
    {{t "components.commit_file.peek_error"}}
    {{/if}} - {{#if isCommitingError}} -
    + {{#if this.isCommitingError}} +
    {{t "components.commit_file.commit_error"}}
    {{/if}} - {{#if isMerge}} - {{#if file}} -
    -
    -

    + {{#if this.isMerge}} + {{#if this.file}} +

    +
    +

    {{t "components.commit_file.language"}} :

    -
    -

    +

    +

    {{t "components.commit_file.commit_type"}} :

    {{/if}} {{/if}} - {{#if isSync}} - {{#if file}} -
    -
    -

    + {{#if this.isSync}} + {{#if this.file}} +

    +
    +

    {{t "components.commit_file.commit_type"}} :

    -
    +
    {{/if}} {{/if}} {{#if file}}
    - {{#unless document}} -
    -

    + {{#unless this.documents}} +

    +

    {{t "components.commit_file.file_source"}}

    - {{#if existingDocumentPath}} - + {{#if this.existingDocumentPath}} + {{t "components.commit_file.existing_document_warning"}} {{else}} - + {{t "components.commit_file.new_document_warning"}} {{/if}}

    - +
    {{/unless}} -
    -

    +

    +

    {{t "components.commit_file.document_format"}}

    - {{#if (get permissions peekAction)}} -
    -

    + {{#if (get @permissions @peekAction)}} +

    +

    {{t "components.commit_file.peek_help"}}

    {{t "components.commit_file.peek_button"}}
    {{/if}} - {{#if (get permissions commitAction)}} -
    + {{#if (get @permissions @commitAction)}} +
    {{t "components.commit_file.cancel_button"}} - {{#if canCommit}} + {{#if @canCommit}} - {{commitButtonText}} + {{@commitButtonText}} {{else}} - {{commitButtonText}} + {{@commitButtonText}} {{/if}}
    {{/if}}
    {{else}} -
    -
    +
    +
    - - {{inline-svg "/assets/folder.svg" class="fileInputIcon"}} + + {{inline-svg "/assets/folder.svg" local-class="fileInputIcon"}} {{t "components.commit_file.upload_title"}} -

    +

    {{t "components.commit_file.upload_help"}}

    -
    - + {{t "components.commit_file.instructions.sync.title"}} -

    +

    {{{t "components.commit_file.instructions.sync.text"}}}

    - + {{t "components.commit_file.instructions.merge.title"}} -

    +

    {{{t "components.commit_file.instructions.merge.text"}}}

    -

    +

    {{t "components.commit_file.instructions.mistakes.title"}}

    -
      -
    • {{t "components.commit_file.instructions.mistakes.item_1"}}
    • -
    • {{t "components.commit_file.instructions.mistakes.item_2"}}
    • -
    • {{t "components.commit_file.instructions.mistakes.item_3"}}
    • +
        +
      • {{t "components.commit_file.instructions.mistakes.item_1"}}
      • +
      • {{t "components.commit_file.instructions.mistakes.item_2"}}
      • +
      • {{t "components.commit_file.instructions.mistakes.item_3"}}
    diff --git a/webapp/app/pods/components/conflict-item/component.js b/webapp/app/pods/components/conflict-item/component.js deleted file mode 100644 index c9264d74..00000000 --- a/webapp/app/pods/components/conflict-item/component.js +++ /dev/null @@ -1,65 +0,0 @@ -import {computed} from '@ember/object'; -import {empty, reads} from '@ember/object/computed'; -import Component from '@ember/component'; - -import parsedKeyProperty from 'accent-webapp/computed-macros/parsed-key'; - -// Attributes: -// project: Object -// permissions: Ember Object containing -// conflict: Object -// revision: Object (optional) -// onCorrect: Function -export default Component.extend({ - classNameBindings: ['active', 'resolved', 'error:errored', 'fullscreen'], - - emptyPreviousText: empty('conflict.conflictedText'), - textInput: reads('conflict.correctedText'), - samePreviousText: computed( - 'conflict.{conflictedText,correctedText}', - function() { - return this.conflict.conflictedText === this.conflict.correctedText; - } - ), - - loading: false, - error: false, - resolved: false, - active: false, - - conflictKey: parsedKeyProperty('conflict.key'), - - actions: { - correct() { - this._onLoading(); - - this.onCorrect(this.conflict, this.textInput) - .then(this._onCorrectSuccess.bind(this)) - .catch(this._onError.bind(this)); - }, - - inputBlur() { - this.set('active', false); - }, - - inputFocus() { - this.set('active', true); - } - }, - - _onLoading() { - this.setProperties({error: false, loading: true}); - }, - - _onError() { - this.setProperties({error: true, loading: false}); - }, - - _onCorrectSuccess() { - this.setProperties({resolved: true, loading: false}); - }, - - _onUncorrectSuccess() { - this.setProperties({resolved: false, loading: false}); - } -}); diff --git a/webapp/app/pods/components/conflict-item/component.ts b/webapp/app/pods/components/conflict-item/component.ts new file mode 100644 index 00000000..eaa1da88 --- /dev/null +++ b/webapp/app/pods/components/conflict-item/component.ts @@ -0,0 +1,80 @@ +import {action} from '@ember/object'; +import {empty} from '@ember/object/computed'; +import Component from '@glimmer/component'; + +import parsedKeyProperty from 'accent-webapp/computed-macros/parsed-key'; +import {tracked} from '@glimmer/tracking'; + +interface Args { + fullscreen: boolean; + revision: any; + permissions: Record; + project: any; + conflict: any; + onCorrect: (conflict: any, textInput: string) => Promise; +} + +export default class ConflictItem extends Component { + @empty('args.conflict.conflictedText') + emptyPreviousText: boolean; + + @tracked + textInput = this.args.conflict.correctedText; + + @tracked + loading = false; + + @tracked + error = false; + + @tracked + resolved = false; + + @tracked + active = false; + + conflictKey = parsedKeyProperty(this.args.conflict.key); + + get samePreviousText() { + return ( + this.args.conflict.conflictedText === this.args.conflict.correctedText + ); + } + + @action + async correct() { + this.onLoading(); + + try { + await this.args.onCorrect(this.args.conflict, this.textInput); + this.onCorrectSuccess(); + } catch (error) { + this.onError(); + } + } + + @action + inputBlur() { + this.active = false; + } + + @action + inputFocus() { + this.active = true; + } + + private onLoading() { + this.error = false; + this.loading = true; + } + + private onError() { + this.error = true; + this.loading = false; + } + + private onCorrectSuccess() { + this.resolved = true; + this.loading = false; + } +} diff --git a/webapp/app/pods/components/conflict-item/styles.scss b/webapp/app/pods/components/conflict-item/styles.scss index 5728ab6b..fa47cc7b 100644 --- a/webapp/app/pods/components/conflict-item/styles.scss +++ b/webapp/app/pods/components/conflict-item/styles.scss @@ -1,22 +1,27 @@ -& { - transition: $transition-speed $transition-easing; +@value transition-speed, transition-easing from 'accent-webapp/styles/variables/transitions'; +@value color-light-background, color-green, color-grey, color-error, color-success, color-black from 'accent-webapp/styles/variables/colors'; + +.conflict-item { + transition: transition-speed transition-easing; transition-property: background, border-color, transform; padding: 10px; margin-bottom: 15px; + border: 1px solid transparent; + border-radius: 3px; &:nth-child(even) { - background: $color-light-background; + background: color-light-background; } &:focus, &:hover { - border-color: lighten($color-green, 40%); - border-color: var(--color-primary-opacity-10); - background: $color-light-background; + border-color: lighten(color-grey, 26%); + background: color-light-background; } &.active { - background: $color-light-background; + border-color: lighten(color-grey, 26%); + background: color-light-background; transform: scale(1.02); } } @@ -25,7 +30,7 @@ position: relative; } -&.fullscreen { +.conflict-item.fullscreen { .item-details { display: flex; align-items: stretch; @@ -43,35 +48,33 @@ } } -&[class*='resolved'] { +.conflict-item.resolved { padding: 5px 10px; - margin: 5px 0 15px; - background: lighten($color-green, 48%); - background: var(--color-primary-opacity-10); - box-shadow: 0 1px 5px lighten($color-grey, 25%); + margin: 5px 15px 15px; + background: lighten(color-green, 48%); + border: 1px solid lighten(color-green, 40%); + box-shadow: 0 1px 6px lighten(color-green, 45%); .item-key-prefix { - color: rgba($color-green, 0.7); - color: var(--color-primary-opacity-70); + color: rgba(color-green, 0.7); } .item-key { font-size: 12px; - color: $color-green; - color: var(--color-primary); + color: color-green; } } -&[class*='errored'] { +.conflict-item.errored { .textInput { - border-color: lighten($color-error, 30%); + border-color: lighten(color-error, 30%); } } .error { font-size: 12px; font-weight: bold; - color: $color-error; + color: color-error; } .item-key-prefix { @@ -84,7 +87,7 @@ .item-key { display: block; @extend %translationKeyBase; - transition: $transition-speed $transition-easing; + transition: transition-speed transition-easing; transition-property: color; margin-right: 15px; line-height: 1.5; @@ -111,9 +114,10 @@ } .correctButton { - position: absolute; - top: 6px; - right: 15px; + position: absolute !important; + top: 6px !important; + right: 15px !important; + padding: 0 !important; } .textDiff, @@ -121,36 +125,36 @@ .conflictedText-textReference { padding: 8px 0; font-size: 13px; - color: darken($color-grey, 15%); + color: darken(color-grey, 15%); } .textDiff { - border-top: 1px dashed lighten($color-grey, 20%); + border-top: 1px dashed lighten(color-grey, 20%); white-space: pre-wrap; - .added { + :global(.added) { padding: 0 3px; - background: lighten($color-success, 42%); - color: darken($color-success, 10%); + background: lighten(color-success, 42%); + color: darken(color-success, 10%); } - .removed { + :global(.removed) { padding: 0 3px; - background: lighten($color-error, 42%); - color: $color-error; + background: lighten(color-error, 42%); + color: color-error; text-decoration: line-through; } } .textConflicted { font-size: 11px; - color: lighten($color-grey, 5%); + color: lighten(color-grey, 5%); } .textConflicted-empty { font-size: 11px; font-style: italic; - color: lighten($color-grey, 10%); + color: lighten(color-grey, 10%); } .textConflicted-content { @@ -159,14 +163,14 @@ .conflictedText-textReference-link { margin-right: 4px; - color: rgba($color-black, 0.7); + color: rgba(color-black, 0.7); text-decoration: none; font-weight: normal; font-size: 12px; &:focus, &:hover { - color: $color-green; + color: color-green; color: var(--color-primary); } } @@ -187,7 +191,7 @@ font-size: 11px; font-style: italic; font-weight: normal; - color: lighten($color-grey, 10%); + color: lighten(color-grey, 10%); } .conflictedText-textReference-text-content { diff --git a/webapp/app/pods/components/conflict-item/template.hbs b/webapp/app/pods/components/conflict-item/template.hbs index b2b4ed9c..313445df 100644 --- a/webapp/app/pods/components/conflict-item/template.hbs +++ b/webapp/app/pods/components/conflict-item/template.hbs @@ -1,108 +1,111 @@ -
  • - - - - {{#if conflictKey.prefix}} - {{conflictKey.prefix}} - {{else}} - {{conflict.document.path}} - {{/if}} - - {{conflictKey.value}} - - - - {{#if resolved}} -
    -
    - {{#if error}} -
    - {{t "components.conflict_item.uncorrect_error_text"}} -
    - {{/if}} -
    -
    - {{else}} -
    -
    -
    - {{#if emptyPreviousText}} - - {{t "components.conflict_item.no_previous_text"}} - - {{else if samePreviousText}} - - {{t "components.conflict_item.same_text"}} - +
    +
  • + + + + {{#if this.conflictKey.prefix}} + {{this.conflictKey.prefix}} {{else}} - {{conflict.conflictedText}} + {{@conflict.document.path}} + {{/if}} + + {{this.conflictKey.value}} + + + + {{#if this.resolved}} +
    +
    + {{#if this.error}} +
    + {{t "components.conflict_item.uncorrect_error_text"}} +
    {{/if}}
    - - {{#if emptyPreviousText}} -
    {{conflict.correctedText}}
    - {{else if samePreviousText}} -
    {{conflict.correctedText}}
    - {{else}} -
    {{string-diff conflict.correctedText conflict.conflictedText}}
    - {{/if}} - - {{#if conflict.relatedTranslation.id}} -
    - - - {{revision.language.name}} - - - +
    + {{else}} +
    +
    +
    + {{#if this.emptyPreviousText}} + + {{t "components.conflict_item.no_previous_text"}} - -
    - {{conflict.relatedTranslation.correctedText}} + {{else if this.samePreviousText}} + + {{t "components.conflict_item.same_text"}} + + {{else}} + {{@conflict.conflictedText}} + {{/if}} +
    + + {{#if this.emptyPreviousText}} +
    {{@conflict.correctedText}}
    + {{else if this.samePreviousText}} +
    {{@conflict.correctedText}}
    + {{else}} +
    {{string-diff @conflict.correctedText @conflict.conflictedText}}
    + {{/if}} + + {{#if @conflict.relatedTranslation.id}} +
    + + + {{@revision.language.name}} + + + + + +
    + {{@conflict.relatedTranslation.correctedText}} +
    -
    - {{/if}} - {{#if error}} -
    - {{t "components.conflict_item.correct_error_text"}} -
    - {{/if}} -
    -
    -
    - + {{/if}} + {{#if this.error}} +
    + {{t "components.conflict_item.correct_error_text"}} +
    + {{/if}} +
    +
    +
    + +
    + {{#if (get @permissions "correct_translation")}} + + {{inline-svg "/assets/check.svg" class="button-icon"}} + {{t "components.conflict_item.correct_button_text"}} + + {{/if}}
    - {{#if (get permissions "correct_translation")}} - - {{inline-svg "/assets/check.svg" class="button-icon"}} - {{t "components.conflict_item.correct_button_text"}} - - {{/if}}
    -
    - {{/if}} -
  • + {{/if}} + +
    diff --git a/webapp/app/pods/components/conflicts-filters/component.js b/webapp/app/pods/components/conflicts-filters/component.js deleted file mode 100644 index d6aeb6e4..00000000 --- a/webapp/app/pods/components/conflicts-filters/component.js +++ /dev/null @@ -1,84 +0,0 @@ -import {observer, computed} from '@ember/object'; -import {inject as service} from '@ember/service'; -import {notEmpty, gt, reads} from '@ember/object/computed'; -import Component from '@ember/component'; -import {run} from '@ember/runloop'; - -const DEBOUNCE_OFFSET = 500; // ms - -// Attributes: -// query: String -// reference: String -// referenceRevisions: Array of -// document: Object -// documents: Array of -// onChangeQuery: Function -// onChangeReference: Function -// onChangeDocument: Function -export default Component.extend({ - intl: service('intl'), - - showReferenceRevisionsSelect: notEmpty('referenceRevisions'), - showDocumentsSelect: gt('documents.length', 1), - debouncedQuery: reads('query'), - - queryDidChanges: observer('debouncedQuery', function() { - run.debounce(this, this._debounceQuery, DEBOUNCE_OFFSET); - }), - - mappedDocuments: computed('documents.[]', function() { - const documents = this.documents.map(({id, path}) => ({ - label: path, - value: id - })); - - documents.unshift({ - label: this.intl.t( - 'components.conflicts_filters.document_default_option_text' - ), - value: null - }); - - return documents; - }), - - mappedReferenceRevisions: computed('referenceRevisions.[]', function() { - const revisions = this.referenceRevisions.map(({id, language}) => ({ - label: language.name, - value: id - })); - - revisions.unshift({ - label: this.intl.t( - 'components.conflicts_filters.reference_default_option_text' - ), - value: null - }); - - return revisions; - }), - - documentValue: computed('document', 'mappedDocuments.[]', function() { - return this.mappedDocuments.find(({value}) => value === this.document); - }), - - referenceValue: computed( - 'reference', - 'mappedReferenceRevisions.[]', - function() { - return this.mappedReferenceRevisions.find( - ({value}) => value === this.reference - ); - } - ), - - _debounceQuery() { - this.onChangeQuery(this.debouncedQuery); - }, - - actions: { - submitForm() { - this._debounceQuery(); - } - } -}); diff --git a/webapp/app/pods/components/conflicts-filters/component.ts b/webapp/app/pods/components/conflicts-filters/component.ts new file mode 100644 index 00000000..f4f09805 --- /dev/null +++ b/webapp/app/pods/components/conflicts-filters/component.ts @@ -0,0 +1,111 @@ +import {action} from '@ember/object'; +import {inject as service} from '@ember/service'; +import {notEmpty, gt} from '@ember/object/computed'; +import Component from '@glimmer/component'; +import IntlService from 'ember-intl/services/intl'; +import {PaginationMeta} from 'accent-webapp/pods/components/resource-pagination/component'; +import {tracked} from '@glimmer/tracking'; +import {restartableTask} from 'ember-concurrency-decorators'; +import {timeout} from 'ember-concurrency'; + +const DEBOUNCE_OFFSET = 500; // ms + +interface Args { + meta: PaginationMeta; + conflicts: any; + referenceRevisions: any; + document: any; + documents: any; + query: any; + reference: any; + onChangeDocument: () => void; + onChangeReference: () => void; + onChangeQuery: (query: string) => void; +} + +export default class ConflictsFilters extends Component { + @service('intl') + intl: IntlService; + + @notEmpty('args.referenceRevisions') + showReferenceRevisionsSelect: boolean; + + @gt('args.documents.length', 1) + showDocumentsSelect: boolean; + + @tracked + debouncedQuery = this.args.query; + + @restartableTask + *debounceQuery(query: string) { + this.debouncedQuery = query; + + yield timeout(DEBOUNCE_OFFSET); + + this.args.onChangeQuery(this.debouncedQuery); + } + + get mappedDocuments() { + const documents = this.args.documents.map( + ({id, path}: {id: string; path: string}) => ({ + label: path, + value: id, + }) + ); + + documents.unshift({ + label: this.intl.t( + 'components.conflicts_filters.document_default_option_text' + ), + value: null, + }); + + return documents; + } + + get mappedReferenceRevisions() { + const revisions = this.args.referenceRevisions.map( + ({id, language}: {id: string; language: any}) => ({ + label: language.name, + value: id, + }) + ); + + revisions.unshift({ + label: this.intl.t( + 'components.conflicts_filters.reference_default_option_text' + ), + value: null, + }); + + return revisions; + } + + get documentValue() { + return this.mappedDocuments.find( + ({value}: {value: string}) => value === this.args.document + ); + } + + get referenceValue() { + return this.mappedReferenceRevisions.find(({value}: {value: string}) => { + return value === this.args.reference; + }); + } + + @action + setDebouncedQuery(event: Event) { + const target = event.target as HTMLInputElement; + + // eslint-disable-next-line @typescript-eslint/ban-ts-ignore + // @ts-ignore + this.debounceQuery.perform(target.value); + } + + @action + submitForm(event: Event) { + event.preventDefault(); + + this.args.onChangeQuery(this.debouncedQuery); + } +} diff --git a/webapp/app/pods/components/conflicts-filters/styles.scss b/webapp/app/pods/components/conflicts-filters/styles.scss index a33abc60..29d6e6a1 100644 --- a/webapp/app/pods/components/conflicts-filters/styles.scss +++ b/webapp/app/pods/components/conflicts-filters/styles.scss @@ -1,4 +1,9 @@ -.subNavigation + & { +@value transition-speed, transition-easing from 'accent-webapp/styles/variables/transitions'; +@value color-black, color-grey from 'accent-webapp/styles/variables/colors'; +@value font-primary from 'accent-webapp/styles/variables/fonts'; +@value screen-sm from 'accent-webapp/styles/variables/dimensions'; + +.subNavigation + .conflicts-filter { position: relative; top: -1px; z-index: 8; @@ -19,6 +24,13 @@ position: relative; } +.totalEntries { + flex-shrink: 0; + margin-top: 10px; + color: color-grey; + font-size: 12px; +} + .search-icon { position: absolute; top: 50%; @@ -31,30 +43,30 @@ .input { @extend %textInput; - transition: $transition-speed $transition-easing; + transition: transition-speed transition-easing; transition-property: border-color; width: 100%; padding: 7px 7px 7px 30px; - font-family: $font-primary; + font-family: font-primary; font-size: 14px; - color: $color-black; + color: color-black; &:focus { - box-shadow: inset 0 1px 2px #f6f6f6, 0 1px 2px rgba($color-black, 0.06); + box-shadow: inset 0 1px 2px #f6f6f6, 0 1px 2px rgba(color-black, 0.06); } &::placeholder { - color: $color-grey; + color: color-grey; } } .totalEntries { margin-top: 10px; - color: $color-grey; + color: color-grey; font-size: 12px; } -@media (max-width: ($screen-sm)) { +@media (max-width: (screen-sm)) { .filters-wrapper { flex-direction: column; } diff --git a/webapp/app/pods/components/conflicts-filters/template.hbs b/webapp/app/pods/components/conflicts-filters/template.hbs index 730ef4e3..b0523c72 100644 --- a/webapp/app/pods/components/conflicts-filters/template.hbs +++ b/webapp/app/pods/components/conflicts-filters/template.hbs @@ -1,57 +1,60 @@ -
    -
    -
    -
    - {{inline-svg "/assets/search.svg" class="search-icon"}} +
    +
    + +
    +
    + {{inline-svg "/assets/search.svg" local-class="search-icon"}} - -
    + +
    -
    -
    - {{#if showDocumentsSelect}} -
    -
    - +
    +
    + {{#if this.showDocumentsSelect}} +
    +
    + +
    -
    - {{/if}} + {{/if}} - {{#if showReferenceRevisionsSelect}} -
    -
    - + {{#if this.showReferenceRevisionsSelect}} +
    +
    + +
    -
    - {{/if}} + {{/if}} +
    -
    - {{#if meta.totalEntries}} - - {{t - "components.conflicts_filters.total_entries_count" - count=meta.totalEntries - }} - - {{/if}} - + {{#if @meta.totalEntries}} + + {{t + "components.conflicts_filters.total_entries_count" + count=@meta.totalEntries + }} + + {{/if}} + +
    diff --git a/webapp/app/pods/components/conflicts-items/component.js b/webapp/app/pods/components/conflicts-items/component.js deleted file mode 100644 index bb37cb71..00000000 --- a/webapp/app/pods/components/conflicts-items/component.js +++ /dev/null @@ -1,32 +0,0 @@ -import Component from '@ember/component'; -import {computed} from '@ember/object'; - -// Attributes: -// project: Object -// permissions: Ember Object containing -// conflicts: Array of -// referenceRevision: Object (optional) -// fullscreen: Boolean -// query: String -// onCorrect: Function -// onCorrectAll: Function -export default Component.extend({ - classNameBindings: ['fullscreen'], - tagName: 'ul', - - isCorrectAllConflictLoading: false, - - toggledFullscreen: computed('fullscreen', function() { - return !this.fullscreen; - }), - - actions: { - correctAllConflicts() { - this.set('isCorrectAllConflictLoading', true); - - this.onCorrectAll().then(() => { - this.set('isCorrectAllConflictLoading', false); - }); - } - } -}); diff --git a/webapp/app/pods/components/conflicts-items/component.ts b/webapp/app/pods/components/conflicts-items/component.ts new file mode 100644 index 00000000..e81167ad --- /dev/null +++ b/webapp/app/pods/components/conflicts-items/component.ts @@ -0,0 +1,33 @@ +import Component from '@glimmer/component'; +import {action} from '@ember/object'; +import {tracked} from '@glimmer/tracking'; + +interface Args { + referenceRevision: any; + revision: any; + fullscreen: boolean; + permissions: Record; + project: any; + conflicts: any; + query: any; + onCorrect: () => Promise; + onCorrectAll: () => Promise; +} + +export default class ConflictsItems extends Component { + @tracked + isCorrectAllConflictLoading = false; + + get toggledFullscreen() { + return !this.args.fullscreen; + } + + @action + async correctAllConflicts() { + this.isCorrectAllConflictLoading = true; + + await this.args.onCorrectAll(); + + this.isCorrectAllConflictLoading = false; + } +} diff --git a/webapp/app/pods/components/conflicts-items/styles.scss b/webapp/app/pods/components/conflicts-items/styles.scss index 05b4233f..5927fb5c 100644 --- a/webapp/app/pods/components/conflicts-items/styles.scss +++ b/webapp/app/pods/components/conflicts-items/styles.scss @@ -1,18 +1,21 @@ -& { +.conflicts-items { position: relative; margin-top: 20px; padding-top: 50px; } -&.fullscreen { +.conflicts-items.fullscreen { padding: 50px 0 0; } -.fullscreen-button { - padding: 4px 12px; +a.fullscreen-button { + margin-left: 6px; + padding: 4px 12px 3px; } .actions { + display: flex; + align-items: center; position: absolute; right: 0; top: 0; diff --git a/webapp/app/pods/components/conflicts-items/template.hbs b/webapp/app/pods/components/conflicts-items/template.hbs index 34b01ae5..7e0939e4 100644 --- a/webapp/app/pods/components/conflicts-items/template.hbs +++ b/webapp/app/pods/components/conflicts-items/template.hbs @@ -1,57 +1,60 @@ -{{#if conflicts}} -
    - {{#unless query}} - + {{#if @conflicts}} +
    + {{#unless query}} + + {{inline-svg "/assets/check.svg" class="button-icon"}} + {{t "components.conflicts_items.correct_all_button"}} + + {{/unless}} + + - {{inline-svg "/assets/check.svg" class="button-icon"}} - {{t "components.conflicts_items.correct_all_button"}} - - {{/unless}} + {{#if @fullscreen}} + {{inline-svg + "/assets/fullscreen-minimize.svg" + class="button-icon fullscreen-icon" + }} + {{else}} + {{inline-svg + "/assets/fullscreen.svg" + class="button-icon fullscreen-icon" + }} + {{/if}} + {{t "components.conflicts_items.fullscreen"}} + +
    + {{/if}} - - {{#if fullscreen}} - {{inline-svg - "/assets/fullscreen-minimize.svg" - class="button-icon fullscreen-icon" - }} - {{else}} - {{inline-svg - "/assets/fullscreen.svg" - class="button-icon fullscreen-icon" - }} - {{/if}} - {{t "components.conflicts_items.fullscreen"}} - -
    -{{/if}} - -{{#each conflicts key="id" as |conflict|}} - -{{else if query}} - -{{else}} - -{{/each}} + {{#each @conflicts key="id" as |conflict|}} + + {{else if query}} + + {{else}} + + {{/each}} + diff --git a/webapp/app/pods/components/conflicts-page/component.js b/webapp/app/pods/components/conflicts-page/component.js deleted file mode 100644 index fb10cb63..00000000 --- a/webapp/app/pods/components/conflicts-page/component.js +++ /dev/null @@ -1,5 +0,0 @@ -import Component from '@ember/component'; - -export default Component.extend({ - classNameBindings: ['fullscreen'] -}); diff --git a/webapp/app/pods/components/conflicts-page/component.ts b/webapp/app/pods/components/conflicts-page/component.ts new file mode 100644 index 00000000..14fe3d0b --- /dev/null +++ b/webapp/app/pods/components/conflicts-page/component.ts @@ -0,0 +1,26 @@ +import Component from '@glimmer/component'; + +interface Args { + project: any; + revision: any; + translations: any; + isLoading: boolean; + showLoading: boolean; + fullscreen: boolean; + document: any; + permissions: Record; + documents: any; + showSkeleton: boolean; + query: any; + reference: any; + referenceRevision: any; + referenceRevisions: any; + onCorrect: () => void; + onCorrectAll: () => void; + onSelectPage: () => void; + onChangeDocument: () => void; + onChangeReference: () => void; + onChangeQuery: () => void; +} + +export default class ConflictsPage extends Component {} diff --git a/webapp/app/pods/components/conflicts-page/styles.scss b/webapp/app/pods/components/conflicts-page/styles.scss index be3048bf..bb7f2420 100644 --- a/webapp/app/pods/components/conflicts-page/styles.scss +++ b/webapp/app/pods/components/conflicts-page/styles.scss @@ -1,8 +1,8 @@ -& { +.conflicts-page { background: #fff; } -&.fullscreen { +.conflicts-page.fullscreen { z-index: 200; position: fixed; top: 0; diff --git a/webapp/app/pods/components/conflicts-page/template.hbs b/webapp/app/pods/components/conflicts-page/template.hbs index 3d93c125..937867e5 100644 --- a/webapp/app/pods/components/conflicts-page/template.hbs +++ b/webapp/app/pods/components/conflicts-page/template.hbs @@ -1,38 +1,40 @@ - - -{{#if isLoading}} - -{{/if}} - -{{#if showSkeleton}} - -{{else if showLoading}} - -{{else}} - + - -{{/if}} + + {{#if @isLoading}} + + {{/if}} + + {{#if @showSkeleton}} + + {{else if @showLoading}} + + {{else}} + + + {{/if}} +
    diff --git a/webapp/app/pods/components/dashboard-features-list/component.js b/webapp/app/pods/components/dashboard-features-list/component.js deleted file mode 100644 index 346d8200..00000000 --- a/webapp/app/pods/components/dashboard-features-list/component.js +++ /dev/null @@ -1,16 +0,0 @@ -import {computed} from '@ember/object'; -import Component from '@ember/component'; - -// Attributes: -// project: Object -// revision: Object -// permissions: Ember Object containing -export default Component.extend({ - highlightSync: computed('revision.translationsCount', function() { - return this.revision.translationsCount <= 0; - }), - - highlightReview: computed('highlightSync', 'permissions.sync', function() { - return !this.highlightSync && this.revision.conflictsCount > 0; - }) -}); diff --git a/webapp/app/pods/components/dashboard-features-list/component.ts b/webapp/app/pods/components/dashboard-features-list/component.ts new file mode 100644 index 00000000..7f2acd65 --- /dev/null +++ b/webapp/app/pods/components/dashboard-features-list/component.ts @@ -0,0 +1,17 @@ +import Component from '@glimmer/component'; + +interface Args { + project: any; + revision: any; + permissions: Record; +} + +export default class DashboardFeaturesList extends Component { + get highlightSync() { + return this.args.revision.translationsCount <= 0; + } + + get highlightReview() { + return !this.highlightSync && this.args.revision.conflictsCount > 0; + } +} diff --git a/webapp/app/pods/components/dashboard-features-list/styles.scss b/webapp/app/pods/components/dashboard-features-list/styles.scss index 63564c7e..be5e83e2 100644 --- a/webapp/app/pods/components/dashboard-features-list/styles.scss +++ b/webapp/app/pods/components/dashboard-features-list/styles.scss @@ -1,4 +1,7 @@ -& { +@value transition-speed, transition-easing from 'accent-webapp/styles/variables/transitions'; +@value color-green, color-grey, color-black from 'accent-webapp/styles/variables/colors'; + +.dashboard-features-list { padding: 0 15px 0 0; flex: 1 0 50%; list-style: none; @@ -9,29 +12,29 @@ &.item--highlight .item-link { padding: 10px 15px 12px; - background: lighten($color-green, 47%); - border-left: 2px solid $color-green; + background: lighten(color-green, 47%); + border-left: 2px solid color-green; .item-icon { - fill: $color-green; + fill: color-green; } .item-text { - color: darken($color-green, 25%); + color: darken(color-green, 25%); } .item-title { - color: $color-green; + color: color-green; } &:focus, &:hover { .item-title { - color: darken($color-green, 10%); + color: darken(color-green, 10%); } .item-text { - color: darken($color-green, 35%); + color: darken(color-green, 35%); } } } @@ -39,32 +42,32 @@ .item-link { display: block; - color: $color-grey; + color: color-grey; text-decoration: none; &:focus, &:hover { .item-title { - color: $color-green; + color: color-green; } .item-icon { - fill: $color-green; + fill: color-green; } .item-text { - color: darken($color-grey, 10%); + color: darken(color-grey, 10%); } } } .item-title { - transition: $transition-speed $transition-easing; + transition: transition-speed transition-easing; transition-property: color; display: flex; align-items: center; padding-bottom: 5px; - color: $color-black; + color: color-black; font-size: 12px; font-weight: normal; } @@ -74,20 +77,20 @@ } .item-icon { - transition: $transition-speed $transition-easing; + transition: transition-speed transition-easing; transition-property: fill; width: 18px; height: 18px; margin-right: 4px; - fill: $color-black; + fill: color-black; } .item-text { - transition: $transition-speed $transition-easing; + transition: transition-speed transition-easing; transition-property: color; display: block; margin-top: 5px; - color: $color-grey; + color: color-grey; font-size: 12px; } diff --git a/webapp/app/pods/components/dashboard-features-list/template.hbs b/webapp/app/pods/components/dashboard-features-list/template.hbs index 4a2c6b81..359df665 100644 --- a/webapp/app/pods/components/dashboard-features-list/template.hbs +++ b/webapp/app/pods/components/dashboard-features-list/template.hbs @@ -1,55 +1,57 @@ -
      - {{#if (get permissions "index_conflicts")}} -
    • - - - {{inline-svg "assets/check.svg" class="item-icon"}} - {{t "components.dashboard_master_revision.features.review.title"}} - - - {{t "components.dashboard_master_revision.features.review.text"}} - - -
    • - {{/if}} +
      +
        + {{#if (get @permissions "index_conflicts")}} +
      • + + + {{inline-svg "assets/check.svg" class="item-icon"}} + {{t "components.dashboard_master_revision.features.review.title"}} + + + {{t "components.dashboard_master_revision.features.review.text"}} + + +
      • + {{/if}} - {{#if (get permissions "sync")}} -
      • - - - {{inline-svg "assets/sync.svg" class="item-icon"}} - {{t "components.dashboard_master_revision.features.sync.title"}} - - - {{t "components.dashboard_master_revision.features.sync.text"}} - - -
      • - {{/if}} + {{#if (get @permissions "sync")}} +
      • + + + {{inline-svg "assets/sync.svg" class="item-icon"}} + {{t "components.dashboard_master_revision.features.sync.title"}} + + + {{t "components.dashboard_master_revision.features.sync.text"}} + + +
      • + {{/if}} - {{#if (get permissions "index_translations")}} -
      • - - - {{inline-svg "assets/search.svg" class="item-icon"}} - {{t "components.dashboard_master_revision.features.translations.title"}} - - - {{t "components.dashboard_master_revision.features.translations.text"}} - - -
      • - {{/if}} -
      + {{#if (get @permissions "index_translations")}} +
    • + + + {{inline-svg "assets/search.svg" class="item-icon"}} + {{t "components.dashboard_master_revision.features.translations.title"}} + + + {{t "components.dashboard_master_revision.features.translations.text"}} + + +
    • + {{/if}} +
    +
    diff --git a/webapp/app/pods/components/dashboard-revision-progress/component.js b/webapp/app/pods/components/dashboard-revision-progress/component.js deleted file mode 100644 index 59172d22..00000000 --- a/webapp/app/pods/components/dashboard-revision-progress/component.js +++ /dev/null @@ -1,43 +0,0 @@ -import {computed} from '@ember/object'; -import {alias, lt, gte} from '@ember/object/computed'; -import Component from '@ember/component'; -import percentage from 'accent-webapp/component-helpers/percentage'; - -const LOW_PERCENTAGE = 50; -const HIGH_PERCENTAGE = 90; - -// Attributes: -// project: Object -// revision: Object -// permissions: Ember Object containing -export default Component.extend({ - master: alias('revision.master'), - lowPercentage: lt('correctedKeysPercentage', LOW_PERCENTAGE), // Lower than low percentage - mediumPercentage: gte('correctedKeysPercentage', LOW_PERCENTAGE), // higher or equal than low percentage - highPercentage: gte('correctedKeysPercentage', HIGH_PERCENTAGE), // higher or equal than high percentage - - classNameBindings: [ - 'master', - 'lowPercentage', - 'mediumPercentage', - 'highPercentage' - ], - - correctedKeysPercentage: computed( - 'revision.{conflictsCount,translationsCount}', - function() { - const {conflictsCount, translationsCount} = this.revision; - - return percentage(conflictsCount, translationsCount); - } - ), - - reviewsCount: computed( - 'revision.{conflictsCount,translationsCount}', - function() { - const {conflictsCount, translationsCount} = this.revision; - - return translationsCount - conflictsCount; - } - ) -}); diff --git a/webapp/app/pods/components/dashboard-revision-progress/styles.scss b/webapp/app/pods/components/dashboard-revision-progress/styles.scss deleted file mode 100644 index f0d6178e..00000000 --- a/webapp/app/pods/components/dashboard-revision-progress/styles.scss +++ /dev/null @@ -1,87 +0,0 @@ -& { - max-width: 330px; - margin-bottom: 20px; -} - -&.master { - .language-name { - color: darken($color-grey, 15%); - } -} - -&.low-percentage { - .reviewedStats { - color: $color-error; - } - - .container { - border-color: lighten($color-error, 47%); - background: lighten($color-error, 53%); - } - - .progress { - background: $color-error; - } -} - -&.medium-percentage { - .reviewedStats { - color: $color-warning; - } - - .container { - border-color: lighten($color-warning, 30%); - background: lighten($color-warning, 45%); - } - - .progress { - background: $color-warning; - } -} - -&.high-percentage { - .reviewedStats { - color: $color-success; - } - - .container { - border-color: lighten($color-success, 45%); - background: lighten($color-success, 53%); - } - - .progress { - background: $color-success; - } -} - -.language { - display: flex; - align-items: center; - justify-content: space-between; - color: $color-grey; -} - -.language-name { - transition: $transition-speed $transition-easing; - transition-property: color; - color: $color-grey; - font-size: 14px; - font-weight: bold; - text-decoration: none; - - &:focus, - &:hover { - color: $color-green; - } -} - -.language-reviewedPercentage { - margin-left: 4px; - font-weight: normal; - font-size: 13px; - color: lighten($color-grey, 10%); -} - -.reviewedStats { - font-size: 12px; -} diff --git a/webapp/app/pods/components/dashboard-revision-progress/template.hbs b/webapp/app/pods/components/dashboard-revision-progress/template.hbs deleted file mode 100644 index 57cd07d1..00000000 --- a/webapp/app/pods/components/dashboard-revision-progress/template.hbs +++ /dev/null @@ -1,36 +0,0 @@ -
    - - {{#if (get permissions "index_translations")}} - - {{revision.language.name}} - - {{correctedKeysPercentage}} - % - - - {{else}} - - {{revision.language.name}} - - {{correctedKeysPercentage}} - % - - - {{/if}} - - - - {{reviewsCount}} - - / - - {{revision.translationsCount}} - - - - -
    diff --git a/webapp/app/pods/components/dashboard-revisions/component.js b/webapp/app/pods/components/dashboard-revisions/component.js deleted file mode 100644 index 481023f8..00000000 --- a/webapp/app/pods/components/dashboard-revisions/component.js +++ /dev/null @@ -1,64 +0,0 @@ -import {computed} from '@ember/object'; -import {lt, gte} from '@ember/object/computed'; -import Component from '@ember/component'; -import percentage from 'accent-webapp/component-helpers/percentage'; - -const LOW_PERCENTAGE = 50; -const HIGH_PERCENTAGE = 90; - -// Attributes: -// project: Object -// document: Object -// revisions: Array of -// permissions: Ember Object containing -// onCorrectAllConflicts: Function -// onUncorrectAllConflicts: Function -export default Component.extend({ - lowPercentage: lt('reviewedPercentage', LOW_PERCENTAGE), // Lower than low percentage - mediumPercentage: gte('reviewedPercentage', LOW_PERCENTAGE), // higher or equal than low percentage - highPercentage: gte('reviewedPercentage', HIGH_PERCENTAGE), // higher or equal than high percentage - - classNameBindings: ['lowPercentage', 'mediumPercentage', 'highPercentage'], - - masterRevision: computed('revisions', function() { - return this.revisions.find(revision => revision.isMaster); - }), - - slaveRevisions: computed('revisions', function() { - return this.revisions.filter(revision => revision !== this.masterRevision); - }), - - totalStrings: computed('revisions.[]', function() { - return this.revisions.reduce((memo, revision) => { - return memo + revision.translationsCount; - }, 0); - }), - - totalConflicts: computed('revisions.[]', function() { - return this.revisions.reduce((memo, revision) => { - return memo + revision.conflictsCount; - }, 0); - }), - - totalReviewed: computed('revisions.[]', function() { - return this.revisions.reduce((memo, revision) => { - return memo + (revision.translationsCount - revision.conflictsCount); - }, 0); - }), - - reviewCompleted: gte('reviewedPercentage', 100), - - reviewedPercentage: computed('totalConflicts', 'totalStrings', function() { - return percentage( - this.totalStrings - this.totalConflicts, - this.totalStrings - ); - }), - - conflictedPercentage: computed('totalReviewed', 'totalStrings', function() { - return percentage( - this.totalStrings - this.totalReviewed, - this.totalStrings - ); - }) -}); diff --git a/webapp/app/pods/components/dashboard-revisions/component.ts b/webapp/app/pods/components/dashboard-revisions/component.ts new file mode 100644 index 00000000..4b46a6d4 --- /dev/null +++ b/webapp/app/pods/components/dashboard-revisions/component.ts @@ -0,0 +1,92 @@ +import {lt, gte} from '@ember/object/computed'; +import Component from '@glimmer/component'; +import percentage from 'accent-webapp/component-helpers/percentage'; + +const LOW_PERCENTAGE = 50; +const HIGH_PERCENTAGE = 90; + +interface Revision { + id: string; + isMaster: boolean; + translationsCount: number; + conflictsCount: number; +} + +interface Args { + document: any; + project: any; + activities: any; + revisions: Revision[]; + permissions: Record; + onCorrectAllConflicts: () => Promise; + onUncorrectAllConflicts: () => Promise; +} + +const calculateTotalRevisions = ( + revisions: Revision[], + accumulate: (revision: Revision) => number +) => { + return revisions.reduce((memo, revision) => { + return memo + accumulate(revision); + }, 0); +}; + +export default class DashboardRevisions extends Component { + @lt('reviewedPercentage', LOW_PERCENTAGE) + lowPercentage: boolean; // Lower than low percentage + + @gte('reviewedPercentage', LOW_PERCENTAGE) + mediumPercentage: boolean; // higher or equal than low percentage + + @gte('reviewedPercentage', HIGH_PERCENTAGE) + highPercentage: boolean; // higher or equal than high percentage + + @gte('reviewedPercentage', 100) + reviewCompleted: boolean; + + get masterRevision() { + return this.args.revisions.find((revision: Revision) => revision.isMaster); + } + + get slaveRevisions() { + return this.args.revisions.filter( + (revision: Revision) => revision !== this.masterRevision + ); + } + + get totalStrings() { + return calculateTotalRevisions( + this.args.revisions, + (revision: Revision) => revision.translationsCount + ); + } + + get totalConflicts() { + return calculateTotalRevisions( + this.args.revisions, + (revision: Revision) => revision.conflictsCount + ); + } + + get totalReviewed() { + return calculateTotalRevisions( + this.args.revisions, + (revision: Revision) => + revision.translationsCount - revision.conflictsCount + ); + } + + get reviewedPercentage() { + return percentage( + this.totalStrings - this.totalConflicts, + this.totalStrings + ); + } + + get conflictedPercentage() { + return percentage( + this.totalStrings - this.totalReviewed, + this.totalStrings + ); + } +} diff --git a/webapp/app/pods/components/dashboard-revisions/item/component.js b/webapp/app/pods/components/dashboard-revisions/item/component.js deleted file mode 100644 index a02b0e97..00000000 --- a/webapp/app/pods/components/dashboard-revisions/item/component.js +++ /dev/null @@ -1,88 +0,0 @@ -import {computed} from '@ember/object'; -import {alias, lt, gte, or, gt} from '@ember/object/computed'; -import Component from '@ember/component'; -import percentage from 'accent-webapp/component-helpers/percentage'; - -const LOW_PERCENTAGE = 50; -const HIGH_PERCENTAGE = 90; - -// Attributes: -// project: Object -// revision: Object -// permissions: Ember Object containing -// onCorrectAllConflicts: Function -// onUncorrectAllConflicts: Function -export default Component.extend({ - showActions: false, - master: alias('revision.isMaster'), - lowPercentage: lt('correctedKeysPercentage', LOW_PERCENTAGE), // Lower than low percentage - mediumPercentage: gte('correctedKeysPercentage', LOW_PERCENTAGE), // higher or equal than low percentage - highPercentage: gte('correctedKeysPercentage', HIGH_PERCENTAGE), // higher or equal than high percentage - - classNameBindings: [ - 'master', - 'lowPercentage', - 'mediumPercentage', - 'highPercentage' - ], - - isCorrectAllConflictLoading: false, - isUncorrectAllConflictLoading: false, - - isAnyActionsLoading: or( - 'isCorrectAllConflictLoading', - 'isUncorrectAllConflictLoading' - ), - - showCorrectAllAction: lt('correctedKeysPercentage', 100), - showUncorrectAllAction: gt('correctedKeysPercentage', 0), - - correctedKeysPercentage: computed( - 'revision.{conflictsCount,translationsCount}', - function() { - return percentage( - this.revision.translationsCount - this.revision.conflictsCount, - this.revision.translationsCount - ); - } - ), - - reviewsCount: computed( - 'revision.{conflictsCount,translationsCount}', - function() { - const {conflictsCount, translationsCount} = this.revision; - - return translationsCount - conflictsCount; - } - ), - - actions: { - toggleShowActions() { - this.toggleProperty('showActions'); - }, - - correctAllConflicts() { - this.set('isCorrectAllConflictLoading', true); - - this.onCorrectAllConflicts(this.revision).then(() => - this._onCorrectAllConflictsDone() - ); - }, - - uncorrectAllConflicts() { - this.set('isUncorrectAllConflictLoading', true); - - this.onUncorrectAllConflicts(this.revision).then(() => - this._onUncorrectAllConflictsDone() - ); - } - }, - - _onCorrectAllConflictsDone() { - this.set('isCorrectAllConflictLoading', false); - }, - - _onUncorrectAllConflictsDone() { - this.set('isUncorrectAllConflictLoading', false); - } -}); diff --git a/webapp/app/pods/components/dashboard-revisions/item/component.ts b/webapp/app/pods/components/dashboard-revisions/item/component.ts new file mode 100644 index 00000000..055d90d3 --- /dev/null +++ b/webapp/app/pods/components/dashboard-revisions/item/component.ts @@ -0,0 +1,92 @@ +import {action} from '@ember/object'; +import {readOnly, lt, gte, or, gt} from '@ember/object/computed'; +import Component from '@glimmer/component'; +import percentage from 'accent-webapp/component-helpers/percentage'; +import {tracked} from '@glimmer/tracking'; + +const LOW_PERCENTAGE = 50; +const HIGH_PERCENTAGE = 90; + +interface Args { + project: any; + revision: any; + permissions: Record; + onCorrectAllConflicts: (revision: any) => Promise; + onUncorrectAllConflicts: (revision: any) => Promise; +} + +export default class DashboardRevisionsItem extends Component { + @readOnly('args.revision.isMaster') + master: boolean; + + @lt('correctedKeysPercentage', LOW_PERCENTAGE) + lowPercentage: boolean; // Lower than low percentage + + @gte('correctedKeysPercentage', LOW_PERCENTAGE) + mediumPercentage: boolean; // higher or equal than low percentage + + @gte('correctedKeysPercentage', HIGH_PERCENTAGE) + highPercentage: boolean; // higher or equal than high percentage + + @or('isCorrectAllConflictLoading', 'isUncorrectAllConflictLoading') + isAnyActionsLoading: boolean; + + @lt('correctedKeysPercentage', 100) + showCorrectAllAction: boolean; + + @gt('correctedKeysPercentage', 0) + showUncorrectAllAction: boolean; + + @tracked + showActions = false; + + @tracked + isCorrectAllConflictLoading = false; + + @tracked + isUncorrectAllConflictLoading = false; + + get correctedKeysPercentage() { + return percentage( + this.args.revision.translationsCount - this.args.revision.conflictsCount, + this.args.revision.translationsCount + ); + } + + get reviewsCount() { + const {conflictsCount, translationsCount} = this.args.revision; + + return translationsCount - conflictsCount; + } + + @action + toggleShowActions() { + this.showActions = !this.showActions; + } + + @action + async correctAllConflicts() { + this.isCorrectAllConflictLoading = true; + + await this.args.onCorrectAllConflicts(this.args.revision); + + this.onCorrectAllConflictsDone(); + } + + @action + async uncorrectAllConflicts() { + this.isUncorrectAllConflictLoading = true; + + await this.args.onUncorrectAllConflicts(this.args.revision); + + this.onUncorrectAllConflictsDone(); + } + + private onCorrectAllConflictsDone() { + this.isCorrectAllConflictLoading = false; + } + + private onUncorrectAllConflictsDone() { + this.isUncorrectAllConflictLoading = false; + } +} diff --git a/webapp/app/pods/components/dashboard-revisions/item/styles.scss b/webapp/app/pods/components/dashboard-revisions/item/styles.scss index cc04ca6a..4eff1ee5 100644 --- a/webapp/app/pods/components/dashboard-revisions/item/styles.scss +++ b/webapp/app/pods/components/dashboard-revisions/item/styles.scss @@ -1,5 +1,10 @@ -& { - transition: $transition-speed $transition-easing; +@value transition-speed, transition-easing from 'accent-webapp/styles/variables/transitions'; +@value color-black, color-error, color-warning, color-success, color-grey, color-green from 'accent-webapp/styles/variables/colors'; +@value font-monospace from 'accent-webapp/styles/variables/fonts'; +@value screen-sm from 'accent-webapp/styles/variables/dimensions'; + +.dashboard-revisions-item { + transition: transition-speed transition-easing; transition-property: border-color; position: relative; flex: 1 1 calc(50% - 10px); @@ -9,7 +14,7 @@ margin-right: 10px; padding: 8px 15px 12px; border-radius: 3px; - box-shadow: 0 2px 4px rgba($color-black, 0.15); + box-shadow: 0 2px 4px rgba(color-black, 0.15); &:nth-child(even) { flex: 1 1 50%; @@ -26,37 +31,37 @@ } } -&.low-percentage { +.dashboard-revisions-item.low-percentage { .language-reviewedPercentage { - color: $color-error; + color: color-error; } .progress { - background: $color-error; + color: color-error; } } -&.medium-percentage { +.dashboard-revisions-item.medium-percentage { .language-reviewedPercentage { - color: $color-warning; + color: color-warning; } .progress { - background: $color-warning; + color: color-warning; } } -&.high-percentage { +.dashboard-revisions-item.high-percentage { .language-reviewedPercentage { - color: $color-success; + color: color-success; } .progress { - background: $color-success; + color: color-success; } } -&.master { +.dashboard-revisions-item.master { flex: 1 1 auto; max-width: none; @@ -70,19 +75,19 @@ align-items: flex-end; justify-content: space-between; margin-bottom: 6px; - color: $color-grey; + color: color-grey; } .language-name { - transition: $transition-speed $transition-easing; + transition: transition-speed transition-easing; transition-property: color; - color: darken($color-grey, 10%); + color: darken(color-grey, 10%); font-size: 12px; text-decoration: none; &:focus, &:hover { - color: $color-green; + color: color-green; color: var(--color-primary); } } @@ -92,20 +97,20 @@ margin-top: 5px; font-weight: normal; font-size: 25px; - color: lighten($color-grey, 10%); + color: lighten(color-grey, 10%); } .reviewedStats { padding: 2px 7px 1px; border-radius: 3px; - background: lighten($color-grey, 25%); - color: $color-grey; + background: lighten(color-grey, 25%); + color: color-grey; font-size: 12px; - font-family: $font-monospace; + font-family: font-monospace; } .actionsButton { - transition: $transition-speed $transition-easing; + transition: transition-speed transition-easing; transition-property: opacity; position: absolute; right: 7px; @@ -122,14 +127,15 @@ &:focus, &:hover { .actionsButton-icon { - stroke: $color-green; + stroke: color-green; stroke: var(--color-primary); } } } .actionsButton-icon { - transition: $transition-speed $transition-easing; + stroke: color-grey; + transition: transition-speed transition-easing; transition-property: stroke; width: 15px; height: 15px; @@ -137,20 +143,19 @@ .actions { margin-top: 10px; - border-top: 1px solid #eee; } .actionItem-text { margin-bottom: 7px; font-size: 12px; - color: $color-grey; + color: color-grey; } .actionItem-button { margin-top: 10px; } -@media (max-width: ($screen-sm)) { +@media (max-width: (screen-sm)) { .language-reviewedPercentage { font-size: 18px; } diff --git a/webapp/app/pods/components/dashboard-revisions/item/template.hbs b/webapp/app/pods/components/dashboard-revisions/item/template.hbs index 41daa888..a454adc2 100644 --- a/webapp/app/pods/components/dashboard-revisions/item/template.hbs +++ b/webapp/app/pods/components/dashboard-revisions/item/template.hbs @@ -1,67 +1,73 @@ -
    - - {{inline-svg "assets/gear.svg" class="actionsButton-icon"}} - - - {{#if (get permissions "index_translations")}} - - {{revision.language.name}} - - {{correctedKeysPercentage}} - % +
    +
    + + {{inline-svg "assets/gear.svg" local-class="actionsButton-icon"}} + + + {{#if (get @permissions "index_translations")}} + + {{@revision.language.name}} + + {{this.correctedKeysPercentage}} + % + + + {{else}} + + {{@revision.language.name}} + + {{this.correctedKeysPercentage}} + % + - - {{else}} - - {{revision.language.name}} - - {{correctedKeysPercentage}} - % - - - {{/if}} + {{/if}} - - - {{reviewsCount}} - - / - - {{revision.translationsCount}} + + + {{this.reviewsCount}} + + / + + {{@revision.translationsCount}} + - - - - {{#if showActions}} -
    - {{#if showCorrectAllAction}} - - {{inline-svg "/assets/check.svg" class="button-icon"}} - {{t "components.dashboard_revisions.item.correct_all_button"}} - - {{/if}} - {{#if showUncorrectAllAction}} - - {{inline-svg "/assets/revert.svg" class="button-icon"}} - {{t "components.dashboard_revisions.item.uncorrect_all_button"}} - - {{/if}} +
    +
    - {{/if}} + + {{#if this.showActions}} +
    + {{#if this.showCorrectAllAction}} + + {{inline-svg "/assets/check.svg" class="button-icon"}} + {{t "components.dashboard_revisions.item.correct_all_button"}} + + {{/if}} + {{#if this.showUncorrectAllAction}} + + {{inline-svg "/assets/revert.svg" class="button-icon"}} + {{t "components.dashboard_revisions.item.uncorrect_all_button"}} + + {{/if}} +
    + {{/if}} +
    diff --git a/webapp/app/pods/components/dashboard-revisions/styles.scss b/webapp/app/pods/components/dashboard-revisions/styles.scss index e545e894..867dffcc 100644 --- a/webapp/app/pods/components/dashboard-revisions/styles.scss +++ b/webapp/app/pods/components/dashboard-revisions/styles.scss @@ -1,29 +1,33 @@ -&.low-percentage { +@value color-error, color-warning, color-success, color-black, color-green from 'accent-webapp/styles/variables/colors'; +@value font-monospace from 'accent-webapp/styles/variables/fonts'; +@value screen-md from 'accent-webapp/styles/variables/dimensions'; + +.dashboard-revisions.low-percentage { .numberStat-reviewCompleted, .numberStat-reviewPercentage { - color: $color-error; + color: color-error; } } -&.medium-percentage { +.dashboard-revisions.medium-percentage { .numberStat-reviewCompleted, .numberStat-reviewPercentage { - color: $color-warning; + color: color-warning; } } -&.high-percentage { +.dashboard-revisions.high-percentage { .numberStat-reviewCompleted, .numberStat-reviewPercentage { - color: $color-success; + color: color-success; } } -& { +.dashboard-revisions { display: flex; } -& > .content { +.dashboard-revisions > .content { display: flex; align-items: flex-start; flex-direction: column; @@ -60,7 +64,7 @@ .numberStat-totalKeys { display: block; font-size: 20px; - font-family: $font-monospace; + font-family: font-monospace; color: #ccc; } @@ -78,7 +82,7 @@ .numberStat-reviewCompleted-successIcon { display: block; - stroke: rgba($color-success, 0.8); + stroke: rgba(color-success, 0.8); width: 52px; height: 52px; margin-bottom: 10px; @@ -98,7 +102,7 @@ padding-bottom: 5px; font-size: 14px; font-weight: bold; - color: $color-black; + color: color-black; color: var(--color-black); } @@ -116,7 +120,7 @@ background: #fff; box-shadow: 0 2px 6px rgba(#000, 0.09); border-radius: 2px; - color: $color-green; + color: color-green; color: var(--color-primary); text-decoration: none; transition: box-shadow 0.2s ease-in-out; @@ -138,7 +142,7 @@ width: 20px; height: 20px; margin-right: 5px; - fill: $color-green; + fill: color-green; fill: var(--color-primary); } @@ -146,7 +150,7 @@ display: block; margin-top: 10px; font-size: 11px; - color: rgba(darken($color-green, 20%), 0.5); + color: rgba(darken(color-green, 20%), 0.5); color: var(--color-black); } @@ -188,13 +192,13 @@ } .activities-viewMoreButton { - display: block; - margin-top: 15px; - text-align: center; + display: block !important; + margin-top: 15px !important; + text-align: center !important; } -@media (max-width: ($screen-md)) { - & > .content { +@media (max-width: (screen-md)) { + .dashboard-revisions > .content { width: 100%; margin-right: 0; } diff --git a/webapp/app/pods/components/dashboard-revisions/template.hbs b/webapp/app/pods/components/dashboard-revisions/template.hbs index 34100491..96d7d543 100644 --- a/webapp/app/pods/components/dashboard-revisions/template.hbs +++ b/webapp/app/pods/components/dashboard-revisions/template.hbs @@ -1,160 +1,162 @@ -
    - {{#if project.lastSyncedAt}} -
    - {{#if reviewCompleted}} - - {{inline-svg - "/assets/thumbs-up.svg" - class="numberStat-reviewCompleted-successIcon" - }} - {{t "components.dashboard_revisions.all_reviewed"}} - - {{else}} - - {{reviewedPercentage}} - +
    +
    + {{#if @project.lastSyncedAt}} +
    + {{#if this.reviewCompleted}} + {{inline-svg - "/assets/percent.svg" - class="numberStat-reviewPercentage-icon" + "/assets/thumbs-up.svg" + local-class="numberStat-reviewCompleted-successIcon" }} + {{t "components.dashboard_revisions.all_reviewed"}} - - {{/if}} + {{else}} + + {{this.reviewedPercentage}} + + {{inline-svg + "/assets/percent.svg" + local-class="numberStat-reviewPercentage-icon" + }} + + + {{/if}} - - {{totalReviewed}} - / - {{totalStrings}} - - {{t "components.dashboard_revisions.strings"}} - - -
    - -
    -

    - - {{t "components.dashboard_revisions.master"}} - : - - - -

    - -
    - + + {{this.totalReviewed}} + / + {{this.totalStrings}} + + {{t "components.dashboard_revisions.strings"}} + +
    - {{#if slaveRevisions}} -

    +
    +

    - {{t "components.dashboard_revisions.slaves"}} + {{t "components.dashboard_revisions.master"}} : -

    + +
    + +
    + + {{#if this.slaveRevisions}} +

    + + {{t "components.dashboard_revisions.slaves"}} + : + +
    + {{#if (get @permissions "create_slave")}} + + {{inline-svg "assets/language.svg" class="button-icon"}} + {{t "components.dashboard_revisions.manage_languages_link_title"}} + + {{/if}} +
    +

    +
    + {{#each this.slaveRevisions key="id" as |revision|}} + + {{/each}} +
    + {{else}} +
    + {{#if (get @permissions "create_slave")}} - {{inline-svg "assets/language.svg" class="button-icon"}} - {{t "components.dashboard_revisions.manage_languages_link_title"}} + + {{inline-svg "assets/add.svg" local-class="empty-slaves-button-icon"}} + {{t "components.dashboard_revisions.new_language_link_title"}} + + + + {{t "components.dashboard_revisions.new_language_link_text"}} + {{/if}}
    -

    -
    - {{#each slaveRevisions key="id" as |revision|}} - - {{/each}} -
    - {{else}} -
    - {{#if (get permissions "create_slave")}} - - - {{inline-svg "assets/add.svg" class="empty-slaves-button-icon"}} - {{t "components.dashboard_revisions.new_language_link_title"}} - + {{/if}} +
    + {{else}} + + {{/if}} +
    - - {{t "components.dashboard_revisions.new_language_link_text"}} - - - {{/if}} -
    - {{/if}} + {{#if @activities}} +
    +

    + {{inline-svg "assets/activity.svg" local-class="activities-title-icon"}} + {{t "components.dashboard_revisions.activities_title"}} +

    + + + {{t "components.dashboard_revisions.view_more_activities"}} +
    - {{else}} - {{/if}}
    - -{{#if activities}} -
    -

    - {{inline-svg "assets/activity.svg" class="activities-title-icon"}} - {{t "components.dashboard_revisions.activities_title"}} -

    - - - {{t "components.dashboard_revisions.view_more_activities"}} - -
    -{{/if}} diff --git a/webapp/app/pods/components/date-tag/component.js b/webapp/app/pods/components/date-tag/component.ts similarity index 53% rename from webapp/app/pods/components/date-tag/component.js rename to webapp/app/pods/components/date-tag/component.ts index 335f892b..6df8d1aa 100644 --- a/webapp/app/pods/components/date-tag/component.js +++ b/webapp/app/pods/components/date-tag/component.ts @@ -1,28 +1,31 @@ -import {computed} from '@ember/object'; import {inject as service} from '@ember/service'; -import Component from '@ember/component'; +import Component from '@glimmer/component'; import dateFormat from 'date-fns/format'; +import IntlService from 'ember-intl/services/intl'; -// Attributes: -// date: String -export default Component.extend({ - intl: service('intl'), +interface Args { + date: string; +} - tagName: 'span', +export default class DateTag extends Component { + @service('intl') + intl: IntlService; // The follow property returns a formatted date like this: 2016-02-03T11:02:34 - formattedDatetime: computed('date', function() { + get formattedDatetime() { const format = this.intl .t('components.date_tag.formatted_date_time_format') .toString(); - return dateFormat(new Date(this.date), format); - }), + + return dateFormat(new Date(this.args.date), format); + } // The follow property returns a formatted date like this: February 3rd 2016, 11:02:34 - humanizedDate: computed('date', function() { + get humanizedDate() { const format = this.intl .t('components.date_tag.humanized_date_title_format') .toString(); - return dateFormat(new Date(this.date), format); - }) -}); + + return dateFormat(new Date(this.args.date), format); + } +} diff --git a/webapp/app/pods/components/date-tag/template.hbs b/webapp/app/pods/components/date-tag/template.hbs index c7485417..453aa890 100644 --- a/webapp/app/pods/components/date-tag/template.hbs +++ b/webapp/app/pods/components/date-tag/template.hbs @@ -1,3 +1,5 @@ - + + + diff --git a/webapp/app/pods/components/documents-add-button/component.js b/webapp/app/pods/components/documents-add-button/component.js deleted file mode 100644 index cbfd5011..00000000 --- a/webapp/app/pods/components/documents-add-button/component.js +++ /dev/null @@ -1,3 +0,0 @@ -import Component from '@ember/component'; - -export default Component.extend(); diff --git a/webapp/app/pods/components/documents-add-button/component.ts b/webapp/app/pods/components/documents-add-button/component.ts new file mode 100644 index 00000000..595947a0 --- /dev/null +++ b/webapp/app/pods/components/documents-add-button/component.ts @@ -0,0 +1,7 @@ +import Component from '@glimmer/component'; + +interface Args { + project: any; +} + +export default class DocumentsAddButton extends Component {} diff --git a/webapp/app/pods/components/documents-add-button/styles.scss b/webapp/app/pods/components/documents-add-button/styles.scss index b56c91e0..1fdae784 100644 --- a/webapp/app/pods/components/documents-add-button/styles.scss +++ b/webapp/app/pods/components/documents-add-button/styles.scss @@ -1,12 +1,13 @@ +@value color-green, color-black from 'accent-webapp/styles/variables/colors'; + .button { display: inline-flex; align-items: center; padding: 15px 20px; - margin-top: 20px; background: #fff; box-shadow: 0 2px 4px rgba(#000, 0.09); border-radius: 3px; - color: $color-green; + color: color-green; color: var(--color-primary); font-weight: normal; font-size: 18px; @@ -17,7 +18,7 @@ background: var(--color-primary-opacity-10); border-color: darken(#fff, 4%); border-color: var(--color-primary-opacity-10); - color: $color-black; + color: color-black; color: var(--color-black); } } @@ -26,6 +27,6 @@ margin-right: 5px; width: 25px; height: 25px; - fill: $color-green; + fill: color-green; fill: var(--color-primary); } diff --git a/webapp/app/pods/components/documents-add-button/template.hbs b/webapp/app/pods/components/documents-add-button/template.hbs index b16495c5..1073e717 100644 --- a/webapp/app/pods/components/documents-add-button/template.hbs +++ b/webapp/app/pods/components/documents-add-button/template.hbs @@ -1,6 +1,7 @@ {{inline-svg "/assets/add.svg" class="button-icon"}} diff --git a/webapp/app/pods/components/documents-list/component.js b/webapp/app/pods/components/documents-list/component.js deleted file mode 100644 index 5095a5bb..00000000 --- a/webapp/app/pods/components/documents-list/component.js +++ /dev/null @@ -1,11 +0,0 @@ -import Component from '@ember/component'; - -// Attributes: -// project: Object -// permissions: Ember Object containing -// documents: Array of -// onDelete: Function -// onRename: Function -export default Component.extend({ - tagName: 'ul' -}); diff --git a/webapp/app/pods/components/documents-list/component.ts b/webapp/app/pods/components/documents-list/component.ts new file mode 100644 index 00000000..42420866 --- /dev/null +++ b/webapp/app/pods/components/documents-list/component.ts @@ -0,0 +1,11 @@ +import Component from '@glimmer/component'; + +interface Args { + permissions: Record; + documents: any; + project: any; + onDelete: (documentEntity: any) => Promise; + onUpdate: (documentEntity: any, path: string) => Promise; +} + +export default class DocumentsList extends Component {} diff --git a/webapp/app/pods/components/documents-list/item/component.js b/webapp/app/pods/components/documents-list/item/component.js deleted file mode 100644 index 6dbf5ab1..00000000 --- a/webapp/app/pods/components/documents-list/item/component.js +++ /dev/null @@ -1,89 +0,0 @@ -import {computed} from '@ember/object'; -import {not, lt, gte, reads} from '@ember/object/computed'; -import {inject as service} from '@ember/service'; -import {scheduleOnce} from '@ember/runloop'; -import Component from '@ember/component'; -import percentage from 'accent-webapp/component-helpers/percentage'; - -const LOW_PERCENTAGE = 50; -const HIGH_PERCENTAGE = 90; - -// Attributes: -// project: Object -// permissions: Ember Object containing -// document: Object -// onDelete: Function -// onRename: Function -export default Component.extend({ - lowPercentage: lt('correctedKeysPercentage', LOW_PERCENTAGE), // Lower than low percentage - mediumPercentage: gte('correctedKeysPercentage', LOW_PERCENTAGE), // higher or equal than low percentage - highPercentage: gte('correctedKeysPercentage', HIGH_PERCENTAGE), // higher or equal than high percentage - - classNameBindings: ['lowPercentage', 'mediumPercentage', 'highPercentage'], - - globalState: service('global-state'), - - tagName: 'li', - - isEditing: false, - isDeleting: false, - isUpdating: false, - renamedDocumentPath: reads('document.path'), - canDeleteFile: not('project.lockedFileOperations'), - - documentFormatItem: computed( - 'document.format', - 'globalState.documentFormats', - function() { - if (!this.globalState.documentFormats) return {}; - - return this.globalState.documentFormats.find( - ({slug}) => slug === this.document.format - ); - } - ), - - correctedKeysPercentage: computed( - 'document.{conflictsCount,translationsCount}', - function() { - return percentage( - this.document.translationsCount - this.document.conflictsCount, - this.document.translationsCount - ); - } - ), - - reviewsCount: computed( - 'document.{conflictsCount,translationsCount}', - function() { - const {conflictsCount, translationsCount} = this.document; - - return translationsCount - conflictsCount; - } - ), - - actions: { - deleteFile() { - this.set('isDeleting', true); - - this.onDelete(this.document).then(() => this.set('isDeleting', false)); - }, - - toggleEdit() { - this.set('isEditing', !this.isEditing); - - scheduleOnce('afterRender', this, function() { - const input = this.element.querySelector('.textInput'); - input && input.focus(); - }); - }, - - updateDocument() { - this.set('isUpdating', true); - - this.onUpdate(this.document, this.renamedDocumentPath).then(() => - this.setProperties({isUpdating: false, isEditing: false}) - ); - } - } -}); diff --git a/webapp/app/pods/components/documents-list/item/component.ts b/webapp/app/pods/components/documents-list/item/component.ts new file mode 100644 index 00000000..ebccdbbc --- /dev/null +++ b/webapp/app/pods/components/documents-list/item/component.ts @@ -0,0 +1,94 @@ +import {action} from '@ember/object'; +import {not, lt, gte} from '@ember/object/computed'; +import {inject as service} from '@ember/service'; +import Component from '@glimmer/component'; +import percentage from 'accent-webapp/component-helpers/percentage'; +import GlobalState from 'accent-webapp/services/global-state'; +import {tracked} from '@glimmer/tracking'; + +const LOW_PERCENTAGE = 50; +const HIGH_PERCENTAGE = 90; + +interface Args { + permissions: Record; + document: any; + project: any; + onDelete: (documentEntity: any) => Promise; + onUpdate: (documentEntity: any, path: string) => Promise; +} + +export default class DocumentsListItem extends Component { + @service('global-state') + globalState: GlobalState; + + @lt('correctedKeysPercentage', LOW_PERCENTAGE) + lowPercentage: boolean; // Lower than low percentage + + @gte('correctedKeysPercentage', LOW_PERCENTAGE) + mediumPercentage: boolean; // higher or equal than low percentage + + @gte('correctedKeysPercentage', HIGH_PERCENTAGE) + highPercentage: boolean; // higher or equal than high percentage + + @tracked + renamedDocumentPath = this.args.document.path; + + @not('project.lockedFileOperations') + canDeleteFile: boolean; + + @tracked + isEditing = false; + + @tracked + isDeleting = false; + + @tracked + isUpdating = false; + + get documentFormatItem() { + if (!this.globalState.documentFormats) return {}; + + return this.globalState.documentFormats.find(({slug}) => { + return slug === this.args.document.format; + }); + } + + get correctedKeysPercentage() { + return percentage( + this.args.document.translationsCount - this.args.document.conflictsCount, + this.args.document.translationsCount + ); + } + + get reviewsCount() { + const {conflictsCount, translationsCount} = this.args.document; + + return translationsCount - conflictsCount; + } + + @action + async deleteFile(document: any) { + this.isDeleting = true; + + await this.args.onDelete(document); + + this.isDeleting = false; + } + + @action + toggleEdit() { + this.isEditing = !this.isEditing; + } + + @action + async updateDocument(event?: Event) { + event?.preventDefault(); + + this.isUpdating = true; + + await this.args.onUpdate(this.args.document, this.renamedDocumentPath); + + this.isUpdating = false; + this.isEditing = false; + } +} diff --git a/webapp/app/pods/components/documents-list/item/styles.scss b/webapp/app/pods/components/documents-list/item/styles.scss index e97a2245..cb7f25b1 100644 --- a/webapp/app/pods/components/documents-list/item/styles.scss +++ b/webapp/app/pods/components/documents-list/item/styles.scss @@ -1,4 +1,8 @@ -& { +@value transition-speed, transition-easing from 'accent-webapp/styles/variables/transitions'; +@value color-error, color-warning, color-success, color-grey, color-black from 'accent-webapp/styles/variables/colors'; +@value font-monospace, font-primary from 'accent-webapp/styles/variables/fonts'; + +.documents-list-item { position: relative; display: flex; margin-bottom: 30px; @@ -11,33 +15,33 @@ } } -&.low-percentage { +.documents-list-item.low-percentage { .reviewedPercentage { - color: $color-error; + color: color-error; } .progress { - background: $color-error; + color: color-error; } } -&.medium-percentage { +.documents-list-item.medium-percentage { .reviewedPercentage { - color: $color-warning; + color: color-warning; } .progress { - background: $color-warning; + color: color-warning; } } -&.high-percentage { +.documents-list-item.high-percentage { .reviewedPercentage { - color: $color-success; + color: color-success; } .progress { - background: $color-success; + color: color-success; } } @@ -58,16 +62,16 @@ font-size: 12px; } -.stat-progress { +.progress { margin: 3px 0 10px; } .reviewedStats { padding: 2px 7px 1px; border-radius: 3px; - background: lighten($color-grey, 25%); - color: $color-grey; - font-family: $font-monospace; + background: lighten(color-grey, 25%); + color: color-grey; + font-family: font-monospace; } .reviewedPercentage { @@ -101,19 +105,19 @@ padding: 5px 8px 4px; width: 100%; font-size: 15px; - font-family: $font-primary; + font-family: font-primary; } .item-document-deleting-title { display: flex; - color: $color-error; + color: color-error; font-size: 13px; } .item-document-deleting-title-loading { width: 10px; margin-right: 6px; - fill: $color-error; + fill: color-error; } .item-form { @@ -143,7 +147,7 @@ border: 1px solid #eee; border-radius: 3px; background: #fafafa; - font-family: $font-monospace; + font-family: font-monospace; font-style: normal; color: #777; } @@ -169,7 +173,7 @@ .item-document { margin-left: -20px; text-decoration: none; - color: $color-black; + color: color-black; } .item-edit-button { @@ -186,7 +190,7 @@ height: 16px; opacity: 0; stroke: #ccc; - transition: $transition-speed $transition-easing; + transition: transition-speed transition-easing; transition-property: opacity, stroke; &:focus, @@ -200,10 +204,10 @@ flex-wrap: wrap; justify-content: space-between; - .button { + :global(.button) { margin-right: 6px; - &.button--borderLess:first-of-type:last-of-type { + &:global(.button--borderLess):first-of-type:last-of-type { margin-left: -14px; } } @@ -211,6 +215,7 @@ .deleteDocumentButton { opacity: 0; + padding: 2px 6px !important; } @media (max-width: (800px)) { diff --git a/webapp/app/pods/components/documents-list/item/template.hbs b/webapp/app/pods/components/documents-list/item/template.hbs index cf2d4d2c..f891d102 100644 --- a/webapp/app/pods/components/documents-list/item/template.hbs +++ b/webapp/app/pods/components/documents-list/item/template.hbs @@ -1,132 +1,134 @@ -
    -
    -

    +
  • + +
    +

    + {{#if this.isEditing}} + + {{else}} + + {{#if this.isDeleting}} + + {{inline-svg "/assets/loading.svg" local-class="item-document-deleting-title-loading"}} + + {{t "components.documents_list.item.deleting_label" path=@document.path extension=this.documentFormatItem.extension}} + + {{else}} + + + + {{@document.path}} + .{{this.documentFormatItem.extension}} + + {{/if}} + + {{/if}} +

    +
    + + {{#unless this.isEditing}} +
    + + {{this.correctedKeysPercentage}} + % + + + + {{this.reviewsCount}} + + / + + {{@document.translationsCount}} + + +
    + +
    + +
    + {{/unless}} + +
    {{#if this.isEditing}} - +
    + + + {{t "components.documents_list.save_button"}} + +
    {{else}} - - {{#if this.isDeleting}} - - {{inline-svg "/assets/loading.svg" class="item-document-deleting-title-loading"}} - - {{t "components.documents_list.item.deleting_label"}} - {{document.path}}.{{documentFormatItem.extension}}… - - {{else}} - - +
    + {{#if (get @permissions "sync")}} - {{document.path}} - .{{documentFormatItem.extension}} + {{inline-svg "/assets/sync.svg" class="button-icon"}} + {{t "components.documents_list.sync"}} {{/if}} - - {{/if}} -
  • -
    - - {{#unless this.isEditing}} -
    - - {{correctedKeysPercentage}} - % - - - - {{reviewsCount}} - - / - - {{document.translationsCount}} - - -
    - -
    - -
    - {{/unless}} - - -
    + + {{inline-svg "/assets/export.svg" class="button-icon"}} + {{t "components.documents_list.export"}} + +
    + +
    + {{#if (get @permissions "delete_document")}} + {{#if this.canDeleteFile}} + + {{inline-svg "/assets/x.svg" class="button-icon"}} + {{t "components.documents_list.delete_document"}} + + {{/if}} + {{/if}} +
    + {{/if}} +
    + + diff --git a/webapp/app/pods/components/documents-list/styles.scss b/webapp/app/pods/components/documents-list/styles.scss index 653a50dd..e2972a67 100644 --- a/webapp/app/pods/components/documents-list/styles.scss +++ b/webapp/app/pods/components/documents-list/styles.scss @@ -1,4 +1,4 @@ -& { +.documents-list { width: 100%; display: flex; flex-wrap: wrap; diff --git a/webapp/app/pods/components/documents-list/template.hbs b/webapp/app/pods/components/documents-list/template.hbs index feb92116..d26ec600 100644 --- a/webapp/app/pods/components/documents-list/template.hbs +++ b/webapp/app/pods/components/documents-list/template.hbs @@ -1,9 +1,11 @@ -{{#each documents key="id" as |document|}} - -{{/each}} +
      + {{#each @documents key="id" as |document|}} + + {{/each}} +
    diff --git a/webapp/app/pods/components/dummy-login-form/component.js b/webapp/app/pods/components/dummy-login-form/component.js deleted file mode 100644 index d5763793..00000000 --- a/webapp/app/pods/components/dummy-login-form/component.js +++ /dev/null @@ -1,16 +0,0 @@ -import {inject as service} from '@ember/service'; -import Component from '@ember/component'; - -// Attributes: -// onDummyLogin: Function -export default Component.extend({ - session: service('session'), - - email: '', - - actions: { - submit() { - this.onDummyLogin(this.email); - } - } -}); diff --git a/webapp/app/pods/components/dummy-login-form/component.ts b/webapp/app/pods/components/dummy-login-form/component.ts new file mode 100644 index 00000000..cc01eae1 --- /dev/null +++ b/webapp/app/pods/components/dummy-login-form/component.ts @@ -0,0 +1,29 @@ +import {inject as service} from '@ember/service'; +import Component from '@glimmer/component'; +import {action} from '@ember/object'; +import Session from 'accent-webapp/services/session'; +import {tracked} from '@glimmer/tracking'; + +interface Args { + onDummyLogin: (email: string) => void; +} + +export default class DummyLoginForm extends Component { + @service('session') + session: Session; + + @tracked + email = ''; + + @action + setEmail(event: Event) { + const target = event.target as HTMLInputElement; + + this.email = target.value; + } + + @action + submit() { + this.args.onDummyLogin(this.email); + } +} diff --git a/webapp/app/pods/components/dummy-login-form/styles.scss b/webapp/app/pods/components/dummy-login-form/styles.scss index 4251078a..a364aa20 100644 --- a/webapp/app/pods/components/dummy-login-form/styles.scss +++ b/webapp/app/pods/components/dummy-login-form/styles.scss @@ -1,10 +1,13 @@ -& { +@value color-light-background, color-error, color-green from 'accent-webapp/styles/variables/colors'; +@value screen-sm from 'accent-webapp/styles/variables/dimensions'; + +.dummy-login-form { max-width: 500px; margin: 100px auto 30px; padding: 20px; box-shadow: 0 3px 21px rgba(#000, 0.07); border: 1px solid #eee; - background: $color-light-background; + background: color-light-background; text-align: center; } @@ -18,10 +21,10 @@ display: inline-block; padding: 10px 15px; margin-bottom: 20px; - background: lighten($color-error, 40%); + background: lighten(color-error, 40%); font-weight: bold; font-size: 12px; - color: $color-error; + color: color-error; } .subtitle { @@ -46,17 +49,17 @@ &:focus { border-right: 0; - border-color: $color-green; + border-color: color-green; } } .dummyLoginButton { - flex: 0 1 auto; - border-radius: 0 3px 3px 0; + flex: 0 1 auto !important; + border-radius: 0 3px 3px 0 !important; } -@media (max-width: ($screen-sm)) { - & { +@media (max-width: (screen-sm)) { + .dummy-login-form { margin-top: 30px; } } diff --git a/webapp/app/pods/components/dummy-login-form/template.hbs b/webapp/app/pods/components/dummy-login-form/template.hbs index de67984d..4ecc0d96 100644 --- a/webapp/app/pods/components/dummy-login-form/template.hbs +++ b/webapp/app/pods/components/dummy-login-form/template.hbs @@ -1,20 +1,26 @@ -

    - {{t "components.dummy_login_form.title"}} -

    +
    +

    + {{t "components.dummy_login_form.title"}} +

    -
    - {{t "components.dummy_login_form.warning"}} +
    + {{t "components.dummy_login_form.warning"}} +
    + +

    + {{t "components.dummy_login_form.subtitle" htmlSafe=true}} +

    + +
    + + + +
    - -

    - {{t "components.dummy_login_form.subtitle" htmlSafe=true}} -

    - -
    - - - -
    diff --git a/webapp/app/pods/components/empty-content/component.js b/webapp/app/pods/components/empty-content/component.js deleted file mode 100644 index 2c7ace2d..00000000 --- a/webapp/app/pods/components/empty-content/component.js +++ /dev/null @@ -1,7 +0,0 @@ -import Component from '@ember/component'; - -// Attributes: -// iconPath: String -// text: String -// block: Yield template (optional) -export default Component.extend(); diff --git a/webapp/app/pods/components/empty-content/component.ts b/webapp/app/pods/components/empty-content/component.ts new file mode 100644 index 00000000..3bc87ea9 --- /dev/null +++ b/webapp/app/pods/components/empty-content/component.ts @@ -0,0 +1,9 @@ +import Component from '@glimmer/component'; + +interface Args { + success?: boolean; + iconPath: string; + text: string; +} + +export default class EmptyContent extends Component {} diff --git a/webapp/app/pods/components/empty-content/styles.scss b/webapp/app/pods/components/empty-content/styles.scss index 0878ded4..0b76f4aa 100644 --- a/webapp/app/pods/components/empty-content/styles.scss +++ b/webapp/app/pods/components/empty-content/styles.scss @@ -1,26 +1,19 @@ -& { +@value color-black, color-error, color-green from 'accent-webapp/styles/variables/colors'; + +.empty-content { display: flex; justify-content: center; align-items: center; flex-direction: column; padding: 30px; margin: 0 auto; - color: rgba($color-black, 0.4); + color: rgba(color-black, 0.4); font-size: 18px; font-weight: 700; text-align: center; - &.error { - .icon { - stroke: $color-error; - opacity: 0.2; - width: 100px; - height: 100px; - } - } - &.success { - color: $color-green; + color: color-green; color: var(--color-primary); .icon { @@ -29,6 +22,17 @@ height: 100px; } } + + :global(.link) { + color: color-green; + color: var(--color-primary); + text-decoration: none; + + &:focus, + &:hover { + text-decoration: underline; + } + } } .icon { @@ -37,14 +41,3 @@ height: 50px; margin-bottom: 10px; } - -.link { - color: $color-green; - color: var(--color-primary); - text-decoration: none; - - &:focus, - &:hover { - text-decoration: underline; - } -} diff --git a/webapp/app/pods/components/empty-content/template.hbs b/webapp/app/pods/components/empty-content/template.hbs index 40882dff..757c5e5e 100644 --- a/webapp/app/pods/components/empty-content/template.hbs +++ b/webapp/app/pods/components/empty-content/template.hbs @@ -1,5 +1,7 @@ -{{#if hasBlock}} - {{yield}} -{{else}} - {{inline-svg iconPath class="icon"}}{{text}} -{{/if}} +
    + {{#if hasBlock}} + {{yield}} + {{else}} + {{inline-svg @iconPath local-class="icon"}}{{@text}} + {{/if}} +
    diff --git a/webapp/app/pods/components/error-section/component.js b/webapp/app/pods/components/error-section/component.js deleted file mode 100644 index 787525db..00000000 --- a/webapp/app/pods/components/error-section/component.js +++ /dev/null @@ -1,9 +0,0 @@ -import Component from '@ember/component'; - -// Attributes: -// status: String -// title: String -// text: String -// isAuthenticated: Boolean -// onLogin: Function -export default Component.extend(); diff --git a/webapp/app/pods/components/error-section/component.ts b/webapp/app/pods/components/error-section/component.ts new file mode 100644 index 00000000..c76b49ff --- /dev/null +++ b/webapp/app/pods/components/error-section/component.ts @@ -0,0 +1,11 @@ +import Component from '@glimmer/component'; + +interface Args { + status: string; + title: string; + text: string; + isAuthenticated: boolean; + onLogout?: () => void; +} + +export default class ErrorSection extends Component {} diff --git a/webapp/app/pods/components/error-section/styles.scss b/webapp/app/pods/components/error-section/styles.scss index 60f7e559..b0f7a367 100644 --- a/webapp/app/pods/components/error-section/styles.scss +++ b/webapp/app/pods/components/error-section/styles.scss @@ -1,10 +1,14 @@ -& { +@value color-light-background, color-green from 'accent-webapp/styles/variables/colors'; +@value font-monospace from 'accent-webapp/styles/variables/fonts'; +@value screen-sm from 'accent-webapp/styles/variables/dimensions'; + +.error-section { max-width: 400px; margin: 100px auto 30px; padding: 20px 20px 40px; box-shadow: 0 3px 21px rgba(#000, 0.07); border: 1px solid #eee; - background: $color-light-background; + background: color-light-background; text-align: center; } @@ -24,19 +28,19 @@ .status { margin-right: 15px; - text-shadow: 0 1px 2px rgba($color-green, 0.3); - font-family: $font-monospace; + text-shadow: 0 1px 2px rgba(color-green, 0.3); + font-family: font-monospace; font-size: 30px; font-weight: 300; - color: $color-green; + color: color-green; } .title { - font-family: $font-monospace; + font-family: font-monospace; font-size: 14px; font-style: italic; font-weight: 300; - color: rgba($color-green, 0.7); + color: rgba(color-green, 0.7); } .text { @@ -55,7 +59,7 @@ &:focus, &:hover { - color: $color-green; + color: color-green; text-decoration: underline; } } @@ -66,8 +70,8 @@ color: #bbb; } -@media (max-width: ($screen-sm)) { - & { +@media (max-width: (screen-sm)) { + .error-section { margin-top: 40px; } } diff --git a/webapp/app/pods/components/error-section/template.hbs b/webapp/app/pods/components/error-section/template.hbs index da6fc24c..a89c9f2c 100644 --- a/webapp/app/pods/components/error-section/template.hbs +++ b/webapp/app/pods/components/error-section/template.hbs @@ -1,29 +1,31 @@ -{{inline-svg "assets/logo-bw.svg" class="logo"}} +
    + {{inline-svg "assets/logo-bw.svg" local-class="logo"}} -
    -

    - {{status}} -

    +
    +

    + {{@status}} +

    -

    - {{title}} -

    +

    + {{@title}} +

    +
    + +

    + {{@text}} +

    + + {{#if @isAuthenticated}} + + + + {{t "components.error_section.or"}} + + {{/if}} + + + {{t "components.error_section.return"}} +
    - -

    - {{text}} -

    - -{{#if isAuthenticated}} - - - - {{t "components.error_section.or"}} - -{{/if}} - - - {{t "components.error_section.return"}} - diff --git a/webapp/app/pods/components/file-export/component.js b/webapp/app/pods/components/file-export/component.js deleted file mode 100644 index fed6a068..00000000 --- a/webapp/app/pods/components/file-export/component.js +++ /dev/null @@ -1,38 +0,0 @@ -import {inject as service} from '@ember/service'; -import Component from '@ember/component'; - -// Attributes: -// project: Object -// document: Object -// revision: Object -// documentFormat: String -// orderBy: String -export default Component.extend({ - exporter: service(), - - tagName: 'pre', - content: '', - - didReceiveAttrs() { - this._super(...arguments); - - if (!this.revision && !this.revisions) return; - if (!this.document) return; - - const revision = this.revision || this.revisions[0]; - - this.exporter - .export({ - revision, - ...this.getProperties( - 'project', - 'document', - 'version', - 'documentFormat', - 'orderBy' - ) - }) - .then(data => this.set('content', data)) - .then(data => this.onFileLoaded(data)); - } -}); diff --git a/webapp/app/pods/components/file-export/component.ts b/webapp/app/pods/components/file-export/component.ts new file mode 100644 index 00000000..84b052b1 --- /dev/null +++ b/webapp/app/pods/components/file-export/component.ts @@ -0,0 +1,45 @@ +import {inject as service} from '@ember/service'; +import {action} from '@ember/object'; +import Component from '@glimmer/component'; +import Exporter from 'accent-webapp/services/exporter'; +import {tracked} from '@glimmer/tracking'; + +interface Args { + class: string; + onFileLoaded: (data: any) => void; + project: any; + revisions: any; + revision: any; + document: any; + documentFormat: any; + orderBy: any; + version?: any; +} + +export default class FileExport extends Component { + @service('exporter') + exporter: Exporter; + + @tracked + content = ''; + + @action + async onUpdate() { + if (!this.args.revision && !this.args.revisions) return; + if (!this.args.document) return; + + const revision = this.args.revision || this.args.revisions[0]; + + const data = await this.exporter.export({ + revision, + project: this.args.project, + document: this.args.document, + version: this.args.version, + documentFormat: this.args.documentFormat, + orderBy: this.args.orderBy, + }); + + this.content = data; + this.args.onFileLoaded(data); + } +} diff --git a/webapp/app/pods/components/file-export/template.hbs b/webapp/app/pods/components/file-export/template.hbs index b92f6522..f9075ef1 100644 --- a/webapp/app/pods/components/file-export/template.hbs +++ b/webapp/app/pods/components/file-export/template.hbs @@ -1 +1,5 @@ -{{content}} +
    {{content}}
    diff --git a/webapp/app/pods/components/file-input/component.js b/webapp/app/pods/components/file-input/component.js deleted file mode 100644 index 9c8b9489..00000000 --- a/webapp/app/pods/components/file-input/component.js +++ /dev/null @@ -1,25 +0,0 @@ -import Component from '@ember/component'; -import Evented from '@ember/object/evented'; - -const attributeBindings = [ - 'name', - 'disabled', - 'form', - 'type', - 'accept', - 'autofocus', - 'required', - 'multiple' -]; - -// Attributes -// onChange: Function -export default Component.extend(Evented, { - tagName: 'input', - type: 'file', - attributeBindings, - - change(event) { - this.onChange(event.target.files); - } -}); diff --git a/webapp/app/pods/components/file-input/component.ts b/webapp/app/pods/components/file-input/component.ts new file mode 100644 index 00000000..0ad4d435 --- /dev/null +++ b/webapp/app/pods/components/file-input/component.ts @@ -0,0 +1,15 @@ +import {action} from '@ember/object'; +import Component from '@glimmer/component'; + +interface Args { + onChange: (files: FileList | null) => void; +} + +export default class FileInput extends Component { + @action + onChange(event: Event) { + const target = event.target as HTMLInputElement; + + this.args.onChange(target.files); + } +} diff --git a/webapp/app/pods/components/file-input/template.hbs b/webapp/app/pods/components/file-input/template.hbs new file mode 100644 index 00000000..aeb4fb31 --- /dev/null +++ b/webapp/app/pods/components/file-input/template.hbs @@ -0,0 +1,5 @@ + diff --git a/webapp/app/pods/components/flash-messages-list/component.js b/webapp/app/pods/components/flash-messages-list/component.js deleted file mode 100644 index d7002476..00000000 --- a/webapp/app/pods/components/flash-messages-list/component.js +++ /dev/null @@ -1,5 +0,0 @@ -import Component from '@ember/component'; - -// Attribute -// flashMessages: Array of from ember-cli-flash lib -export default Component.extend(); diff --git a/webapp/app/pods/components/flash-messages-list/component.ts b/webapp/app/pods/components/flash-messages-list/component.ts new file mode 100644 index 00000000..12a027bf --- /dev/null +++ b/webapp/app/pods/components/flash-messages-list/component.ts @@ -0,0 +1,7 @@ +import Component from '@glimmer/component'; + +interface Args { + flashMessages: any; +} + +export default class FlashMessagesList extends Component {} diff --git a/webapp/app/pods/components/flash-messages-list/styles.scss b/webapp/app/pods/components/flash-messages-list/styles.scss index 16d49392..fafa7419 100644 --- a/webapp/app/pods/components/flash-messages-list/styles.scss +++ b/webapp/app/pods/components/flash-messages-list/styles.scss @@ -1,4 +1,4 @@ -& { +.flash-messages-list { position: fixed; top: 20px; right: 20px; diff --git a/webapp/app/pods/components/flash-messages-list/template.hbs b/webapp/app/pods/components/flash-messages-list/template.hbs index 2f7f71cb..010f3ac9 100644 --- a/webapp/app/pods/components/flash-messages-list/template.hbs +++ b/webapp/app/pods/components/flash-messages-list/template.hbs @@ -1,3 +1,5 @@ -{{#each flashMessages.queue as |flash|}} - -{{/each}} +
    + {{#each @flashMessages.queue as |flash|}} + + {{/each}} +
    diff --git a/webapp/app/pods/components/google-login-form/styles.scss b/webapp/app/pods/components/google-login-form/styles.scss index 56297510..353f984b 100644 --- a/webapp/app/pods/components/google-login-form/styles.scss +++ b/webapp/app/pods/components/google-login-form/styles.scss @@ -1,4 +1,6 @@ -& { +@value screen-sm from 'accent-webapp/styles/variables/dimensions'; + +.google-login-form { max-width: 500px; margin: 0 auto 30px; text-align: center; @@ -24,8 +26,8 @@ } } -@media (max-width: ($screen-sm)) { - & { +@media (max-width: (screen-sm)) { + .google-login-form { margin-top: 30px; } } diff --git a/webapp/app/pods/components/google-login-form/template.hbs b/webapp/app/pods/components/google-login-form/template.hbs index 1dbd2151..d28c7487 100644 --- a/webapp/app/pods/components/google-login-form/template.hbs +++ b/webapp/app/pods/components/google-login-form/template.hbs @@ -1,5 +1,7 @@ - - +
    + + - {{t "components.google_login_form.login_button"}} - + {{t "components.google_login_form.login_button"}} + +
    diff --git a/webapp/app/pods/components/jipt-back-to-translations/component.js b/webapp/app/pods/components/jipt-back-to-translations/component.js deleted file mode 100644 index cbfd5011..00000000 --- a/webapp/app/pods/components/jipt-back-to-translations/component.js +++ /dev/null @@ -1,3 +0,0 @@ -import Component from '@ember/component'; - -export default Component.extend(); diff --git a/webapp/app/pods/components/jipt-back-to-translations/component.ts b/webapp/app/pods/components/jipt-back-to-translations/component.ts new file mode 100644 index 00000000..aa2a9691 --- /dev/null +++ b/webapp/app/pods/components/jipt-back-to-translations/component.ts @@ -0,0 +1,3 @@ +import Component from '@glimmer/component'; + +export default class BackToTranslations extends Component {} diff --git a/webapp/app/pods/components/jipt-back-to-translations/styles.scss b/webapp/app/pods/components/jipt-back-to-translations/styles.scss index 3739acac..c823caaa 100644 --- a/webapp/app/pods/components/jipt-back-to-translations/styles.scss +++ b/webapp/app/pods/components/jipt-back-to-translations/styles.scss @@ -1,18 +1,21 @@ +@value transition-speed, transition-easing from 'accent-webapp/styles/variables/transitions'; +@value color-black from 'accent-webapp/styles/variables/colors'; + .language { display: block; margin-bottom: 6px; - color: lighten($color-black, 20%); + color: lighten(color-black, 20%); font-size: 14px; text-decoration: none; - transition: $transition-speed $transition-easing; + transition: transition-speed transition-easing; transition-property: color; &:focus, &:hover { - color: $color-black; + color: color-black; .back-icon { - stroke: $color-black; + stroke: color-black; transform: translateX(-2px); } } @@ -21,7 +24,7 @@ .back-icon { width: 11px; height: 11px; - stroke: lighten($color-black, 20%); - transition: $transition-speed $transition-easing; + stroke: lighten(color-black, 20%); + transition: transition-speed transition-easing; transition-property: fill transform; } diff --git a/webapp/app/pods/components/jipt-back-to-translations/template.hbs b/webapp/app/pods/components/jipt-back-to-translations/template.hbs index d501b570..c414dd2d 100644 --- a/webapp/app/pods/components/jipt-back-to-translations/template.hbs +++ b/webapp/app/pods/components/jipt-back-to-translations/template.hbs @@ -1,5 +1,5 @@ - - {{inline-svg "assets/chevron-left.svg" class="back-icon"}} + + {{inline-svg "assets/chevron-left.svg" local-class="back-icon"}} {{t "components.jipt.back_to_translations.back"}} diff --git a/webapp/app/pods/components/jipt-export/component.js b/webapp/app/pods/components/jipt-export/component.js deleted file mode 100644 index ad4381d0..00000000 --- a/webapp/app/pods/components/jipt-export/component.js +++ /dev/null @@ -1,25 +0,0 @@ -import {inject as service} from '@ember/service'; -import Component from '@ember/component'; - -export default Component.extend({ - exporter: service(), - - tagName: 'pre', - content: '', - - didReceiveAttrs() { - this._super(...arguments); - - this.exporter - .jipt({ - ...this.getProperties( - 'project', - 'document', - 'version', - 'documentFormat' - ) - }) - .then(data => this.set('content', data)) - .then(data => this.onFileLoaded(data)); - } -}); diff --git a/webapp/app/pods/components/jipt-export/component.ts b/webapp/app/pods/components/jipt-export/component.ts new file mode 100644 index 00000000..c0d5634b --- /dev/null +++ b/webapp/app/pods/components/jipt-export/component.ts @@ -0,0 +1,34 @@ +import {inject as service} from '@ember/service'; +import {action} from '@ember/object'; +import Component from '@glimmer/component'; +import Exporter from 'accent-webapp/services/exporter'; +import {tracked} from '@glimmer/tracking'; + +interface Args { + project: any; + document: any; + version: any; + documentFormat: any; + onFileLoaded: (data: any) => void; +} + +export default class JIPTExport extends Component { + @service('exporter') + exporter: Exporter; + + @tracked + content = ''; + + @action + async onUpdate() { + const data = await this.exporter.jipt({ + project: this.args.project, + document: this.args.document, + version: this.args.version, + documentFormat: this.args.documentFormat, + }); + + this.content = data; + this.args.onFileLoaded(data); + } +} diff --git a/webapp/app/pods/components/jipt-export/template.hbs b/webapp/app/pods/components/jipt-export/template.hbs index b92f6522..f331b763 100644 --- a/webapp/app/pods/components/jipt-export/template.hbs +++ b/webapp/app/pods/components/jipt-export/template.hbs @@ -1 +1,5 @@ -{{content}} +
    {{content}}
    diff --git a/webapp/app/pods/components/jipt-header/component.js b/webapp/app/pods/components/jipt-header/component.js deleted file mode 100644 index cbfd5011..00000000 --- a/webapp/app/pods/components/jipt-header/component.js +++ /dev/null @@ -1,3 +0,0 @@ -import Component from '@ember/component'; - -export default Component.extend(); diff --git a/webapp/app/pods/components/jipt-header/component.ts b/webapp/app/pods/components/jipt-header/component.ts new file mode 100644 index 00000000..59d07311 --- /dev/null +++ b/webapp/app/pods/components/jipt-header/component.ts @@ -0,0 +1,7 @@ +import Component from '@glimmer/component'; + +interface Args { + project: any; +} + +export default class JIPTHeader extends Component {} diff --git a/webapp/app/pods/components/jipt-header/styles.scss b/webapp/app/pods/components/jipt-header/styles.scss index 6822b96c..f962a1e0 100644 --- a/webapp/app/pods/components/jipt-header/styles.scss +++ b/webapp/app/pods/components/jipt-header/styles.scss @@ -1,4 +1,6 @@ -& { +@value color-black, color-green from 'accent-webapp/styles/variables/colors'; + +.jipt-header { position: sticky; top: 0; z-index: 5000; @@ -12,7 +14,7 @@ margin: 0 0 0 10px; font-size: 14px; font-weight: 700; - color: $color-black; + color: color-black; } .applicationLogo { @@ -25,7 +27,7 @@ } path { - fill: $color-green; + fill: color-green; fill: var(--color-primary); } } diff --git a/webapp/app/pods/components/jipt-header/template.hbs b/webapp/app/pods/components/jipt-header/template.hbs index c164c3dd..64988d47 100644 --- a/webapp/app/pods/components/jipt-header/template.hbs +++ b/webapp/app/pods/components/jipt-header/template.hbs @@ -1,10 +1,12 @@ - +
    +
    + {{inline-svg + "assets/logo.svg" + local-class="applicationLogo-image applicationLogo-image--linked" + }} +
    -
    - {{t "general.application_name"}} +
    + {{t "general.application_name"}} +
    diff --git a/webapp/app/pods/components/jipt-translation/styles.scss b/webapp/app/pods/components/jipt-translation/styles.scss index 5fa295fa..6dc05d17 100644 --- a/webapp/app/pods/components/jipt-translation/styles.scss +++ b/webapp/app/pods/components/jipt-translation/styles.scss @@ -1,3 +1,3 @@ -& { +.jipt-translation { margin: 15px; } diff --git a/webapp/app/pods/components/jipt-translation/template.hbs b/webapp/app/pods/components/jipt-translation/template.hbs index 889d9eea..bfb98126 100644 --- a/webapp/app/pods/components/jipt-translation/template.hbs +++ b/webapp/app/pods/components/jipt-translation/template.hbs @@ -1 +1,3 @@ -{{yield}} +
    + {{yield}} +
    diff --git a/webapp/app/pods/components/jipt-translations-filtered-title/component.js b/webapp/app/pods/components/jipt-translations-filtered-title/component.js deleted file mode 100644 index cbfd5011..00000000 --- a/webapp/app/pods/components/jipt-translations-filtered-title/component.js +++ /dev/null @@ -1,3 +0,0 @@ -import Component from '@ember/component'; - -export default Component.extend(); diff --git a/webapp/app/pods/components/jipt-translations-filtered-title/component.ts b/webapp/app/pods/components/jipt-translations-filtered-title/component.ts new file mode 100644 index 00000000..0221b84a --- /dev/null +++ b/webapp/app/pods/components/jipt-translations-filtered-title/component.ts @@ -0,0 +1,7 @@ +import Component from '@glimmer/component'; + +interface Args { + count: number; +} + +export default class TranslationsFilteredTitle extends Component {} diff --git a/webapp/app/pods/components/jipt-translations-filtered-title/styles.scss b/webapp/app/pods/components/jipt-translations-filtered-title/styles.scss index 0c1901e2..8cc77101 100644 --- a/webapp/app/pods/components/jipt-translations-filtered-title/styles.scss +++ b/webapp/app/pods/components/jipt-translations-filtered-title/styles.scss @@ -1,4 +1,4 @@ -& { +.jipt-translations-filtered-title { margin: 20px 0 0; text-align: center; font-style: italic; diff --git a/webapp/app/pods/components/jipt-translations-filtered-title/template.hbs b/webapp/app/pods/components/jipt-translations-filtered-title/template.hbs index 7ab608a6..b7981bc5 100644 --- a/webapp/app/pods/components/jipt-translations-filtered-title/template.hbs +++ b/webapp/app/pods/components/jipt-translations-filtered-title/template.hbs @@ -1 +1,3 @@ -{{t "components.jipt.translations_filtered_title.title_count" count=count}} +
    + {{t "components.jipt.translations_filtered_title.title_count" count=@count}} +
    diff --git a/webapp/app/pods/components/jipt-translations-list/component.js b/webapp/app/pods/components/jipt-translations-list/component.js deleted file mode 100644 index cbfd5011..00000000 --- a/webapp/app/pods/components/jipt-translations-list/component.js +++ /dev/null @@ -1,3 +0,0 @@ -import Component from '@ember/component'; - -export default Component.extend(); diff --git a/webapp/app/pods/components/jipt-translations-list/component.ts b/webapp/app/pods/components/jipt-translations-list/component.ts new file mode 100644 index 00000000..e158b8cc --- /dev/null +++ b/webapp/app/pods/components/jipt-translations-list/component.ts @@ -0,0 +1,7 @@ +import Component from '@glimmer/component'; + +interface Args { + translations: any; +} + +export default class JIPTTranslationsList extends Component {} diff --git a/webapp/app/pods/components/jipt-translations-list/item/component.js b/webapp/app/pods/components/jipt-translations-list/item/component.js deleted file mode 100644 index 91e052e5..00000000 --- a/webapp/app/pods/components/jipt-translations-list/item/component.js +++ /dev/null @@ -1,8 +0,0 @@ -import {equal} from '@ember/object/computed'; -import Component from '@ember/component'; - -// Attributes: -// translation: Object -export default Component.extend({ - isTextEmpty: equal('translation.valueType', 'EMPTY') -}); diff --git a/webapp/app/pods/components/jipt-translations-list/item/component.ts b/webapp/app/pods/components/jipt-translations-list/item/component.ts new file mode 100644 index 00000000..bd7b09c2 --- /dev/null +++ b/webapp/app/pods/components/jipt-translations-list/item/component.ts @@ -0,0 +1,11 @@ +import {equal} from '@ember/object/computed'; +import Component from '@glimmer/component'; + +interface Args { + translation: any; +} + +export default class JIPTTranslationsListItem extends Component { + @equal('translation.valueType', 'EMPTY') + isTextEmpty: boolean; +} diff --git a/webapp/app/pods/components/jipt-translations-list/item/styles.scss b/webapp/app/pods/components/jipt-translations-list/item/styles.scss index 5d9d86e5..df0e36cb 100644 --- a/webapp/app/pods/components/jipt-translations-list/item/styles.scss +++ b/webapp/app/pods/components/jipt-translations-list/item/styles.scss @@ -1,12 +1,14 @@ +@value color-true-black, color-grey from 'accent-webapp/styles/variables/colors'; + .item-text { display: block; text-overflow: ellipsis; overflow-x: hidden; - color: $color-true-black; + color: color-true-black; font-size: 16px; &.item-text--empty { - color: $color-grey; + color: color-grey; font-style: italic; } } diff --git a/webapp/app/pods/components/jipt-translations-list/item/template.hbs b/webapp/app/pods/components/jipt-translations-list/item/template.hbs index 9dbc8e20..a7dd2684 100644 --- a/webapp/app/pods/components/jipt-translations-list/item/template.hbs +++ b/webapp/app/pods/components/jipt-translations-list/item/template.hbs @@ -1,5 +1,5 @@ {{#if this.isTextEmpty}} - {{t "components.translations_list.empty_text"}} + {{t "components.translations_list.empty_text"}} {{else}} - {{@translation.correctedText}} + {{@translation.correctedText}} {{/if}} diff --git a/webapp/app/pods/components/jipt-translations-list/styles.scss b/webapp/app/pods/components/jipt-translations-list/styles.scss index 5a583485..0eb7deff 100644 --- a/webapp/app/pods/components/jipt-translations-list/styles.scss +++ b/webapp/app/pods/components/jipt-translations-list/styles.scss @@ -1,4 +1,7 @@ -& { +@value transition-speed, transition-easing from 'accent-webapp/styles/variables/transitions'; +@value color-light-background, color-black from 'accent-webapp/styles/variables/colors'; + +.jipt-translations-list { margin: 20px 0; border-top: 1px solid #eee; } @@ -11,13 +14,13 @@ white-space: nowrap; overflow: hidden; text-overflow: ellipsis; - transition: $transition-speed $transition-easing; + transition: transition-speed transition-easing; transition-property: padding, background; &:focus, &:hover { - background: $color-light-background; - color: $color-black; + background: color-light-background; + color: color-black; color: var(--color-black); } } diff --git a/webapp/app/pods/components/jipt-translations-list/template.hbs b/webapp/app/pods/components/jipt-translations-list/template.hbs index a958c66d..bd9f4a42 100644 --- a/webapp/app/pods/components/jipt-translations-list/template.hbs +++ b/webapp/app/pods/components/jipt-translations-list/template.hbs @@ -1,9 +1,11 @@ -{{#each translations key="id" as |translation|}} - - - -{{/each}} +
    + {{#each @translations key="id" as |translation|}} + + + + {{/each}} +
    diff --git a/webapp/app/pods/components/loading-content/component.js b/webapp/app/pods/components/loading-content/component.js deleted file mode 100644 index 55024ccd..00000000 --- a/webapp/app/pods/components/loading-content/component.js +++ /dev/null @@ -1,7 +0,0 @@ -import Component from '@ember/component'; - -// Attributes: -// label: String -export default Component.extend({ - color: '#222' -}); diff --git a/webapp/app/pods/components/loading-content/component.ts b/webapp/app/pods/components/loading-content/component.ts new file mode 100644 index 00000000..2c9d5c4b --- /dev/null +++ b/webapp/app/pods/components/loading-content/component.ts @@ -0,0 +1,7 @@ +import Component from '@glimmer/component'; + +interface Args { + label?: string; +} + +export default class LoadingContent extends Component {} diff --git a/webapp/app/pods/components/loading-content/styles.scss b/webapp/app/pods/components/loading-content/styles.scss index 4de2c46e..2a5f699f 100644 --- a/webapp/app/pods/components/loading-content/styles.scss +++ b/webapp/app/pods/components/loading-content/styles.scss @@ -1,4 +1,6 @@ -& { +@value color-grey from 'accent-webapp/styles/variables/colors'; + +.loading-content { display: flex; position: relative; flex-direction: column; @@ -6,29 +8,29 @@ justify-content: center; margin-top: 70px; padding: 40px 0; -} -svg { - position: relative; - left: -4px; - width: 3.75em; - margin-bottom: 30px; - transform-origin: center; - animation: loading-content-rotate 2s ease-in infinite; -} + svg { + position: relative; + left: -4px; + width: 3.75em; + margin-bottom: 30px; + transform-origin: center; + animation: loading-content-rotate 2s ease-in infinite; + } -circle { - fill: none; - stroke: $color-grey; - stroke-width: 2; - stroke-dasharray: 1, 200; - stroke-dashoffset: 0; - stroke-linecap: round; - animation: loading-content-dash 1s ease-in infinite; + circle { + fill: none; + stroke: color-grey; + stroke-width: 2; + stroke-dasharray: 1, 200; + stroke-dashoffset: 0; + stroke-linecap: round; + animation: loading-content-dash 1s ease-in infinite; + } } .label { - color: $color-grey; + color: color-grey; font-size: 14px; font-style: italic; } diff --git a/webapp/app/pods/components/loading-content/template.hbs b/webapp/app/pods/components/loading-content/template.hbs index 115553d5..283a2cad 100644 --- a/webapp/app/pods/components/loading-content/template.hbs +++ b/webapp/app/pods/components/loading-content/template.hbs @@ -1,7 +1,9 @@ - - - +
    + + + -{{#if label}} - {{label}} -{{/if}} + {{#if @label}} + {{@label}} + {{/if}} +
    diff --git a/webapp/app/pods/components/login-footer/component.js b/webapp/app/pods/components/login-footer/component.js deleted file mode 100644 index cbfd5011..00000000 --- a/webapp/app/pods/components/login-footer/component.js +++ /dev/null @@ -1,3 +0,0 @@ -import Component from '@ember/component'; - -export default Component.extend(); diff --git a/webapp/app/pods/components/login-footer/component.ts b/webapp/app/pods/components/login-footer/component.ts new file mode 100644 index 00000000..7cbabf2a --- /dev/null +++ b/webapp/app/pods/components/login-footer/component.ts @@ -0,0 +1,3 @@ +import Component from '@glimmer/component'; + +export default class LoginFooter extends Component {} diff --git a/webapp/app/pods/components/login-footer/styles.scss b/webapp/app/pods/components/login-footer/styles.scss index 8b99f956..b439d7db 100644 --- a/webapp/app/pods/components/login-footer/styles.scss +++ b/webapp/app/pods/components/login-footer/styles.scss @@ -1,4 +1,7 @@ -& { +@value color-black, color-green from 'accent-webapp/styles/variables/colors'; +@value screen-sm from 'accent-webapp/styles/variables/dimensions'; + +.login-footer { max-width: 500px; margin: 30px auto 60px; padding-top: 14px; @@ -7,11 +10,11 @@ .text { font-size: 12px; - color: lighten($color-black, 50%); + color: lighten(color-black, 50%); } .link { - color: $color-green; + color: color-green; text-decoration: none; &:focus, @@ -20,8 +23,8 @@ } } -@media (max-width: ($screen-sm)) { - & { +@media (max-width: (screen-sm)) { + .login-footer { margin-top: 30px; } } diff --git a/webapp/app/pods/components/login-footer/template.hbs b/webapp/app/pods/components/login-footer/template.hbs index 1d6b31e6..2e0ae9aa 100644 --- a/webapp/app/pods/components/login-footer/template.hbs +++ b/webapp/app/pods/components/login-footer/template.hbs @@ -1,12 +1,14 @@ -

    - {{t "components.login_footer.text"}} +

    diff --git a/webapp/app/pods/components/login-forms/component.js b/webapp/app/pods/components/login-forms/component.js deleted file mode 100644 index c540cca9..00000000 --- a/webapp/app/pods/components/login-forms/component.js +++ /dev/null @@ -1,37 +0,0 @@ -// Vendor -import Component from '@ember/component'; -import {computed} from '@ember/object'; -import config from 'accent-webapp/config/environment'; - -export default Component.extend({ - username: '', - providerIds: computed('providers.[].id', function() { - return this.providers.map(({id}) => id); - }), - - googleLoginEnabled: computed('providerIds', function() { - return this.providerIds.includes('google'); - }), - dummyLoginEnabled: computed('providerIds', function() { - return this.providerIds.includes('dummy'); - }), - githubLoginEnabled: computed('providerIds', function() { - return this.providerIds.includes('github'); - }), - slackLoginEnabled: computed('providerIds', function() { - return this.providerIds.includes('slack'); - }), - discordLoginEnabled: computed('providerIds', function() { - return this.providerIds.includes('discord'); - }), - - googleUrl: computed(() => `${config.API.AUTHENTICATION_PATH}/google`), - githubUrl: computed(() => `${config.API.AUTHENTICATION_PATH}/github`), - slackUrl: computed(() => `${config.API.AUTHENTICATION_PATH}/slack`), - discordUrl: computed(() => `${config.API.AUTHENTICATION_PATH}/discord`), - dummyUrl: computed('username', function() { - return `${ - config.API.AUTHENTICATION_PATH - }/dummy/callback?email=${this.username}`; - }) -}); diff --git a/webapp/app/pods/components/login-forms/component.ts b/webapp/app/pods/components/login-forms/component.ts new file mode 100644 index 00000000..68738d39 --- /dev/null +++ b/webapp/app/pods/components/login-forms/component.ts @@ -0,0 +1,52 @@ +// Vendor +import Component from '@glimmer/component'; +import {action} from '@ember/object'; +import config from 'accent-webapp/config/environment'; +import {tracked} from '@glimmer/tracking'; + +interface Args { + providers: any; +} + +export default class LoginForms extends Component { + @tracked + username = ''; + + googleUrl = `${config.API.AUTHENTICATION_PATH}/google`; + githubUrl = `${config.API.AUTHENTICATION_PATH}/github`; + slackUrl = `${config.API.AUTHENTICATION_PATH}/slack`; + discordUrl = `${config.API.AUTHENTICATION_PATH}/discord`; + + get providerIds() { + return this.args.providers.map(({id}: {id: string}) => id); + } + + get googleLoginEnabled() { + return this.providerIds.includes('google'); + } + + get dummyLoginEnabled() { + return this.providerIds.includes('dummy'); + } + + get githubLoginEnabled() { + return this.providerIds.includes('github'); + } + + get slackLoginEnabled() { + return this.providerIds.includes('slack'); + } + + get discordLoginEnabled() { + return this.providerIds.includes('discord'); + } + + get dummyUrl() { + return `${config.API.AUTHENTICATION_PATH}/dummy/callback?email=${this.username}`; + } + + @action + setUsername(username: string) { + this.username = username; + } +} diff --git a/webapp/app/pods/components/login-forms/styles.scss b/webapp/app/pods/components/login-forms/styles.scss index 8f0b55c0..96a73218 100644 --- a/webapp/app/pods/components/login-forms/styles.scss +++ b/webapp/app/pods/components/login-forms/styles.scss @@ -1,4 +1,7 @@ -& { +@value color-green from 'accent-webapp/styles/variables/colors'; +@value font-primary from 'accent-webapp/styles/variables/fonts'; + +.login-forms { max-width: 500px; margin: 0 auto 30px; } @@ -8,12 +11,12 @@ max-width: 300px; padding: 10px; width: 100%; - font-family: $font-primary; + font-family: font-primary; font-size: 13px; - border: 2px solid darken($color-green, 5%); + border: 2px solid darken(color-green, 5%); &:focus { - border-color: $color-green; + border-color: color-green; } } @@ -42,8 +45,8 @@ } &.loginButton--dummy { - border: 2px solid darken($color-green, 5%); - background: $color-green; + border: 2px solid darken(color-green, 5%); + background: color-green; border-radius: 0 0 4px 4px; margin-top: -3px; } diff --git a/webapp/app/pods/components/login-forms/template.hbs b/webapp/app/pods/components/login-forms/template.hbs index 98133d23..0ddf58a5 100644 --- a/webapp/app/pods/components/login-forms/template.hbs +++ b/webapp/app/pods/components/login-forms/template.hbs @@ -1,49 +1,63 @@ -{{#if providers}} - {{#if dummyLoginEnabled}} - - - - {{t "components.login_forms.dummy"}} - - {{/if}} +
    + {{#if @providers}} + {{#if this.dummyLoginEnabled}} + + + + {{t "components.login_forms.dummy"}} + + {{/if}} - {{#if googleLoginEnabled}} - - - {{t "components.login_forms.google"}} - - {{/if}} + {{#if this.googleLoginEnabled}} + + + {{t "components.login_forms.google"}} + + {{/if}} - {{#if githubLoginEnabled}} - - - {{t "components.login_forms.github"}} - - {{/if}} + {{#if this.githubLoginEnabled}} + + + {{t "components.login_forms.github"}} + + {{/if}} - {{#if slackLoginEnabled}} - - - {{t "components.login_forms.slack"}} - - {{/if}} + {{#if this.slackLoginEnabled}} + + + {{t "components.login_forms.slack"}} + + {{/if}} - {{#if discordLoginEnabled}} - - - {{t "components.login_forms.discord"}} - + {{#if this.discordLoginEnabled}} + + + {{t "components.login_forms.discord"}} + + {{/if}} {{/if}} -{{/if}} +
    diff --git a/webapp/app/pods/components/login-header/component.js b/webapp/app/pods/components/login-header/component.js deleted file mode 100644 index 04719e3d..00000000 --- a/webapp/app/pods/components/login-header/component.js +++ /dev/null @@ -1,5 +0,0 @@ -import Component from '@ember/component'; - -export default Component.extend({ - tagName: 'header' -}); diff --git a/webapp/app/pods/components/login-header/component.ts b/webapp/app/pods/components/login-header/component.ts new file mode 100644 index 00000000..59031882 --- /dev/null +++ b/webapp/app/pods/components/login-header/component.ts @@ -0,0 +1,3 @@ +import Component from '@glimmer/component'; + +export default class LoginHeader extends Component {} diff --git a/webapp/app/pods/components/login-header/styles.scss b/webapp/app/pods/components/login-header/styles.scss index 8acff2a0..da298abb 100644 --- a/webapp/app/pods/components/login-header/styles.scss +++ b/webapp/app/pods/components/login-header/styles.scss @@ -1,4 +1,7 @@ -& { +@value color-black from 'accent-webapp/styles/variables/colors'; +@value screen-sm from 'accent-webapp/styles/variables/dimensions'; + +.login-header { max-width: 500px; margin: 100px auto 40px; } @@ -14,13 +17,13 @@ text-decoration: none; font-size: 25px; font-weight: 700; - color: $color-black; + color: color-black; } .text { font-size: 17px; line-height: 1.3; - color: lighten($color-black, 40%); + color: lighten(color-black, 40%); } .text-emphasis { @@ -29,7 +32,7 @@ font-weight: bold; font-size: 22px; font-style: normal; - color: $color-black; + color: color-black; } .logo { @@ -37,8 +40,8 @@ height: 30px; } -@media (max-width: ($screen-sm)) { - & { +@media (max-width: (screen-sm)) { + .login-header { margin-top: 30px; } } diff --git a/webapp/app/pods/components/login-header/template.hbs b/webapp/app/pods/components/login-header/template.hbs index 15747ea8..f7f16934 100644 --- a/webapp/app/pods/components/login-header/template.hbs +++ b/webapp/app/pods/components/login-header/template.hbs @@ -1,13 +1,15 @@ -

    - {{inline-svg "assets/logo.svg" class="logo"}} - - {{t "general.application_name"}} - -

    +
    +

    + {{inline-svg "assets/logo.svg" local-class="logo"}} + + {{t "general.application_name"}} + +

    -

    - - {{t "components.login_header.text"}} - - {{t "components.login_header.subtext"}} -

    +

    + + {{t "components.login_header.text"}} + + {{t "components.login_header.subtext"}} +

    +
    diff --git a/webapp/app/pods/components/operations-peek/component.js b/webapp/app/pods/components/operations-peek/component.js deleted file mode 100644 index 79fd3768..00000000 --- a/webapp/app/pods/components/operations-peek/component.js +++ /dev/null @@ -1,5 +0,0 @@ -import Component from '@ember/component'; - -// Attributes -// revisionOperations: Array of Ember.Object containing and -export default Component.extend(); diff --git a/webapp/app/pods/components/operations-peek/component.ts b/webapp/app/pods/components/operations-peek/component.ts new file mode 100644 index 00000000..d054b8be --- /dev/null +++ b/webapp/app/pods/components/operations-peek/component.ts @@ -0,0 +1,7 @@ +import Component from '@glimmer/component'; + +interface Args { + revisionOperations: any; +} + +export default class RevisionOperations extends Component {} diff --git a/webapp/app/pods/components/operations-peek/item/component.js b/webapp/app/pods/components/operations-peek/item/component.js deleted file mode 100644 index 972c6b20..00000000 --- a/webapp/app/pods/components/operations-peek/item/component.js +++ /dev/null @@ -1,35 +0,0 @@ -import Component from '@ember/component'; - -// Attributes -// revisionOperation: Object containing the and array of -export default Component.extend({ - showStats: true, - showOperations: false, - hideDetails: false, - - actions: { - showStats() { - this.setProperties({ - showStats: true, - showOperations: false, - hideDetails: false - }); - }, - - showOperations() { - this.setProperties({ - showStats: false, - showOperations: true, - hideDetails: false - }); - }, - - hideDetails() { - this.setProperties({ - showStats: false, - showOperations: false, - hideDetails: true - }); - } - } -}); diff --git a/webapp/app/pods/components/operations-peek/item/component.ts b/webapp/app/pods/components/operations-peek/item/component.ts new file mode 100644 index 00000000..7dda65d1 --- /dev/null +++ b/webapp/app/pods/components/operations-peek/item/component.ts @@ -0,0 +1,39 @@ +import Component from '@glimmer/component'; +import {tracked} from '@glimmer/tracking'; +import {action} from '@ember/object'; + +interface Args { + revisionOperation: any; +} + +export default class OperationsPeekItem extends Component { + @tracked + shouldShowStats = true; + + @tracked + shouldShowOperations = false; + + @tracked + shouldHideDetails = false; + + @action + showStats() { + this.shouldShowStats = true; + this.shouldShowOperations = false; + this.shouldHideDetails = false; + } + + @action + showOperations() { + this.shouldShowStats = false; + this.shouldShowOperations = true; + this.shouldHideDetails = false; + } + + @action + hideDetails() { + this.shouldShowStats = false; + this.shouldShowOperations = false; + this.shouldHideDetails = true; + } +} diff --git a/webapp/app/pods/components/operations-peek/item/styles.scss b/webapp/app/pods/components/operations-peek/item/styles.scss index 1f667d91..550e0846 100644 --- a/webapp/app/pods/components/operations-peek/item/styles.scss +++ b/webapp/app/pods/components/operations-peek/item/styles.scss @@ -1,4 +1,6 @@ -& { +@value color-border, color-grey, color-green, color-black, color-light-background from 'accent-webapp/styles/variables/colors'; + +.operations-peek-item { margin-bottom: 15px; } @@ -15,8 +17,8 @@ .languageHeader-displayOptions-button { padding: 0 10px; background: none; - border-right: 1px solid $color-border; - color: $color-grey; + border-right: 1px solid color-border; + color: color-grey; font-size: 13px; &:focus { @@ -30,7 +32,7 @@ } .languageHeader-displayOptions-button[disabled] { - color: $color-green; + color: color-green; color: var(--color-primary); } @@ -38,7 +40,7 @@ .operationsList { margin: 10px 0; background: #fff; - box-shadow: 0 2px 10px rgba($color-black, 0.06); + box-shadow: 0 2px 10px rgba(color-black, 0.06); } .stat { @@ -69,7 +71,7 @@ justify-content: space-between; align-items: center; padding: 10px; - background: $color-light-background; + background: color-light-background; } .operation-content { @@ -78,7 +80,7 @@ .operation-action { font-size: 12px; - color: $color-grey; + color: color-grey; } .operation-key { @@ -101,5 +103,5 @@ padding: 20px 10px; font-style: italic; font-size: 12px; - color: $color-grey; + color: color-grey; } diff --git a/webapp/app/pods/components/operations-peek/item/template.hbs b/webapp/app/pods/components/operations-peek/item/template.hbs index 1ebcb283..5c9cd93b 100644 --- a/webapp/app/pods/components/operations-peek/item/template.hbs +++ b/webapp/app/pods/components/operations-peek/item/template.hbs @@ -1,97 +1,97 @@ -
    -
    - - {{revisionOperation.language.name}} +
    +
    + + {{@revisionOperation.language.name}} -
    +
    - {{#if showStats}} -
      - {{#each revisionOperation.stats as |stat|}} -
    • - + {{#if this.shouldShowStats}} +
        + {{#each @revisionOperation.stats as |stat|}} +
      • + {{stat.count}} - + {{stat.action}}
      • {{else}} -
      • +
      • {{t "components.operations_peek.item.empty_changes"}}
      • {{/each}}
      {{/if}} - {{#if showOperations}} -
        - {{#each revisionOperation.operations as |operation|}} -
      • -
        - + {{#if this.shouldShowOperations}} +
          + {{#each @revisionOperation.operations as |operation|}} +
        • +
          + {{operation.key}} - + {{operation.action}}
          -
          +
          {{#if operation.previousText}} {{#if operation.text}}
          - + {{t "components.operations_peek.item.previous_label"}} -
          {{operation.previousText}}
          +
          {{operation.previousText}}
          - + {{t "components.operations_peek.item.text_label"}} -
          {{operation.text}}
          +
          {{operation.text}}
          {{else}} -
          {{operation.previousText}}
          +
          {{operation.previousText}}
          {{/if}} {{else}} -
          {{operation.text}}
          +
          {{operation.text}}
          {{/if}}
        • {{else}} -
        • +
        • {{t "components.operations_peek.item.empty_changes"}}
        • {{/each}} diff --git a/webapp/app/pods/components/operations-peek/template.hbs b/webapp/app/pods/components/operations-peek/template.hbs index ae2f4b3f..cc565858 100644 --- a/webapp/app/pods/components/operations-peek/template.hbs +++ b/webapp/app/pods/components/operations-peek/template.hbs @@ -1,3 +1,3 @@ -{{#each revisionOperations as |revisionOperation|}} +{{#each @revisionOperations as |revisionOperation|}} {{/each}} diff --git a/webapp/app/pods/components/phoenix-channel-listener/component.js b/webapp/app/pods/components/phoenix-channel-listener/component.js deleted file mode 100644 index 313c38dc..00000000 --- a/webapp/app/pods/components/phoenix-channel-listener/component.js +++ /dev/null @@ -1,32 +0,0 @@ -import {inject as service} from '@ember/service'; -import Component from '@ember/component'; - -export default Component.extend({ - session: service(), - phoenix: service(), - - init() { - this._super(...arguments); - - if (!this.session.credentials.token || !this.project) return; - - const phoenixService = this.phoenix; - const token = `Bearer ${this.session.credentials.token}`; - - phoenixService - .getChannel(`projects:${this.project.id}`, {token}) - .then(phoenixService.joinChannel) - .then(channel => - phoenixService.bindChannelEvents( - channel, - this.session.credentials.user.id - ) - ) - .then(channel => this.set('channel', channel)); - }, - - willDestroyElement() { - this._super(...arguments); - this.phoenix.leaveChannel(this.channel); - } -}); diff --git a/webapp/app/pods/components/phoenix-channel-listener/component.ts b/webapp/app/pods/components/phoenix-channel-listener/component.ts new file mode 100644 index 00000000..5adc6f30 --- /dev/null +++ b/webapp/app/pods/components/phoenix-channel-listener/component.ts @@ -0,0 +1,46 @@ +import {inject as service} from '@ember/service'; +import Component from '@glimmer/component'; +import Session from 'accent-webapp/services/session'; +import Phoenix from 'accent-webapp/services/phoenix'; +import {Channel} from 'accent-webapp/utils/phoenix'; + +interface Args { + project: any; +} + +export default class PhoenixChannelListener extends Component { + @service('session') + session: Session; + + @service('phoenix') + phoenix: Phoenix; + + channel: Channel; + + constructor(owner: unknown, args: Args) { + super(owner, args); + + if (!this.session.credentials.token || !this.args.project) return; + + const phoenixService = this.phoenix; + const token = `Bearer ${this.session.credentials.token}`; + + // eslint-disable-next-line @typescript-eslint/no-floating-promises + phoenixService + .getChannel(`projects:${this.args.project.id}`, {token}) + .then(phoenixService.joinChannel) + .then(async (channel: Channel) => + phoenixService.bindChannelEvents( + channel, + this.session.credentials.user.id + ) + ) + .then((channel) => (this.channel = channel)); + } + + willDestroy() { + super.willDestroy(); + + this.phoenix.leaveChannel(this.channel); + } +} diff --git a/webapp/app/pods/components/project-activities-filter/component.js b/webapp/app/pods/components/project-activities-filter/component.js deleted file mode 100644 index ae9a0015..00000000 --- a/webapp/app/pods/components/project-activities-filter/component.js +++ /dev/null @@ -1,90 +0,0 @@ -import {computed} from '@ember/object'; -import {inject as service} from '@ember/service'; -import Component from '@ember/component'; - -const ACTIONS_PREFIX = 'components.project_activities_filter.actions.'; - -// Attributes: -// collaborators: Array of -// batchFilter: Boolean -// actionFilter: String -// batchFilterChange: Function -// actionFilterChange: Function -// userFilterChange: Function -export default Component.extend({ - intl: service('intl'), - - keys: [ - 'new', - 'renew', - 'remove', - 'update', - 'sync', - 'merge', - 'rollback', - 'correct_conflict', - 'uncorrect_conflict', - 'correct_all', - 'uncorrect_all', - 'conflict_on_proposed', - 'conflict_on_corrected', - 'conflict_on_slave', - 'document_delete' - ], - - mappedActions: computed('keys', function() { - const actions = this.keys.map(key => { - return { - value: key, - label: this.intl.t(`${ACTIONS_PREFIX}${key}`) - }; - }); - - actions.unshift({ - label: this.intl.t( - 'components.project_activities_filter.actions_default_option_text' - ), - value: null - }); - - return actions; - }), - - mappedUsers: computed('collaborators.[]', function() { - const users = this.collaborators - .filter(collaborator => !collaborator.isPending) - .map(({user: {fullname, id}}) => ({label: fullname, value: id})); - - users.unshift({ - label: this.intl.t( - 'components.project_activities_filter.collaborators_default_option_text' - ), - value: null - }); - - return users; - }), - - actionFilterValue: computed('actionFilter', 'mappedActions.[]', function() { - return this.mappedActions.find(({value}) => value === this.actionFilter); - }), - - userFilterValue: computed('userFilter', 'mappedUsers.[]', function() { - return this.mappedUsers.find(({value}) => value === this.userFilter); - }), - - actions: { - batchFilterChange(event) { - this.batchFilterChange(!!event.target.checked); - }, - - actionFilterChange(action) { - this.batchFilterChange(false); - this.actionFilterChange(action); - }, - - userFilterChange(user) { - this.userFilterChange(user); - } - } -}); diff --git a/webapp/app/pods/components/project-activities-filter/component.ts b/webapp/app/pods/components/project-activities-filter/component.ts new file mode 100644 index 00000000..5769cbbe --- /dev/null +++ b/webapp/app/pods/components/project-activities-filter/component.ts @@ -0,0 +1,109 @@ +import {action} from '@ember/object'; +import {inject as service} from '@ember/service'; +import Component from '@glimmer/component'; +import IntlService from 'ember-intl/services/intl'; + +const ACTIONS_PREFIX = 'components.project_activities_filter.actions.'; + +interface Args { + collaborators: any; + batchFilter: any; + actionFilter: any; + userFilter: any; + userFilterChange: (user: any) => void; + batchFilterChange: (checked: boolean) => void; + actionFilterChange: (actionFilter: any) => void; +} + +export default class ProjectActivitiesFilter extends Component { + @service('intl') + intl: IntlService; + + keys = [ + 'new', + 'renew', + 'remove', + 'update', + 'sync', + 'merge', + 'rollback', + 'correct_conflict', + 'uncorrect_conflict', + 'correct_all', + 'uncorrect_all', + 'conflict_on_proposed', + 'conflict_on_corrected', + 'conflict_on_slave', + 'document_delete', + ]; + + get mappedActions() { + const actions: Array<{value: string | null; label: string}> = this.keys.map( + (key) => { + return { + value: key, + label: this.intl.t(`${ACTIONS_PREFIX}${key}`), + }; + } + ); + + actions.unshift({ + label: this.intl.t( + 'components.project_activities_filter.actions_default_option_text' + ), + value: null, + }); + + return actions; + } + + get mappedUsers() { + if (!this.args.collaborators) return []; + + const users = this.args.collaborators + .filter((collaborator: any) => !collaborator.isPending) + .map(({user: {fullname, id}}: {user: any}) => ({ + label: fullname, + value: id, + })); + + users.unshift({ + label: this.intl.t( + 'components.project_activities_filter.collaborators_default_option_text' + ), + value: null, + }); + + return users; + } + + get actionFilterValue() { + return this.mappedActions.find( + ({value}) => value === this.args.actionFilter + ); + } + + get userFilterValue() { + return this.mappedUsers.find( + ({value}: {value: any}) => value === this.args.userFilter + ); + } + + @action + batchFilterChange(event: Event) { + const target = event.target as HTMLInputElement; + + this.args.batchFilterChange(!!target.checked); + } + + @action + actionFilterChange(actionFilter: any) { + this.args.batchFilterChange(false); + this.args.actionFilterChange(actionFilter.value); + } + + @action + userFilterChange(user: any) { + this.args.userFilterChange(user.value); + } +} diff --git a/webapp/app/pods/components/project-activities-filter/styles.scss b/webapp/app/pods/components/project-activities-filter/styles.scss index a871f7b8..79a9f8f1 100644 --- a/webapp/app/pods/components/project-activities-filter/styles.scss +++ b/webapp/app/pods/components/project-activities-filter/styles.scss @@ -1,3 +1,5 @@ +@value color-grey from 'accent-webapp/styles/variables/colors'; + .filterList { display: flex; align-items: center; @@ -12,5 +14,5 @@ } .label-text { - color: $color-grey; + color: color-grey; } diff --git a/webapp/app/pods/components/project-activities-filter/template.hbs b/webapp/app/pods/components/project-activities-filter/template.hbs index 4618fd1c..3e4745fd 100644 --- a/webapp/app/pods/components/project-activities-filter/template.hbs +++ b/webapp/app/pods/components/project-activities-filter/template.hbs @@ -1,15 +1,15 @@
          -
            - {{#unless actionFilter}} -
          • +
              + {{#unless @actionFilter}} +
            • {{/unless}} -
            • +
            • -
            • +
            diff --git a/webapp/app/pods/components/project-activities-list/component.js b/webapp/app/pods/components/project-activities-list/component.js deleted file mode 100644 index fd4e3046..00000000 --- a/webapp/app/pods/components/project-activities-list/component.js +++ /dev/null @@ -1,7 +0,0 @@ -import Component from '@ember/component'; - -// Attributes: -// project: Object -// permissions: Ember Object containing -// activities: Array of object -export default Component.extend(); diff --git a/webapp/app/pods/components/project-activities-list/component.ts b/webapp/app/pods/components/project-activities-list/component.ts new file mode 100644 index 00000000..d1e3a8fa --- /dev/null +++ b/webapp/app/pods/components/project-activities-list/component.ts @@ -0,0 +1,10 @@ +import Component from '@glimmer/component'; + +interface Args { + permissions: Record; + activities: any; + project: any; + compact: boolean; +} + +export default class ProjectActivitiesList extends Component {} diff --git a/webapp/app/pods/components/project-activities-list/template.hbs b/webapp/app/pods/components/project-activities-list/template.hbs index a1583290..d8096d9e 100644 --- a/webapp/app/pods/components/project-activities-list/template.hbs +++ b/webapp/app/pods/components/project-activities-list/template.hbs @@ -1,13 +1,13 @@ -{{#if activities}} -
              - {{#each activities key="id" as |activity|}} +{{#if @activities}} +
                + {{#each @activities key="id" as |activity|}} {{/each}}
              diff --git a/webapp/app/pods/components/project-activity/component.js b/webapp/app/pods/components/project-activity/component.js deleted file mode 100644 index 34207941..00000000 --- a/webapp/app/pods/components/project-activity/component.js +++ /dev/null @@ -1,169 +0,0 @@ -import {computed} from '@ember/object'; -import {inject as service} from '@ember/service'; -import {not, reads, equal} from '@ember/object/computed'; -import Component from '@ember/component'; -import {underscore} from '@ember/string'; - -import activityActivitiesQuery from 'accent-webapp/queries/activity-activities'; -import parsedKeyProperty from 'accent-webapp/computed-macros/parsed-key'; - -const ROLLBACKABLE_ACTIONS = [ - 'sync', - 'merge', - 'document_delete', - 'uncorrect_all', - 'correct_all', - 'update', - 'correct_conflict', - 'uncorrect_conflict', - 'conflict_on_slave', - 'conflict_on_corrected', - 'conflict_on_proposed', - 'merge_on_proposed', - 'merge_on_corrected' -]; - -// componentTranslationPrefix: String -export default Component.extend({ - intl: service('intl'), - apollo: service(), - - isRollbacking: false, - canRollback: not('project.isFileOperationsLocked'), - showStats: reads('activity.stats'), - isRollbacked: reads('activity.isRollbacked'), - isEmptyType: equal('activity.valueType', 'EMPTY'), - previousTranslationIsEmptyType: equal( - 'activity.previousTranslation.valueType', - 'EMPTY' - ), - operationsLoading: false, - - translationKey: parsedKeyProperty('activity.translation.key'), - - init() { - this._super(...arguments); - - if (this.activity.isBatch && this.activity.action !== 'rollback') { - this._fetchActivities(1); - } - }, - - localizedStats: computed('activity.stats.[]', function() { - return this.activity.stats.map(stat => { - const text = this.intl.t( - `components.project_activity.stats_text.${underscore(stat.action)}` - ); - const count = stat.count; - - return {text, count}; - }); - }), - - statsLabel: computed(function() { - return this.intl.t('components.project_activity.stats_label_text'); - }), - - actionExplanation: computed('activity.action', function() { - if (!this.activity.action) return; - - return this.intl.t( - `components.project_activity.action_explanation.${this.activity.action}` - ); - }), - - actionText: computed('activity.action', function() { - if (!this.activity.action) return; - - return this.intl.t( - `components.project_activity.action_text.${this.activity.action}` - ); - }), - - showTextDifferences: computed( - 'activity.{text,previousTranslation.text}', - function() { - return ( - this.activity.previousTranslation && - this.activity.previousTranslation.text && - this.activity.text !== this.activity.previousTranslation.text && - this.activity.text !== null - ); - } - ), - - showPreviousTranslationText: computed( - 'activity.previousTranslation.{text,valueType}', - function() { - return ( - this.activity.previousTranslation.text || - this.activity.previousTranslation.valueType === 'EMPTY' - ); - } - ), - - showLastSyncedText: computed( - 'activity.previousTranslation.{text,proposedText}', - function() { - return ( - this.activity.previousTranslation.proposedText !== - this.activity.previousTranslation.text - ); - } - ), - - isRollbackable: computed( - 'isRollbacked', - 'activity.action', - 'canRollback', - function() { - if (!this.onRollback) return false; - if (!this.canRollback) return false; - if (this.isRollbacked) return false; - - return ROLLBACKABLE_ACTIONS.indexOf(this.activity.action) !== -1; - } - ), - - actions: { - refreshActivities(page) { - this._fetchActivities(page); - }, - - rollback() { - /* eslint-disable no-alert */ - if ( - !window.confirm( - this.intl.t('components.project_activity.rollback_confirm') - ) - ) - return; - /* eslint-enable no-alert */ - - this.set('isRollbacking', true); - this.onRollback().then(() => this.set('isRollbacking', false)); - } - }, - - _fetchActivities(page) { - this.set('operationsLoading', true); - - const variables = { - projectId: this.project.id, - activityId: this.activity.id, - page - }; - - this.apollo.client - .query({ - query: activityActivitiesQuery, - variables - }) - .then(({data}) => { - const operations = data.viewer.project.activity.operations; - - this.set('operationsLoading', false); - this.set('operations', operations); - }); - } -}); diff --git a/webapp/app/pods/components/project-activity/component.ts b/webapp/app/pods/components/project-activity/component.ts new file mode 100644 index 00000000..c4ef78a6 --- /dev/null +++ b/webapp/app/pods/components/project-activity/component.ts @@ -0,0 +1,184 @@ +import {action} from '@ember/object'; +import {inject as service} from '@ember/service'; +import {not, readOnly, equal} from '@ember/object/computed'; +import Component from '@glimmer/component'; +import {underscore} from '@ember/string'; + +import activityActivitiesQuery from 'accent-webapp/queries/activity-activities'; +import parsedKeyProperty from 'accent-webapp/computed-macros/parsed-key'; +import IntlService from 'ember-intl/services/intl'; +import Apollo from 'accent-webapp/services/apollo'; +import {tracked} from '@glimmer/tracking'; + +const ROLLBACKABLE_ACTIONS = [ + 'sync', + 'merge', + 'document_delete', + 'uncorrect_all', + 'correct_all', + 'update', + 'correct_conflict', + 'uncorrect_conflict', + 'conflict_on_slave', + 'conflict_on_corrected', + 'conflict_on_proposed', + 'merge_on_proposed', + 'merge_on_corrected', +]; + +interface Args { + permissions: Record; + showTranslationLink: boolean; + componentTranslationPrefix: string; + project: any; + activity: any; + onRollback: () => Promise; +} + +export default class ProjectActivity extends Component { + @service('intl') + intl: IntlService; + + @service('apollo') + apollo: Apollo; + + @not('args.project.isFileOperationsLocked') + canRollback: boolean; + + @readOnly('args.activity.stats') + showStats: boolean; + + @readOnly('args.activity.isRollbacked') + isRollbacked: boolean; + + @equal('args.activity.valueType', 'EMPTY') + isEmptyType: boolean; + + @equal('args.activity.previousTranslation.valueType', 'EMPTY') + previousTranslationIsEmptyType: boolean; + + @tracked + isRollbacking = false; + + @tracked + operationsLoading = false; + + @tracked + operations = []; + + translationKey = parsedKeyProperty(this.args.activity.translation?.key); + + get localizedStats() { + return this.args.activity.stats.map((stat: any) => { + const text = this.intl.t( + `components.project_activity.stats_text.${underscore(stat.action)}` + ); + const count = stat.count; + + return {text, count}; + }); + } + + get statsLabel() { + return this.intl.t('components.project_activity.stats_label_text'); + } + + get actionExplanation() { + if (!this.args.activity.action) return; + + return this.intl.t( + `components.project_activity.action_explanation.${this.args.activity.action}` + ); + } + + get actionText() { + if (!this.args.activity.action) return; + + return this.intl.t( + `components.project_activity.action_text.${this.args.activity.action}` + ); + } + + get showTextDifferences() { + return ( + this.args.activity.previousTranslation && + this.args.activity.previousTranslation.text && + this.args.activity.text !== this.args.activity.previousTranslation.text && + this.args.activity.text !== null + ); + } + + get showPreviousTranslationText() { + return ( + this.args.activity.previousTranslation.text || + this.args.activity.previousTranslation.valueType === 'EMPTY' + ); + } + + get showLastSyncedText() { + return ( + this.args.activity.previousTranslation.proposedText !== + this.args.activity.previousTranslation.text + ); + } + + get isRollbackable() { + if (!this.args.onRollback) return false; + if (!this.canRollback) return false; + if (this.isRollbacked) return false; + + return ROLLBACKABLE_ACTIONS.indexOf(this.args.activity.action) !== -1; + } + + @action + async maybeFetchActivities() { + if ( + this.args.activity.isBatch && + this.args.activity.action !== 'rollback' + ) { + await this.fetchActivities(1); + } + } + + @action + async refreshActivities(page: number) { + await this.fetchActivities(page); + } + + @action + async rollback() { + const confirmMessage = this.intl.t( + 'components.project_activity.rollback_confirm' + ); + /* eslint-disable-next-line no-alert */ + if (!window.confirm(confirmMessage)) { + return; + } + + this.isRollbacking = true; + + await this.args.onRollback(); + + this.isRollbacking = false; + } + + private async fetchActivities(page: number) { + this.operationsLoading = true; + + const variables = { + projectId: this.args.project.id, + activityId: this.args.activity.id, + page, + }; + + const {data} = await this.apollo.client.query({ + query: activityActivitiesQuery, + variables, + }); + + const operations = data.viewer.project.activity.operations; + + this.operationsLoading = false; + this.operations = operations; + } +} diff --git a/webapp/app/pods/components/project-activity/styles.scss b/webapp/app/pods/components/project-activity/styles.scss index b79d3234..e9bfc8eb 100644 --- a/webapp/app/pods/components/project-activity/styles.scss +++ b/webapp/app/pods/components/project-activity/styles.scss @@ -1,3 +1,7 @@ +@value transition-speed, transition-easing from 'accent-webapp/styles/variables/transitions'; +@value color-blue, color-error, color-green, color-black, color-success from 'accent-webapp/styles/variables/colors'; +@value screen-md from 'accent-webapp/styles/variables/dimensions'; + .activity-title { font-size: 19px; color: #666; @@ -9,12 +13,13 @@ } .activity-explanation { - margin: 20px 0 0; - font-weight: 300; - font-size: 14px; - color: #555; padding: 10px 12px; - background: $color-light-background; + margin: 0 0 20px; + background: rgba(color-blue, 0.15); + box-shadow: 0 1px 20px rgba(color-blue, 0.08); + font-weight: 300; + font-size: 13px; + color: darken(color-blue, 10%); border-radius: 3px; } @@ -23,7 +28,7 @@ margin-bottom: 4px; font-size: 12px; font-weight: 500; - color: #111; + color: darken(color-blue, 20%); } .activity-date { @@ -40,18 +45,17 @@ } .rollbackButton { - font-size: 13px; - margin-left: 10px; - color: lighten($color-error, 25%); + font-size: 13px !important; + margin-left: 10px !important; + color: lighten(color-error, 25%) !important; &:focus, &:hover { - color: $color-error; + color: color-error !important; } - .label { - padding: 1px 4px; - font-weight: normal; + :global(.label) { + font-weight: normal !important; } } @@ -73,7 +77,7 @@ display: block; margin-bottom: 15px; font-size: 15px; - color: $color-green; + color: color-green; color: var(--color-primary); } @@ -81,7 +85,7 @@ max-height: 400px; overflow-y: scroll; border-radius: 3px; - box-shadow: inset 0 2px 5px rgba($color-black, 0.05); + box-shadow: inset 0 2px 5px rgba(color-black, 0.05); padding: 5px 7px; border: 1px solid #eee; } @@ -104,7 +108,7 @@ margin-right: 20px; padding: 13px; background: #fff; - box-shadow: 0 2px 10px rgba($color-black, 0.06); + box-shadow: 0 2px 10px rgba(color-black, 0.06); border-radius: 3px; } @@ -143,12 +147,12 @@ text-decoration: none; font-weight: 600; font-size: 12px; - transition: $transition-speed $transition-easing; + transition: transition-speed transition-easing; transition-property: color; &:focus, &:hover { - color: $color-green; + color: color-green; color: var(--color-primary); } } @@ -188,7 +192,7 @@ margin-left: 7px; font-size: 12px; font-style: italic; - color: $color-error; + color: color-error; } .translation-state-label { @@ -203,19 +207,19 @@ .textDiff { white-space: pre-wrap; - .added { - background: lighten($color-success, 42%); - color: darken($color-success, 10%); + :global(.added) { + background: lighten(color-success, 42%); + color: darken(color-success, 10%); } - .removed { - background: lighten($color-error, 48%); - color: $color-error; + :global(.removed) { + background: lighten(color-error, 48%); + color: color-error; text-decoration: line-through; } } -@media (max-width: ($screen-md)) { +@media (max-width: (screen-md)) { .details { flex-direction: column; } diff --git a/webapp/app/pods/components/project-activity/template.hbs b/webapp/app/pods/components/project-activity/template.hbs index 0d5330a0..663ec613 100644 --- a/webapp/app/pods/components/project-activity/template.hbs +++ b/webapp/app/pods/components/project-activity/template.hbs @@ -1,52 +1,53 @@ -
              -

              - - {{activity.user.fullname}} +
              +

              + + {{t "components.project_activity.explanation_label"}} - {{actionText}} + {{this.actionExplanation}} +

              + +

              + + {{@activity.user.fullname}} + + + {{this.actionText}}

              -
              - +
              + {{#if isRollbacked}} -
              +
              {{t "components.project_activity.rollbacked_label"}}
              - {{else if (get permissions "rollback")}} - {{#if isRollbackable}} + {{else if (get @permissions "rollback")}} + {{#if this.isRollbackable}} {{t "components.project_activity.rollback"}} {{/if}} {{/if}}
              - -

              - - {{t "components.project_activity.explanation_label"}} - - - {{actionExplanation}} -

              -
              -
              - {{#if showStats}} -
              - +
              +
              + {{#if this.showStats}} +
              + {{t "components.project_activity.stats_label"}} -
              - {{#each localizedStats as |stat|}} -
              +
              + {{#each this.localizedStats as |stat|}} +
              {{stat.text}} : @@ -58,56 +59,56 @@
              {{/if}} - {{#if activity.previousTranslation}} -
              - + {{#if @activity.previousTranslation}} +
              + {{t "components.project_activity.details_label"}} -
              - {{#if activity.translation.key}} -
              - +
              + {{#if @activity.translation.key}} +
              + {{t "components.project_activity.key_label"}} - - {{#if translationKey.prefix}} - {{translationKey.prefix}} + + {{#if this.translationKey.prefix}} + {{this.translationKey.prefix}} {{else}} - {{translation.document.path}} + {{@translation.document.path}} {{/if}} - {{translationKey.value}} + {{this.translationKey.value}}
              {{/if}} - {{#if activity.document}} -
              - + {{#if @activity.document}} +
              + {{t "components.project_activity.file_label"}} - - {{activity.document.path}} + + {{@activity.document.path}} ( - {{activity.document.format}} + {{@activity.document.format}} )
              {{/if}} -
              - +
              + {{t "components.project_activity.review_label"}} - - {{#if activity.previousTranslation.isReviewed}} + + {{#if @activity.previousTranslation.isReviewed}} {{t "components.project_activity.reviewed_yes"}} {{else}} {{t "components.project_activity.reviewed_no"}} @@ -115,52 +116,52 @@
              - {{#if showLastSyncedText}} -
              - + {{#if this.showLastSyncedText}} +
              + {{t "components.project_activity.last_synced_text_label"}} - {{#if previousTranslationIsEmptyType}} - {{t "components.project_activity.empty_value"}} + {{#if this.previousTranslationIsEmptyType}} + {{t "components.project_activity.empty_value"}} {{else}} - {{activity.previousTranslation.proposedText}} + {{@activity.previousTranslation.proposedText}} {{/if}}
              {{/if}} - {{#if showPreviousTranslationText}} -
              - + {{#if this.showPreviousTranslationText}} +
              + {{t "components.project_activity.text_before_action_label"}} - {{#if previousTranslationIsEmptyType}} - {{t "components.project_activity.empty_value"}} + {{#if this.previousTranslationIsEmptyType}} + {{t "components.project_activity.empty_value"}} {{else}} - {{activity.previousTranslation.text}} + {{@activity.previousTranslation.text}} {{/if}}
              {{/if}} -
              - +
              + {{t "components.project_activity.new_text_label"}} - {{#if isEmptyType}} - {{t "components.project_activity.empty_value"}} + {{#if this.isEmptyType}} + {{t "components.project_activity.empty_value"}} {{else}} - {{activity.text}} + {{@activity.text}} {{/if}}
              - {{#if showTextDifferences}} -
              - + {{#if this.showTextDifferences}} +
              + {{t "components.project_activity.text_differences_label"}} -
              {{string-diff activity.text activity.previousTranslation.text}}
              +
              {{string-diff @activity.text @activity.previousTranslation.text}}
              {{/if}}
              @@ -168,71 +169,71 @@ {{/if}}
              -
              - {{#if activity.rollbackedOperation}} - +
              + {{#if @activity.rollbackedOperation}} + {{t "components.project_activity.rollbacked_operation_label"}} {{/if}} - {{#if activity.rollbackOperation}} - + {{#if @activity.rollbackOperation}} + {{t "components.project_activity.rollback_operation_label"}} {{/if}} - {{#if activity.batchOperation}} - + {{#if @activity.batchOperation}} + {{t "components.project_activity.batch_operation_label"}} {{/if}} - {{#if operationsLoading}} + {{#if this.operationsLoading}} - {{else if operations.entries}} - + {{else if this.operations.entries.length}} + {{t "components.project_activity.operations_label"}} -
              - {{#each operations.entries key="id" as |activity|}} +
              + {{#each this.operations.entries key="id" as |activity|}} {{/each}}
              {{/if}}
              diff --git a/webapp/app/pods/components/project-comments-list/component.js b/webapp/app/pods/components/project-comments-list/component.js deleted file mode 100644 index 5d8093a9..00000000 --- a/webapp/app/pods/components/project-comments-list/component.js +++ /dev/null @@ -1,41 +0,0 @@ -import {computed} from '@ember/object'; -import Component from '@ember/component'; - -// Attributes: -// project: Object -// comments: Array of -export default Component.extend({ - tagName: 'ul', - - translationsById: computed('comments', function() { - return this.comments - .map(comment => comment.translation) - .reduce((memo, translation) => { - if (!memo[translation.id]) memo[translation.id] = translation; - - return memo; - }, {}); - }), - - commentsByTranslationId: computed('comments', function() { - return this.comments.reduce((memo, comment) => { - memo[comment.translation.id] = memo[comment.translation.id] || []; - memo[comment.translation.id].push(comment); - - return memo; - }, {}); - }), - - commentsByTranslation: computed( - 'commentsByTranslationId', - 'translationsById', - function() { - return Object.keys(this.commentsByTranslationId).map(translationId => { - return { - items: this.commentsByTranslationId[translationId], - value: this.translationsById[translationId] - }; - }); - } - ) -}); diff --git a/webapp/app/pods/components/project-comments-list/component.ts b/webapp/app/pods/components/project-comments-list/component.ts new file mode 100644 index 00000000..09c61bd2 --- /dev/null +++ b/webapp/app/pods/components/project-comments-list/component.ts @@ -0,0 +1,39 @@ +import Component from '@glimmer/component'; + +interface Args { + project: any; + comments: any; +} + +export default class ProjectCommentsList extends Component { + get translationsById() { + return this.args.comments + .map((comment: any) => comment.translation) + .reduce((memo: Record, translation: any) => { + if (!memo[translation.id]) memo[translation.id] = translation; + + return memo; + }, {}); + } + + get commentsByTranslationId() { + return this.args.comments.reduce( + (memo: Record, comment: any) => { + memo[comment.translation.id] = memo[comment.translation.id] || []; + memo[comment.translation.id].push(comment); + + return memo; + }, + {} + ); + } + + get commentsByTranslation() { + return Object.keys(this.commentsByTranslationId).map((translationId) => { + return { + items: this.commentsByTranslationId[translationId], + value: this.translationsById[translationId], + }; + }); + } +} diff --git a/webapp/app/pods/components/project-comments-list/item/component.js b/webapp/app/pods/components/project-comments-list/item/component.js deleted file mode 100644 index 92b04949..00000000 --- a/webapp/app/pods/components/project-comments-list/item/component.js +++ /dev/null @@ -1,11 +0,0 @@ -import Component from '@ember/component'; - -import parsedKeyProperty from 'accent-webapp/computed-macros/parsed-key'; - -// Attributes: -// groupedComment: Object -export default Component.extend({ - tagName: 'li', - - translationKey: parsedKeyProperty('groupedComment.value.key') -}); diff --git a/webapp/app/pods/components/project-comments-list/item/component.ts b/webapp/app/pods/components/project-comments-list/item/component.ts new file mode 100644 index 00000000..cb07aac1 --- /dev/null +++ b/webapp/app/pods/components/project-comments-list/item/component.ts @@ -0,0 +1,12 @@ +import Component from '@glimmer/component'; + +import parsedKeyProperty from 'accent-webapp/computed-macros/parsed-key'; + +interface Args { + groupedComment: any; + project: any; +} + +export default class ProjectCommentsListItem extends Component { + translationKey = parsedKeyProperty(this.args.groupedComment.value.key); +} diff --git a/webapp/app/pods/components/project-comments-list/item/styles.scss b/webapp/app/pods/components/project-comments-list/item/styles.scss index 4225b12d..2f48ff74 100644 --- a/webapp/app/pods/components/project-comments-list/item/styles.scss +++ b/webapp/app/pods/components/project-comments-list/item/styles.scss @@ -1,18 +1,21 @@ -& { +@value transition-speed, transition-easing from 'accent-webapp/styles/variables/transitions'; +@value color-light-background, color-green, color-black, color-error from 'accent-webapp/styles/variables/colors'; + +.project-comments-list-item { margin-bottom: 45px; } .translationCommentsList { - background: $color-light-background; + background: color-light-background; border-radius: 3px; } .item-link { - transition: $transition-speed $transition-easing; + transition: transition-speed transition-easing; transition-property: color; @extend %translationKeyBase; display: inline-block; - color: $color-green; + color: color-green; color: var(--color-primary); font-size: 12px; font-weight: bold; @@ -20,7 +23,7 @@ &:focus, &:hover { - color: darken($color-green, 15%); + color: darken(color-green, 15%); color: var(--color-primary-darken-10); } } @@ -38,18 +41,18 @@ } .item-language { - transition: $transition-speed $transition-easing; + transition: transition-speed transition-easing; transition-property: color; display: block; font-size: 12px; text-decoration: none; - color: $color-black; + color: color-black; color: var(--color-black); } .item-badge { font-size: 12px; - color: $color-green; + color: color-green; color: var(--color-primary); text-decoration: none; } @@ -58,5 +61,5 @@ display: block; margin-top: 5px; font-size: 12px; - color: $color-error; + color: color-error; } diff --git a/webapp/app/pods/components/project-comments-list/item/template.hbs b/webapp/app/pods/components/project-comments-list/item/template.hbs index 09bd6163..41c4acda 100644 --- a/webapp/app/pods/components/project-comments-list/item/template.hbs +++ b/webapp/app/pods/components/project-comments-list/item/template.hbs @@ -1,40 +1,42 @@ -
              - - {{groupedComment.value.revision.language.name}} - - - - {{#if translationKey.prefix}} - {{translationKey.prefix}} - {{else}} - {{groupedComment.value.document.path}} - {{/if}} - - {{translationKey.value}} - - {{#if groupedComment.value.removed}} -
              - {{t - "components.translation_splash_title.removed_label" - removedAt=(time-ago-in-words groupedComment.value.updatedAt) - }} -
              - {{/if}} -
              +
            • +
              + + {{@groupedComment.value.revision.language.name}} + + + + {{#if this.translationKey.prefix}} + {{this.translationKey.prefix}} + {{else}} + {{@groupedComment.value.document.path}} + {{/if}} + + {{this.translationKey.value}} + + {{#if @groupedComment.value.removed}} +
              + {{t + "components.translation_splash_title.removed_label" + removedAt=(time-ago-in-words @groupedComment.value.updatedAt) + }} +
              + {{/if}} +
              - + +
            • diff --git a/webapp/app/pods/components/project-comments-list/styles.scss b/webapp/app/pods/components/project-comments-list/styles.scss index 4ebf1154..187ce6dc 100644 --- a/webapp/app/pods/components/project-comments-list/styles.scss +++ b/webapp/app/pods/components/project-comments-list/styles.scss @@ -1,3 +1,3 @@ -& { +.project-comments-list { display: block; } diff --git a/webapp/app/pods/components/project-comments-list/template.hbs b/webapp/app/pods/components/project-comments-list/template.hbs index 192c4b28..872c01d9 100644 --- a/webapp/app/pods/components/project-comments-list/template.hbs +++ b/webapp/app/pods/components/project-comments-list/template.hbs @@ -1,11 +1,13 @@ -{{#each commentsByTranslation as |groupedComment|}} - -{{else}} - -{{/each}} +
                + {{#each this.commentsByTranslation as |groupedComment|}} + + {{else}} + + {{/each}} +
              diff --git a/webapp/app/pods/components/project-create-form/component.js b/webapp/app/pods/components/project-create-form/component.js deleted file mode 100644 index ab17d6c7..00000000 --- a/webapp/app/pods/components/project-create-form/component.js +++ /dev/null @@ -1,77 +0,0 @@ -import {computed} from '@ember/object'; -import {scheduleOnce} from '@ember/runloop'; -import {inject as service} from '@ember/service'; -import {reads, not} from '@ember/object/computed'; -import {htmlSafe} from '@ember/string'; -import Component from '@ember/component'; - -// Attributes: -// languages: Array of -// error: Boolean -// onCreate: Function -export default Component.extend({ - languageSearcher: service('language-searcher'), - - name: null, - logo: null, - mainColor: '#28cb87', - languagesCopy: reads('languages'), - emptyLanguage: not('language'), - isCreating: false, - - language: computed('mappedLanguages.[]', function() { - const first = this.mappedLanguages[0]; - - return first ? first.value : null; - }), - - languageValue: computed('language', 'mappedLanguages.[]', function() { - return this.mappedLanguages.find(({value}) => value === this.language); - }), - - mappedLanguages: computed('languagesCopy.[]', function() { - if (!this.languagesCopy) return []; - - return this._mapLanguages(this.languagesCopy); - }), - - didInsertElement() { - scheduleOnce('afterRender', this, function() { - this.element.querySelector('.textInput').focus(); - }); - }, - - actions: { - logoPicked(logo) { - this.set('logo', logo); - }, - - submit() { - this.set('isCreating', true); - const languageId = this.language; - const name = this.name; - const mainColor = this.mainColor; - const logo = this.logo; - - this.onCreate({languageId, name, mainColor, logo}).then(() => { - if (!this.isDestroyed) this.set('isCreating', false); - }); - }, - - searchLanguages(term) { - return this.languageSearcher.search({term}).then(languages => { - this.set('languagesCopy', languages); - - return this._mapLanguages(languages); - }); - } - }, - - _mapLanguages(languages) { - return languages.map(({id, name, slug}) => { - const label = htmlSafe(`${name} ${slug}`); - - return {label, value: id}; - }); - } -}); diff --git a/webapp/app/pods/components/project-create-form/component.ts b/webapp/app/pods/components/project-create-form/component.ts new file mode 100644 index 00000000..f8c22075 --- /dev/null +++ b/webapp/app/pods/components/project-create-form/component.ts @@ -0,0 +1,120 @@ +import {action} from '@ember/object'; +import {inject as service} from '@ember/service'; +import {not} from '@ember/object/computed'; +import {htmlSafe} from '@ember/string'; +import Component from '@glimmer/component'; +import LanguageSearcher from 'accent-webapp/services/language-searcher'; +import {tracked} from '@glimmer/tracking'; + +interface Args { + error: boolean; + languages: any; + onCreate: ({ + languageId, + name, + mainColor, + logo, + }: { + languageId: string; + name: string; + mainColor: string; + logo: string; + }) => Promise; +} + +export default class ProjectCreateForm extends Component { + @service('language-searcher') + languageSearcher: LanguageSearcher; + + @tracked + name: string = ''; + + @tracked + logo: string = ''; + + @tracked + mainColor = '#28cb87'; + + @tracked + languagesCopy = this.args.languages; + + @tracked + isCreating = false; + + @tracked + language = this.mappedLanguages[0]?.value; + + @not('language') + emptyLanguage: boolean; + + get languageValue() { + return this.mappedLanguages.find( + ({value}: {value: string}) => value === this.language + ); + } + + get mappedLanguages() { + if (!this.languagesCopy) return []; + + return this.mapLanguages(this.languagesCopy); + } + + @action + logoPicked(logo: string) { + this.logo = logo; + } + + @action + async submit() { + this.isCreating = true; + + const languageId = this.language; + const name = this.name; + const mainColor = this.mainColor; + const logo = this.logo; + + await this.args.onCreate({languageId, name, mainColor, logo}); + + if (!this.isDestroyed) { + this.isCreating = false; + } + } + + @action + setName(event: Event) { + const target = event.target as HTMLInputElement; + + this.name = target.value; + } + + @action + setMainColor(event: Event) { + const target = event.target as HTMLInputElement; + + this.mainColor = target.value; + } + + @action + setLanguage({value}: {value: string}) { + this.language = value; + } + + @action + async searchLanguages(term: string) { + const languages = await this.languageSearcher.search({term}); + + this.languagesCopy = languages; + + return this.mapLanguages(languages); + } + + private mapLanguages(languages: any) { + return languages.map( + ({id, name, slug}: {id: string; name: string; slug: string}) => { + const label = htmlSafe(`${name} ${slug}`); + + return {label, value: id}; + } + ); + } +} diff --git a/webapp/app/pods/components/project-create-form/styles.scss b/webapp/app/pods/components/project-create-form/styles.scss index 7e076e3a..79e96956 100644 --- a/webapp/app/pods/components/project-create-form/styles.scss +++ b/webapp/app/pods/components/project-create-form/styles.scss @@ -1,6 +1,28 @@ -& { +@value color-green, color-error, color-grey, color-light-background from 'accent-webapp/styles/variables/colors'; +@value font-primary from 'accent-webapp/styles/variables/fonts'; + +.project-create-form { padding: 20px; background: #fff; + + :global(.ember-power-select-trigger) { + min-height: 35px; + border-color: #eee; + border: 1px solid #eee; + background: color-light-background; + box-shadow: 0 1px 5px rgba(#000, 0.06); + } + + .textInput { + &:focus { + border: 2px solid rgba(color-green, 0.7); + } + } + + :global(.button).cancelButton:hover, + :global(.button).cancelButton:focus { + border-color: color-grey; + } } .title { @@ -8,7 +30,7 @@ text-align: center; font-size: 27px; font-weight: 300; - color: $color-green; + color: color-green; } .formItem-fields { @@ -23,11 +45,7 @@ padding: 10px; margin-right: 5px; font-size: 12px; - font-family: $font-primary; - - &:focus { - border: 2px solid rgba($color-green, 0.7); - } + font-family: font-primary; } .colorInput { @@ -46,7 +64,7 @@ justify-content: center; width: 48px; height: 40px; - padding: 9px 5px 3px; + padding: 6px 5px 3px; cursor: pointer; font-size: 25px; @@ -61,12 +79,12 @@ .errors { margin-bottom: 15px; padding-bottom: 5px; - border-bottom: 1px solid rgba($color-error, 0.3); + border-bottom: 1px solid rgba(color-error, 0.3); } .error { margin-bottom: 5px; - color: $color-error; + color: color-error; font-size: 13px; font-weight: bold; } @@ -96,11 +114,3 @@ padding-top: 20px; border-top: 1px solid #eee; } - -.ember-power-select-trigger { - min-height: 31px; - border-color: #eee; - border: 1px solid #eee; - background: $color-light-background; - box-shadow: 0 1px 5px rgba(#000, 0.06); -} diff --git a/webapp/app/pods/components/project-create-form/template.hbs b/webapp/app/pods/components/project-create-form/template.hbs index abc86a1a..4bd2beeb 100644 --- a/webapp/app/pods/components/project-create-form/template.hbs +++ b/webapp/app/pods/components/project-create-form/template.hbs @@ -1,69 +1,81 @@ -

              - {{t "components.project_create_form.title"}} -

              +
              +

              + {{t "components.project_create_form.title"}} +

              -{{#if error}} -
              -
              - {{t "components.project_create_form.error"}} + {{#if @error}} +
              +
              + {{t "components.project_create_form.error"}} +
              +
              + {{/if}} + +
              + + +
              + + + + + + +
              -{{/if}} -
              - +
              + -
              - - + {{#if @languages}} + + {{else}} + + {{/if}} +
              - - - +
              + + {{t "components.project_create_form.cancel_button"}} + + + {{t "components.project_create_form.save_button"}} +
              - -
              - - - {{#if languages}} - - {{else}} - - {{/if}} -
              - -
              - - {{t "components.project_create_form.cancel_button"}} - - - {{t "components.project_create_form.save_button"}} - -
              diff --git a/webapp/app/pods/components/project-file-operation/component.js b/webapp/app/pods/components/project-file-operation/component.js deleted file mode 100644 index cbfd5011..00000000 --- a/webapp/app/pods/components/project-file-operation/component.js +++ /dev/null @@ -1,3 +0,0 @@ -import Component from '@ember/component'; - -export default Component.extend(); diff --git a/webapp/app/pods/components/project-file-operation/component.ts b/webapp/app/pods/components/project-file-operation/component.ts new file mode 100644 index 00000000..4915ca7b --- /dev/null +++ b/webapp/app/pods/components/project-file-operation/component.ts @@ -0,0 +1,3 @@ +import Component from '@glimmer/component'; + +export default class ProjectFileOperation extends Component {} diff --git a/webapp/app/pods/components/project-file-operation/styles.scss b/webapp/app/pods/components/project-file-operation/styles.scss index 12060ca4..3cc2f5eb 100644 --- a/webapp/app/pods/components/project-file-operation/styles.scss +++ b/webapp/app/pods/components/project-file-operation/styles.scss @@ -1,9 +1,12 @@ -& { +@value color-error, color-green, color-light-background, color-grey, color-black from 'accent-webapp/styles/variables/colors'; +@value font-monospace from 'accent-webapp/styles/variables/fonts'; + +.project-file-operation { position: relative; background: #fff; } -.closeButton { +:global(.closeButton) { position: absolute; top: 10px; right: 10px; @@ -13,137 +16,136 @@ &:focus, &:hover { .closeButton-icon { - stroke: $color-error; + stroke: color-error; } } } -.closeButton-content { +:global(.closeButton-content) { display: flex; } -.closeButton-icon { +:global(.closeButton-icon) { width: 25px; height: 25px; stroke: #777; } -.sectionType { +:global(.sectionType) { display: flex; align-items: center; font-size: 16px; font-weight: bold; - color: $color-green; + color: color-green; color: var(--color-primary); } -.sectionType-icon { +:global(.sectionType-icon) { width: 18px; height: 18px; margin-right: 4px; - stroke: $color-green; + stroke: color-green; stroke: var(--color-primary); } -.versionTitle { +:global(.versionTitle) { display: flex; align-items: center; } -.versionTitle-name { - color: $color-green; +:global(.versionTitle-name) { + color: color-green; color: var(--color-primary); } -.versionTitle-tag { +:global(.versionTitle-tag) { display: inline-flex; align-items: center; margin-left: 10px; - font-family: $font-monospace; + font-family: font-monospace; font-size: 14px; font-weight: normal; color: #888; } -.versionTitle-tag-icon { +:global(.versionTitle-tag-icon) { width: 12px; height: 12px; stroke: #bbb; } -.title { +:global(.title) { display: flex; padding: 12px 20px 12px 12px; - background: $color-light-background; + background: color-light-background; border-bottom: 1px solid #eee; font-size: 15px; } -.title-document { +:global(.title-document) { display: flex; align-items: baseline; margin-left: 10px; font-size: 16px; } -.title-documentExtension { +:global(.title-documentExtension) { font-size: 14px; - color: $color-grey; + color: color-grey; } -.subtitle { +:global(.subtitle) { font-size: 13px; font-weight: bold; } -.subtitle-label { +:global(.subtitle-label) { font-size: 11px; font-weight: normal; color: #333; } -.render { +:global(.render) { position: relative; padding: 15px; - margin-bottom: -20px; min-height: 50px; border-top: 0; - box-shadow: inset 0 2px 6px rgba($color-black, 0.05); + box-shadow: inset 0 2px 6px rgba(color-black, 0.05); background: #fff; overflow-x: scroll; - font-family: $font-monospace; + font-family: font-monospace; font-size: 11px; line-height: 1.7; } -.renderExport { +:global(.renderExport) { position: absolute; top: 10px; right: 50px; } -.toggleJiptExport { +:global(.toggleJiptExport) { position: absolute; top: 13px; right: 140px; } -.sections { +:global(.sections) { display: flex; } -.sections-file, -.sections-preview { +:global(.sections-file), +:global(.sections-preview) { flex: 1 1 50%; padding: 20px; } -.sections-preview-title { +:global(.sections-preview-title) { font-size: 13px; - color: $color-grey; + color: color-grey; } -.sections-preview-empty { +:global(.sections-preview-empty) { padding: 30px 10px; margin: 10px 0 0; background: #fafafa; @@ -151,11 +153,11 @@ text-align: center; font-size: 13px; font-style: italic; - color: $color-grey; + color: color-grey; } @media (max-width: (800px)) { - .sections { + :global(.sections) { flex-direction: column; } } diff --git a/webapp/app/pods/components/project-file-operation/template.hbs b/webapp/app/pods/components/project-file-operation/template.hbs index 889d9eea..e51873bc 100644 --- a/webapp/app/pods/components/project-file-operation/template.hbs +++ b/webapp/app/pods/components/project-file-operation/template.hbs @@ -1 +1,3 @@ -{{yield}} +
              + {{yield}} +
              diff --git a/webapp/app/pods/components/project-logo/component.js b/webapp/app/pods/components/project-logo/component.ts similarity index 71% rename from webapp/app/pods/components/project-logo/component.js rename to webapp/app/pods/components/project-logo/component.ts index 9bfb8e2e..78144404 100644 --- a/webapp/app/pods/components/project-logo/component.js +++ b/webapp/app/pods/components/project-logo/component.ts @@ -1,5 +1,4 @@ -import Component from '@ember/component'; -import {computed} from '@ember/object'; +import Component from '@glimmer/component'; import {htmlSafe} from '@ember/string'; const DEFAULT_PROJECT_LOGO = ` @@ -10,12 +9,14 @@ const DEFAULT_PROJECT_LOGO = ` `; -export default Component.extend({ - tagName: '', +interface Args { + logo: string; +} - safeLogo: computed('logo', function() { - const logo = this.logo || DEFAULT_PROJECT_LOGO; +export default class ProjectLogo extends Component { + get safeLogo() { + const logo = this.args.logo || DEFAULT_PROJECT_LOGO; return htmlSafe(logo); - }) -}); + } +} diff --git a/webapp/app/pods/components/project-navigation/component.js b/webapp/app/pods/components/project-navigation/component.js deleted file mode 100644 index 1c61ab8a..00000000 --- a/webapp/app/pods/components/project-navigation/component.js +++ /dev/null @@ -1,28 +0,0 @@ -import {computed} from '@ember/object'; -import {inject as service} from '@ember/service'; -import {reads} from '@ember/object/computed'; -import Component from '@ember/component'; - -// Attributes: -// project: Object -// permissions: Ember Object containing -export default Component.extend({ - globalState: service('global-state'), - - isListShowing: reads('globalState.isProjectNavigationListShowing'), - - selectedRevision: computed( - 'globalState.revision', - 'revisions.[]', - function() { - const selected = this.globalState.revision; - - if (selected && this.revisions.map(({id}) => id).includes(selected)) { - return selected; - } - - if (!this.revisions) return; - return this.revisions[0].id; - } - ) -}); diff --git a/webapp/app/pods/components/project-navigation/component.ts b/webapp/app/pods/components/project-navigation/component.ts new file mode 100644 index 00000000..389e9ec7 --- /dev/null +++ b/webapp/app/pods/components/project-navigation/component.ts @@ -0,0 +1,33 @@ +import {inject as service} from '@ember/service'; +import {readOnly} from '@ember/object/computed'; +import Component from '@glimmer/component'; +import GlobalState from 'accent-webapp/services/global-state'; + +interface Args { + project: any; + permissions: Record; + revisions: any; +} + +export default class ProjectNavigation extends Component { + @service('global-state') + globalState: GlobalState; + + @readOnly('globalState.isProjectNavigationListShowing') + isListShowing: boolean; + + get selectedRevision() { + const selected = this.globalState.revision; + + if ( + selected && + this.args.revisions.map(({id}: {id: string}) => id).includes(selected) + ) { + return selected; + } + + if (!this.args.revisions) return; + + return this.args.revisions[0].id; + } +} diff --git a/webapp/app/pods/components/project-navigation/list/component.js b/webapp/app/pods/components/project-navigation/list/component.js deleted file mode 100644 index cbf1b170..00000000 --- a/webapp/app/pods/components/project-navigation/list/component.js +++ /dev/null @@ -1,5 +0,0 @@ -import Component from '@ember/component'; - -export default Component.extend({ - tagName: 'ul' -}); diff --git a/webapp/app/pods/components/project-navigation/list/component.ts b/webapp/app/pods/components/project-navigation/list/component.ts new file mode 100644 index 00000000..366a90ad --- /dev/null +++ b/webapp/app/pods/components/project-navigation/list/component.ts @@ -0,0 +1,9 @@ +import Component from '@glimmer/component'; + +interface Args { + selectedRevision: any; + permissions: Record; + project: any; +} + +export default class ProjectNavigationList extends Component {} diff --git a/webapp/app/pods/components/project-navigation/list/styles.scss b/webapp/app/pods/components/project-navigation/list/styles.scss index 66b92901..a6d7e31a 100644 --- a/webapp/app/pods/components/project-navigation/list/styles.scss +++ b/webapp/app/pods/components/project-navigation/list/styles.scss @@ -1,4 +1,8 @@ -& { +@value transition-speed, transition-easing from 'accent-webapp/styles/variables/transitions'; +@value color-grey, color-light-background, color-green from 'accent-webapp/styles/variables/colors'; +@value screen-sm from 'accent-webapp/styles/variables/dimensions'; + +.project-navigation-list { display: flex; flex-direction: column; padding: 10px; @@ -18,7 +22,7 @@ align-items: center; position: relative; left: 1px; - transition: $transition-speed $transition-easing; + transition: transition-speed transition-easing; transition-property: color, background; padding: 8px 12px; margin-bottom: 10px; @@ -26,11 +30,11 @@ font-weight: 600; font-size: 13px; border-radius: 3px; - color: $color-grey; + color: color-grey; &:hover, &:focus { - background: $color-light-background; + background: color-light-background; color: var(--color-primary); .list-item-link-icon { @@ -42,8 +46,8 @@ } } - &.active { - background: lighten($color-green, 46%); + &:global(.active) { + background: lighten(color-green, 46%); background: var(--color-primary); color: #fff; @@ -60,13 +64,13 @@ .list-item-link-text { width: 127px; padding: 0 0 0 12px; - color: $color-grey; - transition: $transition-speed $transition-easing; + color: color-grey; + transition: transition-speed transition-easing; transition-property: color; } .list-item-link-icon { - transition: $transition-speed $transition-easing; + transition: transition-speed transition-easing; transition-property: fill; display: inline-block; width: 19px; @@ -79,8 +83,8 @@ } } -@media (max-width: ($screen-sm)) { - & { +@media (max-width: (screen-sm)) { + .project-navigation-list { flex-direction: row; justify-content: space-between; margin-left: 0; diff --git a/webapp/app/pods/components/project-navigation/list/template.hbs b/webapp/app/pods/components/project-navigation/list/template.hbs index 8e9497aa..867a8d8b 100644 --- a/webapp/app/pods/components/project-navigation/list/template.hbs +++ b/webapp/app/pods/components/project-navigation/list/template.hbs @@ -1,115 +1,117 @@ -
            • - - {{inline-svg "/assets/home.svg" class="list-item-link-icon"}} - - {{t "components.project_navigation.dashboard_link_title"}} - - -
            • -{{#if (get permissions "index_translations")}} -
            • +
                +
              • - {{inline-svg "/assets/search.svg" class="list-item-link-icon"}} - - {{t "components.project_navigation.translations_link_title"}} + {{inline-svg "/assets/home.svg" local-class="list-item-link-icon"}} + + {{t "components.project_navigation.dashboard_link_title"}}
              • -{{/if}} + {{#if (get @permissions "index_translations")}} +
              • + + {{inline-svg "/assets/search.svg" local-class="list-item-link-icon"}} + + {{t "components.project_navigation.translations_link_title"}} + + +
              • + {{/if}} -{{#if (get permissions "index_translations")}} -
              • + {{#if (get @permissions "index_translations")}} +
              • + + {{inline-svg "/assets/check.svg" local-class="list-item-link-icon"}} + + {{t "components.project_navigation.conflicts_link_title"}} + + +
              • + {{/if}} + + {{#if (get @permissions "index_comments")}} +
              • + + {{inline-svg "/assets/bubble.svg" local-class="list-item-link-icon"}} + + {{t "components.project_navigation.conversation_link_title"}} + + +
              • + {{/if}} + + {{#if (get @permissions "index_project_activities")}} +
              • + + {{inline-svg "/assets/activity.svg" local-class="list-item-link-icon"}} + + + {{t "components.project_navigation.activities_link_title"}} + + +
              • + {{/if}} + + {{#if (get @permissions "index_documents")}} +
              • + + {{inline-svg "/assets/file.svg" local-class="list-item-link-icon"}} + + {{t "components.project_navigation.sync_link_title"}} + + +
              • + {{/if}} + + {{#if (get @permissions "index_versions")}} +
              • + + {{inline-svg "/assets/tag.svg" local-class="list-item-link-icon"}} + + {{t "components.project_navigation.versions_link_title"}} + + +
              • + {{/if}} + +
              • - {{inline-svg "/assets/check.svg" class="list-item-link-icon"}} - - {{t "components.project_navigation.conflicts_link_title"}} + {{inline-svg "/assets/gear.svg" local-class="list-item-link-icon"}} + + {{t "components.project_navigation.settings_link_title"}}
              • -{{/if}} - -{{#if (get permissions "index_comments")}} -
              • - - {{inline-svg "/assets/bubble.svg" class="list-item-link-icon"}} - - {{t "components.project_navigation.conversation_link_title"}} - - -
              • -{{/if}} - -{{#if (get permissions "index_project_activities")}} -
              • - - {{inline-svg "/assets/activity.svg" class="list-item-link-icon"}} - - - {{t "components.project_navigation.activities_link_title"}} - - -
              • -{{/if}} - -{{#if (get permissions "index_documents")}} -
              • - - {{inline-svg "/assets/file.svg" class="list-item-link-icon"}} - - {{t "components.project_navigation.sync_link_title"}} - - -
              • -{{/if}} - -{{#if (get permissions "index_versions")}} -
              • - - {{inline-svg "/assets/tag.svg" class="list-item-link-icon"}} - - {{t "components.project_navigation.versions_link_title"}} - - -
              • -{{/if}} - -
              • - - {{inline-svg "/assets/gear.svg" class="list-item-link-icon"}} - - {{t "components.project_navigation.settings_link_title"}} - - -
              • +
              diff --git a/webapp/app/pods/components/project-navigation/styles.scss b/webapp/app/pods/components/project-navigation/styles.scss index 6f96ad40..25531c5f 100644 --- a/webapp/app/pods/components/project-navigation/styles.scss +++ b/webapp/app/pods/components/project-navigation/styles.scss @@ -1,41 +1,8 @@ -& { +@value color-black from 'accent-webapp/styles/variables/colors'; + +.project-navigation { position: relative; display: flex; flex-direction: column; width: 100%; } - -.nameLink { - display: block; - margin: 0 0 20px; - padding: 14px 0 13px 28px; - font-size: 12px; - font-weight: 700; - text-decoration: none; - color: $color-black; - border-bottom: 1px solid #eee; -} - -.listTrigger { - display: none; - align-items: center; - width: 90px; - margin: 0 0 20px 10px; - padding: 2px 10px; - color: #aaa; - border: 1px solid #eee; - border-radius: 2px; - cursor: pointer; - font-size: 14px; -} - -.listTrigger-icon { - width: 20px; - height: 20px; - margin-right: 10px; - fill: #aaa; -} - -.modalList { - display: none; -} diff --git a/webapp/app/pods/components/project-navigation/template.hbs b/webapp/app/pods/components/project-navigation/template.hbs index dfba8b8f..c4aa7753 100644 --- a/webapp/app/pods/components/project-navigation/template.hbs +++ b/webapp/app/pods/components/project-navigation/template.hbs @@ -1,5 +1,7 @@ - +
              + +
              diff --git a/webapp/app/pods/components/project-settings/api-token/component.js b/webapp/app/pods/components/project-settings/api-token/component.js deleted file mode 100644 index cbfd5011..00000000 --- a/webapp/app/pods/components/project-settings/api-token/component.js +++ /dev/null @@ -1,3 +0,0 @@ -import Component from '@ember/component'; - -export default Component.extend(); diff --git a/webapp/app/pods/components/project-settings/api-token/component.ts b/webapp/app/pods/components/project-settings/api-token/component.ts new file mode 100644 index 00000000..99ea9ab7 --- /dev/null +++ b/webapp/app/pods/components/project-settings/api-token/component.ts @@ -0,0 +1,7 @@ +import Component from '@glimmer/component'; + +interface Args { + token: string; +} + +export default class APIToken extends Component {} diff --git a/webapp/app/pods/components/project-settings/api-token/styles.scss b/webapp/app/pods/components/project-settings/api-token/styles.scss index f09ee9a1..65bd6ee5 100644 --- a/webapp/app/pods/components/project-settings/api-token/styles.scss +++ b/webapp/app/pods/components/project-settings/api-token/styles.scss @@ -1,4 +1,7 @@ -& { +@value color-green from 'accent-webapp/styles/variables/colors'; +@value font-monospace from 'accent-webapp/styles/variables/fonts'; + +.project-settings-api-token { margin-top: 30px; } @@ -17,7 +20,7 @@ overflow-x: scroll; word-break: keep-all; background: #fbfbfb; - font-family: $font-monospace; + font-family: font-monospace; font-size: 11px; border: 2px solid #ddd; border-radius: 3px; @@ -26,18 +29,18 @@ &:focus { outline: none; - border-color: lighten($color-green, 20%); + border-color: lighten(color-green, 20%); border-color: var(--color-primary-opacity-70); - box-shadow: 0 0 3px 2px rgba($color-green, 0.3); + box-shadow: 0 0 3px 2px rgba(color-green, 0.3); box-shadow: 0 0 3px 2px var(--color-primary-opacity-10); &::-moz-selection { - background: lighten($color-green, 45%); + background: lighten(color-green, 45%); background: var(--color-primary-opacity-10); } &::selection { - background: lighten($color-green, 45%); + background: lighten(color-green, 45%); background: var(--color-primary-opacity-10); } } diff --git a/webapp/app/pods/components/project-settings/api-token/template.hbs b/webapp/app/pods/components/project-settings/api-token/template.hbs index 6e13c7bd..08772c86 100644 --- a/webapp/app/pods/components/project-settings/api-token/template.hbs +++ b/webapp/app/pods/components/project-settings/api-token/template.hbs @@ -1,10 +1,12 @@ - +
              + -

              - {{t "components.project_settings.api_token.text_1"}} - {{t "components.project_settings.api_token.text_2"}} -

              +

              + {{t "components.project_settings.api_token.text_1"}} + {{t "components.project_settings.api_token.text_2"}} +

              - + +
              diff --git a/webapp/app/pods/components/project-settings/back-link/styles.scss b/webapp/app/pods/components/project-settings/back-link/styles.scss index 86146d8c..deb8ce77 100644 --- a/webapp/app/pods/components/project-settings/back-link/styles.scss +++ b/webapp/app/pods/components/project-settings/back-link/styles.scss @@ -1,3 +1,3 @@ -& { +.project-settings-back-link { margin-top: 20px; } diff --git a/webapp/app/pods/components/project-settings/back-link/template.hbs b/webapp/app/pods/components/project-settings/back-link/template.hbs index c3144ee4..0bc31cb9 100644 --- a/webapp/app/pods/components/project-settings/back-link/template.hbs +++ b/webapp/app/pods/components/project-settings/back-link/template.hbs @@ -1,6 +1,8 @@ - - {{t "components.project_settings.back_link.title"}} - +
              + + {{t "components.project_settings.back_link.title"}} + +
              diff --git a/webapp/app/pods/components/project-settings/badges/component.js b/webapp/app/pods/components/project-settings/badges/component.js deleted file mode 100644 index 54cf278b..00000000 --- a/webapp/app/pods/components/project-settings/badges/component.js +++ /dev/null @@ -1,39 +0,0 @@ -import fmt from 'simple-fmt'; -import Component from '@ember/component'; -import {computed} from '@ember/object'; -import {htmlSafe} from '@ember/string'; -import config from 'accent-webapp/config/environment'; - -const {API} = config; - -export default Component.extend({ - projectUrl: computed('project.id', function() { - return fmt(API.PROJECT_PATH, this.project.id); - }), - - percentageReviewedBadgeCode: computed( - 'percentageReviewedBadgeUrl', - 'projectUrl', - function() { - // eslint-disable-next-line no-irregular-whitespace - return htmlSafe( - `![strings reviewed status](${this.percentageReviewedBadgeUrl})](${ - this.projectUrl - })` - ); - } - ), - - percentageReviewedBadgeUrlWithDigest: computed( - 'percentageReviewedBadgeUrl', - function() { - return `${ - this.percentageReviewedBadgeUrl - }?digest=${new Date().getTime()}`; - } - ), - - percentageReviewedBadgeUrl: computed('project.id', function() { - return fmt(API.PERCENTAGE_REVIEWED_BADGE_SVG_PROJECT_PATH, this.project.id); - }) -}); diff --git a/webapp/app/pods/components/project-settings/badges/component.ts b/webapp/app/pods/components/project-settings/badges/component.ts new file mode 100644 index 00000000..3f82a5d3 --- /dev/null +++ b/webapp/app/pods/components/project-settings/badges/component.ts @@ -0,0 +1,34 @@ +import fmt from 'simple-fmt'; +import Component from '@glimmer/component'; +import {htmlSafe} from '@ember/string'; +import config from 'accent-webapp/config/environment'; + +const {API} = config; + +interface Args { + project: any; +} + +export default class Badges extends Component { + get projectUrl() { + return fmt(API.PROJECT_PATH, this.args.project.id); + } + + get percentageReviewedBadgeCode() { + // eslint-disable-next-line no-irregular-whitespace + return htmlSafe( + `![strings reviewed status](${this.percentageReviewedBadgeUrl})](${this.projectUrl})` + ); + } + + get percentageReviewedBadgeUrlWithDigest() { + return `${this.percentageReviewedBadgeUrl}?digest=${new Date().getTime()}`; + } + + get percentageReviewedBadgeUrl() { + return fmt( + API.PERCENTAGE_REVIEWED_BADGE_SVG_PROJECT_PATH, + this.args.project.id + ); + } +} diff --git a/webapp/app/pods/components/project-settings/badges/styles.scss b/webapp/app/pods/components/project-settings/badges/styles.scss index 628ab414..4fbe17c2 100644 --- a/webapp/app/pods/components/project-settings/badges/styles.scss +++ b/webapp/app/pods/components/project-settings/badges/styles.scss @@ -1,4 +1,7 @@ -& { +@value color-green from 'accent-webapp/styles/variables/colors'; +@value font-monospace from 'accent-webapp/styles/variables/fonts'; + +.project-settings-badges { margin-top: 30px; } @@ -29,7 +32,7 @@ overflow-x: scroll; word-break: keep-all; background: #fbfbfb; - font-family: $font-monospace; + font-family: font-monospace; font-size: 11px; border: 2px solid #ddd; border-radius: 3px; @@ -38,18 +41,18 @@ &:focus { outline: none; - border-color: lighten($color-green, 20%); + border-color: lighten(color-green, 20%); border-color: var(--color-primary-opacity-70); - box-shadow: 0 0 3px 2px rgba($color-green, 0.3); + box-shadow: 0 0 3px 2px rgba(color-green, 0.3); box-shadow: 0 0 3px 2px var(--color-primary-opacity-10); &::-moz-selection { - background: lighten($color-green, 45%); + background: lighten(color-green, 45%); background: var(--color-primary-opacity-10); } &::selection { - background: lighten($color-green, 45%); + background: lighten(color-green, 45%); background: var(--color-primary-opacity-10); } } diff --git a/webapp/app/pods/components/project-settings/badges/template.hbs b/webapp/app/pods/components/project-settings/badges/template.hbs index e51d92da..33c2d347 100644 --- a/webapp/app/pods/components/project-settings/badges/template.hbs +++ b/webapp/app/pods/components/project-settings/badges/template.hbs @@ -1,21 +1,24 @@ - +
              + -

              - {{t "components.project_settings.badges.text"}} -

              +

              + {{t "components.project_settings.badges.text"}} +

              -
              - - {{t "components.project_settings.badges.percentage_reviewed"}} - - +
              + + {{t "components.project_settings.badges.percentage_reviewed"}} + + + +
              + +
              - - diff --git a/webapp/app/pods/components/project-settings/collaborators/component.js b/webapp/app/pods/components/project-settings/collaborators/component.js deleted file mode 100644 index 3a511957..00000000 --- a/webapp/app/pods/components/project-settings/collaborators/component.js +++ /dev/null @@ -1,18 +0,0 @@ -import Component from '@ember/component'; - -// Attributes -// project: Object -// permissions: Ember Object containing -// collaborators: Array of -// onDeleteCollaborator: Function -// onUpdateCollaborator: Function -// onCreateCollaborator: Function -export default Component.extend({ - showCreateForm: false, - - actions: { - toggleCreateForm() { - this.set('showCreateForm', !this.showCreateForm); - } - } -}); diff --git a/webapp/app/pods/components/project-settings/collaborators/component.ts b/webapp/app/pods/components/project-settings/collaborators/component.ts new file mode 100644 index 00000000..fa126ed0 --- /dev/null +++ b/webapp/app/pods/components/project-settings/collaborators/component.ts @@ -0,0 +1,22 @@ +import Component from '@glimmer/component'; +import {action} from '@ember/object'; +import {tracked} from '@glimmer/tracking'; + +interface Args { + project: any; + permissions: Record; + collaborators: any; + onCreateCollaborator: () => void; + onUpdateCollaborator: () => void; + onDeleteCollaborator: () => void; +} + +export default class Collaborators extends Component { + @tracked + showCreateForm = false; + + @action + toggleCreateForm() { + this.showCreateForm = !this.showCreateForm; + } +} diff --git a/webapp/app/pods/components/project-settings/collaborators/create-form/component.js b/webapp/app/pods/components/project-settings/collaborators/create-form/component.js deleted file mode 100644 index 0f004b08..00000000 --- a/webapp/app/pods/components/project-settings/collaborators/create-form/component.js +++ /dev/null @@ -1,46 +0,0 @@ -import {inject as service} from '@ember/service'; -import {computed} from '@ember/object'; -import {not, map} from '@ember/object/computed'; -import Component from '@ember/component'; - -// Attributes: -// project: Object -// onCreate: Function -export default Component.extend({ - intl: service('intl'), - globalState: service('global-state'), - - isCreating: false, - email: '', - emptyEmail: not('email'), - - possibleRoles: map('globalState.roles', ({slug}) => slug), - mappedPossibleRoles: computed('possibleRoles.[].value', function() { - return this.possibleRoles.map(value => ({ - label: this.intl.t(`general.roles.${value}`), - value - })); - }), - - roleValue: computed('role', 'mappedPossibleRoles.[]', function() { - return this.mappedPossibleRoles.find(({value}) => value === this.role); - }), - - role: computed('possibleRoles.[]', function() { - return this.possibleRoles[0]; - }), - - actions: { - selectRole(value) { - this.set('role', value); - }, - - submit() { - this.set('isCreating', true); - - this.onCreate(this.getProperties('email', 'role')) - .then(() => this.setProperties({email: ''})) - .then(() => this.set('isCreating', false)); - } - } -}); diff --git a/webapp/app/pods/components/project-settings/collaborators/create-form/component.ts b/webapp/app/pods/components/project-settings/collaborators/create-form/component.ts new file mode 100644 index 00000000..6e3f4938 --- /dev/null +++ b/webapp/app/pods/components/project-settings/collaborators/create-form/component.ts @@ -0,0 +1,67 @@ +import {inject as service} from '@ember/service'; +import {action} from '@ember/object'; +import {not} from '@ember/object/computed'; +import Component from '@glimmer/component'; +import IntlService from 'ember-intl/services/intl'; +import GlobalState from 'accent-webapp/services/global-state'; +import {tracked} from '@glimmer/tracking'; + +interface Args { + project: any; + onCancel: () => void; + onCreate: ({email, role}: {email: string; role: string}) => Promise; +} + +export default class CreateForm extends Component { + @service('intl') + intl: IntlService; + + @service('global-state') + globalState: GlobalState; + + @tracked + isCreating = false; + + @tracked + email = ''; + + @tracked + role = this.possibleRoles[0]; + + @not('email') + emptyEmail: boolean; + + get possibleRoles() { + return this.globalState.roles.map(({slug}: {slug: string}) => slug); + } + + get mappedPossibleRoles() { + return this.possibleRoles.map((value) => ({ + label: this.intl.t(`general.roles.${value}`), + value, + })); + } + + get roleValue() { + return this.mappedPossibleRoles.find(({value}) => value === this.role); + } + + @action + setRole({value}: {value: string}) { + this.role = value; + } + + @action + async submit() { + this.isCreating = true; + + await this.args.onCreate({email: this.email, role: this.role}); + this.email = ''; + this.isCreating = false; + } + + @action + focusTextarea(element: HTMLElement) { + element.querySelector('input')?.focus(); + } +} diff --git a/webapp/app/pods/components/project-settings/collaborators/create-form/styles.scss b/webapp/app/pods/components/project-settings/collaborators/create-form/styles.scss index 8c477580..61733b3b 100644 --- a/webapp/app/pods/components/project-settings/collaborators/create-form/styles.scss +++ b/webapp/app/pods/components/project-settings/collaborators/create-form/styles.scss @@ -1,5 +1,20 @@ -& { +@value font-primary from 'accent-webapp/styles/variables/fonts'; + +.project-settings-collaborators-create-form { display: flex; + + :global(.ember-power-select-trigger) { + min-width: 150px; + margin-right: 10px; + border: 1px solid #eee; + background: #fff; + font-size: 12px; + box-shadow: 0 1px 5px rgba(#000, 0.06); + } + + :global(.button) { + margin-right: 5px; + } } .textInput { @@ -9,19 +24,6 @@ padding: 8px 10px; margin-right: 10px; min-width: 350px; - font-family: $font-primary; + font-family: font-primary; font-size: 11px; } - -.ember-power-select-trigger { - min-width: 150px; - margin-right: 10px; - border: 1px solid #eee; - background: #fff; - font-size: 12px; - box-shadow: 0 1px 5px rgba(#000, 0.06); -} - -.button { - margin-right: 5px; -} diff --git a/webapp/app/pods/components/project-settings/collaborators/create-form/template.hbs b/webapp/app/pods/components/project-settings/collaborators/create-form/template.hbs index 3060c05f..65fba8e7 100644 --- a/webapp/app/pods/components/project-settings/collaborators/create-form/template.hbs +++ b/webapp/app/pods/components/project-settings/collaborators/create-form/template.hbs @@ -1,28 +1,30 @@ - +
              + - + - - {{t "components.collaborator_create_form.create_button"}} - + + {{t "components.collaborator_create_form.create_button"}} + -{{#if onCancel}} - -{{/if}} + {{#if @onCancel}} + + {{/if}} +
              diff --git a/webapp/app/pods/components/project-settings/collaborators/list/component.js b/webapp/app/pods/components/project-settings/collaborators/list/component.js deleted file mode 100644 index 898dcf6f..00000000 --- a/webapp/app/pods/components/project-settings/collaborators/list/component.js +++ /dev/null @@ -1,27 +0,0 @@ -import {computed} from '@ember/object'; -import Component from '@ember/component'; - -// Attributes: -// collaborators: Array of -// permissions: Ember Object containing -// onDelete: Function -// onUpdate: Function -export default Component.extend({ - tagName: 'ul', - - filteredCollaborators: computed('collaborators.[]', function() { - return this.collaborators.filter( - collaborator => collaborator.isPending || !collaborator.user.isBot - ); - }), - - actions: { - deleteCollaborator(collaborator) { - return this.onDelete(collaborator); - }, - - updateCollaborator(collaborator, args) { - return this.onUpdate(collaborator, args); - } - } -}); diff --git a/webapp/app/pods/components/project-settings/collaborators/list/component.ts b/webapp/app/pods/components/project-settings/collaborators/list/component.ts new file mode 100644 index 00000000..fffcc0df --- /dev/null +++ b/webapp/app/pods/components/project-settings/collaborators/list/component.ts @@ -0,0 +1,26 @@ +import {action} from '@ember/object'; +import Component from '@glimmer/component'; + +interface Args { + permissions: Record; + collaborators: any; + onDelete: (collaborator: any) => void; + onUpdate: (collaborator: any, args: any) => void; +} + +export default class CollaboratorsList extends Component { + get filteredCollaborators() { + return this.args.collaborators.filter((collaborator: any) => { + return collaborator.isPending || !collaborator.user.isBot; + }); + } + + @action + deleteCollaborator(collaborator: any) { + return this.args.onDelete(collaborator); + } + + updateCollaborator(collaborator: any, args: any) { + return this.args.onUpdate(collaborator, args); + } +} diff --git a/webapp/app/pods/components/project-settings/collaborators/list/item/component.js b/webapp/app/pods/components/project-settings/collaborators/list/item/component.js deleted file mode 100644 index 0c68d901..00000000 --- a/webapp/app/pods/components/project-settings/collaborators/list/item/component.js +++ /dev/null @@ -1,94 +0,0 @@ -import {computed} from '@ember/object'; -import {notEmpty, map, reads} from '@ember/object/computed'; -import {inject as service} from '@ember/service'; -import Component from '@ember/component'; - -// Attributes: -// collaborator: Object -// permissions: Ember Object containing -// onDelete: Function -// onUpdate: Function -export default Component.extend({ - tagName: 'li', - classNameBindings: [ - 'isEditing:editing', - 'hasJoined:joined:invited', - 'collaborator.user.pictureUrl:withPicture' - ], - - session: service('session'), - intl: service('intl'), - globalState: service('global-state'), - - isEditing: false, - - hasJoined: notEmpty('collaborator.user.id'), - - possibleRoles: map('globalState.roles', ({slug}) => slug), - mappedPossibleRoles: computed('possibleRoles', function() { - return this.possibleRoles.map(value => ({ - label: this.intl.t(`general.roles.${value}`), - value - })); - }), - - updatedRole: reads('collaborator.role'), - - roleValue: computed('updatedRole', 'mappedPossibleRoles.[]', function() { - return this.mappedPossibleRoles.find( - ({value}) => value === this.updatedRole - ); - }), - - canDeleteCollaborator: computed( - 'permissions', - 'session.credentials.user.id', - 'collaborator.user.id', - function() { - return ( - this.permissions && - this.permissions.create_collaborator && - (!this.collaborator.user || - (this.collaborator.user && - this.session.credentials.user.id !== this.collaborator.user.id)) - ); - } - ), - - canUpdateCollaborator: computed( - 'permissions', - 'session.credentials.user.id', - 'collaborator.user.id', - function() { - return ( - this.permissions && - this.permissions.update_collaborator && - this.collaborator.user && - this.session.credentials.user.id !== this.collaborator.user.id - ); - } - ), - - role: computed('collaborator.role', function() { - return this.intl.t(`general.roles.${this.collaborator.role}`); - }), - - actions: { - deleteCollaborator() { - this.onDelete(this.collaborator); - }, - - updateCollaborator() { - this.onUpdate(this.collaborator, {role: this.updatedRole}).then(() => - this.set('isEditing', false) - ); - }, - - toggleUpdateCollaborator() { - this.setProperties({ - updatedRole: this.collaborator.role, - isEditing: !this.isEditing - }); - } - } -}); diff --git a/webapp/app/pods/components/project-settings/collaborators/list/item/component.ts b/webapp/app/pods/components/project-settings/collaborators/list/item/component.ts new file mode 100644 index 00000000..2d07fed8 --- /dev/null +++ b/webapp/app/pods/components/project-settings/collaborators/list/item/component.ts @@ -0,0 +1,98 @@ +import {action} from '@ember/object'; +import {notEmpty} from '@ember/object/computed'; +import {inject as service} from '@ember/service'; +import Component from '@glimmer/component'; +import Session from 'accent-webapp/services/session'; +import IntlService from 'ember-intl/services/intl'; +import {tracked} from '@glimmer/tracking'; +import GlobalState from 'accent-webapp/services/global-state'; + +interface Args { + permissions: Record; + collaborator: any; + onDelete: (collaborator: any) => void; + onUpdate: (collaborator: any, args: any) => Promise; +} + +export default class CollaboratorsListItem extends Component { + @service('session') + session: Session; + + @service('intl') + intl: IntlService; + + @service('global-state') + globalState: GlobalState; + + @tracked + isEditing = false; + + @tracked + updatedRole = this.args.collaborator.role; + + @notEmpty('args.collaborator.user.id') + hasJoined: boolean; + + get possibleRoles() { + return this.globalState.roles.map(({slug}: {slug: string}) => slug); + } + + get mappedPossibleRoles() { + return this.possibleRoles.map((value) => ({ + label: this.intl.t(`general.roles.${value}`), + value, + })); + } + + get roleValue() { + return this.mappedPossibleRoles.find(({value}) => { + return value === this.updatedRole; + }); + } + + get canDeleteCollaborator() { + return ( + this.args.permissions && + this.args.permissions.create_collaborator && + (!this.args.collaborator.user || + (this.args.collaborator.user && + this.session.credentials.user.id !== this.args.collaborator.user.id)) + ); + } + + get canUpdateCollaborator() { + return ( + this.args.permissions && + this.args.permissions.update_collaborator && + this.args.collaborator.user && + this.session.credentials.user.id !== this.args.collaborator.user.id + ); + } + + get role() { + return this.intl.t(`general.roles.${this.args.collaborator.role}`); + } + + @action + setRole({value}: {value: string}) { + this.updatedRole = value; + } + + @action + deleteCollaborator() { + this.args.onDelete(this.args.collaborator); + } + + @action + async updateCollaborator() { + await this.args.onUpdate(this.args.collaborator, {role: this.updatedRole}); + + this.isEditing = false; + } + + @action + toggleUpdateCollaborator() { + this.updatedRole = this.args.collaborator.role; + this.isEditing = !this.isEditing; + } +} diff --git a/webapp/app/pods/components/project-settings/collaborators/list/item/styles.scss b/webapp/app/pods/components/project-settings/collaborators/list/item/styles.scss index b7258855..77b5196d 100644 --- a/webapp/app/pods/components/project-settings/collaborators/list/item/styles.scss +++ b/webapp/app/pods/components/project-settings/collaborators/list/item/styles.scss @@ -1,5 +1,8 @@ -& { - transition: $transition-speed $transition-easing; +@value transition-speed, transition-easing from 'accent-webapp/styles/variables/transitions'; +@value color-grey, color-light-background, color-green, color-black from 'accent-webapp/styles/variables/colors'; + +.item { + transition: transition-speed transition-easing; transition-property: background; display: flex; justify-content: space-between; @@ -11,7 +14,7 @@ &.invited { .user { - color: $color-grey; + color: color-grey; } } @@ -24,25 +27,51 @@ &.editing, &:focus, &:hover { - background: $color-light-background; + background: color-light-background; .button { opacity: 1; } } + + .button { + flex: 0 0 auto; + transition: transition-speed transition-easing; + transition-property: opacity; + opacity: 0; + padding: 6px 7px; + margin-left: 10px; + font-size: 11px; + + :global(.button-icon) { + flex-shrink: 0; + width: 12px; + height: 12px; + } + } + + :global(.ember-power-select-trigger) { + min-width: 150px; + padding: 5px 7px 4px; + margin-bottom: 10px; + border: 1px solid #eee; + background: #fff; + font-size: 12px; + box-shadow: 0 1px 5px rgba(#000, 0.06); + } } .role { display: block; margin-bottom: 4px; - color: $color-green; + color: color-green; color: var(--color-primary); font-size: 12px; } .user { display: flex; - color: $color-black; + color: color-black; font-size: 15px; } @@ -60,7 +89,7 @@ } .invite { - color: $color-grey; + color: color-grey; font-size: 13px; font-style: italic; } @@ -68,29 +97,3 @@ .actions { display: flex; } - -.button { - flex: 0 0 auto; - transition: $transition-speed $transition-easing; - transition-property: opacity; - opacity: 0; - padding: 6px 7px; - margin-left: 10px; - font-size: 11px; - - .button-icon { - flex-shrink: 0; - width: 12px; - height: 12px; - } -} - -.ember-power-select-trigger { - min-width: 150px; - padding: 5px 7px 4px; - margin-bottom: 10px; - border: 1px solid #eee; - background: #fff; - font-size: 12px; - box-shadow: 0 1px 5px rgba(#000, 0.06); -} diff --git a/webapp/app/pods/components/project-settings/collaborators/list/item/template.hbs b/webapp/app/pods/components/project-settings/collaborators/list/item/template.hbs index 2f280a06..13b560ed 100644 --- a/webapp/app/pods/components/project-settings/collaborators/list/item/template.hbs +++ b/webapp/app/pods/components/project-settings/collaborators/list/item/template.hbs @@ -1,89 +1,91 @@ -
              -
              - {{#if isEditing}} - - {{else}} - - {{role}} - - {{/if}} - - - {{#if collaborator.user.pictureUrl}} - - {{/if}} - - - {{#if hasJoined}} - {{#if collaborator.user.fullname}} - {{collaborator.user.fullname}} - - {{collaborator.email}} - - {{else}} - {{collaborator.email}} - {{/if}} - {{else}} - {{collaborator.email}} - {{/if}} - - -
              - -
              - - {{#if hasJoined}} - {{t "components.project_settings.collaborators_item.joined"}} - +
            • +
              +
              + {{#if this.isEditing}} + {{else}} - {{t "components.project_settings.collaborators_item.invited"}} - - - - {{#if collaborator.assigner}} - {{t "components.project_settings.collaborators_item.by"}} - {{collaborator.assigner.fullname}} - {{/if}} + + {{this.role}} + {{/if}} - -
              -
              -
              - {{#if isEditing}} - {{#if canUpdateCollaborator}} - - - - {{/if}} - {{else}} - {{#if canUpdateCollaborator}} - - {{/if}} - - {{#if canDeleteCollaborator}} - + + + {{#if this.hasJoined}} + {{#if @collaborator.user.fullname}} + {{@collaborator.user.fullname}} + + {{@collaborator.email}} + + {{else}} + {{@collaborator.email}} + {{/if}} + {{else}} + {{@collaborator.email}} + {{/if}} + + +
              + +
              + + {{#if this.hasJoined}} + {{t "components.project_settings.collaborators_item.joined"}} + + {{else}} + {{t "components.project_settings.collaborators_item.invited"}} + + + + {{#if @collaborator.assigner}} + {{t "components.project_settings.collaborators_item.by"}} + {{@collaborator.assigner.fullname}} + {{/if}} + {{/if}} + +
              +
            • + +
              + {{#if this.isEditing}} + {{#if this.canUpdateCollaborator}} + + + + {{/if}} + {{else}} + {{#if this.canUpdateCollaborator}} + + {{/if}} + + {{#if this.canDeleteCollaborator}} + + {{/if}} {{/if}} - {{/if}} -
              +
              + diff --git a/webapp/app/pods/components/project-settings/collaborators/list/template.hbs b/webapp/app/pods/components/project-settings/collaborators/list/template.hbs index 41582332..641da399 100644 --- a/webapp/app/pods/components/project-settings/collaborators/list/template.hbs +++ b/webapp/app/pods/components/project-settings/collaborators/list/template.hbs @@ -1,8 +1,10 @@ -{{#each filteredCollaborators key="id" as |collaborator|}} - -{{/each}} +
                + {{#each this.filteredCollaborators key="id" as |collaborator|}} + + {{/each}} +
              diff --git a/webapp/app/pods/components/project-settings/collaborators/styles.scss b/webapp/app/pods/components/project-settings/collaborators/styles.scss index b68592bc..ea16b8d4 100644 --- a/webapp/app/pods/components/project-settings/collaborators/styles.scss +++ b/webapp/app/pods/components/project-settings/collaborators/styles.scss @@ -1,4 +1,7 @@ -& { +@value color-grey, color-green from 'accent-webapp/styles/variables/colors'; +@value screen-md from 'accent-webapp/styles/variables/dimensions'; + +.project-settings-collaborators { position: relative; margin-top: 30px; } @@ -10,7 +13,7 @@ border-bottom: 1px solid #eee; padding-bottom: 6px; margin-bottom: 6px; - color: $color-grey; + color: color-grey; font-weight: bold; font-size: 17px; } @@ -43,14 +46,14 @@ .rolesList { padding: 5px 0 20px 20px; - border-left: 1px solid lighten($color-grey, 25%); + border-left: 1px solid lighten(color-grey, 25%); } .rolesList-title { display: block; padding-bottom: 5px; margin: 15px 0 0; - color: $color-green; + color: color-green; color: var(--color-primary); font-weight: bold; font-size: 12px; @@ -61,11 +64,11 @@ } .rolesList-text { - color: $color-grey; + color: color-grey; font-size: 12px; } -@media (max-width: ($screen-md)) { +@media (max-width: (screen-md)) { .rolesList { display: none; } diff --git a/webapp/app/pods/components/project-settings/collaborators/template.hbs b/webapp/app/pods/components/project-settings/collaborators/template.hbs index 850344df..9fd476db 100644 --- a/webapp/app/pods/components/project-settings/collaborators/template.hbs +++ b/webapp/app/pods/components/project-settings/collaborators/template.hbs @@ -1,68 +1,70 @@ - +
              + -{{#if (get permissions "create_collaborator")}} - -{{/if}} + {{#if (get @permissions "create_collaborator")}} + + {{/if}} -{{#if showCreateForm}} -
              - -
              -{{/if}} + {{#if this.showCreateForm}} +
              + +
              + {{/if}} -
              -
              - -
              +
              +
              + +
              -
              - - {{t "general.roles.OWNER"}} - -

              - {{t "components.project_settings.collaborators.owner_text"}} -

              +
              + + {{t "general.roles.OWNER"}} + +

              + {{t "components.project_settings.collaborators.owner_text"}} +

              - - {{t "general.roles.ADMIN"}} - -

              - {{t "components.project_settings.collaborators.admin_text"}} -

              + + {{t "general.roles.ADMIN"}} + +

              + {{t "components.project_settings.collaborators.admin_text"}} +

              - - {{t "general.roles.DEVELOPER"}} - -

              - {{t "components.project_settings.collaborators.developer_text"}} -

              + + {{t "general.roles.DEVELOPER"}} + +

              + {{t "components.project_settings.collaborators.developer_text"}} +

              - - {{t "general.roles.REVIEWER"}} - -

              - {{t "components.project_settings.collaborators.reviewer_text"}} -

              + + {{t "general.roles.REVIEWER"}} + +

              + {{t "components.project_settings.collaborators.reviewer_text"}} +

              +
              diff --git a/webapp/app/pods/components/project-settings/delete-form/component.js b/webapp/app/pods/components/project-settings/delete-form/component.js deleted file mode 100644 index 4a54c57c..00000000 --- a/webapp/app/pods/components/project-settings/delete-form/component.js +++ /dev/null @@ -1,26 +0,0 @@ -import Component from '@ember/component'; -import {inject as service} from '@ember/service'; - -// Attributes -// project: Object -// onSubmit: Function -export default Component.extend({ - intl: service('intl'), - - actions: { - deleteProject() { - /* eslint-disable no-alert */ - if ( - !window.confirm( - this.intl.t( - 'components.project_settings.delete_form.delete_project_confirm' - ) - ) - ) - return; - /* eslint-enable no-alert */ - - this.onSubmit(); - } - } -}); diff --git a/webapp/app/pods/components/project-settings/delete-form/component.ts b/webapp/app/pods/components/project-settings/delete-form/component.ts new file mode 100644 index 00000000..43ab2c9b --- /dev/null +++ b/webapp/app/pods/components/project-settings/delete-form/component.ts @@ -0,0 +1,28 @@ +import Component from '@glimmer/component'; +import {inject as service} from '@ember/service'; +import {action} from '@ember/object'; +import IntlService from 'ember-intl/services/intl'; + +interface Args { + project: any; + onSubmit: () => void; +} + +export default class DeleteForm extends Component { + @service('intl') + intl: IntlService; + + @action + deleteProject() { + const message = this.intl.t( + 'components.project_settings.delete_form.delete_project_confirm' + ); + + // eslint-disable-next-line no-alert + if (!window.confirm(message)) { + return; + } + + this.args.onSubmit(); + } +} diff --git a/webapp/app/pods/components/project-settings/delete-form/styles.scss b/webapp/app/pods/components/project-settings/delete-form/styles.scss index d2580552..3ac8db61 100644 --- a/webapp/app/pods/components/project-settings/delete-form/styles.scss +++ b/webapp/app/pods/components/project-settings/delete-form/styles.scss @@ -1,4 +1,6 @@ -& { +@value color-error, color-light-background from 'accent-webapp/styles/variables/colors'; + +.project-settings-delete-form { margin-top: 90px; } @@ -6,16 +8,16 @@ display: block; width: 100%; padding-bottom: 6px; - border-bottom: 1px solid lighten($color-error, 48%); + border-bottom: 1px solid lighten(color-error, 48%); font-size: 19px; - color: darken($color-error, 10%); + color: darken(color-error, 10%); } .zone { margin-top: 12px; padding: 10px; border-radius: 3px; - background: $color-light-background; + background: color-light-background; } .zone-content { @@ -26,11 +28,11 @@ .zone-title { font-size: 13px; - color: darken($color-error, 26%); + color: darken(color-error, 26%); } .zone-text { font-size: 12px; font-style: italic; - color: rgba(darken($color-error, 30%), 0.5); + color: rgba(darken(color-error, 30%), 0.5); } diff --git a/webapp/app/pods/components/project-settings/delete-form/template.hbs b/webapp/app/pods/components/project-settings/delete-form/template.hbs index 66cc31e6..ffe7234e 100644 --- a/webapp/app/pods/components/project-settings/delete-form/template.hbs +++ b/webapp/app/pods/components/project-settings/delete-form/template.hbs @@ -1,24 +1,26 @@ - - {{t "components.project_settings.delete_form.title"}} - +
              + + {{t "components.project_settings.delete_form.title"}} + -
              -
              - - {{t "components.project_settings.delete_form.delete_project_title"}} - +
              +
              + + {{t "components.project_settings.delete_form.delete_project_title"}} + -
              -

              - {{t "components.project_settings.delete_form.delete_project_text"}} -

              +
              +

              + {{t "components.project_settings.delete_form.delete_project_text"}} +

              - - {{t "components.project_settings.delete_form.delete_project_button"}} - + + {{t "components.project_settings.delete_form.delete_project_button"}} + +
              diff --git a/webapp/app/pods/components/project-settings/form/component.js b/webapp/app/pods/components/project-settings/form/component.js deleted file mode 100644 index 95c39b40..00000000 --- a/webapp/app/pods/components/project-settings/form/component.js +++ /dev/null @@ -1,82 +0,0 @@ -import {inject as service} from '@ember/service'; -import {observer, computed} from '@ember/object'; -import {reads} from '@ember/object/computed'; -import Component from '@ember/component'; - -// Attributes -// project: Object -// permissions: Ember Object containing -// onUpdateProject: Function -export default Component.extend({ - globalState: service('global-state'), - flashMessages: service(), - intl: service('intl'), - - name: reads('project.name'), - mainColor: reads('project.mainColor'), - logo: reads('project.logo'), - isFileOperationsLocked: reads('project.isFileOperationsLocked'), - - mainColorPreviewObserver: observer('mainColor', function() { - this.globalState.set('mainColor', this.mainColor); - }), - - unchangedForm: computed('project', 'mainColor', 'name', 'logo', function() { - return ( - this.logo === this.project.logo && - this.mainColor === this.project.mainColor && - this.name === this.project.name - ); - }), - - actions: { - logoPicked(logo) { - this.set('logo', logo); - }, - - setLockedFileOperations() { - this.toggleProperty('isFileOperationsLocked'); - this.onUpdateProject( - this.getProperties( - 'isFileOperationsLocked', - 'name', - 'mainColor', - 'logo' - ) - ); - }, - - updateProject() { - this.onUpdateProject( - this.getProperties( - 'isFileOperationsLocked', - 'name', - 'mainColor', - 'logo' - ) - ); - }, - - logoReset() { - this.set('logo', null); - }, - - logoChange([logo]) { - if (!logo) return; - - if (logo.type !== 'image/svg+xml') { - this.flashMessages.error( - this.intl.t('components.project_settings.form.unsupported_logo_type') - ); - - return; - } - - const reader = new FileReader(); - - reader.onload = logoProcessed => - this.set('logo', logoProcessed.target.result); - reader.readAsText(logo); - } - } -}); diff --git a/webapp/app/pods/components/project-settings/form/component.ts b/webapp/app/pods/components/project-settings/form/component.ts new file mode 100644 index 00000000..2914967e --- /dev/null +++ b/webapp/app/pods/components/project-settings/form/component.ts @@ -0,0 +1,125 @@ +import {inject as service} from '@ember/service'; +import {action} from '@ember/object'; +import Component from '@glimmer/component'; +import GlobalState from 'accent-webapp/services/global-state'; +import FlashMessages from 'ember-cli-flash/services/flash-messages'; +import IntlService from 'ember-intl/services/intl'; +import {tracked} from '@glimmer/tracking'; + +interface Args { + project: any; + permissions: Record; + onUpdateProject: ({ + isFileOperationsLocked, + name, + mainColor, + logo, + }: { + isFileOperationsLocked: boolean; + name: string; + mainColor: string; + logo: string; + }) => Promise; +} + +export default class ProjectSettingsForm extends Component { + @service('global-state') + globalState: GlobalState; + + @service('flash-messages') + flashMessages: FlashMessages; + + @service('intl') + intl: IntlService; + + @tracked + name = this.args.project.name; + + @tracked + isUpdatingProject = false; + + @tracked + mainColor = this.args.project.mainColor; + + @tracked + logo = this.args.project.logo; + + @tracked + isFileOperationsLocked = this.args.project.isFileOperationsLocked; + + @action + logoPicked(logo: string) { + this.logo = logo; + } + + @action + async setLockedFileOperations() { + this.isUpdatingProject = true; + this.isFileOperationsLocked = !this.isFileOperationsLocked; + + await this.args.onUpdateProject({ + isFileOperationsLocked: this.isFileOperationsLocked, + name: this.name, + mainColor: this.mainColor, + logo: this.logo, + }); + + this.isUpdatingProject = false; + } + + @action + async updateProject() { + this.isUpdatingProject = true; + + await this.args.onUpdateProject({ + isFileOperationsLocked: this.isFileOperationsLocked, + name: this.name, + mainColor: this.mainColor, + logo: this.logo, + }); + + this.isUpdatingProject = false; + } + + @action + logoReset() { + this.logo = null; + } + + @action + logoChange([logo]: [File]) { + if (!logo) return; + + if (logo.type !== 'image/svg+xml') { + this.flashMessages.error( + this.intl.t('components.project_settings.form.unsupported_logo_type') + ); + + return; + } + + const reader = new FileReader(); + + reader.onload = () => { + this.logo = reader.result; + }; + + reader.readAsText(logo); + } + + @action + setName(event: Event) { + const target = event.target as HTMLInputElement; + + this.name = target.value; + } + + @action + setMainColor(event: Event) { + const target = event.target as HTMLInputElement; + + this.mainColor = target.value; + + this.globalState.mainColor = this.mainColor; + } +} diff --git a/webapp/app/pods/components/project-settings/form/styles.scss b/webapp/app/pods/components/project-settings/form/styles.scss index 02351007..52408d68 100644 --- a/webapp/app/pods/components/project-settings/form/styles.scss +++ b/webapp/app/pods/components/project-settings/form/styles.scss @@ -1,4 +1,7 @@ -& { +@value color-light-background, color-green, color-error from 'accent-webapp/styles/variables/colors'; +@value font-primary from 'accent-webapp/styles/variables/fonts'; + +.project-settings-form { margin-top: 25px; } @@ -9,7 +12,7 @@ flex-grow: 0; flex-shrink: 0; padding: 10px; - font-family: $font-primary; + font-family: font-primary; font-size: 12px; } @@ -31,7 +34,7 @@ align-items: center; margin: 20px 0; padding: 10px; - background: $color-light-background; + background: color-light-background; } .lock-text-helper { @@ -58,11 +61,11 @@ border-color: #ddd; &:hover { - color: $color-green; - border-color: $color-green; + color: color-green; + border-color: color-green; .lock-icon { - stroke: $color-green; + stroke: color-green; } } @@ -72,20 +75,20 @@ } &.lock-text--active { - color: $color-error; - border-color: $color-error; + color: color-error; + border-color: color-error; &:hover { - color: darken($color-error, 10%); - border-color: darken($color-error, 10%); + color: darken(color-error, 10%); + border-color: darken(color-error, 10%); .lock-icon { - stroke: darken($color-error, 10%); + stroke: darken(color-error, 10%); } } .lock-icon { - stroke: $color-error; + stroke: color-error; } } } @@ -99,7 +102,7 @@ .logo { display: flex; width: 25px; - height: 20px; + height: 22px; padding: 0; font-size: 25px; line-height: 1; diff --git a/webapp/app/pods/components/project-settings/form/template.hbs b/webapp/app/pods/components/project-settings/form/template.hbs index 1514e43c..1349682e 100644 --- a/webapp/app/pods/components/project-settings/form/template.hbs +++ b/webapp/app/pods/components/project-settings/form/template.hbs @@ -1,73 +1,75 @@ -{{#if (get permissions "update_project")}} -
              - +
              + {{#if (get @permissions "update_project")}} +
              + - + -
              - +
              + + + - {{#if this.logo}} - - {{/if}} + {{#if this.logo}} + + {{/if}} +
              -
              - - {{t "components.project_settings.form.update_button"}} - -{{/if}} + + {{t "components.project_settings.form.update_button"}} + + {{/if}} -{{#if (get permissions "lock_project_file_operations")}} -
              - {{#if isFileOperationsLocked}} -
              - {{inline-svg - "assets/lock--unlocked" - class="lock-icon lock-icon--unlocked" - }} - {{t - "components.project_settings.form.lock_file_operations.remove_lock_button" - }} -
              - {{else}} -
              - {{inline-svg "assets/lock--locked" class="lock-icon lock-icon--locked"}} + {{#if (get @permissions "lock_project_file_operations")}} +
              + {{#if this.isFileOperationsLocked}} +
              + {{inline-svg "assets/lock--unlocked" local-class="lock-icon lock-icon--unlocked"}} - {{t - "components.project_settings.form.lock_file_operations.add_lock_button" - }} -
              - {{/if}} + {{t "components.project_settings.form.lock_file_operations.remove_lock_button"}} +
              + {{else}} +
              + {{inline-svg "assets/lock--locked" local-class="lock-icon lock-icon--locked"}} -

              - {{t "components.project_settings.form.lock_file_operations.text_1"}} -

              -
              -{{/if}} + {{t "components.project_settings.form.lock_file_operations.add_lock_button"}} +
              + {{/if}} + +

              + {{t "components.project_settings.form.lock_file_operations.text_1"}} +

              +
              + {{/if}} +
              diff --git a/webapp/app/pods/components/project-settings/integrations/component.js b/webapp/app/pods/components/project-settings/integrations/component.js deleted file mode 100644 index fdcb0be5..00000000 --- a/webapp/app/pods/components/project-settings/integrations/component.js +++ /dev/null @@ -1,25 +0,0 @@ -import Component from '@ember/component'; - -// Attributes -// project: Object -// permissions: Ember Object containing -// integration: Array of -// onCreateIntegration: Function -// onUpdateIntegration: Function -// onDeleteIntegration: Function -export default Component.extend({ - showCreateForm: false, - - actions: { - toggleCreateForm() { - this.set('showCreateForm', !this.showCreateForm); - }, - - create(args) { - return this.onCreateIntegration(args).then(({errors}) => { - this.set('showCreateForm', errors && errors.length > 0); - return {errors}; - }); - } - } -}); diff --git a/webapp/app/pods/components/project-settings/integrations/component.ts b/webapp/app/pods/components/project-settings/integrations/component.ts new file mode 100644 index 00000000..313f076c --- /dev/null +++ b/webapp/app/pods/components/project-settings/integrations/component.ts @@ -0,0 +1,30 @@ +import Component from '@glimmer/component'; +import {tracked} from '@glimmer/tracking'; +import {action} from '@ember/object'; + +interface Args { + project: any; + permissions: Record; + onCreateIntegration: (args: any) => Promise<{errors: any}>; + onUpdateIntegration: () => void; + onDeleteIntegration: () => void; +} + +export default class Integrations extends Component { + @tracked + showCreateForm = false; + + @action + toggleCreateForm() { + this.showCreateForm = !this.showCreateForm; + } + + @action + async create(args: any) { + const {errors} = await this.args.onCreateIntegration(args); + + this.showCreateForm = errors && errors.length > 0; + + return {errors}; + } +} diff --git a/webapp/app/pods/components/project-settings/integrations/form/component.js b/webapp/app/pods/components/project-settings/integrations/form/component.js deleted file mode 100644 index f7323dec..00000000 --- a/webapp/app/pods/components/project-settings/integrations/form/component.js +++ /dev/null @@ -1,108 +0,0 @@ -import {computed} from '@ember/object'; -import {inject as service} from '@ember/service'; -import {not, reads} from '@ember/object/computed'; -import Component from '@ember/component'; - -// Attributes: -// project: Object -// integration: Object -// onSubmit: Function -export default Component.extend({ - intl: service('intl'), - - isSubmiting: false, - - errors: [], - - emptyUrl: not('url'), - url: reads('integration.data.url'), - repository: reads('integration.data.repository'), - defaultRef: reads('integration.data.defaultRef'), - token: reads('integration.data.token'), - - services: ['DISCORD', 'SLACK', 'GITHUB'], - - service: computed('integration', 'services.[]', function() { - return this.integration.service || this.services[0]; - }), - - serviceValue: computed('service', 'mappedServices', function() { - return this.mappedServices.find(({value}) => value === this.service); - }), - - mappedServices: computed('services', function() { - return this.services.map(value => { - return { - label: this.intl.t(`general.integration_services.${value}`), - value - }; - }); - }), - - syncChecked: computed('integration.events.[]', function() { - if (!this.integration.events) return; - - return this.integration.events.includes('SYNC'); - }), - - dataFormComponent: computed('service', function() { - return `project-settings/integrations/form/${this.service.toLowerCase()}`; - }), - - events: computed('syncChecked', function() { - const data = []; - - if (this.syncChecked) data.push('SYNC'); - - return data; - }), - - didReceiveAttrs() { - this._super(...arguments); - - if (!this.integration) { - this.set('integration', { - newRecord: true, - service: this.services[0], - events: [], - data: { - url: '', - repository: '', - token: '', - defaultRef: '' - } - }); - } - }, - - actions: { - submit() { - this.set('isSubmiting', true); - - return this.onSubmit({ - service: this.service, - events: this.events, - integration: this.integration.newRecord ? null : this.integration, - data: { - url: this.url, - repository: this.repository, - token: this.token, - defaultRef: this.defaultRef - } - }).then(({errors}) => { - this.set('isSubmiting', false); - - if (errors && errors.length > 0) { - this.set('errors', errors); - } else { - if (this.integration.newRecord) { - this.setProperties({ - syncChecked: false, - url: '' - }); - } - } - }); - } - } -}); diff --git a/webapp/app/pods/components/project-settings/integrations/form/component.ts b/webapp/app/pods/components/project-settings/integrations/form/component.ts new file mode 100644 index 00000000..8e40c567 --- /dev/null +++ b/webapp/app/pods/components/project-settings/integrations/form/component.ts @@ -0,0 +1,172 @@ +import {action} from '@ember/object'; +import {inject as service} from '@ember/service'; +import {not} from '@ember/object/computed'; +import Component from '@glimmer/component'; +import IntlService from 'ember-intl/services/intl'; +import {tracked} from '@glimmer/tracking'; + +interface Args { + project: any; + onSubmit: ({ + service, + events, + integration, + data: {url, repository, token, defaultRef}, + }: { + service: any; + events: any; + integration: any; + data: { + url: string; + repository: string; + token: string; + defaultRef: string; + }; + }) => Promise<{errors: any}>; + onCancel: () => void; + integration?: any; + errors?: any; +} + +export default class IntegrationsForm extends Component { + @service('intl') + intl: IntlService; + + @tracked + isSubmiting = false; + + @tracked + errors = []; + + @tracked + integration: any; + + @tracked + service: any; + + @tracked + url: string; + + @tracked + syncChecked: boolean; + + @tracked + repository: string; + + @tracked + token: string; + + @tracked + defaultRef: string; + + services = ['DISCORD', 'SLACK', 'GITHUB']; + + @not('url') + emptyUrl: boolean; + + get serviceValue() { + return this.mappedServices.find(({value}) => value === this.service); + } + + get mappedServices() { + return this.services.map((value) => { + return { + label: this.intl.t(`general.integration_services.${value}`), + value, + }; + }); + } + + get dataFormComponent() { + return `project-settings/integrations/form/${this.service.toLowerCase()}`; + } + + get events() { + return this.syncChecked ? ['SYNC'] : []; + } + + @action + didUpdateIntegration() { + if (this.args.integration) { + this.integration = this.args.integration; + } else { + this.integration = { + newRecord: true, + service: this.services[0], + events: [], + data: { + url: '', + repository: '', + token: '', + defaultRef: '', + }, + }; + } + + this.service = this.integration.service || this.services[0]; + this.url = this.integration.data.url; + this.syncChecked = + this.integration.events && this.integration.events.includes('SYNC'); + this.repository = this.integration.data.repository; + this.token = this.integration.data.token; + this.defaultRef = this.integration.data.defaultRef; + } + + @action + didUpdateErrors() { + this.errors = this.args.errors; + } + + @action + setService({value}: {value: string}) { + this.service = value; + } + + @action + setUrl(url: string) { + this.url = url; + } + + @action + setSyncChecked(syncChecked: boolean) { + this.syncChecked = syncChecked; + } + + @action + setRepository(repository: string) { + this.repository = repository; + } + + @action + setToken(token: string) { + this.token = token; + } + + @action + setDefaultRef(defaultRef: string) { + this.defaultRef = defaultRef; + } + + @action + async submit() { + this.isSubmiting = true; + + const {errors} = await this.args.onSubmit({ + service: this.service, + events: this.events, + integration: this.integration.newRecord ? null : this.integration, + data: { + url: this.url, + repository: this.repository, + token: this.token, + defaultRef: this.defaultRef, + }, + }); + + this.isSubmiting = false; + + if (errors && errors.length > 0) { + this.errors = errors; + } + } +} diff --git a/webapp/app/pods/components/project-settings/integrations/form/data-control-checkboxes/styles.scss b/webapp/app/pods/components/project-settings/integrations/form/data-control-checkboxes/styles.scss new file mode 100644 index 00000000..b162bfe8 --- /dev/null +++ b/webapp/app/pods/components/project-settings/integrations/form/data-control-checkboxes/styles.scss @@ -0,0 +1,24 @@ +.data-control { + margin-bottom: 15px; +} + +.data-title { + display: block; + margin-bottom: 5px; + font-size: 13px; + font-weight: bold; +} + +:global(.checkbox-with-label) { + display: inline-flex; + align-items: center; + margin-right: 10px; + border: 1px solid #eee; + padding: 3px 6px; + border-radius: 3px; + background: #f7f7f7; + + input { + margin-right: 5px; + } +} diff --git a/webapp/app/pods/components/project-settings/integrations/form/data-control-checkboxes/template.hbs b/webapp/app/pods/components/project-settings/integrations/form/data-control-checkboxes/template.hbs new file mode 100644 index 00000000..f217e64d --- /dev/null +++ b/webapp/app/pods/components/project-settings/integrations/form/data-control-checkboxes/template.hbs @@ -0,0 +1,11 @@ +
              +

              + {{@title}} +

              + + +
              diff --git a/webapp/app/pods/components/project-settings/integrations/form/data-control-text/styles.scss b/webapp/app/pods/components/project-settings/integrations/form/data-control-text/styles.scss new file mode 100644 index 00000000..062f6c69 --- /dev/null +++ b/webapp/app/pods/components/project-settings/integrations/form/data-control-text/styles.scss @@ -0,0 +1,47 @@ +@value font-monospace, font-primary from 'accent-webapp/styles/variables/fonts'; + +.data-control { + margin-bottom: 15px; +} + +.data-title { + display: block; + margin-bottom: 5px; + font-size: 13px; + font-weight: bold; +} + +.data-title-help { + margin-left: 4px; + font-size: 11px; + font-weight: normal; + text-decoration: none; + color: var(--color-primary); + + &:focus, + &:hover { + text-decoration: underline; + } +} + +.error-control { + @extend %errorControl; +} + +.textInput { + @extend %textInput; + flex-grow: 1; + flex-shrink: 0; + padding: 8px 10px; + margin-right: 10px; + max-width: 350px; + width: 100%; + font-family: font-primary; + font-size: 11px; + + &[readonly] { + max-width: 500px; + font-family: font-monospace; + background: #fafafa; + } +} diff --git a/webapp/app/pods/components/project-settings/integrations/form/data-control-text/template.hbs b/webapp/app/pods/components/project-settings/integrations/form/data-control-text/template.hbs new file mode 100644 index 00000000..f28839a8 --- /dev/null +++ b/webapp/app/pods/components/project-settings/integrations/form/data-control-text/template.hbs @@ -0,0 +1,23 @@ +
              + + + +
              diff --git a/webapp/app/pods/components/project-settings/integrations/form/discord/component.js b/webapp/app/pods/components/project-settings/integrations/form/discord/component.js deleted file mode 100644 index a9f3db9f..00000000 --- a/webapp/app/pods/components/project-settings/integrations/form/discord/component.js +++ /dev/null @@ -1,6 +0,0 @@ -import Component from '@ember/component'; -import fieldError from 'accent-webapp/computed-macros/field-error'; - -export default Component.extend({ - urlError: fieldError('errors', 'data.url') -}); diff --git a/webapp/app/pods/components/project-settings/integrations/form/discord/component.ts b/webapp/app/pods/components/project-settings/integrations/form/discord/component.ts new file mode 100644 index 00000000..49ea7f80 --- /dev/null +++ b/webapp/app/pods/components/project-settings/integrations/form/discord/component.ts @@ -0,0 +1,29 @@ +import Component from '@glimmer/component'; +import {action} from '@ember/object'; +import fieldError from 'accent-webapp/computed-macros/field-error'; + +interface Args { + repository: any; + defaultRef: any; + token: any; + errors: any; + url: any; + project: any; + syncChecked: any; + onChangeUrl: (url: string) => void; + onChangeSyncChecked: (syncChecked: boolean) => void; + onChangeRepository: (repository: string) => void; + onChangeToken: (token: string) => void; + onChangeDefaultRef: (defaultRef: string) => void; +} + +export default class Discord extends Component { + urlError = fieldError(this.args.errors, this.args.url); + + @action + changeUrl(event: Event) { + const target = event.target as HTMLInputElement; + + this.args.onChangeUrl(target.value); + } +} diff --git a/webapp/app/pods/components/project-settings/integrations/form/discord/template.hbs b/webapp/app/pods/components/project-settings/integrations/form/discord/template.hbs index cfe90db2..3074cc8a 100644 --- a/webapp/app/pods/components/project-settings/integrations/form/discord/template.hbs +++ b/webapp/app/pods/components/project-settings/integrations/form/discord/template.hbs @@ -1,32 +1,16 @@ -
              -
              - + - -
              - -
              -

              - {{t "components.project_settings.integrations.events.title"}} -

              - -
              -
              + diff --git a/webapp/app/pods/components/project-settings/integrations/form/github/component.js b/webapp/app/pods/components/project-settings/integrations/form/github/component.js deleted file mode 100644 index 3f813c1e..00000000 --- a/webapp/app/pods/components/project-settings/integrations/form/github/component.js +++ /dev/null @@ -1,22 +0,0 @@ -import fmt from 'simple-fmt'; -import Component from '@ember/component'; -import {computed} from '@ember/object'; -import fieldError from 'accent-webapp/computed-macros/field-error'; -import config from 'accent-webapp/config/environment'; - -export default Component.extend({ - tokenError: fieldError('errors', 'data.token'), - repositoryError: fieldError('errors', 'data.repository'), - defaultRefError: fieldError('errors', 'data.defaultRef'), - - webhookUrl: computed('project.id', function() { - if (!this.project.accessToken) return; - - return fmt( - config.API.HOOKS_PATH, - 'github', - this.project.id, - this.project.accessToken - ); - }) -}); diff --git a/webapp/app/pods/components/project-settings/integrations/form/github/component.ts b/webapp/app/pods/components/project-settings/integrations/form/github/component.ts new file mode 100644 index 00000000..2437f5be --- /dev/null +++ b/webapp/app/pods/components/project-settings/integrations/form/github/component.ts @@ -0,0 +1,58 @@ +import fmt from 'simple-fmt'; +import Component from '@glimmer/component'; +import {action} from '@ember/object'; +import fieldError from 'accent-webapp/computed-macros/field-error'; +import config from 'accent-webapp/config/environment'; + +interface Args { + repository: any; + defaultRef: any; + token: any; + errors: any; + url: any; + project: any; + syncChecked: any; + onChangeUrl: (url: string) => void; + onChangeSyncChecked: (syncChecked: boolean) => void; + onChangeRepository: (repository: string) => void; + onChangeToken: (token: string) => void; + onChangeDefaultRef: (defaultRef: string) => void; +} + +export default class GitHub extends Component { + tokenError = fieldError(this.args.errors, this.args.token); + repositoryError = fieldError(this.args.errors, this.args.repository); + defaultRefError = fieldError(this.args.errors, this.args.defaultRef); + + get webhookUrl() { + if (!this.args.project.accessToken) return; + + return fmt( + config.API.HOOKS_PATH, + 'github', + this.args.project.id, + this.args.project.accessToken + ); + } + + @action + changeRepository(event: Event) { + const target = event.target as HTMLInputElement; + + this.args.onChangeRepository(target.value); + } + + @action + changeToken(event: Event) { + const target = event.target as HTMLInputElement; + + this.args.onChangeToken(target.value); + } + + @action + changeDefaultRef(event: Event) { + const target = event.target as HTMLInputElement; + + this.args.onChangeDefaultRef(target.value); + } +} diff --git a/webapp/app/pods/components/project-settings/integrations/form/github/styles.scss b/webapp/app/pods/components/project-settings/integrations/form/github/styles.scss new file mode 100644 index 00000000..86865f7a --- /dev/null +++ b/webapp/app/pods/components/project-settings/integrations/form/github/styles.scss @@ -0,0 +1,62 @@ +@value font-monospace from 'accent-webapp/styles/variables/fonts'; + +.instructions { + border-top: 1px solid #eee; + padding-top: 10px; + margin: 20px 0 10px; +} + +.instructions-text { + margin-top: 7px; + font-style: italic; + color: #555; + + a { + font-family: font-monospace; + color: var(--color-primary); + text-decoration: none; + + &:focus, + &:hover { + text-decoration: underline; + opacity: 0.8; + } + } +} + +.data-control { + margin-bottom: 15px; +} + +.data-title { + display: block; + margin-bottom: 5px; + font-size: 13px; + font-weight: bold; +} + +.data-title-help { + margin-left: 4px; + font-size: 11px; + font-weight: normal; + text-decoration: none; + color: var(--color-primary); + + &:focus, + &:hover { + text-decoration: underline; + } +} + +.textInput { + @extend %textInput; + flex-grow: 1; + flex-shrink: 0; + padding: 8px 10px; + margin-right: 10px; + background: #fafafa; + max-width: 500px; + width: 100%; + font-family: font-monospace; + font-size: 11px; +} diff --git a/webapp/app/pods/components/project-settings/integrations/form/github/template.hbs b/webapp/app/pods/components/project-settings/integrations/form/github/template.hbs index 5023d6e4..0d1208e4 100644 --- a/webapp/app/pods/components/project-settings/integrations/form/github/template.hbs +++ b/webapp/app/pods/components/project-settings/integrations/form/github/template.hbs @@ -1,73 +1,64 @@ -
              -
              - - -
              + -
              -
              +{{/if}} diff --git a/webapp/app/pods/components/project-settings/integrations/form/slack/component.js b/webapp/app/pods/components/project-settings/integrations/form/slack/component.js deleted file mode 100644 index a9f3db9f..00000000 --- a/webapp/app/pods/components/project-settings/integrations/form/slack/component.js +++ /dev/null @@ -1,6 +0,0 @@ -import Component from '@ember/component'; -import fieldError from 'accent-webapp/computed-macros/field-error'; - -export default Component.extend({ - urlError: fieldError('errors', 'data.url') -}); diff --git a/webapp/app/pods/components/project-settings/integrations/form/slack/component.ts b/webapp/app/pods/components/project-settings/integrations/form/slack/component.ts new file mode 100644 index 00000000..4dd37a68 --- /dev/null +++ b/webapp/app/pods/components/project-settings/integrations/form/slack/component.ts @@ -0,0 +1,29 @@ +import Component from '@glimmer/component'; +import {action} from '@ember/object'; +import fieldError from 'accent-webapp/computed-macros/field-error'; + +interface Args { + repository: any; + defaultRef: any; + token: any; + errors: any; + url: any; + project: any; + syncChecked: any; + onChangeUrl: (url: string) => void; + onChangeSyncChecked: (syncChecked: boolean) => void; + onChangeRepository: (repository: string) => void; + onChangeToken: (token: string) => void; + onChangeDefaultRef: (defaultRef: string) => void; +} + +export default class Slack extends Component { + urlError = fieldError(this.args.errors, this.args.url); + + @action + changeUrl(event: Event) { + const target = event.target as HTMLInputElement; + + this.args.onChangeUrl(target.value); + } +} diff --git a/webapp/app/pods/components/project-settings/integrations/form/slack/template.hbs b/webapp/app/pods/components/project-settings/integrations/form/slack/template.hbs index 4056c381..4da386c5 100644 --- a/webapp/app/pods/components/project-settings/integrations/form/slack/template.hbs +++ b/webapp/app/pods/components/project-settings/integrations/form/slack/template.hbs @@ -1,33 +1,16 @@ -
              -
              - + - -
              - -
              -

              - {{t "components.project_settings.integrations.events.title"}} -

              - - -
              -
              + diff --git a/webapp/app/pods/components/project-settings/integrations/form/styles.scss b/webapp/app/pods/components/project-settings/integrations/form/styles.scss index 42ddb06b..0d92d675 100644 --- a/webapp/app/pods/components/project-settings/integrations/form/styles.scss +++ b/webapp/app/pods/components/project-settings/integrations/form/styles.scss @@ -1,67 +1,35 @@ -& { - padding: 10px; +@value font-monospace, font-primary from 'accent-webapp/styles/variables/fonts'; + +.project-settings-integrations-form { + padding: 15px; border: 1px solid #eee; border-radius: 3px; + + :global(.ember-power-select-trigger) { + min-width: 150px; + margin-right: 10px; + border: 1px solid #eee; + background: #fff; + font-size: 12px; + font-weight: bold; + box-shadow: 0 1px 5px rgba(#000, 0.06); + } + + :global(.ember-power-select-option), + :global(.ember-power-select-selected-item) { + display: flex; + align-items: center; + } + + :global(.ember-power-select-trigger)[aria-disabled='true'] { + background: transparent; + box-shadow: none; + } } .form { display: flex; -} - -.textInput { - @extend %textInput; - flex-grow: 1; - flex-shrink: 0; - padding: 8px 10px; - margin-right: 10px; - max-width: 350px; - width: 100%; - font-family: $font-primary; - font-size: 11px; - - &[readonly] { - max-width: 500px; - font-family: $font-monospace; - background: #fafafa; - } -} - -.instructions { - border-top: 1px solid #eee; - padding-top: 10px; - margin: 20px 0 10px; -} - -.instructions-text { - margin-top: 7px; - font-style: italic; - color: #555; -} - -.instructions-text a { - font-family: $font-monospace; - color: var(--color-primary); - text-decoration: none; - - &:focus, - &:hover { - text-decoration: underline; - opacity: 0.8; - } -} - -.checkbox-with-label { - display: inline-flex; - align-items: center; - margin-right: 10px; - border: 1px solid #eee; - padding: 3px 6px; - border-radius: 3px; - background: #f7f7f7; - - input { - margin-right: 5px; - } + padding-bottom: 10px; } .data { @@ -69,61 +37,6 @@ font-size: 12px; } -.data-control { - margin-bottom: 15px; -} - -.error-control { - @extend %errorControl; -} - -.data-title { - display: block; - margin-bottom: 5px; - font-size: 13px; - font-weight: bold; -} - -.data-title-help { - margin-left: 4px; - font-size: 11px; - font-weight: normal; - text-decoration: none; - color: var(--color-primary); - - &:focus, - &:hover { - text-decoration: underline; - } -} - -.service-logo { - width: 15px; - height: 15px; - margin-right: 8px; -} - -.ember-power-select-trigger { - min-width: 150px; - margin-right: 10px; - border: 1px solid #eee; - background: #fff; - font-size: 12px; - font-weight: bold; - box-shadow: 0 1px 5px rgba(#000, 0.06); -} - -.ember-power-select-option, -.ember-power-select-selected-item { - display: flex; - align-items: center; -} - -.ember-power-select-trigger[aria-disabled='true'] { - background: transparent; - box-shadow: none; -} - .button { margin-right: 5px; } diff --git a/webapp/app/pods/components/project-settings/integrations/form/template.hbs b/webapp/app/pods/components/project-settings/integrations/form/template.hbs index 86b02210..182b6c9b 100644 --- a/webapp/app/pods/components/project-settings/integrations/form/template.hbs +++ b/webapp/app/pods/components/project-settings/integrations/form/template.hbs @@ -1,36 +1,54 @@ -
              - -
              +
              + {{#if this.integration}} +
              + +
              -{{component - dataFormComponent - repository=repository - defaultRef=defaultRef - token=token - errors=errors - url=url - project=project - syncChecked=syncChecked -}} +
              + {{component + this.dataFormComponent + repository=this.repository + defaultRef=this.defaultRef + token=this.token + errors=this.errors + url=this.url + project=@project + syncChecked=this.syncChecked + onChangeUrl=(fn this.setUrl) + onChangeSyncChecked=(fn this.setSyncChecked) + onChangeRepository=(fn this.setRepository) + onChangeToken=(fn this.setToken) + onChangeDefaultRef=(fn this.setDefaultRef) + }} +
              -
              - - {{t "components.project_settings.integrations.save"}} - +
              + + {{t "components.project_settings.integrations.save"}} + - {{#if onCancel}} - + {{#if @onCancel}} + + {{/if}} +
              {{/if}}
              + diff --git a/webapp/app/pods/components/project-settings/integrations/list/component.js b/webapp/app/pods/components/project-settings/integrations/list/component.js deleted file mode 100644 index 27b71830..00000000 --- a/webapp/app/pods/components/project-settings/integrations/list/component.js +++ /dev/null @@ -1,10 +0,0 @@ -import Component from '@ember/component'; - -// Attributes -// project: Object -// integrations: Array of -// onUpdateIntegration: Function -// onDeleteIntegration: Function -export default Component.extend({ - tagName: 'ul' -}); diff --git a/webapp/app/pods/components/project-settings/integrations/list/component.ts b/webapp/app/pods/components/project-settings/integrations/list/component.ts new file mode 100644 index 00000000..80cc65e4 --- /dev/null +++ b/webapp/app/pods/components/project-settings/integrations/list/component.ts @@ -0,0 +1,11 @@ +import Component from '@glimmer/component'; + +interface Args { + permissions: Record; + project: any; + integrations: any; + onUpdate: () => void; + onDelete: () => void; +} + +export default class IntegrationsList extends Component {} diff --git a/webapp/app/pods/components/project-settings/integrations/list/item/component.js b/webapp/app/pods/components/project-settings/integrations/list/item/component.js deleted file mode 100644 index e92779b8..00000000 --- a/webapp/app/pods/components/project-settings/integrations/list/item/component.js +++ /dev/null @@ -1,54 +0,0 @@ -import {computed} from '@ember/object'; -import {inject as service} from '@ember/service'; -import Component from '@ember/component'; -const LOGOS = { - DISCORD: 'assets/services/discord.svg', - GITHUB: 'assets/services/github.svg', - SLACK: 'assets/services/slack.svg' -}; - -// Attributes -// integration: Object -// onUpdate: Function -// onDelete: Function -export default Component.extend({ - intl: service('intl'), - - tagName: 'li', - errors: [], - - isEditing: false, - - logoService: computed('integration.service', function() { - return LOGOS[this.integration.service]; - }), - - mappedService: computed('integration.service', function() { - return this.intl.t( - `general.integration_services.${this.integration.service}` - ); - }), - - actions: { - toggleEdit() { - this.set('errors', []); - this.set('isEditing', !this.isEditing); - }, - - update(args) { - this.onUpdate(args).then(({errors}) => { - this.set('errors', errors); - this.set('isEditing', errors && errors.length > 0); - }); - }, - - delete() { - this.set('isDeleting', true); - - this.onDelete({id: this.integration.id}).then(({errors}) => { - this.set('errors', errors); - this.set('isEditing', errors && errors.length > 0); - }); - } - } -}); diff --git a/webapp/app/pods/components/project-settings/integrations/list/item/component.ts b/webapp/app/pods/components/project-settings/integrations/list/item/component.ts new file mode 100644 index 00000000..cf637e3c --- /dev/null +++ b/webapp/app/pods/components/project-settings/integrations/list/item/component.ts @@ -0,0 +1,69 @@ +import {inject as service} from '@ember/service'; +import {action} from '@ember/object'; +import Component from '@glimmer/component'; +import IntlService from 'ember-intl/services/intl'; +import {tracked} from '@glimmer/tracking'; + +const LOGOS = { + DISCORD: 'assets/services/discord.svg', + GITHUB: 'assets/services/github.svg', + SLACK: 'assets/services/slack.svg', +}; + +interface Args { + project: any; + permissions: Record; + integration: any; + onUpdate: (args: any) => Promise<{errors: any}>; + onDelete: ({id}: {id: string}) => Promise<{errors: any}>; +} + +export default class IntegrationsListItem extends Component { + @service('intl') + intl: IntlService; + + @tracked + errors = []; + + @tracked + isEditing = false; + + @tracked + isDeleting = false; + + get logoService() { + const service: keyof typeof LOGOS = this.args.integration.service; + + return LOGOS[service]; + } + + get mappedService() { + return this.intl.t( + `general.integration_services.${this.args.integration.service}` + ); + } + + @action + toggleEdit() { + this.errors = []; + this.isEditing = !this.isEditing; + } + + @action + async update(args: any) { + const {errors} = await this.args.onUpdate(args); + + this.errors = errors; + this.isEditing = errors && errors.length > 0; + } + + @action + async delete() { + this.isDeleting = true; + + const {errors} = await this.args.onDelete({id: this.args.integration.id}); + + this.errors = errors; + this.isDeleting = errors && errors.length > 0; + } +} diff --git a/webapp/app/pods/components/project-settings/integrations/list/item/styles.scss b/webapp/app/pods/components/project-settings/integrations/list/item/styles.scss index 0ed178f5..a0358ead 100644 --- a/webapp/app/pods/components/project-settings/integrations/list/item/styles.scss +++ b/webapp/app/pods/components/project-settings/integrations/list/item/styles.scss @@ -1,4 +1,4 @@ -& { +.project-settings-integrations-list-item { margin-bottom: 10px; } diff --git a/webapp/app/pods/components/project-settings/integrations/list/item/template.hbs b/webapp/app/pods/components/project-settings/integrations/list/item/template.hbs index ad9743eb..bdd21ff8 100644 --- a/webapp/app/pods/components/project-settings/integrations/list/item/template.hbs +++ b/webapp/app/pods/components/project-settings/integrations/list/item/template.hbs @@ -1,44 +1,46 @@ -{{#if isEditing}} - -{{else}} -
              -
              - {{inline-svg logoService class="details-logo"}} - - {{mappedService}} - +
            • + {{#if this.isEditing}} + + {{else}} +
              +
              + {{inline-svg this.logoService local-class="details-logo"}} + + {{this.mappedService}} + - - {{integration.data.url}} - {{integration.data.repository}} - + + {{@integration.data.url}} + {{@integration.data.repository}} + +
              + +
              + {{#if (get @permissions "update_project_integration")}} + + {{/if}} + + {{#if (get @permissions "delete_project_integration")}} + + {{t "components.project_settings.integrations.delete"}} + + {{/if}} +
              - -
              - {{#if (get permissions "update_project_integration")}} - - {{/if}} - - {{#if (get permissions "delete_project_integration")}} - - {{t "components.project_settings.integrations.delete"}} - - {{/if}} -
              -
            • -{{/if}} + {{/if}} + diff --git a/webapp/app/pods/components/project-settings/integrations/list/styles.scss b/webapp/app/pods/components/project-settings/integrations/list/styles.scss index 85d7ff2b..5a0117e4 100644 --- a/webapp/app/pods/components/project-settings/integrations/list/styles.scss +++ b/webapp/app/pods/components/project-settings/integrations/list/styles.scss @@ -1,3 +1,3 @@ -& { +.project-settings-integrations-list { margin-top: 10px; } diff --git a/webapp/app/pods/components/project-settings/integrations/list/template.hbs b/webapp/app/pods/components/project-settings/integrations/list/template.hbs index 3dd63197..fa6b95ba 100644 --- a/webapp/app/pods/components/project-settings/integrations/list/template.hbs +++ b/webapp/app/pods/components/project-settings/integrations/list/template.hbs @@ -1,9 +1,11 @@ -{{#each integrations key="id" as |integration|}} - -{{/each}} +
                + {{#each @integrations key="id" as |integration|}} + + {{/each}} +
              diff --git a/webapp/app/pods/components/project-settings/integrations/styles.scss b/webapp/app/pods/components/project-settings/integrations/styles.scss index aff82a99..0b437b20 100644 --- a/webapp/app/pods/components/project-settings/integrations/styles.scss +++ b/webapp/app/pods/components/project-settings/integrations/styles.scss @@ -1,4 +1,6 @@ -& { +@value color-grey from 'accent-webapp/styles/variables/colors'; + +.project-settings-integrations { position: relative; margin-top: 30px; } @@ -10,7 +12,7 @@ border-bottom: 1px solid #eee; padding-bottom: 6px; margin-bottom: 6px; - color: $color-grey; + color: color-grey; font-weight: bold; font-size: 17px; } diff --git a/webapp/app/pods/components/project-settings/integrations/template.hbs b/webapp/app/pods/components/project-settings/integrations/template.hbs index 5df300de..230ef030 100644 --- a/webapp/app/pods/components/project-settings/integrations/template.hbs +++ b/webapp/app/pods/components/project-settings/integrations/template.hbs @@ -1,39 +1,41 @@ - +
              + -{{#if (get permissions "create_project_integration")}} - -{{/if}} + {{#if (get @permissions "create_project_integration")}} + + {{/if}} -

              - {{t "components.project_settings.integrations.help"}} -

              +

              + {{t "components.project_settings.integrations.help"}} +

              -{{#if showCreateForm}} -
              - -
              -{{/if}} + {{#if this.showCreateForm}} +
              + +
              + {{/if}} - + +
              diff --git a/webapp/app/pods/components/project-settings/jipt/component.js b/webapp/app/pods/components/project-settings/jipt/component.js deleted file mode 100644 index 2e18758e..00000000 --- a/webapp/app/pods/components/project-settings/jipt/component.js +++ /dev/null @@ -1,16 +0,0 @@ -import Component from '@ember/component'; -import {computed} from '@ember/object'; -import config from 'accent-webapp/config/environment'; - -export default Component.extend({ - scriptContent: computed('project.id', function() { - const host = config.API.HOST; - const url = config.API.JIPT_SCRIPT_PATH; - - return ` -`; - }) -}); diff --git a/webapp/app/pods/components/project-settings/jipt/component.ts b/webapp/app/pods/components/project-settings/jipt/component.ts new file mode 100644 index 00000000..b17f148b --- /dev/null +++ b/webapp/app/pods/components/project-settings/jipt/component.ts @@ -0,0 +1,20 @@ +import Component from '@glimmer/component'; +import config from 'accent-webapp/config/environment'; + +interface Args { + project: any; +} + +export default class JIPT extends Component { + get scriptContent() { + const host = config.API.HOST; + const url = config.API.JIPT_SCRIPT_PATH; + + return ` + +`; + } +} diff --git a/webapp/app/pods/components/project-settings/jipt/styles.scss b/webapp/app/pods/components/project-settings/jipt/styles.scss index 9cf5e41b..a18c8b5d 100644 --- a/webapp/app/pods/components/project-settings/jipt/styles.scss +++ b/webapp/app/pods/components/project-settings/jipt/styles.scss @@ -1,4 +1,7 @@ -& { +@value color-black, color-green from 'accent-webapp/styles/variables/colors'; +@value font-monospace from 'accent-webapp/styles/variables/fonts'; + +.project-settings-jipt { margin-top: 30px; } @@ -15,7 +18,7 @@ padding-bottom: 10px; font-size: 16px; font-weight: 300; - color: $color-black; + color: color-black; } .code { @@ -26,7 +29,7 @@ height: 111px; word-break: keep-all; background: #fbfbfb; - font-family: $font-monospace; + font-family: font-monospace; font-size: 15px; border: 2px solid #ddd; border-radius: 3px; @@ -36,18 +39,18 @@ &:focus { outline: none; - border-color: lighten($color-green, 20%); + border-color: lighten(color-green, 20%); border-color: var(--color-primary-opacity-70); - box-shadow: 0 0 3px 2px rgba($color-green, 0.3); + box-shadow: 0 0 3px 2px rgba(color-green, 0.3); box-shadow: 0 0 3px 2px var(--color-primary-opacity-10); &::-moz-selection { - background: lighten($color-green, 45%); + background: lighten(color-green, 45%); background: var(--color-primary-opacity-10); } &::selection { - background: lighten($color-green, 45%); + background: lighten(color-green, 45%); background: var(--color-primary-opacity-10); } } diff --git a/webapp/app/pods/components/project-settings/jipt/template.hbs b/webapp/app/pods/components/project-settings/jipt/template.hbs index 1de197b3..64b0a9f7 100644 --- a/webapp/app/pods/components/project-settings/jipt/template.hbs +++ b/webapp/app/pods/components/project-settings/jipt/template.hbs @@ -1,18 +1,20 @@ - +
              + -

              - {{t "components.project_settings.jipt.integration_help"}} -

              +

              + {{t "components.project_settings.jipt.integration_help"}} +

              - - {{t "components.project_settings.jipt.integration_link"}} - + + {{t "components.project_settings.jipt.integration_link"}} + -

              - {{t "components.project_settings.jipt.script_title"}} -

              +

              + {{t "components.project_settings.jipt.script_title"}} +

              - + +
              diff --git a/webapp/app/pods/components/project-settings/links-list/component.js b/webapp/app/pods/components/project-settings/links-list/component.js deleted file mode 100644 index cbfd5011..00000000 --- a/webapp/app/pods/components/project-settings/links-list/component.js +++ /dev/null @@ -1,3 +0,0 @@ -import Component from '@ember/component'; - -export default Component.extend(); diff --git a/webapp/app/pods/components/project-settings/links-list/component.ts b/webapp/app/pods/components/project-settings/links-list/component.ts new file mode 100644 index 00000000..953a16ef --- /dev/null +++ b/webapp/app/pods/components/project-settings/links-list/component.ts @@ -0,0 +1,8 @@ +import Component from '@glimmer/component'; + +interface Args { + project: any; + permissions: Record; +} + +export default class LinksList extends Component {} diff --git a/webapp/app/pods/components/project-settings/links-list/styles.scss b/webapp/app/pods/components/project-settings/links-list/styles.scss index 19ffdfa1..4fbf5918 100644 --- a/webapp/app/pods/components/project-settings/links-list/styles.scss +++ b/webapp/app/pods/components/project-settings/links-list/styles.scss @@ -1,4 +1,8 @@ -& { +@value transition-speed, transition-easing from 'accent-webapp/styles/variables/transitions'; +@value color-green, color-light-background from 'accent-webapp/styles/variables/colors'; +@value screen-md from 'accent-webapp/styles/variables/dimensions'; + +.project-settings-links-list { margin-top: 10px; } @@ -24,7 +28,7 @@ text-decoration: none; font-weight: 600; font-size: 13px; - transition: $transition-speed $transition-easing; + transition: transition-speed transition-easing; transition-property: background, border-color, color; .link-icon { @@ -33,12 +37,12 @@ &:focus, &:hover { - color: $color-green; + color: color-green; color: var(--color-primary); - background: $color-light-background; + background: color-light-background; .link-icon { - stroke: $color-green; + stroke: color-green; stroke: var(--color-primary); } } @@ -48,12 +52,12 @@ width: 20px; height: 20px; margin-bottom: 3px; - transition: $transition-speed $transition-easing; + transition: transition-speed transition-easing; transition-property: stroke; } -@media (max-width: ($screen-md)) { - &, +@media (max-width: (screen-md)) { + .project-settings-links-list, .list { margin: 0; } diff --git a/webapp/app/pods/components/project-settings/links-list/template.hbs b/webapp/app/pods/components/project-settings/links-list/template.hbs index 0bf061fc..f68d7a87 100644 --- a/webapp/app/pods/components/project-settings/links-list/template.hbs +++ b/webapp/app/pods/components/project-settings/links-list/template.hbs @@ -1,31 +1,33 @@ -
              - - {{inline-svg "assets/users.svg" class="link-icon"}} - {{t "components.project_settings.links_list.collaborators"}} - +
              +
              + + {{inline-svg "assets/users.svg" local-class="link-icon"}} + {{t "components.project_settings.links_list.collaborators"}} + - - {{inline-svg "assets/badge.svg" class="link-icon"}} - {{t "components.project_settings.links_list.badges"}} - + + {{inline-svg "assets/badge.svg" local-class="link-icon"}} + {{t "components.project_settings.links_list.badges"}} + - - {{inline-svg "assets/bot.svg" class="link-icon"}} - {{t "components.project_settings.links_list.api_token"}} - + + {{inline-svg "assets/bot.svg" local-class="link-icon"}} + {{t "components.project_settings.links_list.api_token"}} + - - {{inline-svg "assets/share.svg" class="link-icon"}} - {{t "components.project_settings.links_list.service_integrations"}} - + + {{inline-svg "assets/share.svg" local-class="link-icon"}} + {{t "components.project_settings.links_list.service_integrations"}} + - - {{inline-svg "assets/language.svg" class="link-icon"}} - {{t "components.project_settings.links_list.manage_languages"}} - + + {{inline-svg "assets/language.svg" local-class="link-icon"}} + {{t "components.project_settings.links_list.manage_languages"}} + - - {{inline-svg "assets/edit-in-place.svg" class="link-icon"}} - {{t "components.project_settings.links_list.jipt"}} - + + {{inline-svg "assets/edit-in-place.svg" local-class="link-icon"}} + {{t "components.project_settings.links_list.jipt"}} + +
              diff --git a/webapp/app/pods/components/project-settings/manage-languages/component.js b/webapp/app/pods/components/project-settings/manage-languages/component.js deleted file mode 100644 index d4aeb9f2..00000000 --- a/webapp/app/pods/components/project-settings/manage-languages/component.js +++ /dev/null @@ -1,12 +0,0 @@ -import Component from '@ember/component'; - -// Attributes -// project: Object -// permissions: Ember Object containing -// languages: Array of -// revisions: Array of -// errors: Array of String -// onPromoteMaster: Function -// onDelete: Function -// onCreate: Function -export default Component.extend(); diff --git a/webapp/app/pods/components/project-settings/manage-languages/component.ts b/webapp/app/pods/components/project-settings/manage-languages/component.ts new file mode 100644 index 00000000..db003f6a --- /dev/null +++ b/webapp/app/pods/components/project-settings/manage-languages/component.ts @@ -0,0 +1,14 @@ +import Component from '@glimmer/component'; + +interface Args { + project: any; + revisions: any; + permissions: Record; + languages: any; + errors: any; + onPromoteMaster: () => void; + onDelete: () => void; + onCreate: () => void; +} + +export default class ManageLanguages extends Component {} diff --git a/webapp/app/pods/components/project-settings/manage-languages/create-form/component.js b/webapp/app/pods/components/project-settings/manage-languages/create-form/component.js deleted file mode 100644 index 7ffb376a..00000000 --- a/webapp/app/pods/components/project-settings/manage-languages/create-form/component.js +++ /dev/null @@ -1,57 +0,0 @@ -import {computed} from '@ember/object'; -import {inject as service} from '@ember/service'; -import {htmlSafe} from '@ember/string'; -import {not, reads} from '@ember/object/computed'; -import Component from '@ember/component'; - -// Attributes: -// languages: Array of -// onCreate: Function -export default Component.extend({ - languageSearcher: service('language-searcher'), - - languagesCopy: reads('languages'), - isLoading: false, - - emptyLanguage: not('language'), - - language: computed('mappedLanguages.[]', function() { - const first = this.mappedLanguages[0]; - - return first ? first.value : null; - }), - - languageValue: computed('language', 'mappedLanguages.[]', function() { - return this.mappedLanguages.find(({value}) => value === this.language); - }), - - mappedLanguages: computed('languagesCopy.[]', function() { - if (!this.languagesCopy) return []; - - return this._mapLanguages(this.languagesCopy); - }), - - actions: { - submit() { - this.set('isLoading', true); - - this.onCreate(this.language).then(() => this.set('isLoading', false)); - }, - - searchLanguages(term) { - return this.languageSearcher.search({term}).then(languages => { - this.set('languagesCopy', languages); - - return this._mapLanguages(languages); - }); - } - }, - - _mapLanguages(languages) { - return languages.map(({id, name, slug}) => { - const label = htmlSafe(`${name} ${slug}`); - - return {label, value: id}; - }); - } -}); diff --git a/webapp/app/pods/components/project-settings/manage-languages/create-form/component.ts b/webapp/app/pods/components/project-settings/manage-languages/create-form/component.ts new file mode 100644 index 00000000..180eed05 --- /dev/null +++ b/webapp/app/pods/components/project-settings/manage-languages/create-form/component.ts @@ -0,0 +1,76 @@ +import {action} from '@ember/object'; +import {inject as service} from '@ember/service'; +import {htmlSafe} from '@ember/string'; +import {not} from '@ember/object/computed'; +import Component from '@glimmer/component'; +import LanguageSearcher from 'accent-webapp/services/language-searcher'; +import {tracked} from '@glimmer/tracking'; + +interface Args { + permissions: Record; + project: any; + languages: any; + onCreate: (language: any) => Promise; +} + +export default class CreateForm extends Component { + @service('language-searcher') + languageSearcher: LanguageSearcher; + + @tracked + languagesCopy = this.args.languages; + + @tracked + isLoading = false; + + @tracked + language = this.mappedLanguages[0]?.value; + + @not('language') + emptyLanguage: boolean; + + get languageValue() { + return this.mappedLanguages.find( + ({value}: {value: string}) => value === this.language + ); + } + + get mappedLanguages() { + if (!this.languagesCopy) return []; + + return this.mapLanguages(this.languagesCopy); + } + + @action + async submit() { + this.isLoading = true; + + await this.args.onCreate(this.language); + + this.isLoading = false; + } + + @action + async searchLanguages(term: string) { + const languages = await this.languageSearcher.search({term}); + + this.languagesCopy = languages; + + return this.mapLanguages(languages); + } + + @action + setLanguage({value}: {value: string}) { + this.language = value; + } + + private mapLanguages(languages: any) { + return languages.map( + ({id, name, slug}: {id: string; name: string; slug: string}) => { + const label = htmlSafe(`${name} ${slug}`); + + return {label, value: id}; + } + ); + } +} diff --git a/webapp/app/pods/components/project-settings/manage-languages/create-form/template.hbs b/webapp/app/pods/components/project-settings/manage-languages/create-form/template.hbs index a5daca0b..cd39bb77 100644 --- a/webapp/app/pods/components/project-settings/manage-languages/create-form/template.hbs +++ b/webapp/app/pods/components/project-settings/manage-languages/create-form/template.hbs @@ -1,22 +1,22 @@ {{t "components.project_manage_languages_create_form.save_button"}} diff --git a/webapp/app/pods/components/project-settings/manage-languages/overview/component.js b/webapp/app/pods/components/project-settings/manage-languages/overview/component.js deleted file mode 100644 index 9820d43b..00000000 --- a/webapp/app/pods/components/project-settings/manage-languages/overview/component.js +++ /dev/null @@ -1,9 +0,0 @@ -import Component from '@ember/component'; - -// Attributes -// project: Object -// permissions: Ember Object containing -// revisions: Array of -// onPromoteMaster: Function -// onDelete: Function -export default Component.extend(); diff --git a/webapp/app/pods/components/project-settings/manage-languages/overview/component.ts b/webapp/app/pods/components/project-settings/manage-languages/overview/component.ts new file mode 100644 index 00000000..3a812cc2 --- /dev/null +++ b/webapp/app/pods/components/project-settings/manage-languages/overview/component.ts @@ -0,0 +1,11 @@ +import Component from '@glimmer/component'; + +interface Args { + permissions: Record; + project: any; + revisions: any; + onPromoteMaster: () => void; + onDelete: () => void; +} + +export default class Overview extends Component {} diff --git a/webapp/app/pods/components/project-settings/manage-languages/overview/item/component.js b/webapp/app/pods/components/project-settings/manage-languages/overview/item/component.js deleted file mode 100644 index 03d4ce5c..00000000 --- a/webapp/app/pods/components/project-settings/manage-languages/overview/item/component.js +++ /dev/null @@ -1,76 +0,0 @@ -import {computed} from '@ember/object'; -import {inject as service} from '@ember/service'; -import Component from '@ember/component'; - -// Attributes -// revision: Object -// permissions: Ember Object containing -// onPromoteMaster: Function -// onDelete: Function -export default Component.extend({ - intl: service('intl'), - - classNames: ['list-item'], - classNameBindings: [ - 'master:list-item--master', - 'isPromoting:list-item--promoting', - 'isDeleting:list-item--deleting', - 'deleted:list-item--deleted' - ], - - name: computed('revision.{name,language.name}', function() { - return this.revision.name || this.revision.language.name; - }), - - slug: computed('revision.{slug,language.slug}', function() { - return this.revision.slug || this.revision.language.slug; - }), - - isPromoting: false, - isDeleting: false, - isDeleted: false, - - actions: { - promoteRevision() { - /* eslint-disable no-alert */ - if ( - !window.confirm( - this.intl.t( - 'components.project_manage_languages_overview.promote_revision_master_confirm' - ) - ) - ) { - return; - } - /* eslint-enable no-alert */ - - this.set('isPromoting', true); - this.onPromoteMaster(this.revision).then(() => - this.set('isPromoting', false) - ); - }, - - deleteRevision() { - /* eslint-disable no-alert */ - if ( - !window.confirm( - this.intl.t( - 'components.project_manage_languages_overview.delete_revision_confirm' - ) - ) - ) - return; - /* eslint-enable no-alert */ - - this.set('isDeleting', true); - this.onDelete(this.revision) - .then(() => { - this.setProperties({ - isDeleting: false, - isDeleted: true - }); - }) - .catch(() => this.set('isDeleting', false)); - } - } -}); diff --git a/webapp/app/pods/components/project-settings/manage-languages/overview/item/component.ts b/webapp/app/pods/components/project-settings/manage-languages/overview/item/component.ts new file mode 100644 index 00000000..8878d3a8 --- /dev/null +++ b/webapp/app/pods/components/project-settings/manage-languages/overview/item/component.ts @@ -0,0 +1,73 @@ +import {action} from '@ember/object'; +import {inject as service} from '@ember/service'; +import Component from '@glimmer/component'; +import IntlService from 'ember-intl/services/intl'; +import {tracked} from '@glimmer/tracking'; + +interface Args { + master: any; + permissions: Record; + onPromoteMaster: (revision: any) => Promise; + onDelete: (revision: any) => Promise; + project: any; + revision: any; +} + +export default class OverviewItem extends Component { + @service('intl') + intl: IntlService; + + @tracked + isPromoting = false; + + @tracked + isDeleting = false; + + @tracked + isDeleted = false; + + get name() { + return this.args.revision.name || this.args.revision.language.name; + } + + get slug() { + return this.args.revision.slug || this.args.revision.language.slug; + } + + @action + async promoteRevision() { + const message = this.intl.t( + 'components.project_manage_languages_overview.promote_revision_master_confirm' + ); + + // eslint-disable-next-line no-alert + if (!window.confirm(message)) { + return; + } + + this.isPromoting = true; + + await this.args.onPromoteMaster(this.args.revision); + + this.isPromoting = false; + } + + @action + async deleteRevision() { + const message = this.intl.t( + 'components.project_manage_languages_overview.delete_revision_confirm' + ); + + // eslint-disable-next-line no-alert + if (!window.confirm(message)) { + return; + } + + this.isDeleting = true; + + await this.args.onDelete(this.args.revision); + + this.isDeleting = false; + this.isDeleted = true; + } +} diff --git a/webapp/app/pods/components/project-settings/manage-languages/overview/item/styles.scss b/webapp/app/pods/components/project-settings/manage-languages/overview/item/styles.scss new file mode 100644 index 00000000..8f2edf7f --- /dev/null +++ b/webapp/app/pods/components/project-settings/manage-languages/overview/item/styles.scss @@ -0,0 +1,117 @@ +@value transition-speed, transition-easing from 'accent-webapp/styles/variables/transitions'; +@value color-black, color-grey, color-green from 'accent-webapp/styles/variables/colors'; + +.list-item { + margin-bottom: 5px; + padding: 8px 2px; + border-bottom: 1px solid rgba(color-black, 0.1); + font-size: 14px; + + &.list-item--deleted { + display: none; + } + + &.list-item--deleting { + .list-item-actions { + pointer-events: all; + opacity: 1; + } + } + + &.list-item--master { + padding: 10px 2px; + margin-bottom: 10px; + border-bottom-color: rgba(color-black, 0.2); + font-size: 16px; + } + + &:focus, + &:hover { + .list-item-actions { + pointer-events: all; + opacity: 1; + } + + .list-item-header-edit { + opacity: 1; + transform: translateX(-24px); + } + } +} + +.list-item-header { + position: relative; +} + +.list-item-header-edit { + position: absolute; + left: 0; + top: 3px; + padding-right: 12px; + color: color-grey; + opacity: 0; + transform: translateX(-10px); + transition: 0.2s ease-in-out; + transition-property: opacity, transform, color; + + &:focus, + &:hover { + color: color-green; + color: var(--color-primary); + } + + svg { + width: 14px; + } +} + +.list-item-infos { + display: flex; + justify-content: space-between; + align-items: center; +} + +.list-item-infos-date { + font-size: 12px; + color: color-grey; +} + +.list-link { + display: inline-flex; + align-items: center; + text-decoration: none; + color: color-green; + color: var(--color-primary); + + &:focus, + &:hover { + text-decoration: underline; + } +} + +.list-link-small { + margin-left: 5px; + font-size: 11px; + opacity: 0.6; +} + +.list-item-actions { + display: flex; + opacity: 0; + pointer-events: none; + transition: transition-speed transition-easing; + transition-property: opacity; +} + +.masterBadge { + margin-left: 10px; +} + +.promoteSlaveButton { + padding: 2px 6px !important; + margin-right: 10px !important; +} + +.deleteSlaveButton { + padding: 2px 6px !important; +} diff --git a/webapp/app/pods/components/project-settings/manage-languages/overview/item/template.hbs b/webapp/app/pods/components/project-settings/manage-languages/overview/item/template.hbs index 1bedfa98..54efc64e 100644 --- a/webapp/app/pods/components/project-settings/manage-languages/overview/item/template.hbs +++ b/webapp/app/pods/components/project-settings/manage-languages/overview/item/template.hbs @@ -1,65 +1,69 @@ -
              - - {{inline-svg "assets/pencil.svg" class="item-edit-icon"}} - +
              +
              + + {{inline-svg "assets/pencil.svg" local-class="item-edit-icon"}} + - - {{this.name}} - - {{this.slug}} - - + + {{this.name}} + + {{this.slug}} + + - {{#if revision.isMaster}} - - {{t "components.project_manage_languages_overview.master_badge"}} - - {{/if}} -
              - -
              - {{#unless revision.isMaster}} -
              - {{t - "components.project_manage_languages_overview.revision_inserted_at_label" - }} - -
              - -
              - {{#if (get permissions "promote_slave")}} - - {{inline-svg "/assets/chevron-top.svg" class="button-icon"}} - {{t - "components.project_manage_languages_overview.promote_revision_master_button" - }} - - {{/if}} - - {{#if (get permissions "delete_slave")}} - - {{inline-svg "/assets/x.svg" class="button-icon"}} - {{t - "components.project_manage_languages_overview.delete_revision_button" - }} - - {{/if}} -
              - {{/unless}} + {{#if @revision.isMaster}} + + {{t "components.project_manage_languages_overview.master_badge"}} + + {{/if}} +
              + +
              + {{#unless @revision.isMaster}} +
              + {{t + "components.project_manage_languages_overview.revision_inserted_at_label" + }} + +
              + +
              + {{#if (get @permissions "promote_slave")}} + + {{inline-svg "/assets/chevron-top.svg" class="button-icon"}} + {{t + "components.project_manage_languages_overview.promote_revision_master_button" + }} + + {{/if}} + + {{#if (get @permissions "delete_slave")}} + + {{inline-svg "/assets/x.svg" class="button-icon"}} + {{t + "components.project_manage_languages_overview.delete_revision_button" + }} + + {{/if}} +
              + {{/unless}} +
              diff --git a/webapp/app/pods/components/project-settings/manage-languages/overview/styles.scss b/webapp/app/pods/components/project-settings/manage-languages/overview/styles.scss index 4384ee3d..41d9fe68 100644 --- a/webapp/app/pods/components/project-settings/manage-languages/overview/styles.scss +++ b/webapp/app/pods/components/project-settings/manage-languages/overview/styles.scss @@ -1,113 +1,3 @@ .list { margin: 15px 0 0; } - -.list-item { - margin-bottom: 5px; - padding: 8px 2px; - border-bottom: 1px solid rgba($color-black, 0.1); - font-size: 14px; - - &.list-item--deleted { - display: none; - } - - &.list-item--deleting { - .list-item-actions { - pointer-events: all; - opacity: 1; - } - } - - &.list-item--master { - padding: 10px 2px; - margin-bottom: 10px; - border-bottom-color: rgba($color-black, 0.2); - font-size: 16px; - } - - &:focus, - &:hover { - .list-item-actions { - pointer-events: all; - opacity: 1; - } - - .list-item-header-edit { - opacity: 1; - transform: translateX(-24px); - } - } -} - -.list-item-header { - position: relative; -} - -.list-item-header-edit { - position: absolute; - left: 0; - top: 3px; - padding-right: 12px; - color: $color-grey; - opacity: 0; - transform: translateX(-10px); - transition: 0.2s ease-in-out; - transition-property: opacity, transform, color; - - &:focus, - &:hover { - color: $color-green; - color: var(--color-primary); - } - - svg { - width: 14px; - } -} - -.list-item-infos { - display: flex; - justify-content: space-between; - align-items: center; -} - -.list-item-infos-date { - font-size: 12px; - color: $color-grey; -} - -.list-link { - display: inline-flex; - align-items: center; - text-decoration: none; - color: $color-green; - color: var(--color-primary); - - &:focus, - &:hover { - text-decoration: underline; - } -} - -.list-link-small { - margin-left: 5px; - font-size: 11px; - opacity: 0.6; -} - -.list-item-actions { - display: flex; - opacity: 0; - pointer-events: none; - transition: $transition-speed $transition-easing; - transition-property: opacity; -} - -.masterBadge { - margin-left: 10px; -} - -.promoteSlaveButton { - margin-right: 10px; -} diff --git a/webapp/app/pods/components/project-settings/manage-languages/overview/template.hbs b/webapp/app/pods/components/project-settings/manage-languages/overview/template.hbs index d5f4882e..c2d857ea 100644 --- a/webapp/app/pods/components/project-settings/manage-languages/overview/template.hbs +++ b/webapp/app/pods/components/project-settings/manage-languages/overview/template.hbs @@ -2,14 +2,14 @@ @title={{t "components.project_manage_languages_overview.list_languages"}} /> -
                - {{#each revisions key="id" as |revision|}} +
                  + {{#each @revisions key="id" as |revision|}} {{/each}} diff --git a/webapp/app/pods/components/project-settings/manage-languages/styles.scss b/webapp/app/pods/components/project-settings/manage-languages/styles.scss index 35160f5d..94955c8a 100644 --- a/webapp/app/pods/components/project-settings/manage-languages/styles.scss +++ b/webapp/app/pods/components/project-settings/manage-languages/styles.scss @@ -1,6 +1,17 @@ -& { +@value color-black, color-light-background, color-grey, color-error from 'accent-webapp/styles/variables/colors'; +@value screen-md from 'accent-webapp/styles/variables/dimensions'; + +.project-settings-manage-languages { display: flex; margin-top: 25px; + + :global(.ember-power-select-trigger) { + min-height: 31px; + max-width: 400px; + margin-bottom: 20px; + background: color-light-background; + border: 1px solid #eee; + } } .overview { @@ -17,7 +28,7 @@ margin: 15px 0 5px; font-weight: 600; font-size: 13px; - color: $color-black; + color: color-black; &:first-of-type { margin-top: 0; @@ -28,16 +39,16 @@ display: block; max-width: 700px; font-size: 12px; - color: rgba($color-black, 0.8); + color: rgba(color-black, 0.8); } .emptyLanguages { font-size: 14px; padding: 10px; - background: $color-light-background; + background: color-light-background; border: 1px solid #eee; border-radius: 3px; - color: $color-grey; + color: color-grey; } .createSlaveForm { @@ -48,19 +59,11 @@ margin-bottom: 10px; font-size: 12px; font-weight: bold; - color: $color-error; + color: color-error; } -.ember-power-select-trigger { - min-height: 31px; - max-width: 400px; - margin-bottom: 20px; - background: $color-light-background; - border: 1px solid #eee; -} - -@media (max-width: ($screen-md)) { - & { +@media (max-width: (screen-md)) { + .project-settings-manage-languages { flex-direction: column; } diff --git a/webapp/app/pods/components/project-settings/manage-languages/template.hbs b/webapp/app/pods/components/project-settings/manage-languages/template.hbs index 87f1074d..afeaee62 100644 --- a/webapp/app/pods/components/project-settings/manage-languages/template.hbs +++ b/webapp/app/pods/components/project-settings/manage-languages/template.hbs @@ -1,58 +1,60 @@ -
                  - +
                  +
                  + - {{#if (get permissions "create_slave")}} -
                  - {{#if errors}} -
                  - {{#each errors as |error|}} -
                • - {{error}} -
                • - {{/each}} -
                  - {{/if}} - -
                  - {{/if}} -
                  - -
                  -

                  - {{inline-svg "/assets/sync.svg" class="button-icon"}} - {{t "components.project_manage_languages.sync_explain_title"}} -

                  - -

                  - {{t "components.project_manage_languages.sync_explain_text"}} -

                  - -

                  - {{inline-svg "/assets/merge.svg" class="button-icon"}} - {{t "components.project_manage_languages.add_translations_explain_title"}} -

                  - -

                  - {{t "components.project_manage_languages.add_translations_explain_text"}} -

                  - -

                  - {{inline-svg "/assets/check.svg" class="button-icon"}} - {{t "components.project_manage_languages.conflicts_explain_title"}} -

                  - -

                  - {{t "components.project_manage_languages.conflicts_explain_text"}} -

                  + {{#if (get @permissions "create_slave")}} +
                  + {{#if @errors}} +
                  + {{#each @errors as |error|}} +
                • + {{error}} +
                • + {{/each}} +
                  + {{/if}} + +
                  + {{/if}} +
                  + +
                  +

                  + {{inline-svg "/assets/sync.svg" class="button-icon"}} + {{t "components.project_manage_languages.sync_explain_title"}} +

                  + +

                  + {{t "components.project_manage_languages.sync_explain_text"}} +

                  + +

                  + {{inline-svg "/assets/merge.svg" class="button-icon"}} + {{t "components.project_manage_languages.add_translations_explain_title"}} +

                  + +

                  + {{t "components.project_manage_languages.add_translations_explain_text"}} +

                  + +

                  + {{inline-svg "/assets/check.svg" class="button-icon"}} + {{t "components.project_manage_languages.conflicts_explain_title"}} +

                  + +

                  + {{t "components.project_manage_languages.conflicts_explain_text"}} +

                  +
                  diff --git a/webapp/app/pods/components/project-settings/title/component.js b/webapp/app/pods/components/project-settings/title/component.js deleted file mode 100644 index da5fcb72..00000000 --- a/webapp/app/pods/components/project-settings/title/component.js +++ /dev/null @@ -1,5 +0,0 @@ -import Component from '@ember/component'; - -export default Component.extend({ - tagName: 'h2' -}); diff --git a/webapp/app/pods/components/project-settings/title/component.ts b/webapp/app/pods/components/project-settings/title/component.ts new file mode 100644 index 00000000..92125739 --- /dev/null +++ b/webapp/app/pods/components/project-settings/title/component.ts @@ -0,0 +1,7 @@ +import Component from '@glimmer/component'; + +interface Args { + title: string; +} + +export default class Title extends Component {} diff --git a/webapp/app/pods/components/project-settings/title/styles.scss b/webapp/app/pods/components/project-settings/title/styles.scss index 0ba74934..a19344ae 100644 --- a/webapp/app/pods/components/project-settings/title/styles.scss +++ b/webapp/app/pods/components/project-settings/title/styles.scss @@ -1,5 +1,7 @@ -& { +@value color-black from 'accent-webapp/styles/variables/colors'; + +.project-settings-title { font-size: 18px; font-weight: bold; - color: $color-black; + color: color-black; } diff --git a/webapp/app/pods/components/project-settings/title/template.hbs b/webapp/app/pods/components/project-settings/title/template.hbs index ab17eedc..d311dd1c 100644 --- a/webapp/app/pods/components/project-settings/title/template.hbs +++ b/webapp/app/pods/components/project-settings/title/template.hbs @@ -1 +1,3 @@ -{{title}} +

                  + {{@title}} +

                  diff --git a/webapp/app/pods/components/projects-filters/component.js b/webapp/app/pods/components/projects-filters/component.js deleted file mode 100644 index 450d047d..00000000 --- a/webapp/app/pods/components/projects-filters/component.js +++ /dev/null @@ -1,30 +0,0 @@ -import {observer} from '@ember/object'; -import {inject as service} from '@ember/service'; -import {reads} from '@ember/object/computed'; -import Component from '@ember/component'; -import {run} from '@ember/runloop'; - -const DEBOUNCE_OFFSET = 500; // ms - -// Attributes: -// query: String -// onChangeQuery: Function -export default Component.extend({ - session: service(), - - debouncedQuery: reads('query'), - - queryDidChanges: observer('debouncedQuery', function() { - run.debounce(this, this._debounceQuery, DEBOUNCE_OFFSET); - }), - - _debounceQuery() { - this.onChangeQuery(this.debouncedQuery); - }, - - actions: { - submitForm() { - this._debounceQuery(); - } - } -}); diff --git a/webapp/app/pods/components/projects-filters/component.ts b/webapp/app/pods/components/projects-filters/component.ts new file mode 100644 index 00000000..a0e03158 --- /dev/null +++ b/webapp/app/pods/components/projects-filters/component.ts @@ -0,0 +1,48 @@ +import {action} from '@ember/object'; +import {inject as service} from '@ember/service'; +import Component from '@glimmer/component'; +import Session from 'accent-webapp/services/session'; +import {restartableTask} from 'ember-concurrency-decorators'; +import {timeout} from 'ember-concurrency'; +import {tracked} from '@glimmer/tracking'; + +const DEBOUNCE_OFFSET = 500; // ms + +interface Args { + permissions: any; + query: any; + onChangeQuery: (query: string) => void; +} + +export default class ProjectsFilter extends Component { + @service('session') + session: Session; + + @tracked + debouncedQuery: string = this.args.query; + + @action + setDebouncedQuery(event: Event) { + const target = event.target as HTMLInputElement; + + // eslint-disable-next-line @typescript-eslint/ban-ts-ignore + // @ts-ignore + this.debounceQuery.perform(target.value); + } + + @restartableTask + *debounceQuery(query: string) { + this.debouncedQuery = query; + + yield timeout(DEBOUNCE_OFFSET); + + this.args.onChangeQuery(query); + } + + @action + submitForm(event: Event) { + event.preventDefault(); + + this.args.onChangeQuery(this.debouncedQuery); + } +} diff --git a/webapp/app/pods/components/projects-filters/styles.scss b/webapp/app/pods/components/projects-filters/styles.scss index ff17c312..4cceb3c3 100644 --- a/webapp/app/pods/components/projects-filters/styles.scss +++ b/webapp/app/pods/components/projects-filters/styles.scss @@ -1,8 +1,12 @@ +@value color-grey, color-black, color-green from 'accent-webapp/styles/variables/colors'; +@value font-primary from 'accent-webapp/styles/variables/fonts'; +@value screen-lg from 'accent-webapp/styles/variables/dimensions'; + .filters { margin: 0 auto; padding: 15px 15px 10px; - max-width: $screen-lg; - background: none; + max-width: screen-lg; + background: none !important; } .filters-wrapper { @@ -17,7 +21,7 @@ .totalEntries { margin-left: 20px; - color: $color-grey; + color: color-grey; font-size: 13px; font-style: italic; } @@ -33,7 +37,7 @@ } .createProjectButton { - margin-left: 15px; + margin-left: 15px !important; } .input { @@ -41,25 +45,25 @@ width: 100%; padding: 7px 7px 7px 30px; font-size: 14px; - font-family: $font-primary; - color: $color-black; + font-family: font-primary; + color: color-black; &::placeholder { - color: $color-grey; + color: color-grey; } &:focus { - border-color: $color-green; + border-color: color-green; } } .filters-meta { margin-top: 7px; font-size: 14px; - color: $color-grey; + color: color-grey; } .filters-meta-keyword { font-style: italic; - color: $color-green; + color: color-green; } diff --git a/webapp/app/pods/components/projects-filters/template.hbs b/webapp/app/pods/components/projects-filters/template.hbs index 1692acda..e24eff36 100644 --- a/webapp/app/pods/components/projects-filters/template.hbs +++ b/webapp/app/pods/components/projects-filters/template.hbs @@ -1,33 +1,35 @@ -
                  -
                  -
                  - {{inline-svg "/assets/search.svg" class="search-icon"}} - + +
                  + {{inline-svg "/assets/search.svg" local-class="search-icon"}} + + value={{this.debouncedQuery}} + >
                  - {{#unless debouncedQuery}} - {{#if (get permissions "create_project")}} + {{#unless this.debouncedQuery}} + {{#if (get @permissions "create_project")}} - {{inline-svg "/assets/add.svg" class="button-icon"}} + {{inline-svg "/assets/add.svg" local-class="button-icon"}} {{t "components.projects_filters.new_project"}} {{/if}} {{/unless}} -
                  - {{#if query}} +
                  + {{#if @query}} {{t "components.projects_filters.searching_for"}} - - {{query}} + + {{@query}} {{/if}}
                  diff --git a/webapp/app/pods/components/projects-header/component.js b/webapp/app/pods/components/projects-header/component.js deleted file mode 100644 index 7fbcd8a9..00000000 --- a/webapp/app/pods/components/projects-header/component.js +++ /dev/null @@ -1,64 +0,0 @@ -import {computed, observer} from '@ember/object'; -import {run} from '@ember/runloop'; -import {inject as service} from '@ember/service'; -import Component from '@ember/component'; - -const DEBOUNCE_OFFSET = 500; // ms - -// Attributes: -// session: Service -export default Component.extend({ - tagName: 'header', - session: service('session'), - router: service('router'), - globalState: service('global-state'), - classNameBindings: ['project:withProject'], - - debouncedQuery: '', - - selectedRevision: computed( - 'globalState.revision', - 'project.revisions.[]', - function() { - const selected = this.globalState.revision; - - if ( - selected && - this.project.revisions.map(({id}) => id).includes(selected) - ) { - return selected; - } - - if (!this.project.revisions) return; - return this.project.revisions[0].id; - } - ), - - queryDidChanges: observer('debouncedQuery', function() { - if (!this.debouncedQuery) return; - run.debounce(this, this._debounceQuery, DEBOUNCE_OFFSET); - }), - - _debounceQuery() { - const query = this.debouncedQuery; - this.set('debouncedQuery', ''); - const input = this.element.getElementsByTagName('input')[0]; - input && input.blur(); - - this.router.transitionTo( - 'logged-in.project.revision.translations', - this.project.id, - this.selectedRevision, - { - queryParams: {query} - } - ); - }, - - actions: { - logout() { - this.session.logout(); - window.location = '/'; - } - } -}); diff --git a/webapp/app/pods/components/projects-header/component.ts b/webapp/app/pods/components/projects-header/component.ts new file mode 100644 index 00000000..08acdc1e --- /dev/null +++ b/webapp/app/pods/components/projects-header/component.ts @@ -0,0 +1,78 @@ +import {action} from '@ember/object'; +import {inject as service} from '@ember/service'; +import Component from '@glimmer/component'; +import Session from 'accent-webapp/services/session'; +import RouterService from '@ember/routing/router-service'; +import GlobalState from 'accent-webapp/services/global-state'; +import {tracked} from '@glimmer/tracking'; +import {restartableTask} from 'ember-concurrency-decorators'; +import {timeout} from 'ember-concurrency'; + +const DEBOUNCE_OFFSET = 500; // ms + +interface Args { + session: any; + project?: any; +} + +export default class ProjectsHeader extends Component { + @service('session') + session: Session; + + @service('router') + router: RouterService; + + @service('global-state') + globalState: GlobalState; + + @tracked + debouncedQuery = ''; + + get selectedRevision() { + const selected = this.globalState.revision; + + if ( + selected && + this.args.project.revisions + .map(({id}: {id: string}) => id) + .includes(selected) + ) { + return selected; + } + + if (!this.args.project.revisions) return; + return this.args.project.revisions[0].id; + } + + @action + setDebouncedQuery(event: Event) { + const target = event.target as HTMLInputElement; + + // eslint-disable-next-line @typescript-eslint/ban-ts-ignore + // @ts-ignore + this.debounceQuery.perform(target.value); + } + + @restartableTask + *debounceQuery(query: string) { + this.debouncedQuery = query; + + yield timeout(DEBOUNCE_OFFSET); + + this.router.transitionTo( + 'logged-in.project.revision.translations', + this.args.project.id, + this.selectedRevision, + { + queryParams: {query}, + } + ); + } + + @action + logout() { + this.session.logout(); + + window.location.href = '/'; + } +} diff --git a/webapp/app/pods/components/projects-header/styles.scss b/webapp/app/pods/components/projects-header/styles.scss index 17faa2b5..b0fa5712 100644 --- a/webapp/app/pods/components/projects-header/styles.scss +++ b/webapp/app/pods/components/projects-header/styles.scss @@ -1,15 +1,19 @@ -& { +@value transition-speed, transition-easing from 'accent-webapp/styles/variables/transitions'; +@value color-black, color-grey from 'accent-webapp/styles/variables/colors'; +@value screen-lg, screen-md, screen-sm from 'accent-webapp/styles/variables/dimensions'; + +.projects-header { padding: 64px 0 20px; background-image: linear-gradient(0, transparent, #eee); } -&.withProject { +.projects-header.withProject { padding-top: 59px; .applicationLogo { position: absolute; padding-right: 10px; - transition: $transition-speed $transition-easing; + transition: transition-speed transition-easing; transition-property: transform, opacity; transform: translate3d(0, 0, 0); opacity: 0; @@ -32,7 +36,7 @@ align-items: center; justify-content: space-between; margin: 0 auto; - max-width: $screen-lg; + max-width: screen-lg; padding: 0 15px; width: 100%; } @@ -59,7 +63,7 @@ .applicationLogo-back, .applicationLogo-image { display: block; - transition: 0.7s $transition-easing; + transition: 0.7s transition-easing; transition-property: transform; width: 25px; height: 25px; @@ -81,7 +85,7 @@ text-decoration: none; font-size: 18px; font-weight: 700; - color: $color-black; + color: color-black; } .project { @@ -91,7 +95,7 @@ align-items: center; font-size: 18px; font-weight: 700; - color: $color-black; + color: color-black; text-decoration: none; } @@ -141,36 +145,36 @@ .search-input { padding: 10px 5px 10px 28px; border-radius: 50px; - border: 1px solid lighten($color-grey, 15%); - transition: 0.2s $transition-easing; + border: 1px solid lighten(color-grey, 15%); + transition: 0.2s transition-easing; transition-property: padding, border, box-shadow; - box-shadow: inset 0 1px 2px rgba($color-black, 0.1); + box-shadow: inset 0 1px 2px rgba(color-black, 0.1); &::placeholder { - color: lighten($color-grey, 5%); + color: lighten(color-grey, 5%); } &:hover { - border-color: $color-grey; + border-color: color-grey; } &:focus { outline: none; border-color: var(--color-primary); padding-right: 40px; - box-shadow: inset 0 1px 2px #fff; + box-shadow: inset 0 1px 2px #fff, 0 1px 8px rgba(color-black, 0.09); } } -@media (max-width: ($screen-md)) { - & { +@media (max-width: (screen-md)) { + .projects-header { padding: 10px 0; .content { padding: 0 30px; } - &.withProject { + .projects-header.withProject { padding: 10px 0; } } @@ -180,7 +184,7 @@ } } -@media (max-width: ($screen-sm)) { +@media (max-width: (screen-sm)) { .applicationLogo-image { width: 18px; height: 18px; @@ -190,7 +194,7 @@ font-size: 11px; } - .button { + :global(.button) { padding: 3px 7px 4px; font-size: 11px; } diff --git a/webapp/app/pods/components/projects-header/template.hbs b/webapp/app/pods/components/projects-header/template.hbs index 57b1c6fb..b8c41c70 100644 --- a/webapp/app/pods/components/projects-header/template.hbs +++ b/webapp/app/pods/components/projects-header/template.hbs @@ -1,59 +1,62 @@ -
                  -
                  - {{#if project}} - +
                  +
                  +
                  + {{#if @project}} + + {{inline-svg + "assets/chevron-left.svg" + local-class="applicationLogo-back" + }} + - -
                  + + {{#if @session.credentials.user}} +
                  + {{#if @session.credentials.user.pictureUrl}} + + {{/if}} + + + {{@session.credentials.user.fullname}} - {{project.name}} - - - - {{else}} - {{/if}}
                  - - {{#if session.credentials.user}} -
                  - {{#if session.credentials.user.pictureUrl}} - - {{/if}} - - - {{session.credentials.user.fullname}} - - - {{#unless project}} - - {{/unless}} -
                  - {{/if}} -
                  +
                  diff --git a/webapp/app/pods/components/projects-list/component.js b/webapp/app/pods/components/projects-list/component.js deleted file mode 100644 index d60a9cfa..00000000 --- a/webapp/app/pods/components/projects-list/component.js +++ /dev/null @@ -1,9 +0,0 @@ -import Component from '@ember/component'; - -// Attributes: -// projects: Array of -// permissions: Ember Object containing -// query: String -export default Component.extend({ - tagName: 'ul' -}); diff --git a/webapp/app/pods/components/projects-list/component.ts b/webapp/app/pods/components/projects-list/component.ts new file mode 100644 index 00000000..f85ee67e --- /dev/null +++ b/webapp/app/pods/components/projects-list/component.ts @@ -0,0 +1,9 @@ +import Component from '@glimmer/component'; + +interface Args { + permissions: Record; + projects: any; + query: any; +} + +export default class ProjectsList extends Component {} diff --git a/webapp/app/pods/components/projects-list/item/component.js b/webapp/app/pods/components/projects-list/item/component.js deleted file mode 100644 index e7f3b1cb..00000000 --- a/webapp/app/pods/components/projects-list/item/component.js +++ /dev/null @@ -1,56 +0,0 @@ -import Component from '@ember/component'; -import {computed} from '@ember/object'; -import {readOnly, lt, gte} from '@ember/object/computed'; -import percentage from 'accent-webapp/component-helpers/percentage'; - -const LOW_PERCENTAGE = 50; -const HIGH_PERCENTAGE = 90; - -// Attributes: -// project: Object -export default Component.extend({ - revisions: readOnly('project.revisions'), - - lowPercentage: lt('correctedKeysPercentage', LOW_PERCENTAGE), // Lower than low percentage - mediumPercentage: gte('correctedKeysPercentage', LOW_PERCENTAGE), // higher or equal than low percentage - highPercentage: gte('correctedKeysPercentage', HIGH_PERCENTAGE), // higher or equal than high percentage - - classNameBindings: ['lowPercentage', 'mediumPercentage', 'highPercentage'], - - colors: computed('project.mainColor', function() { - return ` - .projectId-${this.project.id} { - --color-primary: ${this.project.mainColor}; - } - `; - }), - - totalStrings: computed('revisions.[]', function() { - return this.revisions.reduce((memo, revision) => { - return memo + revision.translationsCount; - }, 0); - }), - - totalConflicts: computed('revisions.[]', function() { - return this.revisions.reduce((memo, revision) => { - return memo + revision.conflictsCount; - }, 0); - }), - - totalReviewed: computed('revisions.[]', function() { - return this.revisions.reduce((memo, revision) => { - return memo + (revision.translationsCount - revision.conflictsCount); - }, 0); - }), - - correctedKeysPercentage: computed( - 'totalConflicts', - 'totalStrings', - function() { - return percentage( - this.totalStrings - this.totalConflicts, - this.totalStrings - ); - } - ) -}); diff --git a/webapp/app/pods/components/projects-list/item/component.ts b/webapp/app/pods/components/projects-list/item/component.ts new file mode 100644 index 00000000..daaf5e91 --- /dev/null +++ b/webapp/app/pods/components/projects-list/item/component.ts @@ -0,0 +1,51 @@ +import Component from '@glimmer/component'; +import {readOnly, lt, gte} from '@ember/object/computed'; +import percentage from 'accent-webapp/component-helpers/percentage'; + +const LOW_PERCENTAGE = 50; +const HIGH_PERCENTAGE = 90; + +interface Args { + project: any; +} + +export default class ProjectsListItem extends Component { + @readOnly('args.project') + project: any; + + @lt('correctedKeysPercentage', LOW_PERCENTAGE) + lowPercentage: boolean; // Lower than low percentage + + @gte('correctedKeysPercentage', LOW_PERCENTAGE) + mediumPercentage: boolean; // higher or equal than low percentage + + @gte('correctedKeysPercentage', HIGH_PERCENTAGE) + highPercentage: boolean; // higher or equal than high percentage + + get colors() { + return ` + .projectId-${this.project.id} { + --color-primary: ${this.project.mainColor}; + } + `; + } + + get totalStrings() { + return this.project.translationsCount; + } + + get totalConflicts() { + return this.project.conflictsCount; + } + + get totalReviewed() { + return this.project.translationsCount - this.project.conflictsCount; + } + + get correctedKeysPercentage() { + return percentage( + this.totalStrings - this.totalConflicts, + this.totalStrings + ); + } +} diff --git a/webapp/app/pods/components/projects-list/item/styles.scss b/webapp/app/pods/components/projects-list/item/styles.scss index 59d594eb..2df1dfdb 100644 --- a/webapp/app/pods/components/projects-list/item/styles.scss +++ b/webapp/app/pods/components/projects-list/item/styles.scss @@ -1,44 +1,48 @@ -&.low-percentage { +@value transition-speed, transition-easing from 'accent-webapp/styles/variables/transitions'; +@value color-error, color-warning, color-success, color-black, color-light-background, color-grey from 'accent-webapp/styles/variables/colors'; +@value font-monospace from 'accent-webapp/styles/variables/fonts'; + +.projects-list-item.low-percentage { .language-reviewedPercentage { - color: $color-error; + color: color-error; } .progress { - background: $color-error; + color: color-error; } } -&.medium-percentage { +.projects-list-item.medium-percentage { .language-reviewedPercentage { - color: $color-warning; + color: color-warning; } .progress { - background: $color-warning; + color: color-warning; } } -&.high-percentage { +.projects-list-item.high-percentage { .language-reviewedPercentage { - color: $color-success; + color: color-success; } .progress { - background: $color-success; + color: color-success; } } -& { +.projects-list-item { padding: 12px 15px; - transition: $transition-speed $transition-easing; + transition: transition-speed transition-easing; transition-property: background; border-radius: 3px; - box-shadow: 0 2px 4px rgba($color-black, 0.15); - color: $color-black; + box-shadow: 0 2px 4px rgba(color-black, 0.15); + color: color-black; &:focus, &:hover { - background: $color-light-background; + background: color-light-background; .projectName { color: var(--color-primary); @@ -53,7 +57,7 @@ } .projectName { - transition: $transition-speed $transition-easing; + transition: transition-speed transition-easing; transition-property: color; font-weight: 600; font-size: 18px; @@ -74,7 +78,7 @@ .projectUpdates { display: block; - color: $color-grey; + color: color-grey; font-style: italic; font-size: 11px; } @@ -93,8 +97,8 @@ .numberStat-totals { padding: 2px 7px 1px; border-radius: 3px; - background: lighten($color-grey, 25%); - color: $color-grey; + background: lighten(color-grey, 25%); + color: color-grey; font-size: 12px; - font-family: $font-monospace; + font-family: font-monospace; } diff --git a/webapp/app/pods/components/projects-list/item/template.hbs b/webapp/app/pods/components/projects-list/item/template.hbs index 12a91f4b..9e6e20c9 100644 --- a/webapp/app/pods/components/projects-list/item/template.hbs +++ b/webapp/app/pods/components/projects-list/item/template.hbs @@ -1,37 +1,40 @@ -
                  - {{#if project.logo}} - - {{/if}} - - - {{project.name}} - - -
                  - -
                  - - {{#if project.lastSyncedAt}} - - {{t "components.projects_list.last_synced_at_label"}} - +
                  +
                  + {{#if @project.logo}} + + - {{else}} - {{t "components.projects_list.never_synced"}} {{/if}} - - - {{totalStrings}} - {{t "components.dashboard_revisions.strings"}} - + + {{@project.name}} + + +
                  + +
                  + + {{#if @project.lastSyncedAt}} + + {{t "components.projects_list.last_synced_at_label"}} + + + + + {{else}} + {{t "components.projects_list.never_synced"}} + {{/if}} + + + + {{this.totalStrings}} + {{t "components.dashboard_revisions.strings"}} + +
                  + +
                  + +
                  - - diff --git a/webapp/app/pods/components/projects-list/styles.scss b/webapp/app/pods/components/projects-list/styles.scss index d53c4273..824589f3 100644 --- a/webapp/app/pods/components/projects-list/styles.scss +++ b/webapp/app/pods/components/projects-list/styles.scss @@ -1,9 +1,11 @@ -& { +@value screen-lg, screen-md from 'accent-webapp/styles/variables/dimensions'; + +.projects-list { display: flex; flex-wrap: wrap; padding: 0 5px; margin: 0 auto; - max-width: $screen-lg; + max-width: screen-lg; position: relative; margin-top: 20px; } @@ -20,7 +22,7 @@ margin: 0 10px 30px; } -@media (max-width: ($screen-md)) { +@media (max-width: (screen-md)) { .item { max-width: none; width: 100%; diff --git a/webapp/app/pods/components/projects-list/template.hbs b/webapp/app/pods/components/projects-list/template.hbs index 9f6af41e..5754e2f3 100644 --- a/webapp/app/pods/components/projects-list/template.hbs +++ b/webapp/app/pods/components/projects-list/template.hbs @@ -1,29 +1,30 @@ -{{#each projects key="id" as |project|}} -
                • - - - -
                • -{{else if query}} - -{{else}} - - {{inline-svg "assets/empty.svg" class="icon"}} - {{t "components.projects_list.no_projects"}} - {{#if (get permissions "create_project")}} - - {{/if}} - -{{/each}} - +
                    + {{#each @projects key="id" as |project|}} +
                  • + + + +
                  • + {{else if @query}} + + {{else}} + + {{inline-svg "assets/empty.svg" class="icon"}} + {{t "components.projects_list.no_projects"}} + {{#if (get @permissions "create_project")}} +
                    + + {{t "components.projects_list.maybe_create_one"}} + +
                    + {{/if}} +
                    + {{/each}} +
                  diff --git a/webapp/app/pods/components/quick-submit-textarea/component.js b/webapp/app/pods/components/quick-submit-textarea/component.js deleted file mode 100644 index 73584a49..00000000 --- a/webapp/app/pods/components/quick-submit-textarea/component.js +++ /dev/null @@ -1,23 +0,0 @@ -import TextArea from '@ember/component/text-area'; - -const ENTER_KEY = 13; - -export default TextArea.extend({ - focusIn() { - if (this.onFocus) this.onFocus(); - }, - - focusOut() { - if (this.onBlur) this.onBlur(); - }, - - keyUp(event) { - if (this.onKeyUp) this.onKeyUp(event); - }, - - keyDown(event) { - if (event.which === ENTER_KEY && (event.metaKey || event.ctrlKey)) { - if (this.onSubmit) this.onSubmit(); - } - } -}); diff --git a/webapp/app/pods/components/quick-submit-textarea/component.ts b/webapp/app/pods/components/quick-submit-textarea/component.ts new file mode 100644 index 00000000..1164f791 --- /dev/null +++ b/webapp/app/pods/components/quick-submit-textarea/component.ts @@ -0,0 +1,36 @@ +import Component from '@glimmer/component'; +import {action} from '@ember/object'; + +const ENTER_KEY = 13; + +interface Args { + value: string | null | undefined; + onFocus?: () => void; + onBlur?: () => void; + onKeyUp?: (event: KeyboardEvent) => void; + onSubmit?: () => void; +} + +export default class QuickSubmitTextarea extends Component { + @action + blur() { + this.args.onBlur && this.args.onBlur(); + } + + @action + focus() { + this.args.onFocus && this.args.onFocus(); + } + + @action + keyUp(event: KeyboardEvent) { + this.args.onKeyUp && this.args.onKeyUp(event); + } + + @action + keyDown(event: KeyboardEvent) { + if (event.which === ENTER_KEY && (event.metaKey || event.ctrlKey)) { + this.args.onSubmit && this.args.onSubmit(); + } + } +} diff --git a/webapp/app/pods/components/quick-submit-textarea/template.hbs b/webapp/app/pods/components/quick-submit-textarea/template.hbs new file mode 100644 index 00000000..e73e45c3 --- /dev/null +++ b/webapp/app/pods/components/quick-submit-textarea/template.hbs @@ -0,0 +1,7 @@ + diff --git a/webapp/app/pods/components/quick-submit-textfield/component.js b/webapp/app/pods/components/quick-submit-textfield/component.js deleted file mode 100644 index ffdadbd2..00000000 --- a/webapp/app/pods/components/quick-submit-textfield/component.js +++ /dev/null @@ -1,23 +0,0 @@ -import TextField from '@ember/component/text-field'; - -const ENTER_KEY = 13; - -export default TextField.extend({ - focusIn() { - if (this.onFocus) this.onFocus(); - }, - - focusOut() { - if (this.onBlur) this.onBlur(); - }, - - keyUp(_event) { - if (this.onKeyUp) this.onKeyUp(); - }, - - keyDown(event) { - if (event.which === ENTER_KEY && (event.metaKey || event.ctrlKey)) { - if (this.onSubmit) this.onSubmit(); - } - } -}); diff --git a/webapp/app/pods/components/quick-submit-textfield/component.ts b/webapp/app/pods/components/quick-submit-textfield/component.ts new file mode 100644 index 00000000..9683ad30 --- /dev/null +++ b/webapp/app/pods/components/quick-submit-textfield/component.ts @@ -0,0 +1,36 @@ +import Component from '@glimmer/component'; +import {action} from '@ember/object'; + +const ENTER_KEY = 13; + +interface Args { + value: string | null | undefined; + onFocus?: () => void; + onBlur?: () => void; + onKeyUp?: (event: KeyboardEvent) => void; + onSubmit?: () => void; +} + +export default class QuickSubmitTextfield extends Component { + @action + blur() { + this.args.onBlur && this.args.onBlur(); + } + + @action + focus() { + this.args.onFocus && this.args.onFocus(); + } + + @action + keyUp(event: KeyboardEvent) { + this.args.onKeyUp && this.args.onKeyUp(event); + } + + @action + keyDown(event: KeyboardEvent) { + if (event.which === ENTER_KEY && (event.metaKey || event.ctrlKey)) { + this.args.onSubmit && this.args.onSubmit(); + } + } +} diff --git a/webapp/app/pods/components/quick-submit-textfield/template.hbs b/webapp/app/pods/components/quick-submit-textfield/template.hbs new file mode 100644 index 00000000..62b0cbcf --- /dev/null +++ b/webapp/app/pods/components/quick-submit-textfield/template.hbs @@ -0,0 +1,9 @@ + diff --git a/webapp/app/pods/components/related-translations-list/component.js b/webapp/app/pods/components/related-translations-list/component.js deleted file mode 100644 index b0edc8fe..00000000 --- a/webapp/app/pods/components/related-translations-list/component.js +++ /dev/null @@ -1,8 +0,0 @@ -import Component from '@ember/component'; - -// Attributes: -// project: Object -// translations: Array of object -export default Component.extend({ - tagName: 'ul' -}); diff --git a/webapp/app/pods/components/related-translations-list/component.ts b/webapp/app/pods/components/related-translations-list/component.ts new file mode 100644 index 00000000..aa0f83c2 --- /dev/null +++ b/webapp/app/pods/components/related-translations-list/component.ts @@ -0,0 +1,14 @@ +import Component from '@glimmer/component'; +import {action} from '@ember/object'; + +interface Args { + project: any; + translations: any; + onUpdateText: (translation: any, text: string) => Promise; +} +export default class RelatedTranslationsList extends Component { + @action + focusTextarea(element: HTMLElement) { + element.querySelector('textarea')?.focus(); + } +} diff --git a/webapp/app/pods/components/related-translations-list/item/component.js b/webapp/app/pods/components/related-translations-list/item/component.js deleted file mode 100644 index e5090fc7..00000000 --- a/webapp/app/pods/components/related-translations-list/item/component.js +++ /dev/null @@ -1,34 +0,0 @@ -import {computed} from '@ember/object'; -import {reads, not} from '@ember/object/computed'; -import Component from '@ember/component'; - -// Attributes: -// translation: Object -// onUpdateText: Fucntion -export default Component.extend({ - tagName: 'li', - - isSaving: false, - showSaveButton: not('translation.isRemoved'), - editText: reads('translation.correctedText'), - - revisionName: computed( - 'translation.revision.{name,language.name}', - function() { - return ( - this.translation.revision.name || - this.translation.revision.language.name - ); - } - ), - - actions: { - save() { - this.set('isSaving', true); - - this.onUpdateText(this.translation, this.editText).then(() => { - this.set('isSaving', false); - }); - } - } -}); diff --git a/webapp/app/pods/components/related-translations-list/item/component.ts b/webapp/app/pods/components/related-translations-list/item/component.ts new file mode 100644 index 00000000..b2ef0f5e --- /dev/null +++ b/webapp/app/pods/components/related-translations-list/item/component.ts @@ -0,0 +1,39 @@ +import {action} from '@ember/object'; +import {readOnly, not} from '@ember/object/computed'; +import Component from '@glimmer/component'; +import {tracked} from '@glimmer/tracking'; + +interface Args { + onUpdateText: (translation: any, editText: string) => Promise; + isInEditMode: boolean; + showEditButton: boolean; + translation: any; + project: any; +} + +export default class RelatedTranslationsListItem extends Component { + @tracked + isSaving = false; + + @not('args.translation.isRemoved') + showSaveButton: boolean; + + @readOnly('args.translation.correctedText') + editText: string; + + get revisionName() { + return ( + this.args.translation.revision.name || + this.args.translation.revision.language.name + ); + } + + @action + async save() { + this.isSaving = true; + + await this.args.onUpdateText(this.args.translation, this.editText); + + this.isSaving = false; + } +} diff --git a/webapp/app/pods/components/related-translations-list/item/styles.scss b/webapp/app/pods/components/related-translations-list/item/styles.scss index 21eb62d5..921ceee8 100644 --- a/webapp/app/pods/components/related-translations-list/item/styles.scss +++ b/webapp/app/pods/components/related-translations-list/item/styles.scss @@ -1,9 +1,11 @@ -& { +@value color-grey, color-black, color-green from 'accent-webapp/styles/variables/colors'; + +.related-translations-list-item { position: relative; &.empty { padding: 35px 10px; - color: $color-grey; + color: color-grey; font-size: 13px; font-style: italic; text-align: center; @@ -18,21 +20,21 @@ display: flex; align-items: center; margin-right: 4px; - color: rgba($color-black, 0.7); + color: rgba(color-black, 0.7); text-decoration: none; font-weight: normal; font-size: 12px; &:focus, &:hover { - color: $color-green; + color: color-green; color: var(--color-primary); } } .updatedAt { margin: 0 6px; - color: $color-grey; + color: color-grey; font-size: 11px; font-style: italic; } @@ -57,16 +59,16 @@ .textEdit-cancel { margin-right: 20px; - color: $color-grey; + color: color-grey; font-size: 12px; cursor: pointer; } .textEdit-button { - padding: 1px 9px; - position: absolute; - top: 41px; - right: 14px; + padding: 1px 9px !important; + position: absolute !important; + top: 41px !important; + right: 14px !important; } .textEdit-actions { diff --git a/webapp/app/pods/components/related-translations-list/item/template.hbs b/webapp/app/pods/components/related-translations-list/item/template.hbs index a0bae76f..2d1853f5 100644 --- a/webapp/app/pods/components/related-translations-list/item/template.hbs +++ b/webapp/app/pods/components/related-translations-list/item/template.hbs @@ -1,70 +1,73 @@ -
                  -
                  - - {{revisionName}} +
                • +
                  +
                  + + {{this.revisionName}} - - {{t "components.related_translations_list.last_updated_label"}} - - - + + {{t "components.related_translations_list.last_updated_label"}} + + + +
                  + +
                  + {{#unless @translation.isRemoved}} + {{#if @translation.commentsCount}} + + + {{t + "components.related_translations_list.comments_label" + count=@translation.commentsCount + }} + + + {{/if}} + + {{#if @translation.isConflicted}} + + + {{t "components.related_translations_list.conflicted_label"}} + + + {{/if}} + {{/unless}} +
                  -
                  - {{#unless translation.isRemoved}} - {{#if translation.commentsCount}} - - - {{t - "components.related_translations_list.comments_label" - count=translation.commentsCount - }} - - - {{/if}} +
                  + - {{#if translation.isConflicted}} - - - {{t "components.related_translations_list.conflicted_label"}} - - - {{/if}} - {{/unless}} + {{#if showSaveButton}} + + {{t "components.related_translations_list.save_button"}} + + {{/if}}
                  -
                  - -
                  - - - {{#if showSaveButton}} - - {{t "components.related_translations_list.save_button"}} - - {{/if}} -
                  +
                • diff --git a/webapp/app/pods/components/related-translations-list/styles.scss b/webapp/app/pods/components/related-translations-list/styles.scss index 8c21ba75..2bad2198 100644 --- a/webapp/app/pods/components/related-translations-list/styles.scss +++ b/webapp/app/pods/components/related-translations-list/styles.scss @@ -1,10 +1,12 @@ -& { +@value color-grey from 'accent-webapp/styles/variables/colors'; + +.related-translations-list { margin-top: 30px; } .emptyItem { margin: 60px 0 15px; - color: $color-grey; + color: color-grey; font-size: 13px; font-style: italic; text-align: center; diff --git a/webapp/app/pods/components/related-translations-list/template.hbs b/webapp/app/pods/components/related-translations-list/template.hbs index b7dcc3e1..80c15d44 100644 --- a/webapp/app/pods/components/related-translations-list/template.hbs +++ b/webapp/app/pods/components/related-translations-list/template.hbs @@ -1,24 +1,26 @@ -{{#each translations key="id" as |translation|}} - -{{else}} -
                • -

                  - {{t "components.related_translations_list.no_related_translations"}} -

                  +
                    + {{#each @translations key="id" as |translation|}} + + {{else}} +
                  • +

                    + {{t "components.related_translations_list.no_related_translations"}} +

                    - - {{inline-svg "assets/add.svg" class="button-icon"}} - {{t "components.related_translations_list.new_language_link"}} - -
                  • -{{/each}} + + {{inline-svg "assets/add.svg" class="button-icon"}} + {{t "components.related_translations_list.new_language_link"}} + + + {{/each}} +
                  diff --git a/webapp/app/pods/components/removed-translation-edit/component.js b/webapp/app/pods/components/removed-translation-edit/component.js deleted file mode 100644 index 56bcd0e5..00000000 --- a/webapp/app/pods/components/removed-translation-edit/component.js +++ /dev/null @@ -1,4 +0,0 @@ -import Component from '@ember/component'; - -// Attributes: -export default Component.extend(); diff --git a/webapp/app/pods/components/removed-translation-edit/component.ts b/webapp/app/pods/components/removed-translation-edit/component.ts new file mode 100644 index 00000000..cb56c961 --- /dev/null +++ b/webapp/app/pods/components/removed-translation-edit/component.ts @@ -0,0 +1,7 @@ +import Component from '@glimmer/component'; + +interface Args { + translation: any; +} + +export default class RemovedTranslationEdit extends Component {} diff --git a/webapp/app/pods/components/removed-translation-edit/styles.scss b/webapp/app/pods/components/removed-translation-edit/styles.scss index e0df080e..de18c559 100644 --- a/webapp/app/pods/components/removed-translation-edit/styles.scss +++ b/webapp/app/pods/components/removed-translation-edit/styles.scss @@ -1,3 +1,6 @@ +@value color-grey from 'accent-webapp/styles/variables/colors'; +@value font-monospace from 'accent-webapp/styles/variables/fonts'; + .text { width: 100%; min-height: 140px; @@ -5,16 +8,16 @@ padding: 15px; resize: vertical; outline: 0; - border: 1px solid lighten($color-grey, 20%); + border: 1px solid lighten(color-grey, 20%); background: darken(#fff, 2%); - font-family: $font-monospace; + font-family: font-monospace; font-size: 12px; } .label { display: block; margin-top: 10px; - color: $color-grey; + color: color-grey; font-size: 13px; font-style: italic; text-align: right; diff --git a/webapp/app/pods/components/removed-translation-edit/template.hbs b/webapp/app/pods/components/removed-translation-edit/template.hbs index 6b241291..ab307d51 100644 --- a/webapp/app/pods/components/removed-translation-edit/template.hbs +++ b/webapp/app/pods/components/removed-translation-edit/template.hbs @@ -1,5 +1,5 @@ -
                  {{translation.correctedText}}
                  +
                  {{@translation.correctedText}}
                  - + {{t "components.removed_translation_edit.cant_edit"}} diff --git a/webapp/app/pods/components/resource-pagination/component.js b/webapp/app/pods/components/resource-pagination/component.js deleted file mode 100644 index 7282696e..00000000 --- a/webapp/app/pods/components/resource-pagination/component.js +++ /dev/null @@ -1,26 +0,0 @@ -import {or, readOnly, not} from '@ember/object/computed'; -import Component from '@ember/component'; - -// Attributes: -// meta: Object containing meta infos from a model -// onSelectPage: Function -export default Component.extend({ - showPagination: or('meta.{nextPage,previousPage}'), - - hasPrevious: readOnly('meta.previousPage'), - hasNext: readOnly('meta.nextPage'), - disabledPrevious: not('hasPrevious'), - disabledNext: not('hasNext'), - - actions: { - goToNextPage() { - if (!this.meta.nextPage) return; - this.onSelectPage(this.meta.nextPage); - }, - - goToPreviousPage() { - if (!this.meta.previousPage) return; - this.onSelectPage(this.meta.previousPage); - } - } -}); diff --git a/webapp/app/pods/components/resource-pagination/component.ts b/webapp/app/pods/components/resource-pagination/component.ts new file mode 100644 index 00000000..99473204 --- /dev/null +++ b/webapp/app/pods/components/resource-pagination/component.ts @@ -0,0 +1,44 @@ +import {action} from '@ember/object'; +import {or, readOnly, not} from '@ember/object/computed'; +import Component from '@glimmer/component'; + +export interface PaginationMeta { + nextPage: number; + previousPage: number; +} + +interface Args { + meta: PaginationMeta; + onSelectPage: (page: number) => void; +} + +export default class ResourcePagination extends Component { + @or('args.meta.{nextPage,previousPage}') + showPagination: boolean; + + @readOnly('args.meta.previousPage') + hasPrevious: boolean; + + @readOnly('args.meta.nextPage') + hasNext: boolean; + + @not('hasPrevious') + disabledPrevious: boolean; + + @not('hasNext') + disabledNext: boolean; + + @action + goToNextPage() { + if (!this.args.meta.nextPage) return; + + this.args.onSelectPage(this.args.meta.nextPage); + } + + @action + goToPreviousPage() { + if (!this.args.meta.previousPage) return; + + this.args.onSelectPage(this.args.meta.previousPage); + } +} diff --git a/webapp/app/pods/components/resource-pagination/styles.scss b/webapp/app/pods/components/resource-pagination/styles.scss index b2fb09f3..77037084 100644 --- a/webapp/app/pods/components/resource-pagination/styles.scss +++ b/webapp/app/pods/components/resource-pagination/styles.scss @@ -1,4 +1,6 @@ -& { +@value color-grey from 'accent-webapp/styles/variables/colors'; + +.resource-pagination { display: flex; align-items: center; justify-content: center; @@ -7,7 +9,7 @@ .label { margin: 0 10px; - color: $color-grey; + color: color-grey; font-size: 14px; } diff --git a/webapp/app/pods/components/resource-pagination/template.hbs b/webapp/app/pods/components/resource-pagination/template.hbs index 6642b3b1..cc0ca4e2 100644 --- a/webapp/app/pods/components/resource-pagination/template.hbs +++ b/webapp/app/pods/components/resource-pagination/template.hbs @@ -1,27 +1,29 @@ -{{#if showPagination}} - +
                  + {{#if this.showPagination}} + - - - {{attrs.meta.currentPage}} + + + {{@meta.currentPage}} + + / + + {{@meta.totalPages}} + - / - - {{attrs.meta.totalPages}} - - - -{{/if}} + + {{/if}} +
                  diff --git a/webapp/app/pods/components/review-progress-bar/component.js b/webapp/app/pods/components/review-progress-bar/component.js deleted file mode 100644 index 2d36f675..00000000 --- a/webapp/app/pods/components/review-progress-bar/component.js +++ /dev/null @@ -1,14 +0,0 @@ -import {computed} from '@ember/object'; -import Component from '@ember/component'; -import {htmlSafe} from '@ember/string'; - -// Attributes: -// correctedKeysPercentage: Number -export default Component.extend({ - progressStyles: computed('correctedKeysPercentage', function() { - let percentage = this.correctedKeysPercentage; - if (percentage < 1 && percentage !== 0) percentage = 1; - - return htmlSafe(`width: ${percentage}%`); - }) -}); diff --git a/webapp/app/pods/components/review-progress-bar/component.ts b/webapp/app/pods/components/review-progress-bar/component.ts new file mode 100644 index 00000000..ad7cc9f8 --- /dev/null +++ b/webapp/app/pods/components/review-progress-bar/component.ts @@ -0,0 +1,35 @@ +import {tracked} from '@glimmer/tracking'; +import Component from '@glimmer/component'; +import {action} from '@ember/object'; +import {htmlSafe} from '@ember/string'; + +interface Args { + correctedKeysPercentage: number; +} + +const minimumTransitionDelay = 300; +const thresholdTransitionDelay = 200; +const transitionDelay = () => + Math.floor(Math.random() * Math.floor(thresholdTransitionDelay)) + + minimumTransitionDelay; + +export default class ReviewProgressBar extends Component { + @tracked + percentage = 0; + + @action + setPercentage() { + setTimeout( + () => (this.percentage = this.args.correctedKeysPercentage), + transitionDelay() + ); + } + + get progressStyles() { + let percentage = this.percentage; + + if (percentage < 1 && percentage !== 0) percentage = 1; + + return htmlSafe(`width: ${percentage}%`); + } +} diff --git a/webapp/app/pods/components/review-progress-bar/styles.scss b/webapp/app/pods/components/review-progress-bar/styles.scss index bc861b48..bcc37b16 100644 --- a/webapp/app/pods/components/review-progress-bar/styles.scss +++ b/webapp/app/pods/components/review-progress-bar/styles.scss @@ -1,13 +1,27 @@ -& { +@value color-black from 'accent-webapp/styles/variables/colors'; + +.progress-bar { width: 100%; height: 2px; background: #eee; border-radius: 3px; - overflow: hidden; - box-shadow: 0 1px 8px rgba($color-black, 0.04); + box-shadow: 0 1px 8px rgba(color-black, 0.04); } .progress { - height: 5px; - background: $color-grey; + height: 2px; + width: 0; + background: currentColor; + border-radius: 3px; + transition: width 500ms ease-in-out; + + &:after { + width: 100%; + content: ''; + height: 1px; + background: transparent; + box-shadow: 3px 2px 4px currentColor; + display: block; + opacity: 0.7; + } } diff --git a/webapp/app/pods/components/review-progress-bar/template.hbs b/webapp/app/pods/components/review-progress-bar/template.hbs index e2a8f427..1a92ffcb 100644 --- a/webapp/app/pods/components/review-progress-bar/template.hbs +++ b/webapp/app/pods/components/review-progress-bar/template.hbs @@ -1 +1,4 @@ -
                  +{{!-- template-lint-disable no-inline-styles --}} +
                  +
                  +
                  diff --git a/webapp/app/pods/components/revision-export-options/component.js b/webapp/app/pods/components/revision-export-options/component.js deleted file mode 100644 index c956c06b..00000000 --- a/webapp/app/pods/components/revision-export-options/component.js +++ /dev/null @@ -1,119 +0,0 @@ -import {computed} from '@ember/object'; -import {inject as service} from '@ember/service'; -import {gt, notEmpty} from '@ember/object/computed'; -import Component from '@ember/component'; - -// Attributes: -// orderBy: String -// format: String -// revision: String -// document: String -// onChangeOrderBy: Function -// onChangeFormat: Function -// onChangeRevision: Function -// onChangeDocument: Function -export default Component.extend({ - intl: service('intl'), - globalState: service('global-state'), - - showOrders: notEmpty('onChangeOrderBy'), - showRevisions: gt('mappedRevisions.length', 1), - showDocuments: gt('mappedDocuments.length', 1), - - orderByValue: computed('orderBy', 'orderByOptions.[]', function() { - return this.orderByOptions.find(({value}) => value === this.orderBy); - }), - - orderByOptions: computed(function() { - return [ - { - value: null, - label: this.intl.t('components.revision_export_options.orders.original') - }, - { - value: 'key', - label: this.intl.t('components.revision_export_options.orders.az') - } - ]; - }), - - formatValue: computed('format', 'formatOptions', function() { - return this.formatOptions.find(({value}) => value === this.format); - }), - - formattedDocumentFormats: computed('globalState.documentFormats', function() { - if (!this.globalState.documentFormats) return []; - - return this.globalState.documentFormats.map(({slug, name}) => ({ - value: slug, - label: name - })); - }), - - formatOptions: computed('formattedDocumentFormats', function() { - return [ - { - value: null, - label: this.intl.t('components.revision_export_options.default_format') - } - ].concat(this.formattedDocumentFormats); - }), - - revisionValue: computed('revision', 'mappedRevisions.[]', function() { - return ( - this.mappedRevisions.find(({value}) => value === this.revision) || - this.mappedRevisions[0] - ); - }), - - mappedRevisions: computed('revisions.[]', function() { - if (!this.revisions) return []; - - return this.revisions.map(({id, language}) => ({ - label: language.name, - value: id - })); - }), - - documentValue: computed('document', 'mappedDocuments.[]', function() { - return ( - this.mappedDocuments.find(({value}) => value === this.document) || - this.mappedDocuments[0] - ); - }), - - mappedDocuments: computed('documents.[]', function() { - if (!this.documents) return []; - - return this.documents.map(({id, path}) => ({ - label: path, - value: id - })); - }), - - actions: { - orderByChanged(orderBy) { - if (orderBy === this.orderBy) return; - - this.onChangeOrderBy(orderBy); - }, - - formatChanged(format) { - if (format === this.format) return; - - this.onChangeFormat(format); - }, - - documentChanged(document) { - if (document === this.document) return; - - this.onChangeDocument(document); - }, - - revisionChanged(revision) { - if (revision === this.revision) return; - - this.onChangeRevision(revision); - } - } -}); diff --git a/webapp/app/pods/components/revision-export-options/component.ts b/webapp/app/pods/components/revision-export-options/component.ts new file mode 100644 index 00000000..90199f51 --- /dev/null +++ b/webapp/app/pods/components/revision-export-options/component.ts @@ -0,0 +1,146 @@ +import {action} from '@ember/object'; +import {inject as service} from '@ember/service'; +import {gt, notEmpty} from '@ember/object/computed'; +import Component from '@glimmer/component'; +import IntlService from 'ember-intl/services/intl'; +import GlobalState from 'accent-webapp/services/global-state'; + +interface Args { + format: any; + onChangeFormat: (format: any) => void; + orderBy?: any; + revision?: any; + revisions?: any; + document?: any; + documents?: any; + onChangeRevision?: (revision: any) => void; + onChangeOrderBy?: (orderBy: any) => void; + onChangeDocument?: (document: any) => void; +} + +export default class RevisionExportOptions extends Component { + @service('intl') + intl: IntlService; + + @service('global-state') + globalState: GlobalState; + + @notEmpty('args.onChangeOrderBy') + showOrders: boolean; + + @gt('mappedRevisions.length', 1) + showRevisions: boolean; + + @gt('mappedDocuments.length', 1) + showDocuments: boolean; + + get orderByValue() { + return this.orderByOptions.find(({value}) => value === this.args.orderBy); + } + + get orderByOptions() { + return [ + { + value: null, + label: this.intl.t( + 'components.revision_export_options.orders.original' + ), + }, + { + value: 'key', + label: this.intl.t('components.revision_export_options.orders.az'), + }, + ]; + } + + get formatValue() { + return this.formatOptions.find( + ({value}: {value: any}) => value === this.args.format + ); + } + + get formattedDocumentFormats() { + if (!this.globalState.documentFormats) return []; + + return this.globalState.documentFormats.map(({slug, name}) => ({ + value: slug, + label: name, + })); + } + + get formatOptions() { + return [ + { + value: null, + label: this.intl.t('components.revision_export_options.default_format'), + }, + ...this.formattedDocumentFormats, + ]; + } + + get revisionValue() { + return ( + this.mappedRevisions.find( + ({value}: {value: any}) => value === this.args.revision + ) || this.mappedRevisions[0] + ); + } + + get mappedRevisions() { + if (!this.args.revisions) return []; + + return this.args.revisions.map( + ({id, language}: {id: string; language: any}) => ({ + label: language.name, + value: id, + }) + ); + } + + get documentValue() { + return ( + this.mappedDocuments.find( + ({value}: {value: any}) => value === this.args.document + ) || this.mappedDocuments[0] + ); + } + + get mappedDocuments() { + if (!this.args.documents) return []; + + return this.args.documents.map( + ({id, path}: {id: string; path: string}) => ({ + label: path, + value: id, + }) + ); + } + + @action + orderByChanged(orderBy: any) { + if (orderBy.value === this.args.orderBy) return; + + this.args.onChangeOrderBy?.(orderBy.value); + } + + @action + formatChanged(format: any) { + if (format.value === this.args.format) return; + + this.args.onChangeFormat(format.value); + } + + @action + documentChanged(document: any) { + if (document.value === this.args.document) return; + + this.args.onChangeDocument?.(document.value); + } + + @action + revisionChanged(revision: any) { + if (revision.value === this.args.revision) return; + + this.args.onChangeRevision?.(revision.value); + } +} diff --git a/webapp/app/pods/components/revision-export-options/styles.scss b/webapp/app/pods/components/revision-export-options/styles.scss index 0e2a269f..a6950775 100644 --- a/webapp/app/pods/components/revision-export-options/styles.scss +++ b/webapp/app/pods/components/revision-export-options/styles.scss @@ -1,4 +1,4 @@ -.subNavigation + & { +.subNavigation + .revision-export-options { position: relative; top: -1px; z-index: 8; @@ -19,7 +19,7 @@ flex: 1 1 auto; margin: 0 5px; - .ember-power-select-trigger { + :global(.ember-power-select-trigger) { font-size: 13px; } diff --git a/webapp/app/pods/components/revision-export-options/template.hbs b/webapp/app/pods/components/revision-export-options/template.hbs index 9e79d0a0..f989aee4 100644 --- a/webapp/app/pods/components/revision-export-options/template.hbs +++ b/webapp/app/pods/components/revision-export-options/template.hbs @@ -1,47 +1,49 @@ -
                  -
                  -
                  - {{#if showRevisions}} -
                  +
                  +
                  +
                  +
                  + {{#if this.showRevisions}} +
                  + +
                  + {{/if}} + + {{#if this.showOrders}} +
                  + +
                  + {{/if}} + +
                  - {{/if}} - {{#if showOrders}} -
                  - -
                  - {{/if}} - -
                  - + {{#if this.showDocuments}} +
                  + +
                  + {{/if}}
                  - - {{#if showDocuments}} -
                  - -
                  - {{/if}}
                  diff --git a/webapp/app/pods/components/revision-selector/component.js b/webapp/app/pods/components/revision-selector/component.js deleted file mode 100644 index 4001e89e..00000000 --- a/webapp/app/pods/components/revision-selector/component.js +++ /dev/null @@ -1,51 +0,0 @@ -import {computed} from '@ember/object'; -import {inject as service} from '@ember/service'; -import {htmlSafe} from '@ember/string'; -import Component from '@ember/component'; - -// Attributes: -// revision: Object -// onSelect: Function -export default Component.extend({ - intl: service('intl'), - globalState: service('global-state'), - - classNameBindings: ['hasManyRevisions:with-many-revisions'], - - withRevisionsCount: true, - - hasManyRevisions: computed('revisions.[]', function() { - return this.revisions && this.revisions.length > 1; - }), - - revisionValue: computed('revision', 'revisions.[]', function() { - return this.mappedRevisions.find(({value}) => value === this.revision); - }), - - mappedRevisions: computed('revisions.[]', function() { - return this.revisions.map(({id, name, isMaster, language}) => { - const masterLabel = name => - htmlSafe( - `${name} ${this.intl.t( - 'components.revision_selector.master' - )}` - ); - const displayName = name || language.name; - const label = isMaster ? masterLabel(displayName) : displayName; - - return {label, value: id}; - }); - }), - - otherRevisionsCount: computed('revisions.length', function() { - return this.revisions && this.revisions.length - 1; - }), - - actions: { - selectRevision(value) { - this.set('globalState.revision', value); - - this.onSelect(value); - } - } -}); diff --git a/webapp/app/pods/components/revision-selector/component.ts b/webapp/app/pods/components/revision-selector/component.ts new file mode 100644 index 00000000..02409640 --- /dev/null +++ b/webapp/app/pods/components/revision-selector/component.ts @@ -0,0 +1,73 @@ +import {action} from '@ember/object'; +import {inject as service} from '@ember/service'; +import {htmlSafe} from '@ember/string'; +import Component from '@glimmer/component'; +import IntlService from 'ember-intl/services/intl'; +import GlobalState from 'accent-webapp/services/global-state'; +import {tracked} from '@glimmer/tracking'; + +interface Args { + revisions: any; + revision: any; + withRevisionsCount: boolean; + onSelect: (revision: any) => void; +} + +export default class RevisionSelector extends Component { + @service('intl') + intl: IntlService; + + @service('global-state') + globalState: GlobalState; + + @tracked + withRevisionsCount = true; + + get hasManyRevisions() { + return this.args.revisions && this.args.revisions.length > 1; + } + + get revisionValue() { + return this.mappedRevisions.find( + ({value}: {value: string}) => value === this.args.revision + ); + } + + get mappedRevisions() { + return this.args.revisions.map( + ({ + id, + name, + isMaster, + language, + }: { + id: string; + name: string; + isMaster: boolean; + language: any; + }) => { + const masterLabel = (name: string) => + htmlSafe( + `${name} ${this.intl.t( + 'components.revision_selector.master' + )}` + ); + const displayName = name || language.name; + const label = isMaster ? masterLabel(displayName) : displayName; + + return {label, value: id}; + } + ); + } + + get otherRevisionsCount() { + return this.args.revisions && this.args.revisions.length - 1; + } + + @action + selectRevision({value}: any) { + this.globalState.revision = value; + + this.args.onSelect(value); + } +} diff --git a/webapp/app/pods/components/revision-selector/styles.scss b/webapp/app/pods/components/revision-selector/styles.scss index 809b1b5b..667d021f 100644 --- a/webapp/app/pods/components/revision-selector/styles.scss +++ b/webapp/app/pods/components/revision-selector/styles.scss @@ -1,26 +1,53 @@ -& { +@value color-light-background, color-black, color-green from 'accent-webapp/styles/variables/colors'; + +.revision-selector { position: relative; box-shadow: 0 2px 4px rgba(#000, 0.06); + + :global(.ember-power-select-selected-item) { + margin-left: 10px; + font-weight: 700; + color: color-black; + color: var(--color-black); + + em { + margin-left: 1px; + font-size: 11px; + font-style: normal; + color: color-green; + color: var(--color-primary); + } + } + + :global(.ember-power-select-status-icon) { + opacity: 0.3; + right: 10px; + font-size: 27px; + margin-top: 4px; + } + + :global(.ember-power-select-trigger) { + padding: 10px; + font-size: 20px; + flex-direction: row-reverse; + border: 1px solid #eee; + cursor: default; + pointer-events: none; + } } -&.with-many-revisions { - .ember-power-select-selected-item { +.revision-selector.with-many-revisions { + :global(.ember-power-select-selected-item) { margin-left: 0; } - .ember-power-select-trigger { + :global(.ember-power-select-trigger) { padding-bottom: 25px; cursor: pointer; pointer-events: all; &:hover { - background: $color-light-background; - } - - .ember-power-select-status-icon { - &:after { - display: block; - } + background: color-light-background; } } } @@ -28,52 +55,8 @@ .otherLanguages { position: absolute; bottom: 8px; - left: 13px; + left: 11px; font-size: 12px; - font-style: italic; color: #ccc; pointer-events: none; } - -.ember-power-select-selected-item { - margin-left: 10px; - font-weight: 700; - color: $color-black; - color: var(--color-black); - - em { - margin-left: 1px; - font-size: 11px; - font-style: normal; - color: $color-green; - color: var(--color-primary); - } -} - -.ember-power-select-trigger { - padding: 10px; - font-size: 20px; - flex-direction: row-reverse; - border: 1px solid #eee; - cursor: default; - pointer-events: none; - - .ember-power-select-status-icon { - &:after { - display: none; - content: 'Ξ'; - transform: rotate(0); - bottom: -14px; - left: 0; - color: #ddd; - } - } - - &[aria-expanded='true'] { - .ember-power-select-status-icon { - &:after { - transform: rotate(0); - } - } - } -} diff --git a/webapp/app/pods/components/revision-selector/template.hbs b/webapp/app/pods/components/revision-selector/template.hbs index c6c6153c..83e94b2c 100644 --- a/webapp/app/pods/components/revision-selector/template.hbs +++ b/webapp/app/pods/components/revision-selector/template.hbs @@ -1,18 +1,20 @@ -{{#if revisions.length}} -
                  - - {{#if hasManyRevisions}} - - {{t - "components.revision_selector.languages_count" - count=otherRevisionsCount - }} - - {{/if}} -
                  -{{/if}} +
                  + {{#if @revisions.length}} +
                  + + {{#if this.hasManyRevisions}} + + {{t + "components.revision_selector.languages_count" + count=this.otherRevisionsCount + }} + + {{/if}} +
                  + {{/if}} +
                  diff --git a/webapp/app/pods/components/revision-update-form/component.js b/webapp/app/pods/components/revision-update-form/component.js deleted file mode 100644 index 54c45f0d..00000000 --- a/webapp/app/pods/components/revision-update-form/component.js +++ /dev/null @@ -1,38 +0,0 @@ -import {computed} from '@ember/object'; -import {reads} from '@ember/object/computed'; -import {scheduleOnce} from '@ember/runloop'; -import Component from '@ember/component'; - -// Attributes: -// revision: Object -// error: Boolean -// onUpdate: Function -export default Component.extend({ - name: reads('revision.name'), - namePlaceholder: computed('revision.{name,language.name}', function() { - return this.revision.name || this.revision.language.name; - }), - slug: reads('revision.slug'), - slugPlaceholder: computed('revision.{slug,language.slug}', function() { - return this.revision.slug || this.revision.language.slug; - }), - isUpdating: false, - - didInsertElement() { - scheduleOnce('afterRender', this, function() { - this.element.querySelector('.textInput').focus(); - }); - }, - - actions: { - submit() { - this.set('isUpdating', true); - const name = this.name; - const slug = this.slug; - - this.onUpdate({name, slug}).then(() => { - if (!this.isDestroyed) this.set('isUpdated', false); - }); - } - } -}); diff --git a/webapp/app/pods/components/revision-update-form/component.ts b/webapp/app/pods/components/revision-update-form/component.ts new file mode 100644 index 00000000..7e8c0632 --- /dev/null +++ b/webapp/app/pods/components/revision-update-form/component.ts @@ -0,0 +1,54 @@ +import {action} from '@ember/object'; +import Component from '@glimmer/component'; +import {tracked} from '@glimmer/tracking'; + +interface Args { + project: any; + revision: any; + onUpdate: ({name, slug}: {name: string; slug: string}) => Promise; +} + +export default class RevisionUpdateForm extends Component { + @tracked + name = this.args.revision.name; + + @tracked + slug = this.args.revision.slug; + + @tracked + isUpdating = false; + + get namePlaceholder() { + return this.args.revision.name || this.args.revision.language.name; + } + + get slugPlaceholder() { + return this.args.revision.slug || this.args.revision.language.slug; + } + + @action + async submit() { + this.isUpdating = true; + + const name = this.name; + const slug = this.slug; + + await this.args.onUpdate({name, slug}); + + if (!this.isDestroyed) this.isUpdating = false; + } + + @action + setName(event: Event) { + const target = event.target as HTMLInputElement; + + this.name = target.value; + } + + @action + setSlug(event: Event) { + const target = event.target as HTMLInputElement; + + this.slug = target.value; + } +} diff --git a/webapp/app/pods/components/revision-update-form/styles.scss b/webapp/app/pods/components/revision-update-form/styles.scss index 3872b20c..283762b0 100644 --- a/webapp/app/pods/components/revision-update-form/styles.scss +++ b/webapp/app/pods/components/revision-update-form/styles.scss @@ -1,4 +1,7 @@ -& { +@value color-green, color-error from 'accent-webapp/styles/variables/colors'; +@value font-primary from 'accent-webapp/styles/variables/fonts'; + +.revision-update-form { padding: 20px; background: #fff; } @@ -8,7 +11,7 @@ text-align: center; font-size: 27px; font-weight: 300; - color: $color-green; + color: color-green; color: var(--color-primary); } @@ -17,18 +20,18 @@ padding: 10px; width: 100%; font-size: 12px; - font-family: $font-primary; + font-family: font-primary; } .errors { margin-bottom: 15px; padding-bottom: 5px; - border-bottom: 1px solid rgba($color-error, 0.3); + border-bottom: 1px solid rgba(color-error, 0.3); } .error { margin-bottom: 5px; - color: $color-error; + color: color-error; font-size: 13px; font-weight: bold; } diff --git a/webapp/app/pods/components/revision-update-form/template.hbs b/webapp/app/pods/components/revision-update-form/template.hbs index 98c0c2da..c51f61a0 100644 --- a/webapp/app/pods/components/revision-update-form/template.hbs +++ b/webapp/app/pods/components/revision-update-form/template.hbs @@ -1,46 +1,50 @@ -

                  - {{t "components.revision_update_form.title"}} -

                  +
                  +

                  + {{t "components.revision_update_form.title"}} +

                  -{{#if error}} -
                  -
                  - {{t "components.revision_update_form.error"}} +
                  +
                  + + +
                  -
                  -{{/if}} - -
                  - - -
                  +
                  + + +
                  -
                  - - -
                  +
                  + + {{t "components.revision_update_form.cancel_button"}} + -
                  - - {{t "components.revision_update_form.cancel_button"}} - - - - {{t "components.revision_update_form.save_button"}} - -
                  - + + {{t "components.revision_update_form.save_button"}} + +
                  + +
                  diff --git a/webapp/app/pods/components/skeleton-ui/activities-list/component.js b/webapp/app/pods/components/skeleton-ui/activities-list/component.js deleted file mode 100644 index cbfd5011..00000000 --- a/webapp/app/pods/components/skeleton-ui/activities-list/component.js +++ /dev/null @@ -1,3 +0,0 @@ -import Component from '@ember/component'; - -export default Component.extend(); diff --git a/webapp/app/pods/components/skeleton-ui/activities-list/component.ts b/webapp/app/pods/components/skeleton-ui/activities-list/component.ts new file mode 100644 index 00000000..812e3ca1 --- /dev/null +++ b/webapp/app/pods/components/skeleton-ui/activities-list/component.ts @@ -0,0 +1,3 @@ +import Component from '@glimmer/component'; + +export default class ActivitiesList extends Component {} diff --git a/webapp/app/pods/components/skeleton-ui/activities-list/styles.scss b/webapp/app/pods/components/skeleton-ui/activities-list/styles.scss index 2c9d2f70..04b280b2 100644 --- a/webapp/app/pods/components/skeleton-ui/activities-list/styles.scss +++ b/webapp/app/pods/components/skeleton-ui/activities-list/styles.scss @@ -1,4 +1,6 @@ -& { +@value color-green, color-black, color-light-background from 'accent-webapp/styles/variables/colors'; + +.activities-list { margin-top: 20px; } @@ -21,7 +23,7 @@ } .item-icon { - background: rgba($color-green, 0.3); + background: rgba(color-green, 0.3); background: var(--color-primary-opacity-70); } } @@ -53,7 +55,7 @@ display: inline-block; height: 3px; width: 100px; - background: rgba($color-green, 0.5); + background: rgba(color-green, 0.5); background: var(--color-primary-opacity-70); } @@ -62,7 +64,7 @@ height: 4px; width: 90px; margin-right: 10px; - background: rgba($color-black, 0.2); + background: rgba(color-black, 0.2); } .item-text { @@ -70,11 +72,11 @@ height: 3px; width: 120px; margin-right: 10px; - background: rgba($color-black, 0.07); + background: rgba(color-black, 0.07); } .item-content { width: 100%; height: 30px; - background: $color-light-background; + background: color-light-background; } diff --git a/webapp/app/pods/components/skeleton-ui/activities-list/template.hbs b/webapp/app/pods/components/skeleton-ui/activities-list/template.hbs index 0b98c562..d9f7d1ce 100644 --- a/webapp/app/pods/components/skeleton-ui/activities-list/template.hbs +++ b/webapp/app/pods/components/skeleton-ui/activities-list/template.hbs @@ -1,33 +1,35 @@ -
                  -
                  -
                  - - - {{#if showTranslationLink}} - - {{/if}} +
                  +
                  +
                  +
                  + + + {{#if showTranslationLink}} + + {{/if}} +
                  +
                  -
                  -
                  -
                  -
                  -
                  - - - {{#if showTranslationLink}} - - {{/if}} +
                  +
                  +
                  + + + {{#if showTranslationLink}} + + {{/if}} +
                  +
                  -
                  -
                  -
                  -
                  -
                  - - - {{#if showTranslationLink}} - - {{/if}} +
                  +
                  +
                  + + + {{#if showTranslationLink}} + + {{/if}} +
                  +
                  -
                  diff --git a/webapp/app/pods/components/skeleton-ui/component.js b/webapp/app/pods/components/skeleton-ui/component.js deleted file mode 100644 index cbfd5011..00000000 --- a/webapp/app/pods/components/skeleton-ui/component.js +++ /dev/null @@ -1,3 +0,0 @@ -import Component from '@ember/component'; - -export default Component.extend(); diff --git a/webapp/app/pods/components/skeleton-ui/conflicts-items/component.js b/webapp/app/pods/components/skeleton-ui/conflicts-items/component.js deleted file mode 100644 index cbfd5011..00000000 --- a/webapp/app/pods/components/skeleton-ui/conflicts-items/component.js +++ /dev/null @@ -1,3 +0,0 @@ -import Component from '@ember/component'; - -export default Component.extend(); diff --git a/webapp/app/pods/components/skeleton-ui/conflicts-items/component.ts b/webapp/app/pods/components/skeleton-ui/conflicts-items/component.ts new file mode 100644 index 00000000..b5076ee7 --- /dev/null +++ b/webapp/app/pods/components/skeleton-ui/conflicts-items/component.ts @@ -0,0 +1,3 @@ +import Component from '@glimmer/component'; + +export default class ConflictsItems extends Component {} diff --git a/webapp/app/pods/components/skeleton-ui/conflicts-items/styles.scss b/webapp/app/pods/components/skeleton-ui/conflicts-items/styles.scss index 5a1e816f..2c226869 100644 --- a/webapp/app/pods/components/skeleton-ui/conflicts-items/styles.scss +++ b/webapp/app/pods/components/skeleton-ui/conflicts-items/styles.scss @@ -1,4 +1,6 @@ -& { +@value color-green, color-success from 'accent-webapp/styles/variables/colors'; + +.conflicts-items { margin-top: 60px; } @@ -21,7 +23,7 @@ height: 5px; width: 120px; margin-bottom: 20px; - background: rgba($color-green, 0.1); + background: rgba(color-green, 0.1); background: var(--color-primary-opacity-10); } @@ -47,7 +49,7 @@ height: 3px; width: 250px; margin-bottom: 5px; - background: rgba($color-success, 0.1); + background: rgba(color-success, 0.1); } .item-textarea { diff --git a/webapp/app/pods/components/skeleton-ui/conflicts-items/template.hbs b/webapp/app/pods/components/skeleton-ui/conflicts-items/template.hbs index 2560cbed..626cd91b 100644 --- a/webapp/app/pods/components/skeleton-ui/conflicts-items/template.hbs +++ b/webapp/app/pods/components/skeleton-ui/conflicts-items/template.hbs @@ -1,42 +1,44 @@ -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  diff --git a/webapp/app/pods/components/skeleton-ui/documents-list/component.js b/webapp/app/pods/components/skeleton-ui/documents-list/component.js deleted file mode 100644 index cbfd5011..00000000 --- a/webapp/app/pods/components/skeleton-ui/documents-list/component.js +++ /dev/null @@ -1,3 +0,0 @@ -import Component from '@ember/component'; - -export default Component.extend(); diff --git a/webapp/app/pods/components/skeleton-ui/documents-list/component.ts b/webapp/app/pods/components/skeleton-ui/documents-list/component.ts new file mode 100644 index 00000000..50a5ff07 --- /dev/null +++ b/webapp/app/pods/components/skeleton-ui/documents-list/component.ts @@ -0,0 +1,3 @@ +import Component from '@glimmer/component'; + +export default class DocumentsList extends Component {} diff --git a/webapp/app/pods/components/skeleton-ui/documents-list/styles.scss b/webapp/app/pods/components/skeleton-ui/documents-list/styles.scss index fefe6550..658668ed 100644 --- a/webapp/app/pods/components/skeleton-ui/documents-list/styles.scss +++ b/webapp/app/pods/components/skeleton-ui/documents-list/styles.scss @@ -1,4 +1,6 @@ -& { +@value color-light-background, color-green from 'accent-webapp/styles/variables/colors'; + +.documents-list { margin-top: 25px; display: flex; flex-wrap: wrap; @@ -27,7 +29,7 @@ height: 3px; width: 160px; margin-bottom: 20px; - background: $color-light-background; + background: color-light-background; } .item-document { @@ -46,6 +48,6 @@ } .item-button--green { - border-color: rgba($color-green, 0.3); - background: rgba($color-green, 0.1); + border-color: rgba(color-green, 0.3); + background: rgba(color-green, 0.1); } diff --git a/webapp/app/pods/components/skeleton-ui/documents-list/template.hbs b/webapp/app/pods/components/skeleton-ui/documents-list/template.hbs index 18566b8d..1a6f994a 100644 --- a/webapp/app/pods/components/skeleton-ui/documents-list/template.hbs +++ b/webapp/app/pods/components/skeleton-ui/documents-list/template.hbs @@ -1,30 +1,32 @@ -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  diff --git a/webapp/app/pods/components/skeleton-ui/progress-line/component.js b/webapp/app/pods/components/skeleton-ui/progress-line/component.js deleted file mode 100644 index cbfd5011..00000000 --- a/webapp/app/pods/components/skeleton-ui/progress-line/component.js +++ /dev/null @@ -1,3 +0,0 @@ -import Component from '@ember/component'; - -export default Component.extend(); diff --git a/webapp/app/pods/components/skeleton-ui/progress-line/component.ts b/webapp/app/pods/components/skeleton-ui/progress-line/component.ts new file mode 100644 index 00000000..6b6691d4 --- /dev/null +++ b/webapp/app/pods/components/skeleton-ui/progress-line/component.ts @@ -0,0 +1,3 @@ +import Component from '@glimmer/component'; + +export default class ProgressLine extends Component {} diff --git a/webapp/app/pods/components/skeleton-ui/progress-line/styles.scss b/webapp/app/pods/components/skeleton-ui/progress-line/styles.scss index 7b205b21..213153bc 100644 --- a/webapp/app/pods/components/skeleton-ui/progress-line/styles.scss +++ b/webapp/app/pods/components/skeleton-ui/progress-line/styles.scss @@ -1,20 +1,22 @@ -&, -&:before { +@value color-green from 'accent-webapp/styles/variables/colors'; + +.progress-line, +.progress-line:before { height: 2px; width: 100%; margin: 0; border-radius: 4px; } -& { +.progress-line { display: flex; position: relative; bottom: 1px; margin-bottom: -2px; } -&:before { - background-color: lighten($color-green, 20%); +.progress-line:before { + background-color: lighten(color-green, 20%); background-color: var(--color-primary-opacity-70); content: ''; animation: progress-line-running-progress 1.8s cubic-bezier(0.5, 0, 0.1, 1) diff --git a/webapp/app/pods/components/skeleton-ui/progress-line/template.hbs b/webapp/app/pods/components/skeleton-ui/progress-line/template.hbs index e69de29b..0492b153 100644 --- a/webapp/app/pods/components/skeleton-ui/progress-line/template.hbs +++ b/webapp/app/pods/components/skeleton-ui/progress-line/template.hbs @@ -0,0 +1 @@ +
                  diff --git a/webapp/app/pods/components/skeleton-ui/project-activities-filter/component.js b/webapp/app/pods/components/skeleton-ui/project-activities-filter/component.js deleted file mode 100644 index cbfd5011..00000000 --- a/webapp/app/pods/components/skeleton-ui/project-activities-filter/component.js +++ /dev/null @@ -1,3 +0,0 @@ -import Component from '@ember/component'; - -export default Component.extend(); diff --git a/webapp/app/pods/components/skeleton-ui/project-activities-filter/component.ts b/webapp/app/pods/components/skeleton-ui/project-activities-filter/component.ts new file mode 100644 index 00000000..41902260 --- /dev/null +++ b/webapp/app/pods/components/skeleton-ui/project-activities-filter/component.ts @@ -0,0 +1,3 @@ +import Component from '@glimmer/component'; + +export default class ProjectActivitiesFilter extends Component {} diff --git a/webapp/app/pods/components/skeleton-ui/project-activities-filter/template.hbs b/webapp/app/pods/components/skeleton-ui/project-activities-filter/template.hbs index bc6c920b..d3289994 100644 --- a/webapp/app/pods/components/skeleton-ui/project-activities-filter/template.hbs +++ b/webapp/app/pods/components/skeleton-ui/project-activities-filter/template.hbs @@ -1 +1 @@ -
                  +
                  diff --git a/webapp/app/pods/components/skeleton-ui/project-comments-list/component.js b/webapp/app/pods/components/skeleton-ui/project-comments-list/component.js deleted file mode 100644 index cbfd5011..00000000 --- a/webapp/app/pods/components/skeleton-ui/project-comments-list/component.js +++ /dev/null @@ -1,3 +0,0 @@ -import Component from '@ember/component'; - -export default Component.extend(); diff --git a/webapp/app/pods/components/skeleton-ui/project-comments-list/component.ts b/webapp/app/pods/components/skeleton-ui/project-comments-list/component.ts new file mode 100644 index 00000000..044803e1 --- /dev/null +++ b/webapp/app/pods/components/skeleton-ui/project-comments-list/component.ts @@ -0,0 +1,3 @@ +import Component from '@glimmer/component'; + +export default class ProjectCommentsList extends Component {} diff --git a/webapp/app/pods/components/skeleton-ui/project-comments-list/styles.scss b/webapp/app/pods/components/skeleton-ui/project-comments-list/styles.scss index 2c8cc92e..5d591d56 100644 --- a/webapp/app/pods/components/skeleton-ui/project-comments-list/styles.scss +++ b/webapp/app/pods/components/skeleton-ui/project-comments-list/styles.scss @@ -1,4 +1,6 @@ -& { +@value color-green from 'accent-webapp/styles/variables/colors'; + +.project-comments-list { margin-top: 25px; } @@ -27,7 +29,7 @@ height: 5px; width: 180px; margin-bottom: 15px; - background: rgba($color-green, 0.3); + background: rgba(color-green, 0.3); background: var(--color-primary-opacity-70); } diff --git a/webapp/app/pods/components/skeleton-ui/project-comments-list/template.hbs b/webapp/app/pods/components/skeleton-ui/project-comments-list/template.hbs index 4c69ce37..42f0e062 100644 --- a/webapp/app/pods/components/skeleton-ui/project-comments-list/template.hbs +++ b/webapp/app/pods/components/skeleton-ui/project-comments-list/template.hbs @@ -1,54 +1,56 @@ -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  -
                  -
                  -
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  diff --git a/webapp/app/pods/components/skeleton-ui/project-navigation/component.js b/webapp/app/pods/components/skeleton-ui/project-navigation/component.js deleted file mode 100644 index cbfd5011..00000000 --- a/webapp/app/pods/components/skeleton-ui/project-navigation/component.js +++ /dev/null @@ -1,3 +0,0 @@ -import Component from '@ember/component'; - -export default Component.extend(); diff --git a/webapp/app/pods/components/skeleton-ui/project-navigation/component.ts b/webapp/app/pods/components/skeleton-ui/project-navigation/component.ts new file mode 100644 index 00000000..74ad130e --- /dev/null +++ b/webapp/app/pods/components/skeleton-ui/project-navigation/component.ts @@ -0,0 +1,3 @@ +import Component from '@glimmer/component'; + +export default class ProjectNavigation extends Component {} diff --git a/webapp/app/pods/components/skeleton-ui/project-navigation/styles.scss b/webapp/app/pods/components/skeleton-ui/project-navigation/styles.scss index b93bcb96..549a9b8d 100644 --- a/webapp/app/pods/components/skeleton-ui/project-navigation/styles.scss +++ b/webapp/app/pods/components/skeleton-ui/project-navigation/styles.scss @@ -1,4 +1,6 @@ -& { +@value screen-sm from 'accent-webapp/styles/variables/dimensions'; + +.project-navigation { display: flex; flex-direction: column; align-items: flex-end; @@ -35,8 +37,8 @@ } } -@media (max-width: ($screen-sm)) { - & { +@media (max-width: (screen-sm)) { + .project-navigation { flex-direction: row; width: 100%; padding-left: 15px; diff --git a/webapp/app/pods/components/skeleton-ui/project-navigation/template.hbs b/webapp/app/pods/components/skeleton-ui/project-navigation/template.hbs index 6df6dbf1..628a939b 100644 --- a/webapp/app/pods/components/skeleton-ui/project-navigation/template.hbs +++ b/webapp/app/pods/components/skeleton-ui/project-navigation/template.hbs @@ -1,6 +1,8 @@ -
                  -
                  -
                  -
                  -
                  -
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  diff --git a/webapp/app/pods/components/skeleton-ui/related-translations-list/component.js b/webapp/app/pods/components/skeleton-ui/related-translations-list/component.js deleted file mode 100644 index cbfd5011..00000000 --- a/webapp/app/pods/components/skeleton-ui/related-translations-list/component.js +++ /dev/null @@ -1,3 +0,0 @@ -import Component from '@ember/component'; - -export default Component.extend(); diff --git a/webapp/app/pods/components/skeleton-ui/related-translations-list/component.ts b/webapp/app/pods/components/skeleton-ui/related-translations-list/component.ts new file mode 100644 index 00000000..cdbea40e --- /dev/null +++ b/webapp/app/pods/components/skeleton-ui/related-translations-list/component.ts @@ -0,0 +1,3 @@ +import Component from '@glimmer/component'; + +export default class RelatedTranslationsList extends Component {} diff --git a/webapp/app/pods/components/skeleton-ui/related-translations-list/styles.scss b/webapp/app/pods/components/skeleton-ui/related-translations-list/styles.scss index 9395fd3a..ae56be64 100644 --- a/webapp/app/pods/components/skeleton-ui/related-translations-list/styles.scss +++ b/webapp/app/pods/components/skeleton-ui/related-translations-list/styles.scss @@ -1,4 +1,4 @@ -& { +.related-translations-list { margin-top: 30px; } diff --git a/webapp/app/pods/components/skeleton-ui/related-translations-list/template.hbs b/webapp/app/pods/components/skeleton-ui/related-translations-list/template.hbs index a38c5206..c1f6433d 100644 --- a/webapp/app/pods/components/skeleton-ui/related-translations-list/template.hbs +++ b/webapp/app/pods/components/skeleton-ui/related-translations-list/template.hbs @@ -1,18 +1,20 @@ -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  diff --git a/webapp/app/pods/components/skeleton-ui/releases-list/component.js b/webapp/app/pods/components/skeleton-ui/releases-list/component.js deleted file mode 100644 index cbfd5011..00000000 --- a/webapp/app/pods/components/skeleton-ui/releases-list/component.js +++ /dev/null @@ -1,3 +0,0 @@ -import Component from '@ember/component'; - -export default Component.extend(); diff --git a/webapp/app/pods/components/skeleton-ui/releases-list/component.ts b/webapp/app/pods/components/skeleton-ui/releases-list/component.ts new file mode 100644 index 00000000..4c5f9752 --- /dev/null +++ b/webapp/app/pods/components/skeleton-ui/releases-list/component.ts @@ -0,0 +1,3 @@ +import Component from '@glimmer/component'; + +export default class ReleasesList extends Component {} diff --git a/webapp/app/pods/components/skeleton-ui/releases-list/styles.scss b/webapp/app/pods/components/skeleton-ui/releases-list/styles.scss index fb60fe2d..5c6b290a 100644 --- a/webapp/app/pods/components/skeleton-ui/releases-list/styles.scss +++ b/webapp/app/pods/components/skeleton-ui/releases-list/styles.scss @@ -1,4 +1,6 @@ -& { +@value color-light-background, color-green from 'accent-webapp/styles/variables/colors'; + +.releases-list { margin-top: 25px; } @@ -20,7 +22,7 @@ height: 3px; width: 160px; margin-bottom: 20px; - background: $color-light-background; + background: color-light-background; } .item-document { @@ -39,6 +41,6 @@ } .item-button--green { - border-color: rgba($color-green, 0.3); - background: rgba($color-green, 0.1); + border-color: rgba(color-green, 0.3); + background: rgba(color-green, 0.1); } diff --git a/webapp/app/pods/components/skeleton-ui/releases-list/template.hbs b/webapp/app/pods/components/skeleton-ui/releases-list/template.hbs index b265a3b7..f30c7b53 100644 --- a/webapp/app/pods/components/skeleton-ui/releases-list/template.hbs +++ b/webapp/app/pods/components/skeleton-ui/releases-list/template.hbs @@ -1,21 +1,23 @@ -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  diff --git a/webapp/app/pods/components/skeleton-ui/translation-comments-list/component.js b/webapp/app/pods/components/skeleton-ui/translation-comments-list/component.js deleted file mode 100644 index cbfd5011..00000000 --- a/webapp/app/pods/components/skeleton-ui/translation-comments-list/component.js +++ /dev/null @@ -1,3 +0,0 @@ -import Component from '@ember/component'; - -export default Component.extend(); diff --git a/webapp/app/pods/components/skeleton-ui/translation-comments-list/component.ts b/webapp/app/pods/components/skeleton-ui/translation-comments-list/component.ts new file mode 100644 index 00000000..6278c265 --- /dev/null +++ b/webapp/app/pods/components/skeleton-ui/translation-comments-list/component.ts @@ -0,0 +1,3 @@ +import Component from '@glimmer/component'; + +export default class TranslationCommentsList extends Component {} diff --git a/webapp/app/pods/components/skeleton-ui/translation-comments-list/styles.scss b/webapp/app/pods/components/skeleton-ui/translation-comments-list/styles.scss index 1a03e7ee..249e3b97 100644 --- a/webapp/app/pods/components/skeleton-ui/translation-comments-list/styles.scss +++ b/webapp/app/pods/components/skeleton-ui/translation-comments-list/styles.scss @@ -1,4 +1,4 @@ -& { +.translation-comments-list { margin-top: 30px; width: 530px; } diff --git a/webapp/app/pods/components/skeleton-ui/translation-comments-list/template.hbs b/webapp/app/pods/components/skeleton-ui/translation-comments-list/template.hbs index 51bea20d..a9220911 100644 --- a/webapp/app/pods/components/skeleton-ui/translation-comments-list/template.hbs +++ b/webapp/app/pods/components/skeleton-ui/translation-comments-list/template.hbs @@ -1,16 +1,18 @@ -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  diff --git a/webapp/app/pods/components/skeleton-ui/translation-splash-title/component.js b/webapp/app/pods/components/skeleton-ui/translation-splash-title/component.js deleted file mode 100644 index cbfd5011..00000000 --- a/webapp/app/pods/components/skeleton-ui/translation-splash-title/component.js +++ /dev/null @@ -1,3 +0,0 @@ -import Component from '@ember/component'; - -export default Component.extend(); diff --git a/webapp/app/pods/components/skeleton-ui/translation-splash-title/component.ts b/webapp/app/pods/components/skeleton-ui/translation-splash-title/component.ts new file mode 100644 index 00000000..e216e62f --- /dev/null +++ b/webapp/app/pods/components/skeleton-ui/translation-splash-title/component.ts @@ -0,0 +1,3 @@ +import Component from '@glimmer/component'; + +export default class TranslationSplashTitle extends Component {} diff --git a/webapp/app/pods/components/skeleton-ui/translation-splash-title/styles.scss b/webapp/app/pods/components/skeleton-ui/translation-splash-title/styles.scss index 472c7e63..1f6afd04 100644 --- a/webapp/app/pods/components/skeleton-ui/translation-splash-title/styles.scss +++ b/webapp/app/pods/components/skeleton-ui/translation-splash-title/styles.scss @@ -1,4 +1,6 @@ -& { +@value color-green from 'accent-webapp/styles/variables/colors'; + +.translation-splash-title { margin: 5px 0 62px; } @@ -12,6 +14,6 @@ .translation { height: 4px; width: 180px; - background: $color-green; + background: color-green; background: var(--color-primary); } diff --git a/webapp/app/pods/components/skeleton-ui/translation-splash-title/template.hbs b/webapp/app/pods/components/skeleton-ui/translation-splash-title/template.hbs index c1fe5376..e4eee294 100644 --- a/webapp/app/pods/components/skeleton-ui/translation-splash-title/template.hbs +++ b/webapp/app/pods/components/skeleton-ui/translation-splash-title/template.hbs @@ -1 +1,3 @@ -
                  +
                  +
                  +
                  diff --git a/webapp/app/pods/components/skeleton-ui/translations-list/component.js b/webapp/app/pods/components/skeleton-ui/translations-list/component.js deleted file mode 100644 index cbfd5011..00000000 --- a/webapp/app/pods/components/skeleton-ui/translations-list/component.js +++ /dev/null @@ -1,3 +0,0 @@ -import Component from '@ember/component'; - -export default Component.extend(); diff --git a/webapp/app/pods/components/skeleton-ui/translations-list/component.ts b/webapp/app/pods/components/skeleton-ui/translations-list/component.ts new file mode 100644 index 00000000..b5cb4d4c --- /dev/null +++ b/webapp/app/pods/components/skeleton-ui/translations-list/component.ts @@ -0,0 +1,3 @@ +import Component from '@glimmer/component'; + +export default class TranslationsList extends Component {} diff --git a/webapp/app/pods/components/skeleton-ui/translations-list/styles.scss b/webapp/app/pods/components/skeleton-ui/translations-list/styles.scss index 77b53500..b1616e58 100644 --- a/webapp/app/pods/components/skeleton-ui/translations-list/styles.scss +++ b/webapp/app/pods/components/skeleton-ui/translations-list/styles.scss @@ -1,4 +1,4 @@ -& { +.translations-list { margin-top: 20px; } diff --git a/webapp/app/pods/components/skeleton-ui/translations-list/template.hbs b/webapp/app/pods/components/skeleton-ui/translations-list/template.hbs index 682abe0b..28d885ca 100644 --- a/webapp/app/pods/components/skeleton-ui/translations-list/template.hbs +++ b/webapp/app/pods/components/skeleton-ui/translations-list/template.hbs @@ -1,35 +1,37 @@ -
                  -
                  -
                  -
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  -
                  -
                  diff --git a/webapp/app/pods/components/skeleton-ui/versions-list/component.js b/webapp/app/pods/components/skeleton-ui/versions-list/component.js deleted file mode 100644 index cbfd5011..00000000 --- a/webapp/app/pods/components/skeleton-ui/versions-list/component.js +++ /dev/null @@ -1,3 +0,0 @@ -import Component from '@ember/component'; - -export default Component.extend(); diff --git a/webapp/app/pods/components/skeleton-ui/versions-list/component.ts b/webapp/app/pods/components/skeleton-ui/versions-list/component.ts new file mode 100644 index 00000000..6a9060ae --- /dev/null +++ b/webapp/app/pods/components/skeleton-ui/versions-list/component.ts @@ -0,0 +1,3 @@ +import Component from '@glimmer/component'; + +export default class VersionsList extends Component {} diff --git a/webapp/app/pods/components/skeleton-ui/versions-list/styles.scss b/webapp/app/pods/components/skeleton-ui/versions-list/styles.scss index 2cffbbac..ac86bf83 100644 --- a/webapp/app/pods/components/skeleton-ui/versions-list/styles.scss +++ b/webapp/app/pods/components/skeleton-ui/versions-list/styles.scss @@ -1,4 +1,6 @@ -& { +@value color-light-background from 'accent-webapp/styles/variables/colors'; + +.versions-list { margin-top: 25px; } @@ -21,7 +23,7 @@ height: 3px; width: 160px; margin-bottom: 20px; - background: $color-light-background; + background: color-light-background; } .item-document { diff --git a/webapp/app/pods/components/skeleton-ui/versions-list/template.hbs b/webapp/app/pods/components/skeleton-ui/versions-list/template.hbs index c0049218..308dfc69 100644 --- a/webapp/app/pods/components/skeleton-ui/versions-list/template.hbs +++ b/webapp/app/pods/components/skeleton-ui/versions-list/template.hbs @@ -1,24 +1,26 @@ -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  diff --git a/webapp/app/pods/components/time-ago-in-words-tag/component.js b/webapp/app/pods/components/time-ago-in-words-tag/component.js deleted file mode 100644 index 004dea59..00000000 --- a/webapp/app/pods/components/time-ago-in-words-tag/component.js +++ /dev/null @@ -1,34 +0,0 @@ -import {computed} from '@ember/object'; -import {inject as service} from '@ember/service'; -import Component from '@ember/component'; -import dateFormat from 'date-fns/format'; - -// Attributes: -// date: String -export default Component.extend({ - intl: service('intl'), - - attributeBindings: ['formattedDatetime:datetime', 'humanizedDate:title'], - - tagName: 'time', - - // The follow property returns a formatted date like this: 2016-02-03T11:02:34 - formattedDatetime: computed('date', function() { - if (!this.date) return null; - - const format = this.intl - .t('components.time_ago_in_words_tag.formatted_date_time_format') - .toString(); - return dateFormat(new Date(this.date), format); // Ex.: 2016-02-03T11:02:34 - }), - - // The follow property returns a formatted date like this: Wednesday, February 2 2016, 11:02 am - humanizedDate: computed('date', function() { - if (!this.date) return null; - - const format = this.intl - .t('components.time_ago_in_words_tag.humanized_date_title_format') - .toString(); - return dateFormat(new Date(this.date), format); // Ex.: 2016-02-03T11:02:34 - }) -}); diff --git a/webapp/app/pods/components/time-ago-in-words-tag/component.ts b/webapp/app/pods/components/time-ago-in-words-tag/component.ts new file mode 100644 index 00000000..bc4d35e1 --- /dev/null +++ b/webapp/app/pods/components/time-ago-in-words-tag/component.ts @@ -0,0 +1,35 @@ +import {inject as service} from '@ember/service'; +import Component from '@glimmer/component'; +import dateFormat from 'date-fns/format'; +import IntlService from 'ember-intl/services/intl'; + +interface Args { + date: string; +} + +export default class TimeAgoInWordsTag extends Component { + @service('intl') + intl: IntlService; + + // The follow property returns a formatted date like this: 2016-02-03T11:02:34 + get formattedDatetime() { + if (!this.args.date) return null; + + const format = this.intl + .t('components.time_ago_in_words_tag.formatted_date_time_format') + .toString(); + + return dateFormat(new Date(this.args.date), format); + } + + // The follow property returns a formatted date like this: Wednesday, February 2 2016, 11:02 am + get humanizedDate() { + if (!this.args.date) return null; + + const format = this.intl + .t('components.time_ago_in_words_tag.humanized_date_title_format') + .toString(); + + return dateFormat(new Date(this.args.date), format); + } +} diff --git a/webapp/app/pods/components/time-ago-in-words-tag/template.hbs b/webapp/app/pods/components/time-ago-in-words-tag/template.hbs index 48411327..26351477 100644 --- a/webapp/app/pods/components/time-ago-in-words-tag/template.hbs +++ b/webapp/app/pods/components/time-ago-in-words-tag/template.hbs @@ -1 +1,3 @@ -{{time-ago-in-words attrs.date}} + diff --git a/webapp/app/pods/components/translation-activities-list/component.js b/webapp/app/pods/components/translation-activities-list/component.js deleted file mode 100644 index 44e985ec..00000000 --- a/webapp/app/pods/components/translation-activities-list/component.js +++ /dev/null @@ -1,9 +0,0 @@ -import Component from '@ember/component'; - -// Attributes: -// project: Object -// activities: Array of object -// permissions: Ember Object containing -export default Component.extend({ - tagName: 'ul' -}); diff --git a/webapp/app/pods/components/translation-activities-list/component.ts b/webapp/app/pods/components/translation-activities-list/component.ts new file mode 100644 index 00000000..865557df --- /dev/null +++ b/webapp/app/pods/components/translation-activities-list/component.ts @@ -0,0 +1,9 @@ +import Component from '@glimmer/component'; + +interface Args { + permissions: Record; + project: any; + activities: any; +} + +export default class TranslationActivitiesList extends Component {} diff --git a/webapp/app/pods/components/translation-activities-list/styles.scss b/webapp/app/pods/components/translation-activities-list/styles.scss index ef406ada..8712f97e 100644 --- a/webapp/app/pods/components/translation-activities-list/styles.scss +++ b/webapp/app/pods/components/translation-activities-list/styles.scss @@ -1,4 +1,4 @@ -& { +.translations-activities-list { position: relative; margin-top: 30px; diff --git a/webapp/app/pods/components/translation-activities-list/template.hbs b/webapp/app/pods/components/translation-activities-list/template.hbs index 43b14997..0b1c73e8 100644 --- a/webapp/app/pods/components/translation-activities-list/template.hbs +++ b/webapp/app/pods/components/translation-activities-list/template.hbs @@ -1,9 +1,11 @@ -{{#each activities key="id" as |activity|}} - -{{/each}} +
                    + {{#each @activities key="id" as |activity|}} + + {{/each}} +
                  diff --git a/webapp/app/pods/components/translation-comment-form/component.js b/webapp/app/pods/components/translation-comment-form/component.js deleted file mode 100644 index 8266ff19..00000000 --- a/webapp/app/pods/components/translation-comment-form/component.js +++ /dev/null @@ -1,34 +0,0 @@ -import Component from '@ember/component'; - -// Attributes: -// onSubmit: Function -export default Component.extend({ - text: null, - loading: false, - error: false, - - actions: { - submit() { - this._onLoading(); - - this.onSubmit(this.text) - .then(this._onSuccess.bind(this)) - .catch(this._onError.bind(this)); - } - }, - - _onLoading() { - this.set('error', false); - this.set('loading', true); - }, - - _onError() { - this.set('loading', false); - this.set('error', true); - }, - - _onSuccess() { - this.set('loading', false); - this.set('text', null); - } -}); diff --git a/webapp/app/pods/components/translation-comment-form/component.ts b/webapp/app/pods/components/translation-comment-form/component.ts new file mode 100644 index 00000000..2c63b8a9 --- /dev/null +++ b/webapp/app/pods/components/translation-comment-form/component.ts @@ -0,0 +1,53 @@ +import Component from '@glimmer/component'; +import {action} from '@ember/object'; +import {tracked} from '@glimmer/tracking'; + +interface Args { + onSubmit: (text: string) => Promise; +} + +export default class TranslationCommentForm extends Component { + @tracked + text = ''; + + @tracked + loading = false; + + @tracked + error = false; + + @action + async submit(event?: Event) { + event?.preventDefault(); + + this.onLoading(); + + try { + await this.args.onSubmit(this.text); + + this.onSuccess(); + } catch (error) { + this.onError(); + } + } + + @action + setText(text: string) { + this.text = text; + } + + private onLoading() { + this.error = false; + this.loading = true; + } + + private onError() { + this.loading = false; + this.error = true; + } + + private onSuccess() { + this.loading = false; + this.text = ''; + } +} diff --git a/webapp/app/pods/components/translation-comment-form/styles.scss b/webapp/app/pods/components/translation-comment-form/styles.scss index 533f2b50..113054c4 100644 --- a/webapp/app/pods/components/translation-comment-form/styles.scss +++ b/webapp/app/pods/components/translation-comment-form/styles.scss @@ -1,5 +1,9 @@ -& { - margin-top: 30px; +@value color-error from 'accent-webapp/styles/variables/colors'; +@value font-primary from 'accent-webapp/styles/variables/fonts'; +@value screen-sm from 'accent-webapp/styles/variables/dimensions'; + +.translation-comment-form { + margin: 30px 0; } .form-content { @@ -14,7 +18,7 @@ .error { display: block; margin-bottom: 10px; - color: $color-error; + color: color-error; font-size: 13px; font-weight: bold; } @@ -25,11 +29,11 @@ padding: 10px; margin-right: 10px; width: 100%; - font-family: $font-primary; + font-family: font-primary; font-size: 13px; } -@media (max-width: ($screen-sm)) { +@media (max-width: (screen-sm)) { .form-content { flex-direction: column; } diff --git a/webapp/app/pods/components/translation-comment-form/template.hbs b/webapp/app/pods/components/translation-comment-form/template.hbs index b02a3894..26b2e40f 100644 --- a/webapp/app/pods/components/translation-comment-form/template.hbs +++ b/webapp/app/pods/components/translation-comment-form/template.hbs @@ -1,20 +1,23 @@ -
                  - {{#if error}} - - {{t "components.translation_comment_form.submit_error"}} - - {{/if}} +
                  + + {{#if this.error}} + + {{t "components.translation_comment_form.submit_error"}} + + {{/if}} -
                  - - - {{t "components.translation_comment_form.comment_button"}} - -
                  - +
                  + + + {{t "components.translation_comment_form.comment_button"}} + +
                  + +
                  diff --git a/webapp/app/pods/components/translation-comments-list/component.js b/webapp/app/pods/components/translation-comments-list/component.js deleted file mode 100644 index e054ab28..00000000 --- a/webapp/app/pods/components/translation-comments-list/component.js +++ /dev/null @@ -1,7 +0,0 @@ -import Component from '@ember/component'; - -// Attributes: -// comments: Array of object -export default Component.extend({ - tagName: 'ul' -}); diff --git a/webapp/app/pods/components/translation-comments-list/component.ts b/webapp/app/pods/components/translation-comments-list/component.ts new file mode 100644 index 00000000..d949ccc1 --- /dev/null +++ b/webapp/app/pods/components/translation-comments-list/component.ts @@ -0,0 +1,7 @@ +import Component from '@glimmer/component'; + +interface Args { + comments: any; +} + +export default class TranslationsCommentsList extends Component {} diff --git a/webapp/app/pods/components/translation-comments-list/styles.scss b/webapp/app/pods/components/translation-comments-list/styles.scss index 7ad36775..5ca347f6 100644 --- a/webapp/app/pods/components/translation-comments-list/styles.scss +++ b/webapp/app/pods/components/translation-comments-list/styles.scss @@ -1,11 +1,14 @@ -& { +@value color-black, color-border, color-light-background, color-grey from 'accent-webapp/styles/variables/colors'; +@value screen-lg from 'accent-webapp/styles/variables/dimensions'; + +.translation-comments-list { position: relative; - box-shadow: 0 1px 5px rgba($color-black, 0.04); + box-shadow: 0 1px 5px rgba(color-black, 0.04); border-radius: 3px; - border: 1px solid $color-border; + border: 1px solid color-border; } -&.translationRemoved { +.translation-comments-list.translationRemoved { opacity: 0.5; .itemComment { @@ -13,7 +16,7 @@ } } -&.at-translation { +.translation-comments-list.at-translation { margin-top: 20px; &:before, @@ -28,7 +31,7 @@ &:focus, &:hover { - background: $color-light-background; + background: color-light-background; } &:last-of-type { @@ -57,7 +60,7 @@ } .itemComment-date { - color: darken($color-grey, 15%); + color: darken(color-grey, 15%); font-size: 11px; } @@ -66,8 +69,8 @@ font-size: 13px; } -@media (max-width: ($screen-lg + 40px)) { - & { +@media (max-width: (screen-lg + 40px)) { + .translation-comments-list { border-color: transparent; box-shadow: none; } diff --git a/webapp/app/pods/components/translation-comments-list/template.hbs b/webapp/app/pods/components/translation-comments-list/template.hbs index 7cb88181..6224ea3c 100644 --- a/webapp/app/pods/components/translation-comments-list/template.hbs +++ b/webapp/app/pods/components/translation-comments-list/template.hbs @@ -1,29 +1,30 @@ -{{#each comments key="id" as |comment|}} -
                • -
                  - - {{#if comment.user.pictureUrl}} - - {{/if}} - {{comment.user.fullname}} - +
                    + {{#each @comments key="id" as |comment|}} +
                  • +
                    + + {{#if comment.user.pictureUrl}} + + {{/if}} + {{comment.user.fullname}} + - -
                    + + + +
                  -
                  - {{comment.text}} -
                  -
                • -{{else}} - -{{/each}} +
                  + {{comment.text}} +
                  + + {{else}} + + {{/each}} +
                diff --git a/webapp/app/pods/components/translation-comments-subscriptions/component.js b/webapp/app/pods/components/translation-comments-subscriptions/component.js deleted file mode 100644 index 18279565..00000000 --- a/webapp/app/pods/components/translation-comments-subscriptions/component.js +++ /dev/null @@ -1,17 +0,0 @@ -import {computed} from '@ember/object'; -import Component from '@ember/component'; - -// Attributes -// subscriptions: Array of -// collaborators: Array of -// onCreateSubscription: Function -// onDeleteSubscription: Function -export default Component.extend({ - tagName: 'ul', - - filteredCollaborators: computed('collaborators', function() { - return this.collaborators - .filter(collaborator => !collaborator.isPending) - .filter(collaborator => collaborator.role !== 'BOT'); - }) -}); diff --git a/webapp/app/pods/components/translation-comments-subscriptions/component.ts b/webapp/app/pods/components/translation-comments-subscriptions/component.ts new file mode 100644 index 00000000..9edb1ac8 --- /dev/null +++ b/webapp/app/pods/components/translation-comments-subscriptions/component.ts @@ -0,0 +1,16 @@ +import Component from '@glimmer/component'; + +interface Args { + collaborators: any; + subscriptions: any; + onCreateSubscription: (user: any) => Promise; + onDeleteSubscription: (subscription: any) => Promise; +} + +export default class TranslationCommentsSubscriptions extends Component { + get filteredCollaborators() { + return this.args.collaborators + .filter((collaborator: any) => !collaborator.isPending) + .filter((collaborator: any) => collaborator.role !== 'BOT'); + } +} diff --git a/webapp/app/pods/components/translation-comments-subscriptions/item/component.js b/webapp/app/pods/components/translation-comments-subscriptions/item/component.js deleted file mode 100644 index e5116d91..00000000 --- a/webapp/app/pods/components/translation-comments-subscriptions/item/component.js +++ /dev/null @@ -1,41 +0,0 @@ -import {computed} from '@ember/object'; -import {inject as service} from '@ember/service'; -import {reads, bool} from '@ember/object/computed'; -import Component from '@ember/component'; - -// Attributes: -// collaborator: Object -// subscriptions: Array of -// onCreateSubscription: Function -// onDeleteSubscription: Function -export default Component.extend({ - classNameBindings: ['isCurrentUser:currentUser'], - tagName: 'li', - - session: service('session'), - currentUser: reads('session.credentials.user'), - - isCurrentUser: computed('currentUser.id', 'collaborator.user.id', function() { - return this.currentUser.id === this.collaborator.user.id; - }), - - isSubscribed: bool('subscription'), - - subscription: computed( - 'subscriptions.[]', - 'collaborator.user.id', - function() { - return this.subscriptions.find( - subscription => subscription.user.id === this.collaborator.user.id - ); - } - ), - - click() { - if (this.isSubscribed) { - this.onDeleteSubscription(this.subscription); - } else { - this.onCreateSubscription(this.collaborator.user); - } - } -}); diff --git a/webapp/app/pods/components/translation-comments-subscriptions/item/component.ts b/webapp/app/pods/components/translation-comments-subscriptions/item/component.ts new file mode 100644 index 00000000..4590664f --- /dev/null +++ b/webapp/app/pods/components/translation-comments-subscriptions/item/component.ts @@ -0,0 +1,44 @@ +import {action} from '@ember/object'; +import {inject as service} from '@ember/service'; +import {readOnly, bool} from '@ember/object/computed'; +import Component from '@glimmer/component'; +import Session from 'accent-webapp/services/session'; + +interface Args { + collaborator: any; + subscriptions: any; + onCreateSubscription: (user: any) => Promise; + onDeleteSubscription: (subscription: any) => Promise; +} + +export default class TranslationCommentsSubscriptionsItem extends Component< + Args +> { + @service('session') + session: Session; + + @readOnly('session.credentials.user') + currentUser: any; + + @bool('subscription') + isSubscribed: boolean; + + get isCurrentUser() { + return this.currentUser.id === this.args.collaborator.user.id; + } + + get subscription() { + return this.args.subscriptions.find((subscription: any) => { + return subscription.user.id === this.args.collaborator.user.id; + }); + } + + @action + async toggleSubscription() { + if (this.isSubscribed) { + await this.args.onDeleteSubscription(this.subscription); + } else { + await this.args.onCreateSubscription(this.args.collaborator.user); + } + } +} diff --git a/webapp/app/pods/components/translation-comments-subscriptions/item/styles.scss b/webapp/app/pods/components/translation-comments-subscriptions/item/styles.scss index 86413f69..de19ea91 100644 --- a/webapp/app/pods/components/translation-comments-subscriptions/item/styles.scss +++ b/webapp/app/pods/components/translation-comments-subscriptions/item/styles.scss @@ -1,11 +1,13 @@ -& { +@value transition-speed, transition-easing from 'accent-webapp/styles/variables/transitions'; + +.translation-comments-subscriptions-item { display: flex; align-items: flex-start; margin: 0 0 10px; font-size: 13px; color: #888; cursor: pointer; - transition: $transition-speed $transition-easing; + transition: transition-speed transition-easing; transition-property: color; &:last-child { @@ -21,7 +23,7 @@ } } -&.currentUser { +.translation-comments-subscriptions-item.currentUser { font-weight: bold; color: #444; } diff --git a/webapp/app/pods/components/translation-comments-subscriptions/item/template.hbs b/webapp/app/pods/components/translation-comments-subscriptions/item/template.hbs index fbd8395b..b03dc026 100644 --- a/webapp/app/pods/components/translation-comments-subscriptions/item/template.hbs +++ b/webapp/app/pods/components/translation-comments-subscriptions/item/template.hbs @@ -1,9 +1,16 @@ - +
              • + - - {{collaborator.user.fullname}} + + {{@collaborator.user.fullname}} - - {{collaborator.email}} + + {{@collaborator.email}} + - +
              • diff --git a/webapp/app/pods/components/translation-comments-subscriptions/styles.scss b/webapp/app/pods/components/translation-comments-subscriptions/styles.scss index 82a707a5..3832a82c 100644 --- a/webapp/app/pods/components/translation-comments-subscriptions/styles.scss +++ b/webapp/app/pods/components/translation-comments-subscriptions/styles.scss @@ -1,4 +1,6 @@ -& { +@value color-black from 'accent-webapp/styles/variables/colors'; + +.translation-comments-subscriptions { padding: 5px 0 20px 20px; border-left: 1px solid #eee; } @@ -10,6 +12,6 @@ font-size: 11px; font-weight: bold; font-style: normal; - color: $color-black; + color: color-black; color: var(--color-black); } diff --git a/webapp/app/pods/components/translation-comments-subscriptions/template.hbs b/webapp/app/pods/components/translation-comments-subscriptions/template.hbs index b3dd9f76..fa44444e 100644 --- a/webapp/app/pods/components/translation-comments-subscriptions/template.hbs +++ b/webapp/app/pods/components/translation-comments-subscriptions/template.hbs @@ -1,12 +1,14 @@ - - {{t "components.translation_comments_subscriptions.title"}} - +
                  + + {{t "components.translation_comments_subscriptions.title"}} + -{{#each filteredCollaborators key="id" as |collaborator|}} - -{{/each}} + {{#each this.filteredCollaborators key="id" as |collaborator|}} + + {{/each}} +
                diff --git a/webapp/app/pods/components/translation-conversation/component.js b/webapp/app/pods/components/translation-conversation/component.js deleted file mode 100644 index 6a2326f4..00000000 --- a/webapp/app/pods/components/translation-conversation/component.js +++ /dev/null @@ -1,13 +0,0 @@ -import Component from '@ember/component'; - -// Attributes -// permissions: Ember Object containing -// translation: Object -// comments: Array of -// collaborators: Array of -// subscriptions: Array of -// onCreateSubscription: Function -// onDeleteSubscription: Function -// onSelectPage: Function -// onSubmit: Function -export default Component.extend(); diff --git a/webapp/app/pods/components/translation-conversation/component.ts b/webapp/app/pods/components/translation-conversation/component.ts new file mode 100644 index 00000000..969885b1 --- /dev/null +++ b/webapp/app/pods/components/translation-conversation/component.ts @@ -0,0 +1,21 @@ +import Component from '@glimmer/component'; +import {action} from '@ember/object'; + +interface Args { + permissions: Record; + translation: any; + collaborators: any; + subscriptions: any; + comments: any; + onCreateSubscription: (user: any) => Promise; + onDeleteSubscription: (subscription: any) => Promise; + onSubmit: (text: string) => Promise; + onSelectPage: (page: number) => void; +} + +export default class TranslationConversation extends Component { + @action + focusTextarea(element: HTMLElement) { + element.querySelector('textarea')?.focus(); + } +} diff --git a/webapp/app/pods/components/translation-conversation/styles.scss b/webapp/app/pods/components/translation-conversation/styles.scss index 375baa79..7c2e085e 100644 --- a/webapp/app/pods/components/translation-conversation/styles.scss +++ b/webapp/app/pods/components/translation-conversation/styles.scss @@ -1,4 +1,4 @@ -& { +.translation-conversation { display: flex; width: 100%; } @@ -7,6 +7,10 @@ flex: 1 1 100%; } +.list { + margin-top: 30px; +} + .subscriptions { flex: 1 1 100%; max-width: 250px; diff --git a/webapp/app/pods/components/translation-conversation/template.hbs b/webapp/app/pods/components/translation-conversation/template.hbs index 83153f1f..340756b4 100644 --- a/webapp/app/pods/components/translation-conversation/template.hbs +++ b/webapp/app/pods/components/translation-conversation/template.hbs @@ -1,23 +1,29 @@ -
                - {{#if (get permissions "create_comment")}} - {{#unless translation.isRemoved}} - - {{/unless}} - {{/if}} +
                +
                + {{#if (get @permissions "create_comment")}} + {{#unless @translation.isRemoved}} +
                + +
                + {{/unless}} + {{/if}} - +
                + - -
                - -
                - + +
                +
                + +
                + +
                diff --git a/webapp/app/pods/components/translation-edit/component.js b/webapp/app/pods/components/translation-edit/component.js deleted file mode 100644 index ace7aee3..00000000 --- a/webapp/app/pods/components/translation-edit/component.js +++ /dev/null @@ -1,61 +0,0 @@ -import {computed} from '@ember/object'; -import {reads} from '@ember/object/computed'; -import Component from '@ember/component'; - -// Attributes: -// translation: Object -// permissions: Ember Object containing -// onUpdateText: Function -// onCorrectConflict: Function -// onUncorrectConflict: Function -export default Component.extend({ - isCorrectingConflict: false, - isUncorrectingConflict: false, - isUpdatingText: false, - - text: reads('translation.correctedText'), - samePreviousText: computed( - 'translation.{conflictedText,correctedText}', - function() { - return this.translation.conflictedText === this.translation.correctedText; - } - ), - - hasTextNotChanged: computed('text', 'translation.correctedText', function() { - if (!this.translation) return false; - - return this.text === this.translation.correctedText; - }), - - actions: { - correctConflict() { - this.set('isCorrectingConflict', true); - - this.onCorrectConflict(this.text).then(() => - this.set('isCorrectingConflict', false) - ); - }, - - uncorrectConflict() { - this.set('isUncorrectingConflict', true); - - this.onUncorrectConflict().then(() => - this.set('isUncorrectingConflict', false) - ); - }, - - updateText() { - this.set('isUpdatingText', true); - - this.onUpdateText(this.text).then(() => - this.set('isUpdatingText', false) - ); - }, - - changeText() { - if (!this.onChangeText) return; - - this.onChangeText(this.text); - } - } -}); diff --git a/webapp/app/pods/components/translation-edit/component.ts b/webapp/app/pods/components/translation-edit/component.ts new file mode 100644 index 00000000..2a06b4ea --- /dev/null +++ b/webapp/app/pods/components/translation-edit/component.ts @@ -0,0 +1,79 @@ +import {action} from '@ember/object'; +import Component from '@glimmer/component'; +import {tracked} from '@glimmer/tracking'; + +interface Args { + translation: any; + project: any; + permissions: Record; + onChangeText?: (text: string) => void; + onUpdateText: (text: string) => Promise; + onCorrectConflict: (text: string) => Promise; + onUncorrectConflict: () => Promise; +} + +export default class TranslationEdit extends Component { + @tracked + isCorrectingConflict = false; + + @tracked + isUncorrectingConflict = false; + + @tracked + isUpdatingText = false; + + @tracked + text = this.args.translation.correctedText; + + get samePreviousText() { + return ( + this.args.translation.conflictedText === + this.args.translation.correctedText + ); + } + + get hasTextNotChanged() { + if (!this.args.translation) return false; + + return this.text === this.args.translation.correctedText; + } + + @action + async correctConflict() { + this.isCorrectingConflict = true; + + await this.args.onCorrectConflict(this.text); + + this.isCorrectingConflict = false; + } + + @action + async uncorrectConflict() { + this.isUncorrectingConflict = true; + + await this.args.onUncorrectConflict(); + + this.isUncorrectingConflict = false; + } + + @action + async updateText() { + this.isUpdatingText = true; + + await this.args.onUpdateText(this.text); + + this.isUpdatingText = false; + } + + @action + changeText(text: string) { + this.text = text; + + this.args.onChangeText && this.args.onChangeText(text); + } + + @action + focusTextarea(element: HTMLElement) { + element.querySelector('textarea')?.focus(); + } +} diff --git a/webapp/app/pods/components/translation-edit/form/component.js b/webapp/app/pods/components/translation-edit/form/component.js deleted file mode 100644 index db3c3d1a..00000000 --- a/webapp/app/pods/components/translation-edit/form/component.js +++ /dev/null @@ -1,93 +0,0 @@ -import {inject as service} from '@ember/service'; -import {equal} from '@ember/object/computed'; -import {debounce} from '@ember/runloop'; -import {computed} from '@ember/object'; -import Component from '@ember/component'; - -import translationLintQuery from 'accent-webapp/queries/lint-translation'; - -const DEBOUNCE_LINT_MESSAGES = 1000; -const SMALL_INPUT_ROWS = 1; -const MEDIUM_INPUT_ROWS = 3; -const LARGE_INPUT_ROWS = 7; -const SMALL_INPUT_VALUE = 70; -const LARGE_INPUT_VALUE = 100; - -export default Component.extend({ - apollo: service('apollo'), - - lintMessages: () => [], - - rows: computed('value', function() { - if (!this.value) return SMALL_INPUT_ROWS; - if (this.value.length < SMALL_INPUT_VALUE) return SMALL_INPUT_ROWS; - if (this.value.length < LARGE_INPUT_VALUE) return MEDIUM_INPUT_ROWS; - - return LARGE_INPUT_ROWS; - }), - showTypeHints: true, - - isStringType: equal('valueType', 'STRING'), - isBooleanType: equal('valueType', 'BOOLEAN'), - isIntegerType: equal('valueType', 'INTEGER'), - isFloatType: equal('valueType', 'FLOAT'), - isEmptyType: equal('valueType', 'EMPTY'), - isNullType: equal('valueType', 'NULL'), - - unusedPlaceholders: computed('value', 'placeholders', function() { - return this.placeholders.reduce((memo, placeholder) => { - if (!this.value.includes(placeholder)) memo[placeholder] = true; - return memo; - }, {}); - }), - - didInsertElement() { - this.send('changeText'); - }, - - fetchLintMessages(event) { - return () => { - let text = this.value; - if (event) text = event.target.value; - - this.apollo.client - .query({ - fetchPolicy: 'network-only', - query: translationLintQuery, - variables: { - text, - projectId: this.projectId, - translationId: this.translationId - } - }) - .then(({data}) => { - if (this.isDestroyed) return; - - this.set( - 'lintMessages', - data.viewer.project.translation.lintMessages - ); - }); - }; - }, - - actions: { - changeText(event) { - debounce(this, this.fetchLintMessages(event), DEBOUNCE_LINT_MESSAGES); - - if (this.onKeyUp) this.onKeyUp(event); - }, - - replaceText(context, replacement) { - const wordToReplace = context.text.substring( - context.offset, - context.offset + context.length - ); - const wordRegexp = new RegExp(wordToReplace, 'g'); - const newText = this.value.replace(wordRegexp, replacement.value); - - this.set('value', newText); - this.send('changeText'); - } - } -}); diff --git a/webapp/app/pods/components/translation-edit/form/component.ts b/webapp/app/pods/components/translation-edit/form/component.ts new file mode 100644 index 00000000..a70465db --- /dev/null +++ b/webapp/app/pods/components/translation-edit/form/component.ts @@ -0,0 +1,125 @@ +import {inject as service} from '@ember/service'; +import {equal} from '@ember/object/computed'; +import {action} from '@ember/object'; +import Component from '@glimmer/component'; + +import translationLintQuery from 'accent-webapp/queries/lint-translation'; +import Apollo from 'accent-webapp/services/apollo'; +import {tracked} from '@glimmer/tracking'; +import {restartableTask} from 'ember-concurrency-decorators'; +import {timeout} from 'ember-concurrency'; + +const DEBOUNCE_LINT_MESSAGES = 1000; +const SMALL_INPUT_ROWS = 1; +const MEDIUM_INPUT_ROWS = 3; +const LARGE_INPUT_ROWS = 7; +const SMALL_INPUT_VALUE = 70; +const LARGE_INPUT_VALUE = 100; + +interface Context { + text: string; + offset: number; + length: number; +} + +interface Args { + projectId: string; + translationId: string; + disabled: boolean; + valueType: 'STRING' | 'BOOLEAN' | 'INTEGER' | 'FLOAT' | 'EMPTY' | 'NULL'; + value: string; + onSubmit: () => void; + showTypeHints?: boolean; + placeholders?: any; + onFocus?: () => void; + onBlur?: () => void; + onKeyUp?: (text: string) => void; +} + +export default class TranslationEditForm extends Component { + @service('apollo') + apollo: Apollo; + + @tracked + lintMessages: String[] = []; + + @tracked + showTypeHints = true; + + @equal('args.valueType', 'STRING') + isStringType: boolean; + + @equal('args.valueType', 'BOOLEAN') + isBooleanType: boolean; + + @equal('args.valueType', 'INTEGER') + isIntegerType: boolean; + + @equal('args.valueType', 'FLOAT') + isFloatType: boolean; + + @equal('args.valueType', 'EMPTY') + isEmptyType: boolean; + + @equal('args.valueType', 'NULL') + isNullType: boolean; + + get rows() { + if (!this.args.value) return SMALL_INPUT_ROWS; + if (this.args.value.length < LARGE_INPUT_VALUE) return MEDIUM_INPUT_ROWS; + if (this.args.value.length < SMALL_INPUT_VALUE) return SMALL_INPUT_ROWS; + + return LARGE_INPUT_ROWS; + } + + get unusedPlaceholders() { + return this.args.placeholders.reduce( + (memo: Record, placeholder: string) => { + if (!this.args.value.includes(placeholder)) memo[placeholder] = true; + return memo; + }, + {} + ); + } + + @action + changeText(event: Event) { + const target = event.target as HTMLInputElement; + + if (this.args.onKeyUp) this.args.onKeyUp(target.value); + + // eslint-disable-next-line @typescript-eslint/ban-ts-ignore + // @ts-ignore + this.fetchLintMessagesTask.perform(target.value); + } + + @restartableTask + *fetchLintMessagesTask(value: string) { + yield timeout(DEBOUNCE_LINT_MESSAGES); + + const {data} = yield this.apollo.client.query({ + fetchPolicy: 'network-only', + query: translationLintQuery, + variables: { + text: value, + projectId: this.args.projectId, + translationId: this.args.translationId, + }, + }); + + this.lintMessages = data.viewer.project.translation + .lintMessages as String[]; + } + + @action + replaceText(context: Context, replacement: any) { + const wordToReplace = context.text.substring( + context.offset, + context.offset + context.length + ); + const wordRegexp = new RegExp(wordToReplace, 'g'); + const newText = this.args.value.replace(wordRegexp, replacement.value); + + this.args.onKeyUp?.(newText); + } +} diff --git a/webapp/app/pods/components/translation-edit/form/styles.scss b/webapp/app/pods/components/translation-edit/form/styles.scss index 60cf6ca0..6d187d04 100644 --- a/webapp/app/pods/components/translation-edit/form/styles.scss +++ b/webapp/app/pods/components/translation-edit/form/styles.scss @@ -1,33 +1,36 @@ -& { +@value color-green, color-blue, color-true-black, color-error from 'accent-webapp/styles/variables/colors'; +@value font-primary from 'accent-webapp/styles/variables/fonts'; + +.translation-edit-form { height: 100%; -} -.ember-radio-button { - display: flex; - align-items: center; - padding: 10px; - margin-bottom: 3px; - border-radius: 3px; - font-weight: bold; - font-size: 13px; - color: #444; + :global(.ember-radio-button) { + display: flex; + align-items: center; + padding: 10px; + margin-bottom: 3px; + border-radius: 3px; + font-weight: bold; + font-size: 13px; + color: #444; - &.checked { - background: lighten($color-green, 45%); - color: darken($color-green, 25%); - } + &.checked { + background: lighten(color-green, 45%); + color: darken(color-green, 25%); + } - input { - margin-right: 8px; + input { + margin-right: 8px; + } } } .label { width: 100%; padding: 5px 5px 5px 8px; - border-left: 2px solid lighten($color-blue, 40%); + border-left: 2px solid lighten(color-blue, 40%); margin-bottom: 5px; - background: lighten($color-blue, 46%); + background: lighten(color-blue, 46%); font-size: 12px; color: #888; } @@ -42,7 +45,7 @@ &::placeholder { opacity: 0.2; font-style: italic; - font-family: $font-primary; + font-family: font-primary; } } @@ -55,19 +58,19 @@ display: flex; align-items: center; padding: 10px 10px 0; - background: lighten($color-blue, 46%); - border-left: 2px solid lighten($color-blue, 40%); + background: lighten(color-blue, 46%); + border-left: 2px solid lighten(color-blue, 40%); font-size: 13px; font-weight: bold; - color: $color-blue; + color: color-blue; } .placeholders-text { margin-bottom: 6px; padding: 5px 10px 8px; - background: lighten($color-blue, 46%); - border-left: 2px solid lighten($color-blue, 40%); - color: darken($color-blue, 15%); + background: lighten(color-blue, 46%); + border-left: 2px solid lighten(color-blue, 40%); + color: darken(color-blue, 15%); } .placeholders-text-content { @@ -78,13 +81,13 @@ display: flex; align-items: center; padding-left: 12px; - border-left: 2px solid lighten($color-true-black, 80%); + border-left: 2px solid lighten(color-true-black, 80%); font-size: 14px; - color: darken($color-blue, 15%); + color: darken(color-blue, 15%); &.placeholders-item--warning { - border-color: lighten($color-error, 20%); - color: lighten($color-error, 10%); + border-color: lighten(color-error, 20%); + color: lighten(color-error, 10%); } } @@ -92,12 +95,12 @@ margin-right: 5px; width: 14px; height: 14px; - stroke: lighten($color-error, 15%); + stroke: lighten(color-error, 15%); } .placeholders-title-icon { width: 14px; height: 14px; margin-right: 6px; - stroke: darken($color-blue, 10%); + stroke: darken(color-blue, 10%); } diff --git a/webapp/app/pods/components/translation-edit/form/template.hbs b/webapp/app/pods/components/translation-edit/form/template.hbs index 0d6c66f6..4fcb2474 100644 --- a/webapp/app/pods/components/translation-edit/form/template.hbs +++ b/webapp/app/pods/components/translation-edit/form/template.hbs @@ -1,90 +1,91 @@ -{{#if this.isBooleanType}} - - {{t "components.translation_edit.form.boolean_type_notice"}} - +
                + {{#if this.isBooleanType}} + + {{t "components.translation_edit.form.boolean_type_notice"}} + - - {{t "components.translation_edit.form.true_option"}} - + + {{t "components.translation_edit.form.true_option"}} + - - {{t "components.translation_edit.form.false_option"}} - -{{else}} - {{#if this.showTypeHints}} - {{#if this.isIntegerType}} - - {{t "components.translation_edit.form.integer_type_notice"}} - + + {{t "components.translation_edit.form.false_option"}} + + {{else}} + {{#if this.showTypeHints}} + {{#if this.isIntegerType}} + + {{t "components.translation_edit.form.integer_type_notice"}} + + {{/if}} + + {{#if this.isFloatType}} + + {{t "components.translation_edit.form.float_type_notice"}} + + {{/if}} + + {{#if this.isEmptyType}} + + {{t "components.translation_edit.form.empty_type_notice"}} + + {{/if}} + + {{#if this.isNullType}} + + {{t "components.translation_edit.form.null_type_notice"}} + + {{/if}} {{/if}} - {{#if this.isFloatType}} - - {{t "components.translation_edit.form.float_type_notice"}} - - {{/if}} + {{#if this.placeholders}} +
                + + {{inline-svg "assets/code.svg" local-class="placeholders-title-icon"}} + {{t "components.translation_edit.form.placeholders.title"}} + - {{#if this.isEmptyType}} - - {{t "components.translation_edit.form.empty_type_notice"}} - - {{/if}} +
                +

                + {{t "components.translation_edit.form.placeholders.text"}} +

                +
                - {{#if this.isNullType}} - - {{t "components.translation_edit.form.null_type_notice"}} - - {{/if}} - {{/if}} - - {{#if this.placeholders}} -
                - - {{inline-svg "assets/code.svg" class="placeholders-title-icon"}} - {{t "components.translation_edit.form.placeholders.title"}} - - -
                -

                - {{t "components.translation_edit.form.placeholders.text"}} -

                +
                  + {{#each this.placeholders as |placeholder|}} +
                • + + {{placeholder}} + +
                • + {{/each}} +
                + {{/if}} -
                  - {{#each this.placeholders as |placeholder|}} -
                • - - {{placeholder}} - -
                • - {{/each}} -
                -
                + {{/if}} - - -{{/if}} - -{{#each this.lintMessages as |message|}} - -{{/each}} + {{#each this.lintMessages as |message|}} + + {{/each}} +
                diff --git a/webapp/app/pods/components/translation-edit/lint-message/component.js b/webapp/app/pods/components/translation-edit/lint-message/component.js deleted file mode 100644 index 1d07a2fd..00000000 --- a/webapp/app/pods/components/translation-edit/lint-message/component.js +++ /dev/null @@ -1,43 +0,0 @@ -import Component from '@ember/component'; -import {computed} from '@ember/object'; -import {gt} from '@ember/object/computed'; - -const REPLACEMENTS_LIMIT = 10; - -export default Component.extend({ - multipleReplacements: gt('mappedReplacements', 1), - - selectedReplacement: computed('attrs.message.replacements', function() { - const replacement = this.attrs.message.replacements[0]; - - return { - label: replacement.value, - value: replacement.value - }; - }), - - mappedReplacements: computed('attrs.message.replacements', function() { - return this.attrs.message.replacements - .slice(0, REPLACEMENTS_LIMIT) - .map(replacement => { - return { - label: replacement.value, - value: replacement.value - }; - }); - }), - - actions: { - replaceTextSelected() { - const replacement = this.selectedReplacement; - this.onReplaceText(this.attrs.message.context, replacement); - }, - - replaceText(value) { - const replacement = this.attrs.message.replacements.find( - replacement => replacement.value === value - ); - this.onReplaceText(this.attrs.message.context, replacement); - } - } -}); diff --git a/webapp/app/pods/components/translation-edit/lint-message/component.ts b/webapp/app/pods/components/translation-edit/lint-message/component.ts new file mode 100644 index 00000000..9cefeb85 --- /dev/null +++ b/webapp/app/pods/components/translation-edit/lint-message/component.ts @@ -0,0 +1,61 @@ +import Component from '@glimmer/component'; +import {action} from '@ember/object'; +import {gt} from '@ember/object/computed'; + +const REPLACEMENTS_LIMIT = 10; + +interface Context { + text: string; + offset: number; + length: number; +} + +interface Args { + message: any; + onReplaceText: ( + context: Context, + replacement: {label: string; value: string} + ) => void; +} + +export default class LintMessage extends Component { + @gt('mappedReplacements', 1) + multipleReplacements: boolean; + + get selectedReplacement() { + const replacement = this.args.message.replacements[0]; + + return { + label: replacement.value, + value: replacement.value, + }; + } + + get mappedReplacements() { + return this.args.message.replacements + .slice(0, REPLACEMENTS_LIMIT) + .map((replacement: any) => { + return { + label: replacement.value, + value: replacement.value, + }; + }); + } + + @action + replaceTextSelected() { + const replacement = this.selectedReplacement; + this.args.onReplaceText(this.args.message.context, replacement); + } + + @action + replaceText({value}: {value: string}) { + const replacement = this.args.message.replacements.find( + (replacement: {label: string; value: string}) => { + return replacement.value === value; + } + ); + + this.args.onReplaceText(this.args.message.context, replacement); + } +} diff --git a/webapp/app/pods/components/translation-edit/lint-message/styles.scss b/webapp/app/pods/components/translation-edit/lint-message/styles.scss index 6f29dd58..8e7033ec 100644 --- a/webapp/app/pods/components/translation-edit/lint-message/styles.scss +++ b/webapp/app/pods/components/translation-edit/lint-message/styles.scss @@ -1,22 +1,46 @@ -& { +@value color-error, color-success from 'accent-webapp/styles/variables/colors'; + +.translation-edit-lint-message { display: flex; align-items: center; padding: 2px 8px; margin-bottom: 5px; background: #fff; - border-left: 2px solid lighten($color-error, 10%); + border-left: 2px solid lighten(color-error, 10%); font-size: 12px; + + :global(.ember-power-select-trigger) { + border: 0; + margin-left: 4px; + padding: 3px 8px 3px 6px; + background: transparent; + font-size: 12px; + } + + :global(.ember-power-select-status-icon):after { + left: -12px; + color: #aaa; + } + + :global(.ember-power-select-selected-item) { + margin-right: 10px; + } + + :global(.ember-basic-dropdown-trigger)[aria-expanded='true'], + :global(.ember-power-select-status-icon)::after { + left: -14px; + } } .description { - color: lighten($color-error, 10%); + color: lighten(color-error, 10%); } .text { padding: 0 4px; margin-left: 5px; - color: $color-error; - background: lighten($color-error, 38%); + color: color-error; + background: lighten(color-error, 38%); font-weight: bold; } @@ -26,36 +50,14 @@ } .replaceButton { - margin-left: 10px; -} - -.ember-power-select-trigger { - border: 0; - margin-left: 4px; - padding: 3px 8px 3px 6px; - background: transparent; - font-size: 12px; + margin-left: 10px !important; } .single-replacement { margin-left: 4px; padding: 0 4px; - background: lighten($color-success, 38%); - color: $color-success; + background: lighten(color-success, 38%); + color: color-success; font-size: 12px; font-weight: bold; } - -.ember-power-select-status-icon:after { - left: -12px; - color: #aaa; -} - -.ember-power-select-selected-item { - margin-right: 10px; -} - -.ember-basic-dropdown-trigger[aria-expanded='true'] - .ember-power-select-status-icon::after { - left: -14px; -} diff --git a/webapp/app/pods/components/translation-edit/lint-message/template.hbs b/webapp/app/pods/components/translation-edit/lint-message/template.hbs index 23c43d90..92e1082d 100644 --- a/webapp/app/pods/components/translation-edit/lint-message/template.hbs +++ b/webapp/app/pods/components/translation-edit/lint-message/template.hbs @@ -1,29 +1,32 @@ -{{@message.rule.description}} -{{@message.text}} +
                + {{@message.rule.description}} + {{@message.text}} -{{#if this.mappedReplacements}} - - {{t "components.translation_edit.lint_message.arrow"}} - - - {{#if this.multipleReplacements}} - - {{else}} - - {{this.selectedReplacement.label}} + {{#if this.mappedReplacements}} + + {{t "components.translation_edit.lint_message.arrow"}} - {{/if}} - {{#if @message.context}} - + {{#if this.multipleReplacements}} + + {{else}} + + {{this.selectedReplacement.label}} + + {{/if}} + + {{#if @message.context}} + + {{/if}} {{/if}} -{{/if}} +
                diff --git a/webapp/app/pods/components/translation-edit/styles.scss b/webapp/app/pods/components/translation-edit/styles.scss index e61f50ec..45e59f23 100644 --- a/webapp/app/pods/components/translation-edit/styles.scss +++ b/webapp/app/pods/components/translation-edit/styles.scss @@ -1,15 +1,18 @@ -& { +@value transition-speed, transition-easing from 'accent-webapp/styles/variables/transitions'; +@value color-grey, color-green from 'accent-webapp/styles/variables/colors'; + +.translation-edit { margin-top: 30px; } .previousText { margin-bottom: 15px; - color: $color-grey; + color: color-grey; font-size: 12px; } .previousText-label { - color: darken($color-grey, 10%); + color: darken(color-grey, 10%); font-weight: bold; } @@ -36,9 +39,9 @@ font-size: 13px; font-weight: bold; text-decoration: none; - color: $color-green; + color: color-green; color: var(--color-primary); - transition: $transition-speed $transition-easing; + transition: transition-speed transition-easing; transition-property: color, opacity; &:focus, @@ -51,9 +54,9 @@ width: 18px; height: 18px; margin-right: 3px; - stroke: $color-green; + stroke: color-green; stroke: var(--color-primary); - transition: $transition-speed $transition-easing; + transition: transition-speed transition-easing; transition-property: stroke; } @@ -62,14 +65,14 @@ justify-content: flex-end; align-items: center; - & > .button { + & > :global(.button) { margin-left: 10px; } } .actions-updatedAt { margin-right: 10px; - color: $color-grey; + color: color-grey; font-size: 11px; font-style: italic; } diff --git a/webapp/app/pods/components/translation-edit/template.hbs b/webapp/app/pods/components/translation-edit/template.hbs index 4421b212..b13dce59 100644 --- a/webapp/app/pods/components/translation-edit/template.hbs +++ b/webapp/app/pods/components/translation-edit/template.hbs @@ -1,115 +1,119 @@ -{{#if translation.isConflicted}} - {{#if translation.conflictedText}} - {{#unless samePreviousText}} -
                - - {{t "components.translation_edit.previous_text"}} - -
                {{translation.conflictedText}}
                -
                - {{/unless}} +
                + {{#if @translation.isConflicted}} + {{#if @translation.conflictedText}} + {{#unless this.samePreviousText}} +
                + + {{t "components.translation_edit.previous_text"}} + +
                {{@translation.conflictedText}}
                +
                + {{/unless}} + {{/if}} {{/if}} -{{/if}} -{{#if translation.id}} - -{{/if}} + {{#if @translation.id}} +
                + +
                + {{/if}} -{{#if translation}} - {{#if translation.isConflicted}} - {{#unless translation.isRemoved}} -
                - -
                -
                - {{t "components.translation_edit.last_updated_label"}} - -
                - {{#if (get permissions "update_translation")}} - - {{t "components.translation_edit.update_text"}} - - {{/if}} - {{#if (get permissions "correct_translation")}} - - {{inline-svg "/assets/check.svg" class="button-icon"}} - {{t "components.translation_edit.correct_button"}} - - {{/if}} -
                -
                - {{/unless}} - {{else}} - {{#unless translation.isRemoved}} -
                - -
                -
                - {{t "components.translation_edit.last_updated_label"}} - -
                - {{#if (get permissions "update_translation")}} - - {{t "components.translation_edit.update_text"}} - - {{/if}} - {{#unless translation.version}} - {{#if (get permissions "uncorrect_translation")}} - +
                + {{#if @translation.sourceTranslation}} + - {{inline-svg "/assets/revert.svg" class="button-icon"}} - {{t "components.translation_edit.uncorrect_button"}} + {{t "components.translation_edit.source_translation"}} + + {{/if}} +
                +
                +
                + {{t "components.translation_edit.last_updated_label"}} + +
                + {{#if (get @permissions "update_translation")}} + + {{t "components.translation_edit.update_text"}} {{/if}} - {{/unless}} + {{#if (get @permissions "correct_translation")}} + + {{inline-svg "/assets/check.svg" class="button-icon"}} + {{t "components.translation_edit.correct_button"}} + + {{/if}} +
                -
                - {{/unless}} + {{/unless}} + {{else}} + {{#unless @translation.isRemoved}} +
                +
                + {{#if @translation.sourceTranslation}} + + {{t "components.translation_edit.source_translation"}} + + {{/if}} +
                +
                +
                + {{t "components.translation_edit.last_updated_label"}} + +
                + {{#if (get @permissions "update_translation")}} + + {{t "components.translation_edit.update_text"}} + + {{/if}} + {{#unless @translation.version}} + {{#if (get @permissions "uncorrect_translation")}} + + {{inline-svg "/assets/revert.svg" class="button-icon"}} + {{t "components.translation_edit.uncorrect_button"}} + + {{/if}} + {{/unless}} +
                +
                + {{/unless}} + {{/if}} {{/if}} -{{/if}} +
                diff --git a/webapp/app/pods/components/translation-navigation/component.js b/webapp/app/pods/components/translation-navigation/component.js deleted file mode 100644 index d16551ea..00000000 --- a/webapp/app/pods/components/translation-navigation/component.js +++ /dev/null @@ -1,7 +0,0 @@ -import Component from '@ember/component'; - -// Attributes: -// project: Object -// permissions: Ember Object containing -// translation: Object -export default Component.extend(); diff --git a/webapp/app/pods/components/translation-navigation/component.ts b/webapp/app/pods/components/translation-navigation/component.ts new file mode 100644 index 00000000..7a24b9e4 --- /dev/null +++ b/webapp/app/pods/components/translation-navigation/component.ts @@ -0,0 +1,9 @@ +import Component from '@glimmer/component'; + +interface Args { + project: any; + permissions: Record; + translation: any; +} + +export default class TranslationNavigation extends Component {} diff --git a/webapp/app/pods/components/translation-navigation/template.hbs b/webapp/app/pods/components/translation-navigation/template.hbs index 7f5e7293..bc9c202a 100644 --- a/webapp/app/pods/components/translation-navigation/template.hbs +++ b/webapp/app/pods/components/translation-navigation/template.hbs @@ -1,26 +1,28 @@
                - {{document.path}} + {{this.document.path}} . - {{documentFormatItem.extension}} + {{this.documentFormatItem.extension}}
                @@ -24,22 +24,22 @@
                - {{#if revisionOperations.length}} + {{#if this.revisionOperations.length}}
                - +
                {{/if}}
                diff --git a/webapp/app/pods/logged-in/project/files/controller.js b/webapp/app/pods/logged-in/project/files/controller.js deleted file mode 100644 index 1ad0e880..00000000 --- a/webapp/app/pods/logged-in/project/files/controller.js +++ /dev/null @@ -1,69 +0,0 @@ -import {inject as service} from '@ember/service'; -import {not, readOnly, and} from '@ember/object/computed'; -import Controller from '@ember/controller'; -import documentDeleteQuery from 'accent-webapp/queries/delete-document'; -import documentUpdateQuery from 'accent-webapp/queries/update-document'; - -const FLASH_MESSAGE_DELETE_SUCCESS = - 'pods.document.index.flash_messages.delete_success'; -const FLASH_MESSAGE_DELETE_ERROR = - 'pods.document.index.flash_messages.delete_error'; -const FLASH_MESSAGE_UPDATE_SUCCESS = - 'pods.document.index.flash_messages.update_success'; -const FLASH_MESSAGE_UPDATE_ERROR = - 'pods.document.index.flash_messages.update_error'; - -export default Controller.extend({ - intl: service('intl'), - flashMessages: service(), - apolloMutate: service('apollo-mutate'), - globalState: service('global-state'), - - page: 1, - - emptyEntries: not('model.documents', undefined), - permissions: readOnly('globalState.permissions'), - showSkeleton: and('emptyEntries', 'model.loading'), - - actions: { - deleteDocument(documentEntity) { - return this.apolloMutate - .mutate({ - mutation: documentDeleteQuery, - variables: { - documentId: documentEntity.id - } - }) - .then(() => { - this.flashMessages.success(this.intl.t(FLASH_MESSAGE_DELETE_SUCCESS)); - this.send('onRefresh'); - }) - .catch(() => - this.flashMessages.error(this.intl.t(FLASH_MESSAGE_DELETE_ERROR)) - ); - }, - - updateDocument(documentEntity, path) { - return this.apolloMutate - .mutate({ - mutation: documentUpdateQuery, - variables: { - documentId: documentEntity.id, - path - } - }) - .then(() => { - this.flashMessages.success(this.intl.t(FLASH_MESSAGE_UPDATE_SUCCESS)); - this.send('onRefresh'); - }) - .catch(() => - this.flashMessages.error(this.intl.t(FLASH_MESSAGE_UPDATE_ERROR)) - ); - }, - - selectPage(page) { - window.scroll(0, 0); - this.set('page', page); - } - } -}); diff --git a/webapp/app/pods/logged-in/project/files/controller.ts b/webapp/app/pods/logged-in/project/files/controller.ts new file mode 100644 index 00000000..fca33fa7 --- /dev/null +++ b/webapp/app/pods/logged-in/project/files/controller.ts @@ -0,0 +1,88 @@ +import {inject as service} from '@ember/service'; +import {action} from '@ember/object'; +import {equal, readOnly, and} from '@ember/object/computed'; +import Controller from '@ember/controller'; +import documentDeleteQuery from 'accent-webapp/queries/delete-document'; +import documentUpdateQuery from 'accent-webapp/queries/update-document'; +import IntlService from 'ember-intl/services/intl'; +import FlashMessages from 'ember-cli-flash/services/flash-messages'; +import ApolloMutate from 'accent-webapp/services/apollo-mutate'; +import GlobalState from 'accent-webapp/services/global-state'; +import {tracked} from '@glimmer/tracking'; + +const FLASH_MESSAGE_DELETE_SUCCESS = + 'pods.document.index.flash_messages.delete_success'; +const FLASH_MESSAGE_DELETE_ERROR = + 'pods.document.index.flash_messages.delete_error'; +const FLASH_MESSAGE_UPDATE_SUCCESS = + 'pods.document.index.flash_messages.update_success'; +const FLASH_MESSAGE_UPDATE_ERROR = + 'pods.document.index.flash_messages.update_error'; + +export default class FilesController extends Controller { + @service('intl') + intl: IntlService; + + @service('flash-messages') + flashMessages: FlashMessages; + + @service('apollo-mutate') + apolloMutate: ApolloMutate; + + @service('global-state') + globalState: GlobalState; + + @tracked + page = 1; + + @equal('model.documents', undefined) + emptyEntries: boolean; + + @readOnly('globalState.permissions') + permissions: any; + + @and('emptyEntries', 'model.loading') + showSkeleton: boolean; + + @action + async deleteDocument(documentEntity: any) { + try { + await this.apolloMutate.mutate({ + mutation: documentDeleteQuery, + variables: { + documentId: documentEntity.id, + }, + }); + + this.flashMessages.success(this.intl.t(FLASH_MESSAGE_DELETE_SUCCESS)); + this.send('onRefresh'); + } catch (error) { + this.flashMessages.error(this.intl.t(FLASH_MESSAGE_DELETE_ERROR)); + } + } + + @action + async updateDocument(documentEntity: any, path: string) { + try { + await this.apolloMutate.mutate({ + mutation: documentUpdateQuery, + variables: { + documentId: documentEntity.id, + path, + }, + }); + + this.flashMessages.success(this.intl.t(FLASH_MESSAGE_UPDATE_SUCCESS)); + this.send('onRefresh'); + } catch (error) { + this.flashMessages.error(this.intl.t(FLASH_MESSAGE_UPDATE_ERROR)); + } + } + + @action + selectPage(page: number) { + window.scroll(0, 0); + + this.page = page; + } +} diff --git a/webapp/app/pods/logged-in/project/files/export/controller.js b/webapp/app/pods/logged-in/project/files/export/controller.js deleted file mode 100644 index a09a2e0c..00000000 --- a/webapp/app/pods/logged-in/project/files/export/controller.js +++ /dev/null @@ -1,79 +0,0 @@ -import {computed} from '@ember/object'; -import {inject as service} from '@ember/service'; -import {reads, empty} from '@ember/object/computed'; -import Controller from '@ember/controller'; - -export default Controller.extend({ - fileSaver: service('file-saver'), - globalState: service('global-state'), - - queryParams: ['revisionFilter', 'documentFormatFilter', 'orderByFilter'], - - exportLoading: true, - fileRender: null, - documentFormatFilter: null, - orderByFilter: null, - revisionFilter: null, - - project: reads('model.projectModel.project'), - revisions: reads('project.revisions'), - documents: reads('model.fileModel.documents.entries'), - showLoading: reads('model.fileModel.loading'), - exportButtonDisabled: empty('fileRender'), - - revision: computed('revisions', 'revisionFilter', function() { - if (!this.revisions) return; - - return this.revisions.find(({id}) => id === this.revisionFilter); - }), - - document: computed('documents', 'model.fileId', function() { - if (!this.documents) return; - - return this.documents.find(({id}) => id === this.model.fileId); - }), - - documentFormatItem: computed('document.format', function() { - if (!this.globalState.documentFormats) return {}; - - return this.globalState.documentFormats.find( - ({slug}) => slug === this.document.format - ); - }), - - fileExtension: computed( - 'documentFormatFilter', - 'document.format', - function() { - if (!this.globalState.documentFormats) return ''; - - const format = this.documentFormatFilter || this.document.format; - const documentFormatItem = this.globalState.documentFormats.find( - ({slug}) => slug === format - ); - if (!documentFormatItem) return ''; - - return documentFormatItem.extension; - } - ), - - actions: { - closeModal() { - this.transitionToRoute('logged-in.project.files', this.project.id); - }, - - onFileLoaded(content) { - this.set('fileRender', content); - this.set('exportLoading', false); - }, - - exportFile() { - const blob = new Blob([this.fileRender], { - type: 'charset=utf-8' - }); - const filename = `${this.document.path}.${this.fileExtension}`; - - this.fileSaver.saveAs(blob, filename); - } - } -}); diff --git a/webapp/app/pods/logged-in/project/files/export/controller.ts b/webapp/app/pods/logged-in/project/files/export/controller.ts new file mode 100644 index 00000000..d526775e --- /dev/null +++ b/webapp/app/pods/logged-in/project/files/export/controller.ts @@ -0,0 +1,111 @@ +import {action} from '@ember/object'; +import {inject as service} from '@ember/service'; +import {readOnly, empty} from '@ember/object/computed'; +import Controller from '@ember/controller'; +import FileSaver from 'accent-webapp/services/file-saver'; +import GlobalState from 'accent-webapp/services/global-state'; +import {tracked} from '@glimmer/tracking'; +import RouterService from '@ember/routing/router-service'; + +export default class ExportController extends Controller { + @service('file-saver') + fileSaver: FileSaver; + + @service('global-state') + globalState: GlobalState; + + @service('router') + router: RouterService; + + queryParams = ['revisionFilter', 'documentFormatFilter', 'orderByFilter']; + + @tracked + exportLoading = true; + + @tracked + fileRender: any = null; + + @tracked + documentFormatFilter = null; + + @tracked + orderByFilter = null; + + @tracked + revisionFilter = null; + + @readOnly('model.projectModel.project') + project: any; + + @readOnly('project.revisions') + revisions: any; + + @readOnly('model.fileModel.documents.entries') + documents: any; + + @readOnly('model.fileModel.loading') + showLoading: boolean; + + @empty('fileRender') + exportButtonDisabled: boolean; + + get revision() { + if (!this.revisions) return; + + return this.revisions.find( + ({id}: {id: string}) => id === this.revisionFilter + ); + } + + get document() { + if (!this.documents) return; + + return this.documents.find( + ({id}: {id: string}) => id === this.model.fileId + ); + } + + get documentFormatItem() { + if (!this.globalState.documentFormats) return {}; + + return this.globalState.documentFormats.find( + ({slug}) => slug === this.document.format + ); + } + + get fileExtension() { + if (!this.globalState.documentFormats) return ''; + + const format = this.documentFormatFilter || this.document.format; + + const documentFormatItem = this.globalState.documentFormats.find( + ({slug}) => slug === format + ); + + if (!documentFormatItem) return ''; + + return documentFormatItem.extension; + } + + @action + closeModal() { + this.router.transitionTo('logged-in.project.files', this.project.id); + } + + @action + onFileLoaded(content: any) { + this.fileRender = content; + this.exportLoading = false; + } + + @action + exportFile() { + const blob = new Blob([this.fileRender], { + type: 'charset=utf-8', + }); + + const filename = `${this.document.path}.${this.fileExtension}`; + + this.fileSaver.saveAs(blob, filename); + } +} diff --git a/webapp/app/pods/logged-in/project/files/export/route.js b/webapp/app/pods/logged-in/project/files/export/route.js deleted file mode 100644 index d06da683..00000000 --- a/webapp/app/pods/logged-in/project/files/export/route.js +++ /dev/null @@ -1,37 +0,0 @@ -import {inject as service} from '@ember/service'; -import Route from '@ember/routing/route'; -import RSVP from 'rsvp'; - -export default Route.extend({ - exporter: service('exporter'), - - queryParams: { - revisionFilter: { - refreshModel: true - }, - documentFormatFilter: { - refreshModel: true - }, - orderByFilter: { - refreshModel: true - } - }, - - model({fileId}) { - return RSVP.hash({ - projectModel: this.modelFor('logged-in.project'), - fileModel: this.modelFor('logged-in.project.files'), - fileId - }); - }, - - resetController(controller, isExiting) { - controller.set('exportLoading', true); - - if (isExiting) { - controller.setProperties({ - fileRender: null - }); - } - } -}); diff --git a/webapp/app/pods/logged-in/project/files/export/route.ts b/webapp/app/pods/logged-in/project/files/export/route.ts new file mode 100644 index 00000000..7745089c --- /dev/null +++ b/webapp/app/pods/logged-in/project/files/export/route.ts @@ -0,0 +1,37 @@ +import {inject as service} from '@ember/service'; +import Route from '@ember/routing/route'; +import Exporter from 'accent-webapp/services/exporter'; +import ExportController from 'accent-webapp/pods/logged-in/project/files/export/controller'; + +export default class ExportRoute extends Route { + @service('exporter') + exporter: Exporter; + + queryParams = { + revisionFilter: { + refreshModel: true, + }, + documentFormatFilter: { + refreshModel: true, + }, + orderByFilter: { + refreshModel: true, + }, + }; + + model({fileId}: {fileId: string}) { + return { + projectModel: this.modelFor('logged-in.project'), + fileModel: this.modelFor('logged-in.project.files'), + fileId, + }; + } + + resetController(controller: ExportController, isExiting: boolean) { + controller.exportLoading = true; + + if (isExiting) { + controller.fileRender = null; + } + } +} diff --git a/webapp/app/pods/logged-in/project/files/export/template.hbs b/webapp/app/pods/logged-in/project/files/export/template.hbs index dd455484..b5cef8cb 100644 --- a/webapp/app/pods/logged-in/project/files/export/template.hbs +++ b/webapp/app/pods/logged-in/project/files/export/template.hbs @@ -1,6 +1,6 @@ - + -
                - {{document.path}} + {{this.document.path}} . - {{documentFormatItem.extension}} + {{this.documentFormatItem.extension}}
              {{inline-svg "/assets/edit-in-place.svg" class="button-icon"}} @@ -39,26 +39,26 @@ {{t "components.project_file_operations.export"}} - {{#if exportLoading}} + {{#if this.exportLoading}} {{/if}} diff --git a/webapp/app/pods/logged-in/project/files/jipt/controller.js b/webapp/app/pods/logged-in/project/files/jipt/controller.js deleted file mode 100644 index ca8a9aa8..00000000 --- a/webapp/app/pods/logged-in/project/files/jipt/controller.js +++ /dev/null @@ -1,71 +0,0 @@ -import {computed} from '@ember/object'; -import {inject as service} from '@ember/service'; -import {reads, empty} from '@ember/object/computed'; -import Controller from '@ember/controller'; - -export default Controller.extend({ - fileSaver: service('file-saver'), - globalState: service('global-state'), - - queryParams: ['documentFormatFilter'], - - documentFormatFilter: null, - exportLoading: true, - fileRender: null, - - project: reads('model.projectModel.project'), - revisions: reads('project.revisions'), - documents: reads('model.fileModel.documents.entries'), - showLoading: reads('model.fileModel.loading'), - exportButtonDisabled: empty('fileRender'), - - document: computed('documents', 'model.fileId', function() { - if (!this.documents) return; - - return this.documents.find(({id}) => id === this.model.fileId); - }), - - documentFormatItem: computed('document.format', function() { - if (!this.globalState.documentFormats) return {}; - - return this.globalState.documentFormats.find( - ({slug}) => slug === this.document.format - ); - }), - - fileExtension: computed( - 'documentFormatFilter', - 'document.format', - function() { - if (!this.globalState.documentFormats) return ''; - - const format = this.documentFormatFilter || this.document.format; - const documentFormatItem = this.globalState.documentFormats.find( - ({slug}) => slug === format - ); - if (!documentFormatItem) return ''; - - return documentFormatItem.extension; - } - ), - - actions: { - closeModal() { - this.transitionToRoute('logged-in.project.files', this.project.id); - }, - - onFileLoaded(content) { - this.set('fileRender', content); - this.set('exportLoading', false); - }, - - exportFile() { - const blob = new Blob([this.fileRender], { - type: 'charset=utf-8' - }); - const filename = `${this.document.path}.${this.fileExtension}`; - - this.fileSaver.saveAs(blob, filename); - } - } -}); diff --git a/webapp/app/pods/logged-in/project/files/jipt/controller.ts b/webapp/app/pods/logged-in/project/files/jipt/controller.ts new file mode 100644 index 00000000..a2cbd40d --- /dev/null +++ b/webapp/app/pods/logged-in/project/files/jipt/controller.ts @@ -0,0 +1,97 @@ +import {action} from '@ember/object'; +import {inject as service} from '@ember/service'; +import {readOnly, empty} from '@ember/object/computed'; +import Controller from '@ember/controller'; +import FileSaver from 'accent-webapp/services/file-saver'; +import GlobalState from 'accent-webapp/services/global-state'; +import {tracked} from '@glimmer/tracking'; +import RouterService from '@ember/routing/router-service'; + +export default class JIPTController extends Controller { + @service('file-saver') + fileSaver: FileSaver; + + @service('global-state') + globalState: GlobalState; + + @service('router') + router: RouterService; + + queryParams = ['documentFormatFilter']; + + @tracked + documentFormatFilter = null; + + @tracked + exportLoading = true; + + @tracked + fileRender: any = null; + + @readOnly('model.projectModel.project') + project: any; + + @readOnly('project.revisions') + revisions: any; + + @readOnly('model.fileModel.documents.entries') + documents: any; + + @readOnly('model.fileModel.loading') + showLoading: boolean; + + @empty('fileRender') + exportButtonDisabled: boolean; + + get document() { + if (!this.documents) return; + + return this.documents.find(({id}: {id: string}) => { + return id === this.model.fileId; + }); + } + + get documentFormatItem() { + if (!this.globalState.documentFormats) return {}; + + return this.globalState.documentFormats.find(({slug}) => { + return slug === this.document.format; + }); + } + + get fileExtension() { + if (!this.globalState.documentFormats) return ''; + + const format = this.documentFormatFilter || this.document.format; + + const documentFormatItem = this.globalState.documentFormats.find( + ({slug}) => slug === format + ); + + if (!documentFormatItem) return ''; + + return documentFormatItem.extension; + } + + @action + closeModal() { + this.router.transitionTo('logged-in.project.files', this.project.id); + } + + @action + onFileLoaded(content: any) { + this.fileRender = content; + this.exportLoading = false; + } + + @action + exportFile() { + const blob = new Blob([this.fileRender], { + type: 'charset=utf-8', + }); + + const filename = `${this.document.path}.${this.fileExtension}`; + + this.fileSaver.saveAs(blob, filename); + } +} diff --git a/webapp/app/pods/logged-in/project/files/jipt/route.js b/webapp/app/pods/logged-in/project/files/jipt/route.js deleted file mode 100644 index 56225bdc..00000000 --- a/webapp/app/pods/logged-in/project/files/jipt/route.js +++ /dev/null @@ -1,31 +0,0 @@ -import {inject as service} from '@ember/service'; -import Route from '@ember/routing/route'; -import RSVP from 'rsvp'; - -export default Route.extend({ - exporter: service('exporter'), - - queryParams: { - documentFormatFilter: { - refreshModel: true - } - }, - - model({fileId}) { - return RSVP.hash({ - projectModel: this.modelFor('logged-in.project'), - fileModel: this.modelFor('logged-in.project.files'), - fileId - }); - }, - - resetController(controller, isExiting) { - controller.set('exportLoading', true); - - if (isExiting) { - controller.setProperties({ - fileRender: null - }); - } - } -}); diff --git a/webapp/app/pods/logged-in/project/files/jipt/route.ts b/webapp/app/pods/logged-in/project/files/jipt/route.ts new file mode 100644 index 00000000..b36bdb0a --- /dev/null +++ b/webapp/app/pods/logged-in/project/files/jipt/route.ts @@ -0,0 +1,31 @@ +import {inject as service} from '@ember/service'; +import Route from '@ember/routing/route'; +import Exporter from 'accent-webapp/services/exporter'; +import JIPTController from 'accent-webapp/pods/logged-in/project/files/jipt/controller'; + +export default class JIPTRoute extends Route { + @service('exporter') + exporter: Exporter; + + queryParams = { + documentFormatFilter: { + refreshModel: true, + }, + }; + + model({fileId}: {fileId: string}) { + return { + projectModel: this.modelFor('logged-in.project'), + fileModel: this.modelFor('logged-in.project.files'), + fileId, + }; + } + + resetController(controller: JIPTController, isExiting: boolean) { + controller.exportLoading = true; + + if (isExiting) { + controller.fileRender = null; + } + } +} diff --git a/webapp/app/pods/logged-in/project/files/jipt/template.hbs b/webapp/app/pods/logged-in/project/files/jipt/template.hbs index e278b74a..e3f8bcbc 100644 --- a/webapp/app/pods/logged-in/project/files/jipt/template.hbs +++ b/webapp/app/pods/logged-in/project/files/jipt/template.hbs @@ -1,6 +1,6 @@ - + -
              - {{document.path}} + {{this.document.path}} - .{{documentFormatItem.extension}} + .{{this.documentFormatItem.extension}}
              {{inline-svg "/assets/export.svg" class="button-icon"}} @@ -34,23 +34,23 @@ {{t "components.project_file_operations.export"}} - {{#if exportLoading}} + {{#if this.exportLoading}} {{/if}} diff --git a/webapp/app/pods/logged-in/project/files/new-sync/controller.js b/webapp/app/pods/logged-in/project/files/new-sync/controller.js deleted file mode 100644 index 327c4af7..00000000 --- a/webapp/app/pods/logged-in/project/files/new-sync/controller.js +++ /dev/null @@ -1,67 +0,0 @@ -import {inject as service} from '@ember/service'; -import {readOnly} from '@ember/object/computed'; -import Controller from '@ember/controller'; - -const FLASH_MESSAGE_CREATE_SUCCESS = - 'pods.document.sync.flash_messages.create_success'; -const FLASH_MESSAGE_CREATE_ERROR = - 'pods.document.sync.flash_messages.create_error'; - -export default Controller.extend({ - peeker: service('peeker'), - syncer: service('syncer'), - intl: service('intl'), - flashMessages: service(), - globalState: service('global-state'), - - project: readOnly('model.project'), - revisions: readOnly('project.revisions'), - documents: readOnly('project.documents.entries'), - permissions: readOnly('globalState.permissions'), - - actions: { - closeModal() { - this.send('onRefresh'); - this.transitionToRoute('logged-in.project.files', this.model.project.id); - }, - - cancelFile() { - this.set('revisionOperations', null); - }, - - peek({fileSource, documentFormat, documentPath, revision, syncType}) { - const file = fileSource; - const project = this.project; - const revisions = this.revisions; - - return this.peeker - .sync({ - project, - revision, - revisions, - file, - documentPath, - documentFormat, - syncType - }) - .then(revisionOperations => - this.set('revisionOperations', revisionOperations) - ); - }, - - sync({fileSource, documentFormat, documentPath, revision, syncType}) { - const file = fileSource; - const project = this.project; - - return this.syncer - .sync({project, revision, file, documentPath, documentFormat, syncType}) - .then(() => - this.flashMessages.success(this.intl.t(FLASH_MESSAGE_CREATE_SUCCESS)) - ) - .then(() => this.send('closeModal')) - .catch(() => - this.flashMessages.error(this.intl.t(FLASH_MESSAGE_CREATE_ERROR)) - ); - } - } -}); diff --git a/webapp/app/pods/logged-in/project/files/new-sync/controller.ts b/webapp/app/pods/logged-in/project/files/new-sync/controller.ts new file mode 100644 index 00000000..6cad0a78 --- /dev/null +++ b/webapp/app/pods/logged-in/project/files/new-sync/controller.ts @@ -0,0 +1,127 @@ +import {inject as service} from '@ember/service'; +import {action} from '@ember/object'; +import {readOnly} from '@ember/object/computed'; +import Controller from '@ember/controller'; +import Peeker from 'accent-webapp/services/peeker'; +import Syncer from 'accent-webapp/services/syncer'; +import IntlService from 'ember-intl/services/intl'; +import FlashMessages from 'ember-cli-flash/services/flash-messages'; +import GlobalState from 'accent-webapp/services/global-state'; +import RouterService from '@ember/routing/router-service'; +import {tracked} from '@glimmer/tracking'; + +const FLASH_MESSAGE_CREATE_SUCCESS = + 'pods.document.sync.flash_messages.create_success'; +const FLASH_MESSAGE_CREATE_ERROR = + 'pods.document.sync.flash_messages.create_error'; + +export default class NewSyncController extends Controller { + @service('peeker') + peeker: Peeker; + + @service('syncer') + syncer: Syncer; + + @service('intl') + intl: IntlService; + + @service('router') + router: RouterService; + + @service('flash-messages') + flashMessages: FlashMessages; + + @service('global-state') + globalState: GlobalState; + + @readOnly('model.project') + project: any; + + @readOnly('project.revisions') + revisions: any; + + @readOnly('project.documents.entries') + documents: any; + + @readOnly('globalState.permissions') + permissions: any; + + @tracked + revisionOperations: any = null; + + @action + closeModal() { + this.send('onRefresh'); + this.router.transitionTo('logged-in.project.files', this.model.project.id); + } + + @action + cancelFile() { + this.revisionOperations = null; + } + + @action + async peek({ + fileSource, + documentFormat, + documentPath, + revision, + syncType, + }: { + fileSource: any; + documentFormat: any; + documentPath: any; + revision: any; + syncType: any; + }) { + const file = fileSource; + const project = this.project; + const revisions = this.revisions; + + const revisionOperations = await this.peeker.sync({ + project, + revision, + revisions, + file, + documentPath, + documentFormat, + syncType, + }); + + this.revisionOperations = revisionOperations; + } + + @action + async sync({ + fileSource, + documentFormat, + documentPath, + revision, + syncType, + }: { + fileSource: any; + documentFormat: any; + documentPath: any; + revision: any; + syncType: any; + }) { + const file = fileSource; + const project = this.project; + + try { + await this.syncer.sync({ + project, + revision, + file, + documentPath, + documentFormat, + syncType, + }); + + this.flashMessages.success(this.intl.t(FLASH_MESSAGE_CREATE_SUCCESS)); + this.send('closeModal'); + } catch (error) { + this.flashMessages.error(this.intl.t(FLASH_MESSAGE_CREATE_ERROR)); + } + } +} diff --git a/webapp/app/pods/logged-in/project/files/new-sync/route.js b/webapp/app/pods/logged-in/project/files/new-sync/route.js deleted file mode 100644 index da3b4dcc..00000000 --- a/webapp/app/pods/logged-in/project/files/new-sync/route.js +++ /dev/null @@ -1,15 +0,0 @@ -import Route from '@ember/routing/route'; - -export default Route.extend({ - model() { - return this.modelFor('logged-in.project'); - }, - - resetController(controller, isExiting) { - if (isExiting) { - controller.setProperties({ - revisionOperations: null - }); - } - } -}); diff --git a/webapp/app/pods/logged-in/project/files/new-sync/route.ts b/webapp/app/pods/logged-in/project/files/new-sync/route.ts new file mode 100644 index 00000000..0d360b5f --- /dev/null +++ b/webapp/app/pods/logged-in/project/files/new-sync/route.ts @@ -0,0 +1,14 @@ +import Route from '@ember/routing/route'; +import NewSyncController from 'accent-webapp/pods/logged-in/project/files/new-sync/controller'; + +export default class NewSyncRoute extends Route { + model() { + return this.modelFor('logged-in.project'); + } + + resetController(controller: NewSyncController, isExiting: boolean) { + if (isExiting) { + controller.revisionOperations = null; + } + } +} diff --git a/webapp/app/pods/logged-in/project/files/new-sync/template.hbs b/webapp/app/pods/logged-in/project/files/new-sync/template.hbs index b6cc45f6..57cf9de6 100644 --- a/webapp/app/pods/logged-in/project/files/new-sync/template.hbs +++ b/webapp/app/pods/logged-in/project/files/new-sync/template.hbs @@ -1,6 +1,6 @@ - + -
              - {{document.path}} + {{this.document.path}} . - {{documentFormatItem.extension}} + {{this.documentFormatItem.extension}}
              @@ -24,22 +24,22 @@
              - {{#if revisionOperations.length}} + {{#if this.revisionOperations.length}}
              - +
              {{/if}}
              diff --git a/webapp/app/pods/logged-in/project/files/template.hbs b/webapp/app/pods/logged-in/project/files/template.hbs index 48b50b41..d9efd0c8 100644 --- a/webapp/app/pods/logged-in/project/files/template.hbs +++ b/webapp/app/pods/logged-in/project/files/template.hbs @@ -1,25 +1,25 @@ -{{#if model.loading}} +{{#if this.model.loading}} {{/if}} -{{#if showSkeleton}} +{{#if this.showSkeleton}} {{else}} - {{#if (get permissions "sync")}} - + {{#if (get this.permissions "sync")}} + {{/if}} {{outlet}} diff --git a/webapp/app/pods/logged-in/project/index/controller.js b/webapp/app/pods/logged-in/project/index/controller.js deleted file mode 100644 index 2dc2e220..00000000 --- a/webapp/app/pods/logged-in/project/index/controller.js +++ /dev/null @@ -1,70 +0,0 @@ -import {inject as service} from '@ember/service'; -import {readOnly, reads, equal, and} from '@ember/object/computed'; -import {computed} from '@ember/object'; -import Controller from '@ember/controller'; -import correctAllRevisionQuery from 'accent-webapp/queries/correct-all-revision'; -import uncorrectAllRevisionQuery from 'accent-webapp/queries/uncorrect-all-revision'; - -const FLASH_MESSAGE_REVISION_CORRECT_SUCCESS = - 'pods.project.index.flash_messages.revision_correct_success'; -const FLASH_MESSAGE_REVISION_CORRECT_ERROR = - 'pods.project.index.flash_messages.revision_correct_error'; -const FLASH_MESSAGE_REVISION_UNCORRECT_SUCCESS = - 'pods.project.index.flash_messages.revision_uncorrect_success'; -const FLASH_MESSAGE_REVISION_UNCORRECT_ERROR = - 'pods.project.index.flash_messages.revision_uncorrect_error'; - -export default Controller.extend({ - globalState: service('global-state'), - apolloMutate: service('apollo-mutate'), - flashMessages: service(), - intl: service('intl'), - - permissions: readOnly('globalState.permissions'), - project: reads('model.project'), - revisions: reads('project.revisions'), - emptyProject: equal('model.project', undefined), - showLoading: and('emptyProject', 'model.loading'), - - document: computed('project.documents.entries.[]', function() { - return this.project.documents.entries[0]; - }), - - actions: { - correctAllConflicts(revision) { - return this.apolloMutate - .mutate({ - mutation: correctAllRevisionQuery, - variables: {revisionId: revision.id} - }) - .then(() => - this.flashMessages.success( - this.intl.t(FLASH_MESSAGE_REVISION_CORRECT_SUCCESS) - ) - ) - .catch(() => - this.flashMessages.error( - this.intl.t(FLASH_MESSAGE_REVISION_CORRECT_ERROR) - ) - ); - }, - - uncorrectAllConflicts(revision) { - return this.apolloMutate - .mutate({ - mutation: uncorrectAllRevisionQuery, - variables: {revisionId: revision.id} - }) - .then(() => - this.flashMessages.success( - this.intl.t(FLASH_MESSAGE_REVISION_UNCORRECT_SUCCESS) - ) - ) - .catch(() => - this.flashMessages.error( - this.intl.t(FLASH_MESSAGE_REVISION_UNCORRECT_ERROR) - ) - ); - } - } -}); diff --git a/webapp/app/pods/logged-in/project/index/controller.ts b/webapp/app/pods/logged-in/project/index/controller.ts new file mode 100644 index 00000000..c2a23fde --- /dev/null +++ b/webapp/app/pods/logged-in/project/index/controller.ts @@ -0,0 +1,88 @@ +import {inject as service} from '@ember/service'; +import {readOnly, equal, and} from '@ember/object/computed'; +import {action} from '@ember/object'; +import Controller from '@ember/controller'; +import correctAllRevisionQuery from 'accent-webapp/queries/correct-all-revision'; +import uncorrectAllRevisionQuery from 'accent-webapp/queries/uncorrect-all-revision'; +import GlobalState from 'accent-webapp/services/global-state'; +import ApolloMutate from 'accent-webapp/services/apollo-mutate'; +import FlashMessages from 'ember-cli-flash/services/flash-messages'; +import IntlService from 'ember-intl/services/intl'; + +const FLASH_MESSAGE_REVISION_CORRECT_SUCCESS = + 'pods.project.index.flash_messages.revision_correct_success'; +const FLASH_MESSAGE_REVISION_CORRECT_ERROR = + 'pods.project.index.flash_messages.revision_correct_error'; +const FLASH_MESSAGE_REVISION_UNCORRECT_SUCCESS = + 'pods.project.index.flash_messages.revision_uncorrect_success'; +const FLASH_MESSAGE_REVISION_UNCORRECT_ERROR = + 'pods.project.index.flash_messages.revision_uncorrect_error'; + +export default class ProjectIndexController extends Controller { + @service('global-state') + globalState: GlobalState; + + @service('apollo-mutate') + apolloMutate: ApolloMutate; + + @service('flash-messages') + flashMessages: FlashMessages; + + @service('intl') + intl: IntlService; + + @readOnly('globalState.permissions') + permissions: any; + + @readOnly('model.project') + project: any; + + @readOnly('project.revisions') + revisions: any; + + @equal('model.project', undefined) + emptyProject: boolean; + + @and('emptyProject', 'model.loading') + showLoading: boolean; + + get document() { + return this.project.documents.entries[0]; + } + + @action + async correctAllConflicts(revision: any) { + try { + await this.apolloMutate.mutate({ + mutation: correctAllRevisionQuery, + variables: {revisionId: revision.id}, + }); + + this.flashMessages.success( + this.intl.t(FLASH_MESSAGE_REVISION_CORRECT_SUCCESS) + ); + } catch (error) { + this.flashMessages.error( + this.intl.t(FLASH_MESSAGE_REVISION_CORRECT_ERROR) + ); + } + } + + @action + async uncorrectAllConflicts(revision: any) { + try { + await this.apolloMutate.mutate({ + mutation: uncorrectAllRevisionQuery, + variables: {revisionId: revision.id}, + }); + + this.flashMessages.success( + this.intl.t(FLASH_MESSAGE_REVISION_UNCORRECT_SUCCESS) + ); + } catch (error) { + this.flashMessages.error( + this.intl.t(FLASH_MESSAGE_REVISION_UNCORRECT_ERROR) + ); + } + } +} diff --git a/webapp/app/pods/logged-in/project/index/route.js b/webapp/app/pods/logged-in/project/index/route.js deleted file mode 100644 index 95568ca3..00000000 --- a/webapp/app/pods/logged-in/project/index/route.js +++ /dev/null @@ -1,25 +0,0 @@ -import {get} from '@ember/object'; -import {inject as service} from '@ember/service'; -import Route from '@ember/routing/route'; -import ApolloRoute from 'accent-webapp/mixins/apollo-route'; - -import projectDashboardQuery from 'accent-webapp/queries/project-dashboard'; - -export default Route.extend(ApolloRoute, { - routeParams: service(), - - model(_params, transition) { - return this.graphql(projectDashboardQuery, { - props: data => ({ - project: get(data, 'viewer.project') - }), - options: { - fetchPolicy: 'cache-and-network', - variables: { - projectId: this.routeParams.fetch(transition, 'logged-in.project') - .projectId - } - } - }); - } -}); diff --git a/webapp/app/pods/logged-in/project/index/route.ts b/webapp/app/pods/logged-in/project/index/route.ts new file mode 100644 index 00000000..fe94ec94 --- /dev/null +++ b/webapp/app/pods/logged-in/project/index/route.ts @@ -0,0 +1,44 @@ +import {inject as service} from '@ember/service'; +import Route from '@ember/routing/route'; + +import projectDashboardQuery from 'accent-webapp/queries/project-dashboard'; +import RouteParams from 'accent-webapp/services/route-params'; +import ApolloSubscription, { + Subscription, +} from 'accent-webapp/services/apollo-subscription'; +import Transition from '@ember/routing/-private/transition'; + +export default class ProjectIndexRoute extends Route { + @service('apollo-subscription') + apolloSubscription: ApolloSubscription; + + @service('route-params') + routeParams: RouteParams; + + subscription: Subscription; + + model(_params: object, transition: Transition) { + const props = (data: any) => ({project: data.viewer.project}); + + this.subscription = this.apolloSubscription.graphql( + () => this.modelFor(this.routeName), + projectDashboardQuery, + { + props, + options: { + fetchPolicy: 'cache-and-network', + variables: { + projectId: this.routeParams.fetch(transition, 'logged-in.project') + .projectId, + }, + }, + } + ); + + return this.subscription.currentResult(); + } + + deactivate() { + this.apolloSubscription.clearSubscription(this.subscription); + } +} diff --git a/webapp/app/pods/logged-in/project/index/template.hbs b/webapp/app/pods/logged-in/project/index/template.hbs index 67f94e56..1e11b906 100644 --- a/webapp/app/pods/logged-in/project/index/template.hbs +++ b/webapp/app/pods/logged-in/project/index/template.hbs @@ -1,17 +1,17 @@ -{{#if model.loading}} +{{#if this.model.loading}} {{/if}} -{{#if showLoading}} +{{#if this.showLoading}} {{else}} {{/if}} diff --git a/webapp/app/pods/logged-in/project/revision/conflicts/controller.js b/webapp/app/pods/logged-in/project/revision/conflicts/controller.js deleted file mode 100644 index f430f547..00000000 --- a/webapp/app/pods/logged-in/project/revision/conflicts/controller.js +++ /dev/null @@ -1,129 +0,0 @@ -import {computed} from '@ember/object'; -import {inject as service} from '@ember/service'; -import {readOnly, equal, empty, and} from '@ember/object/computed'; -import Controller from '@ember/controller'; -import translationCorrectQuery from 'accent-webapp/queries/correct-translation'; -import correctAllRevisionQuery from 'accent-webapp/queries/correct-all-revision'; - -const FLASH_MESSAGE_REVISION_CORRECT_SUCCESS = - 'pods.project.conflicts.flash_messages.revision_correct_success'; -const FLASH_MESSAGE_REVISION_CORRECT_ERROR = - 'pods.project.conflicts.flash_messages.revision_correct_error'; -const FLASH_MESSAGE_CORRECT_SUCCESS = - 'pods.project.conflicts.flash_messages.correct_success'; -const FLASH_MESSAGE_CORRECT_ERROR = - 'pods.project.conflicts.flash_messages.correct_error'; - -export default Controller.extend({ - intl: service('intl'), - flashMessages: service(), - apolloMutate: service('apollo-mutate'), - globalState: service('global-state'), - - queryParams: ['reference', 'page', 'query', 'document'], - - fullscreen: false, - query: '', - reference: null, - document: null, - page: 1, - - permissions: readOnly('globalState.permissions'), - revision: readOnly('model.project.revision'), - revisions: readOnly('model.revisionModel.project.revisions'), - - emptyEntries: equal('model.translations.entries', undefined), - emptyReference: empty('reference'), - emptyDocument: empty('document'), - emptyQuery: equal('query', ''), - - showLoading: and('emptyEntries', 'model.loading'), - - showSkeleton: and( - 'emptyEntries', - 'model.loading', - 'emptyQuery', - 'emptyReference', - 'emptyDocument' - ), - referenceRevisions: computed('model.revisionId', 'revisions', function() { - if (!this.revisions) return []; - - return this.revisions.filter( - revision => revision.id !== this.model.revisionId - ); - }), - - referenceRevision: computed( - 'model.referenceRevisionId', - 'revisions', - function() { - if (!this.revisions || !this.model.referenceRevisionId) return; - - return this.revisions.find( - revision => revision.id === this.model.referenceRevisionId - ); - } - ), - - actions: { - deactivateFullscreen() { - this.set('fullscreen', false); - }, - - correctConflict(conflict, text) { - return this.apolloMutate - .mutate({ - mutation: translationCorrectQuery, - variables: { - translationId: conflict.id, - text - } - }) - .then(() => - this.flashMessages.success(this.intl.t(FLASH_MESSAGE_CORRECT_SUCCESS)) - ) - .catch(() => - this.flashMessages.error(this.intl.t(FLASH_MESSAGE_CORRECT_ERROR)) - ); - }, - - correctAllConflicts() { - return this.apolloMutate - .mutate({ - mutation: correctAllRevisionQuery, - variables: {revisionId: this.revision.id} - }) - .then(() => { - this.flashMessages.success( - this.intl.t(FLASH_MESSAGE_REVISION_CORRECT_SUCCESS) - ); - return this.send('refresh'); - }) - .catch(() => - this.flashMessages.error( - this.intl.t(FLASH_MESSAGE_REVISION_CORRECT_ERROR) - ) - ); - }, - - changeQuery(query) { - this.set('page', 1); - this.set('query', query); - }, - - changeReference(reference) { - this.set('reference', reference); - }, - - changeDocument(documentEntry) { - this.set('page', 1); - this.set('document', documentEntry); - }, - - selectPage(page) { - window.scrollTo(0, 0); - this.set('page', page); - } - } -}); diff --git a/webapp/app/pods/logged-in/project/revision/conflicts/controller.ts b/webapp/app/pods/logged-in/project/revision/conflicts/controller.ts new file mode 100644 index 00000000..e0b598c7 --- /dev/null +++ b/webapp/app/pods/logged-in/project/revision/conflicts/controller.ts @@ -0,0 +1,166 @@ +import {action} from '@ember/object'; +import {inject as service} from '@ember/service'; +import {readOnly, equal, empty, and} from '@ember/object/computed'; +import Controller from '@ember/controller'; +import translationCorrectQuery from 'accent-webapp/queries/correct-translation'; +import correctAllRevisionQuery from 'accent-webapp/queries/correct-all-revision'; +import IntlService from 'ember-intl/services/intl'; +import FlashMessages from 'ember-cli-flash/services/flash-messages'; +import ApolloMutate from 'accent-webapp/services/apollo-mutate'; +import GlobalState from 'accent-webapp/services/global-state'; +import {tracked} from '@glimmer/tracking'; + +const FLASH_MESSAGE_REVISION_CORRECT_SUCCESS = + 'pods.project.conflicts.flash_messages.revision_correct_success'; +const FLASH_MESSAGE_REVISION_CORRECT_ERROR = + 'pods.project.conflicts.flash_messages.revision_correct_error'; +const FLASH_MESSAGE_CORRECT_SUCCESS = + 'pods.project.conflicts.flash_messages.correct_success'; +const FLASH_MESSAGE_CORRECT_ERROR = + 'pods.project.conflicts.flash_messages.correct_error'; + +export default class ConflictsController extends Controller { + @service('intl') + intl: IntlService; + + @service('flash-messages') + flashMessages: FlashMessages; + + @service('apollo-mutate') + apolloMutate: ApolloMutate; + + @service('global-state') + globalState: GlobalState; + + queryParams = ['reference', 'page', 'query', 'document']; + + @tracked + fullscreen = false; + + @tracked + query = ''; + + @tracked + reference = null; + + @tracked + document = null; + + @tracked + page = 1; + + @readOnly('globalState.permissions') + permissions: any; + + @readOnly('model.project.revision') + revision: any; + + @readOnly('model.revisionModel.project.revisions') + revisions: any; + + @equal('model.translations.entries', undefined) + emptyEntries: boolean; + + @empty('reference') + emptyReference: boolean; + + @empty('document') + emptyDocument: boolean; + + @equal('query', '') + emptyQuery: boolean; + + @and('emptyEntries', 'model.loading') + showLoading: boolean; + + @and( + 'emptyEntries', + 'model.loading', + 'emptyQuery', + 'emptyReference', + 'emptyDocument' + ) + showSkeleton: boolean; + + get referenceRevisions() { + if (!this.revisions) return []; + + return this.revisions.filter((revision: any) => { + return revision.id !== this.model.revisionId; + }); + } + + get referenceRevision() { + if (!this.revisions || !this.model.referenceRevisionId) return; + + return this.revisions.find((revision: any) => { + return revision.id === this.model.referenceRevisionId; + }); + } + + @action + deactivateFullscreen() { + this.fullscreen = false; + } + + @action + async correctConflict(conflict: any, text: string) { + try { + await this.apolloMutate.mutate({ + mutation: translationCorrectQuery, + variables: { + translationId: conflict.id, + text, + }, + }); + + this.flashMessages.success(this.intl.t(FLASH_MESSAGE_CORRECT_SUCCESS)); + } catch (error) { + this.flashMessages.error(this.intl.t(FLASH_MESSAGE_CORRECT_ERROR)); + } + } + + @action + async correctAllConflicts() { + try { + await this.apolloMutate.mutate({ + mutation: correctAllRevisionQuery, + variables: {revisionId: this.revision.id}, + }); + + this.flashMessages.success( + this.intl.t(FLASH_MESSAGE_REVISION_CORRECT_SUCCESS) + ); + + return this.send('onRefresh'); + } catch (error) { + this.flashMessages.error( + this.intl.t(FLASH_MESSAGE_REVISION_CORRECT_ERROR) + ); + } + } + + @action + changeQuery(query: string) { + this.page = 1; + this.query = query; + } + + @action + changeReference(reference: any) { + this.reference = reference.value; + } + + @action + changeDocument(documentEntry: any) { + this.page = 1; + this.document = documentEntry.value; + } + + @action + selectPage(page: number) { + window.scrollTo(0, 0); + + this.page = page; + } +} diff --git a/webapp/app/pods/logged-in/project/revision/conflicts/route.js b/webapp/app/pods/logged-in/project/revision/conflicts/route.js deleted file mode 100644 index fd360f07..00000000 --- a/webapp/app/pods/logged-in/project/revision/conflicts/route.js +++ /dev/null @@ -1,95 +0,0 @@ -import {get} from '@ember/object'; -import {inject as service} from '@ember/service'; -import Route from '@ember/routing/route'; -import ResetScroll from 'accent-webapp/mixins/reset-scroll'; -import ApolloRoute from 'accent-webapp/mixins/apollo-route'; - -import translationsQuery from 'accent-webapp/queries/conflicts'; - -export default Route.extend(ResetScroll, ApolloRoute, { - routeParams: service(), - - queryParams: { - fullscreen: { - refreshModel: true - }, - query: { - refreshModel: true - }, - page: { - refreshModel: true - }, - reference: { - refreshModel: true - }, - document: { - refreshModel: true - } - }, - - model({query, page, reference, document}, transition) { - return this.graphql(translationsQuery, { - props: data => ({ - revisionId: this.routeParams.fetch( - transition, - 'logged-in.project.revision' - ).revisionId, - referenceRevisionId: reference, - revisionModel: this.modelFor('logged-in.project.revision'), - documents: get(data, 'viewer.project.documents.entries'), - project: get(data, 'viewer.project'), - translations: get(data, 'viewer.project.revision.translations') - }), - options: { - fetchPolicy: 'cache-and-network', - variables: { - projectId: this.routeParams.fetch(transition, 'logged-in.project') - .projectId, - revisionId: this.routeParams.fetch( - transition, - 'logged-in.project.revision' - ).revisionId, - query, - page, - document, - reference - } - } - }); - }, - - renderTemplate(controller) { - if (controller.fullscreen) { - this.render('logged-in.project.revision.full-screen-conflicts', { - controller, - outlet: 'main' - }); - } else { - return this._super(...arguments); - } - }, - - resetController(controller, isExiting) { - if (isExiting) { - controller.setProperties({ - page: 1 - }); - } - }, - - actions: { - onRevisionChange({revisionId}) { - const {project} = this.modelFor('logged-in.project'); - - this.transitionTo( - 'logged-in.project.revision.conflicts', - project.id, - revisionId - ); - }, - - refresh() { - this.refresh(); - } - } -}); diff --git a/webapp/app/pods/logged-in/project/revision/conflicts/route.ts b/webapp/app/pods/logged-in/project/revision/conflicts/route.ts new file mode 100644 index 00000000..4b2d8c0b --- /dev/null +++ b/webapp/app/pods/logged-in/project/revision/conflicts/route.ts @@ -0,0 +1,129 @@ +import {action} from '@ember/object'; +import {inject as service} from '@ember/service'; +import Route from '@ember/routing/route'; + +import translationsQuery from 'accent-webapp/queries/conflicts'; +import ApolloSubscription, { + Subscription, +} from 'accent-webapp/services/apollo-subscription'; +import RouteParams from 'accent-webapp/services/route-params'; +import Transition from '@ember/routing/-private/transition'; +import ConflictsController from 'accent-webapp/pods/logged-in/project/revision/conflicts/controller'; +import RouterService from '@ember/routing/router-service'; + +export default class ConflictsRoute extends Route { + @service('apollo-subscription') + apolloSubscription: ApolloSubscription; + + @service('route-params') + routeParams: RouteParams; + + @service('router') + router: RouterService; + + queryParams = { + fullscreen: { + refreshModel: true, + }, + query: { + refreshModel: true, + }, + page: { + refreshModel: true, + }, + reference: { + refreshModel: true, + }, + document: { + refreshModel: true, + }, + }; + + subscription: Subscription; + + model( + { + query, + page, + reference, + document, + }: {query: any; page: number; reference: any; document: any}, + transition: Transition + ) { + this.subscription = this.apolloSubscription.graphql( + () => this.modelFor(this.routeName), + translationsQuery, + { + props: (data) => ({ + revisionId: this.routeParams.fetch( + transition, + 'logged-in.project.revision' + ).revisionId, + referenceRevisionId: reference, + revisionModel: this.modelFor('logged-in.project.revision'), + documents: data.viewer.project.documents.entries, + project: data.viewer.project, + translations: data.viewer.project.revision.translations, + }), + options: { + fetchPolicy: 'cache-and-network', + variables: { + projectId: this.routeParams.fetch(transition, 'logged-in.project') + .projectId, + revisionId: this.routeParams.fetch( + transition, + 'logged-in.project.revision' + ).revisionId, + query, + page, + document, + reference, + }, + }, + } + ); + + return this.subscription.currentResult(); + } + + renderTemplate(controller: ConflictsController, model: any) { + if (controller.fullscreen) { + this.render('logged-in.project.revision.full-screen-conflicts', { + controller: 'logged-in.project.revision.conflicts', + outlet: 'main', + }); + } else { + super.renderTemplate(controller, model); + } + } + + resetController(controller: ConflictsController, isExiting: boolean) { + if (isExiting) { + controller.page = 1; + } + } + + activate() { + window.scrollTo(0, 0); + } + + deactivate() { + this.apolloSubscription.clearSubscription(this.subscription); + } + + @action + onRevisionChange({revisionId}: {revisionId: string}) { + const {project} = this.modelFor('logged-in.project') as any; + + this.router.transitionTo( + 'logged-in.project.revision.conflicts', + project.id, + revisionId + ); + } + + @action + onRefresh() { + this.refresh(); + } +} diff --git a/webapp/app/pods/logged-in/project/revision/conflicts/template.hbs b/webapp/app/pods/logged-in/project/revision/conflicts/template.hbs index 916391e7..07ea2dd5 100644 --- a/webapp/app/pods/logged-in/project/revision/conflicts/template.hbs +++ b/webapp/app/pods/logged-in/project/revision/conflicts/template.hbs @@ -1,22 +1,22 @@ diff --git a/webapp/app/pods/logged-in/project/revision/controller.js b/webapp/app/pods/logged-in/project/revision/controller.js deleted file mode 100644 index 505f7d9b..00000000 --- a/webapp/app/pods/logged-in/project/revision/controller.js +++ /dev/null @@ -1,16 +0,0 @@ -import {inject as service} from '@ember/service'; -import {readOnly} from '@ember/object/computed'; -import Controller from '@ember/controller'; - -export default Controller.extend({ - globalState: service('global-state'), - - revisions: readOnly('model.project.revisions'), - revision: readOnly('globalState.revision'), - - actions: { - selectRevision(revisionId) { - this.send('onRevisionChange', {revisionId}); - } - } -}); diff --git a/webapp/app/pods/logged-in/project/revision/controller.ts b/webapp/app/pods/logged-in/project/revision/controller.ts new file mode 100644 index 00000000..5277ae7d --- /dev/null +++ b/webapp/app/pods/logged-in/project/revision/controller.ts @@ -0,0 +1,21 @@ +import {inject as service} from '@ember/service'; +import {action} from '@ember/object'; +import {readOnly} from '@ember/object/computed'; +import Controller from '@ember/controller'; +import GlobalState from 'accent-webapp/services/global-state'; + +export default class RevisionController extends Controller { + @service('global-state') + globalState: GlobalState; + + @readOnly('model.project.revisions') + revisions: any; + + @readOnly('globalState.revision') + revision: any; + + @action + selectRevision(revisionId: string) { + this.send('onRevisionChange', {revisionId}); + } +} diff --git a/webapp/app/pods/logged-in/project/revision/full-screen-conflicts/template.hbs b/webapp/app/pods/logged-in/project/revision/full-screen-conflicts/template.hbs index f8953985..6fdf94d4 100644 --- a/webapp/app/pods/logged-in/project/revision/full-screen-conflicts/template.hbs +++ b/webapp/app/pods/logged-in/project/revision/full-screen-conflicts/template.hbs @@ -1,23 +1,23 @@ diff --git a/webapp/app/pods/logged-in/project/revision/route.js b/webapp/app/pods/logged-in/project/revision/route.js deleted file mode 100644 index 55910ce8..00000000 --- a/webapp/app/pods/logged-in/project/revision/route.js +++ /dev/null @@ -1,12 +0,0 @@ -import {inject as service} from '@ember/service'; -import Route from '@ember/routing/route'; - -export default Route.extend({ - globalState: service('global-state'), - - model({revisionId}) { - this.globalState.set('revision', revisionId); - - return this.modelFor('logged-in.project'); - } -}); diff --git a/webapp/app/pods/logged-in/project/revision/route.ts b/webapp/app/pods/logged-in/project/revision/route.ts new file mode 100644 index 00000000..f165315f --- /dev/null +++ b/webapp/app/pods/logged-in/project/revision/route.ts @@ -0,0 +1,14 @@ +import {inject as service} from '@ember/service'; +import Route from '@ember/routing/route'; +import GlobalState from 'accent-webapp/services/global-state'; + +export default class RevisionRoute extends Route { + @service('global-state') + globalState: GlobalState; + + model({revisionId}: {revisionId: string}) { + this.globalState.revision = revisionId; + + return this.modelFor('logged-in.project'); + } +} diff --git a/webapp/app/pods/logged-in/project/revision/template.hbs b/webapp/app/pods/logged-in/project/revision/template.hbs index 194903b9..8848ca03 100644 --- a/webapp/app/pods/logged-in/project/revision/template.hbs +++ b/webapp/app/pods/logged-in/project/revision/template.hbs @@ -1,7 +1,7 @@ {{outlet}} diff --git a/webapp/app/pods/logged-in/project/revision/translations/controller.js b/webapp/app/pods/logged-in/project/revision/translations/controller.js deleted file mode 100644 index 004ce516..00000000 --- a/webapp/app/pods/logged-in/project/revision/translations/controller.js +++ /dev/null @@ -1,100 +0,0 @@ -import {computed} from '@ember/object'; -import {inject as service} from '@ember/service'; -import {equal, and} from '@ember/object/computed'; -import Controller from '@ember/controller'; -import translationUpdateQuery from 'accent-webapp/queries/update-translation'; - -const FLASH_MESSAGE_UPDATE_SUCCESS = - 'pods.translation.edit.flash_messages.update_success'; -const FLASH_MESSAGE_UPDATE_ERROR = - 'pods.translation.edit.flash_messages.update_error'; - -export default Controller.extend({ - apolloMutate: service('apollo-mutate'), - globalState: service('global-state'), - intl: service('intl'), - flashMessages: service(), - - queryParams: [ - 'query', - 'page', - 'document', - 'version', - 'isTextEmpty', - 'isTextNotEmpty', - 'isAddedLastSync', - 'isCommentedOn' - ], - - query: '', - page: 1, - document: null, - version: null, - isTextEmpty: null, - isTextNotEmpty: null, - isAddedLastSync: null, - isCommentedOn: null, - - emptyEntries: equal('model.translations.entries', undefined), - emptyQuery: equal('query', ''), - showSkeleton: and('emptyEntries', 'model.loading', 'emptyQuery'), - showLoading: and('emptyEntries', 'model.loading'), - - withAdvancedFilters: computed( - 'isTextEmpty', - 'isTextNotEmpty', - 'isAddedLastSync', - 'isCommentedOn', - function() { - return [ - this.isTextEmpty, - this.isTextNotEmpty, - this.isAddedLastSync, - this.isCommentedOn - ].filter(filter => filter === 'true').length; - } - ), - - actions: { - changeQuery(query) { - this.set('page', 1); - this.set('query', query); - }, - - changeAdvancedFilterBoolean(a, b) { - this.set(a, b.target.checked ? true : null); - }, - - changeVersion(versionId) { - this.set('page', 1); - this.set('version', versionId); - }, - - changeDocument(documentId) { - this.set('page', 1); - this.set('document', documentId); - }, - - selectPage(page) { - window.scrollTo(0, 0); - this.set('page', page); - }, - - updateText(translation, text) { - return this.apolloMutate - .mutate({ - mutation: translationUpdateQuery, - variables: { - translationId: translation.id, - text - } - }) - .then(() => - this.flashMessages.success(this.intl.t(FLASH_MESSAGE_UPDATE_SUCCESS)) - ) - .catch(() => - this.flashMessages.error(this.intl.t(FLASH_MESSAGE_UPDATE_ERROR)) - ); - } - } -}); diff --git a/webapp/app/pods/logged-in/project/revision/translations/controller.ts b/webapp/app/pods/logged-in/project/revision/translations/controller.ts new file mode 100644 index 00000000..353d23f3 --- /dev/null +++ b/webapp/app/pods/logged-in/project/revision/translations/controller.ts @@ -0,0 +1,134 @@ +import {action} from '@ember/object'; +import {inject as service} from '@ember/service'; +import {equal, and} from '@ember/object/computed'; +import Controller from '@ember/controller'; +import translationUpdateQuery from 'accent-webapp/queries/update-translation'; +import ApolloMutate from 'accent-webapp/services/apollo-mutate'; +import GlobalState from 'accent-webapp/services/global-state'; +import IntlService from 'ember-intl/services/intl'; +import FlashMessages from 'ember-cli-flash/services/flash-messages'; +import {tracked} from '@glimmer/tracking'; + +const FLASH_MESSAGE_UPDATE_SUCCESS = + 'pods.translation.edit.flash_messages.update_success'; +const FLASH_MESSAGE_UPDATE_ERROR = + 'pods.translation.edit.flash_messages.update_error'; + +export default class TranslationsController extends Controller { + @service('apollo-mutate') + apolloMutate: ApolloMutate; + + @service('global-state') + globalState: GlobalState; + + @service('intl') + intl: IntlService; + + @service('flash-messages') + flashMessages: FlashMessages; + + queryParams = [ + 'query', + 'page', + 'document', + 'version', + 'isTextEmpty', + 'isTextNotEmpty', + 'isAddedLastSync', + 'isCommentedOn', + ]; + + @tracked + query = ''; + + @tracked + page = 1; + + @tracked + document: string | null = null; + + @tracked + version: string | null = null; + + @tracked + isTextEmpty: 'true' | null = null; + + @tracked + isTextNotEmpty: 'true' | null = null; + + @tracked + isAddedLastSync: 'true' | null = null; + + @tracked + isCommentedOn: 'true' | null = null; + + @equal('model.translations.entries', undefined) + emptyEntries: boolean; + + @equal('query', '') + emptyQuery: boolean; + + @and('emptyEntries', 'model.loading', 'emptyQuery') + showSkeleton: boolean; + + @and('emptyEntries', 'model.loading') + showLoading: boolean; + + get withAdvancedFilters() { + return [ + this.isTextEmpty, + this.isTextNotEmpty, + this.isAddedLastSync, + this.isCommentedOn, + ].filter((filter) => filter === 'true').length; + } + + @action + changeQuery(query: string) { + this.page = 1; + this.query = query; + } + + @action + changeAdvancedFilterBoolean( + key: 'isTextEmpty' | 'isTextNotEmpty' | 'isAddedLastSync' | 'isCommentedOn', + event: InputEvent + ) { + this[key] = (event.target as HTMLInputElement).checked ? 'true' : null; + } + + @action + changeVersion(versionId: string) { + this.page = 1; + this.version = versionId; + } + + @action + changeDocument(documentId: string) { + this.page = 1; + this.document = documentId; + } + + @action + selectPage(page: number) { + window.scrollTo(0, 0); + + this.page = page; + } + + @action + async updateText(translation: any, text: string) { + try { + await this.apolloMutate.mutate({ + mutation: translationUpdateQuery, + variables: { + translationId: translation.id, + text, + }, + }); + this.flashMessages.success(this.intl.t(FLASH_MESSAGE_UPDATE_SUCCESS)); + } catch (error) { + this.flashMessages.error(this.intl.t(FLASH_MESSAGE_UPDATE_ERROR)); + } + } +} diff --git a/webapp/app/pods/logged-in/project/revision/translations/route.js b/webapp/app/pods/logged-in/project/revision/translations/route.js deleted file mode 100644 index 93ab20b6..00000000 --- a/webapp/app/pods/logged-in/project/revision/translations/route.js +++ /dev/null @@ -1,90 +0,0 @@ -import {get} from '@ember/object'; -import {inject as service} from '@ember/service'; -import Route from '@ember/routing/route'; -import ResetScroll from 'accent-webapp/mixins/reset-scroll'; -import ApolloRoute from 'accent-webapp/mixins/apollo-route'; - -import translationsQuery from 'accent-webapp/queries/translations'; - -export default Route.extend(ResetScroll, ApolloRoute, { - routeParams: service(), - - queryParams: { - query: { - refreshModel: true - }, - page: { - refreshModel: true - }, - document: { - refreshModel: true - }, - version: { - refreshModel: true - }, - isTextEmpty: { - refreshModel: true - }, - isTextNotEmpty: { - refreshModel: true - }, - isAddedLastSync: { - refreshModel: true - }, - isCommentedOn: { - refreshModel: true - } - }, - - model(params, transition) { - params.isTextEmpty = params.isTextEmpty === 'true' ? true : null; - params.isTextNotEmpty = params.isTextNotEmpty === 'true' ? true : null; - params.isAddedLastSync = params.isAddedLastSync === 'true' ? true : null; - params.isCommentedOn = params.isCommentedOn === 'true' ? true : null; - - return this.graphql(translationsQuery, { - props: data => ({ - revisionId: this.routeParams.fetch( - transition, - 'logged-in.project.revision' - ).revisionId, - project: get(data, 'viewer.project'), - documents: get(data, 'viewer.project.documents.entries'), - versions: get(data, 'viewer.project.versions.entries'), - translations: get(data, 'viewer.project.revision.translations') - }), - options: { - fetchPolicy: 'cache-and-network', - variables: { - projectId: this.routeParams.fetch(transition, 'logged-in.project') - .projectId, - revisionId: this.routeParams.fetch( - transition, - 'logged-in.project.revision' - ).revisionId, - ...params - } - } - }); - }, - - resetController(controller, isExiting) { - if (isExiting) { - controller.setProperties({ - page: 1 - }); - } - }, - - actions: { - onRevisionChange({revisionId}) { - const {project} = this.modelFor('logged-in.project'); - - this.transitionTo( - 'logged-in.project.revision.translations', - project.id, - revisionId - ); - } - } -}); diff --git a/webapp/app/pods/logged-in/project/revision/translations/route.ts b/webapp/app/pods/logged-in/project/revision/translations/route.ts new file mode 100644 index 00000000..806e3366 --- /dev/null +++ b/webapp/app/pods/logged-in/project/revision/translations/route.ts @@ -0,0 +1,115 @@ +import {action} from '@ember/object'; +import {inject as service} from '@ember/service'; +import Route from '@ember/routing/route'; + +import translationsQuery from 'accent-webapp/queries/translations'; +import ApolloSubscription, { + Subscription, +} from 'accent-webapp/services/apollo-subscription'; +import RouteParams from 'accent-webapp/services/route-params'; +import TranslationsController from 'accent-webapp/pods/logged-in/project/revision/translations/controller'; +import RouterService from '@ember/routing/router-service'; +import Transition from '@ember/routing/-private/transition'; + +export default class TranslationsRoute extends Route { + @service('apollo-subscription') + apolloSubscription: ApolloSubscription; + + @service('route-params') + routeParams: RouteParams; + + @service('router') + router: RouterService; + + queryParams = { + query: { + refreshModel: true, + }, + page: { + refreshModel: true, + }, + document: { + refreshModel: true, + }, + version: { + refreshModel: true, + }, + isTextEmpty: { + refreshModel: true, + }, + isTextNotEmpty: { + refreshModel: true, + }, + isAddedLastSync: { + refreshModel: true, + }, + isCommentedOn: { + refreshModel: true, + }, + }; + + subscription: Subscription; + + model(params: any, transition: Transition) { + params.isTextEmpty = params.isTextEmpty === 'true' ? true : null; + params.isTextNotEmpty = params.isTextNotEmpty === 'true' ? true : null; + params.isAddedLastSync = params.isAddedLastSync === 'true' ? true : null; + params.isCommentedOn = params.isCommentedOn === 'true' ? true : null; + + this.subscription = this.apolloSubscription.graphql( + () => this.modelFor(this.routeName), + translationsQuery, + { + props: (data) => ({ + revisionId: this.routeParams.fetch( + transition, + 'logged-in.project.revision' + ).revisionId, + project: data.viewer.project, + documents: data.viewer.project.documents.entries, + versions: data.viewer.project.versions.entries, + translations: data.viewer.project.revision.translations, + }), + options: { + fetchPolicy: 'cache-and-network', + variables: { + projectId: this.routeParams.fetch(transition, 'logged-in.project') + .projectId, + revisionId: this.routeParams.fetch( + transition, + 'logged-in.project.revision' + ).revisionId, + ...params, + }, + }, + } + ); + + return this.subscription.currentResult(); + } + + resetController(controller: TranslationsController, isExiting: boolean) { + if (isExiting) { + controller.page = 1; + } + } + + activate() { + window.scrollTo(0, 0); + } + + deactivate() { + this.apolloSubscription.clearSubscription(this.subscription); + } + + @action + onRevisionChange({revisionId}: {revisionId: string}) { + const {project} = this.modelFor('logged-in.project') as {project: any}; + + this.router.transitionTo( + 'logged-in.project.revision.translations', + project.id, + revisionId + ); + } +} diff --git a/webapp/app/pods/logged-in/project/revision/translations/template.hbs b/webapp/app/pods/logged-in/project/revision/translations/template.hbs index f73b6cbe..b063f490 100644 --- a/webapp/app/pods/logged-in/project/revision/translations/template.hbs +++ b/webapp/app/pods/logged-in/project/revision/translations/template.hbs @@ -1,39 +1,40 @@ -{{#if model.loading}} + +{{#if this.model.loading}} {{/if}} -{{#if showSkeleton}} +{{#if this.showSkeleton}} -{{else if showLoading}} +{{else if this.showLoading}} {{else}} {{/if}} diff --git a/webapp/app/pods/logged-in/project/route.js b/webapp/app/pods/logged-in/project/route.js deleted file mode 100644 index df520ced..00000000 --- a/webapp/app/pods/logged-in/project/route.js +++ /dev/null @@ -1,49 +0,0 @@ -import {inject as service} from '@ember/service'; -import Route from '@ember/routing/route'; -import ApolloRoute from 'accent-webapp/mixins/apollo-route'; - -import projectQuery from 'accent-webapp/queries/project'; - -const props = data => { - if (!data.viewer || !data.viewer.project) return {permissions: []}; - - const permissions = data.viewer.project.viewerPermissions.reduce( - (memo, permission) => { - memo[permission] = true; - return memo; - }, - {} - ); - - return { - project: data.viewer.project, - permissions, - roles: data.roles, - documentFormats: data.documentFormats - }; -}; - -export default Route.extend(ApolloRoute, { - globalState: service('global-state'), - - model(params) { - return this.graphql(projectQuery, { - props, - options: { - variables: { - projectId: params.projectId - } - } - }); - }, - - actions: { - refreshModel() { - this.refresh(); - }, - - willTransition() { - this.set('globalState.isProjectNavigationListShowing', false); - } - } -}); diff --git a/webapp/app/pods/logged-in/project/route.ts b/webapp/app/pods/logged-in/project/route.ts new file mode 100644 index 00000000..df19f26b --- /dev/null +++ b/webapp/app/pods/logged-in/project/route.ts @@ -0,0 +1,84 @@ +import {inject as service} from '@ember/service'; +import Route from '@ember/routing/route'; +import {action} from '@ember/object'; + +import projectQuery, { + ProjectQueryResponse, +} from 'accent-webapp/queries/project'; +import GlobalState from 'accent-webapp/services/global-state'; +import ApolloSubscription, { + Subscription, +} from 'accent-webapp/services/apollo-subscription'; + +interface RouteParams { + projectId: string; +} + +export default class ProjectRoute extends Route { + @service('apollo-subscription') + apolloSubscription: ApolloSubscription; + + @service('global-state') + globalState: GlobalState; + + subscription: Subscription; + + model(params: RouteParams) { + const props = (data: any) => this.transformData(data); + + this.subscription = this.apolloSubscription.graphql( + () => this.modelFor(this.routeName), + projectQuery, + { + props, + options: { + variables: { + projectId: params.projectId, + }, + }, + } + ); + + return this.subscription.currentResult(); + } + + @action + refreshModel() { + this.refresh(); + } + + @action + willTransition() { + this.globalState.isProjectNavigationListShowing = false; + } + + deactivate() { + this.apolloSubscription.clearSubscription(this.subscription); + } + + private transformData(data: ProjectQueryResponse) { + if (!data.viewer || !data.viewer.project) return {permissions: []}; + + const permissions = data.viewer.project.viewerPermissions.reduce( + (memo: Record, permission: string) => { + memo[permission] = true; + return memo; + }, + {} + ); + + // FIXME: These are a side-effects, we should refactor this to avoid having + // to set state here. + this.globalState.permissions = permissions; + this.globalState.mainColor = data.viewer.project.mainColor; + this.globalState.roles = data.roles; + this.globalState.documentFormats = data.documentFormats; + + return { + project: data.viewer.project, + permissions, + roles: data.roles, + documentFormats: data.documentFormats, + }; + } +} diff --git a/webapp/app/pods/logged-in/project/template.hbs b/webapp/app/pods/logged-in/project/template.hbs index 07393b4d..72c71f2e 100644 --- a/webapp/app/pods/logged-in/project/template.hbs +++ b/webapp/app/pods/logged-in/project/template.hbs @@ -1,5 +1,5 @@
              - +