diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index dbdcdb24c..6e74ab560 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -64,11 +64,13 @@ jobs: - name: Install NodeJS Dependencies run: | - npm config set spin false - npm ci --no-audit --no-color - npm ci --prefix webapp --no-audit --no-color - npm ci --prefix cli --no-audit --no-color - npm ci --prefix jipt --no-audit --no-color + npm set fund false + npm set audit false + npm set color false + npm ci + npm ci --prefix webapp + npm ci --prefix cli + npm ci --prefix jipt - name: Build webapp production run: npm run build-production-inline --prefix webapp diff --git a/.tool-versions b/.tool-versions index 711a8c7e6..92f045f11 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,3 +1,3 @@ elixir 1.15.7-otp-26 erlang 26.1.2 -nodejs 16.19.1 +nodejs 21.6.1 diff --git a/Dockerfile b/Dockerfile index 58b63b9e3..3fbbcdc14 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ # # Build webapp and jipt deps # -FROM node:16.19-bullseye-slim AS webapp-builder +FROM node:21.6.1-bullseye-slim AS webapp-builder RUN apt-get update -y && \ apt-get install -y build-essential git python3 python3-pip && \ apt-get clean && \ @@ -11,7 +11,7 @@ COPY webapp . RUN npm ci --no-audit --no-color && \ npm run build-production -FROM node:16.19-bullseye-slim AS jipt-builder +FROM node:21.6.1-bullseye-slim AS jipt-builder RUN apt-get update -y && \ apt-get install -y build-essential git python3 python3-pip && \ apt-get clean && \ @@ -47,10 +47,11 @@ COPY config config RUN mix deps.get --only prod RUN mix deps.compile --only prod -COPY vendor vendor +COPY vendor/language_tool/priv/ vendor/language_tool/priv/ RUN cd ./vendor/language_tool/priv/native/languagetool && ./gradlew shadowJar RUN cp ./vendor/language_tool/priv/native/languagetool/app/build/libs/language-tool.jar priv/native/language-tool.jar +COPY vendor vendor COPY lib lib RUN mix compile --only prod diff --git a/Makefile b/Makefile index bfea78118..671dc1b22 100644 --- a/Makefile +++ b/Makefile @@ -97,7 +97,7 @@ lint-eslint: .PHONY: lint-prettier lint-prettier: - npx prettier --check './{webapp,jipt,cli}/!(node_modules)/**/*.{js,ts,json,svg,scss,md,hbs}' '*.md' + npx prettier --trailing-comma none --check './{webapp,jipt,cli}/!(node_modules)/**/*.{js,ts,json,svg,scss,md,hbs}' '*.md' .PHONY: lint-template-hbs lint-template-hbs: @@ -110,16 +110,12 @@ type-check: ## Type-check typescript files cd jipt && npx tsc .PHONY: test -test: test-api test-webapp +test: test-api .PHONY: test-api test-api: ## Run the backend test suite mix test -.PHONY: test-webapp -test-webapp: ## Run the frontend test suite - cd webapp && npx ember exam --reporter dot - .PHONY: test-coverage test-coverage: ## Generate the code coverage report mix coveralls @@ -133,7 +129,7 @@ format-elixir: .PHONY: format-prettier format-prettier: - npx prettier --write --single-quote --no-bracket-spacing './{webapp,jipt,cli}/!(node_modules)/**/*.{js,ts,json,svg,scss,md,hbs}' '*.md' + npx prettier --write --single-quote --trailing-comma none --no-bracket-spacing './{webapp,jipt,cli}/!(node_modules)/**/*.{js,ts,json,svg,scss,md,hbs}' '*.md' # Development targets # ------------------- diff --git a/README.md b/README.md index 21bcc141e..4751ade4a 100644 --- a/README.md +++ b/README.md @@ -28,8 +28,8 @@ Accent provides a powerful abstraction around the process maintaining translatio | --------------------------------------------------- | -------------------------------------------------------------------- | | [🚀 Getting started](#-getting-started) | Quickly setup a working app | | [🚧 Requirements](#-requirements) | Dependencies required to run Accent’ stack | -| [🎛 Mix commands](#-executing-mix-commands) | How to execute mix task with the Twelve-Factor pattern | -| [🏎 Quickstart](#-quickstart) | Steps to run the project, from API to webapp, with or without Docker | +| [🎛 Mix commands](#-executing-mix-commands) | How to execute mix task with the Twelve-Factor pattern | +| [🏎 Quickstart](#-quickstart) | Steps to run the project, from API to webapp, with or without Docker | | [🌳 Environment variables](#-environment-variables) | Required and optional env var used | | [✅ Tests](#-tests) | How to run the extensive tests suite | | [🚀 Heroku](#-deploy-on-heroku) | Easy deployment setup with Heroku | @@ -103,13 +103,14 @@ The Makefile should be the main entry for common tasks such as tests, linting, D For the production setup, we use Docker to build an OTP release of the app. With docker-compose, you can run the image locally. Here are the steps to have a working app running locally with Docker: -_When running the production env, you need to provide a valid GOOGLE_API_CLIENT_ID in the `docker-compose.yml` file._ +_When running the production env, you need to provide a valid authentication setup in the `environment` section in `docker-compose.yml` file._ +See the following sections to see available variables to enable third-party logins or dummy login (email only, no password). 1. Run `make build` to build the OTP release with Docker 2. Run `make dev-start-postgresql` to start an instance of Postgresql. The instance will run on port 5432 with the `postgres` user. You can change those values in the `docker-compose.yml` file. 3. Run `make dev-start-application` to start the app! The release hook of the release will execute migrations and seeds before starting the webserver on port 4000 (again you can change the settings in `docker-compose.yml`) -_That’s it! You now have a working Accent instance without installing Elixir or Node!_ +_That’s it! You now have a working Accent instance without installing Elixir or NodeJS!_ ## 🌳 Environment variables @@ -139,24 +140,29 @@ Accent provides a default value for every required environment variable. This me Various login providers are included in Accent using Ueberauth to abstract services. -| Variable | Default | Description | -| -------------------------- | -------------------- | --------------------------------------------------------------------------------------- | -| `DUMMY_LOGIN_ENABLED` | _none_ | If specified, the password-less authentication (with only the email) will be available. | -| `GITHUB_CLIENT_ID` | _none_ | | -| `GITHUB_CLIENT_SECRET` | _none_ | | -| `GITLAB_CLIENT_ID` | _none_ | | -| `GITLAB_CLIENT_SECRET` | _none_ | | -| `GITLAB_SITE_URL` | `https://gitlab.com` | | -| `GOOGLE_API_CLIENT_ID` | _none_ | | -| `GOOGLE_API_CLIENT_SECRET` | _none_ | | -| `SLACK_CLIENT_ID` | _none_ | | -| `SLACK_CLIENT_SECRET` | _none_ | | -| `SLACK_TEAM_ID` | _none_ | | -| `DISCORD_CLIENT_ID` | _none_ | | -| `DISCORD_CLIENT_SECRET` | _none_ | | -| `MICROSOFT_CLIENT_ID` | _none_ | | -| `MICROSOFT_CLIENT_SECRET` | _none_ | | -| `MICROSOFT_TENANT_ID` | _none_ | | +| Variable | Default | Description | +| -------------------------- | ---------------------- | --------------------------------------------------------------------------------------- | +| `DUMMY_LOGIN_ENABLED` | _none_ | If specified, the password-less authentication (with only the email) will be available. | +| `GITHUB_CLIENT_ID` | _none_ | | +| `GITHUB_CLIENT_SECRET` | _none_ | | +| `GITLAB_CLIENT_ID` | _none_ | | +| `GITLAB_CLIENT_SECRET` | _none_ | | +| `GITLAB_SITE_URL` | `https://gitlab.com` | | +| `GOOGLE_API_CLIENT_ID` | _none_ | | +| `GOOGLE_API_CLIENT_SECRET` | _none_ | | +| `SLACK_CLIENT_ID` | _none_ | | +| `SLACK_CLIENT_SECRET` | _none_ | | +| `SLACK_TEAM_ID` | _none_ | | +| `DISCORD_CLIENT_ID` | _none_ | | +| `DISCORD_CLIENT_SECRET` | _none_ | | +| `MICROSOFT_CLIENT_ID` | _none_ | | +| `MICROSOFT_CLIENT_SECRET` | _none_ | | +| `MICROSOFT_TENANT_ID` | _none_ | | +| `OIDC_CLIENT_ID` | _none_ | | +| `OIDC_CLIENT_SECRET` | _none_ | | +| `OIDC_DISCOVERY_URI` | _none_ | | +| `OIDC_UID_FIELD` | `sub` | | +| `OIDC_SCOPE` | `openid profile email` | | ### Email setup diff --git a/cli/README.md b/cli/README.md index 739d57002..74183043d 100644 --- a/cli/README.md +++ b/cli/README.md @@ -20,7 +20,7 @@ $ npm install -g accent-cli $ accent COMMAND running command... $ accent (-v|--version|version) -accent-cli/0.16.0 darwin-arm64 node-v16.19.1 +accent-cli/0.16.2 darwin-arm64 node-v21.6.1 $ accent --help [COMMAND] USAGE $ accent COMMAND @@ -47,7 +47,7 @@ accent-cli reads from a `accent.json` file. The file should contain valid JSON r "source": "localization/fr/*.json", "target": "localization/%slug%/%document_path%.json", "hooks": { - "afterSync": "touch sync-done.txt" + "afterSync": ["touch sync-done.txt", "echo 'Done!'"] } } ] @@ -207,7 +207,7 @@ EXAMPLES $ accent export --order-by=key --version=build.myapp.com:0.12.345 ``` -_See code: [src/commands/export.ts](https://github.com/mirego/accent/blob/v0.16.0/src/commands/export.ts)_ +_See code: [src/commands/export.ts](https://github.com/mirego/accent/blob/v0.16.2/src/commands/export.ts)_ ## `accent format` @@ -225,7 +225,7 @@ EXAMPLE $ accent format ``` -_See code: [src/commands/format.ts](https://github.com/mirego/accent/blob/v0.16.0/src/commands/format.ts)_ +_See code: [src/commands/format.ts](https://github.com/mirego/accent/blob/v0.16.2/src/commands/format.ts)_ ## `accent help [COMMAND]` @@ -262,7 +262,7 @@ EXAMPLE $ accent jipt ``` -_See code: [src/commands/jipt.ts](https://github.com/mirego/accent/blob/v0.16.0/src/commands/jipt.ts)_ +_See code: [src/commands/jipt.ts](https://github.com/mirego/accent/blob/v0.16.2/src/commands/jipt.ts)_ ## `accent lint` @@ -279,7 +279,7 @@ EXAMPLE $ accent lint ``` -_See code: [src/commands/lint.ts](https://github.com/mirego/accent/blob/v0.16.0/src/commands/lint.ts)_ +_See code: [src/commands/lint.ts](https://github.com/mirego/accent/blob/v0.16.2/src/commands/lint.ts)_ ## `accent stats` @@ -299,7 +299,7 @@ EXAMPLE $ accent stats ``` -_See code: [src/commands/stats.ts](https://github.com/mirego/accent/blob/v0.16.0/src/commands/stats.ts)_ +_See code: [src/commands/stats.ts](https://github.com/mirego/accent/blob/v0.16.2/src/commands/stats.ts)_ ## `accent sync` @@ -331,7 +331,7 @@ EXAMPLES $ accent sync --add-translations --merge-type=smart --order-key=key --version=v0.23 ``` -_See code: [src/commands/sync.ts](https://github.com/mirego/accent/blob/v0.16.0/src/commands/sync.ts)_ +_See code: [src/commands/sync.ts](https://github.com/mirego/accent/blob/v0.16.2/src/commands/sync.ts)_ # GitHub Actions diff --git a/cli/package-lock.json b/cli/package-lock.json index a42e4d1c8..4c5e0e18e 100644 --- a/cli/package-lock.json +++ b/cli/package-lock.json @@ -1,12 +1,12 @@ { "name": "accent-cli", - "version": "0.16.0", + "version": "0.16.2", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "accent-cli", - "version": "0.14.0", + "version": "0.16.2", "license": "MIT", "dependencies": { "@oclif/command": "^1.8.22", diff --git a/cli/package.json b/cli/package.json index 87673486a..27c73d014 100644 --- a/cli/package.json +++ b/cli/package.json @@ -1,6 +1,6 @@ { "name": "accent-cli", - "version": "0.16.0", + "version": "0.16.2", "author": "Simon Prévost", "description": "Accent CLI", "bin": { diff --git a/cli/src/base.ts b/cli/src/base.ts index 0620aa699..13994a17a 100644 --- a/cli/src/base.ts +++ b/cli/src/base.ts @@ -17,7 +17,7 @@ const sleep = async (ms: number) => export const configFlag = flags.string({ default: 'accent.json', - description: 'Path to the config file', + description: 'Path to the config file' }); const parseConfigFlag = (argv: string[]) => { diff --git a/cli/src/commands/export.ts b/cli/src/commands/export.ts index 989c88912..d1dc90e4a 100644 --- a/cli/src/commands/export.ts +++ b/cli/src/commands/export.ts @@ -19,7 +19,7 @@ export default class Export extends Command { static examples = [ `$ accent export`, - `$ accent export --order-by=key --version=build.myapp.com:0.12.345`, + `$ accent export --order-by=key --version=build.myapp.com:0.12.345` ]; static args = []; @@ -27,13 +27,13 @@ export default class Export extends Command { 'order-by': flags.string({ default: 'index', description: 'Order of the keys', - options: ['index', 'key'], + options: ['index', 'key'] }), version: flags.string({ default: '', - description: 'Fetch a specific version', + description: 'Fetch a specific version' }), - config: configFlag, + config: configFlag }; async run() { diff --git a/cli/src/commands/format.ts b/cli/src/commands/format.ts index 7bf939ae3..7599ad341 100644 --- a/cli/src/commands/format.ts +++ b/cli/src/commands/format.ts @@ -21,9 +21,9 @@ export default class Format extends Command { 'order-by': flags.string({ default: 'index', description: 'Order of the keys', - options: ['index', 'key', '-index', '-key'], + options: ['index', 'key', '-index', '-key'] }), - config: configFlag, + config: configFlag }; async run() { diff --git a/cli/src/commands/jipt.ts b/cli/src/commands/jipt.ts index a91be0312..3fbf99775 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 = {config: configFlag}; diff --git a/cli/src/commands/lint.ts b/cli/src/commands/lint.ts index 5477e3969..d08c1b407 100644 --- a/cli/src/commands/lint.ts +++ b/cli/src/commands/lint.ts @@ -31,13 +31,13 @@ export default class Lint extends Command { const {path, language} = target; if (fs.existsSync(path)) { const { - data: {lint_translations: lintTranslations}, + data: {lint_translations: lintTranslations} } = (await document.lint(path, language)) as {data: any}; const lintTranslationsWithLocalPath = lintTranslations.map( (lintTranslation: LintTranslation) => ({ ...lintTranslation, - path, + path }) ); diff --git a/cli/src/commands/stats.ts b/cli/src/commands/stats.ts index 26a037f7f..fc838c14c 100644 --- a/cli/src/commands/stats.ts +++ b/cli/src/commands/stats.ts @@ -19,15 +19,15 @@ export default class Stats extends Command { static flags = { version: flags.string({ default: undefined, - description: 'View stats for a specific version', + description: 'View stats for a specific version' }), 'check-reviewed': flags.boolean({ - description: 'Exit 1 when reviewed percentage is not 100%', + description: 'Exit 1 when reviewed percentage is not 100%' }), 'check-translated': flags.boolean({ - description: 'Exit 1 when translated percentage is not 100%', + description: 'Exit 1 when translated percentage is not 100%' }), - config: configFlag, + config: configFlag }; async run() { diff --git a/cli/src/commands/sync.ts b/cli/src/commands/sync.ts index 45bdd9cac..bc999c404 100644 --- a/cli/src/commands/sync.ts +++ b/cli/src/commands/sync.ts @@ -29,7 +29,7 @@ export default class Sync extends Command { static examples = [ `$ accent sync`, `$ accent sync --dry-run --sync-type=force`, - `$ accent sync --add-translations --merge-type=smart --order-key=key --version=v0.23`, + `$ accent sync --add-translations --merge-type=smart --order-key=key --version=v0.23` ]; static args = []; @@ -37,36 +37,40 @@ 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 locally', + 'Add translations in Accent to help translators if you already have translated strings locally' }), - 'dry-run': flags.boolean({ + 'no-local-write': flags.boolean({ default: false, description: - 'Do not write the file from the export _after_ the operation', + 'Do not write to the local files _after_ the sync. Warning: This option could lead to a mismatch between the source of truth (your code repository) and Accent' + }), + 'dry-run': flags.boolean({ + default: false, + description: 'Do not commit the changes in Accent' }), 'merge-type': flags.string({ default: 'passive', description: 'Algorithm to use on existing strings when adding translation', - 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'], + options: ['index', 'key'] }), 'sync-type': flags.string({ default: 'smart', description: 'Algorithm to use on existing strings when syncing the main language', - options: ['smart', 'passive'], + options: ['smart', 'passive'] }), version: flags.string({ default: '', description: - 'Sync a specific version, the tag needs to exists in Accent first', + 'Sync a specific version, the tag needs to exists in Accent first' }), - config: configFlag, + config: configFlag }; async run() { @@ -110,6 +114,8 @@ export default class Sync extends Command { return; } + if (flags['no-local-write']) return; + const formatter = new DocumentExportFormatter(); // From all the documentConfigs, do the export, write to local file and log the results. diff --git a/cli/src/services/document-jipt-paths-fetcher.ts b/cli/src/services/document-jipt-paths-fetcher.ts index e14fc5ac5..c35728f5d 100644 --- a/cli/src/services/document-jipt-paths-fetcher.ts +++ b/cli/src/services/document-jipt-paths-fetcher.ts @@ -20,7 +20,7 @@ export default class DocumentJiptPathsFetcher { return { documentPath: path, language: pseudoLanguageName, - path: parsedTarget, + path: parsedTarget }; }); } diff --git a/cli/src/services/document.ts b/cli/src/services/document.ts index 7e7424c55..e64ffa329 100644 --- a/cli/src/services/document.ts +++ b/cli/src/services/document.ts @@ -65,7 +65,7 @@ export default class Document { const response = await fetch(url, { body: formData, headers: this.authorizationHeader(), - method: 'POST', + method: 'POST' }); await throwOnServerError(response); @@ -87,7 +87,7 @@ export default class Document { const response = await fetch(url, { body: formData, headers: this.authorizationHeader(), - method: 'POST', + method: 'POST' }); await throwOnServerError(response); @@ -114,7 +114,7 @@ export default class Document { const response = await fetch(url, { body: formData, headers: this.authorizationHeader(), - method: 'POST', + method: 'POST' }); await throwOnServerError(response); @@ -146,7 +146,7 @@ export default class Document { const response = await fetch(url, { body: formData, headers: this.authorizationHeader(), - method: 'POST', + method: 'POST' }); await throwOnServerError(response); @@ -174,7 +174,7 @@ export default class Document { ['document_path', documentPath], ['document_format', this.config.format], ['order_by', options['order-by']], - ['language', language], + ['language', language] ]; if (options.version) query.push(['version', options.version]); @@ -182,7 +182,7 @@ export default class Document { const url = `${this.apiUrl}/export?${this.encodeQuery(query)}`; const response = await fetch(url, { - headers: this.authorizationHeader(), + headers: this.authorizationHeader() }); await throwOnServerError(response); @@ -192,7 +192,7 @@ 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] ]; if (this.projectId) query.push(['project_id', this.projectId]); @@ -200,7 +200,7 @@ export default class Document { const url = `${this.apiUrl}/jipt-export?${this.encodeQuery(query)}`; const response = await fetch(url, { - headers: this.authorizationHeader(), + headers: this.authorizationHeader() }); await throwOnServerError(response); diff --git a/cli/src/services/formatters/hook-runner.ts b/cli/src/services/formatters/hook-runner.ts index ffd7ba626..4840b769d 100644 --- a/cli/src/services/formatters/hook-runner.ts +++ b/cli/src/services/formatters/hook-runner.ts @@ -8,10 +8,30 @@ const capitalizeFirstLetter = (str: string) => export default class HookRunnerFomatter { log(name: string, commands: string[]) { const operation = capitalizeFirstLetter(decamelize(name, {separator: ' '})); - console.log(chalk.yellow('➤ '), chalk.bold(chalk.yellow(`${operation}:`))); + console.log(chalk.yellow('➤'), chalk.bold(chalk.yellow(`${operation}:`))); + commands.forEach((command) => { - console.log(' ', chalk.yellow(command)); + console.log(' ', chalk.yellow(command)); + }); + + console.log(''); + } + + error(command: string, errors: string[]) { + console.log(chalk.red('⚠'), chalk.bold(chalk.red(`${command}:`))); + + errors.forEach((error) => { + console.log(' ', chalk.red(error)); }); + + console.log(''); + } + + success(command: string, message: string) { + console.log(chalk.green('✓'), chalk.bold(chalk.green(`${command}:`))); + + console.log(' ', chalk.green(message)); + console.log(''); } } diff --git a/cli/src/services/formatters/project-stats.ts b/cli/src/services/formatters/project-stats.ts index 3588730c8..5b8e006f7 100644 --- a/cli/src/services/formatters/project-stats.ts +++ b/cli/src/services/formatters/project-stats.ts @@ -8,13 +8,13 @@ import { Document, Project, Revision, - Version, + Version } from '../../types/project'; // Services import { fetchFromRevision, - fetchNameFromRevision, + fetchNameFromRevision } from '../revision-slug-fetcher'; import Base from './base'; diff --git a/cli/src/services/hook-runner.ts b/cli/src/services/hook-runner.ts index cbb0bc196..1ba8255c1 100644 --- a/cli/src/services/hook-runner.ts +++ b/cli/src/services/hook-runner.ts @@ -23,9 +23,25 @@ export default class HookRunner { const hooks = this.hooks[name]; if (hooks) { - new Formatter().log(name, hooks); - - hooks.forEach(execSync); + const formatter = new Formatter(); + formatter.log(name, hooks); + + hooks.forEach((hook) => { + try { + const output = execSync(hook, {stdio: 'pipe'}).toString(); + if (output.length > 0) formatter.success(hook, output); + } catch (error: any) { + const output = error.stderr.toString(); + + if (output.length > 0) { + formatter.error(hook, [output]); + } else { + formatter.error(hook, [`Exit status: ${error.status}`]); + } + + process.exit(error.status); + } + }); } return this.document.refreshPaths(); diff --git a/cli/src/services/project-fetcher.ts b/cli/src/services/project-fetcher.ts index 031081d12..e72b9f8e4 100644 --- a/cli/src/services/project-fetcher.ts +++ b/cli/src/services/project-fetcher.ts @@ -115,9 +115,9 @@ export default class ProjectFetcher { body: JSON.stringify({query, variables}), 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 9ba9df482..8b0bf5bde 100644 --- a/cli/src/types/document-config.ts +++ b/cli/src/types/document-config.ts @@ -4,14 +4,14 @@ export enum Hooks { beforeExport = 'beforeExport', afterExport = 'afterExport', beforeSync = 'beforeSync', - afterSync = 'afterSync', + afterSync = 'afterSync' } export enum NamePattern { file = 'file', fileWithSlugSuffix = 'fileWithSlugSuffix', parentDirectory = 'parentDirectory', - fileWithParentDirectory = 'fileWithParentDirectory', + fileWithParentDirectory = 'fileWithParentDirectory' } export interface HookConfig { diff --git a/config/config.exs b/config/config.exs index 1596009fc..609ea7c05 100644 --- a/config/config.exs +++ b/config/config.exs @@ -13,17 +13,14 @@ if config_env() == :dev do end if config_env() == :test do - events = ~w(sync add_translations create_collaborator create_comment complete_review new_conflicts) - - config :accent, Accent.Hook, outbounds: [{Accent.Hook.Outbounds.Mock, events: events}] + config :accent, Accent.Hook, outbounds: [Accent.Hook.Outbounds.Mock] else config :accent, Accent.Hook, outbounds: [ - {Accent.Hook.Outbounds.Discord, events: ~w(sync complete_review new_conflicts)}, - {Accent.Hook.Outbounds.Email, events: ~w(create_collaborator create_comment)}, - {Accent.Hook.Outbounds.Slack, events: ~w(sync complete_review new_conflicts)}, - {Accent.Hook.Outbounds.Websocket, - events: ~w(sync create_collaborator create_comment complete_review new_conflicts)} + Accent.Hook.Outbounds.Discord, + Accent.Hook.Outbounds.Email, + Accent.Hook.Outbounds.Slack, + Accent.Hook.Outbounds.Websocket ] end diff --git a/config/dev.exs b/config/dev.exs index 2521ba125..8929d095a 100644 --- a/config/dev.exs +++ b/config/dev.exs @@ -9,6 +9,11 @@ watchers = "run", "build-dev", cd: Path.expand("../webapp", __DIR__) + ], + npm: [ + "run", + "watch-production-inline", + cd: Path.expand("../jipt", __DIR__) ] ] end diff --git a/config/runtime.exs b/config/runtime.exs index 065c7f72c..94efb0bd8 100644 --- a/config/runtime.exs +++ b/config/runtime.exs @@ -31,17 +31,23 @@ else debug_errors: get_env("DEBUG_ERRORS", :boolean) end -ecto_ipv6? = get_env("ECTO_IPV6", :boolean) - -config :accent, Accent.Repo, - timeout: get_env("DATABASE_TIMEOUT", :integer) || 29_000, - queue_target: get_env("DATABASE_QUEUE_TARGET", :integer) || 500, - queue_interval: get_env("DATABASE_QUEUE_INTERVAL", :integer) || 2000, - pool_size: get_env("DATABASE_POOL_SIZE", :integer), - ssl: get_env("DATABASE_SSL", :boolean), - ssl_opts: [verify: :verify_none], - url: get_env("DATABASE_URL") || "postgres://localhost/accent_development", - socket_options: if(ecto_ipv6?, do: [:inet6], else: []) +if config_env() === :test do + config :accent, Accent.Repo, + pool_size: System.schedulers_online() * 2, + url: get_env("DATABASE_URL") +else + ecto_ipv6? = get_env("ECTO_IPV6", :boolean) + + config :accent, Accent.Repo, + timeout: get_env("DATABASE_TIMEOUT", :integer) || 29_000, + queue_target: get_env("DATABASE_QUEUE_TARGET", :integer) || 500, + queue_interval: get_env("DATABASE_QUEUE_INTERVAL", :integer) || 2000, + pool_size: get_env("DATABASE_POOL_SIZE", :integer), + ssl: get_env("DATABASE_SSL", :boolean), + ssl_opts: [verify: :verify_none], + url: get_env("DATABASE_URL") || "postgres://localhost/accent_development", + socket_options: if(ecto_ipv6?, do: [:inet6], else: []) +end config :accent, Accent.MachineTranslations, default_providers_config: %{ @@ -49,6 +55,11 @@ config :accent, Accent.MachineTranslations, "deepl" => %{"key" => get_env("DEEPL_TRANSLATIONS_KEY")} } +config :accent, Accent.Prompts, + default_providers_config: %{ + "openai" => %{"key" => get_env("OPENAI_API_KEY")} + } + config :accent, LanguageTool, languages: get_env("LANGUAGE_TOOL_LANGUAGES", :comma_separated_list) providers = [] @@ -88,6 +99,11 @@ providers = providers = if get_env("AUTH0_CLIENT_ID"), do: [{:auth0, {Ueberauth.Strategy.Auth0, []}} | providers], else: providers +providers = + if get_env("OIDC_CLIENT_ID"), + do: [{:oidc, {Ueberauth.Strategy.OIDC, [default: [provider: :default_oidc, uid_field: :sub]]}} | providers], + else: providers + providers = if get_env("DUMMY_LOGIN_ENABLED"), do: [{:dummy, {Accent.Auth.Ueberauth.DummyStrategy, []}} | providers], @@ -129,6 +145,18 @@ config :ueberauth, Ueberauth.Strategy.Microsoft.OAuth, client_secret: get_env("MICROSOFT_CLIENT_SECRET"), tenant_id: get_env("MICROSOFT_TENANT_ID") +config :ueberauth, Ueberauth.Strategy.OIDC, + default_oidc: [ + fetch_userinfo: true, + uid_field: get_env("OIDC_UID_FIELD") || "sub", + client_id: get_env("OIDC_CLIENT_ID"), + client_secret: get_env("OIDC_CLIENT_SECRET"), + discovery_document_uri: get_env("OIDC_DISCOVERY_URI"), + redirect_uri: "#{static_uri}/auth/oidc/callback", + response_type: "code", + scope: get_env("OIDC_SCOPE") || "openid profile email" + ] + config :accent, Accent.WebappView, path: "priv/static/webapp/index.html", sentry_dsn: get_env("WEBAPP_SENTRY_DSN") || "", diff --git a/docker-compose.yml b/docker-compose.yml index 399c6476a..05a282d95 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,8 +1,8 @@ version: '3.7' services: application: - image: mirego/accent container_name: accent + network_mode: "host" build: . ports: - 4000:4000 @@ -10,9 +10,9 @@ services: - postgresql environment: - PORT=4000 - - DATABASE_URL=postgres://postgres@postgresql:5432/accent_development + - DATABASE_URL=postgres://postgres@localhost:5432/accent_development postgresql: - image: postgres:10.3 + image: postgres:15.6 container_name: accent-postgres environment: - POSTGRES_DB=accent_development diff --git a/jipt/index.html b/jipt/index.html index 631a0ad7c..98d1feaa1 100644 --- a/jipt/index.html +++ b/jipt/index.html @@ -1,7 +1,7 @@
-

{^demo-accent.foo@session}

+

{^accept-ticket.error@ticketss}

diff --git a/jipt/package-lock.json b/jipt/package-lock.json index b0231b909..1d6bd0274 100644 --- a/jipt/package-lock.json +++ b/jipt/package-lock.json @@ -1,35 +1,44 @@ { "name": "jipt", "version": "1.0.0", - "lockfileVersion": 1, + "lockfileVersion": 3, "requires": true, - "dependencies": { - "@babel/code-frame": { + "packages": { + "": { + "name": "jipt", + "version": "1.0.0", + "license": "ISC", + "devDependencies": { + "parcel-bundler": "1.12.4", + "typescript": "3.8.3" + } + }, + "node_modules/@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": { + "dependencies": { "@babel/highlight": "^7.8.3" } }, - "@babel/compat-data": { + "node_modules/@babel/compat-data": { "version": "7.9.0", "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.9.0.tgz", "integrity": "sha512-zeFQrr+284Ekvd9e7KAX954LkapWiOmQtsfHirhxqfdlX6MEC32iRE+pqUGlYIBchdevaCwvzxWGSy/YBNI85g==", "dev": true, - "requires": { + "dependencies": { "browserslist": "^4.9.1", "invariant": "^2.2.4", "semver": "^5.5.0" } }, - "@babel/core": { + "node_modules/@babel/core": { "version": "7.9.0", "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.9.0.tgz", "integrity": "sha512-kWc7L0fw1xwvI0zi8OKVBuxRVefwGOrKSQMvrQ3dW+bIIavBY3/NpXmpjMy7bQnLgwgzWQZ8TlM57YHpHNHz4w==", "dev": true, - "requires": { + "dependencies": { "@babel/code-frame": "^7.8.3", "@babel/generator": "^7.9.0", "@babel/helper-module-transforms": "^7.9.0", @@ -47,182 +56,203 @@ "semver": "^5.4.1", "source-map": "^0.5.0" }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/json5": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", + "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==", + "dev": true, "dependencies": { - "json5": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", - "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } + "minimist": "^1.2.5" + }, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@babel/core/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true, + "engines": { + "node": ">=0.10.0" } }, - "@babel/generator": { + "node_modules/@babel/generator": { "version": "7.9.4", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.9.4.tgz", "integrity": "sha512-rjP8ahaDy/ouhrvCoU1E5mqaitWrxwuNGU+dy1EpaoK48jZay4MdkskKGIMHLZNewg8sAsqpGSREJwP0zH3YQA==", "dev": true, - "requires": { + "dependencies": { "@babel/types": "^7.9.0", "jsesc": "^2.5.1", "lodash": "^4.17.13", "source-map": "^0.5.0" - }, - "dependencies": { - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } } }, - "@babel/helper-annotate-as-pure": { + "node_modules/@babel/generator/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.8.3.tgz", "integrity": "sha512-6o+mJrZBxOoEX77Ezv9zwW7WV8DdluouRKNY/IR5u/YTMuKHgugHOzYWlYvYLpLA9nPsQCAAASpCIbjI9Mv+Uw==", "dev": true, - "requires": { + "dependencies": { "@babel/types": "^7.8.3" } }, - "@babel/helper-builder-binary-assignment-operator-visitor": { + "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.8.3.tgz", "integrity": "sha512-5eFOm2SyFPK4Rh3XMMRDjN7lBH0orh3ss0g3rTYZnBQ+r6YPj7lgDyCvPphynHvUrobJmeMignBr6Acw9mAPlw==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-explode-assignable-expression": "^7.8.3", "@babel/types": "^7.8.3" } }, - "@babel/helper-builder-react-jsx": { + "node_modules/@babel/helper-builder-react-jsx": { "version": "7.9.0", "resolved": "https://registry.npmjs.org/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.9.0.tgz", "integrity": "sha512-weiIo4gaoGgnhff54GQ3P5wsUQmnSwpkvU0r6ZHq6TzoSzKy4JxHEgnxNytaKbov2a9z/CVNyzliuCOUPEX3Jw==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-annotate-as-pure": "^7.8.3", "@babel/types": "^7.9.0" } }, - "@babel/helper-builder-react-jsx-experimental": { + "node_modules/@babel/helper-builder-react-jsx-experimental": { "version": "7.9.0", "resolved": "https://registry.npmjs.org/@babel/helper-builder-react-jsx-experimental/-/helper-builder-react-jsx-experimental-7.9.0.tgz", "integrity": "sha512-3xJEiyuYU4Q/Ar9BsHisgdxZsRlsShMe90URZ0e6przL26CCs8NJbDoxH94kKT17PcxlMhsCAwZd90evCo26VQ==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-annotate-as-pure": "^7.8.3", "@babel/helper-module-imports": "^7.8.3", "@babel/types": "^7.9.0" } }, - "@babel/helper-compilation-targets": { + "node_modules/@babel/helper-compilation-targets": { "version": "7.8.7", "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.8.7.tgz", "integrity": "sha512-4mWm8DCK2LugIS+p1yArqvG1Pf162upsIsjE7cNBjez+NjliQpVhj20obE520nao0o14DaTnFJv+Fw5a0JpoUw==", "dev": true, - "requires": { + "dependencies": { "@babel/compat-data": "^7.8.6", "browserslist": "^4.9.1", "invariant": "^2.2.4", "levenary": "^1.1.1", "semver": "^5.5.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "@babel/helper-create-regexp-features-plugin": { + "node_modules/@babel/helper-create-regexp-features-plugin": { "version": "7.8.8", "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.8.8.tgz", "integrity": "sha512-LYVPdwkrQEiX9+1R29Ld/wTrmQu1SSKYnuOk3g0CkcZMA1p0gsNxJFj/3gBdaJ7Cg0Fnek5z0DsMULePP7Lrqg==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-annotate-as-pure": "^7.8.3", "@babel/helper-regex": "^7.8.3", "regexpu-core": "^4.7.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "@babel/helper-define-map": { + "node_modules/@babel/helper-define-map": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.8.3.tgz", "integrity": "sha512-PoeBYtxoZGtct3md6xZOCWPcKuMuk3IHhgxsRRNtnNShebf4C8YonTSblsK4tvDbm+eJAw2HAPOfCr+Q/YRG/g==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-function-name": "^7.8.3", "@babel/types": "^7.8.3", "lodash": "^4.17.13" } }, - "@babel/helper-explode-assignable-expression": { + "node_modules/@babel/helper-explode-assignable-expression": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.8.3.tgz", "integrity": "sha512-N+8eW86/Kj147bO9G2uclsg5pwfs/fqqY5rwgIL7eTBklgXjcOJ3btzS5iM6AitJcftnY7pm2lGsrJVYLGjzIw==", "dev": true, - "requires": { + "dependencies": { "@babel/traverse": "^7.8.3", "@babel/types": "^7.8.3" } }, - "@babel/helper-function-name": { + "node_modules/@babel/helper-function-name": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz", "integrity": "sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-get-function-arity": "^7.8.3", "@babel/template": "^7.8.3", "@babel/types": "^7.8.3" } }, - "@babel/helper-get-function-arity": { + "node_modules/@babel/helper-get-function-arity": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz", "integrity": "sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA==", "dev": true, - "requires": { + "dependencies": { "@babel/types": "^7.8.3" } }, - "@babel/helper-hoist-variables": { + "node_modules/@babel/helper-hoist-variables": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.8.3.tgz", "integrity": "sha512-ky1JLOjcDUtSc+xkt0xhYff7Z6ILTAHKmZLHPxAhOP0Nd77O+3nCsd6uSVYur6nJnCI029CrNbYlc0LoPfAPQg==", "dev": true, - "requires": { + "dependencies": { "@babel/types": "^7.8.3" } }, - "@babel/helper-member-expression-to-functions": { + "node_modules/@babel/helper-member-expression-to-functions": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.8.3.tgz", "integrity": "sha512-fO4Egq88utkQFjbPrSHGmGLFqmrshs11d46WI+WZDESt7Wu7wN2G2Iu+NMMZJFDOVRHAMIkB5SNh30NtwCA7RA==", "dev": true, - "requires": { + "dependencies": { "@babel/types": "^7.8.3" } }, - "@babel/helper-module-imports": { + "node_modules/@babel/helper-module-imports": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.8.3.tgz", "integrity": "sha512-R0Bx3jippsbAEtzkpZ/6FIiuzOURPcMjHp+Z6xPe6DtApDJx+w7UYyOLanZqO8+wKR9G10s/FmHXvxaMd9s6Kg==", "dev": true, - "requires": { + "dependencies": { "@babel/types": "^7.8.3" } }, - "@babel/helper-module-transforms": { + "node_modules/@babel/helper-module-transforms": { "version": "7.9.0", "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.9.0.tgz", "integrity": "sha512-0FvKyu0gpPfIQ8EkxlrAydOWROdHpBmiCiRwLkUiBGhCUPRRbVD2/tm3sFr/c/GWFrQ/ffutGUAnx7V0FzT2wA==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-module-imports": "^7.8.3", "@babel/helper-replace-supers": "^7.8.6", "@babel/helper-simple-access": "^7.8.3", @@ -232,36 +262,36 @@ "lodash": "^4.17.13" } }, - "@babel/helper-optimise-call-expression": { + "node_modules/@babel/helper-optimise-call-expression": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.8.3.tgz", "integrity": "sha512-Kag20n86cbO2AvHca6EJsvqAd82gc6VMGule4HwebwMlwkpXuVqrNRj6CkCV2sKxgi9MyAUnZVnZ6lJ1/vKhHQ==", "dev": true, - "requires": { + "dependencies": { "@babel/types": "^7.8.3" } }, - "@babel/helper-plugin-utils": { + "node_modules/@babel/helper-plugin-utils": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", "dev": true }, - "@babel/helper-regex": { + "node_modules/@babel/helper-regex": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.8.3.tgz", "integrity": "sha512-BWt0QtYv/cg/NecOAZMdcn/waj/5P26DR4mVLXfFtDokSR6fyuG0Pj+e2FqtSME+MqED1khnSMulkmGl8qWiUQ==", "dev": true, - "requires": { + "dependencies": { "lodash": "^4.17.13" } }, - "@babel/helper-remap-async-to-generator": { + "node_modules/@babel/helper-remap-async-to-generator": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.8.3.tgz", "integrity": "sha512-kgwDmw4fCg7AVgS4DukQR/roGp+jP+XluJE5hsRZwxCYGg+Rv9wSGErDWhlI90FODdYfd4xG4AQRiMDjjN0GzA==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-annotate-as-pure": "^7.8.3", "@babel/helper-wrap-function": "^7.8.3", "@babel/template": "^7.8.3", @@ -269,318 +299,408 @@ "@babel/types": "^7.8.3" } }, - "@babel/helper-replace-supers": { + "node_modules/@babel/helper-replace-supers": { "version": "7.8.6", "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.8.6.tgz", "integrity": "sha512-PeMArdA4Sv/Wf4zXwBKPqVj7n9UF/xg6slNRtZW84FM7JpE1CbG8B612FyM4cxrf4fMAMGO0kR7voy1ForHHFA==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-member-expression-to-functions": "^7.8.3", "@babel/helper-optimise-call-expression": "^7.8.3", "@babel/traverse": "^7.8.6", "@babel/types": "^7.8.6" } }, - "@babel/helper-simple-access": { + "node_modules/@babel/helper-simple-access": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.8.3.tgz", "integrity": "sha512-VNGUDjx5cCWg4vvCTR8qQ7YJYZ+HBjxOgXEl7ounz+4Sn7+LMD3CFrCTEU6/qXKbA2nKg21CwhhBzO0RpRbdCw==", "dev": true, - "requires": { + "dependencies": { "@babel/template": "^7.8.3", "@babel/types": "^7.8.3" } }, - "@babel/helper-split-export-declaration": { + "node_modules/@babel/helper-split-export-declaration": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz", "integrity": "sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA==", "dev": true, - "requires": { + "dependencies": { "@babel/types": "^7.8.3" } }, - "@babel/helper-validator-identifier": { + "node_modules/@babel/helper-validator-identifier": { "version": "7.9.0", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.0.tgz", "integrity": "sha512-6G8bQKjOh+of4PV/ThDm/rRqlU7+IGoJuofpagU5GlEl29Vv0RGqqt86ZGRV8ZuSOY3o+8yXl5y782SMcG7SHw==", "dev": true }, - "@babel/helper-wrap-function": { + "node_modules/@babel/helper-wrap-function": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.8.3.tgz", "integrity": "sha512-LACJrbUET9cQDzb6kG7EeD7+7doC3JNvUgTEQOx2qaO1fKlzE/Bf05qs9w1oXQMmXlPO65lC3Tq9S6gZpTErEQ==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-function-name": "^7.8.3", "@babel/template": "^7.8.3", "@babel/traverse": "^7.8.3", "@babel/types": "^7.8.3" } }, - "@babel/helpers": { + "node_modules/@babel/helpers": { "version": "7.9.2", "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.9.2.tgz", "integrity": "sha512-JwLvzlXVPjO8eU9c/wF9/zOIN7X6h8DYf7mG4CiFRZRvZNKEF5dQ3H3V+ASkHoIB3mWhatgl5ONhyqHRI6MppA==", "dev": true, - "requires": { + "dependencies": { "@babel/template": "^7.8.3", "@babel/traverse": "^7.9.0", "@babel/types": "^7.9.0" } }, - "@babel/highlight": { + "node_modules/@babel/highlight": { "version": "7.9.0", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.9.0.tgz", "integrity": "sha512-lJZPilxX7Op3Nv/2cvFdnlepPXDxi29wxteT57Q965oc5R9v86ztx0jfxVrTcBk8C2kcPkkDa2Z4T3ZsPPVWsQ==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-validator-identifier": "^7.9.0", "chalk": "^2.0.0", "js-tokens": "^4.0.0" } }, - "@babel/parser": { + "node_modules/@babel/parser": { "version": "7.9.4", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.9.4.tgz", "integrity": "sha512-bC49otXX6N0/VYhgOMh4gnP26E9xnDZK3TmbNpxYzzz9BQLBosQwfyOe9/cXUU3txYhTzLCbcqd5c8y/OmCjHA==", - "dev": true + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } }, - "@babel/plugin-proposal-async-generator-functions": { + "node_modules/@babel/plugin-proposal-async-generator-functions": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.8.3.tgz", "integrity": "sha512-NZ9zLv848JsV3hs8ryEh7Uaz/0KsmPLqv0+PdkDJL1cJy0K4kOCFa8zc1E3mp+RHPQcpdfb/6GovEsW4VDrOMw==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-async-generator-functions instead.", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.8.3", "@babel/helper-remap-async-to-generator": "^7.8.3", "@babel/plugin-syntax-async-generators": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-proposal-dynamic-import": { + "node_modules/@babel/plugin-proposal-dynamic-import": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.8.3.tgz", "integrity": "sha512-NyaBbyLFXFLT9FP+zk0kYlUlA8XtCUbehs67F0nnEg7KICgMc2mNkIeu9TYhKzyXMkrapZFwAhXLdnt4IYHy1w==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-dynamic-import instead.", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.8.3", "@babel/plugin-syntax-dynamic-import": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-proposal-json-strings": { + "node_modules/@babel/plugin-proposal-json-strings": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.8.3.tgz", "integrity": "sha512-KGhQNZ3TVCQG/MjRbAUwuH+14y9q0tpxs1nWWs3pbSleRdDro9SAMMDyye8HhY1gqZ7/NqIc8SKhya0wRDgP1Q==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-json-strings instead.", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.8.3", "@babel/plugin-syntax-json-strings": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-proposal-nullish-coalescing-operator": { + "node_modules/@babel/plugin-proposal-nullish-coalescing-operator": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.8.3.tgz", "integrity": "sha512-TS9MlfzXpXKt6YYomudb/KU7nQI6/xnapG6in1uZxoxDghuSMZsPb6D2fyUwNYSAp4l1iR7QtFOjkqcRYcUsfw==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-nullish-coalescing-operator instead.", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.8.3", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-proposal-numeric-separator": { + "node_modules/@babel/plugin-proposal-numeric-separator": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.8.3.tgz", "integrity": "sha512-jWioO1s6R/R+wEHizfaScNsAx+xKgwTLNXSh7tTC4Usj3ItsPEhYkEpU4h+lpnBwq7NBVOJXfO6cRFYcX69JUQ==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-numeric-separator instead.", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.8.3", "@babel/plugin-syntax-numeric-separator": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-proposal-object-rest-spread": { + "node_modules/@babel/plugin-proposal-object-rest-spread": { "version": "7.9.0", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.9.0.tgz", "integrity": "sha512-UgqBv6bjq4fDb8uku9f+wcm1J7YxJ5nT7WO/jBr0cl0PLKb7t1O6RNR1kZbjgx2LQtsDI9hwoQVmn0yhXeQyow==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-object-rest-spread instead.", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.8.3", "@babel/plugin-syntax-object-rest-spread": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-proposal-optional-catch-binding": { + "node_modules/@babel/plugin-proposal-optional-catch-binding": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.8.3.tgz", "integrity": "sha512-0gkX7J7E+AtAw9fcwlVQj8peP61qhdg/89D5swOkjYbkboA2CVckn3kiyum1DE0wskGb7KJJxBdyEBApDLLVdw==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-optional-catch-binding instead.", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.8.3", "@babel/plugin-syntax-optional-catch-binding": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-proposal-optional-chaining": { + "node_modules/@babel/plugin-proposal-optional-chaining": { "version": "7.9.0", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.9.0.tgz", "integrity": "sha512-NDn5tu3tcv4W30jNhmc2hyD5c56G6cXx4TesJubhxrJeCvuuMpttxr0OnNCqbZGhFjLrg+NIhxxC+BK5F6yS3w==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-optional-chaining instead.", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.8.3", "@babel/plugin-syntax-optional-chaining": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-proposal-unicode-property-regex": { + "node_modules/@babel/plugin-proposal-unicode-property-regex": { "version": "7.8.8", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.8.8.tgz", "integrity": "sha512-EVhjVsMpbhLw9ZfHWSx2iy13Q8Z/eg8e8ccVWt23sWQK5l1UdkoLJPN5w69UA4uITGBnEZD2JOe4QOHycYKv8A==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-unicode-property-regex instead.", "dev": true, - "requires": { + "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.8.8", "@babel/helper-plugin-utils": "^7.8.3" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-syntax-async-generators": { + "node_modules/@babel/plugin-syntax-async-generators": { "version": "7.8.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-syntax-dynamic-import": { + "node_modules/@babel/plugin-syntax-dynamic-import": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-syntax-flow": { + "node_modules/@babel/plugin-syntax-flow": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.8.3.tgz", "integrity": "sha512-innAx3bUbA0KSYj2E2MNFSn9hiCeowOFLxlsuhXzw8hMQnzkDomUr9QCD7E9VF60NmnG1sNTuuv6Qf4f8INYsg==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-syntax-json-strings": { + "node_modules/@babel/plugin-syntax-json-strings": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-syntax-jsx": { + "node_modules/@babel/plugin-syntax-jsx": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.8.3.tgz", "integrity": "sha512-WxdW9xyLgBdefoo0Ynn3MRSkhe5tFVxxKNVdnZSh318WrG2e2jH+E9wd/++JsqcLJZPfz87njQJ8j2Upjm0M0A==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-syntax-nullish-coalescing-operator": { + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-syntax-numeric-separator": { + "node_modules/@babel/plugin-syntax-numeric-separator": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.8.3.tgz", "integrity": "sha512-H7dCMAdN83PcCmqmkHB5dtp+Xa9a6LKSvA2hiFBC/5alSHxM5VgWZXFqDi0YFe8XNGT6iCa+z4V4zSt/PdZ7Dw==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-syntax-object-rest-spread": { + "node_modules/@babel/plugin-syntax-object-rest-spread": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-syntax-optional-catch-binding": { + "node_modules/@babel/plugin-syntax-optional-catch-binding": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-syntax-optional-chaining": { + "node_modules/@babel/plugin-syntax-optional-chaining": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-syntax-top-level-await": { + "node_modules/@babel/plugin-syntax-top-level-await": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.8.3.tgz", "integrity": "sha512-kwj1j9lL/6Wd0hROD3b/OZZ7MSrZLqqn9RAZ5+cYYsflQ9HZBIKCUkr3+uL1MEJ1NePiUbf98jjiMQSv0NMR9g==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-transform-arrow-functions": { + "node_modules/@babel/plugin-transform-arrow-functions": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.8.3.tgz", "integrity": "sha512-0MRF+KC8EqH4dbuITCWwPSzsyO3HIWWlm30v8BbbpOrS1B++isGxPnnuq/IZvOX5J2D/p7DQalQm+/2PnlKGxg==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-transform-async-to-generator": { + "node_modules/@babel/plugin-transform-async-to-generator": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.8.3.tgz", "integrity": "sha512-imt9tFLD9ogt56Dd5CI/6XgpukMwd/fLGSrix2httihVe7LOGVPhyhMh1BU5kDM7iHD08i8uUtmV2sWaBFlHVQ==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-module-imports": "^7.8.3", "@babel/helper-plugin-utils": "^7.8.3", "@babel/helper-remap-async-to-generator": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-transform-block-scoped-functions": { + "node_modules/@babel/plugin-transform-block-scoped-functions": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.8.3.tgz", "integrity": "sha512-vo4F2OewqjbB1+yaJ7k2EJFHlTP3jR634Z9Cj9itpqNjuLXvhlVxgnjsHsdRgASR8xYDrx6onw4vW5H6We0Jmg==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-transform-block-scoping": { + "node_modules/@babel/plugin-transform-block-scoping": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.8.3.tgz", "integrity": "sha512-pGnYfm7RNRgYRi7bids5bHluENHqJhrV4bCZRwc5GamaWIIs07N4rZECcmJL6ZClwjDz1GbdMZFtPs27hTB06w==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.8.3", "lodash": "^4.17.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-transform-classes": { + "node_modules/@babel/plugin-transform-classes": { "version": "7.9.2", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.9.2.tgz", "integrity": "sha512-TC2p3bPzsfvSsqBZo0kJnuelnoK9O3welkUpqSqBQuBF6R5MN2rysopri8kNvtlGIb2jmUO7i15IooAZJjZuMQ==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-annotate-as-pure": "^7.8.3", "@babel/helper-define-map": "^7.8.3", "@babel/helper-function-name": "^7.8.3", @@ -589,287 +709,374 @@ "@babel/helper-replace-supers": "^7.8.6", "@babel/helper-split-export-declaration": "^7.8.3", "globals": "^11.1.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-transform-computed-properties": { + "node_modules/@babel/plugin-transform-computed-properties": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.8.3.tgz", "integrity": "sha512-O5hiIpSyOGdrQZRQ2ccwtTVkgUDBBiCuK//4RJ6UfePllUTCENOzKxfh6ulckXKc0DixTFLCfb2HVkNA7aDpzA==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-transform-destructuring": { + "node_modules/@babel/plugin-transform-destructuring": { "version": "7.8.8", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.8.8.tgz", "integrity": "sha512-eRJu4Vs2rmttFCdhPUM3bV0Yo/xPSdPw6ML9KHs/bjB4bLA5HXlbvYXPOD5yASodGod+krjYx21xm1QmL8dCJQ==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-transform-dotall-regex": { + "node_modules/@babel/plugin-transform-dotall-regex": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.8.3.tgz", "integrity": "sha512-kLs1j9Nn4MQoBYdRXH6AeaXMbEJFaFu/v1nQkvib6QzTj8MZI5OQzqmD83/2jEM1z0DLilra5aWO5YpyC0ALIw==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.8.3", "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-transform-duplicate-keys": { + "node_modules/@babel/plugin-transform-duplicate-keys": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.8.3.tgz", "integrity": "sha512-s8dHiBUbcbSgipS4SMFuWGqCvyge5V2ZeAWzR6INTVC3Ltjig/Vw1G2Gztv0vU/hRG9X8IvKvYdoksnUfgXOEQ==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-transform-exponentiation-operator": { + "node_modules/@babel/plugin-transform-exponentiation-operator": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.8.3.tgz", "integrity": "sha512-zwIpuIymb3ACcInbksHaNcR12S++0MDLKkiqXHl3AzpgdKlFNhog+z/K0+TGW+b0w5pgTq4H6IwV/WhxbGYSjQ==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-builder-binary-assignment-operator-visitor": "^7.8.3", "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-transform-flow-strip-types": { + "node_modules/@babel/plugin-transform-flow-strip-types": { "version": "7.9.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.9.0.tgz", "integrity": "sha512-7Qfg0lKQhEHs93FChxVLAvhBshOPQDtJUTVHr/ZwQNRccCm4O9D79r9tVSoV8iNwjP1YgfD+e/fgHcPkN1qEQg==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.8.3", "@babel/plugin-syntax-flow": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-transform-for-of": { + "node_modules/@babel/plugin-transform-for-of": { "version": "7.9.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.9.0.tgz", "integrity": "sha512-lTAnWOpMwOXpyDx06N+ywmF3jNbafZEqZ96CGYabxHrxNX8l5ny7dt4bK/rGwAh9utyP2b2Hv7PlZh1AAS54FQ==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-transform-function-name": { + "node_modules/@babel/plugin-transform-function-name": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.8.3.tgz", "integrity": "sha512-rO/OnDS78Eifbjn5Py9v8y0aR+aSYhDhqAwVfsTl0ERuMZyr05L1aFSCJnbv2mmsLkit/4ReeQ9N2BgLnOcPCQ==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-function-name": "^7.8.3", "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-transform-literals": { + "node_modules/@babel/plugin-transform-literals": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.8.3.tgz", "integrity": "sha512-3Tqf8JJ/qB7TeldGl+TT55+uQei9JfYaregDcEAyBZ7akutriFrt6C/wLYIer6OYhleVQvH/ntEhjE/xMmy10A==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-transform-member-expression-literals": { + "node_modules/@babel/plugin-transform-member-expression-literals": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.8.3.tgz", "integrity": "sha512-3Wk2EXhnw+rP+IDkK6BdtPKsUE5IeZ6QOGrPYvw52NwBStw9V1ZVzxgK6fSKSxqUvH9eQPR3tm3cOq79HlsKYA==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-transform-modules-amd": { + "node_modules/@babel/plugin-transform-modules-amd": { "version": "7.9.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.9.0.tgz", "integrity": "sha512-vZgDDF003B14O8zJy0XXLnPH4sg+9X5hFBBGN1V+B2rgrB+J2xIypSN6Rk9imB2hSTHQi5OHLrFWsZab1GMk+Q==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-module-transforms": "^7.9.0", "@babel/helper-plugin-utils": "^7.8.3", "babel-plugin-dynamic-import-node": "^2.3.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-transform-modules-commonjs": { + "node_modules/@babel/plugin-transform-modules-commonjs": { "version": "7.9.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.9.0.tgz", "integrity": "sha512-qzlCrLnKqio4SlgJ6FMMLBe4bySNis8DFn1VkGmOcxG9gqEyPIOzeQrA//u0HAKrWpJlpZbZMPB1n/OPa4+n8g==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-module-transforms": "^7.9.0", "@babel/helper-plugin-utils": "^7.8.3", "@babel/helper-simple-access": "^7.8.3", "babel-plugin-dynamic-import-node": "^2.3.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-transform-modules-systemjs": { + "node_modules/@babel/plugin-transform-modules-systemjs": { "version": "7.9.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.9.0.tgz", "integrity": "sha512-FsiAv/nao/ud2ZWy4wFacoLOm5uxl0ExSQ7ErvP7jpoihLR6Cq90ilOFyX9UXct3rbtKsAiZ9kFt5XGfPe/5SQ==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-hoist-variables": "^7.8.3", "@babel/helper-module-transforms": "^7.9.0", "@babel/helper-plugin-utils": "^7.8.3", "babel-plugin-dynamic-import-node": "^2.3.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-transform-modules-umd": { + "node_modules/@babel/plugin-transform-modules-umd": { "version": "7.9.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.9.0.tgz", "integrity": "sha512-uTWkXkIVtg/JGRSIABdBoMsoIeoHQHPTL0Y2E7xf5Oj7sLqwVsNXOkNk0VJc7vF0IMBsPeikHxFjGe+qmwPtTQ==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-module-transforms": "^7.9.0", "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-transform-named-capturing-groups-regex": { + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.8.3.tgz", "integrity": "sha512-f+tF/8UVPU86TrCb06JoPWIdDpTNSGGcAtaD9mLP0aYGA0OS0j7j7DHJR0GTFrUZPUU6loZhbsVZgTh0N+Qdnw==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "@babel/plugin-transform-new-target": { + "node_modules/@babel/plugin-transform-new-target": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.8.3.tgz", "integrity": "sha512-QuSGysibQpyxexRyui2vca+Cmbljo8bcRckgzYV4kRIsHpVeyeC3JDO63pY+xFZ6bWOBn7pfKZTqV4o/ix9sFw==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-transform-object-super": { + "node_modules/@babel/plugin-transform-object-super": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.8.3.tgz", "integrity": "sha512-57FXk+gItG/GejofIyLIgBKTas4+pEU47IXKDBWFTxdPd7F80H8zybyAY7UoblVfBhBGs2EKM+bJUu2+iUYPDQ==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.8.3", "@babel/helper-replace-supers": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-transform-parameters": { + "node_modules/@babel/plugin-transform-parameters": { "version": "7.9.3", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.9.3.tgz", "integrity": "sha512-fzrQFQhp7mIhOzmOtPiKffvCYQSK10NR8t6BBz2yPbeUHb9OLW8RZGtgDRBn8z2hGcwvKDL3vC7ojPTLNxmqEg==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-get-function-arity": "^7.8.3", "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-transform-property-literals": { + "node_modules/@babel/plugin-transform-property-literals": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.8.3.tgz", "integrity": "sha512-uGiiXAZMqEoQhRWMK17VospMZh5sXWg+dlh2soffpkAl96KAm+WZuJfa6lcELotSRmooLqg0MWdH6UUq85nmmg==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-transform-react-jsx": { + "node_modules/@babel/plugin-transform-react-jsx": { "version": "7.9.4", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.9.4.tgz", "integrity": "sha512-Mjqf3pZBNLt854CK0C/kRuXAnE6H/bo7xYojP+WGtX8glDGSibcwnsWwhwoSuRg0+EBnxPC1ouVnuetUIlPSAw==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-builder-react-jsx": "^7.9.0", "@babel/helper-builder-react-jsx-experimental": "^7.9.0", "@babel/helper-plugin-utils": "^7.8.3", "@babel/plugin-syntax-jsx": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-transform-regenerator": { + "node_modules/@babel/plugin-transform-regenerator": { "version": "7.8.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.8.7.tgz", "integrity": "sha512-TIg+gAl4Z0a3WmD3mbYSk+J9ZUH6n/Yc57rtKRnlA/7rcCvpekHXe0CMZHP1gYp7/KLe9GHTuIba0vXmls6drA==", "dev": true, - "requires": { + "dependencies": { "regenerator-transform": "^0.14.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-transform-reserved-words": { + "node_modules/@babel/plugin-transform-reserved-words": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.8.3.tgz", "integrity": "sha512-mwMxcycN3omKFDjDQUl+8zyMsBfjRFr0Zn/64I41pmjv4NJuqcYlEtezwYtw9TFd9WR1vN5kiM+O0gMZzO6L0A==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-transform-shorthand-properties": { + "node_modules/@babel/plugin-transform-shorthand-properties": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.8.3.tgz", "integrity": "sha512-I9DI6Odg0JJwxCHzbzW08ggMdCezoWcuQRz3ptdudgwaHxTjxw5HgdFJmZIkIMlRymL6YiZcped4TTCB0JcC8w==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-transform-spread": { + "node_modules/@babel/plugin-transform-spread": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.8.3.tgz", "integrity": "sha512-CkuTU9mbmAoFOI1tklFWYYbzX5qCIZVXPVy0jpXgGwkplCndQAa58s2jr66fTeQnA64bDox0HL4U56CFYoyC7g==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-transform-sticky-regex": { + "node_modules/@babel/plugin-transform-sticky-regex": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.8.3.tgz", "integrity": "sha512-9Spq0vGCD5Bb4Z/ZXXSK5wbbLFMG085qd2vhL1JYu1WcQ5bXqZBAYRzU1d+p79GcHs2szYv5pVQCX13QgldaWw==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.8.3", "@babel/helper-regex": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-transform-template-literals": { + "node_modules/@babel/plugin-transform-template-literals": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.8.3.tgz", "integrity": "sha512-820QBtykIQOLFT8NZOcTRJ1UNuztIELe4p9DCgvj4NK+PwluSJ49we7s9FB1HIGNIYT7wFUJ0ar2QpCDj0escQ==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-annotate-as-pure": "^7.8.3", "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-transform-typeof-symbol": { + "node_modules/@babel/plugin-transform-typeof-symbol": { "version": "7.8.4", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.8.4.tgz", "integrity": "sha512-2QKyfjGdvuNfHsb7qnBBlKclbD4CfshH2KvDabiijLMGXPHJXGxtDzwIF7bQP+T0ysw8fYTtxPafgfs/c1Lrqg==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-transform-unicode-regex": { + "node_modules/@babel/plugin-transform-unicode-regex": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.8.3.tgz", "integrity": "sha512-+ufgJjYdmWfSQ+6NS9VGUR2ns8cjJjYbrbi11mZBTaWm+Fui/ncTLFF28Ei1okavY+xkojGr1eJxNsWYeA5aZw==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.8.3", "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/preset-env": { + "node_modules/@babel/preset-env": { "version": "7.9.0", "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.9.0.tgz", "integrity": "sha512-712DeRXT6dyKAM/FMbQTV/FvRCms2hPCx+3weRjZ8iQVQWZejWWk1wwG6ViWMyqb/ouBbGOl5b6aCk0+j1NmsQ==", "dev": true, - "requires": { + "dependencies": { "@babel/compat-data": "^7.9.0", "@babel/helper-compilation-targets": "^7.8.7", "@babel/helper-module-imports": "^7.8.3", @@ -930,47 +1137,53 @@ "invariant": "^2.2.2", "levenary": "^1.1.1", "semver": "^5.5.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/preset-modules": { + "node_modules/@babel/preset-modules": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.3.tgz", "integrity": "sha512-Ra3JXOHBq2xd56xSF7lMKXdjBn3T772Y1Wet3yWnkDly9zHvJki029tAFzvAAK5cf4YV3yoxuP61crYRol6SVg==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.0.0", "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", "@babel/plugin-transform-dotall-regex": "^7.4.4", "@babel/types": "^7.4.4", "esutils": "^2.0.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/runtime": { + "node_modules/@babel/runtime": { "version": "7.9.2", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.9.2.tgz", "integrity": "sha512-NE2DtOdufG7R5vnfQUTehdTfNycfUANEtCa9PssN9O/xmTzP4E08UI797ixaei6hBEVL9BI/PsdJS5x7mWoB9Q==", "dev": true, - "requires": { + "dependencies": { "regenerator-runtime": "^0.13.4" } }, - "@babel/template": { + "node_modules/@babel/template": { "version": "7.8.6", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.6.tgz", "integrity": "sha512-zbMsPMy/v0PWFZEhQJ66bqjhH+z0JgMoBWuikXybgG3Gkd/3t5oQ1Rw2WQhnSrsOmsKXnZOx15tkC4qON/+JPg==", "dev": true, - "requires": { + "dependencies": { "@babel/code-frame": "^7.8.3", "@babel/parser": "^7.8.6", "@babel/types": "^7.8.6" } }, - "@babel/traverse": { + "node_modules/@babel/traverse": { "version": "7.9.0", "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.9.0.tgz", "integrity": "sha512-jAZQj0+kn4WTHO5dUZkZKhbFrqZE7K5LAQ5JysMnmvGij+wOdr+8lWqPeW0BcF4wFwrEXXtdGO7wcV6YPJcf3w==", "dev": true, - "requires": { + "dependencies": { "@babel/code-frame": "^7.8.3", "@babel/generator": "^7.9.0", "@babel/helper-function-name": "^7.8.3", @@ -982,398 +1195,467 @@ "lodash": "^4.17.13" } }, - "@babel/types": { + "node_modules/@babel/types": { "version": "7.9.0", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.0.tgz", "integrity": "sha512-BS9JKfXkzzJl8RluW4JGknzpiUV7ZrvTayM6yfqLTVBEnFtyowVIOu6rqxRd5cVO6yGoWf4T8u8dgK9oB+GCng==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-validator-identifier": "^7.9.0", "lodash": "^4.17.13", "to-fast-properties": "^2.0.0" } }, - "@iarna/toml": { + "node_modules/@iarna/toml": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/@iarna/toml/-/toml-2.2.3.tgz", "integrity": "sha512-FmuxfCuolpLl0AnQ2NHSzoUKWEJDFl63qXjzdoWBVyFCXzMGm1spBzk7LeHNoVCiWCF7mRVms9e6jEV9+MoPbg==", "dev": true }, - "@mrmlnc/readdir-enhanced": { + "node_modules/@mrmlnc/readdir-enhanced": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz", "integrity": "sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==", "dev": true, - "requires": { + "dependencies": { "call-me-maybe": "^1.0.1", "glob-to-regexp": "^0.3.0" + }, + "engines": { + "node": ">=4" } }, - "@nodelib/fs.stat": { + "node_modules/@nodelib/fs.stat": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz", "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==", - "dev": true + "dev": true, + "engines": { + "node": ">= 6" + } }, - "@parcel/fs": { + "node_modules/@parcel/fs": { "version": "1.11.0", "resolved": "https://registry.npmjs.org/@parcel/fs/-/fs-1.11.0.tgz", "integrity": "sha512-86RyEqULbbVoeo8OLcv+LQ1Vq2PKBAvWTU9fCgALxuCTbbs5Ppcvll4Vr+Ko1AnmMzja/k++SzNAwJfeQXVlpA==", "dev": true, - "requires": { + "dependencies": { "@parcel/utils": "^1.11.0", "mkdirp": "^0.5.1", "rimraf": "^2.6.2" + }, + "engines": { + "node": ">= 6.0.0" } }, - "@parcel/logger": { + "node_modules/@parcel/logger": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/@parcel/logger/-/logger-1.11.1.tgz", "integrity": "sha512-9NF3M6UVeP2udOBDILuoEHd8VrF4vQqoWHEafymO1pfSoOMfxrSJZw1MfyAAIUN/IFp9qjcpDCUbDZB+ioVevA==", "dev": true, - "requires": { + "dependencies": { "@parcel/workers": "^1.11.0", "chalk": "^2.1.0", "grapheme-breaker": "^0.3.2", "ora": "^2.1.0", "strip-ansi": "^4.0.0" + }, + "engines": { + "node": ">= 6.0.0" } }, - "@parcel/utils": { + "node_modules/@parcel/utils": { "version": "1.11.0", "resolved": "https://registry.npmjs.org/@parcel/utils/-/utils-1.11.0.tgz", "integrity": "sha512-cA3p4jTlaMeOtAKR/6AadanOPvKeg8VwgnHhOyfi0yClD0TZS/hi9xu12w4EzA/8NtHu0g6o4RDfcNjqN8l1AQ==", - "dev": true + "dev": true, + "engines": { + "node": ">= 6.0.0" + } }, - "@parcel/watcher": { + "node_modules/@parcel/watcher": { "version": "1.12.1", "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-1.12.1.tgz", "integrity": "sha512-od+uCtCxC/KoNQAIE1vWx1YTyKYY+7CTrxBJPRh3cDWw/C0tCtlBMVlrbplscGoEpt6B27KhJDCv82PBxOERNA==", "dev": true, - "requires": { + "dependencies": { "@parcel/utils": "^1.11.0", "chokidar": "^2.1.5" } }, - "@parcel/workers": { + "node_modules/@parcel/workers": { "version": "1.11.0", "resolved": "https://registry.npmjs.org/@parcel/workers/-/workers-1.11.0.tgz", "integrity": "sha512-USSjRAAQYsZFlv43FUPdD+jEGML5/8oLF0rUzPQTtK4q9kvaXr49F5ZplyLz5lox78cLZ0TxN2bIDQ1xhOkulQ==", "dev": true, - "requires": { + "dependencies": { "@parcel/utils": "^1.11.0", "physical-cpu-count": "^2.0.0" + }, + "engines": { + "node": ">= 6.0.0" } }, - "@types/q": { + "node_modules/@types/q": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.2.tgz", "integrity": "sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw==", "dev": true }, - "abab": { + "node_modules/abab": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.3.tgz", "integrity": "sha512-tsFzPpcttalNjFBCFMqsKYQcWxxen1pgJR56by//QwvJc4/OUS3kPOOttx2tSIfjsylB0pYu7f5D3K1RCxUnUg==", + "deprecated": "Use your platform's native atob() and btoa() methods instead", "dev": true }, - "acorn": { + "node_modules/acorn": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.1.tgz", "integrity": "sha512-add7dgA5ppRPxCFJoAGfMDi7PIBXq1RtGo7BhbLaxwrXPOmw8gq48Y9ozT01hUKy9byMjlR20EJhu5zlkErEkg==", - "dev": true + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } }, - "acorn-globals": { + "node_modules/acorn-globals": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.3.4.tgz", "integrity": "sha512-clfQEh21R+D0leSbUdWf3OcfqyaCSAQ8Ryq00bofSekfr9W8u1jyYZo6ir0xu9Gtcf7BjcHJpnbZH7JOCpP60A==", "dev": true, - "requires": { + "dependencies": { "acorn": "^6.0.1", "acorn-walk": "^6.0.1" + } + }, + "node_modules/acorn-globals/node_modules/acorn": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz", + "integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==", + "dev": true, + "bin": { + "acorn": "bin/acorn" }, - "dependencies": { - "acorn": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz", - "integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==", - "dev": true - } + "engines": { + "node": ">=0.4.0" } }, - "acorn-walk": { + "node_modules/acorn-walk": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.2.0.tgz", "integrity": "sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==", - "dev": true + "dev": true, + "engines": { + "node": ">=0.4.0" + } }, - "ajv": { + "node_modules/ajv": { "version": "6.12.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.0.tgz", "integrity": "sha512-D6gFiFA0RRLyUbvijN74DWAjXSFxWKaWP7mldxkVhyhAV3+SWA9HEJPHQ2c9soIeTFJqcSdFDGFgdqs1iUU2Hw==", "dev": true, - "requires": { + "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, - "alphanum-sort": { + "node_modules/alphanum-sort": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/alphanum-sort/-/alphanum-sort-1.0.2.tgz", "integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM=", "dev": true }, - "ansi-regex": { + "node_modules/ansi-regex": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true + "dev": true, + "engines": { + "node": ">=4" + } }, - "ansi-styles": { + "node_modules/ansi-styles": { "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": { + "dependencies": { "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" } }, - "ansi-to-html": { + "node_modules/ansi-to-html": { "version": "0.6.14", "resolved": "https://registry.npmjs.org/ansi-to-html/-/ansi-to-html-0.6.14.tgz", "integrity": "sha512-7ZslfB1+EnFSDO5Ju+ue5Y6It19DRnZXWv8jrGHgIlPna5Mh4jz7BV5jCbQneXNFurQcKoolaaAjHtgSBfOIuA==", "dev": true, - "requires": { + "dependencies": { "entities": "^1.1.2" + }, + "bin": { + "ansi-to-html": "bin/ansi-to-html" + }, + "engines": { + "node": "*" } }, - "anymatch": { + "node_modules/anymatch": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", "dev": true, - "requires": { + "dependencies": { "micromatch": "^3.1.4", "normalize-path": "^2.1.1" - }, + } + }, + "node_modules/anymatch/node_modules/normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, "dependencies": { - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } - } + "remove-trailing-separator": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" } }, - "argparse": { + "node_modules/argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "dev": true, - "requires": { + "dependencies": { "sprintf-js": "~1.0.2" } }, - "arr-diff": { + "node_modules/arr-diff": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "arr-flatten": { + "node_modules/arr-flatten": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "arr-union": { + "node_modules/arr-union": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "array-equal": { + "node_modules/array-equal": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz", "integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=", "dev": true }, - "array-unique": { + "node_modules/array-unique": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "asn1": { + "node_modules/asn1": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", "dev": true, - "requires": { + "dependencies": { "safer-buffer": "~2.1.0" } }, - "asn1.js": { + "node_modules/asn1.js": { "version": "4.10.1", "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", "dev": true, - "requires": { + "dependencies": { "bn.js": "^4.0.0", "inherits": "^2.0.1", "minimalistic-assert": "^1.0.0" } }, - "assert": { + "node_modules/assert": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", "dev": true, - "requires": { + "dependencies": { "object-assign": "^4.1.1", "util": "0.10.3" - }, - "dependencies": { - "inherits": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", - "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", - "dev": true - }, - "util": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", - "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", - "dev": true, - "requires": { - "inherits": "2.0.1" - } - } } }, - "assert-plus": { + "node_modules/assert-plus": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/assert/node_modules/inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", "dev": true }, - "assign-symbols": { + "node_modules/assert/node_modules/util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "dev": true, + "dependencies": { + "inherits": "2.0.1" + } + }, + "node_modules/assign-symbols": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "async-each": { + "node_modules/async-each": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", "dev": true }, - "async-limiter": { + "node_modules/async-limiter": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", "dev": true }, - "asynckit": { + "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", "dev": true }, - "atob": { + "node_modules/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 + "dev": true, + "bin": { + "atob": "bin/atob.js" + }, + "engines": { + "node": ">= 4.5.0" + } }, - "aws-sign2": { + "node_modules/aws-sign2": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", - "dev": true + "dev": true, + "engines": { + "node": "*" + } }, - "aws4": { + "node_modules/aws4": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.9.1.tgz", "integrity": "sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug==", "dev": true }, - "babel-plugin-dynamic-import-node": { + "node_modules/babel-plugin-dynamic-import-node": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz", "integrity": "sha512-o6qFkpeQEBxcqt0XYlWzAVxNCSCZdUgcR8IRlhD/8DylxjjO4foPcvTW0GGKa/cVt3rvxZ7o5ippJ+/0nvLhlQ==", "dev": true, - "requires": { + "dependencies": { "object.assign": "^4.1.0" } }, - "babel-runtime": { + "node_modules/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": { + "dependencies": { "core-js": "^2.4.0", "regenerator-runtime": "^0.11.0" - }, - "dependencies": { - "regenerator-runtime": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", - "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", - "dev": true - } } }, - "babel-types": { + "node_modules/babel-runtime/node_modules/regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", + "dev": true + }, + "node_modules/babel-types": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", "dev": true, - "requires": { + "dependencies": { "babel-runtime": "^6.26.0", "esutils": "^2.0.2", "lodash": "^4.17.4", "to-fast-properties": "^1.0.3" - }, - "dependencies": { - "to-fast-properties": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", - "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", - "dev": true - } } }, - "babylon-walk": { + "node_modules/babel-types/node_modules/to-fast-properties": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", + "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/babylon-walk": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/babylon-walk/-/babylon-walk-1.0.2.tgz", "integrity": "sha1-OxWl3btIKni0zpwByLoYFwLZ1s4=", "dev": true, - "requires": { + "dependencies": { "babel-runtime": "^6.11.6", "babel-types": "^6.15.0", "lodash.clone": "^4.5.0" } }, - "balanced-match": { + "node_modules/balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", "dev": true }, - "base": { + "node_modules/base": { "version": "0.11.2", "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", "dev": true, - "requires": { + "dependencies": { "cache-base": "^1.0.1", "class-utils": "^0.3.5", "component-emitter": "^1.2.1", @@ -1382,105 +1664,123 @@ "mixin-deep": "^1.2.0", "pascalcase": "^0.1.1" }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "dependencies": { + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base/node_modules/is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "deprecated": "Please upgrade to v1.0.1", + "dev": true, "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "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" - } - } + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base/node_modules/is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "deprecated": "Please upgrade to v1.0.1", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base/node_modules/is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=0.10.0" } }, - "base64-js": { + "node_modules/base64-js": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==", "dev": true }, - "bcrypt-pbkdf": { + "node_modules/bcrypt-pbkdf": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", "dev": true, - "requires": { + "dependencies": { "tweetnacl": "^0.14.3" } }, - "binary-extensions": { + "node_modules/binary-extensions": { "version": "1.13.1", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "bindings": { + "node_modules/bindings": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", "dev": true, - "requires": { + "dependencies": { "file-uri-to-path": "1.0.0" } }, - "bn.js": { + "node_modules/bn.js": { "version": "4.11.8", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", "dev": true }, - "boolbase": { + "node_modules/boolbase": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", "dev": true }, - "brace-expansion": { + "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, - "requires": { + "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, - "braces": { + "node_modules/braces": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", "dev": true, - "requires": { + "dependencies": { "arr-flatten": "^1.1.0", "array-unique": "^0.3.2", "extend-shallow": "^2.0.1", @@ -1492,48 +1792,55 @@ "split-string": "^3.0.2", "to-regex": "^3.0.1" }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/braces/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "brfs": { + "node_modules/brfs": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/brfs/-/brfs-1.6.1.tgz", "integrity": "sha512-OfZpABRQQf+Xsmju8XE9bDjs+uU4vLREGolP7bDgcpsI17QREyZ4Bl+2KLxxx1kCgA0fAIhKQBaBYh+PEcCqYQ==", "dev": true, - "requires": { + "dependencies": { "quote-stream": "^1.0.1", "resolve": "^1.1.5", "static-module": "^2.2.0", "through2": "^2.0.0" + }, + "bin": { + "brfs": "bin/cmd.js" } }, - "brorand": { + "node_modules/brorand": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", "dev": true }, - "browser-process-hrtime": { + "node_modules/browser-process-hrtime": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==", "dev": true }, - "browserify-aes": { + "node_modules/browserify-aes": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", "dev": true, - "requires": { + "dependencies": { "buffer-xor": "^1.0.3", "cipher-base": "^1.0.0", "create-hash": "^1.1.0", @@ -1542,45 +1849,45 @@ "safe-buffer": "^5.0.1" } }, - "browserify-cipher": { + "node_modules/browserify-cipher": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", "dev": true, - "requires": { + "dependencies": { "browserify-aes": "^1.0.4", "browserify-des": "^1.0.0", "evp_bytestokey": "^1.0.0" } }, - "browserify-des": { + "node_modules/browserify-des": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", "dev": true, - "requires": { + "dependencies": { "cipher-base": "^1.0.1", "des.js": "^1.0.0", "inherits": "^2.0.1", "safe-buffer": "^5.1.2" } }, - "browserify-rsa": { + "node_modules/browserify-rsa": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", "dev": true, - "requires": { + "dependencies": { "bn.js": "^4.1.0", "randombytes": "^2.0.1" } }, - "browserify-sign": { + "node_modules/browserify-sign": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", "dev": true, - "requires": { + "dependencies": { "bn.js": "^4.1.1", "browserify-rsa": "^4.0.0", "create-hash": "^1.1.0", @@ -1590,76 +1897,84 @@ "parse-asn1": "^5.0.0" } }, - "browserify-zlib": { + "node_modules/browserify-zlib": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", "dev": true, - "requires": { - "pako": "~1.0.5" - }, "dependencies": { - "pako": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", - "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", - "dev": true - } + "pako": "~1.0.5" } }, - "browserslist": { + "node_modules/browserify-zlib/node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "dev": true + }, + "node_modules/browserslist": { "version": "4.11.1", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.11.1.tgz", "integrity": "sha512-DCTr3kDrKEYNw6Jb9HFxVLQNaue8z+0ZfRBRjmCunKDEXEBajKDj2Y+Uelg+Pi29OnvaSGwjOsnRyNEkXzHg5g==", "dev": true, - "requires": { + "dependencies": { "caniuse-lite": "^1.0.30001038", "electron-to-chromium": "^1.3.390", "node-releases": "^1.1.53", "pkg-up": "^2.0.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "funding": { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" } }, - "buffer": { + "node_modules/buffer": { "version": "4.9.2", "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", "dev": true, - "requires": { + "dependencies": { "base64-js": "^1.0.2", "ieee754": "^1.1.4", "isarray": "^1.0.0" } }, - "buffer-equal": { + "node_modules/buffer-equal": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-0.0.1.tgz", "integrity": "sha1-kbx0sR6kBbyRa8aqkI+q+ltKrEs=", - "dev": true + "dev": true, + "engines": { + "node": ">=0.4.0" + } }, - "buffer-from": { + "node_modules/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 }, - "buffer-xor": { + "node_modules/buffer-xor": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", "dev": true }, - "builtin-status-codes": { + "node_modules/builtin-status-codes": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", "dev": true }, - "cache-base": { + "node_modules/cache-base": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", "dev": true, - "requires": { + "dependencies": { "collection-visit": "^1.0.0", "component-emitter": "^1.2.1", "get-value": "^2.0.6", @@ -1669,89 +1984,121 @@ "to-object-path": "^0.3.0", "union-value": "^1.0.0", "unset-value": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "call-me-maybe": { + "node_modules/call-me-maybe": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz", "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=", "dev": true }, - "caller-callsite": { + "node_modules/caller-callsite": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=", "dev": true, - "requires": { + "dependencies": { "callsites": "^2.0.0" + }, + "engines": { + "node": ">=4" } }, - "caller-path": { + "node_modules/caller-path": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz", "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=", "dev": true, - "requires": { + "dependencies": { "caller-callsite": "^2.0.0" + }, + "engines": { + "node": ">=4" } }, - "callsites": { + "node_modules/callsites": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=", - "dev": true + "dev": true, + "engines": { + "node": ">=4" + } }, - "camelcase": { + "node_modules/camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true + "dev": true, + "engines": { + "node": ">=6" + } }, - "caniuse-api": { + "node_modules/caniuse-api": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", "dev": true, - "requires": { + "dependencies": { "browserslist": "^4.0.0", "caniuse-lite": "^1.0.0", "lodash.memoize": "^4.1.2", "lodash.uniq": "^4.5.0" } }, - "caniuse-lite": { - "version": "1.0.30001039", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001039.tgz", - "integrity": "sha512-SezbWCTT34eyFoWHgx8UWso7YtvtM7oosmFoXbCkdC6qJzRfBTeTgE9REtKtiuKXuMwWTZEvdnFNGAyVMorv8Q==", - "dev": true + "node_modules/caniuse-lite": { + "version": "1.0.30001584", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001584.tgz", + "integrity": "sha512-LOz7CCQ9M1G7OjJOF9/mzmqmj3jE/7VOmrfw6Mgs0E8cjOsbRXQJHsPBfmBOXDskXKrHLyyW3n7kpDW/4BsfpQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] }, - "caseless": { + "node_modules/caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", "dev": true }, - "chalk": { + "node_modules/chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, - "requires": { + "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" } }, - "chokidar": { + "node_modules/chokidar": { "version": "2.1.8", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "deprecated": "Chokidar 2 does not receive security updates since 2019. Upgrade to chokidar 3 with 15x fewer dependencies", "dev": true, - "requires": { + "dependencies": { "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", @@ -1760,276 +2107,321 @@ "path-is-absolute": "^1.0.0", "readdirp": "^2.2.1", "upath": "^1.1.1" + }, + "optionalDependencies": { + "fsevents": "^1.2.7" } }, - "cipher-base": { + "node_modules/cipher-base": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", "dev": true, - "requires": { + "dependencies": { "inherits": "^2.0.1", "safe-buffer": "^5.0.1" } }, - "class-utils": { + "node_modules/class-utils": { "version": "0.3.6", "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", "dev": true, - "requires": { + "dependencies": { "arr-union": "^3.1.0", "define-property": "^0.2.5", "isobject": "^3.0.0", "static-extend": "^0.1.1" }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/class-utils/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - } + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "cli-cursor": { + "node_modules/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=", "dev": true, - "requires": { + "dependencies": { "restore-cursor": "^2.0.0" + }, + "engines": { + "node": ">=4" } }, - "cli-spinners": { + "node_modules/cli-spinners": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-1.3.1.tgz", "integrity": "sha512-1QL4544moEsDVH9T/l6Cemov/37iv1RtoKf7NJ04A60+4MREXNfx/QvavbH6QoGdsD4N4Mwy49cmaINR/o2mdg==", - "dev": true + "dev": true, + "engines": { + "node": ">=4" + } }, - "cliui": { + "node_modules/cliui": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", "dev": true, - "requires": { + "dependencies": { "string-width": "^3.1.0", "strip-ansi": "^5.2.0", "wrap-ansi": "^5.1.0" - }, + } + }, + "node_modules/cliui/node_modules/ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/cliui/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "strip-ansi": { - "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": "^4.1.0" - } - } + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" } }, - "clone": { + "node_modules/clone": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", - "dev": true + "dev": true, + "engines": { + "node": ">=0.8" + } }, - "coa": { + "node_modules/coa": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/coa/-/coa-2.0.2.tgz", "integrity": "sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA==", "dev": true, - "requires": { + "dependencies": { "@types/q": "^1.5.1", "chalk": "^2.4.1", "q": "^1.1.2" + }, + "engines": { + "node": ">= 4.0" } }, - "collection-visit": { + "node_modules/collection-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", "dev": true, - "requires": { + "dependencies": { "map-visit": "^1.0.0", "object-visit": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "color": { + "node_modules/color": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/color/-/color-3.1.2.tgz", "integrity": "sha512-vXTJhHebByxZn3lDvDJYw4lR5+uB3vuoHsuYA5AKuxRVn5wzzIfQKGLBmgdVRHKTJYeK5rvJcHnrd0Li49CFpg==", "dev": true, - "requires": { + "dependencies": { "color-convert": "^1.9.1", "color-string": "^1.5.2" } }, - "color-convert": { + "node_modules/color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, - "requires": { + "dependencies": { "color-name": "1.1.3" } }, - "color-name": { + "node_modules/color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", "dev": true }, - "color-string": { + "node_modules/color-string": { "version": "1.5.3", "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.3.tgz", "integrity": "sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw==", "dev": true, - "requires": { + "dependencies": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" } }, - "combined-stream": { + "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "dev": true, - "requires": { + "dependencies": { "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" } }, - "command-exists": { + "node_modules/command-exists": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.8.tgz", "integrity": "sha512-PM54PkseWbiiD/mMsbvW351/u+dafwTJ0ye2qB60G1aGQP9j3xK2gmMDc+R34L3nDtx4qMCitXT75mkbkGJDLw==", "dev": true }, - "commander": { + "node_modules/commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "dev": true }, - "component-emitter": { + "node_modules/component-emitter": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", "dev": true }, - "concat-map": { + "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true }, - "concat-stream": { + "node_modules/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": { + "engines": [ + "node >= 0.8" + ], + "dependencies": { "buffer-from": "^1.0.0", "inherits": "^2.0.3", "readable-stream": "^2.2.2", "typedarray": "^0.0.6" } }, - "console-browserify": { + "node_modules/console-browserify": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==", "dev": true }, - "constants-browserify": { + "node_modules/constants-browserify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", "dev": true }, - "convert-source-map": { + "node_modules/convert-source-map": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", "dev": true, - "requires": { + "dependencies": { "safe-buffer": "~5.1.1" } }, - "copy-descriptor": { + "node_modules/copy-descriptor": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "core-js": { + "node_modules/core-js": { "version": "2.6.11", "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz", "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==", - "dev": true + "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.", + "dev": true, + "hasInstallScript": true }, - "core-js-compat": { + "node_modules/core-js-compat": { "version": "3.6.4", "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.6.4.tgz", "integrity": "sha512-zAa3IZPvsJ0slViBQ2z+vgyyTuhd3MFn1rBQjZSKVEgB0UMYhUkCj9jJUVPgGTGqWvsBVmfnruXgTcNyTlEiSA==", "dev": true, - "requires": { + "dependencies": { "browserslist": "^4.8.3", "semver": "7.0.0" }, - "dependencies": { - "semver": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", - "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", - "dev": true - } + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" } }, - "core-util-is": { + "node_modules/core-js-compat/node_modules/semver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", + "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/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 }, - "cosmiconfig": { + "node_modules/cosmiconfig": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", "dev": true, - "requires": { + "dependencies": { "import-fresh": "^2.0.0", "is-directory": "^0.3.1", "js-yaml": "^3.13.1", "parse-json": "^4.0.0" + }, + "engines": { + "node": ">=4" } }, - "create-ecdh": { + "node_modules/create-ecdh": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==", "dev": true, - "requires": { + "dependencies": { "bn.js": "^4.1.0", "elliptic": "^6.0.0" } }, - "create-hash": { + "node_modules/create-hash": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", "dev": true, - "requires": { + "dependencies": { "cipher-base": "^1.0.1", "inherits": "^2.0.1", "md5.js": "^1.3.4", @@ -2037,12 +2429,12 @@ "sha.js": "^2.4.0" } }, - "create-hmac": { + "node_modules/create-hmac": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", "dev": true, - "requires": { + "dependencies": { "cipher-base": "^1.0.3", "create-hash": "^1.1.0", "inherits": "^2.0.1", @@ -2051,25 +2443,28 @@ "sha.js": "^2.4.8" } }, - "cross-spawn": { + "node_modules/cross-spawn": { "version": "6.0.5", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", "dev": true, - "requires": { + "dependencies": { "nice-try": "^1.0.4", "path-key": "^2.0.1", "semver": "^5.5.0", "shebang-command": "^1.2.0", "which": "^1.2.9" + }, + "engines": { + "node": ">=4.8" } }, - "crypto-browserify": { + "node_modules/crypto-browserify": { "version": "3.12.0", "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", "dev": true, - "requires": { + "dependencies": { "browserify-cipher": "^1.0.0", "browserify-sign": "^4.0.0", "create-ecdh": "^4.0.0", @@ -2081,183 +2476,230 @@ "public-encrypt": "^4.0.0", "randombytes": "^2.0.0", "randomfill": "^1.0.3" + }, + "engines": { + "node": "*" } }, - "css-color-names": { + "node_modules/css-color-names": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz", "integrity": "sha1-gIrcLnnPhHOAabZGyyDsJ762KeA=", - "dev": true + "dev": true, + "engines": { + "node": "*" + } }, - "css-declaration-sorter": { + "node_modules/css-declaration-sorter": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-4.0.1.tgz", "integrity": "sha512-BcxQSKTSEEQUftYpBVnsH4SF05NTuBokb19/sBt6asXGKZ/6VP7PLG1CBCkFDYOnhXhPh0jMhO6xZ71oYHXHBA==", "dev": true, - "requires": { + "dependencies": { "postcss": "^7.0.1", "timsort": "^0.3.0" + }, + "engines": { + "node": ">4" } }, - "css-modules-loader-core": { + "node_modules/css-modules-loader-core": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/css-modules-loader-core/-/css-modules-loader-core-1.1.0.tgz", "integrity": "sha1-WQhmgpShvs0mGuCkziGwtVHyHRY=", "dev": true, - "requires": { + "dependencies": { "icss-replace-symbols": "1.1.0", "postcss": "6.0.1", "postcss-modules-extract-imports": "1.1.0", "postcss-modules-local-by-default": "1.2.0", "postcss-modules-scope": "1.1.0", "postcss-modules-values": "1.3.0" + } + }, + "node_modules/css-modules-loader-core/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/css-modules-loader-core/node_modules/ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/css-modules-loader-core/node_modules/chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "dependencies": { + "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" }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/css-modules-loader-core/node_modules/chalk/node_modules/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, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/css-modules-loader-core/node_modules/has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/css-modules-loader-core/node_modules/postcss": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.1.tgz", + "integrity": "sha1-AA29H47vIXqjaLmiEsX8QLKo8/I=", + "dev": true, "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" - }, - "dependencies": { - "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 - } - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "postcss": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.1.tgz", - "integrity": "sha1-AA29H47vIXqjaLmiEsX8QLKo8/I=", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "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": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } + "chalk": "^1.1.3", + "source-map": "^0.5.6", + "supports-color": "^3.2.3" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/css-modules-loader-core/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/css-modules-loader-core/node_modules/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, + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/css-modules-loader-core/node_modules/supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "dependencies": { + "has-flag": "^1.0.0" + }, + "engines": { + "node": ">=0.8.0" } }, - "css-select": { + "node_modules/css-select": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.1.0.tgz", "integrity": "sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ==", "dev": true, - "requires": { + "dependencies": { "boolbase": "^1.0.0", "css-what": "^3.2.1", "domutils": "^1.7.0", "nth-check": "^1.0.2" } }, - "css-select-base-adapter": { + "node_modules/css-select-base-adapter": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz", "integrity": "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w==", "dev": true }, - "css-selector-tokenizer": { + "node_modules/css-selector-tokenizer": { "version": "0.7.2", "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.7.2.tgz", "integrity": "sha512-yj856NGuAymN6r8bn8/Jl46pR+OC3eEvAhfGYDUe7YPtTPAYrSSw4oAniZ9Y8T5B92hjhwTBLUen0/vKPxf6pw==", "dev": true, - "requires": { + "dependencies": { "cssesc": "^3.0.0", "fastparse": "^1.1.2", "regexpu-core": "^4.6.0" } }, - "css-tree": { + "node_modules/css-tree": { "version": "1.0.0-alpha.37", "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.37.tgz", "integrity": "sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg==", "dev": true, - "requires": { + "dependencies": { "mdn-data": "2.0.4", "source-map": "^0.6.1" + }, + "engines": { + "node": ">=8.0.0" } }, - "css-what": { + "node_modules/css-what": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/css-what/-/css-what-3.2.1.tgz", "integrity": "sha512-WwOrosiQTvyms+Ti5ZC5vGEK0Vod3FTt1ca+payZqvKuGJF+dq7bG63DstxtN0dpm6FxY27a/zS3Wten+gEtGw==", - "dev": true + "dev": true, + "engines": { + "node": ">= 6" + } }, - "cssesc": { + "node_modules/cssesc": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "dev": true + "dev": true, + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } }, - "cssnano": { + "node_modules/cssnano": { "version": "4.1.10", "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-4.1.10.tgz", "integrity": "sha512-5wny+F6H4/8RgNlaqab4ktc3e0/blKutmq8yNlBFXA//nSFFAqAngjNVRzUvCgYROULmZZUoosL/KSoZo5aUaQ==", "dev": true, - "requires": { + "dependencies": { "cosmiconfig": "^5.0.0", "cssnano-preset-default": "^4.0.7", "is-resolvable": "^1.0.0", "postcss": "^7.0.0" + }, + "engines": { + "node": ">=6.9.0" } }, - "cssnano-preset-default": { + "node_modules/cssnano-preset-default": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-4.0.7.tgz", "integrity": "sha512-x0YHHx2h6p0fCl1zY9L9roD7rnlltugGu7zXSKQx6k2rYw0Hi3IqxcoAGF7u9Q5w1nt7vK0ulxV8Lo+EvllGsA==", "dev": true, - "requires": { + "dependencies": { "css-declaration-sorter": "^4.0.1", "cssnano-util-raw-cache": "^4.0.1", "postcss": "^7.0.0", @@ -2288,362 +2730,426 @@ "postcss-reduce-transforms": "^4.0.2", "postcss-svgo": "^4.0.2", "postcss-unique-selectors": "^4.0.1" + }, + "engines": { + "node": ">=6.9.0" } }, - "cssnano-util-get-arguments": { + "node_modules/cssnano-util-get-arguments": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/cssnano-util-get-arguments/-/cssnano-util-get-arguments-4.0.0.tgz", "integrity": "sha1-7ToIKZ8h11dBsg87gfGU7UnMFQ8=", - "dev": true + "dev": true, + "engines": { + "node": ">=6.9.0" + } }, - "cssnano-util-get-match": { + "node_modules/cssnano-util-get-match": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/cssnano-util-get-match/-/cssnano-util-get-match-4.0.0.tgz", "integrity": "sha1-wOTKB/U4a7F+xeUiULT1lhNlFW0=", - "dev": true + "dev": true, + "engines": { + "node": ">=6.9.0" + } }, - "cssnano-util-raw-cache": { + "node_modules/cssnano-util-raw-cache": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/cssnano-util-raw-cache/-/cssnano-util-raw-cache-4.0.1.tgz", "integrity": "sha512-qLuYtWK2b2Dy55I8ZX3ky1Z16WYsx544Q0UWViebptpwn/xDBmog2TLg4f+DBMg1rJ6JDWtn96WHbOKDWt1WQA==", "dev": true, - "requires": { + "dependencies": { "postcss": "^7.0.0" + }, + "engines": { + "node": ">=6.9.0" } }, - "cssnano-util-same-parent": { + "node_modules/cssnano-util-same-parent": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/cssnano-util-same-parent/-/cssnano-util-same-parent-4.0.1.tgz", "integrity": "sha512-WcKx5OY+KoSIAxBW6UBBRay1U6vkYheCdjyVNDm85zt5K9mHoGOfsOsqIszfAqrQQFIIKgjh2+FDgIj/zsl21Q==", - "dev": true + "dev": true, + "engines": { + "node": ">=6.9.0" + } }, - "csso": { + "node_modules/csso": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/csso/-/csso-4.0.3.tgz", "integrity": "sha512-NL3spysxUkcrOgnpsT4Xdl2aiEiBG6bXswAABQVHcMrfjjBisFOKwLDOmf4wf32aPdcJws1zds2B0Rg+jqMyHQ==", "dev": true, - "requires": { + "dependencies": { "css-tree": "1.0.0-alpha.39" }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/csso/node_modules/css-tree": { + "version": "1.0.0-alpha.39", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.39.tgz", + "integrity": "sha512-7UvkEYgBAHRG9Nt980lYxjsTrCyHFN53ky3wVsDkiMdVqylqRt+Zc+jm5qw7/qyOvN2dHSYtX0e4MbCCExSvnA==", + "dev": true, "dependencies": { - "css-tree": { - "version": "1.0.0-alpha.39", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.39.tgz", - "integrity": "sha512-7UvkEYgBAHRG9Nt980lYxjsTrCyHFN53ky3wVsDkiMdVqylqRt+Zc+jm5qw7/qyOvN2dHSYtX0e4MbCCExSvnA==", - "dev": true, - "requires": { - "mdn-data": "2.0.6", - "source-map": "^0.6.1" - } - }, - "mdn-data": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.6.tgz", - "integrity": "sha512-rQvjv71olwNHgiTbfPZFkJtjNMciWgswYeciZhtvWLO8bmX3TnhyA62I6sTWOyZssWHJJjY6/KiWwqQsWWsqOA==", - "dev": true - } + "mdn-data": "2.0.6", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=8.0.0" } }, - "cssom": { + "node_modules/csso/node_modules/mdn-data": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.6.tgz", + "integrity": "sha512-rQvjv71olwNHgiTbfPZFkJtjNMciWgswYeciZhtvWLO8bmX3TnhyA62I6sTWOyZssWHJJjY6/KiWwqQsWWsqOA==", + "dev": true + }, + "node_modules/cssom": { "version": "0.3.8", "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", "dev": true }, - "cssstyle": { + "node_modules/cssstyle": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-1.4.0.tgz", "integrity": "sha512-GBrLZYZ4X4x6/QEoBnIrqb8B/f5l4+8me2dkom/j1Gtbxy0kBv6OGzKuAsGM75bkGwGAFkt56Iwg28S3XTZgSA==", "dev": true, - "requires": { + "dependencies": { "cssom": "0.3.x" } }, - "dashdash": { + "node_modules/dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", "dev": true, - "requires": { + "dependencies": { "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" } }, - "data-urls": { + "node_modules/data-urls": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.1.0.tgz", "integrity": "sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ==", "dev": true, - "requires": { + "dependencies": { "abab": "^2.0.0", "whatwg-mimetype": "^2.2.0", "whatwg-url": "^7.0.0" } }, - "deasync": { + "node_modules/deasync": { "version": "0.1.19", "resolved": "https://registry.npmjs.org/deasync/-/deasync-0.1.19.tgz", "integrity": "sha512-oh3MRktfnPlLysCPpBpKZZzb4cUC/p0aA3SyRGp15lN30juJBTo/CiD0d4fR+f1kBtUQoJj1NE9RPNWQ7BQ9Mg==", "dev": true, - "requires": { + "hasInstallScript": true, + "dependencies": { "bindings": "^1.5.0", "node-addon-api": "^1.7.1" + }, + "engines": { + "node": ">=0.11.0" } }, - "debug": { + "node_modules/debug": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)", "dev": true, - "requires": { + "dependencies": { "ms": "^2.1.1" } }, - "decamelize": { + "node_modules/decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "decode-uri-component": { + "node_modules/decode-uri-component": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10" + } }, - "deep-is": { + "node_modules/deep-is": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", "dev": true }, - "defaults": { + "node_modules/defaults": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", "dev": true, - "requires": { - "clone": "^1.0.2" - }, "dependencies": { - "clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", - "dev": true - } + "clone": "^1.0.2" + } + }, + "node_modules/defaults/node_modules/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", + "dev": true, + "engines": { + "node": ">=0.8" } }, - "define-properties": { + "node_modules/define-properties": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", "dev": true, - "requires": { + "dependencies": { "object-keys": "^1.0.12" + }, + "engines": { + "node": ">= 0.4" } }, - "define-property": { + "node_modules/define-property": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", "dev": true, - "requires": { + "dependencies": { "is-descriptor": "^1.0.2", "isobject": "^3.0.1" }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/define-property/node_modules/is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "deprecated": "Please upgrade to v1.0.1", + "dev": true, "dependencies": { - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "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" - } - } + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/define-property/node_modules/is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "deprecated": "Please upgrade to v1.0.1", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/define-property/node_modules/is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=0.10.0" } }, - "delayed-stream": { + "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "dev": true + "dev": true, + "engines": { + "node": ">=0.4.0" + } }, - "depd": { + "node_modules/depd": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", - "dev": true + "dev": true, + "engines": { + "node": ">= 0.6" + } }, - "des.js": { + "node_modules/des.js": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", "dev": true, - "requires": { + "dependencies": { "inherits": "^2.0.1", "minimalistic-assert": "^1.0.0" } }, - "destroy": { + "node_modules/destroy": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", "dev": true }, - "diffie-hellman": { + "node_modules/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": { + "dependencies": { "bn.js": "^4.1.0", "miller-rabin": "^4.0.0", "randombytes": "^2.0.0" } }, - "dom-serializer": { + "node_modules/dom-serializer": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", "dev": true, - "requires": { + "dependencies": { "domelementtype": "^2.0.1", "entities": "^2.0.0" - }, - "dependencies": { - "domelementtype": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.0.1.tgz", - "integrity": "sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ==", - "dev": true - }, - "entities": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.0.tgz", - "integrity": "sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw==", - "dev": true - } } }, - "domain-browser": { + "node_modules/dom-serializer/node_modules/domelementtype": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.0.1.tgz", + "integrity": "sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ==", + "dev": true + }, + "node_modules/dom-serializer/node_modules/entities": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.0.tgz", + "integrity": "sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw==", + "dev": true + }, + "node_modules/domain-browser": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", - "dev": true + "dev": true, + "engines": { + "node": ">=0.4", + "npm": ">=1.2" + } }, - "domelementtype": { + "node_modules/domelementtype": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", "dev": true }, - "domexception": { + "node_modules/domexception": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/domexception/-/domexception-1.0.1.tgz", "integrity": "sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug==", + "deprecated": "Use your platform's native DOMException instead", "dev": true, - "requires": { + "dependencies": { "webidl-conversions": "^4.0.2" } }, - "domhandler": { + "node_modules/domhandler": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", "dev": true, - "requires": { + "dependencies": { "domelementtype": "1" } }, - "domutils": { + "node_modules/domutils": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", "dev": true, - "requires": { + "dependencies": { "dom-serializer": "0", "domelementtype": "1" } }, - "dot-prop": { + "node_modules/dot-prop": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.2.0.tgz", "integrity": "sha512-uEUyaDKoSQ1M4Oq8l45hSE26SnTxL6snNnqvK/VWx5wJhmff5z0FUVJDKDanor/6w3kzE3i7XZOk+7wC0EXr1A==", "dev": true, - "requires": { + "dependencies": { "is-obj": "^2.0.0" + }, + "engines": { + "node": ">=8" } }, - "dotenv": { + "node_modules/dotenv": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-5.0.1.tgz", "integrity": "sha512-4As8uPrjfwb7VXC+WnLCbXK7y+Ueb2B3zgNCePYfhxS1PYeaO1YTeplffTEcbfLhvFNGLAz90VvJs9yomG7bow==", - "dev": true + "dev": true, + "engines": { + "node": ">=4.6.0" + } }, - "dotenv-expand": { + "node_modules/dotenv-expand": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz", "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==", "dev": true }, - "duplexer2": { + "node_modules/duplexer2": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", "dev": true, - "requires": { + "dependencies": { "readable-stream": "^2.0.2" } }, - "ecc-jsbn": { + "node_modules/ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", "dev": true, - "requires": { + "dependencies": { "jsbn": "~0.1.0", "safer-buffer": "^2.1.0" } }, - "ee-first": { + "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", "dev": true }, - "electron-to-chromium": { + "node_modules/electron-to-chromium": { "version": "1.3.398", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.398.tgz", "integrity": "sha512-BJjxuWLKFbM5axH3vES7HKMQgAknq9PZHBkMK/rEXUQG9i1Iw5R+6hGkm6GtsQSANjSUrh/a6m32nzCNDNo/+w==", "dev": true }, - "elliptic": { + "node_modules/elliptic": { "version": "6.5.2", "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.2.tgz", "integrity": "sha512-f4x70okzZbIQl/NSRLkI/+tteV/9WqL98zx+SQ69KbXxmVrmjwsNUPn/gYJJ0sHvEak24cZgHIPegRePAtA/xw==", "dev": true, - "requires": { + "dependencies": { "bn.js": "^4.4.0", "brorand": "^1.0.1", "hash.js": "^1.0.0", @@ -2653,45 +3159,54 @@ "minimalistic-crypto-utils": "^1.0.0" } }, - "emoji-regex": { + "node_modules/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 }, - "encodeurl": { + "node_modules/encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", - "dev": true + "dev": true, + "engines": { + "node": ">= 0.8" + } }, - "entities": { + "node_modules/entities": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==", "dev": true }, - "envinfo": { + "node_modules/envinfo": { "version": "7.5.0", "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.5.0.tgz", "integrity": "sha512-jDgnJaF/Btomk+m3PZDTTCb5XIIIX3zYItnCRfF73zVgvinLoRomuhi75Y4su0PtQxWz4v66XnLLckyvyJTOIQ==", - "dev": true + "dev": true, + "bin": { + "envinfo": "dist/cli.js" + }, + "engines": { + "node": ">=4" + } }, - "error-ex": { + "node_modules/error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", "dev": true, - "requires": { + "dependencies": { "is-arrayish": "^0.2.1" } }, - "es-abstract": { + "node_modules/es-abstract": { "version": "1.17.5", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.5.tgz", "integrity": "sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg==", "dev": true, - "requires": { + "dependencies": { "es-to-primitive": "^1.2.1", "function-bind": "^1.1.1", "has": "^1.0.3", @@ -2704,97 +3219,141 @@ "string.prototype.trimleft": "^2.1.1", "string.prototype.trimright": "^2.1.1" }, - "dependencies": { - "object-inspect": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", - "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==", - "dev": true - } + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-abstract/node_modules/object-inspect": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", + "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "es-to-primitive": { + "node_modules/es-to-primitive": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", "dev": true, - "requires": { + "dependencies": { "is-callable": "^1.1.4", "is-date-object": "^1.0.1", "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "escape-html": { + "node_modules/escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", "dev": true }, - "escape-string-regexp": { + "node_modules/escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true + "dev": true, + "engines": { + "node": ">=0.8.0" + } }, - "escodegen": { + "node_modules/escodegen": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.9.1.tgz", "integrity": "sha512-6hTjO1NAWkHnDk3OqQ4YrCuwwmGHL9S3nPlzBOUG/R44rda3wLNrfvQ5fkSGjyhHFKM7ALPKcKGrwvCLe0lC7Q==", "dev": true, - "requires": { + "dependencies": { "esprima": "^3.1.3", "estraverse": "^4.2.0", "esutils": "^2.0.2", - "optionator": "^0.8.1", + "optionator": "^0.8.1" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=4.0" + }, + "optionalDependencies": { "source-map": "~0.6.1" } }, - "esprima": { + "node_modules/esprima": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", - "dev": true + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } }, - "estraverse": { + "node_modules/estraverse": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true + "dev": true, + "engines": { + "node": ">=4.0" + } }, - "esutils": { + "node_modules/esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "etag": { + "node_modules/etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", - "dev": true + "dev": true, + "engines": { + "node": ">= 0.6" + } }, - "events": { + "node_modules/events": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/events/-/events-3.1.0.tgz", "integrity": "sha512-Rv+u8MLHNOdMjTAFeT3nCjHn2aGlx435FP/sDHNaRhDEMwyI/aB22Kj2qIN8R0cw3z28psEQLYwxVKLsKrMgWg==", - "dev": true + "dev": true, + "engines": { + "node": ">=0.8.x" + } }, - "evp_bytestokey": { + "node_modules/evp_bytestokey": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", "dev": true, - "requires": { + "dependencies": { "md5.js": "^1.3.4", "safe-buffer": "^5.1.1" } }, - "expand-brackets": { + "node_modules/expand-brackets": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", "dev": true, - "requires": { + "dependencies": { "debug": "^2.3.3", "define-property": "^0.2.5", "extend-shallow": "^2.0.1", @@ -2803,75 +3362,86 @@ "snapdragon": "^0.8.1", "to-regex": "^3.0.1" }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } + "ms": "2.0.0" + } + }, + "node_modules/expand-brackets/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "extend": { + "node_modules/expand-brackets/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", "dev": true }, - "extend-shallow": { + "node_modules/extend-shallow": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", "dev": true, - "requires": { + "dependencies": { "assign-symbols": "^1.0.0", "is-extendable": "^1.0.1" }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extend-shallow/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - } + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" } }, - "extglob": { + "node_modules/extglob": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", "dev": true, - "requires": { + "dependencies": { "array-unique": "^0.3.2", "define-property": "^1.0.0", "expand-brackets": "^2.1.4", @@ -2881,1029 +3451,1297 @@ "snapdragon": "^0.8.1", "to-regex": "^3.0.1" }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "dependencies": { + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "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-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob/node_modules/is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "deprecated": "Please upgrade to v1.0.1", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob/node_modules/is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "deprecated": "Please upgrade to v1.0.1", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob/node_modules/is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=0.10.0" } }, - "extsprintf": { + "node_modules/extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", - "dev": true + "dev": true, + "engines": [ + "node >=0.6.0" + ] }, - "falafel": { + "node_modules/falafel": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/falafel/-/falafel-2.2.4.tgz", "integrity": "sha512-0HXjo8XASWRmsS0X1EkhwEMZaD3Qvp7FfURwjLKjG1ghfRm/MGZl2r4cWUTv41KdNghTw4OUMmVtdGQp3+H+uQ==", "dev": true, - "requires": { + "dependencies": { "acorn": "^7.1.1", "foreach": "^2.0.5", "isarray": "^2.0.1", "object-keys": "^1.0.6" }, - "dependencies": { - "isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true - } + "engines": { + "node": ">=0.4.0" } }, - "fast-deep-equal": { + "node_modules/falafel/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, + "node_modules/fast-deep-equal": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==", "dev": true }, - "fast-glob": { + "node_modules/fast-glob": { "version": "2.2.7", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.7.tgz", "integrity": "sha512-g1KuQwHOZAmOZMuBtHdxDtju+T2RT8jgCC9aANsbpdiDDTSnjgfuVsIBNKbUeJI3oKMRExcfNDtJl4OhbffMsw==", "dev": true, - "requires": { + "dependencies": { "@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" + }, + "engines": { + "node": ">=4.0.0" } }, - "fast-json-stable-stringify": { + "node_modules/fast-json-stable-stringify": { "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": { + "node_modules/fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", "dev": true }, - "fastparse": { + "node_modules/fastparse": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.2.tgz", "integrity": "sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==", "dev": true }, - "file-uri-to-path": { + "node_modules/file-uri-to-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", "dev": true }, - "filesize": { + "node_modules/filesize": { "version": "3.6.1", "resolved": "https://registry.npmjs.org/filesize/-/filesize-3.6.1.tgz", "integrity": "sha512-7KjR1vv6qnicaPMi1iiTcI85CyYwRO/PSFCu6SvqL8jN2Wjt/NIYQTFtFs7fSDCYOstUkEWIQGFUg5YZQfjlcg==", - "dev": true + "dev": true, + "engines": { + "node": ">= 0.4.0" + } }, - "fill-range": { + "node_modules/fill-range": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", "dev": true, - "requires": { + "dependencies": { "extend-shallow": "^2.0.1", "is-number": "^3.0.0", "repeat-string": "^1.6.1", "to-regex-range": "^2.1.0" }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fill-range/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "find-up": { + "node_modules/find-up": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", "dev": true, - "requires": { + "dependencies": { "locate-path": "^2.0.0" + }, + "engines": { + "node": ">=4" } }, - "for-in": { + "node_modules/for-in": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "foreach": { + "node_modules/foreach": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", "dev": true }, - "forever-agent": { + "node_modules/forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", - "dev": true + "dev": true, + "engines": { + "node": "*" + } }, - "form-data": { + "node_modules/form-data": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", "dev": true, - "requires": { + "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.6", "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" } }, - "fragment-cache": { + "node_modules/fragment-cache": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", "dev": true, - "requires": { + "dependencies": { "map-cache": "^0.2.2" + }, + "engines": { + "node": ">=0.10.0" } }, - "fresh": { + "node_modules/fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", - "dev": true + "dev": true, + "engines": { + "node": ">= 0.6" + } }, - "fs.realpath": { + "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true }, - "fsevents": { + "node_modules/fsevents": { "version": "1.2.12", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.12.tgz", "integrity": "sha512-Ggd/Ktt7E7I8pxZRbGIs7vwqAPscSESMrCSkx2FtWeqmheJgCo2R74fTsZFCifr0VTPwqRpPv17+6b8Zp7th0Q==", + "bundleDependencies": [ + "node-pre-gyp" + ], + "deprecated": "The v1 package contains DANGEROUS / INSECURE binaries. Upgrade to safe fsevents v2", "dev": true, + "hasInstallScript": true, "optional": true, - "requires": { + "os": [ + "darwin" + ], + "dependencies": { "bindings": "^1.5.0", "nan": "^2.12.1", "node-pre-gyp": "*" }, + "engines": { + "node": ">= 4.0" + } + }, + "node_modules/fsevents/node_modules/abbrev": { + "version": "1.1.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "optional": true + }, + "node_modules/fsevents/node_modules/ansi-regex": { + "version": "2.1.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fsevents/node_modules/aproba": { + "version": "1.2.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "optional": true + }, + "node_modules/fsevents/node_modules/are-we-there-yet": { + "version": "1.1.5", + "dev": true, + "inBundle": true, + "license": "ISC", + "optional": true, "dependencies": { - "abbrev": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "ansi-regex": { - "version": "2.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "aproba": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - }, - "are-we-there-yet": { - "version": "1.1.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "balanced-match": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "brace-expansion": { - "version": "1.1.11", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "chownr": { - "version": "1.1.4", - "bundled": true, - "dev": true, - "optional": true - }, - "code-point-at": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "optional": true - }, - "concat-map": { - "version": "0.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "console-control-strings": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "optional": true - }, - "core-util-is": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "debug": { - "version": "3.2.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ms": "^2.1.1" - } - }, - "deep-extend": { - "version": "0.6.0", - "bundled": true, - "dev": true, - "optional": true - }, - "delegates": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "detect-libc": { - "version": "1.0.3", - "bundled": true, - "dev": true, - "optional": true - }, - "fs-minipass": { - "version": "1.2.7", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.6.0" - } - }, - "fs.realpath": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "gauge": { - "version": "2.7.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - } - }, - "glob": { - "version": "7.1.6", - "bundled": true, - "dev": true, - "optional": 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" - } - }, - "has-unicode": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "iconv-lite": { - "version": "0.4.24", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "ignore-walk": { - "version": "3.0.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minimatch": "^3.0.4" - } - }, - "inflight": { - "version": "1.0.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "bundled": true, - "dev": true, - "optional": true - }, - "ini": { - "version": "1.3.5", - "bundled": true, - "dev": true, - "optional": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "minimatch": { - "version": "3.0.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "1.2.5", - "bundled": true, - "dev": true, - "optional": true - }, - "minipass": { - "version": "2.9.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } - }, - "minizlib": { - "version": "1.3.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.9.0" - } - }, - "mkdirp": { - "version": "0.5.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minimist": "^1.2.5" - } - }, - "ms": { - "version": "2.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "needle": { - "version": "2.3.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "debug": "^3.2.6", - "iconv-lite": "^0.4.4", - "sax": "^1.2.4" - } - }, - "node-pre-gyp": { - "version": "0.14.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "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.4.2" - } - }, - "nopt": { - "version": "4.0.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "abbrev": "1", - "osenv": "^0.1.4" - } - }, - "npm-bundled": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "npm-normalize-package-bin": "^1.0.1" - } - }, - "npm-normalize-package-bin": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "npm-packlist": { - "version": "1.4.8", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1", - "npm-normalize-package-bin": "^1.0.1" - } - }, - "npmlog": { - "version": "4.1.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "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, - "optional": true - }, - "object-assign": { - "version": "4.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "once": { - "version": "1.4.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "wrappy": "1" - } - }, - "os-homedir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "os-tmpdir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "osenv": { - "version": "0.1.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "process-nextick-args": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "rc": { - "version": "1.2.8", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - } - }, - "readable-stream": { - "version": "2.3.7", - "bundled": true, - "dev": true, - "optional": 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" - } - }, - "rimraf": { - "version": "2.7.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "glob": "^7.1.3" - } - }, - "safe-buffer": { - "version": "5.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "safer-buffer": { - "version": "2.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "sax": { - "version": "1.2.4", - "bundled": true, - "dev": true, - "optional": true - }, - "semver": { - "version": "5.7.1", - "bundled": true, - "dev": true, - "optional": true - }, - "set-blocking": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "signal-exit": { - "version": "3.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "string-width": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-json-comments": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "tar": { - "version": "4.4.13", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "chownr": "^1.1.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.8.6", - "minizlib": "^1.2.1", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.2", - "yallist": "^3.0.3" - } - }, - "util-deprecate": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "wide-align": { - "version": "1.1.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "string-width": "^1.0.2 || 2" - } - }, - "wrappy": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "yallist": { - "version": "3.1.1", - "bundled": true, - "dev": true, - "optional": true - } + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "node_modules/fsevents/node_modules/balanced-match": { + "version": "1.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true + }, + "node_modules/fsevents/node_modules/brace-expansion": { + "version": "1.1.11", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/fsevents/node_modules/chownr": { + "version": "1.1.4", + "dev": true, + "inBundle": true, + "license": "ISC", + "optional": true + }, + "node_modules/fsevents/node_modules/code-point-at": { + "version": "1.1.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fsevents/node_modules/concat-map": { + "version": "0.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true + }, + "node_modules/fsevents/node_modules/console-control-strings": { + "version": "1.1.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "optional": true + }, + "node_modules/fsevents/node_modules/core-util-is": { + "version": "1.0.2", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true + }, + "node_modules/fsevents/node_modules/debug": { + "version": "3.2.6", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/fsevents/node_modules/deep-extend": { + "version": "0.6.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/fsevents/node_modules/delegates": { + "version": "1.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true + }, + "node_modules/fsevents/node_modules/detect-libc": { + "version": "1.0.3", + "dev": true, + "inBundle": true, + "license": "Apache-2.0", + "optional": true, + "bin": { + "detect-libc": "bin/detect-libc.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/fsevents/node_modules/fs-minipass": { + "version": "1.2.7", + "dev": true, + "inBundle": true, + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^2.6.0" + } + }, + "node_modules/fsevents/node_modules/fs.realpath": { + "version": "1.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "optional": true + }, + "node_modules/fsevents/node_modules/gauge": { + "version": "2.7.4", + "dev": true, + "inBundle": true, + "license": "ISC", + "optional": true, + "dependencies": { + "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" + } + }, + "node_modules/fsevents/node_modules/glob": { + "version": "7.1.6", + "dev": true, + "inBundle": true, + "license": "ISC", + "optional": true, + "dependencies": { + "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" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/fsevents/node_modules/has-unicode": { + "version": "2.0.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "optional": true + }, + "node_modules/fsevents/node_modules/iconv-lite": { + "version": "0.4.24", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fsevents/node_modules/ignore-walk": { + "version": "3.0.3", + "dev": true, + "inBundle": true, + "license": "ISC", + "optional": true, + "dependencies": { + "minimatch": "^3.0.4" + } + }, + "node_modules/fsevents/node_modules/inflight": { + "version": "1.0.6", + "dev": true, + "inBundle": true, + "license": "ISC", + "optional": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/fsevents/node_modules/inherits": { + "version": "2.0.4", + "dev": true, + "inBundle": true, + "license": "ISC", + "optional": true + }, + "node_modules/fsevents/node_modules/ini": { + "version": "1.3.5", + "dev": true, + "inBundle": true, + "license": "ISC", + "optional": true, + "engines": { + "node": "*" + } + }, + "node_modules/fsevents/node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fsevents/node_modules/isarray": { + "version": "1.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true + }, + "node_modules/fsevents/node_modules/minimatch": { + "version": "3.0.4", + "dev": true, + "inBundle": true, + "license": "ISC", + "optional": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/fsevents/node_modules/minimist": { + "version": "1.2.5", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true + }, + "node_modules/fsevents/node_modules/minipass": { + "version": "2.9.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "optional": true, + "dependencies": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "node_modules/fsevents/node_modules/minizlib": { + "version": "1.3.3", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "minipass": "^2.9.0" + } + }, + "node_modules/fsevents/node_modules/mkdirp": { + "version": "0.5.3", + "deprecated": "Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/fsevents/node_modules/ms": { + "version": "2.1.2", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true + }, + "node_modules/fsevents/node_modules/needle": { + "version": "2.3.3", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "debug": "^3.2.6", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + }, + "bin": { + "needle": "bin/needle" + }, + "engines": { + "node": ">= 4.4.x" + } + }, + "node_modules/fsevents/node_modules/node-pre-gyp": { + "version": "0.14.0", + "dev": true, + "inBundle": true, + "license": "BSD-3-Clause", + "optional": true, + "dependencies": { + "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.4.2" + }, + "bin": { + "node-pre-gyp": "bin/node-pre-gyp" + } + }, + "node_modules/fsevents/node_modules/nopt": { + "version": "4.0.3", + "dev": true, + "inBundle": true, + "license": "ISC", + "optional": true, + "dependencies": { + "abbrev": "1", + "osenv": "^0.1.4" + }, + "bin": { + "nopt": "bin/nopt.js" + } + }, + "node_modules/fsevents/node_modules/npm-bundled": { + "version": "1.1.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "optional": true, + "dependencies": { + "npm-normalize-package-bin": "^1.0.1" + } + }, + "node_modules/fsevents/node_modules/npm-normalize-package-bin": { + "version": "1.0.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "optional": true + }, + "node_modules/fsevents/node_modules/npm-packlist": { + "version": "1.4.8", + "dev": true, + "inBundle": true, + "license": "ISC", + "optional": true, + "dependencies": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1", + "npm-normalize-package-bin": "^1.0.1" + } + }, + "node_modules/fsevents/node_modules/npmlog": { + "version": "4.1.2", + "dev": true, + "inBundle": true, + "license": "ISC", + "optional": true, + "dependencies": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "node_modules/fsevents/node_modules/number-is-nan": { + "version": "1.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fsevents/node_modules/object-assign": { + "version": "4.1.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fsevents/node_modules/once": { + "version": "1.4.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "optional": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/fsevents/node_modules/os-homedir": { + "version": "1.0.2", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fsevents/node_modules/os-tmpdir": { + "version": "1.0.2", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fsevents/node_modules/osenv": { + "version": "0.1.5", + "dev": true, + "inBundle": true, + "license": "ISC", + "optional": true, + "dependencies": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "node_modules/fsevents/node_modules/path-is-absolute": { + "version": "1.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fsevents/node_modules/process-nextick-args": { + "version": "2.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true + }, + "node_modules/fsevents/node_modules/rc": { + "version": "1.2.8", + "dev": true, + "inBundle": true, + "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", + "optional": true, + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/fsevents/node_modules/readable-stream": { + "version": "2.3.7", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "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" + } + }, + "node_modules/fsevents/node_modules/rimraf": { + "version": "2.7.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "optional": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/fsevents/node_modules/safe-buffer": { + "version": "5.1.2", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true + }, + "node_modules/fsevents/node_modules/safer-buffer": { + "version": "2.1.2", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true + }, + "node_modules/fsevents/node_modules/sax": { + "version": "1.2.4", + "dev": true, + "inBundle": true, + "license": "ISC", + "optional": true + }, + "node_modules/fsevents/node_modules/semver": { + "version": "5.7.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "optional": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/fsevents/node_modules/set-blocking": { + "version": "2.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "optional": true + }, + "node_modules/fsevents/node_modules/signal-exit": { + "version": "3.0.2", + "dev": true, + "inBundle": true, + "license": "ISC", + "optional": true + }, + "node_modules/fsevents/node_modules/string_decoder": { + "version": "1.1.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/fsevents/node_modules/string-width": { + "version": "1.0.2", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fsevents/node_modules/strip-ansi": { + "version": "3.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fsevents/node_modules/strip-json-comments": { + "version": "2.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fsevents/node_modules/tar": { + "version": "4.4.13", + "dev": true, + "inBundle": true, + "license": "ISC", + "optional": true, + "dependencies": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.8.6", + "minizlib": "^1.2.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.3" + }, + "engines": { + "node": ">=4.5" + } + }, + "node_modules/fsevents/node_modules/util-deprecate": { + "version": "1.0.2", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true + }, + "node_modules/fsevents/node_modules/wide-align": { + "version": "1.1.3", + "dev": true, + "inBundle": true, + "license": "ISC", + "optional": true, + "dependencies": { + "string-width": "^1.0.2 || 2" } }, - "function-bind": { + "node_modules/fsevents/node_modules/wrappy": { + "version": "1.0.2", + "dev": true, + "inBundle": true, + "license": "ISC", + "optional": true + }, + "node_modules/fsevents/node_modules/yallist": { + "version": "3.1.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "optional": true + }, + "node_modules/function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", "dev": true }, - "gensync": { + "node_modules/gensync": { "version": "1.0.0-beta.1", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.1.tgz", "integrity": "sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg==", - "dev": true + "dev": true, + "engines": { + "node": ">=6.9.0" + } }, - "get-caller-file": { + "node_modules/get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } }, - "get-port": { + "node_modules/get-port": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/get-port/-/get-port-3.2.0.tgz", "integrity": "sha1-3Xzn3hh8Bsi/NTeWrHHgmfCYDrw=", - "dev": true + "dev": true, + "engines": { + "node": ">=4" + } }, - "get-value": { + "node_modules/get-value": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "getpass": { + "node_modules/getpass": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", "dev": true, - "requires": { + "dependencies": { "assert-plus": "^1.0.0" } }, - "glob": { + "node_modules/glob": { "version": "7.1.6", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", "dev": true, - "requires": { + "dependencies": { "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" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "glob-parent": { + "node_modules/glob-parent": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", "dev": true, - "requires": { + "dependencies": { "is-glob": "^3.1.0", "path-dirname": "^1.0.0" - }, + } + }, + "node_modules/glob-parent/node_modules/is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, "dependencies": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } - } + "is-extglob": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "glob-to-regexp": { + "node_modules/glob-to-regexp": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz", "integrity": "sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs=", "dev": true }, - "globals": { + "node_modules/globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true + "dev": true, + "engines": { + "node": ">=4" + } }, - "graceful-fs": { + "node_modules/graceful-fs": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", "dev": true }, - "grapheme-breaker": { + "node_modules/grapheme-breaker": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/grapheme-breaker/-/grapheme-breaker-0.3.2.tgz", "integrity": "sha1-W55reMODJFLSuiuxy4MPlidkEKw=", "dev": true, - "requires": { + "dependencies": { "brfs": "^1.2.0", "unicode-trie": "^0.3.1" } }, - "har-schema": { + "node_modules/har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", - "dev": true + "dev": true, + "engines": { + "node": ">=4" + } }, - "har-validator": { + "node_modules/har-validator": { "version": "5.1.3", "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "deprecated": "this library is no longer supported", "dev": true, - "requires": { + "dependencies": { "ajv": "^6.5.5", "har-schema": "^2.0.0" + }, + "engines": { + "node": ">=6" } }, - "has": { + "node_modules/has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", "dev": true, - "requires": { + "dependencies": { "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" } }, - "has-ansi": { + "node_modules/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": { + "dependencies": { "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 - } + "engines": { + "node": ">=0.10.0" } }, - "has-flag": { + "node_modules/has-ansi/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true + "dev": true, + "engines": { + "node": ">=4" + } }, - "has-symbols": { + "node_modules/has-symbols": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", - "dev": true + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "has-value": { + "node_modules/has-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", "dev": true, - "requires": { + "dependencies": { "get-value": "^2.0.6", "has-values": "^1.0.0", "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "has-values": { + "node_modules/has-values": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", "dev": true, - "requires": { + "dependencies": { "is-number": "^3.0.0", "kind-of": "^4.0.0" }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-values/node_modules/kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, "dependencies": { - "kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" } }, - "hash-base": { + "node_modules/hash-base": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", "dev": true, - "requires": { + "dependencies": { "inherits": "^2.0.1", "safe-buffer": "^5.0.1" + }, + "engines": { + "node": ">=4" } }, - "hash.js": { + "node_modules/hash.js": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", "dev": true, - "requires": { + "dependencies": { "inherits": "^2.0.3", "minimalistic-assert": "^1.0.1" } }, - "hex-color-regex": { + "node_modules/hex-color-regex": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/hex-color-regex/-/hex-color-regex-1.1.0.tgz", "integrity": "sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ==", "dev": true }, - "hmac-drbg": { + "node_modules/hmac-drbg": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", "dev": true, - "requires": { + "dependencies": { "hash.js": "^1.0.3", "minimalistic-assert": "^1.0.0", "minimalistic-crypto-utils": "^1.0.1" } }, - "hsl-regex": { + "node_modules/hsl-regex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/hsl-regex/-/hsl-regex-1.0.0.tgz", "integrity": "sha1-1JMwx4ntgZ4nakwNJy3/owsY/m4=", "dev": true }, - "hsla-regex": { + "node_modules/hsla-regex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/hsla-regex/-/hsla-regex-1.0.0.tgz", "integrity": "sha1-wc56MWjIxmFAM6S194d/OyJfnDg=", "dev": true }, - "html-comment-regex": { + "node_modules/html-comment-regex": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/html-comment-regex/-/html-comment-regex-1.1.2.tgz", "integrity": "sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ==", "dev": true }, - "html-encoding-sniffer": { + "node_modules/html-encoding-sniffer": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz", "integrity": "sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw==", "dev": true, - "requires": { + "dependencies": { "whatwg-encoding": "^1.0.1" } }, - "html-tags": { + "node_modules/html-tags": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-1.2.0.tgz", "integrity": "sha1-x43mW1Zjqll5id0rerSSANfk25g=", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "htmlnano": { + "node_modules/htmlnano": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/htmlnano/-/htmlnano-0.2.5.tgz", "integrity": "sha512-X1iPSwXG/iF9bVs+/obt2n6F64uH0ETkA8zp7qFDmLW9/+A6ueHGeb/+qD67T21qUY22owZPMdawljN50ajkqA==", "dev": true, - "requires": { + "dependencies": { "cssnano": "^4.1.10", "normalize-html-whitespace": "^1.0.0", "posthtml": "^0.12.0", @@ -3912,209 +4750,247 @@ "svgo": "^1.3.2", "terser": "^4.3.9", "uncss": "^0.17.2" + } + }, + "node_modules/htmlnano/node_modules/posthtml": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/posthtml/-/posthtml-0.12.0.tgz", + "integrity": "sha512-aNUEP/SfKUXAt+ghG51LC5MmafChBZeslVe/SSdfKIgLGUVRE68mrMF4V8XbH07ZifM91tCSuxY3eHIFLlecQw==", + "dev": true, + "dependencies": { + "posthtml-parser": "^0.4.1", + "posthtml-render": "^1.1.5" }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/htmlnano/node_modules/terser": { + "version": "4.6.10", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.6.10.tgz", + "integrity": "sha512-qbF/3UOo11Hggsbsqm2hPa6+L4w7bkr+09FNseEe8xrcVD3APGLFqE+Oz1ZKAxjYnFsj80rLOfgAtJ0LNJjtTA==", + "dev": true, "dependencies": { - "posthtml": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/posthtml/-/posthtml-0.12.0.tgz", - "integrity": "sha512-aNUEP/SfKUXAt+ghG51LC5MmafChBZeslVe/SSdfKIgLGUVRE68mrMF4V8XbH07ZifM91tCSuxY3eHIFLlecQw==", - "dev": true, - "requires": { - "posthtml-parser": "^0.4.1", - "posthtml-render": "^1.1.5" - } - }, - "terser": { - "version": "4.6.10", - "resolved": "https://registry.npmjs.org/terser/-/terser-4.6.10.tgz", - "integrity": "sha512-qbF/3UOo11Hggsbsqm2hPa6+L4w7bkr+09FNseEe8xrcVD3APGLFqE+Oz1ZKAxjYnFsj80rLOfgAtJ0LNJjtTA==", - "dev": true, - "requires": { - "commander": "^2.20.0", - "source-map": "~0.6.1", - "source-map-support": "~0.5.12" - } - } + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=6.0.0" } }, - "htmlparser2": { + "node_modules/htmlparser2": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==", "dev": true, - "requires": { + "dependencies": { "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" - }, + } + }, + "node_modules/htmlparser2/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, "dependencies": { - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" } }, - "http-errors": { + "node_modules/http-errors": { "version": "1.7.3", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", "dev": true, - "requires": { + "dependencies": { "depd": "~1.1.2", "inherits": "2.0.4", "setprototypeof": "1.1.1", "statuses": ">= 1.5.0 < 2", "toidentifier": "1.0.0" + }, + "engines": { + "node": ">= 0.6" } }, - "http-signature": { + "node_modules/http-signature": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", "dev": true, - "requires": { + "dependencies": { "assert-plus": "^1.0.0", "jsprim": "^1.2.2", "sshpk": "^1.7.0" + }, + "engines": { + "node": ">=0.8", + "npm": ">=1.3.7" } }, - "https-browserify": { + "node_modules/https-browserify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", "dev": true }, - "iconv-lite": { + "node_modules/iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "dev": true, - "requires": { + "dependencies": { "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" } }, - "icss-replace-symbols": { + "node_modules/icss-replace-symbols": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz", "integrity": "sha1-Bupvg2ead0njhs/h/oEq5dsiPe0=", "dev": true }, - "ieee754": { + "node_modules/ieee754": { "version": "1.1.13", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==", "dev": true }, - "import-fresh": { + "node_modules/import-fresh": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=", "dev": true, - "requires": { + "dependencies": { "caller-path": "^2.0.0", "resolve-from": "^3.0.0" + }, + "engines": { + "node": ">=4" } }, - "indexes-of": { + "node_modules/indexes-of": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=", "dev": true }, - "inflight": { + "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "dev": true, - "requires": { + "dependencies": { "once": "^1.3.0", "wrappy": "1" } }, - "inherits": { + "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, - "invariant": { + "node_modules/invariant": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", "dev": true, - "requires": { + "dependencies": { "loose-envify": "^1.0.0" } }, - "is-absolute-url": { + "node_modules/is-absolute-url": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-2.1.0.tgz", "integrity": "sha1-UFMN+4T8yap9vnhS6Do3uTufKqY=", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "is-accessor-descriptor": { + "node_modules/is-accessor-descriptor": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "deprecated": "Please upgrade to v0.1.7", "dev": true, - "requires": { + "dependencies": { "kind-of": "^3.0.2" }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-accessor-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" } }, - "is-arrayish": { + "node_modules/is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", "dev": true }, - "is-binary-path": { + "node_modules/is-binary-path": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", "dev": true, - "requires": { + "dependencies": { "binary-extensions": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "is-buffer": { + "node_modules/is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", "dev": true }, - "is-callable": { + "node_modules/is-callable": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==", - "dev": true + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "is-color-stop": { + "node_modules/is-color-stop": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-color-stop/-/is-color-stop-1.1.0.tgz", "integrity": "sha1-z/9HGu5N1cnhWFmPvhKWe1za00U=", "dev": true, - "requires": { + "dependencies": { "css-color-names": "^0.0.4", "hex-color-regex": "^1.1.0", "hsl-regex": "^1.0.0", @@ -4123,245 +4999,320 @@ "rgba-regex": "^1.0.0" } }, - "is-data-descriptor": { + "node_modules/is-data-descriptor": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "deprecated": "Please upgrade to v0.1.5", "dev": true, - "requires": { + "dependencies": { "kind-of": "^3.0.2" }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-data-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" } }, - "is-date-object": { + "node_modules/is-date-object": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", - "dev": true + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "is-descriptor": { + "node_modules/is-descriptor": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", "dev": true, - "requires": { + "dependencies": { "is-accessor-descriptor": "^0.1.6", "is-data-descriptor": "^0.1.4", "kind-of": "^5.0.0" }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-descriptor/node_modules/kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true, + "engines": { + "node": ">=0.10.0" } }, - "is-directory": { + "node_modules/is-directory": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "is-extendable": { + "node_modules/is-extendable": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "is-extglob": { + "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "is-fullwidth-code-point": { + "node_modules/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 + "dev": true, + "engines": { + "node": ">=4" + } }, - "is-glob": { + "node_modules/is-glob": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", "dev": true, - "requires": { + "dependencies": { "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" } }, - "is-html": { + "node_modules/is-html": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-html/-/is-html-1.1.0.tgz", "integrity": "sha1-4E8cGNOUhRETlvmgJz6rUa8hhGQ=", "dev": true, - "requires": { + "dependencies": { "html-tags": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "is-number": { + "node_modules/is-number": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", "dev": true, - "requires": { + "dependencies": { "kind-of": "^3.0.2" }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" } }, - "is-obj": { + "node_modules/is-obj": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", - "dev": true + "dev": true, + "engines": { + "node": ">=8" + } }, - "is-plain-object": { + "node_modules/is-plain-object": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", "dev": true, - "requires": { + "dependencies": { "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" } }, - "is-regex": { + "node_modules/is-regex": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", "dev": true, - "requires": { + "dependencies": { "has": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "is-resolvable": { + "node_modules/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-svg": { + "node_modules/is-svg": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-svg/-/is-svg-3.0.0.tgz", "integrity": "sha512-gi4iHK53LR2ujhLVVj+37Ykh9GLqYHX6JOVXbLAucaG/Cqw9xwdFOjDM2qeifLs1sF1npXXFvDu0r5HNgCMrzQ==", "dev": true, - "requires": { + "dependencies": { "html-comment-regex": "^1.1.0" + }, + "engines": { + "node": ">=4" } }, - "is-symbol": { + "node_modules/is-symbol": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", "dev": true, - "requires": { + "dependencies": { "has-symbols": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "is-typedarray": { + "node_modules/is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", "dev": true }, - "is-url": { + "node_modules/is-url": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==", "dev": true }, - "is-windows": { + "node_modules/is-windows": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "is-wsl": { + "node_modules/is-wsl": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", - "dev": true + "dev": true, + "engines": { + "node": ">=4" + } }, - "isarray": { + "node_modules/isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, - "isexe": { + "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", "dev": true }, - "isobject": { + "node_modules/isobject": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "isstream": { + "node_modules/isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", "dev": true }, - "js-tokens": { + "node_modules/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 }, - "js-yaml": { + "node_modules/js-yaml": { "version": "3.13.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", "dev": true, - "requires": { + "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" }, - "dependencies": { - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true - } + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/js-yaml/node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" } }, - "jsbn": { + "node_modules/jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", "dev": true }, - "jsdom": { + "node_modules/jsdom": { "version": "14.1.0", "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-14.1.0.tgz", "integrity": "sha512-O901mfJSuTdwU2w3Sn+74T+RnDVP+FuV5fH8tcPWyqrseRAb0s5xOtPgCFiPOtLcyK7CLIJwPyD83ZqQWvA5ng==", "dev": true, - "requires": { + "dependencies": { "abab": "^2.0.0", "acorn": "^6.0.4", "acorn-globals": "^4.3.0", @@ -4389,253 +5340,319 @@ "ws": "^6.1.2", "xml-name-validator": "^3.0.0" }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jsdom/node_modules/acorn": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz", + "integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/jsdom/node_modules/escodegen": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.1.tgz", + "integrity": "sha512-Bmt7NcRySdIfNPfU2ZoXDrrXsG9ZjvDxcAlMfDUgRBjLOWTuIACXPBFJH7Z+cLb40JeQco5toikyc9t9P8E9SQ==", + "dev": true, + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=4.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/jsdom/node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/jsdom/node_modules/ws": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz", + "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==", + "dev": true, "dependencies": { - "acorn": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz", - "integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==", - "dev": true - }, - "escodegen": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.1.tgz", - "integrity": "sha512-Bmt7NcRySdIfNPfU2ZoXDrrXsG9ZjvDxcAlMfDUgRBjLOWTuIACXPBFJH7Z+cLb40JeQco5toikyc9t9P8E9SQ==", - "dev": true, - "requires": { - "esprima": "^4.0.1", - "estraverse": "^4.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1", - "source-map": "~0.6.1" - } - }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true - }, - "ws": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz", - "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==", - "dev": true, - "requires": { - "async-limiter": "~1.0.0" - } - } + "async-limiter": "~1.0.0" } }, - "jsesc": { + "node_modules/jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } }, - "json-parse-better-errors": { + "node_modules/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", "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", "dev": true }, - "json-schema": { + "node_modules/json-schema": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", "dev": true }, - "json-schema-traverse": { + "node_modules/json-schema-traverse": { "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-stringify-safe": { + "node_modules/json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", "dev": true }, - "json5": { + "node_modules/json5": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", "dev": true, - "requires": { + "dependencies": { "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" } }, - "jsprim": { + "node_modules/jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", "dev": true, - "requires": { + "engines": [ + "node >=0.6.0" + ], + "dependencies": { "assert-plus": "1.0.0", "extsprintf": "1.3.0", "json-schema": "0.2.3", "verror": "1.10.0" } }, - "kind-of": { + "node_modules/kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "leven": { + "node_modules/leven": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true + "dev": true, + "engines": { + "node": ">=6" + } }, - "levenary": { + "node_modules/levenary": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/levenary/-/levenary-1.1.1.tgz", "integrity": "sha512-mkAdOIt79FD6irqjYSs4rdbnlT5vRonMEvBVPVb3XmevfS8kgRXwfes0dhPdEtzTWD/1eNE/Bm/G1iRt6DcnQQ==", "dev": true, - "requires": { + "dependencies": { "leven": "^3.1.0" + }, + "engines": { + "node": ">= 6" } }, - "levn": { + "node_modules/levn": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", "dev": true, - "requires": { + "dependencies": { "prelude-ls": "~1.1.2", "type-check": "~0.3.2" + }, + "engines": { + "node": ">= 0.8.0" } }, - "locate-path": { + "node_modules/locate-path": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", "dev": true, - "requires": { + "dependencies": { "p-locate": "^2.0.0", "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=4" } }, - "lodash": { + "node_modules/lodash": { "version": "4.17.15", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", "dev": true }, - "lodash.clone": { + "node_modules/lodash.clone": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-4.5.0.tgz", "integrity": "sha1-GVhwRQ9aExkkeN9Lw9I9LeoZB7Y=", "dev": true }, - "lodash.memoize": { + "node_modules/lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", "dev": true }, - "lodash.sortby": { + "node_modules/lodash.sortby": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=", "dev": true }, - "lodash.uniq": { + "node_modules/lodash.uniq": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=", "dev": true }, - "log-symbols": { + "node_modules/log-symbols": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", "dev": true, - "requires": { + "dependencies": { "chalk": "^2.0.1" + }, + "engines": { + "node": ">=4" } }, - "loose-envify": { + "node_modules/loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", "dev": true, - "requires": { + "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" } }, - "magic-string": { + "node_modules/magic-string": { "version": "0.22.5", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.22.5.tgz", "integrity": "sha512-oreip9rJZkzvA8Qzk9HFs8fZGF/u7H/gtrE8EN6RjKJ9kh2HlC+yQ2QezifqTZfGyiuAV0dRv5a+y/8gBb1m9w==", "dev": true, - "requires": { + "dependencies": { "vlq": "^0.2.2" } }, - "map-cache": { + "node_modules/map-cache": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "map-visit": { + "node_modules/map-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", "dev": true, - "requires": { + "dependencies": { "object-visit": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "md5.js": { + "node_modules/md5.js": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", "dev": true, - "requires": { + "dependencies": { "hash-base": "^3.0.0", "inherits": "^2.0.1", "safe-buffer": "^5.1.2" } }, - "mdn-data": { + "node_modules/mdn-data": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz", "integrity": "sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA==", "dev": true }, - "merge-source-map": { + "node_modules/merge-source-map": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.0.4.tgz", "integrity": "sha1-pd5GU42uhNQRTMXqArR3KmNGcB8=", "dev": true, - "requires": { - "source-map": "^0.5.6" - }, "dependencies": { - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } + "source-map": "^0.5.6" + } + }, + "node_modules/merge-source-map/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true, + "engines": { + "node": ">=0.10.0" } }, - "merge2": { + "node_modules/merge2": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.3.0.tgz", "integrity": "sha512-2j4DAdlBOkiSZIsaXk4mTE3sRS02yBHAtfy127xRV3bQUFqXkjHCHLW6Scv7DwNRbIWNHH8zpnz9zMaKXIdvYw==", - "dev": true + "dev": true, + "engines": { + "node": ">= 6" + } }, - "micromatch": { + "node_modules/micromatch": { "version": "3.1.10", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", "dev": true, - "requires": { + "dependencies": { "arr-diff": "^4.0.0", "array-unique": "^0.3.2", "braces": "^2.3.1", @@ -4649,121 +5666,152 @@ "regex-not": "^1.0.0", "snapdragon": "^0.8.1", "to-regex": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" } }, - "miller-rabin": { + "node_modules/miller-rabin": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", "dev": true, - "requires": { + "dependencies": { "bn.js": "^4.0.0", "brorand": "^1.0.1" + }, + "bin": { + "miller-rabin": "bin/miller-rabin" } }, - "mime": { + "node_modules/mime": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } }, - "mime-db": { + "node_modules/mime-db": { "version": "1.43.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz", "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==", - "dev": true + "dev": true, + "engines": { + "node": ">= 0.6" + } }, - "mime-types": { + "node_modules/mime-types": { "version": "2.1.26", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz", "integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==", "dev": true, - "requires": { + "dependencies": { "mime-db": "1.43.0" + }, + "engines": { + "node": ">= 0.6" } }, - "mimic-fn": { + "node_modules/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==", - "dev": true + "dev": true, + "engines": { + "node": ">=4" + } }, - "minimalistic-assert": { + "node_modules/minimalistic-assert": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", "dev": true }, - "minimalistic-crypto-utils": { + "node_modules/minimalistic-crypto-utils": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", "dev": true }, - "minimatch": { + "node_modules/minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, - "requires": { + "dependencies": { "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" } }, - "minimist": { + "node_modules/minimist": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", "dev": true }, - "mixin-deep": { + "node_modules/mixin-deep": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", "dev": true, - "requires": { + "dependencies": { "for-in": "^1.0.2", "is-extendable": "^1.0.1" }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/mixin-deep/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - } + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" } }, - "mkdirp": { + "node_modules/mkdirp": { "version": "0.5.5", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", "dev": true, - "requires": { + "dependencies": { "minimist": "^1.2.5" + }, + "bin": { + "mkdirp": "bin/cmd.js" } }, - "ms": { + "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, - "nan": { + "node_modules/nan": { "version": "2.14.0", "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", "dev": true, "optional": true }, - "nanomatch": { + "node_modules/nanomatch": { "version": "1.2.13", "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", "dev": true, - "requires": { + "dependencies": { "arr-diff": "^4.0.0", "array-unique": "^0.3.2", "define-property": "^2.0.2", @@ -4775,32 +5823,38 @@ "regex-not": "^1.0.0", "snapdragon": "^0.8.1", "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" } }, - "nice-try": { + "node_modules/nice-try": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", "dev": true }, - "node-addon-api": { + "node_modules/node-addon-api": { "version": "1.7.1", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-1.7.1.tgz", "integrity": "sha512-2+DuKodWvwRTrCfKOeR24KIc5unKjOh8mz17NCzVnHWfjAdDqbfbjqh7gUT+BkXBRQM52+xCHciKWonJ3CbJMQ==", "dev": true }, - "node-forge": { + "node_modules/node-forge": { "version": "0.7.6", "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.6.tgz", "integrity": "sha512-sol30LUpz1jQFBjOKwbjxijiE3b6pjd74YwfD0fJOKPjF+fONKb2Yg8rYgS6+bK6VDl+/wfr4IYpC7jDzLUIfw==", - "dev": true + "dev": true, + "engines": { + "node": "*" + } }, - "node-libs-browser": { + "node_modules/node-libs-browser": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", "integrity": "sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==", "dev": true, - "requires": { + "dependencies": { "assert": "^1.1.1", "browserify-zlib": "^0.2.0", "buffer": "^4.3.0", @@ -4824,268 +5878,338 @@ "url": "^0.11.0", "util": "^0.11.0", "vm-browserify": "^1.0.1" - }, - "dependencies": { - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", - "dev": true - } } }, - "node-releases": { + "node_modules/node-libs-browser/node_modules/punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + }, + "node_modules/node-releases": { "version": "1.1.53", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.53.tgz", "integrity": "sha512-wp8zyQVwef2hpZ/dJH7SfSrIPD6YoJz6BDQDpGEkcA0s3LpAQoxBIYmfIq6QAhC1DhwsyCgTaTTcONwX8qzCuQ==", "dev": true }, - "normalize-html-whitespace": { + "node_modules/normalize-html-whitespace": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/normalize-html-whitespace/-/normalize-html-whitespace-1.0.0.tgz", "integrity": "sha512-9ui7CGtOOlehQu0t/OhhlmDyc71mKVlv+4vF+me4iZLPrNtRL2xoquEdfZxasC/bdQi/Hr3iTrpyRKIG+ocabA==", - "dev": true + "dev": true, + "engines": { + "node": ">= 8" + } }, - "normalize-path": { + "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "normalize-url": { + "node_modules/normalize-url": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-3.3.0.tgz", "integrity": "sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg==", - "dev": true + "dev": true, + "engines": { + "node": ">=6" + } }, - "nth-check": { + "node_modules/nth-check": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", "dev": true, - "requires": { + "dependencies": { "boolbase": "~1.0.0" } }, - "nwsapi": { + "node_modules/nwsapi": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.0.tgz", "integrity": "sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==", "dev": true }, - "oauth-sign": { + "node_modules/oauth-sign": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", - "dev": true + "dev": true, + "engines": { + "node": "*" + } }, - "object-assign": { + "node_modules/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 + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "object-copy": { + "node_modules/object-copy": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", "dev": true, - "requires": { + "dependencies": { "copy-descriptor": "^0.1.0", "define-property": "^0.2.5", "kind-of": "^3.0.3" }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "object-inspect": { + "node_modules/object-copy/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.4.1.tgz", "integrity": "sha512-wqdhLpfCUbEsoEwl3FXwGyv8ief1k/1aUdIPCqVnupM6e8l63BEJdiF/0swtn04/8p05tG/T0FrpTlfwvljOdw==", "dev": true }, - "object-keys": { + "node_modules/object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true + "dev": true, + "engines": { + "node": ">= 0.4" + } }, - "object-visit": { + "node_modules/object-visit": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", "dev": true, - "requires": { + "dependencies": { "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "object.assign": { + "node_modules/object.assign": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", "dev": true, - "requires": { + "dependencies": { "define-properties": "^1.1.2", "function-bind": "^1.1.1", "has-symbols": "^1.0.0", "object-keys": "^1.0.11" + }, + "engines": { + "node": ">= 0.4" } }, - "object.getownpropertydescriptors": { + "node_modules/object.getownpropertydescriptors": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz", "integrity": "sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg==", "dev": true, - "requires": { + "dependencies": { "define-properties": "^1.1.3", "es-abstract": "^1.17.0-next.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "object.pick": { + "node_modules/object.pick": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", "dev": true, - "requires": { + "dependencies": { "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" } }, - "object.values": { + "node_modules/object.values": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.1.tgz", "integrity": "sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA==", "dev": true, - "requires": { + "dependencies": { "define-properties": "^1.1.3", "es-abstract": "^1.17.0-next.1", "function-bind": "^1.1.1", "has": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "on-finished": { + "node_modules/on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", "dev": true, - "requires": { + "dependencies": { "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" } }, - "once": { + "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, - "requires": { + "dependencies": { "wrappy": "1" } }, - "onetime": { + "node_modules/onetime": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", "dev": true, - "requires": { + "dependencies": { "mimic-fn": "^1.0.0" + }, + "engines": { + "node": ">=4" } }, - "opn": { + "node_modules/opn": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/opn/-/opn-5.5.0.tgz", "integrity": "sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA==", "dev": true, - "requires": { + "dependencies": { "is-wsl": "^1.1.0" + }, + "engines": { + "node": ">=4" } }, - "optionator": { + "node_modules/optionator": { "version": "0.8.3", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", "dev": true, - "requires": { + "dependencies": { "deep-is": "~0.1.3", "fast-levenshtein": "~2.0.6", "levn": "~0.3.0", "prelude-ls": "~1.1.2", "type-check": "~0.3.2", "word-wrap": "~1.2.3" + }, + "engines": { + "node": ">= 0.8.0" } }, - "ora": { + "node_modules/ora": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/ora/-/ora-2.1.0.tgz", "integrity": "sha512-hNNlAd3gfv/iPmsNxYoAPLvxg7HuPozww7fFonMZvL84tP6Ox5igfk5j/+a9rtJJwqMgKK+JgWsAQik5o0HTLA==", "dev": true, - "requires": { + "dependencies": { "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" + }, + "engines": { + "node": ">=4" } }, - "os-browserify": { + "node_modules/os-browserify": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", "dev": true }, - "p-limit": { + "node_modules/p-limit": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", "dev": true, - "requires": { + "dependencies": { "p-try": "^1.0.0" + }, + "engines": { + "node": ">=4" } }, - "p-locate": { + "node_modules/p-locate": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", "dev": true, - "requires": { + "dependencies": { "p-limit": "^1.1.0" + }, + "engines": { + "node": ">=4" } }, - "p-try": { + "node_modules/p-try": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true + "dev": true, + "engines": { + "node": ">=4" + } }, - "pako": { + "node_modules/pako": { "version": "0.2.9", "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=", "dev": true }, - "parcel-bundler": { + "node_modules/parcel-bundler": { "version": "1.12.4", "resolved": "https://registry.npmjs.org/parcel-bundler/-/parcel-bundler-1.12.4.tgz", "integrity": "sha512-G+iZGGiPEXcRzw0fiRxWYCKxdt/F7l9a0xkiU4XbcVRJCSlBnioWEwJMutOCCpoQmaQtjB4RBHDGIHN85AIhLQ==", + "deprecated": "Parcel v1 is no longer maintained. Please migrate to v2, which is published under the 'parcel' package. See https://v2.parceljs.org/getting-started/migration for details.", "dev": true, - "requires": { + "hasInstallScript": true, + "dependencies": { "@babel/code-frame": "^7.0.0", "@babel/core": "^7.4.4", "@babel/generator": "^7.4.4", @@ -5145,14 +6269,20 @@ "terser": "^3.7.3", "v8-compile-cache": "^2.0.0", "ws": "^5.1.1" + }, + "bin": { + "parcel": "bin/cli.js" + }, + "engines": { + "node": ">= 6.0.0" } }, - "parse-asn1": { + "node_modules/parse-asn1": { "version": "5.1.5", "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.5.tgz", "integrity": "sha512-jkMYn1dcJqF6d5CpU689bq7w/b5ALS9ROVSpQDPrZsqqesUJii9qutvoT5ltGedNXMO2e16YUWIghG9KxaViTQ==", "dev": true, - "requires": { + "dependencies": { "asn1.js": "^4.0.0", "browserify-aes": "^1.0.0", "create-hash": "^1.1.0", @@ -5161,234 +6291,276 @@ "safe-buffer": "^5.1.1" } }, - "parse-json": { + "node_modules/parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", "dev": true, - "requires": { + "dependencies": { "error-ex": "^1.3.1", "json-parse-better-errors": "^1.0.1" + }, + "engines": { + "node": ">=4" } }, - "parse5": { + "node_modules/parse5": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.0.tgz", "integrity": "sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ==", "dev": true }, - "parseurl": { + "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "dev": true + "dev": true, + "engines": { + "node": ">= 0.8" + } }, - "pascalcase": { + "node_modules/pascalcase": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "path-browserify": { + "node_modules/path-browserify": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==", "dev": true }, - "path-dirname": { + "node_modules/path-dirname": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", "dev": true }, - "path-exists": { + "node_modules/path-exists": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true + "dev": true, + "engines": { + "node": ">=4" + } }, - "path-is-absolute": { + "node_modules/path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "path-key": { + "node_modules/path-key": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", - "dev": true + "dev": true, + "engines": { + "node": ">=4" + } }, - "path-parse": { + "node_modules/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 }, - "pbkdf2": { + "node_modules/pbkdf2": { "version": "3.0.17", "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz", "integrity": "sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA==", "dev": true, - "requires": { + "dependencies": { "create-hash": "^1.1.2", "create-hmac": "^1.1.4", "ripemd160": "^2.0.1", "safe-buffer": "^5.0.1", "sha.js": "^2.4.8" + }, + "engines": { + "node": ">=0.12" } }, - "performance-now": { + "node_modules/performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", "dev": true }, - "physical-cpu-count": { + "node_modules/physical-cpu-count": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/physical-cpu-count/-/physical-cpu-count-2.0.0.tgz", "integrity": "sha1-GN4vl+S/epVRrXURlCtUlverpmA=", "dev": true }, - "pkg-up": { + "node_modules/pkg-up": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-2.0.0.tgz", "integrity": "sha1-yBmscoBZpGHKscOImivjxJoATX8=", "dev": true, - "requires": { + "dependencies": { "find-up": "^2.1.0" + }, + "engines": { + "node": ">=4" } }, - "pn": { + "node_modules/pn": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/pn/-/pn-1.1.0.tgz", "integrity": "sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==", "dev": true }, - "posix-character-classes": { + "node_modules/posix-character-classes": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "postcss": { + "node_modules/postcss": { "version": "7.0.27", "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", "dev": true, - "requires": { + "dependencies": { "chalk": "^2.4.2", "source-map": "^0.6.1", "supports-color": "^6.1.0" }, - "dependencies": { - "supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" } }, - "postcss-calc": { + "node_modules/postcss-calc": { "version": "7.0.2", "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-7.0.2.tgz", "integrity": "sha512-rofZFHUg6ZIrvRwPeFktv06GdbDYLcGqh9EwiMutZg+a0oePCCw1zHOEiji6LCpyRcjTREtPASuUqeAvYlEVvQ==", "dev": true, - "requires": { + "dependencies": { "postcss": "^7.0.27", "postcss-selector-parser": "^6.0.2", "postcss-value-parser": "^4.0.2" - }, - "dependencies": { - "postcss-value-parser": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.0.3.tgz", - "integrity": "sha512-N7h4pG+Nnu5BEIzyeaaIYWs0LI5XC40OrRh5L60z0QjFsqGWcHcbkBvpe1WYpcIS9yQ8sOi/vIPt1ejQCrMVrg==", - "dev": true - } } }, - "postcss-colormin": { + "node_modules/postcss-calc/node_modules/postcss-value-parser": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.0.3.tgz", + "integrity": "sha512-N7h4pG+Nnu5BEIzyeaaIYWs0LI5XC40OrRh5L60z0QjFsqGWcHcbkBvpe1WYpcIS9yQ8sOi/vIPt1ejQCrMVrg==", + "dev": true + }, + "node_modules/postcss-colormin": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-4.0.3.tgz", "integrity": "sha512-WyQFAdDZpExQh32j0U0feWisZ0dmOtPl44qYmJKkq9xFWY3p+4qnRzCHeNrkeRhwPHz9bQ3mo0/yVkaply0MNw==", "dev": true, - "requires": { + "dependencies": { "browserslist": "^4.0.0", "color": "^3.0.0", "has": "^1.0.0", "postcss": "^7.0.0", "postcss-value-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" } }, - "postcss-convert-values": { + "node_modules/postcss-convert-values": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-4.0.1.tgz", "integrity": "sha512-Kisdo1y77KUC0Jmn0OXU/COOJbzM8cImvw1ZFsBgBgMgb1iL23Zs/LXRe3r+EZqM3vGYKdQ2YJVQ5VkJI+zEJQ==", "dev": true, - "requires": { + "dependencies": { "postcss": "^7.0.0", "postcss-value-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" } }, - "postcss-discard-comments": { + "node_modules/postcss-discard-comments": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-4.0.2.tgz", "integrity": "sha512-RJutN259iuRf3IW7GZyLM5Sw4GLTOH8FmsXBnv8Ab/Tc2k4SR4qbV4DNbyyY4+Sjo362SyDmW2DQ7lBSChrpkg==", "dev": true, - "requires": { + "dependencies": { "postcss": "^7.0.0" + }, + "engines": { + "node": ">=6.9.0" } }, - "postcss-discard-duplicates": { + "node_modules/postcss-discard-duplicates": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-4.0.2.tgz", "integrity": "sha512-ZNQfR1gPNAiXZhgENFfEglF93pciw0WxMkJeVmw8eF+JZBbMD7jp6C67GqJAXVZP2BWbOztKfbsdmMp/k8c6oQ==", "dev": true, - "requires": { + "dependencies": { "postcss": "^7.0.0" + }, + "engines": { + "node": ">=6.9.0" } }, - "postcss-discard-empty": { + "node_modules/postcss-discard-empty": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-4.0.1.tgz", "integrity": "sha512-B9miTzbznhDjTfjvipfHoqbWKwd0Mj+/fL5s1QOz06wufguil+Xheo4XpOnc4NqKYBCNqqEzgPv2aPBIJLox0w==", "dev": true, - "requires": { + "dependencies": { "postcss": "^7.0.0" + }, + "engines": { + "node": ">=6.9.0" } }, - "postcss-discard-overridden": { + "node_modules/postcss-discard-overridden": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-4.0.1.tgz", "integrity": "sha512-IYY2bEDD7g1XM1IDEsUT4//iEYCxAmP5oDSFMVU/JVvT7gh+l4fmjciLqGgwjdWpQIdb0Che2VX00QObS5+cTg==", "dev": true, - "requires": { + "dependencies": { "postcss": "^7.0.0" + }, + "engines": { + "node": ">=6.9.0" } }, - "postcss-merge-longhand": { + "node_modules/postcss-merge-longhand": { "version": "4.0.11", "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-4.0.11.tgz", "integrity": "sha512-alx/zmoeXvJjp7L4mxEMjh8lxVlDFX1gqWHzaaQewwMZiVhLo42TEClKaeHbRf6J7j82ZOdTJ808RtN0ZOZwvw==", "dev": true, - "requires": { + "dependencies": { "css-color-names": "0.0.4", "postcss": "^7.0.0", "postcss-value-parser": "^3.0.0", "stylehacks": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" } }, - "postcss-merge-rules": { + "node_modules/postcss-merge-rules": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-4.0.3.tgz", "integrity": "sha512-U7e3r1SbvYzO0Jr3UT/zKBVgYYyhAz0aitvGIYOYK5CPmkNih+WDSsS5tvPrJ8YMQYlEMvsZIiqmn7HdFUaeEQ==", "dev": true, - "requires": { + "dependencies": { "browserslist": "^4.0.0", "caniuse-api": "^3.0.0", "cssnano-util-same-parent": "^4.0.0", @@ -5396,407 +6568,500 @@ "postcss-selector-parser": "^3.0.0", "vendors": "^1.0.0" }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-merge-rules/node_modules/postcss-selector-parser": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz", + "integrity": "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA==", + "dev": true, "dependencies": { - "postcss-selector-parser": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz", - "integrity": "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA==", - "dev": true, - "requires": { - "dot-prop": "^5.2.0", - "indexes-of": "^1.0.1", - "uniq": "^1.0.1" - } - } + "dot-prop": "^5.2.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + }, + "engines": { + "node": ">=8" } }, - "postcss-minify-font-values": { + "node_modules/postcss-minify-font-values": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-4.0.2.tgz", "integrity": "sha512-j85oO6OnRU9zPf04+PZv1LYIYOprWm6IA6zkXkrJXyRveDEuQggG6tvoy8ir8ZwjLxLuGfNkCZEQG7zan+Hbtg==", "dev": true, - "requires": { + "dependencies": { "postcss": "^7.0.0", "postcss-value-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" } }, - "postcss-minify-gradients": { + "node_modules/postcss-minify-gradients": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-4.0.2.tgz", "integrity": "sha512-qKPfwlONdcf/AndP1U8SJ/uzIJtowHlMaSioKzebAXSG4iJthlWC9iSWznQcX4f66gIWX44RSA841HTHj3wK+Q==", "dev": true, - "requires": { + "dependencies": { "cssnano-util-get-arguments": "^4.0.0", "is-color-stop": "^1.0.0", "postcss": "^7.0.0", "postcss-value-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" } }, - "postcss-minify-params": { + "node_modules/postcss-minify-params": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-4.0.2.tgz", "integrity": "sha512-G7eWyzEx0xL4/wiBBJxJOz48zAKV2WG3iZOqVhPet/9geefm/Px5uo1fzlHu+DOjT+m0Mmiz3jkQzVHe6wxAWg==", "dev": true, - "requires": { + "dependencies": { "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" + }, + "engines": { + "node": ">=6.9.0" } }, - "postcss-minify-selectors": { + "node_modules/postcss-minify-selectors": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-4.0.2.tgz", "integrity": "sha512-D5S1iViljXBj9kflQo4YutWnJmwm8VvIsU1GeXJGiG9j8CIg9zs4voPMdQDUmIxetUOh60VilsNzCiAFTOqu3g==", "dev": true, - "requires": { + "dependencies": { "alphanum-sort": "^1.0.0", "has": "^1.0.0", "postcss": "^7.0.0", "postcss-selector-parser": "^3.0.0" }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-minify-selectors/node_modules/postcss-selector-parser": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz", + "integrity": "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA==", + "dev": true, "dependencies": { - "postcss-selector-parser": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz", - "integrity": "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA==", - "dev": true, - "requires": { - "dot-prop": "^5.2.0", - "indexes-of": "^1.0.1", - "uniq": "^1.0.1" - } - } + "dot-prop": "^5.2.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + }, + "engines": { + "node": ">=8" } }, - "postcss-modules-extract-imports": { + "node_modules/postcss-modules-extract-imports": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.1.0.tgz", "integrity": "sha1-thTJcgvmgW6u41+zpfqh26agXds=", "dev": true, - "requires": { + "dependencies": { "postcss": "^6.0.1" - }, + } + }, + "node_modules/postcss-modules-extract-imports/node_modules/postcss": { + "version": "6.0.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", + "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", + "dev": true, "dependencies": { - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - } + "chalk": "^2.4.1", + "source-map": "^0.6.1", + "supports-color": "^5.4.0" + }, + "engines": { + "node": ">=4.0.0" } }, - "postcss-modules-local-by-default": { + "node_modules/postcss-modules-local-by-default": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-1.2.0.tgz", "integrity": "sha1-99gMOYxaOT+nlkRmvRlQCn1hwGk=", "dev": true, - "requires": { + "dependencies": { "css-selector-tokenizer": "^0.7.0", "postcss": "^6.0.1" - }, + } + }, + "node_modules/postcss-modules-local-by-default/node_modules/postcss": { + "version": "6.0.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", + "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", + "dev": true, "dependencies": { - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - } + "chalk": "^2.4.1", + "source-map": "^0.6.1", + "supports-color": "^5.4.0" + }, + "engines": { + "node": ">=4.0.0" } }, - "postcss-modules-scope": { + "node_modules/postcss-modules-scope": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-1.1.0.tgz", "integrity": "sha1-1upkmUx5+XtipytCb75gVqGUu5A=", "dev": true, - "requires": { + "dependencies": { "css-selector-tokenizer": "^0.7.0", "postcss": "^6.0.1" - }, + } + }, + "node_modules/postcss-modules-scope/node_modules/postcss": { + "version": "6.0.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", + "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", + "dev": true, "dependencies": { - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - } + "chalk": "^2.4.1", + "source-map": "^0.6.1", + "supports-color": "^5.4.0" + }, + "engines": { + "node": ">=4.0.0" } }, - "postcss-modules-values": { + "node_modules/postcss-modules-values": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-1.3.0.tgz", "integrity": "sha1-7P+p1+GSUYOJ9CrQ6D9yrsRW6iA=", "dev": true, - "requires": { + "dependencies": { "icss-replace-symbols": "^1.1.0", "postcss": "^6.0.1" - }, + } + }, + "node_modules/postcss-modules-values/node_modules/postcss": { + "version": "6.0.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", + "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", + "dev": true, "dependencies": { - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - } + "chalk": "^2.4.1", + "source-map": "^0.6.1", + "supports-color": "^5.4.0" + }, + "engines": { + "node": ">=4.0.0" } }, - "postcss-normalize-charset": { + "node_modules/postcss-normalize-charset": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-4.0.1.tgz", "integrity": "sha512-gMXCrrlWh6G27U0hF3vNvR3w8I1s2wOBILvA87iNXaPvSNo5uZAMYsZG7XjCUf1eVxuPfyL4TJ7++SGZLc9A3g==", "dev": true, - "requires": { + "dependencies": { "postcss": "^7.0.0" + }, + "engines": { + "node": ">=6.9.0" } }, - "postcss-normalize-display-values": { + "node_modules/postcss-normalize-display-values": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-4.0.2.tgz", "integrity": "sha512-3F2jcsaMW7+VtRMAqf/3m4cPFhPD3EFRgNs18u+k3lTJJlVe7d0YPO+bnwqo2xg8YiRpDXJI2u8A0wqJxMsQuQ==", "dev": true, - "requires": { + "dependencies": { "cssnano-util-get-match": "^4.0.0", "postcss": "^7.0.0", "postcss-value-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" } }, - "postcss-normalize-positions": { + "node_modules/postcss-normalize-positions": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-4.0.2.tgz", "integrity": "sha512-Dlf3/9AxpxE+NF1fJxYDeggi5WwV35MXGFnnoccP/9qDtFrTArZ0D0R+iKcg5WsUd8nUYMIl8yXDCtcrT8JrdA==", "dev": true, - "requires": { + "dependencies": { "cssnano-util-get-arguments": "^4.0.0", "has": "^1.0.0", "postcss": "^7.0.0", "postcss-value-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" } }, - "postcss-normalize-repeat-style": { + "node_modules/postcss-normalize-repeat-style": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-4.0.2.tgz", "integrity": "sha512-qvigdYYMpSuoFs3Is/f5nHdRLJN/ITA7huIoCyqqENJe9PvPmLhNLMu7QTjPdtnVf6OcYYO5SHonx4+fbJE1+Q==", "dev": true, - "requires": { + "dependencies": { "cssnano-util-get-arguments": "^4.0.0", "cssnano-util-get-match": "^4.0.0", "postcss": "^7.0.0", "postcss-value-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" } }, - "postcss-normalize-string": { + "node_modules/postcss-normalize-string": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-4.0.2.tgz", "integrity": "sha512-RrERod97Dnwqq49WNz8qo66ps0swYZDSb6rM57kN2J+aoyEAJfZ6bMx0sx/F9TIEX0xthPGCmeyiam/jXif0eA==", "dev": true, - "requires": { + "dependencies": { "has": "^1.0.0", "postcss": "^7.0.0", "postcss-value-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" } }, - "postcss-normalize-timing-functions": { + "node_modules/postcss-normalize-timing-functions": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-4.0.2.tgz", "integrity": "sha512-acwJY95edP762e++00Ehq9L4sZCEcOPyaHwoaFOhIwWCDfik6YvqsYNxckee65JHLKzuNSSmAdxwD2Cud1Z54A==", "dev": true, - "requires": { + "dependencies": { "cssnano-util-get-match": "^4.0.0", "postcss": "^7.0.0", "postcss-value-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" } }, - "postcss-normalize-unicode": { + "node_modules/postcss-normalize-unicode": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-4.0.1.tgz", "integrity": "sha512-od18Uq2wCYn+vZ/qCOeutvHjB5jm57ToxRaMeNuf0nWVHaP9Hua56QyMF6fs/4FSUnVIw0CBPsU0K4LnBPwYwg==", "dev": true, - "requires": { + "dependencies": { "browserslist": "^4.0.0", "postcss": "^7.0.0", "postcss-value-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" } }, - "postcss-normalize-url": { + "node_modules/postcss-normalize-url": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-4.0.1.tgz", "integrity": "sha512-p5oVaF4+IHwu7VpMan/SSpmpYxcJMtkGppYf0VbdH5B6hN8YNmVyJLuY9FmLQTzY3fag5ESUUHDqM+heid0UVA==", "dev": true, - "requires": { + "dependencies": { "is-absolute-url": "^2.0.0", "normalize-url": "^3.0.0", "postcss": "^7.0.0", "postcss-value-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" } }, - "postcss-normalize-whitespace": { + "node_modules/postcss-normalize-whitespace": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-4.0.2.tgz", "integrity": "sha512-tO8QIgrsI3p95r8fyqKV+ufKlSHh9hMJqACqbv2XknufqEDhDvbguXGBBqxw9nsQoXWf0qOqppziKJKHMD4GtA==", "dev": true, - "requires": { + "dependencies": { "postcss": "^7.0.0", "postcss-value-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" } }, - "postcss-ordered-values": { + "node_modules/postcss-ordered-values": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-4.1.2.tgz", "integrity": "sha512-2fCObh5UanxvSxeXrtLtlwVThBvHn6MQcu4ksNT2tsaV2Fg76R2CV98W7wNSlX+5/pFwEyaDwKLLoEV7uRybAw==", "dev": true, - "requires": { + "dependencies": { "cssnano-util-get-arguments": "^4.0.0", "postcss": "^7.0.0", "postcss-value-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" } }, - "postcss-reduce-initial": { + "node_modules/postcss-reduce-initial": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-4.0.3.tgz", "integrity": "sha512-gKWmR5aUulSjbzOfD9AlJiHCGH6AEVLaM0AV+aSioxUDd16qXP1PCh8d1/BGVvpdWn8k/HiK7n6TjeoXN1F7DA==", "dev": true, - "requires": { + "dependencies": { "browserslist": "^4.0.0", "caniuse-api": "^3.0.0", "has": "^1.0.0", "postcss": "^7.0.0" + }, + "engines": { + "node": ">=6.9.0" } }, - "postcss-reduce-transforms": { + "node_modules/postcss-reduce-transforms": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-4.0.2.tgz", "integrity": "sha512-EEVig1Q2QJ4ELpJXMZR8Vt5DQx8/mo+dGWSR7vWXqcob2gQLyQGsionYcGKATXvQzMPn6DSN1vTN7yFximdIAg==", "dev": true, - "requires": { + "dependencies": { "cssnano-util-get-match": "^4.0.0", "has": "^1.0.0", "postcss": "^7.0.0", "postcss-value-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" } }, - "postcss-selector-parser": { + "node_modules/postcss-selector-parser": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.2.tgz", "integrity": "sha512-36P2QR59jDTOAiIkqEprfJDsoNrvwFei3eCqKd1Y0tUsBimsq39BLp7RD+JWny3WgB1zGhJX8XVePwm9k4wdBg==", "dev": true, - "requires": { + "dependencies": { "cssesc": "^3.0.0", "indexes-of": "^1.0.1", "uniq": "^1.0.1" + }, + "engines": { + "node": ">=4" } }, - "postcss-svgo": { + "node_modules/postcss-svgo": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-4.0.2.tgz", "integrity": "sha512-C6wyjo3VwFm0QgBy+Fu7gCYOkCmgmClghO+pjcxvrcBKtiKt0uCF+hvbMO1fyv5BMImRK90SMb+dwUnfbGd+jw==", "dev": true, - "requires": { + "dependencies": { "is-svg": "^3.0.0", "postcss": "^7.0.0", "postcss-value-parser": "^3.0.0", "svgo": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" } }, - "postcss-unique-selectors": { + "node_modules/postcss-unique-selectors": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-4.0.1.tgz", "integrity": "sha512-+JanVaryLo9QwZjKrmJgkI4Fn8SBgRO6WXQBJi7KiAVPlmxikB5Jzc4EvXMT2H0/m0RjrVVm9rGNhZddm/8Spg==", "dev": true, - "requires": { + "dependencies": { "alphanum-sort": "^1.0.0", "postcss": "^7.0.0", "uniqs": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" } }, - "postcss-value-parser": { + "node_modules/postcss-value-parser": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", "dev": true }, - "posthtml": { + "node_modules/postcss/node_modules/supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/posthtml": { "version": "0.11.6", "resolved": "https://registry.npmjs.org/posthtml/-/posthtml-0.11.6.tgz", "integrity": "sha512-C2hrAPzmRdpuL3iH0TDdQ6XCc9M7Dcc3zEW5BLerY65G4tWWszwv6nG/ksi6ul5i2mx22ubdljgktXCtNkydkw==", "dev": true, - "requires": { + "dependencies": { "posthtml-parser": "^0.4.1", "posthtml-render": "^1.1.5" + }, + "engines": { + "node": ">=6.0.0" } }, - "posthtml-parser": { + "node_modules/posthtml-parser": { "version": "0.4.2", "resolved": "https://registry.npmjs.org/posthtml-parser/-/posthtml-parser-0.4.2.tgz", "integrity": "sha512-BUIorsYJTvS9UhXxPTzupIztOMVNPa/HtAm9KHni9z6qEfiJ1bpOBL5DfUOL9XAc3XkLIEzBzpph+Zbm4AdRAg==", "dev": true, - "requires": { + "dependencies": { "htmlparser2": "^3.9.2" } }, - "posthtml-render": { + "node_modules/posthtml-render": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/posthtml-render/-/posthtml-render-1.2.0.tgz", "integrity": "sha512-dQB+hoAKDtnI94RZm/wxBUH9My8OJcXd0uhWmGh2c7tVtQ85A+OS3yCN3LNbFtPz3bViwBJXAeoi+CBGMXM0DA==", - "dev": true + "dev": true, + "engines": { + "node": ">=6" + } }, - "prelude-ls": { + "node_modules/prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", - "dev": true + "dev": true, + "engines": { + "node": ">= 0.8.0" + } }, - "private": { + "node_modules/private": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", - "dev": true + "dev": true, + "engines": { + "node": ">= 0.6" + } }, - "process": { + "node_modules/process": { "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", - "dev": true + "dev": true, + "engines": { + "node": ">= 0.6.0" + } }, - "process-nextick-args": { + "node_modules/process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true }, - "psl": { + "node_modules/psl": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", "dev": true }, - "public-encrypt": { + "node_modules/public-encrypt": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", "dev": true, - "requires": { + "dependencies": { "bn.js": "^4.1.0", "browserify-rsa": "^4.0.0", "create-hash": "^1.1.0", @@ -5805,90 +7070,123 @@ "safe-buffer": "^5.1.2" } }, - "punycode": { + "node_modules/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 + "dev": true, + "engines": { + "node": ">=6" + } }, - "purgecss": { + "node_modules/purgecss": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/purgecss/-/purgecss-1.4.2.tgz", "integrity": "sha512-hkOreFTgiyMHMmC2BxzdIw5DuC6kxAbP/gGOGd3MEsF3+5m69rIvUEPaxrnoUtfODTFKe9hcXjGwC6jcjoyhOw==", "dev": true, - "requires": { + "dependencies": { "glob": "^7.1.3", "postcss": "^7.0.14", "postcss-selector-parser": "^6.0.0", "yargs": "^14.0.0" + }, + "bin": { + "purgecss": "bin/purgecss" + }, + "engines": { + "node": ">=4.4.0", + "npm": ">=5.2.0" + }, + "funding": { + "url": "https://github.com/sponsors/Ffloriel" } }, - "q": { + "node_modules/q": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", - "dev": true + "dev": true, + "engines": { + "node": ">=0.6.0", + "teleport": ">=0.2.0" + } }, - "qs": { + "node_modules/qs": { "version": "6.5.2", "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", - "dev": true + "dev": true, + "engines": { + "node": ">=0.6" + } }, - "querystring": { + "node_modules/querystring": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", - "dev": true + "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.", + "dev": true, + "engines": { + "node": ">=0.4.x" + } }, - "querystring-es3": { + "node_modules/querystring-es3": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", - "dev": true + "dev": true, + "engines": { + "node": ">=0.4.x" + } }, - "quote-stream": { + "node_modules/quote-stream": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/quote-stream/-/quote-stream-1.0.2.tgz", "integrity": "sha1-hJY/jJwmuULhU/7rU6rnRlK34LI=", "dev": true, - "requires": { + "dependencies": { "buffer-equal": "0.0.1", "minimist": "^1.1.3", "through2": "^2.0.0" + }, + "bin": { + "quote-stream": "bin/cmd.js" } }, - "randombytes": { + "node_modules/randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", "dev": true, - "requires": { + "dependencies": { "safe-buffer": "^5.1.0" } }, - "randomfill": { + "node_modules/randomfill": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", "dev": true, - "requires": { + "dependencies": { "randombytes": "^2.0.5", "safe-buffer": "^5.1.0" } }, - "range-parser": { + "node_modules/range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "dev": true + "dev": true, + "engines": { + "node": ">= 0.6" + } }, - "readable-stream": { + "node_modules/readable-stream": { "version": "2.3.7", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "dev": true, - "requires": { + "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", @@ -5898,119 +7196,142 @@ "util-deprecate": "~1.0.1" } }, - "readdirp": { + "node_modules/readdirp": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", "dev": true, - "requires": { + "dependencies": { "graceful-fs": "^4.1.11", "micromatch": "^3.1.10", "readable-stream": "^2.0.2" + }, + "engines": { + "node": ">=0.10" } }, - "regenerate": { + "node_modules/regenerate": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==", "dev": true }, - "regenerate-unicode-properties": { + "node_modules/regenerate-unicode-properties": { "version": "8.2.0", "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz", "integrity": "sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA==", "dev": true, - "requires": { + "dependencies": { "regenerate": "^1.4.0" + }, + "engines": { + "node": ">=4" } }, - "regenerator-runtime": { + "node_modules/regenerator-runtime": { "version": "0.13.5", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz", "integrity": "sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA==", "dev": true }, - "regenerator-transform": { + "node_modules/regenerator-transform": { "version": "0.14.4", "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.4.tgz", "integrity": "sha512-EaJaKPBI9GvKpvUz2mz4fhx7WPgvwRLY9v3hlNHWmAuJHI13T4nwKnNvm5RWJzEdnI5g5UwtOww+S8IdoUC2bw==", "dev": true, - "requires": { + "dependencies": { "@babel/runtime": "^7.8.4", "private": "^0.1.8" } }, - "regex-not": { + "node_modules/regex-not": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", "dev": true, - "requires": { + "dependencies": { "extend-shallow": "^3.0.2", "safe-regex": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "regexpu-core": { + "node_modules/regexpu-core": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.7.0.tgz", "integrity": "sha512-TQ4KXRnIn6tz6tjnrXEkD/sshygKH/j5KzK86X8MkeHyZ8qst/LZ89j3X4/8HEIfHANTFIP/AbXakeRhWIl5YQ==", "dev": true, - "requires": { + "dependencies": { "regenerate": "^1.4.0", "regenerate-unicode-properties": "^8.2.0", "regjsgen": "^0.5.1", "regjsparser": "^0.6.4", "unicode-match-property-ecmascript": "^1.0.4", "unicode-match-property-value-ecmascript": "^1.2.0" + }, + "engines": { + "node": ">=4" } }, - "regjsgen": { + "node_modules/regjsgen": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.1.tgz", "integrity": "sha512-5qxzGZjDs9w4tzT3TPhCJqWdCc3RLYwy9J2NB0nm5Lz+S273lvWcpjaTGHsT1dc6Hhfq41uSEOw8wBmxrKOuyg==", "dev": true }, - "regjsparser": { + "node_modules/regjsparser": { "version": "0.6.4", "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.4.tgz", "integrity": "sha512-64O87/dPDgfk8/RQqC4gkZoGyyWFIEUTTh80CU6CWuK5vkCGyekIx+oKcEIYtP/RAxSQltCZHCNu/mdd7fqlJw==", "dev": true, - "requires": { + "dependencies": { "jsesc": "~0.5.0" }, - "dependencies": { - "jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", - "dev": true - } + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/regjsparser/node_modules/jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" } }, - "remove-trailing-separator": { + "node_modules/remove-trailing-separator": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", "dev": true }, - "repeat-element": { + "node_modules/repeat-element": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "repeat-string": { + "node_modules/repeat-string": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10" + } }, - "request": { + "node_modules/request": { "version": "2.88.2", "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", "dev": true, - "requires": { + "dependencies": { "aws-sign2": "~0.7.0", "aws4": "^1.8.0", "caseless": "~0.12.0", @@ -6031,156 +7352,197 @@ "tough-cookie": "~2.5.0", "tunnel-agent": "^0.6.0", "uuid": "^3.3.2" + }, + "engines": { + "node": ">= 6" } }, - "request-promise-core": { + "node_modules/request-promise-core": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.3.tgz", "integrity": "sha512-QIs2+ArIGQVp5ZYbWD5ZLCY29D5CfWizP8eWnm8FoGD1TX61veauETVQbrV60662V0oFBkrDOuaBI8XgtuyYAQ==", "dev": true, - "requires": { + "dependencies": { "lodash": "^4.17.15" + }, + "engines": { + "node": ">=0.10.0" + }, + "peerDependencies": { + "request": "^2.34" } }, - "request-promise-native": { + "node_modules/request-promise-native": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.8.tgz", "integrity": "sha512-dapwLGqkHtwL5AEbfenuzjTYg35Jd6KPytsC2/TLkVMz8rm+tNt72MGUWT1RP/aYawMpN6HqbNGBQaRcBtjQMQ==", + "deprecated": "request-promise-native has been deprecated because it extends the now deprecated request package, see https://github.com/request/request/issues/3142", "dev": true, - "requires": { + "dependencies": { "request-promise-core": "1.1.3", "stealthy-require": "^1.1.1", "tough-cookie": "^2.3.3" + }, + "engines": { + "node": ">=0.12.0" + }, + "peerDependencies": { + "request": "^2.34" } }, - "require-directory": { + "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "require-main-filename": { + "node_modules/require-main-filename": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", "dev": true }, - "resolve": { + "node_modules/resolve": { "version": "1.15.1", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz", "integrity": "sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==", "dev": true, - "requires": { + "dependencies": { "path-parse": "^1.0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "resolve-from": { + "node_modules/resolve-from": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", - "dev": true + "dev": true, + "engines": { + "node": ">=4" + } }, - "resolve-url": { + "node_modules/resolve-url": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "deprecated": "https://github.com/lydell/resolve-url#deprecated", "dev": true }, - "restore-cursor": { + "node_modules/restore-cursor": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", "dev": true, - "requires": { + "dependencies": { "onetime": "^2.0.0", "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=4" } }, - "ret": { + "node_modules/ret": { "version": "0.1.15", "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", - "dev": true + "dev": true, + "engines": { + "node": ">=0.12" + } }, - "rgb-regex": { + "node_modules/rgb-regex": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/rgb-regex/-/rgb-regex-1.0.1.tgz", "integrity": "sha1-wODWiC3w4jviVKR16O3UGRX+rrE=", "dev": true }, - "rgba-regex": { + "node_modules/rgba-regex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/rgba-regex/-/rgba-regex-1.0.0.tgz", "integrity": "sha1-QzdOLiyglosO8VI0YLfXMP8i7rM=", "dev": true }, - "rimraf": { + "node_modules/rimraf": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", "dev": true, - "requires": { + "dependencies": { "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" } }, - "ripemd160": { + "node_modules/ripemd160": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", "dev": true, - "requires": { + "dependencies": { "hash-base": "^3.0.0", "inherits": "^2.0.1" } }, - "safe-buffer": { + "node_modules/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": { + "node_modules/safe-regex": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", "dev": true, - "requires": { + "dependencies": { "ret": "~0.1.10" } }, - "safer-buffer": { + "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true }, - "sax": { + "node_modules/sax": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", "dev": true }, - "saxes": { + "node_modules/saxes": { "version": "3.1.11", "resolved": "https://registry.npmjs.org/saxes/-/saxes-3.1.11.tgz", "integrity": "sha512-Ydydq3zC+WYDJK1+gRxRapLIED9PWeSuuS41wqyoRmzvhhh9nc+QQrVMKJYzJFULazeGhzSV0QleN2wD3boh2g==", "dev": true, - "requires": { + "dependencies": { "xmlchars": "^2.1.1" + }, + "engines": { + "node": ">=8" } }, - "semver": { + "node_modules/semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true + "dev": true, + "bin": { + "semver": "bin/semver" + } }, - "send": { + "node_modules/send": { "version": "0.17.1", "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", "dev": true, - "requires": { + "dependencies": { "debug": "2.6.9", "depd": "~1.1.2", "destroy": "~1.0.4", @@ -6195,151 +7557,167 @@ "range-parser": "~1.2.1", "statuses": "~1.5.0" }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - }, - "dependencies": { - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - } + "ms": "2.0.0" } }, - "serialize-to-js": { + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "node_modules/serialize-to-js": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/serialize-to-js/-/serialize-to-js-3.1.1.tgz", "integrity": "sha512-F+NGU0UHMBO4Q965tjw7rvieNVjlH6Lqi2emq/Lc9LUURYJbiCzmpi4Cy1OOjjVPtxu0c+NE85LU6968Wko5ZA==", - "dev": true + "dev": true, + "engines": { + "node": ">=4.0.0" + } }, - "serve-static": { + "node_modules/serve-static": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", "dev": true, - "requires": { + "dependencies": { "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "parseurl": "~1.3.3", "send": "0.17.1" + }, + "engines": { + "node": ">= 0.8.0" } }, - "set-blocking": { + "node_modules/set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true }, - "set-value": { + "node_modules/set-value": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", "dev": true, - "requires": { + "dependencies": { "extend-shallow": "^2.0.1", "is-extendable": "^0.1.1", "is-plain-object": "^2.0.3", "split-string": "^3.0.1" }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/set-value/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "setimmediate": { + "node_modules/setimmediate": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", "dev": true }, - "setprototypeof": { + "node_modules/setprototypeof": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", "dev": true }, - "sha.js": { + "node_modules/sha.js": { "version": "2.4.11", "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", "dev": true, - "requires": { + "dependencies": { "inherits": "^2.0.1", "safe-buffer": "^5.0.1" + }, + "bin": { + "sha.js": "bin.js" } }, - "shallow-copy": { + "node_modules/shallow-copy": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/shallow-copy/-/shallow-copy-0.0.1.tgz", "integrity": "sha1-QV9CcC1z2BAzApLMXuhurhoRoXA=", "dev": true }, - "shebang-command": { + "node_modules/shebang-command": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", "dev": true, - "requires": { + "dependencies": { "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "shebang-regex": { + "node_modules/shebang-regex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "signal-exit": { + "node_modules/signal-exit": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", "dev": true }, - "simple-swizzle": { + "node_modules/simple-swizzle": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", "dev": true, - "requires": { - "is-arrayish": "^0.3.1" - }, "dependencies": { - "is-arrayish": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", - "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", - "dev": true - } + "is-arrayish": "^0.3.1" } }, - "snapdragon": { + "node_modules/simple-swizzle/node_modules/is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", + "dev": true + }, + "node_modules/snapdragon": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", "dev": true, - "requires": { + "dependencies": { "base": "^0.11.1", "debug": "^2.2.0", "define-property": "^0.2.5", @@ -6349,131 +7727,164 @@ "source-map-resolve": "^0.5.0", "use": "^3.1.0" }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } + "engines": { + "node": ">=0.10.0" } }, - "snapdragon-node": { + "node_modules/snapdragon-node": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", "dev": true, - "requires": { + "dependencies": { "define-property": "^1.0.0", "isobject": "^3.0.0", "snapdragon-util": "^3.0.1" }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-node/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "dependencies": { + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-node/node_modules/is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "deprecated": "Please upgrade to v1.0.1", + "dev": true, "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "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" - } - } + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-node/node_modules/is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "deprecated": "Please upgrade to v1.0.1", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-node/node_modules/is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=0.10.0" } }, - "snapdragon-util": { + "node_modules/snapdragon-util": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", "dev": true, - "requires": { + "dependencies": { "kind-of": "^3.2.0" }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-util/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" } }, - "source-map": { + "node_modules/snapdragon/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/snapdragon/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/snapdragon/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "source-map-resolve": { + "node_modules/source-map-resolve": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", + "deprecated": "See https://github.com/lydell/source-map-resolve#deprecated", "dev": true, - "requires": { + "dependencies": { "atob": "^2.1.2", "decode-uri-component": "^0.2.0", "resolve-url": "^0.2.1", @@ -6481,43 +7892,47 @@ "urix": "^0.1.0" } }, - "source-map-support": { + "node_modules/source-map-support": { "version": "0.5.16", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.16.tgz", "integrity": "sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ==", "dev": true, - "requires": { + "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" } }, - "source-map-url": { + "node_modules/source-map-url": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "deprecated": "See https://github.com/lydell/source-map-url#deprecated", "dev": true }, - "split-string": { + "node_modules/split-string": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", "dev": true, - "requires": { + "dependencies": { "extend-shallow": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "sprintf-js": { + "node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", "dev": true }, - "sshpk": { + "node_modules/sshpk": { "version": "1.16.1", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", "dev": true, - "requires": { + "dependencies": { "asn1": "~0.2.3", "assert-plus": "^1.0.0", "bcrypt-pbkdf": "^1.0.0", @@ -6527,71 +7942,98 @@ "jsbn": "~0.1.0", "safer-buffer": "^2.0.2", "tweetnacl": "~0.14.0" + }, + "bin": { + "sshpk-conv": "bin/sshpk-conv", + "sshpk-sign": "bin/sshpk-sign", + "sshpk-verify": "bin/sshpk-verify" + }, + "engines": { + "node": ">=0.10.0" } }, - "stable": { + "node_modules/stable": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", + "deprecated": "Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility", "dev": true }, - "static-eval": { + "node_modules/static-eval": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/static-eval/-/static-eval-2.0.5.tgz", "integrity": "sha512-nNbV6LbGtMBgv7e9LFkt5JV8RVlRsyJrphfAt9tOtBBW/SfnzZDf2KnS72an8e434A+9e/BmJuTxeGPvrAK7KA==", "dev": true, - "requires": { + "dependencies": { "escodegen": "^1.11.1" - }, + } + }, + "node_modules/static-eval/node_modules/escodegen": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.1.tgz", + "integrity": "sha512-Bmt7NcRySdIfNPfU2ZoXDrrXsG9ZjvDxcAlMfDUgRBjLOWTuIACXPBFJH7Z+cLb40JeQco5toikyc9t9P8E9SQ==", + "dev": true, "dependencies": { - "escodegen": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.1.tgz", - "integrity": "sha512-Bmt7NcRySdIfNPfU2ZoXDrrXsG9ZjvDxcAlMfDUgRBjLOWTuIACXPBFJH7Z+cLb40JeQco5toikyc9t9P8E9SQ==", - "dev": true, - "requires": { - "esprima": "^4.0.1", - "estraverse": "^4.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1", - "source-map": "~0.6.1" - } - }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true - } + "esprima": "^4.0.1", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=4.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/static-eval/node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" } }, - "static-extend": { + "node_modules/static-extend": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", "dev": true, - "requires": { + "dependencies": { "define-property": "^0.2.5", "object-copy": "^0.1.0" }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-extend/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - } + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "static-module": { + "node_modules/static-module": { "version": "2.2.5", "resolved": "https://registry.npmjs.org/static-module/-/static-module-2.2.5.tgz", "integrity": "sha512-D8vv82E/Kpmz3TXHKG8PPsCPg+RAX6cbCOyvjM6x04qZtQ47EtJFVwRsdov3n5d6/6ynrOY9XB4JkaZwB2xoRQ==", "dev": true, - "requires": { + "dependencies": { "concat-stream": "~1.6.0", "convert-source-map": "^1.5.1", "duplexer2": "~0.1.4", @@ -6608,34 +8050,40 @@ "through2": "~2.0.3" } }, - "statuses": { + "node_modules/statuses": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", - "dev": true + "dev": true, + "engines": { + "node": ">= 0.6" + } }, - "stealthy-require": { + "node_modules/stealthy-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "stream-browserify": { + "node_modules/stream-browserify": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", "dev": true, - "requires": { + "dependencies": { "inherits": "~2.0.1", "readable-stream": "^2.0.2" } }, - "stream-http": { + "node_modules/stream-http": { "version": "2.8.3", "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", "dev": true, - "requires": { + "dependencies": { "builtin-status-codes": "^3.0.0", "inherits": "^2.0.1", "readable-stream": "^2.3.6", @@ -6643,133 +8091,169 @@ "xtend": "^4.0.0" } }, - "string-width": { + "node_modules/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, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/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": { + "dependencies": { "emoji-regex": "^7.0.1", "is-fullwidth-code-point": "^2.0.0", "strip-ansi": "^5.1.0" }, + "engines": { + "node": ">=6" + } + }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "strip-ansi": { - "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": "^4.1.0" - } - } + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" } }, - "string.prototype.trimend": { + "node_modules/string.prototype.trimend": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.0.tgz", "integrity": "sha512-EEJnGqa/xNfIg05SxiPSqRS7S9qwDhYts1TSLR1BQfYUfPe1stofgGKvwERK9+9yf+PpfBMlpBaCHucXGPQfUA==", "dev": true, - "requires": { + "dependencies": { "define-properties": "^1.1.3", "es-abstract": "^1.17.5" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "string.prototype.trimleft": { + "node_modules/string.prototype.trimleft": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.2.tgz", "integrity": "sha512-gCA0tza1JBvqr3bfAIFJGqfdRTyPae82+KTnm3coDXkZN9wnuW3HjGgN386D7hfv5CHQYCI022/rJPVlqXyHSw==", "dev": true, - "requires": { + "dependencies": { "define-properties": "^1.1.3", "es-abstract": "^1.17.5", "string.prototype.trimstart": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "string.prototype.trimright": { + "node_modules/string.prototype.trimright": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.2.tgz", "integrity": "sha512-ZNRQ7sY3KroTaYjRS6EbNiiHrOkjihL9aQE/8gfQ4DtAC/aEBRHFJa44OmoWxGGqXuJlfKkZW4WcXErGr+9ZFg==", "dev": true, - "requires": { + "dependencies": { "define-properties": "^1.1.3", "es-abstract": "^1.17.5", "string.prototype.trimend": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "string.prototype.trimstart": { + "node_modules/string.prototype.trimstart": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.0.tgz", "integrity": "sha512-iCP8g01NFYiiBOnwG1Xc3WZLyoo+RuBymwIlWncShXDDJYWN6DbnM3odslBJdgCdRlq94B5s63NWAZlcn2CS4w==", "dev": true, - "requires": { + "dependencies": { "define-properties": "^1.1.3", "es-abstract": "^1.17.5" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "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" - } - }, - "strip-ansi": { + "node_modules/strip-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, - "requires": { + "dependencies": { "ansi-regex": "^3.0.0" + }, + "engines": { + "node": ">=4" } }, - "stylehacks": { + "node_modules/stylehacks": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-4.0.3.tgz", "integrity": "sha512-7GlLk9JwlElY4Y6a/rmbH2MhVlTyVmiJd1PfTCqFaIBEGMYNsrO/v3SeGTdhBThLg4Z+NbOk/qFMwCa+J+3p/g==", "dev": true, - "requires": { + "dependencies": { "browserslist": "^4.0.0", "postcss": "^7.0.0", "postcss-selector-parser": "^3.0.0" }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/stylehacks/node_modules/postcss-selector-parser": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz", + "integrity": "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA==", + "dev": true, "dependencies": { - "postcss-selector-parser": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz", - "integrity": "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA==", - "dev": true, - "requires": { - "dot-prop": "^5.2.0", - "indexes-of": "^1.0.1", - "uniq": "^1.0.1" - } - } + "dot-prop": "^5.2.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + }, + "engines": { + "node": ">=8" } }, - "supports-color": { + "node_modules/supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, - "requires": { + "dependencies": { "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" } }, - "svgo": { + "node_modules/svgo": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/svgo/-/svgo-1.3.2.tgz", "integrity": "sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw==", + "deprecated": "This SVGO version is no longer supported. Upgrade to v2.x.x.", "dev": true, - "requires": { + "dependencies": { "chalk": "^2.4.1", "coa": "^2.0.2", "css-select": "^2.0.0", @@ -6783,183 +8267,230 @@ "stable": "^0.1.8", "unquote": "~1.1.1", "util.promisify": "~1.0.0" + }, + "bin": { + "svgo": "bin/svgo" + }, + "engines": { + "node": ">=4.0.0" } }, - "symbol-tree": { + "node_modules/symbol-tree": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", "dev": true }, - "terser": { + "node_modules/terser": { "version": "3.17.0", "resolved": "https://registry.npmjs.org/terser/-/terser-3.17.0.tgz", "integrity": "sha512-/FQzzPJmCpjAH9Xvk2paiWrFq+5M6aVOf+2KRbwhByISDX/EujxsK+BAvrhb6H+2rtrLCHK9N01wO014vrIwVQ==", "dev": true, - "requires": { + "dependencies": { "commander": "^2.19.0", "source-map": "~0.6.1", "source-map-support": "~0.5.10" + }, + "bin": { + "terser": "bin/uglifyjs" + }, + "engines": { + "node": ">=6.0.0" } }, - "through2": { + "node_modules/through2": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", "dev": true, - "requires": { + "dependencies": { "readable-stream": "~2.3.6", "xtend": "~4.0.1" } }, - "timers-browserify": { + "node_modules/timers-browserify": { "version": "2.0.11", "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.11.tgz", "integrity": "sha512-60aV6sgJ5YEbzUdn9c8kYGIqOubPoUdqQCul3SBAsRCZ40s6Y5cMcrW4dt3/k/EsbLVJNl9n6Vz3fTc+k2GeKQ==", "dev": true, - "requires": { + "dependencies": { "setimmediate": "^1.0.4" + }, + "engines": { + "node": ">=0.6.0" } }, - "timsort": { + "node_modules/timsort": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz", "integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=", "dev": true }, - "tiny-inflate": { + "node_modules/tiny-inflate": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz", "integrity": "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==", "dev": true }, - "to-arraybuffer": { + "node_modules/to-arraybuffer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", "dev": true }, - "to-fast-properties": { + "node_modules/to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true + "dev": true, + "engines": { + "node": ">=4" + } }, - "to-object-path": { + "node_modules/to-object-path": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", "dev": true, - "requires": { + "dependencies": { "kind-of": "^3.0.2" }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-object-path/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" } }, - "to-regex": { + "node_modules/to-regex": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", "dev": true, - "requires": { + "dependencies": { "define-property": "^2.0.2", "extend-shallow": "^3.0.2", "regex-not": "^1.0.2", "safe-regex": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "to-regex-range": { + "node_modules/to-regex-range": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", "dev": true, - "requires": { + "dependencies": { "is-number": "^3.0.0", "repeat-string": "^1.6.1" + }, + "engines": { + "node": ">=0.10.0" } }, - "toidentifier": { + "node_modules/toidentifier": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", - "dev": true + "dev": true, + "engines": { + "node": ">=0.6" + } }, - "tough-cookie": { + "node_modules/tough-cookie": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", "dev": true, - "requires": { + "dependencies": { "psl": "^1.1.28", "punycode": "^2.1.1" + }, + "engines": { + "node": ">=0.8" } }, - "tr46": { + "node_modules/tr46": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=", "dev": true, - "requires": { + "dependencies": { "punycode": "^2.1.0" } }, - "tty-browserify": { + "node_modules/tty-browserify": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", "dev": true }, - "tunnel-agent": { + "node_modules/tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", "dev": true, - "requires": { + "dependencies": { "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" } }, - "tweetnacl": { + "node_modules/tweetnacl": { "version": "0.14.5", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", "dev": true }, - "type-check": { + "node_modules/type-check": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", "dev": true, - "requires": { + "dependencies": { "prelude-ls": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" } }, - "typedarray": { + "node_modules/typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", "dev": true }, - "typescript": { + "node_modules/typescript": { "version": "3.8.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.8.3.tgz", "integrity": "sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w==", - "dev": true + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } }, - "uncss": { + "node_modules/uncss": { "version": "0.17.3", "resolved": "https://registry.npmjs.org/uncss/-/uncss-0.17.3.tgz", "integrity": "sha512-ksdDWl81YWvF/X14fOSw4iu8tESDHFIeyKIeDrK6GEVTQvqJc1WlOEXqostNwOCi3qAj++4EaLsdAgPmUbEyog==", "dev": true, - "requires": { + "dependencies": { "commander": "^2.20.0", "glob": "^7.1.4", "is-absolute-url": "^3.0.1", @@ -6970,399 +8501,464 @@ "postcss-selector-parser": "6.0.2", "request": "^2.88.0" }, - "dependencies": { - "is-absolute-url": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-3.0.3.tgz", - "integrity": "sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q==", - "dev": true - } + "bin": { + "uncss": "bin/uncss" + }, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/uncss/node_modules/is-absolute-url": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-3.0.3.tgz", + "integrity": "sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q==", + "dev": true, + "engines": { + "node": ">=8" } }, - "unicode-canonical-property-names-ecmascript": { + "node_modules/unicode-canonical-property-names-ecmascript": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", "integrity": "sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ==", - "dev": true + "dev": true, + "engines": { + "node": ">=4" + } }, - "unicode-match-property-ecmascript": { + "node_modules/unicode-match-property-ecmascript": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz", "integrity": "sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==", "dev": true, - "requires": { + "dependencies": { "unicode-canonical-property-names-ecmascript": "^1.0.4", "unicode-property-aliases-ecmascript": "^1.0.4" + }, + "engines": { + "node": ">=4" } }, - "unicode-match-property-value-ecmascript": { + "node_modules/unicode-match-property-value-ecmascript": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz", "integrity": "sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ==", - "dev": true + "dev": true, + "engines": { + "node": ">=4" + } }, - "unicode-property-aliases-ecmascript": { + "node_modules/unicode-property-aliases-ecmascript": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz", "integrity": "sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg==", - "dev": true + "dev": true, + "engines": { + "node": ">=4" + } }, - "unicode-trie": { + "node_modules/unicode-trie": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/unicode-trie/-/unicode-trie-0.3.1.tgz", "integrity": "sha1-1nHd3YkQGgi6w3tqUWEBBgIFIIU=", "dev": true, - "requires": { + "dependencies": { "pako": "^0.2.5", "tiny-inflate": "^1.0.0" } }, - "union-value": { + "node_modules/union-value": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", "dev": true, - "requires": { + "dependencies": { "arr-union": "^3.1.0", "get-value": "^2.0.6", "is-extendable": "^0.1.1", "set-value": "^2.0.1" + }, + "engines": { + "node": ">=0.10.0" } }, - "uniq": { + "node_modules/uniq": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=", "dev": true }, - "uniqs": { + "node_modules/uniqs": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/uniqs/-/uniqs-2.0.0.tgz", "integrity": "sha1-/+3ks2slKQaW5uFl1KWe25mOawI=", "dev": true }, - "unquote": { + "node_modules/unquote": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/unquote/-/unquote-1.1.1.tgz", "integrity": "sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ=", "dev": true }, - "unset-value": { + "node_modules/unset-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", "dev": true, - "requires": { + "dependencies": { "has-value": "^0.3.1", "isobject": "^3.0.0" }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dev": true, "dependencies": { - "has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", - "dev": true, - "requires": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" - }, - "dependencies": { - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "requires": { - "isarray": "1.0.0" - } - } - } - }, - "has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", - "dev": true - } + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/has-value/node_modules/isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "dependencies": { + "isarray": "1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "dev": true, + "engines": { + "node": ">=0.10.0" } }, - "upath": { + "node_modules/upath": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", - "dev": true + "dev": true, + "engines": { + "node": ">=4", + "yarn": "*" + } }, - "uri-js": { + "node_modules/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": { + "dependencies": { "punycode": "^2.1.0" } }, - "urix": { + "node_modules/urix": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "deprecated": "Please see https://github.com/lydell/urix#deprecated", "dev": true }, - "url": { + "node_modules/url": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", "dev": true, - "requires": { + "dependencies": { "punycode": "1.3.2", "querystring": "0.2.0" - }, - "dependencies": { - "punycode": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", - "dev": true - } } }, - "use": { + "node_modules/url/node_modules/punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", + "dev": true + }, + "node_modules/use": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "util": { + "node_modules/util": { "version": "0.11.1", "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", "dev": true, - "requires": { - "inherits": "2.0.3" - }, "dependencies": { - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - } + "inherits": "2.0.3" } }, - "util-deprecate": { + "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true }, - "util.promisify": { + "node_modules/util.promisify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.1.tgz", "integrity": "sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA==", "dev": true, - "requires": { + "dependencies": { "define-properties": "^1.1.3", "es-abstract": "^1.17.2", "has-symbols": "^1.0.1", "object.getownpropertydescriptors": "^2.1.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "uuid": { + "node_modules/util/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "node_modules/uuid": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "dev": true + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "dev": true, + "bin": { + "uuid": "bin/uuid" + } }, - "v8-compile-cache": { + "node_modules/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 }, - "vendors": { + "node_modules/vendors": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/vendors/-/vendors-1.0.4.tgz", "integrity": "sha512-/juG65kTL4Cy2su4P8HjtkTxk6VmJDiOPBufWniqQ6wknac6jNiXS9vU+hO3wgusiyqWlzTbVHi0dyJqRONg3w==", - "dev": true + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } }, - "verror": { + "node_modules/verror": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", "dev": true, - "requires": { + "engines": [ + "node >=0.6.0" + ], + "dependencies": { "assert-plus": "^1.0.0", "core-util-is": "1.0.2", "extsprintf": "^1.2.0" } }, - "vlq": { + "node_modules/vlq": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/vlq/-/vlq-0.2.3.tgz", "integrity": "sha512-DRibZL6DsNhIgYQ+wNdWDL2SL3bKPlVrRiBqV5yuMm++op8W4kGFtaQfCs4KEJn0wBZcHVHJ3eoywX8983k1ow==", "dev": true }, - "vm-browserify": { + "node_modules/vm-browserify": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==", "dev": true }, - "w3c-hr-time": { + "node_modules/w3c-hr-time": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==", + "deprecated": "Use your platform's native performance.now() and performance.timeOrigin.", "dev": true, - "requires": { + "dependencies": { "browser-process-hrtime": "^1.0.0" } }, - "w3c-xmlserializer": { + "node_modules/w3c-xmlserializer": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-1.1.2.tgz", "integrity": "sha512-p10l/ayESzrBMYWRID6xbuCKh2Fp77+sA0doRuGn4tTIMrrZVeqfpKjXHY+oDh3K4nLdPgNwMTVP6Vp4pvqbNg==", "dev": true, - "requires": { + "dependencies": { "domexception": "^1.0.1", "webidl-conversions": "^4.0.2", "xml-name-validator": "^3.0.0" } }, - "wcwidth": { + "node_modules/wcwidth": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", "dev": true, - "requires": { + "dependencies": { "defaults": "^1.0.3" } }, - "webidl-conversions": { + "node_modules/webidl-conversions": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", "dev": true }, - "whatwg-encoding": { + "node_modules/whatwg-encoding": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", "dev": true, - "requires": { + "dependencies": { "iconv-lite": "0.4.24" } }, - "whatwg-mimetype": { + "node_modules/whatwg-mimetype": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", "dev": true }, - "whatwg-url": { + "node_modules/whatwg-url": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", "dev": true, - "requires": { + "dependencies": { "lodash.sortby": "^4.7.0", "tr46": "^1.0.1", "webidl-conversions": "^4.0.2" } }, - "which": { + "node_modules/which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, - "requires": { + "dependencies": { "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" } }, - "which-module": { + "node_modules/which-module": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", "dev": true }, - "word-wrap": { + "node_modules/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 + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "wrap-ansi": { + "node_modules/wrap-ansi": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", "dev": true, - "requires": { + "dependencies": { "ansi-styles": "^3.2.0", "string-width": "^3.0.0", "strip-ansi": "^5.0.0" }, + "engines": { + "node": ">=6" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "strip-ansi": { - "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": "^4.1.0" - } - } + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" } }, - "wrappy": { + "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true }, - "ws": { + "node_modules/ws": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz", "integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==", "dev": true, - "requires": { + "dependencies": { "async-limiter": "~1.0.0" } }, - "xml-name-validator": { + "node_modules/xml-name-validator": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", "dev": true }, - "xmlchars": { + "node_modules/xmlchars": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", "dev": true }, - "xtend": { + "node_modules/xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true + "dev": true, + "engines": { + "node": ">=0.4" + } }, - "y18n": { + "node_modules/y18n": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", "dev": true }, - "yargs": { + "node_modules/yargs": { "version": "14.2.3", "resolved": "https://registry.npmjs.org/yargs/-/yargs-14.2.3.tgz", "integrity": "sha512-ZbotRWhF+lkjijC/VhmOT9wSgyBQ7+zr13+YLkhfsSiTriYsMzkTUFP18pFhWwBeMa5gUc1MzbhrO6/VB7c9Xg==", "dev": true, - "requires": { + "dependencies": { "cliui": "^5.0.0", "decamelize": "^1.2.0", "find-up": "^3.0.0", @@ -7374,62 +8970,78 @@ "which-module": "^2.0.0", "y18n": "^4.0.0", "yargs-parser": "^15.0.1" - }, - "dependencies": { - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "requires": { - "p-limit": "^2.0.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - } } }, - "yargs-parser": { + "node_modules/yargs-parser": { "version": "15.0.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-15.0.1.tgz", "integrity": "sha512-0OAMV2mAZQrs3FkNpDQcBk1x5HXb8X4twADss4S0Iuk+2dGnLOE/fRHrsYm542GduMveyA77OF4wrNJuanRCWw==", "dev": true, - "requires": { + "dependencies": { "camelcase": "^5.0.0", "decamelize": "^1.2.0" } + }, + "node_modules/yargs/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yargs/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs/node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } } } } diff --git a/jipt/package.json b/jipt/package.json index 7d850119c..d02652c6a 100644 --- a/jipt/package.json +++ b/jipt/package.json @@ -7,6 +7,7 @@ "build": "parcel index.html", "build-production": "parcel build index.ts --out-dir=jipt-dist --target browser --experimental-scope-hoisting", "build-production-inline": "parcel build index.ts --out-dir=../priv/static/jipt --target browser --experimental-scope-hoisting", + "watch-production-inline": "parcel watch index.ts --out-dir=../priv/static/jipt --target browser", "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], diff --git a/jipt/src/accent.ts b/jipt/src/accent.ts index 213a5eef4..21c2b0a57 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: new Map(), - 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 5c9567735..7f486d21a 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 { @@ -47,9 +47,9 @@ export default class FrameListener { ); } - private handleAccentMessage({data}) { - if (!data.jipt) return; - const action = data.action; + private handleAccentMessage(event: MessageEvent) { + if (!event.data.jipt) return; + const action = event.data.action; if (action === ACTIONS.listTranslations) { return this.handleListTranslations(event); @@ -76,7 +76,7 @@ export default class FrameListener { } } - private handleListTranslations(event) { + private handleListTranslations(event: MessageEvent) { const currentRevision = this.state.getCurrentRevision(); const newRevision = event.data.payload.revisionId; this.state.projectTranslations = event.data.payload.translations; @@ -102,7 +102,7 @@ export default class FrameListener { this.ui.collapse(); } - private handleChangeText(event) { + private handleChangeText(event: MessageEvent) { const ref = this.state.refs.get(event.data.payload.translationId); if (!ref) return; @@ -113,11 +113,11 @@ export default class FrameListener { }); } - private handleUpdateTranslation(event) { + private handleUpdateTranslation(event: MessageEvent) { const ref = this.state.refs.get(event.data.payload.translationId); if (!ref) return; - ref.elements.forEach((meta, node: HTMLElement) => { + ref.elements.forEach((_meta, node: HTMLElement) => { if (!this.liveNode.isLive(node)) return; Mutation.nodeStyleRefresh(node, event.data.payload); diff --git a/jipt/src/mutation/live-node.ts b/jipt/src/mutation/live-node.ts index 642cada6a..7a68589da 100644 --- a/jipt/src/mutation/live-node.ts +++ b/jipt/src/mutation/live-node.ts @@ -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 a47700b33..5f7d570e7 100644 --- a/jipt/src/mutation/mutation.ts +++ b/jipt/src/mutation/mutation.ts @@ -75,7 +75,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 4645be292..3478a42bf 100644 --- a/jipt/src/ui/pin.ts +++ b/jipt/src/ui/pin.ts @@ -78,7 +78,7 @@ export default class Pin { ); } - private pinContent(id) { + private pinContent(id: string) { return `
diff --git a/jipt/src/ui/styles.ts b/jipt/src/ui/styles.ts index 490e569a7..29166f7bd 100644 --- a/jipt/src/ui/styles.ts +++ b/jipt/src/ui/styles.ts @@ -21,11 +21,11 @@ const translationNodeUpdated = // Frame const frameBase = - 'position: fixed; z-index: 10001; bottom: 0; right: 10px; background: #fff; box-shadow: 0 3px 20px rgba(0, 0, 0, 0.3); transition: transform 0.2s ease-in-out;'; + 'position: fixed; overflow: hidden; border-radius: 8px 0 0 0; z-index: 10001; bottom: 1px; right: 0; background: #fff; box-shadow: 0 3px 20px rgba(0, 0, 0, 0.3); transition: transform 0.2s ease-in-out;'; const frameCollapsed = `${frameBase} transform: translate3d(0, 558px, 0);`; const frameExpanded = `${frameBase} transform: translate3d(0, 0, 0);`; const frameCentered = - 'position: fixed; z-index: 10003; top: calc(50% - 300px); right: calc(50% - 300px); background: #fff; box-shadow: 0 3px 20px rgba(0, 0, 0, 0.3);'; + 'position: fixed; z-index: 10003; top: calc(50% - 300px); right: calc(50% - 300px); background: #fff; box-shadow: 0 3px 20px rgba(0, 0, 0, 0.2);'; const frameCollapseButton = 'cursor: pointer; position: absolute; right: 4px; top: 2px; width: 24px; height: 24px; text-align: center; color: #555; font-size: 20px;'; const frameExpandButton = @@ -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 73cdb60bd..36b677958 100644 --- a/jipt/src/ui/ui.ts +++ b/jipt/src/ui/ui.ts @@ -126,7 +126,7 @@ export default class UI { return element; } - private buildFrame(config) { + private buildFrame(config: Config) { const element = document.createElement('iframe'); const query = this.state.getCurrentRevision() ? `?revisionId=${this.state.getCurrentRevision()}` diff --git a/lib/accent.ex b/lib/accent.ex index d5509ddae..ba8c376f5 100644 --- a/lib/accent.ex +++ b/lib/accent.ex @@ -16,6 +16,11 @@ defmodule Accent do {Phoenix.PubSub, [name: Accent.PubSub, adapter: Phoenix.PubSub.PG2]} ] + children = + if Application.get_env(:ueberauth, Ueberauth.Strategy.OIDC)[:default_oidc][:client_id], + do: [{OpenIDConnect.Worker, Application.get_env(:ueberauth, Ueberauth.Strategy.OIDC)} | children], + else: children + if Application.get_env(:sentry, :dsn) do {:ok, _} = Logger.add_backend(Sentry.LoggerBackend) end diff --git a/lib/accent/integrations/execute/aws_s3.ex b/lib/accent/integrations/execute/aws_s3.ex new file mode 100644 index 000000000..b5a206362 --- /dev/null +++ b/lib/accent/integrations/execute/aws_s3.ex @@ -0,0 +1,65 @@ +defmodule Accent.IntegrationManager.Execute.AWSS3 do + @moduledoc false + + alias Accent.Hook + + def upload_translations(integration, user, params) do + {uploads, version_tag} = Accent.IntegrationManager.Execute.UploadDocuments.all(integration, params) + + # To support bucket with '.' in the name, we need to use the region subdomain. + # The us-east-1 subdomain is not s3-us-east-1. It’s s3 only. + base_url = + case integration.data.aws_s3_region do + "us-east-1" -> "https://s3.amazonaws.com/#{integration.data.aws_s3_bucket}" + region -> "https://s3-#{region}.amazonaws.com/#{integration.data.aws_s3_bucket}" + end + + url = + Path.join([ + base_url, + integration.data.aws_s3_path_prefix + ]) + + uri = URI.parse(url) + + document_urls = + for upload <- uploads do + {url, document_name} = Accent.IntegrationManager.Execute.UploadDocuments.url(upload, uri, version_tag) + + headers = + :aws_signature.sign_v4( + integration.data.aws_s3_access_key_id, + integration.data.aws_s3_secret_access_key, + integration.data.aws_s3_region, + "s3", + :calendar.universal_time(), + "put", + url, + [ + {"host", uri.authority}, + {"x-amz-acl", "public-read"}, + {"x-amz-tagging", + "ACCENT_VERSION=#{Application.get_env(:accent, :version)}&USER_ID=#{user.id}&PROJECT_ID=#{integration.project_id}"} + ], + upload.render, + uri_encode_path: false + ) + + {:ok, %{status_code: 200}} = HTTPoison.put(url, {:file, upload.file}, headers) + + %{name: document_name, url: url} + end + + Hook.outbound(%Hook.Context{ + event: "integration_execute_azure_storage_container", + project_id: integration.project_id, + user_id: user.id, + payload: %{ + version_tag: version_tag, + document_urls: document_urls + } + }) + + :ok + end +end diff --git a/lib/accent/integrations/execute/azure_storage_container.ex b/lib/accent/integrations/execute/azure_storage_container.ex index 067087e56..24ea48405 100644 --- a/lib/accent/integrations/execute/azure_storage_container.ex +++ b/lib/accent/integrations/execute/azure_storage_container.ex @@ -1,95 +1,31 @@ defmodule Accent.IntegrationManager.Execute.AzureStorageContainer do @moduledoc false - alias Accent.Document - alias Accent.Repo - alias Accent.Revision - alias Accent.Scopes.Document, as: DocumentScope - alias Accent.Scopes.Revision, as: RevisionScope - alias Accent.Scopes.Translation, as: TranslationScope - alias Accent.Scopes.Version, as: VersionScope - alias Accent.Translation - alias Accent.Version + alias Accent.Hook - def upload_translations(integration, params) do - project = Repo.one!(Ecto.assoc(integration, :project)) - version = fetch_version(project, params) - documents = fetch_documents(project) - revisions = fetch_revisions(project) - master_revision = Repo.preload(Repo.one!(RevisionScope.master(Ecto.assoc(project, :revisions))), :language) + def upload_translations(integration, user, params) do + {uploads, version_tag} = Accent.IntegrationManager.Execute.UploadDocuments.all(integration, params) - uploads = - Enum.flat_map(documents, fn document -> - Enum.flat_map(revisions, fn revision -> - translations = fetch_translations(document, revision, version) + uri = URI.parse(integration.data.azure_storage_container_sas) - if Enum.any?(translations) do - render_options = %{ - translations: translations, - master_language: Revision.language(master_revision), - language: Revision.language(revision), - document: document - } + document_urls = + for upload <- uploads do + {url, document_name} = Accent.IntegrationManager.Execute.UploadDocuments.url(upload, uri, version_tag) + HTTPoison.put(url, {:file, upload.file}, [{"x-ms-blob-type", "BlockBlob"}]) - %{render: render} = Accent.TranslationsRenderer.render_translations(render_options) - [%{document: %{document | render: render}, language: Accent.Revision.language(revision)}] - else - [] - end - end) - end) + %{name: document_name, url: url} + end - for upload <- uploads do - file = Path.join([System.tmp_dir(), Accent.Utils.SecureRandom.urlsafe_base64(16)]) - :ok = File.write(file, upload.document.render) - - uri = URI.parse(integration.data.azure_storage_container_sas) - extension = Accent.DocumentFormat.extension_by_format(upload.document.format) - - path = - Path.join([ - uri.path, - (version && version.tag) || "latest", - upload.language.slug, - upload.document.path <> "." <> extension - ]) - - HTTPoison.put(URI.to_string(%{uri | path: path}), {:file, file}, [{"x-ms-blob-type", "BlockBlob"}]) - end + Hook.outbound(%Hook.Context{ + event: "integration_execute_azure_storage_container", + project_id: integration.project_id, + user_id: user.id, + payload: %{ + version_tag: version_tag, + document_urls: document_urls + } + }) :ok end - - defp fetch_version(project, %{target_version: :specific, tag: tag}) do - Version - |> VersionScope.from_project(project.id) - |> VersionScope.from_tag(tag) - |> Repo.one() - end - - defp fetch_version(_, _) do - nil - end - - defp fetch_documents(project) do - Document - |> DocumentScope.from_project(project.id) - |> Repo.all() - end - - defp fetch_revisions(project) do - Revision - |> RevisionScope.from_project(project.id) - |> Repo.all() - |> Repo.preload(:language) - end - - defp fetch_translations(document, revision, version) do - Translation - |> TranslationScope.active() - |> TranslationScope.from_document(document.id) - |> TranslationScope.from_revision(revision.id) - |> TranslationScope.from_version(version && version.id) - |> Repo.all() - end end diff --git a/lib/accent/integrations/execute/upload_documents.ex b/lib/accent/integrations/execute/upload_documents.ex new file mode 100644 index 000000000..c6c8722d7 --- /dev/null +++ b/lib/accent/integrations/execute/upload_documents.ex @@ -0,0 +1,106 @@ +defmodule Accent.IntegrationManager.Execute.UploadDocuments do + @moduledoc false + + alias Accent.Document + alias Accent.Repo + alias Accent.Revision + alias Accent.Scopes.Document, as: DocumentScope + alias Accent.Scopes.Revision, as: RevisionScope + alias Accent.Scopes.Translation, as: TranslationScope + alias Accent.Scopes.Version, as: VersionScope + alias Accent.Translation + alias Accent.Version + + def url(upload, uri, version_tag) do + extension = Accent.DocumentFormat.extension_by_format(upload.document.format) + document_name = upload.document.path <> "." <> extension + + path = + Path.join([ + uri.path || "/", + version_tag, + upload.language.slug, + document_name + ]) + + {URI.to_string(%{uri | path: path}), document_name} + end + + def all(integration, params) do + project = Repo.one!(Ecto.assoc(integration, :project)) + version = fetch_version(project, params) + documents = fetch_documents(project) + revisions = fetch_revisions(project) + + master_revision = + Repo.preload(Repo.one!(RevisionScope.master(Ecto.assoc(project, :revisions))), :language) + + version_tag = (version && version.tag) || "latest" + + uploads = + Enum.flat_map(documents, fn document -> + Enum.flat_map(revisions, fn revision -> + translations = fetch_translations(document, revision, version) + + if Enum.any?(translations) do + render_options = %{ + translations: translations, + master_language: Revision.language(master_revision), + language: Revision.language(revision), + document: document + } + + %{render: render} = Accent.TranslationsRenderer.render_translations(render_options) + file = Path.join([System.tmp_dir(), Accent.Utils.SecureRandom.urlsafe_base64(16)]) + :ok = File.write(file, render) + + [ + %{ + file: file, + render: render, + document: document, + language: Accent.Revision.language(revision) + } + ] + else + [] + end + end) + end) + + {uploads, version_tag} + end + + defp fetch_version(project, %{target_version: :specific, tag: tag}) do + Version + |> VersionScope.from_project(project.id) + |> VersionScope.from_tag(tag) + |> Repo.one() + end + + defp fetch_version(_, _) do + nil + end + + defp fetch_documents(project) do + Document + |> DocumentScope.from_project(project.id) + |> Repo.all() + end + + defp fetch_revisions(project) do + Revision + |> RevisionScope.from_project(project.id) + |> Repo.all() + |> Repo.preload(:language) + end + + defp fetch_translations(document, revision, version) do + Translation + |> TranslationScope.active() + |> TranslationScope.from_document(document.id) + |> TranslationScope.from_revision(revision.id) + |> TranslationScope.from_version(version && version.id) + |> Repo.all() + end +end diff --git a/lib/accent/integrations/integration_manager.ex b/lib/accent/integrations/integration_manager.ex index 5d7504cfd..5c4194b16 100644 --- a/lib/accent/integrations/integration_manager.ex +++ b/lib/accent/integrations/integration_manager.ex @@ -23,7 +23,7 @@ defmodule Accent.IntegrationManager do @spec execute(Integration.t(), User.t(), map()) :: {:ok, Integration.t()} def execute(integration, user, params) do - case execute_integration(integration, params) do + case execute_integration(integration, user, params) do :ok -> integration |> change(%{last_executed_at: DateTime.utc_now(), last_executed_by_user_id: user.id}) @@ -45,22 +45,33 @@ defmodule Accent.IntegrationManager do defp changeset(model, params) do model |> cast(params, [:project_id, :user_id, :service, :events]) - |> validate_inclusion(:service, ~w(slack github discord azure_storage_container)) + |> validate_inclusion(:service, ~w(slack github discord azure_storage_container aws_s3)) |> cast_embed(:data, with: changeset_data(params[:service] || model.service)) |> foreign_key_constraint(:project_id) |> validate_required([:service, :data]) end - defp execute_integration(%{service: "azure_storage_container"} = integration, params) do + defp execute_integration(%{service: "azure_storage_container"} = integration, user, params) do Accent.IntegrationManager.Execute.AzureStorageContainer.upload_translations( integration, + user, params[:azure_storage_container] ) :ok end - defp execute_integration(_integration, _params) do + defp execute_integration(%{service: "aws_s3"} = integration, user, params) do + Accent.IntegrationManager.Execute.AWSS3.upload_translations( + integration, + user, + params[:aws_s3] + ) + + :ok + end + + defp execute_integration(_integration, _user, _params) do :noop end @@ -88,6 +99,26 @@ defmodule Accent.IntegrationManager do end end + defp changeset_data("aws_s3") do + fn model, params -> + model + |> cast(params, [ + :aws_s3_bucket, + :aws_s3_path_prefix, + :aws_s3_region, + :aws_s3_access_key_id, + :aws_s3_secret_access_key + ]) + |> validate_required([ + :aws_s3_bucket, + :aws_s3_path_prefix, + :aws_s3_region, + :aws_s3_access_key_id, + :aws_s3_secret_access_key + ]) + end + end + defp changeset_data(_) do fn model, params -> cast(model, params, []) end end diff --git a/lib/accent/projects/project_deleter.ex b/lib/accent/projects/project_deleter.ex index 86855b3f9..d1de403c2 100644 --- a/lib/accent/projects/project_deleter.ex +++ b/lib/accent/projects/project_deleter.ex @@ -1,5 +1,8 @@ defmodule Accent.ProjectDeleter do @moduledoc false + import Ecto.Query, only: [from: 2] + + alias Accent.Operation alias Accent.Repo def delete(project: project) do @@ -7,6 +10,17 @@ defmodule Accent.ProjectDeleter do |> Ecto.assoc(:all_collaborators) |> Repo.delete_all() + Repo.transaction(fn -> + Repo.delete_all( + from(operations in Operation, + inner_join: revisions in assoc(operations, :revision), + where: revisions.project_id == ^project.id + ) + ) + + Repo.delete_all(from(operations in Operation, where: operations.project_id == ^project.id)) + end) + {:ok, project} end end diff --git a/lib/accent/prompt_config/prompt_config_manager.ex b/lib/accent/prompt_config/prompt_config_manager.ex index 3c6e8c12b..3a405f466 100644 --- a/lib/accent/prompt_config/prompt_config_manager.ex +++ b/lib/accent/prompt_config/prompt_config_manager.ex @@ -11,7 +11,8 @@ defmodule Accent.PromptConfigManager do "config" => %{ "key" => params[:config_key] }, - "provider" => params[:provider] + "provider" => params[:provider], + "use_platform" => params[:use_platform] } } diff --git a/lib/accent/schemas/integration.ex b/lib/accent/schemas/integration.ex index 0abb689f4..d0b24ba18 100644 --- a/lib/accent/schemas/integration.ex +++ b/lib/accent/schemas/integration.ex @@ -10,6 +10,11 @@ defmodule Accent.Integration do embeds_one(:data, IntegrationData, on_replace: :update) do field(:url) field(:azure_storage_container_sas) + field(:aws_s3_bucket) + field(:aws_s3_path_prefix) + field(:aws_s3_region) + field(:aws_s3_access_key_id) + field(:aws_s3_secret_access_key) end belongs_to(:project, Accent.Project) diff --git a/lib/accent/schemas/version.ex b/lib/accent/schemas/version.ex index 4345e758f..18ffb1404 100644 --- a/lib/accent/schemas/version.ex +++ b/lib/accent/schemas/version.ex @@ -6,6 +6,7 @@ defmodule Accent.Version do field(:name, :string) field(:tag, :string) field(:parsed_tag, :any, virtual: true) + field(:copy_on_update_translation, :boolean) belongs_to(:user, Accent.User) belongs_to(:project, Accent.Project) @@ -17,10 +18,11 @@ defmodule Accent.Version do end @required_fields ~w(project_id user_id name tag)a + @optional_fields ~w(copy_on_update_translation)a def changeset(model, params) do model - |> cast(params, @required_fields) + |> cast(params, @required_fields ++ @optional_fields) |> validate_required(@required_fields) |> unique_constraint(:tag, name: :versions_tag_project_id_index) end diff --git a/lib/accent/scopes/operation.ex b/lib/accent/scopes/operation.ex index 937f1a2fd..06be34e4a 100644 --- a/lib/accent/scopes/operation.ex +++ b/lib/accent/scopes/operation.ex @@ -39,11 +39,19 @@ defmodule Accent.Scopes.Operation do Accent.Operation iex> Accent.Scopes.Operation.filter_from_project(Accent.Operation, "test") #Ecto.Query + iex> Accent.Scopes.Operation.filter_from_project(Accent.Operation, "test", "sync") + #Ecto.Query """ - @spec filter_from_project(Ecto.Queryable.t(), String.t() | nil) :: Ecto.Queryable.t() - def filter_from_project(query, nil), do: query + @spec filter_from_project(Ecto.Queryable.t(), String.t() | nil, String.t() | nil) :: Ecto.Queryable.t() + def filter_from_project(query, project_id, action \\ nil) + def filter_from_project(query, nil, _), do: query - def filter_from_project(query, project_id) do + def filter_from_project(query, project_id, action) + when action in ~w(sync batch_sync batch_merge create_version document_delete merge new_slave version_new) do + from(query, where: [project_id: ^project_id]) + end + + def filter_from_project(query, project_id, _) do from(o in query, left_join: r in assoc(o, :revision), where: r.project_id == ^project_id or o.project_id == ^project_id diff --git a/lib/accent/scopes/translation.ex b/lib/accent/scopes/translation.ex index 29537da5f..08eb1b20b 100644 --- a/lib/accent/scopes/translation.ex +++ b/lib/accent/scopes/translation.ex @@ -421,23 +421,4 @@ defmodule Accent.Scopes.Translation do _ -> query end end - - @doc """ - ## Examples - - iex> Accent.Scopes.Translation.select_key_text(Accent.Translation) - #Ecto.Query - """ - @spec select_key_text(Queryable.t()) :: Queryable.t() - def select_key_text(query) do - from( - translation in query, - select: %{ - id: translation.id, - key: translation.key, - updated_at: translation.updated_at, - corrected_text: translation.corrected_text - } - ) - end end diff --git a/lib/accent/telemetry_ui/ecto_psql_extras.ex b/lib/accent/telemetry_ui/ecto_psql_extras.ex index 833bcf800..16917a604 100644 --- a/lib/accent/telemetry_ui/ecto_psql_extras.ex +++ b/lib/accent/telemetry_ui/ecto_psql_extras.ex @@ -4,25 +4,17 @@ defmodule Accent.TelemetryUI.EctoPSQLExtras do @queries [ bloat: EctoPSQLExtras.Bloat, - blocking: EctoPSQLExtras.Blocking, cache_hit: EctoPSQLExtras.CacheHit, + connections: EctoPSQLExtras.Connections, table_cache_hit: EctoPSQLExtras.TableCacheHit, index_cache_hit: EctoPSQLExtras.IndexCacheHit, index_size: EctoPSQLExtras.IndexSize, index_usage: EctoPSQLExtras.IndexUsage, - locks: EctoPSQLExtras.Locks, - all_locks: EctoPSQLExtras.AllLocks, - long_running_queries: EctoPSQLExtras.LongRunningQueries, records_rank: EctoPSQLExtras.RecordsRank, - seq_scans: EctoPSQLExtras.SeqScans, - table_indexes_size: EctoPSQLExtras.TableIndexesSize, table_size: EctoPSQLExtras.TableSize, - total_index_size: EctoPSQLExtras.TotalIndexSize, + table_indexes_size: EctoPSQLExtras.TableIndexesSize, total_table_size: EctoPSQLExtras.TotalTableSize, - unused_indexes: EctoPSQLExtras.UnusedIndexes, - duplicate_indexes: EctoPSQLExtras.DuplicateIndexes, - null_indexes: EctoPSQLExtras.NullIndexes, - vacuum_stats: EctoPSQLExtras.VacuumStats + unused_indexes: EctoPSQLExtras.UnusedIndexes ] def all(repo), do: Enum.map(Keyword.keys(@queries), &new(repo, &1)) @@ -51,7 +43,7 @@ defmodule Accent.TelemetryUI.EctoPSQLExtras do Enum.map(result.rows, &parse_row(&1, types)) end - TableRex.quick_render!(rows, names) + {rows, names} end defp parse_row(list, types) do @@ -102,13 +94,39 @@ defmodule Accent.TelemetryUI.EctoPSQLExtras do end def to_html(metric, _assigns) do + {rows, names} = metric.data + + names = + Enum.map_join(names, "", fn name -> + "" <> + to_string(name) <> "" + end) + + rows = + for cells <- rows do + "
" <> + Enum.map_join(cells, "", fn cell -> + "" <> + cell <> "" + end) <> "
" + end + {:safe, """
-

#{metric.title}

+

#{metric.title}

-
#{metric.data}
+ + + + #{names} + + + + #{rows} + +
"""} end diff --git a/lib/graphql/mutations/integration.ex b/lib/graphql/mutations/integration.ex index b25289b8f..48ac89d07 100644 --- a/lib/graphql/mutations/integration.ex +++ b/lib/graphql/mutations/integration.ex @@ -12,15 +12,30 @@ defmodule Accent.GraphQL.Mutations.Integration do value(:latest) end + enum :project_integration_execute_aws_s3_target_version do + value(:specific) + value(:latest) + end + input_object :project_integration_execute_azure_storage_container_input do field(:target_version, :project_integration_execute_azure_storage_container_target_version) field(:tag, :string) end + input_object :project_integration_execute_aws_s3_input do + field(:target_version, :project_integration_execute_aws_s3_target_version) + field(:tag, :string) + end + input_object :project_integration_data_input do field(:id, :id) field(:url, :string) field(:azure_storage_container_sas, :string) + field(:aws_s3_region, :string) + field(:aws_s3_bucket, :string) + field(:aws_s3_path_prefix, :string) + field(:aws_s3_access_key_id, :string) + field(:aws_s3_secret_access_key, :string) end payload_object(:project_integration_payload, :project_integration) @@ -39,6 +54,7 @@ defmodule Accent.GraphQL.Mutations.Integration do field :execute_project_integration, :project_integration_payload do arg(:id, non_null(:id)) arg(:azure_storage_container, :project_integration_execute_azure_storage_container_input) + arg(:aws_s3, :project_integration_execute_aws_s3_input) resolve(integration_authorize(:execute_project_integration, &IntegrationResolver.execute/3)) middleware(&build_payload/2) diff --git a/lib/graphql/mutations/prompt.ex b/lib/graphql/mutations/prompt.ex index 52342cc13..b6a52a595 100644 --- a/lib/graphql/mutations/prompt.ex +++ b/lib/graphql/mutations/prompt.ex @@ -42,6 +42,7 @@ defmodule Accent.GraphQL.Mutations.Prompt do arg(:project_id, non_null(:id)) arg(:provider, non_null(:string)) arg(:config_key, :string) + arg(:use_platform, non_null(:boolean)) resolve(project_authorize(:save_project_prompt_config, &Resolver.save_config/3, :project_id)) end diff --git a/lib/graphql/mutations/version.ex b/lib/graphql/mutations/version.ex index 05564f8a8..78a4f3ce9 100644 --- a/lib/graphql/mutations/version.ex +++ b/lib/graphql/mutations/version.ex @@ -9,6 +9,7 @@ defmodule Accent.GraphQL.Mutations.Version do arg(:project_id, non_null(:id)) arg(:name, non_null(:string)) arg(:tag, non_null(:string)) + arg(:copy_on_update_translation, non_null(:boolean)) resolve(project_authorize(:create_version, &Accent.GraphQL.Resolvers.Version.create/3, :project_id)) end @@ -17,6 +18,7 @@ defmodule Accent.GraphQL.Mutations.Version do arg(:id, non_null(:id)) arg(:name, non_null(:string)) arg(:tag, non_null(:string)) + arg(:copy_on_update_translation, non_null(:boolean)) resolve(version_authorize(:update_version, &Accent.GraphQL.Resolvers.Version.update/3)) end diff --git a/lib/graphql/paginated.ex b/lib/graphql/paginated.ex index 84d10cbc5..995276070 100644 --- a/lib/graphql/paginated.ex +++ b/lib/graphql/paginated.ex @@ -15,8 +15,8 @@ defmodule Accent.GraphQL.Paginated do @enforce_keys [:entries, :meta] defstruct entries: [], meta: %{} - def paginate(query, args) do - Accent.Repo.paginate(query, page: args[:page], page_size: args[:page_size]) + def paginate(query, args, options \\ []) do + Accent.Repo.paginate(query, page: args[:page], page_size: args[:page_size], options: options) end def format(paginated_list) do diff --git a/lib/graphql/resolvers/integration.ex b/lib/graphql/resolvers/integration.ex index f946fa10d..c1672a9a9 100644 --- a/lib/graphql/resolvers/integration.ex +++ b/lib/graphql/resolvers/integration.ex @@ -6,6 +6,10 @@ defmodule Accent.GraphQL.Resolvers.Integration do alias Accent.IntegrationManager alias Accent.Plugs.GraphQLContext alias Accent.Project + alias Accent.Repo + alias Accent.Scopes.Integration, as: IntegrationScope + + require Ecto.Query @typep integration_operation :: Accent.GraphQL.Response.t() @@ -38,4 +42,13 @@ defmodule Accent.GraphQL.Resolvers.Integration do |> IntegrationManager.delete() |> build() end + + @spec list_project(Project.t(), map(), GraphQLContext.t()) :: {:ok, [Integration.t()]} + def list_project(project, _args, _) do + Integration + |> IntegrationScope.from_project(project.id) + |> Ecto.Query.order_by(desc: :inserted_at) + |> Repo.all() + |> then(&{:ok, &1}) + end end diff --git a/lib/graphql/resolvers/project.ex b/lib/graphql/resolvers/project.ex index eeed1e094..b91a30c17 100644 --- a/lib/graphql/resolvers/project.ex +++ b/lib/graphql/resolvers/project.ex @@ -62,7 +62,7 @@ defmodule Accent.GraphQL.Resolvers.Project do "name" => args.name, "main_color" => args.main_color, "logo" => args.logo, - "locked_file_operations" => args.is_file_operations_locked + "locked_file_operations" => args.is_file_operations_locked || false } case ProjectUpdater.update( @@ -85,9 +85,8 @@ defmodule Accent.GraphQL.Resolvers.Project do Project |> Query.join(:inner, [p], c in assoc(p, :collaborators)) |> Query.where([_, c], c.user_id == ^viewer.id) - |> Query.order_by([p, _], asc: p.name) + |> Query.order_by([p, _], desc_nulls_first: p.last_synced_at) |> ProjectScope.from_search(args[:query]) - |> ProjectScope.with_stats() |> Paginated.paginate(args) |> Paginated.format() @@ -96,7 +95,6 @@ defmodule Accent.GraphQL.Resolvers.Project do |> Query.join(:inner, [p], c in assoc(p, :collaborators)) |> Query.where([_, c], c.user_id == ^viewer.id) |> ProjectScope.from_ids(args[:node_ids]) - |> ProjectScope.with_stats() |> Repo.all() projects = Map.put(paginated_projects, :nodes, nodes_projects) @@ -115,8 +113,8 @@ defmodule Accent.GraphQL.Resolvers.Project do @spec last_activity(Project.t(), any(), GraphQLContext.t()) :: {:ok, Operation.t() | nil} def last_activity(project, args, _) do Operation - |> OperationScope.filter_from_project(project.id) |> OperationScope.filter_from_action(args[:action]) + |> OperationScope.filter_from_project(project.id, args[:action]) |> OperationScope.order_last_to_first() |> Query.limit(1) |> Repo.one() diff --git a/lib/graphql/resolvers/revision.ex b/lib/graphql/resolvers/revision.ex index 06053ee63..90bace358 100644 --- a/lib/graphql/resolvers/revision.ex +++ b/lib/graphql/resolvers/revision.ex @@ -113,7 +113,7 @@ defmodule Accent.GraphQL.Resolvers.Revision do end @spec show_project(Project.t(), %{id: String.t()}, GraphQLContext.t()) :: {:ok, Revision.t() | nil} - def show_project(project, %{id: id} = args, _) do + def show_project(project, %{id: id} = args, _) when not is_nil(id) do Revision |> RevisionScope.from_project(project.id) |> RevisionScope.with_stats(version_id: args[:version_id]) diff --git a/lib/graphql/resolvers/translation.ex b/lib/graphql/resolvers/translation.ex index 31968b8ed..31190c1d9 100644 --- a/lib/graphql/resolvers/translation.ex +++ b/lib/graphql/resolvers/translation.ex @@ -1,5 +1,8 @@ defmodule Accent.GraphQL.Resolvers.Translation do @moduledoc false + import Absinthe.Resolution.Helpers, only: [batch: 3] + + alias Accent.Document alias Accent.GraphQL.Paginated alias Accent.Plugs.GraphQLContext alias Accent.Project @@ -27,6 +30,59 @@ defmodule Accent.GraphQL.Resolvers.Translation do |> then(&{:ok, &1}) end + def batch_translation_ids(grouped_translation, _args, _resolution) do + ids = Enum.reject(grouped_translation.translation_ids, &is_nil/1) + + batch( + {__MODULE__, :from_translation_ids}, + ids, + fn batch_results -> + translations = + Map.get(batch_results, {grouped_translation.key, grouped_translation.document_id}, []) + + translations = + Enum.sort(translations, fn a, b -> + cond do + a.revision.master == true -> true + DateTime.compare(a.revision.inserted_at, b.revision.inserted_at) === :lt -> true + true -> false + end + end) + + {:ok, translations} + end + ) + end + + def from_translation_ids(_, ids) do + ids = Enum.map(List.flatten(ids), &Ecto.UUID.cast!(&1)) + + query = + Query.from(translations in Translation, + preload: [:revision], + where: translations.id in ^ids + ) + + query + |> Repo.all() + |> Enum.group_by(&{&1.key, &1.document_id}) + end + + def batch_document(grouped_translation, _args, _resolution) do + batch({__MODULE__, :from_document_id}, grouped_translation.document_id, fn batch_results -> + [document | _] = Map.get(batch_results, grouped_translation.document_id) + {:ok, document} + end) + end + + def from_document_id(_, ids) do + query = Query.from(documents in Document, where: documents.id in ^ids) + + query + |> Repo.all() + |> Enum.group_by(& &1.id) + end + @spec correct(Translation.t(), %{text: String.t()}, GraphQLContext.t()) :: translation_operation def correct(translation, %{text: text}, info) do %Context{} @@ -124,12 +180,29 @@ defmodule Accent.GraphQL.Resolvers.Translation do translations = Translation |> list(args, project.id) - |> TranslationScope.from_project(project.id) |> Paginated.paginate(args) {:ok, Paginated.format(translations)} end + @spec list_grouped_project(Project.t(), map(), GraphQLContext.t()) :: {:ok, Paginated.t(Translation.t())} + def list_grouped_project(project, args, _) do + total_entries = + Translation + |> list_grouped_count(args, project.id) + |> Repo.all() + |> Enum.count() + + translations = + Translation + |> list_grouped(args, project.id) + |> Paginated.paginate(args, total_entries: total_entries) + + revisions = grouped_related_revisions(Map.put(args, :project_id, project.id)) + + {:ok, Map.put(Paginated.format(translations), :revisions, revisions)} + end + @spec related_translations(Translation.t(), map(), struct()) :: {:ok, [Translation.t()]} def related_translations(translation, _, _) do translations = @@ -179,7 +252,112 @@ defmodule Accent.GraphQL.Resolvers.Translation do end end + defp grouped_related_revisions(args) do + query_revision_ids = + if Enum.empty?(args[:related_revisions]) do + Query.from( + revisions in Revision, + where: revisions.project_id == ^args[:project_id], + order_by: [asc: :inserted_at], + limit: 2 + ) + else + Query.from( + revisions in Revision, + where: revisions.id in ^args[:related_revisions], + order_by: [asc: :inserted_at], + limit: 2 + ) + end + + Repo.all(query_revision_ids) + end + + defp grouped_related_query(schema, args, project_id) do + revision_ids = + if Enum.empty?(args[:related_revisions]) do + Enum.map(grouped_related_revisions(Map.put(args, :project_id, project_id)), & &1.id) + else + args[:related_revisions] + end + + query = + schema + |> TranslationScope.from_version(args[:version]) + |> TranslationScope.from_project(project_id) + |> TranslationScope.from_revisions(revision_ids) + |> TranslationScope.active() + |> TranslationScope.not_locked() + + {query, revision_ids} + end + + defp list_grouped_count(schema, args, project_id) do + query = list_base_query(schema, args, project_id) + {related_query, revision_ids} = grouped_related_query(schema, args, project_id) + + query = + Query.from( + translations in query, + left_join: related_translations in subquery(related_query), + as: :related_translations, + on: + related_translations.revision_id in ^revision_ids and + related_translations.key == translations.key and + related_translations.document_id == translations.document_id, + distinct: [translations.key, translations.document_id], + select: translations.key, + group_by: [translations.key, translations.document_id] + ) + + if args[:is_conflicted] do + Query.from([related_translations: related_translations] in query, + having: fragment("array_agg(distinct(?))", related_translations.conflicted) != [false] + ) + else + query + end + end + + defp list_grouped(schema, args, project_id) do + query = list_base_query(schema, args, project_id) + {related_query, revision_ids} = grouped_related_query(schema, args, project_id) + + query = + Query.from( + translations in query, + left_join: related_translations in subquery(related_query), + as: :related_translations, + on: + related_translations.revision_id in ^revision_ids and + related_translations.key == translations.key and + related_translations.document_id == translations.document_id, + distinct: translations.key, + select: %{ + key: translations.key, + document_id: translations.document_id, + translation_ids: fragment("array_agg(distinct(?))", related_translations.id) + }, + group_by: [translations.key, translations.document_id] + ) + + if args[:is_conflicted] do + Query.from([related_translations: related_translations] in query, + having: fragment("array_agg(distinct(?))", related_translations.conflicted) != [false] + ) + else + query + end + end + defp list(schema, args, project_id) do + schema + |> list_base_query(args, project_id) + |> Query.distinct(true) + |> Query.preload(:revision) + end + + defp list_base_query(schema, args, project_id) do schema |> TranslationScope.active() |> TranslationScope.not_locked() @@ -193,7 +371,6 @@ defmodule Accent.GraphQL.Resolvers.Translation do |> TranslationScope.parse_empty(args[:is_text_empty]) |> TranslationScope.parse_commented_on(args[:is_commented_on]) |> TranslationScope.from_version(args[:version]) - |> Query.distinct(true) - |> Query.preload(:revision) + |> TranslationScope.from_project(project_id) end end diff --git a/lib/graphql/resolvers/version.ex b/lib/graphql/resolvers/version.ex index 8b7911287..4c4553e08 100644 --- a/lib/graphql/resolvers/version.ex +++ b/lib/graphql/resolvers/version.ex @@ -13,12 +13,17 @@ defmodule Accent.GraphQL.Resolvers.Version do @typep version_operation :: {:ok, %{version: Version.t() | nil, errors: [String.t()] | nil}} - @spec create(Project.t(), %{name: String.t(), tag: String.t()}, GraphQLContext.t()) :: version_operation - def create(project, %{name: name, tag: tag}, info) do + @spec create( + Project.t(), + %{name: String.t(), tag: String.t(), copy_on_update_translation: boolean()}, + GraphQLContext.t() + ) :: version_operation + def create(project, args, info) do %Context{} |> Context.assign(:project, project) - |> Context.assign(:name, name) - |> Context.assign(:tag, tag) + |> Context.assign(:name, args[:name]) + |> Context.assign(:tag, args[:tag]) + |> Context.assign(:copy_on_update_translation, args[:copy_on_update_translation]) |> Context.assign(:user_id, info.context[:conn].assigns[:current_user].id) |> NewVersionBuilder.build() |> NewVersionPersister.persist() @@ -31,10 +36,18 @@ defmodule Accent.GraphQL.Resolvers.Version do end end - @spec update(Version.t(), %{name: String.t(), tag: String.t()}, GraphQLContext.t()) :: version_operation + @spec update( + Version.t(), + %{name: String.t(), tag: String.t(), copy_on_update_translation: boolean()}, + GraphQLContext.t() + ) :: version_operation def update(version, args, _info) do version - |> Version.changeset(%{name: args[:name], tag: args[:tag]}) + |> Version.changeset(%{ + name: args[:name], + tag: args[:tag], + copy_on_update_translation: args[:copy_on_update_translation] || false + }) |> Repo.update() |> case do {:ok, version} -> diff --git a/lib/graphql/schema.ex b/lib/graphql/schema.ex index 86f1e2a5c..b298b0c7f 100644 --- a/lib/graphql/schema.ex +++ b/lib/graphql/schema.ex @@ -30,10 +30,12 @@ defmodule Accent.GraphQL.Schema do import_types(Accent.GraphQL.Types.MutationResult) import_types(Accent.GraphQL.Types.Lint) + @version Application.compile_env!(:accent, :version) + object :application do field(:version, :string, resolve: fn _, _ -> - {:ok, "1.2.3"} + {:ok, @version} end ) end diff --git a/lib/graphql/types/integration.ex b/lib/graphql/types/integration.ex index 075a7f186..2b1606291 100644 --- a/lib/graphql/types/integration.ex +++ b/lib/graphql/types/integration.ex @@ -7,6 +7,7 @@ defmodule Accent.GraphQL.Types.Integration do value(:discord, as: "discord") value(:github, as: "github") value(:azure_storage_container, as: "azure_storage_container") + value(:aws_s3, as: "aws_s3") end enum :project_integration_event do @@ -15,6 +16,8 @@ defmodule Accent.GraphQL.Types.Integration do value(:complete_review, as: "complete_review") value(:create_collaborator, as: "create_collaborator") value(:create_comment, as: "create_comment") + value(:integration_execute_azure_storage_container, as: "integration_execute_azure_storage_container") + value(:integration_execute_aws_s3, as: "integration_execute_aws_s3") end interface :project_integration do @@ -26,6 +29,7 @@ defmodule Accent.GraphQL.Types.Integration do %{service: "slack"}, _ -> :project_integration_slack %{service: "github"}, _ -> :project_integration_github %{service: "azure_storage_container"}, _ -> :project_integration_azure_storage_container + %{service: "aws_s3"}, _ -> :project_integration_aws_s3 end) end @@ -60,7 +64,16 @@ defmodule Accent.GraphQL.Types.Integration do field(:id, non_null(:id)) field(:service, non_null(:project_integration_service)) field(:last_executed_at, :datetime) - field(:data, non_null(:project_integration_azure_data)) + field(:data, non_null(:project_integration_azure_storage_container_data)) + + interfaces([:project_integration]) + end + + object :project_integration_aws_s3 do + field(:id, non_null(:id)) + field(:service, non_null(:project_integration_service)) + field(:last_executed_at, :datetime) + field(:data, non_null(:project_integration_aws_s3_data)) interfaces([:project_integration]) end @@ -74,7 +87,7 @@ defmodule Accent.GraphQL.Types.Integration do field(:id, non_null(:id)) end - object :project_integration_azure_data do + object :project_integration_azure_storage_container_data do field(:id, non_null(:id)) field(:sas_base_url, non_null(:string), @@ -85,4 +98,12 @@ defmodule Accent.GraphQL.Types.Integration do end ) end + + object :project_integration_aws_s3_data do + field(:id, non_null(:id)) + field(:bucket, non_null(:string), resolve: fn data, _, _ -> {:ok, data.aws_s3_bucket} end) + field(:path_prefix, non_null(:string), resolve: fn data, _, _ -> {:ok, data.aws_s3_path_prefix} end) + field(:region, non_null(:string), resolve: fn data, _, _ -> {:ok, data.aws_s3_region} end) + field(:access_key_id, non_null(:string), resolve: fn data, _, _ -> {:ok, data.aws_s3_access_key_id} end) + end end diff --git a/lib/graphql/types/project.ex b/lib/graphql/types/project.ex index 4184647d3..2e866bc28 100644 --- a/lib/graphql/types/project.ex +++ b/lib/graphql/types/project.ex @@ -6,6 +6,8 @@ defmodule Accent.GraphQL.Types.Project do import Accent.GraphQL.Helpers.Authorization import Accent.GraphQL.Helpers.Fields + alias Accent.GraphQL.Resolvers.Translation, as: TranslationResolver + object :projects do field(:meta, non_null(:pagination_meta)) field(:entries, list_of(:project)) @@ -27,6 +29,8 @@ defmodule Accent.GraphQL.Types.Project do object :prompt_config do field(:provider, non_null(:string)) + field(:use_platform, non_null(:boolean)) + field(:use_config_key, non_null(:boolean)) end object :project do @@ -48,7 +52,7 @@ defmodule Accent.GraphQL.Types.Project do %{ provider: project.machine_translations_config["provider"], enabled_actions: project.machine_translations_config["enabled_actions"] || [], - use_platform: project.machine_translations_config["use_platform"], + use_platform: project.machine_translations_config["use_platform"] || false, use_config_key: not is_nil(project.machine_translations_config["config"]["key"]) }} else @@ -62,7 +66,9 @@ defmodule Accent.GraphQL.Types.Project do if project.prompt_config do {:ok, %{ - provider: project.prompt_config["provider"] + provider: project.prompt_config["provider"], + use_platform: project.prompt_config["use_platform"] || false, + use_config_key: not is_nil(project.prompt_config["config"]["key"]) }} else {:ok, nil} @@ -119,7 +125,10 @@ defmodule Accent.GraphQL.Types.Project do end field(:language, :language, resolve: dataloader(Accent.Language)) - field(:integrations, list_of(:project_integration), resolve: dataloader(Accent.Integration)) + + field :integrations, list_of(non_null(:project_integration)) do + resolve(project_authorize(:index_project_integrations, &Accent.GraphQL.Resolvers.Integration.list_project/3)) + end field :document, :document do arg(:id, non_null(:id)) @@ -135,13 +144,14 @@ defmodule Accent.GraphQL.Types.Project do resolve(project_authorize(:index_documents, &Accent.GraphQL.Resolvers.Document.list_project/3)) end - field :translations, :translations do + field :grouped_translations, :grouped_translations do arg(:page, :integer) arg(:page_size, :integer) - arg(:order, :string) arg(:document, :id) arg(:version, :id) + arg(:related_revisions, list_of(non_null(:id))) arg(:query, :string) + arg(:is_translated, :boolean) arg(:is_conflicted, :boolean) arg(:is_text_empty, :boolean) arg(:is_text_not_empty, :boolean) @@ -151,11 +161,28 @@ defmodule Accent.GraphQL.Types.Project do resolve( project_authorize( :index_translations, - &Accent.GraphQL.Resolvers.Translation.list_project/3 + &TranslationResolver.list_grouped_project/3 ) ) end + field :translations, :translations do + arg(:page, :integer) + arg(:page_size, :integer) + arg(:order, :string) + arg(:document, :id) + arg(:version, :id) + arg(:query, :string) + arg(:is_translated, :boolean) + arg(:is_conflicted, :boolean) + arg(:is_text_empty, :boolean) + arg(:is_text_not_empty, :boolean) + arg(:is_added_last_sync, :boolean) + arg(:is_commented_on, :boolean) + + resolve(project_authorize(:index_translations, &TranslationResolver.list_project/3)) + end + field :activities, :activities do arg(:page, :integer) arg(:page_size, :integer) @@ -182,7 +209,7 @@ defmodule Accent.GraphQL.Types.Project do field :translation, :translation do arg(:id, non_null(:id)) - resolve(project_authorize(:show_translation, &Accent.GraphQL.Resolvers.Translation.show_project/3)) + resolve(project_authorize(:show_translation, &TranslationResolver.show_project/3)) end field :activity, :activity do @@ -200,6 +227,7 @@ defmodule Accent.GraphQL.Types.Project do field :revisions, list_of(:revision) do arg(:version_id, :id) + resolve(project_authorize(:index_revisions, &Accent.GraphQL.Resolvers.Revision.list_project/3)) end diff --git a/lib/graphql/types/translation.ex b/lib/graphql/types/translation.ex index 04f884dac..e3a216e65 100644 --- a/lib/graphql/types/translation.ex +++ b/lib/graphql/types/translation.ex @@ -18,6 +18,15 @@ defmodule Accent.GraphQL.Types.Translation do value(:float, as: "float") end + object :grouped_translation do + field(:key, non_null(:string)) + field(:document, non_null(:document), resolve: &Accent.GraphQL.Resolvers.Translation.batch_document/3) + + field(:translations, non_null(list_of(non_null(:translation))), + resolve: &Accent.GraphQL.Resolvers.Translation.batch_translation_ids/3 + ) + end + object :translation do field(:id, non_null(:id)) field(:key, non_null(:string), resolve: &Accent.GraphQL.Resolvers.Translation.key/3) @@ -119,4 +128,10 @@ defmodule Accent.GraphQL.Types.Translation do field(:meta, :pagination_meta) field(:entries, list_of(:translation)) end + + object :grouped_translations do + field(:meta, :pagination_meta) + field(:entries, list_of(:grouped_translation)) + field(:revisions, non_null(list_of(non_null(:revision)))) + end end diff --git a/lib/graphql/types/version.ex b/lib/graphql/types/version.ex index 37a34e03a..0f554dea6 100644 --- a/lib/graphql/types/version.ex +++ b/lib/graphql/types/version.ex @@ -10,6 +10,7 @@ defmodule Accent.GraphQL.Types.Version do field(:tag, non_null(:string)) field(:project, :project, resolve: dataloader(Accent.Project)) field(:user, :user, resolve: dataloader(Accent.User)) + field(:copy_on_update_translation, non_null(:boolean)) field(:inserted_at, non_null(:datetime)) end diff --git a/lib/hook/event.ex b/lib/hook/event.ex new file mode 100644 index 000000000..319190002 --- /dev/null +++ b/lib/hook/event.ex @@ -0,0 +1,6 @@ +defmodule Accent.Hook.Event do + @moduledoc false + @callback name :: String.t() + @callback triggered?(args :: map(), new_state :: map()) :: boolean() + @callback payload(args :: map(), new_state :: map()) :: map() +end diff --git a/lib/hook/events.ex b/lib/hook/events.ex new file mode 100644 index 000000000..2d930c473 --- /dev/null +++ b/lib/hook/events.ex @@ -0,0 +1,24 @@ +defmodule Accent.Hook.Events do + @moduledoc false + path_wildcard = Path.join(Path.dirname(__ENV__.file), "events/*.ex") + paths = Path.wildcard(path_wildcard) + paths_hash = :erlang.md5(paths) + + @callback registered_events :: [String.t()] | :all + + event_modules = + for name <- paths do + Module.concat(__MODULE__, Phoenix.Naming.camelize(Path.basename(name, ".ex"))) + end + + @event_modules event_modules + + def available do + @event_modules + end + + def __mix_recompile__? do + paths = Path.wildcard(unquote(path_wildcard)) + :erlang.md5(paths) != unquote(paths_hash) + end +end diff --git a/lib/hook/events/add_translations.ex b/lib/hook/events/add_translations.ex new file mode 100644 index 000000000..21d6f0706 --- /dev/null +++ b/lib/hook/events/add_translations.ex @@ -0,0 +1,23 @@ +defmodule Accent.Hook.Events.AddTranslations do + @moduledoc false + @behaviour Accent.Hook.Event + + alias Movement.Persisters.ProjectHookWorker + + @impl true + def name do + "add_translations" + end + + @impl true + def triggered?(%ProjectHookWorker.Args{} = args, _new_state) do + args.batch_action === "merge" and args.operations_count > 0 + end + + @impl true + def payload(%ProjectHookWorker.Args{} = args, _new_state) do + %{ + language_name: args.revision.language.name + } + end +end diff --git a/lib/hook/events/complete_review.ex b/lib/hook/events/complete_review.ex new file mode 100644 index 000000000..7b31ded76 --- /dev/null +++ b/lib/hook/events/complete_review.ex @@ -0,0 +1,24 @@ +defmodule Accent.Hook.Events.CompleteReview do + @moduledoc false + @behaviour Accent.Hook.Event + + alias Movement.Persisters.ProjectHookWorker + + @impl true + def name do + "complete_review" + end + + @impl true + def triggered?(%ProjectHookWorker.Args{} = args, %ProjectHookWorker.ProjectState{} = project_state) do + args.previous_project_state.reviewed_count !== args.previous_project_state.translations_count and + project_state.reviewed_count === project_state.translations_count + end + + @impl true + def payload(_args, %ProjectHookWorker.ProjectState{} = project_state) do + %{ + translations_count: project_state.translations_count + } + end +end diff --git a/lib/hook/events/new_conflicts.ex b/lib/hook/events/new_conflicts.ex new file mode 100644 index 000000000..44d6c2a28 --- /dev/null +++ b/lib/hook/events/new_conflicts.ex @@ -0,0 +1,25 @@ +defmodule Accent.Hook.Events.NewConflicts do + @moduledoc false + @behaviour Accent.Hook.Event + + alias Movement.Persisters.ProjectHookWorker + + @impl true + def name do + "new_conflicts" + end + + @impl true + def triggered?(%ProjectHookWorker.Args{} = args, %ProjectHookWorker.ProjectState{} = project_state) do + args.previous_project_state.conflicts_count < project_state.conflicts_count + end + + @impl true + def payload(%ProjectHookWorker.Args{} = args, %ProjectHookWorker.ProjectState{} = project_state) do + %{ + reviewed_count: project_state.reviewed_count, + translations_count: project_state.translations_count, + new_conflicts_count: project_state.conflicts_count - args.previous_project_state.conflicts_count + } + end +end diff --git a/lib/hook/events/sync.ex b/lib/hook/events/sync.ex new file mode 100644 index 000000000..4ec7c58d8 --- /dev/null +++ b/lib/hook/events/sync.ex @@ -0,0 +1,24 @@ +defmodule Accent.Hook.Events.Sync do + @moduledoc false + @behaviour Accent.Hook.Event + + alias Movement.Persisters.ProjectHookWorker + + @impl true + def name do + "sync" + end + + @impl true + def triggered?(%ProjectHookWorker.Args{} = args, _new_state) do + args.batch_action === "sync" and args.operations_count > 0 + end + + @impl true + def payload(%ProjectHookWorker.Args{} = args, _new_state) do + %{ + batch_operation_stats: args.batch_operation.stats, + document_path: args.document.path + } + end +end diff --git a/lib/hook/hook.ex b/lib/hook/hook.ex index a709cc9a1..546be80c5 100644 --- a/lib/hook/hook.ex +++ b/lib/hook/hook.ex @@ -1,19 +1,17 @@ defmodule Accent.Hook do @moduledoc false - def outbound(context), do: run(outbounds_modules(), context) + @outbounds_modules Application.compile_env!(:accent, __MODULE__)[:outbounds] - defp run(modules, context) do + def outbound(context) do jobs = - Enum.reduce(modules, [], fn {module, opts}, acc -> - if context.event in Keyword.fetch!(opts, :events), - do: [module.new(context) | acc], - else: acc + Enum.flat_map(@outbounds_modules, fn module -> + events = module.registered_events() + + if events === :all or context.event in events, + do: [module.new(context)], + else: [] end) Oban.insert_all(jobs) end - - defp outbounds_modules do - Application.get_env(:accent, __MODULE__)[:outbounds] - end end diff --git a/lib/hook/outbounds/discord.ex b/lib/hook/outbounds/discord.ex new file mode 100644 index 000000000..139bdd11b --- /dev/null +++ b/lib/hook/outbounds/discord.ex @@ -0,0 +1,50 @@ +defmodule Accent.Hook.Outbounds.Discord do + @moduledoc false + @behaviour Accent.Hook.Events + + use Oban.Worker, queue: :hook + + defmodule Templates do + @moduledoc false + import Accent.Hook.Outbounds.Helpers.StringTemplate + + deftemplate(:new_conflicts, """ + **<%= @user %>** just added *<%= @new_conflicts_count %> strings* to review. + The project is currently **<%= Float.round(@reviewed_count / @translations_count * 100, 2) %>%** reviewed (<%= @reviewed_count %>/<%= @translations_count %>) + """) + + deftemplate(:sync, """ + **<%= @user %>** just synced a file: *<%= @document_path %>* + + **Stats:**<%= for %{"action" => action, "count" => count} <- @stats do %> + <%= Phoenix.Naming.humanize(action) %>: *<%= count %>*<% end %> + """) + + deftemplate(:complete_review, """ + **<%= @user %>** just finished reviewing all strings! + The project currently has <%= @translations_count %> reviewed translations. + """) + + deftemplate(:integration_execute_azure_storage_container, """ + **<%= @user %>** just uploaded all *<%= @version_tag %>* files to Azure Container Storage. + <%= for %{"name" => document_name, "url" => url} <- @document_urls do %> + [<%= document_name %>](<%= url %>) + <% end %> + """) + end + + @impl Accent.Hook.Events + def registered_events do + ~w(sync complete_review new_conflicts integration_execute_azure_storage_container) + end + + @impl Oban.Worker + def perform(%Oban.Job{args: args}) do + context = Accent.Hook.Context.from_worker(args) + + Accent.Hook.Outbounds.Helpers.PostURL.perform("discord", context, + http_body: &%{content: &1}, + templates: Templates + ) + end +end diff --git a/lib/hook/outbounds/discord/discord.ex b/lib/hook/outbounds/discord/discord.ex deleted file mode 100644 index 396716d8e..000000000 --- a/lib/hook/outbounds/discord/discord.ex +++ /dev/null @@ -1,15 +0,0 @@ -defmodule Accent.Hook.Outbounds.Discord do - @moduledoc false - use Oban.Worker, queue: :hook - - @impl Oban.Worker - def perform(%Oban.Job{args: args}) do - context = Accent.Hook.Context.from_worker(args) - http_body = fn content -> %{content: content} end - - Accent.Hook.Outbounds.PostURL.perform("discord", context, - http_body: http_body, - templates: Hook.Outbounds.Discord.Templates - ) - end -end diff --git a/lib/hook/outbounds/discord/templates.ex b/lib/hook/outbounds/discord/templates.ex deleted file mode 100644 index 54976a895..000000000 --- a/lib/hook/outbounds/discord/templates.ex +++ /dev/null @@ -1,23 +0,0 @@ -defmodule Hook.Outbounds.Discord.Templates do - @moduledoc false - require EEx - - @sync_template """ - **<%= @user %>** just synced a file: *<%= @document_path %>* - - **Stats:**<%= for %{"action" => action, "count" => count} <- @stats do %> - <%= Phoenix.Naming.humanize(action) %>: *<%= count %>*<% end %> - """ - @new_conflicts_template """ - **<%= @user %>** just added *<%= @new_conflicts_count %> strings* to review. - The project is currently **<%= Float.round(@reviewed_count / @translations_count * 100, 2) %>** reviewed (<%= @reviewed_count %>/<%= @translations_count %>) - """ - @complete_review_template """ - **<%= @user %>** just finished reviewing all strings! - The project currently has <%= @translations_count %> reviewed translations. - """ - - EEx.function_from_string(:def, :sync, @sync_template, [:assigns], trim: true) - EEx.function_from_string(:def, :new_conflicts, @new_conflicts_template, [:assigns], trim: true) - EEx.function_from_string(:def, :complete_review, @complete_review_template, [:assigns], trim: true) -end diff --git a/lib/hook/outbounds/email.ex b/lib/hook/outbounds/email.ex index d1325039c..4518d0838 100644 --- a/lib/hook/outbounds/email.ex +++ b/lib/hook/outbounds/email.ex @@ -1,5 +1,7 @@ defmodule Accent.Hook.Outbounds.Email do @moduledoc false + @behaviour Accent.Hook.Events + use Oban.Worker, queue: :hook alias Accent.CreateCommentEmail @@ -7,6 +9,11 @@ defmodule Accent.Hook.Outbounds.Email do alias Accent.Repo alias Accent.Translation + @impl Accent.Hook.Events + def registered_events do + ~w(create_collaborator create_comment) + end + @impl Oban.Worker def perform(%Oban.Job{args: args}) do context = Accent.Hook.Context.from_worker(args) diff --git a/lib/hook/outbounds/post_url.ex b/lib/hook/outbounds/helpers/post_url.ex similarity index 61% rename from lib/hook/outbounds/post_url.ex rename to lib/hook/outbounds/helpers/post_url.ex index 5907245c6..3013d2395 100644 --- a/lib/hook/outbounds/post_url.ex +++ b/lib/hook/outbounds/helpers/post_url.ex @@ -1,4 +1,4 @@ -defmodule Accent.Hook.Outbounds.PostURL do +defmodule Accent.Hook.Outbounds.Helpers.PostURL do @moduledoc false import Ecto.Query, only: [where: 2] @@ -58,27 +58,35 @@ defmodule Accent.Hook.Outbounds.PostURL do defp formatted_diff(diff) when diff > 1000, do: [diff |> div(1000) |> Integer.to_string(), "ms"] defp formatted_diff(diff), do: [Integer.to_string(diff), "µs"] - defp build_content(templates, %{event: "sync", user: user, payload: payload}) do + defp build_content(templates, %{event: "sync"} = context) do templates.sync(%{ - user: User.name_with_fallback(user), - document_path: payload["document_path"], - stats: payload["batch_operation_stats"] + user: User.name_with_fallback(context.user), + document_path: context.payload["document_path"], + stats: context.payload["batch_operation_stats"] }) end - defp build_content(templates, %{event: "new_conflicts", user: user, payload: payload}) do + defp build_content(templates, %{event: "new_conflicts"} = context) do templates.new_conflicts(%{ - user: User.name_with_fallback(user), - reviewed_count: payload["reviewed_count"], - new_conflicts_count: payload["new_conflicts_count"], - translations_count: payload["translations_count"] + user: User.name_with_fallback(context.user), + reviewed_count: context.payload["reviewed_count"], + new_conflicts_count: context.payload["new_conflicts_count"], + translations_count: context.payload["translations_count"] }) end - defp build_content(templates, %{event: "complete_review", user: user, payload: payload}) do + defp build_content(templates, %{event: "complete_review"} = context) do templates.complete_review(%{ - user: User.name_with_fallback(user), - translations_count: payload["translations_count"] + user: User.name_with_fallback(context.user), + translations_count: context.payload["translations_count"] + }) + end + + defp build_content(templates, %{event: "integration_execute_azure_storage_container"} = context) do + templates.integration_execute_azure_storage_container(%{ + user: User.name_with_fallback(context.user), + version_tag: context.payload["version_tag"], + document_urls: context.payload["document_urls"] }) end end diff --git a/lib/hook/outbounds/helpers/string_template.ex b/lib/hook/outbounds/helpers/string_template.ex new file mode 100644 index 000000000..36b7823c7 --- /dev/null +++ b/lib/hook/outbounds/helpers/string_template.ex @@ -0,0 +1,11 @@ +defmodule Accent.Hook.Outbounds.Helpers.StringTemplate do + @moduledoc false + + defmacro deftemplate(name, template) do + quote do + require EEx + + EEx.function_from_string(:def, unquote(name), unquote(template), [:assigns], trim: true) + end + end +end diff --git a/lib/hook/outbounds/slack.ex b/lib/hook/outbounds/slack.ex new file mode 100644 index 000000000..84e5b1182 --- /dev/null +++ b/lib/hook/outbounds/slack.ex @@ -0,0 +1,50 @@ +defmodule Accent.Hook.Outbounds.Slack do + @moduledoc false + @behaviour Accent.Hook.Events + + use Oban.Worker, queue: :hook + + defmodule Templates do + @moduledoc false + import Accent.Hook.Outbounds.Helpers.StringTemplate + + deftemplate(:new_conflicts, """ + *<%= @user %>* just added _<%= @new_conflicts_count %> strings_ to review. + The project is currently *<%= Float.round(@reviewed_count / @translations_count * 100, 2) %>%* reviewed (<%= @reviewed_count %>/<%= @translations_count %>) + """) + + deftemplate(:sync, """ + *<%= @user %>* just synced a file: _<%= @document_path %>_ + + *Stats:*<%= for %{"action" => action, "count" => count} <- @stats do %> + <%= Phoenix.Naming.humanize(action) %>: _<%= count %>_<% end %> + """) + + deftemplate(:complete_review, """ + *<%= @user %>* just finished reviewing all strings! + The project currently has <%= @translations_count %> reviewed translations. + """) + + deftemplate(:integration_execute_azure_storage_container, """ + *<%= @user %>* just uploaded all _<%= @version_tag %>_ files to Azure Container Storage. + <%= for %{"name" => document_name, "url" => url} <- @document_urls do %> + [<%= document_name %>](<%= url %>) + <% end %> + """) + end + + @impl Accent.Hook.Events + def registered_events do + ~w(sync complete_review new_conflicts integration_execute_azure_storage_container) + end + + @impl Oban.Worker + def perform(%Oban.Job{args: args}) do + context = Accent.Hook.Context.from_worker(args) + + Accent.Hook.Outbounds.Helpers.PostURL.perform("slack", context, + http_body: &%{text: &1}, + templates: Templates + ) + end +end diff --git a/lib/hook/outbounds/slack/slack.ex b/lib/hook/outbounds/slack/slack.ex deleted file mode 100644 index 03da43079..000000000 --- a/lib/hook/outbounds/slack/slack.ex +++ /dev/null @@ -1,15 +0,0 @@ -defmodule Accent.Hook.Outbounds.Slack do - @moduledoc false - use Oban.Worker, queue: :hook - - @impl Oban.Worker - def perform(%Oban.Job{args: args}) do - context = Accent.Hook.Context.from_worker(args) - http_body = fn content -> %{text: content} end - - Accent.Hook.Outbounds.PostURL.perform("slack", context, - http_body: http_body, - templates: Hook.Outbounds.Slack.Templates - ) - end -end diff --git a/lib/hook/outbounds/slack/templates.ex b/lib/hook/outbounds/slack/templates.ex deleted file mode 100644 index a21a927cd..000000000 --- a/lib/hook/outbounds/slack/templates.ex +++ /dev/null @@ -1,23 +0,0 @@ -defmodule Hook.Outbounds.Slack.Templates do - @moduledoc false - require EEx - - @sync_template """ - *<%= @user %>* just synced a file: _<%= @document_path %>_ - - *Stats:*<%= for %{"action" => action, "count" => count} <- @stats do %> - <%= Phoenix.Naming.humanize(action) %>: _<%= count %>_<% end %> - """ - @new_conflicts_template """ - *<%= @user %>* just added _<%= @new_conflicts_count %> strings_ to review. - The project is currently *<%= Float.round(@reviewed_count / @translations_count * 100, 2) %>* reviewed (<%= @reviewed_count %>/<%= @translations_count %>) - """ - @complete_review_template """ - *<%= @user %>* just finished reviewing all strings! - The project currently has <%= @translations_count %> reviewed translations. - """ - - EEx.function_from_string(:def, :sync, @sync_template, [:assigns], trim: true) - EEx.function_from_string(:def, :new_conflicts, @new_conflicts_template, [:assigns], trim: true) - EEx.function_from_string(:def, :complete_review, @complete_review_template, [:assigns], trim: true) -end diff --git a/lib/hook/outbounds/websocket.ex b/lib/hook/outbounds/websocket.ex index f70c76883..749bb5030 100644 --- a/lib/hook/outbounds/websocket.ex +++ b/lib/hook/outbounds/websocket.ex @@ -1,7 +1,14 @@ defmodule Accent.Hook.Outbounds.Websocket do @moduledoc false + @behaviour Accent.Hook.Events + use Oban.Worker, queue: :hook + @impl Accent.Hook.Events + def registered_events do + ~w(sync create_collaborator create_comment complete_review new_conflicts) + end + @impl Oban.Worker def perform(%Oban.Job{args: args}) do args diff --git a/lib/langue/formatter/json/parser.ex b/lib/langue/formatter/json/parser.ex index a7d751d6a..4e63f796a 100644 --- a/lib/langue/formatter/json/parser.ex +++ b/lib/langue/formatter/json/parser.ex @@ -19,5 +19,6 @@ defmodule Langue.Formatter.Json.Parser do |> :jsone.decode(object_format: :tuple) |> elem(0) |> NestedParserHelper.parse() + |> Enum.uniq_by(& &1.key) end end diff --git a/lib/langue/utils/parser.ex b/lib/langue/utils/parser.ex index e65cb4de4..0456a1948 100644 --- a/lib/langue/utils/parser.ex +++ b/lib/langue/utils/parser.ex @@ -3,7 +3,5 @@ defmodule Langue.Formatter.Parser do alias Langue.Formatter.ParserResult, as: Output alias Langue.Formatter.SerializerResult, as: Input - @type result :: {:ok, Output.t()} | {:error, any()} - - @callback parse(Input.t()) :: result + @callback parse(Input.t()) :: Output.t() end diff --git a/lib/langue/utils/serializer.ex b/lib/langue/utils/serializer.ex index 88a285303..4328d173a 100644 --- a/lib/langue/utils/serializer.ex +++ b/lib/langue/utils/serializer.ex @@ -3,7 +3,5 @@ defmodule Langue.Formatter.Serializer do alias Langue.Formatter.ParserResult, as: Input alias Langue.Formatter.SerializerResult, as: Output - @type result :: {:ok, Output.t()} | {:error, any()} - - @callback serialize(Input.t()) :: result + @callback serialize(Input.t()) :: Output.t() end diff --git a/lib/machine_translations/machine_translations.ex b/lib/machine_translations/machine_translations.ex index f162da6f7..ff63753cb 100644 --- a/lib/machine_translations/machine_translations.ex +++ b/lib/machine_translations/machine_translations.ex @@ -87,15 +87,15 @@ defmodule Accent.MachineTranslations do defp provider_from_config(nil), do: %Provider.NotImplemented{} - defp provider_from_config(machine_translations_config) do + defp provider_from_config(config) do struct_module = - case machine_translations_config["provider"] do + case config["provider"] do "google_translate" -> Provider.GoogleTranslate "deepl" -> Provider.Deepl _ -> Provider.NotImplemented end - struct!(struct_module, config: fetch_config(machine_translations_config)) + struct!(struct_module, config: fetch_config(config)) end defp fetch_config(%{"provider" => provider, "use_platform" => true}) do diff --git a/lib/machine_translations/provider/deepl.ex b/lib/machine_translations/provider/deepl.ex index ea1e45bd4..8e5399643 100644 --- a/lib/machine_translations/provider/deepl.ex +++ b/lib/machine_translations/provider/deepl.ex @@ -46,7 +46,7 @@ defmodule Accent.MachineTranslations.Provider.Deepl do def translate(provider, contents, source, target) do with {:ok, {source, target}} <- Accent.MachineTranslations.map_source_and_target(source, target, @supported_languages), - params = %{text: contents, source_lang: String.upcase(source), target_lang: String.upcase(target)}, + params = %{text: contents, source_lang: source && String.upcase(source), target_lang: String.upcase(target)}, {:ok, %{body: %{"translations" => translations}}} <- Tesla.post(client(provider.config["key"]), "translate", params) do {:ok, Enum.map(translations, &%TranslatedText{text: &1["text"]})} diff --git a/lib/machine_translations/provider/google_translate.ex b/lib/machine_translations/provider/google_translate.ex index a77f2e771..9aec72a47 100644 --- a/lib/machine_translations/provider/google_translate.ex +++ b/lib/machine_translations/provider/google_translate.ex @@ -137,7 +137,7 @@ defmodule Accent.MachineTranslations.Provider.GoogleTranslate do ), params = %{ contents: contents_with_no_translate, - mimeType: "text/html", + mimeType: "text/plain", sourceLanguageCode: source, targetLanguageCode: target }, @@ -166,7 +166,7 @@ defmodule Accent.MachineTranslations.Provider.GoogleTranslate do end defp unmark_no_translate(value) do - String.replace(value, ~r/([^<]+)<\/span>/, "\\1") + String.replace(value, ~r/([^<]+)<\/span>/i, "\\1") end defmodule Auth do diff --git a/lib/movement/builders/translation_update.ex b/lib/movement/builders/translation_update.ex index e78874007..fc31a24be 100644 --- a/lib/movement/builders/translation_update.ex +++ b/lib/movement/builders/translation_update.ex @@ -2,6 +2,7 @@ defmodule Movement.Builders.TranslationUpdate do @moduledoc false @behaviour Movement.Builder + alias Accent.Version alias Movement.Mappers.Operation, as: OperationMapper @action "update" @@ -17,6 +18,25 @@ defmodule Movement.Builders.TranslationUpdate do value_type = Movement.Mappers.ValueType.from_translation_new_value(translation, text) operation = OperationMapper.map(@action, translation, %{text: text, value_type: value_type}) - %{context | operations: Enum.concat(operations, [operation])} + copy_version_operation = + if copy_translation_update_to_latest_version?(translation) do + copy_translation_update_to_latest_version(translation, text) + end + + %{context | operations: Enum.concat(operations, [operation] ++ List.wrap(copy_version_operation))} + end + + defp copy_translation_update_to_latest_version(translation, text) do + source_translation = Accent.Repo.one!(Ecto.assoc(translation, :source_translation)) + value_type = Movement.Mappers.ValueType.from_translation_new_value(source_translation, text) + OperationMapper.map(@action, source_translation, %{text: text, value_type: value_type}) + end + + defp copy_translation_update_to_latest_version?(translation) do + if translation.version_id do + version = Accent.Repo.get(Version, translation.version_id) + + version.copy_on_update_translation + end end end diff --git a/lib/movement/context.ex b/lib/movement/context.ex index 91c5e7340..995002751 100644 --- a/lib/movement/context.ex +++ b/lib/movement/context.ex @@ -1,6 +1,6 @@ defmodule Movement.Context do @moduledoc false - defstruct entries: [], operations: [], assigns: %{options: []}, render: "" + defstruct entries: [], operations: [], assigns: %{batch_operation: nil, options: []}, render: "" @type t :: %__MODULE__{} diff --git a/lib/movement/migration/translation.ex b/lib/movement/migration/translation.ex index 78486b9c7..e18f250c2 100644 --- a/lib/movement/migration/translation.ex +++ b/lib/movement/migration/translation.ex @@ -56,7 +56,7 @@ defmodule Movement.Migration.Translation do locked: operation.locked, file_index: operation.file_index, file_comment: operation.file_comment, - removed: operation.previous_translation && operation.previous_translation.removed, + removed: (operation.previous_translation && operation.previous_translation.removed) || false, translated: is_nil(operation.translation_id), revision_id: operation.revision_id, document_id: operation.document_id, @@ -82,11 +82,11 @@ defmodule Movement.Migration.Translation do proposed_text: operation.text, corrected_text: operation.text, translated: (operation.previous_translation && operation.previous_translation.translated) || false, - conflicted: operation.previous_translation && operation.previous_translation.conflicted, + conflicted: (operation.previous_translation && operation.previous_translation.conflicted) || false, value_type: operation.value_type, file_index: operation.file_index, file_comment: operation.file_comment, - removed: operation.previous_translation && operation.previous_translation.removed, + removed: (operation.previous_translation && operation.previous_translation.removed) || false, revision_id: operation.revision_id, document_id: operation.document_id, version_id: operation.version_id, diff --git a/lib/movement/persisters/base.ex b/lib/movement/persisters/base.ex index 910a6b8c3..bb8cf6963 100644 --- a/lib/movement/persisters/base.ex +++ b/lib/movement/persisters/base.ex @@ -4,7 +4,7 @@ defmodule Movement.Persisters.Base do alias Accent.Repo alias Movement.Mappers.OperationsStats, as: StatMapper alias Movement.Migrator - alias Movement.Persisters.ProjectStateChangeWorker + alias Movement.Persisters.ProjectHookWorker require Ecto.Query @@ -17,7 +17,8 @@ defmodule Movement.Persisters.Base do @spec execute(Movement.Context.t()) :: {Movement.Context.t(), [Operation.t()]} def execute(%Movement.Context{operations: []} = context), do: {context, []} - def execute(%Movement.Context{assigns: %{batch_action: action} = assigns} = context) when is_binary(action) do + def execute(%Movement.Context{assigns: %{batch_action: action, batch_operation: nil} = assigns} = context) + when is_binary(action) do stats = StatMapper.map(context.operations) batch_operation = @@ -34,12 +35,13 @@ defmodule Movement.Persisters.Base do context |> Movement.Context.assign(:batch_operation, batch_operation) - |> Movement.Context.assign(:batch_action, nil) |> execute() end def execute(context) do - project_state_change_context = %{ + project_context = %{ + batch_action: context.assigns[:batch_action], + operations_count: Enum.count(context.operations), project_id: context.assigns[:project] && context.assigns.project.id, document_id: context.assigns[:document] && context.assigns.document.id, master_revision_id: context.assigns[:master_revision] && context.assigns.master_revision.id, @@ -47,15 +49,14 @@ defmodule Movement.Persisters.Base do version_id: context.assigns[:version] && context.assigns.version.id, batch_operation_id: context.assigns[:batch_operation] && context.assigns.batch_operation.id, user_id: context.assigns[:user_id], - previous_project_state: ProjectStateChangeWorker.get_project_state(context.assigns[:project]) + previous_project_state: ProjectHookWorker.get_project_state(context.assigns[:project]) } context |> persist_operations() |> migrate_up_operations() |> tap(fn _ -> - project_state_change_context.previous_project_state && - Oban.insert(ProjectStateChangeWorker.new(project_state_change_context)) + context.assigns[:project] && Oban.insert(ProjectHookWorker.new(project_context)) end) end diff --git a/lib/movement/persisters/new_version.ex b/lib/movement/persisters/new_version.ex index 97ea01ee4..20bbd6cb6 100644 --- a/lib/movement/persisters/new_version.ex +++ b/lib/movement/persisters/new_version.ex @@ -23,7 +23,8 @@ defmodule Movement.Persisters.NewVersion do "project_id" => assigns[:project].id, "user_id" => assigns[:user_id], "name" => assigns[:name], - "tag" => assigns[:tag] + "tag" => assigns[:tag], + "copy_on_update_translation" => assigns[:copy_on_update_translation] }) |> Repo.insert() |> case do diff --git a/lib/movement/persisters/project_hook_worker.ex b/lib/movement/persisters/project_hook_worker.ex new file mode 100644 index 000000000..db07837a7 --- /dev/null +++ b/lib/movement/persisters/project_hook_worker.ex @@ -0,0 +1,93 @@ +defmodule Movement.Persisters.ProjectHookWorker do + @moduledoc false + use Oban.Worker, queue: :hook + + import Ecto.Query + + alias Accent.Hook + alias Accent.Repo + alias Accent.Scopes.Project, as: ProjectScope + + defmodule ProjectState do + @moduledoc false + @derive Jason.Encoder + defstruct translations_count: 0, reviewed_count: 0, conflicts_count: 0 + + @type t :: %__MODULE__{} + end + + defmodule Args do + @moduledoc false + defstruct previous_project_state: %ProjectState{}, + operations_count: 0, + project: nil, + document: nil, + master_revision: nil, + revision: nil, + version: nil, + batch_operation: nil, + batch_action: nil, + user: nil + + @type t :: %__MODULE__{} + end + + @impl Oban.Worker + def perform(%Oban.Job{args: args}) do + args = cast_args(args) + current_project_state = get_project_state(args.project) + + for module <- Accent.Hook.Events.available() do + if module.triggered?(args, current_project_state) do + Hook.outbound(%Hook.Context{ + event: module.name(), + project_id: args.project.id, + user_id: args.user && args.user.id, + payload: module.payload(args, current_project_state) + }) + end + end + + :ok + end + + def get_project_state(nil), do: nil + + def get_project_state(project) do + project = + Accent.Project + |> from(where: [id: ^project.id]) + |> ProjectScope.with_stats() + |> Repo.one() + + struct!(ProjectState, Map.take(project, ~w(translations_count reviewed_count conflicts_count)a)) + end + + defp cast_args(args) do + %Args{ + previous_project_state: cast_project_state(args["previous_project_state"]), + project: get_record(Accent.Project, args["project_id"]), + document: get_record(Accent.Document, args["document_id"]), + master_revision: get_record(Accent.Revision, args["master_revision_id"]), + revision: get_record(Accent.Revision, args["revision_id"]), + version: get_record(Accent.Version, args["version_id"]), + batch_operation: get_record(Accent.Operation, args["batch_operation_id"]), + operations_count: args["operations_count"], + batch_action: args["batch_action"], + user: get_record(Accent.User, args["user_id"]) + } + end + + defp cast_project_state(nil), do: nil + + defp cast_project_state(args) do + %ProjectState{ + translations_count: args["translations_count"], + reviewed_count: args["reviewed_count"], + conflicts_count: args["conflicts_count"] + } + end + + defp get_record(_schema, nil), do: nil + defp get_record(schema, id), do: Repo.get(schema, id) +end diff --git a/lib/movement/persisters/project_state_change_worker.ex b/lib/movement/persisters/project_state_change_worker.ex deleted file mode 100644 index edc9e99f4..000000000 --- a/lib/movement/persisters/project_state_change_worker.ex +++ /dev/null @@ -1,90 +0,0 @@ -defmodule Movement.Persisters.ProjectStateChangeWorker do - @moduledoc false - use Oban.Worker, queue: :hook - - import Ecto.Query - - alias Accent.Hook - alias Accent.Repo - alias Accent.Scopes.Project, as: ProjectScope - - @impl Oban.Worker - def perform(%Oban.Job{args: args}) do - args = cast_args(args) - current_project_state = get_project_state(args.project) - - if new_conflicts_to_review?(args.previous_project_state, current_project_state) do - Hook.outbound(%Hook.Context{ - event: "new_conflicts", - project_id: args.project.id, - user_id: args.user.id, - payload: %{ - reviewed_count: current_project_state.project.reviewed_count, - translations_count: current_project_state.project.translations_count, - new_conflicts_count: - current_project_state.project.conflicts_count - args.previous_project_state.project.conflicts_count - } - }) - end - - if all_reviewed?(args.previous_project_state, current_project_state) do - Hook.outbound(%Hook.Context{ - event: "complete_review", - project_id: args.project.id, - user_id: args.user.id, - payload: %{ - translations_count: current_project_state.project.translations_count - } - }) - end - - :ok - end - - defp new_conflicts_to_review?(previous_state, current_state) do - previous_state.project.conflicts_count < current_state.project.conflicts_count - end - - defp all_reviewed?(previous_state, current_state) do - previous_state.project.reviewed_count !== previous_state.project.translations_count and - current_state.project.reviewed_count === current_state.project.translations_count - end - - def get_project_state(nil), do: nil - - def get_project_state(project) do - project = - Accent.Project - |> from(where: [id: ^project.id]) - |> ProjectScope.with_stats() - |> Repo.one() - - %{project: Map.take(project, ~w(translations_count reviewed_count conflicts_count)a)} - end - - defp cast_project_state(args) do - %{ - project: %{ - translations_count: args["project"]["translations_count"], - reviewed_count: args["project"]["reviewed_count"], - conflicts_count: args["project"]["conflicts_count"] - } - } - end - - defp cast_args(args) do - %{ - previous_project_state: cast_project_state(args["previous_project_state"]), - project: get_record(Accent.Project, args["project_id"]), - document: get_record(Accent.Document, args["document_id"]), - master_revision: get_record(Accent.Revision, args["master_revision_id"]), - revision: get_record(Accent.Revision, args["revision_id"]), - version: get_record(Accent.Version, args["version_id"]), - batch_operation: get_record(Accent.Operation, args["batch_operation_id"]), - user: get_record(Accent.User, args["user_id"]) - } - end - - defp get_record(_schema, nil), do: nil - defp get_record(schema, id), do: Repo.get(schema, id) -end diff --git a/lib/prompts/prompts.ex b/lib/prompts/prompts.ex index 253c76493..6bf1fa6eb 100644 --- a/lib/prompts/prompts.ex +++ b/lib/prompts/prompts.ex @@ -17,6 +17,8 @@ defmodule Accent.Prompts do Provider.enabled?(provider) end + defp provider_from_config(nil), do: %Provider.NotImplemented{} + defp provider_from_config(config) do struct_module = case config["provider"] do @@ -24,6 +26,12 @@ defmodule Accent.Prompts do _ -> Provider.NotImplemented end - struct!(struct_module, config: config) + struct!(struct_module, config: fetch_config(config)) + end + + defp fetch_config(%{"provider" => provider, "use_platform" => true}) do + Map.get(Application.get_env(:accent, __MODULE__)[:default_providers_config], provider) end + + defp fetch_config(%{"config" => config}), do: config end diff --git a/lib/prompts/provider/open_ai.ex b/lib/prompts/provider/open_ai.ex index ff1131fb3..e09b5f78e 100644 --- a/lib/prompts/provider/open_ai.ex +++ b/lib/prompts/provider/open_ai.ex @@ -9,7 +9,7 @@ defmodule Accent.Prompts.Provider.OpenAI do def enabled?(_), do: true def completions(provider, prompt, user_input) do - config = provider.config["config"] + config = provider.config params = %{ messages: [ diff --git a/lib/web/controllers/merge_controller.ex b/lib/web/controllers/merge_controller.ex index 64541363e..a856ab8e2 100644 --- a/lib/web/controllers/merge_controller.ex +++ b/lib/web/controllers/merge_controller.ex @@ -3,9 +3,9 @@ defmodule Accent.MergeController do import Canary.Plugs - alias Accent.Hook.Context, as: HookContext alias Accent.Project alias Movement.Builders.RevisionMerge, as: RevisionMergeBuilder + alias Movement.Context alias Movement.Persisters.RevisionMerge, as: RevisionMergePersister plug(Plug.Assign, canary_action: :merge) @@ -44,27 +44,14 @@ defmodule Accent.MergeController do """ def create(conn, _params) do conn.assigns[:movement_context] - |> Movement.Context.assign(:revision, conn.assigns[:revision]) - |> Movement.Context.assign(:merge_type, conn.assigns[:merge_type]) - |> Movement.Context.assign(:options, conn.assigns[:merge_options]) - |> Movement.Context.assign(:user_id, conn.assigns[:current_user].id) + |> Context.assign(:revision, conn.assigns[:revision]) + |> Context.assign(:merge_type, conn.assigns[:merge_type]) + |> Context.assign(:options, conn.assigns[:merge_options]) + |> Context.assign(:user_id, conn.assigns[:current_user].id) |> RevisionMergeBuilder.build() |> RevisionMergePersister.persist() |> case do - {:ok, {_context, []}} -> - send_resp(conn, :ok, "") - - {:ok, _} -> - Accent.Hook.outbound(%HookContext{ - event: "add_translations", - project_id: conn.assigns[:project].id, - user_id: conn.assigns[:current_user].id, - payload: %{ - merge_type: conn.assigns[:merge_type], - language_name: conn.assigns[:revision].language.name - } - }) - + {:ok, {_context, _}} -> send_resp(conn, :ok, "") {:error, _reason} -> @@ -74,7 +61,7 @@ defmodule Accent.MergeController do defp assign_comparer(conn, _) do comparer = Movement.Comparer.comparer(:merge, conn.params["merge_type"]) - context = Movement.Context.assign(conn.assigns[:movement_context], :comparer, comparer) + context = Context.assign(conn.assigns[:movement_context], :comparer, comparer) assign(conn, :movement_context, context) end diff --git a/lib/web/controllers/sync_controller.ex b/lib/web/controllers/sync_controller.ex index a110745aa..e0310072e 100644 --- a/lib/web/controllers/sync_controller.ex +++ b/lib/web/controllers/sync_controller.ex @@ -3,9 +3,9 @@ defmodule Accent.SyncController do import Canary.Plugs - alias Accent.Hook.Context, as: HookContext alias Accent.Project alias Movement.Builders.ProjectSync, as: SyncBuilder + alias Movement.Context alias Movement.Persisters.ProjectSync, as: SyncPersister plug(Plug.Assign, canary_action: :sync) @@ -41,25 +41,12 @@ defmodule Accent.SyncController do """ def create(conn, _) do conn.assigns[:movement_context] - |> Movement.Context.assign(:project, conn.assigns[:project]) - |> Movement.Context.assign(:user_id, conn.assigns[:current_user].id) + |> Context.assign(:project, conn.assigns[:project]) + |> Context.assign(:user_id, conn.assigns[:current_user].id) |> SyncBuilder.build() |> SyncPersister.persist() |> case do - {:ok, {_context, []}} -> - send_resp(conn, :ok, "") - - {:ok, {context, _operations}} -> - Accent.Hook.outbound(%HookContext{ - event: "sync", - project_id: conn.assigns[:project].id, - user_id: conn.assigns[:current_user].id, - payload: %{ - batch_operation_stats: context.assigns[:batch_operation].stats, - document_path: context.assigns[:document].path - } - }) - + {:ok, {_context, _}} -> send_resp(conn, :ok, "") {:error, _reason} -> @@ -69,7 +56,7 @@ defmodule Accent.SyncController do defp assign_comparer(conn, _) do comparer = Movement.Comparer.comparer(:sync, conn.params["sync_type"]) - context = Movement.Context.assign(conn.assigns[:movement_context], :comparer, comparer) + context = Context.assign(conn.assigns[:movement_context], :comparer, comparer) assign(conn, :movement_context, context) end diff --git a/lib/web/plugs/movement_context_parser.ex b/lib/web/plugs/movement_context_parser.ex index aa8bf3998..7c5ce4d7d 100644 --- a/lib/web/plugs/movement_context_parser.ex +++ b/lib/web/plugs/movement_context_parser.ex @@ -90,7 +90,7 @@ defmodule Accent.Plugs.MovementContextParser do end def assign_movement_context(conn, _) do - assign(conn, :movement_context, %Context{assigns: %{options: [], project: conn.assigns[:project]}}) + assign(conn, :movement_context, Context.assign(%Context{}, :project, conn.assigns[:project])) end def assign_movement_version(%{assigns: %{version: version, movement_context: context}} = conn, _opts) do diff --git a/mix.exs b/mix.exs index 8ee1c0fbb..8e84e1d20 100644 --- a/mix.exs +++ b/mix.exs @@ -1,7 +1,7 @@ defmodule Accent.Mixfile do use Mix.Project - @version "1.19.12" + @version "1.21.4" def project do [ @@ -82,6 +82,7 @@ defmodule Accent.Mixfile do {:jason, "~> 1.2", override: true}, {:erlsom, "~> 1.5"}, {:xml_builder, "~> 2.0"}, + {:aws_signature, "~> 0.3"}, # Auth {:ueberauth, "~> 0.10"}, @@ -91,6 +92,7 @@ defmodule Accent.Mixfile do {:ueberauth_github, "~> 0.7"}, {:ueberauth_discord, "~> 0.5"}, {:ueberauth_auth0, "~> 2.0"}, + {:ueberauth_oidc, "~> 0.1.7"}, # Errors {:sentry, "~> 7.0"}, @@ -114,6 +116,7 @@ defmodule Accent.Mixfile do # Mock testing {:mox, "~> 1.0", only: :test}, {:mock, "~> 0.3.0", only: :test}, + {:factori, "~> 0.13", only: :test}, # Google API authentication {:goth, "~> 1.4"}, diff --git a/mix.lock b/mix.lock index 32f80e65a..a05a8e0f4 100644 --- a/mix.lock +++ b/mix.lock @@ -2,28 +2,29 @@ "absinthe": {:hex, :absinthe, "1.7.6", "0b897365f98d068cfcb4533c0200a8e58825a4aeeae6ec33633ebed6de11773b", [:mix], [{:dataloader, "~> 1.0.0 or ~> 2.0", [hex: :dataloader, repo: "hexpm", optional: true]}, {:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}, {:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}, {:opentelemetry_process_propagator, "~> 0.2.1", [hex: :opentelemetry_process_propagator, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "e7626951ca5eec627da960615b51009f3a774765406ff02722b1d818f17e5778"}, "absinthe_error_payload": {:hex, :absinthe_error_payload, "1.1.4", "502ff239148c8deaac028ddb600d6502d5be68d24fece0c93f4c3cf7e74c1a4d", [:make, :mix], [{:absinthe, "~> 1.3", [hex: :absinthe, repo: "hexpm", optional: false]}, {:ecto, "~> 3.1", [hex: :ecto, repo: "hexpm", optional: false]}], "hexpm", "9e262ef2fd4a2c644075e0cdde2573b1f713c0676ab905c8640eaa8a882b2aca"}, "absinthe_plug": {:hex, :absinthe_plug, "1.5.8", "38d230641ba9dca8f72f1fed2dfc8abd53b3907d1996363da32434ab6ee5d6ab", [:mix], [{:absinthe, "~> 1.5", [hex: :absinthe, repo: "hexpm", optional: false]}, {:plug, "~> 1.4", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "bbb04176647b735828861e7b2705465e53e2cf54ccf5a73ddd1ebd855f996e5a"}, + "aws_signature": {:hex, :aws_signature, "0.3.2", "adf33bc4af00b2089b7708bf20e3246f09c639a905a619b3689f0a0a22c3ef8f", [:rebar3], [], "hexpm", "b0daf61feb4250a8ab0adea60db3e336af732ff71dd3fb22e45ae3dcbd071e44"}, "bamboo": {:hex, :bamboo, "2.3.0", "d2392a2cabe91edf488553d3c70638b532e8db7b76b84b0a39e3dfe492ffd6fc", [:mix], [{:hackney, ">= 1.15.2", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:mime, "~> 1.4 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "dd0037e68e108fd04d0e8773921512c940e35d981e097b5793543e3b2f9cd3f6"}, "bamboo_phoenix": {:hex, :bamboo_phoenix, "1.0.0", "f3cc591ffb163ed0bf935d256f1f4645cd870cf436545601215745fb9cc9953f", [:mix], [{:bamboo, ">= 2.0.0", [hex: :bamboo, repo: "hexpm", optional: false]}, {:phoenix, ">= 1.3.0", [hex: :phoenix, repo: "hexpm", optional: false]}], "hexpm", "6db88fbb26019c84a47994bb2bd879c0887c29ce6c559bc6385fd54eb8b37dee"}, "bamboo_smtp": {:hex, :bamboo_smtp, "4.2.2", "e9f57a2300df9cb496c48751bd7668a86a2b89aa2e79ccaa34e0c46a5f64c3ae", [:mix], [{:bamboo, "~> 2.2.0", [hex: :bamboo, repo: "hexpm", optional: false]}, {:gen_smtp, "~> 1.2.0", [hex: :gen_smtp, repo: "hexpm", optional: false]}], "hexpm", "28cac2ec8adaae02aed663bf68163992891a3b44cfd7ada0bebe3e09bed7207f"}, - "bandit": {:hex, :bandit, "1.2.0", "2b5784909cc25b2514868055ff27458cdc63314514b90d86448ff91d18bece80", [:mix], [{:hpax, "~> 0.1.1", [hex: :hpax, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:thousand_island, "~> 1.0", [hex: :thousand_island, repo: "hexpm", optional: false]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "05688b883d87cc3b32991517a61e8c2ce8ee2dd6aa6eb73635426002a6661491"}, + "bandit": {:hex, :bandit, "1.3.0", "6a4e8d7c9ea721edd02c389e2cc867890cd96f83116e71ddf1ccbdd80661550c", [:mix], [{:hpax, "~> 0.1.1", [hex: :hpax, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:thousand_island, "~> 1.0", [hex: :thousand_island, repo: "hexpm", optional: false]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "bda37d6c614d74778a5dc43b8bcdc3245cd30619eab0342f58042f968f2165da"}, "bunt": {:hex, :bunt, "1.0.0", "081c2c665f086849e6d57900292b3a161727ab40431219529f13c4ddcf3e7a44", [:mix], [], "hexpm", "dc5f86aa08a5f6fa6b8096f0735c4e76d54ae5c9fa2c143e5a1fc7c1cd9bb6b5"}, "cachex": {:hex, :cachex, "3.6.0", "14a1bfbeee060dd9bec25a5b6f4e4691e3670ebda28c8ba2884b12fe30b36bf8", [:mix], [{:eternal, "~> 1.2", [hex: :eternal, repo: "hexpm", optional: false]}, {:jumper, "~> 1.0", [hex: :jumper, repo: "hexpm", optional: false]}, {:sleeplocks, "~> 1.1", [hex: :sleeplocks, repo: "hexpm", optional: false]}, {:unsafe, "~> 1.0", [hex: :unsafe, repo: "hexpm", optional: false]}], "hexpm", "ebf24e373883bc8e0c8d894a63bbe102ae13d918f790121f5cfe6e485cc8e2e2"}, "canada": {:hex, :canada, "2.0.0", "ce5e058f576a0625959fc5427fcde15311fb28a5ebc13775eafd13468ad16553", [:mix], [], "hexpm", "49a648c48d8b0864380f38f02a7f316bd30fd45602205c48197432b5225d8596"}, "canary": {:git, "https://github.com/runhyve/canary.git", "b81d780e1cb7a1c276599f980ab9c9a7c9cd8c12", []}, - "castore": {:hex, :castore, "1.0.5", "9eeebb394cc9a0f3ae56b813459f990abb0a3dedee1be6b27fdb50301930502f", [:mix], [], "hexpm", "8d7c597c3e4a64c395980882d4bca3cebb8d74197c590dc272cfd3b6a6310578"}, + "castore": {:hex, :castore, "1.0.6", "ffc42f110ebfdafab0ea159cd43d31365fa0af0ce4a02ecebf1707ae619ee727", [:mix], [], "hexpm", "374c6e7ca752296be3d6780a6d5b922854ffcc74123da90f2f328996b962d33a"}, "certifi": {:hex, :certifi, "2.12.0", "2d1cca2ec95f59643862af91f001478c9863c2ac9cb6e2f89780bfd8de987329", [:rebar3], [], "hexpm", "ee68d85df22e554040cdb4be100f33873ac6051387baf6a8f6ce82272340ff1c"}, "cloak": {:hex, :cloak, "1.1.2", "7e0006c2b0b98d976d4f559080fabefd81f0e0a50a3c4b621f85ceeb563e80bb", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "940d5ac4fcd51b252930fd112e319ea5ae6ab540b722f3ca60a85666759b9585"}, "cloak_ecto": {:hex, :cloak_ecto, "1.2.0", "e86a3df3bf0dc8980f70406bcb0af2858bac247d55494d40bc58a152590bd402", [:mix], [{:cloak, "~> 1.1.1", [hex: :cloak, repo: "hexpm", optional: false]}, {:ecto, "~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}], "hexpm", "8bcc677185c813fe64b786618bd6689b1707b35cd95acaae0834557b15a0c62f"}, "combine": {:hex, :combine, "0.10.0", "eff8224eeb56498a2af13011d142c5e7997a80c8f5b97c499f84c841032e429f", [:mix], [], "hexpm", "1b1dbc1790073076580d0d1d64e42eae2366583e7aecd455d1215b0d16f2451b"}, "corsica": {:hex, :corsica, "2.1.3", "dccd094ffce38178acead9ae743180cdaffa388f35f0461ba1e8151d32e190e6", [:mix], [{:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "616c08f61a345780c2cf662ff226816f04d8868e12054e68963e95285b5be8bc"}, - "credo": {:hex, :credo, "1.7.3", "05bb11eaf2f2b8db370ecaa6a6bda2ec49b2acd5e0418bc106b73b07128c0436", [:mix], [{:bunt, "~> 0.2.1 or ~> 1.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "35ea675a094c934c22fb1dca3696f3c31f2728ae6ef5a53b5d648c11180a4535"}, + "credo": {:hex, :credo, "1.7.5", "643213503b1c766ec0496d828c90c424471ea54da77c8a168c725686377b9545", [:mix], [{:bunt, "~> 0.2.1 or ~> 1.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "f799e9b5cd1891577d8c773d245668aa74a2fcd15eb277f51a0131690ebfb3fd"}, "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.5.0", "c47b5a5221bf2e56d6e8eb79e77884046d7fd516280dc7d9b674251e0ae46246", [:mix], [{:parallel_stream, "~> 1.0.4 or ~> 1.1.0", [hex: :parallel_stream, repo: "hexpm", optional: false]}], "hexpm", "e821f541487045c7591a1963eeb42afff0dfa99bdcdbeb3410795a2f59c77d34"}, "dataloader": {:hex, :dataloader, "2.0.0", "49b42d60b9bb06d761a71d7b034c4b34787957e713d4fae15387a25fcd639112", [:mix], [{:ecto, ">= 3.4.3 and < 4.0.0", [hex: :ecto, repo: "hexpm", optional: true]}, {:opentelemetry_process_propagator, "~> 0.2.1", [hex: :opentelemetry_process_propagator, repo: "hexpm", optional: true]}, {:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "09d61781b76ce216e395cdbc883ff00d00f46a503e215c22722dba82507dfef0"}, "db_connection": {:hex, :db_connection, "2.6.0", "77d835c472b5b67fc4f29556dee74bf511bbafecdcaf98c27d27fa5918152086", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "c2f992d15725e721ec7fbc1189d4ecdb8afef76648c746a8e1cad35e3b8a35f3"}, "decimal": {:hex, :decimal, "2.1.1", "5611dca5d4b2c3dd497dec8f68751f1f1a54755e8ed2a966c2633cf885973ad6", [:mix], [], "hexpm", "53cfe5f497ed0e7771ae1a475575603d77425099ba5faef9394932b35020ffcc"}, "dialyxir": {:hex, :dialyxir, "1.4.3", "edd0124f358f0b9e95bfe53a9fcf806d615d8f838e2202a9f430d59566b6b53b", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "bf2cfb75cd5c5006bec30141b131663299c661a864ec7fbbc72dfa557487a986"}, - "ecto": {:hex, :ecto, "3.11.1", "4b4972b717e7ca83d30121b12998f5fcdc62ba0ed4f20fd390f16f3270d85c3e", [:mix], [{:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "ebd3d3772cd0dfcd8d772659e41ed527c28b2a8bde4b00fe03e0463da0f1983b"}, + "ecto": {:hex, :ecto, "3.11.2", "e1d26be989db350a633667c5cda9c3d115ae779b66da567c68c80cfb26a8c9ee", [:mix], [{:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "3c38bca2c6f8d8023f2145326cc8a80100c3ffe4dcbd9842ff867f7fc6156c65"}, "ecto_dev_logger": {:hex, :ecto_dev_logger, "0.10.0", "5b3a3900b845e0d40127bed9bdf9d02bf20aa38198a60fe108cddff63ed0048f", [:mix], [{:ecto, "~> 3.7", [hex: :ecto, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "a55e58bad5d5c9b8ef2a3c3347dbdf7efa880a5371cf1457e44b41f489a43927"}, "ecto_psql_extras": {:hex, :ecto_psql_extras, "0.7.15", "0fc29dbae0e444a29bd6abeee4cf3c4c037e692a272478a234a1cc765077dbb1", [:mix], [{:ecto_sql, "~> 3.7", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.16.0 or ~> 0.17.0", [hex: :postgrex, repo: "hexpm", optional: false]}, {:table_rex, "~> 3.1.1 or ~> 4.0.0", [hex: :table_rex, repo: "hexpm", optional: false]}], "hexpm", "b6127f3a5c6fc3d84895e4768cc7c199f22b48b67d6c99b13fbf4a374e73f039"}, "ecto_sql": {:hex, :ecto_sql, "3.11.1", "e9abf28ae27ef3916b43545f9578b4750956ccea444853606472089e7d169470", [:mix], [{:db_connection, "~> 2.4.1 or ~> 2.5", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.11.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.6.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.16.0 or ~> 0.17.0 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1 or ~> 2.2", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "ce14063ab3514424276e7e360108ad6c2308f6d88164a076aac8a387e1fea634"}, @@ -33,8 +34,10 @@ "eternal": {:hex, :eternal, "1.2.2", "d1641c86368de99375b98d183042dd6c2b234262b8d08dfd72b9eeaafc2a1abd", [:mix], [], "hexpm", "2c9fe32b9c3726703ba5e1d43a1d255a4f3f2d8f8f9bc19f094c7cb1a7a9e782"}, "excoveralls": {:hex, :excoveralls, "0.18.0", "b92497e69465dc51bc37a6422226ee690ab437e4c06877e836f1c18daeb35da9", [:mix], [{:castore, "~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "1109bb911f3cb583401760be49c02cbbd16aed66ea9509fc5479335d284da60b"}, "exile": {:hex, :exile, "0.9.1", "832b6340cf800661e90e52cebc760b795450f803c0e9265ccdc54150423fbb32", [:make, :mix], [{:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "553a1847b27118c843d3dc6912adbc36d60336811d15ad70a31b82eb5a416328"}, + "factori": {:hex, :factori, "0.13.0", "989602327020e6ad9cb3b5403a30591cc3b81528477d894f7d11f3c0eb3c3d18", [:make, :mix], [{:ecto, "~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:ecto_sql, "~> 3.0", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:faker, "~> 0.16", [hex: :faker, repo: "hexpm", optional: false]}], "hexpm", "cedb92ff18ad2a5e854e46344ad59bdbfb2729bef7bf557bc06e89e89c98df1a"}, + "faker": {:hex, :faker, "0.18.0", "943e479319a22ea4e8e39e8e076b81c02827d9302f3d32726c5bf82f430e6e14", [:mix], [], "hexpm", "bfbdd83958d78e2788e99ec9317c4816e651ad05e24cfd1196ce5db5b3e81797"}, "fast_yaml": {:git, "https://github.com/processone/fast_yaml.git", "e789f68895f71b7ad31057177810ca0161bf790e", [ref: "e789f68895f71b7ad31057177810ca0161bf790e"]}, - "file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"}, + "file_system": {:hex, :file_system, "1.0.0", "b689cc7dcee665f774de94b5a832e578bd7963c8e637ef940cd44327db7de2cd", [:mix], [], "hexpm", "6752092d66aec5a10e662aefeed8ddb9531d79db0bc145bb8c40325ca1d8536d"}, "finch": {:hex, :finch, "0.17.0", "17d06e1d44d891d20dbd437335eebe844e2426a0cd7e3a3e220b461127c73f70", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.3", [hex: :mint, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.4 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 0.2.6 or ~> 1.0", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "8d014a661bb6a437263d4b5abf0bcbd3cf0deb26b1e8596f2a271d22e48934c7"}, "gen_smtp": {:hex, :gen_smtp, "1.2.0", "9cfc75c72a8821588b9b9fe947ae5ab2aed95a052b81237e0928633a13276fd3", [:rebar3], [{:ranch, ">= 1.8.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "5ee0375680bca8f20c4d85f58c2894441443a743355430ff33a783fe03296779"}, "gettext": {:hex, :gettext, "0.20.0", "75ad71de05f2ef56991dbae224d35c68b098dd0e26918def5bb45591d5c8d429", [:mix], [], "hexpm", "1c03b177435e93a47441d7f681a7040bd2a816ece9e2666d1c9001035121eb3d"}, @@ -56,20 +59,21 @@ "mock": {:hex, :mock, "0.3.8", "7046a306b71db2488ef54395eeb74df0a7f335a7caca4a3d3875d1fc81c884dd", [:mix], [{:meck, "~> 0.9.2", [hex: :meck, repo: "hexpm", optional: false]}], "hexpm", "7fa82364c97617d79bb7d15571193fc0c4fe5afd0c932cef09426b3ee6fe2022"}, "mox": {:hex, :mox, "1.1.0", "0f5e399649ce9ab7602f72e718305c0f9cdc351190f72844599545e4996af73c", [:mix], [], "hexpm", "d44474c50be02d5b72131070281a5d3895c0e7a95c780e90bc0cfe712f633a13"}, "new_relic_absinthe": {:hex, :new_relic_absinthe, "0.0.4", "57917f99789d9b36e4beb599deba495a474e5bf99a5c70a33717b0e17f1c5d4d", [:mix], [{:absinthe, "~> 1.4", [hex: :absinthe, repo: "hexpm", optional: false]}, {:new_relic_agent, "~> 1.19", [hex: :new_relic_agent, repo: "hexpm", optional: false]}], "hexpm", "6b796662e550ddd07e98ff3df95803a6b2a023605e78e0a45261d3e66341c296"}, - "new_relic_agent": {:hex, :new_relic_agent, "1.28.0", "eb015edb4f4887a31ee0488cf9ce97b7e46c9e0208eeff8737d8ea09cd506d09", [:mix], [{:castore, ">= 0.1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:ecto, ">= 3.4.1", [hex: :ecto, repo: "hexpm", optional: true]}, {:ecto_sql, ">= 3.4.0", [hex: :ecto_sql, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:phoenix, ">= 1.5.5", [hex: :phoenix, repo: "hexpm", optional: true]}, {:plug, ">= 1.10.4", [hex: :plug, repo: "hexpm", optional: true]}, {:plug_cowboy, ">= 2.4.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:redix, ">= 0.11.0", [hex: :redix, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "ef220f429f2d673e78679ec96cd4e8979b2cb2166b204bfe1a43ca974520743a"}, + "new_relic_agent": {:hex, :new_relic_agent, "1.29.0", "928795ce65f2a28688100973e70ba96001288df66be8fb87903d1f49b7ed4cc0", [:mix], [{:castore, ">= 0.1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:ecto, ">= 3.9.5", [hex: :ecto, repo: "hexpm", optional: true]}, {:ecto_sql, ">= 3.4.0", [hex: :ecto_sql, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:phoenix, ">= 1.5.5", [hex: :phoenix, repo: "hexpm", optional: true]}, {:plug, ">= 1.10.4", [hex: :plug, repo: "hexpm", optional: true]}, {:plug_cowboy, ">= 2.4.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:redix, ">= 0.11.0", [hex: :redix, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "ff90ba00671b84039141e662699d337254c4c4f7285c417839aad2e166e51e66"}, "nimble_options": {:hex, :nimble_options, "1.1.0", "3b31a57ede9cb1502071fade751ab0c7b8dbe75a9a4c2b5bbb0943a690b63172", [:mix], [], "hexpm", "8bbbb3941af3ca9acc7835f5655ea062111c9c27bcac53e004460dfd19008a99"}, "nimble_parsec": {:hex, :nimble_parsec, "1.4.0", "51f9b613ea62cfa97b25ccc2c1b4216e81df970acd8e16e8d1bdc58fef21370d", [:mix], [], "hexpm", "9c565862810fb383e9838c1dd2d7d2c437b3d13b267414ba6af33e50d2d1cf28"}, "nimble_pool": {:hex, :nimble_pool, "1.0.0", "5eb82705d138f4dd4423f69ceb19ac667b3b492ae570c9f5c900bb3d2f50a847", [:mix], [], "hexpm", "80be3b882d2d351882256087078e1b1952a28bf98d0a287be87e4a24a710b67a"}, "oauth2": {:hex, :oauth2, "2.1.0", "beb657f393814a3a7a8a15bd5e5776ecae341fd344df425342a3b6f1904c2989", [:mix], [{:tesla, "~> 1.5", [hex: :tesla, repo: "hexpm", optional: false]}], "hexpm", "8ac07f85b3307dd1acfeb0ec852f64161b22f57d0ce0c15e616a1dfc8ebe2b41"}, - "oban": {:hex, :oban, "2.17.3", "ddfd5710aadcd550d2e174c8d73ce5f1865601418cf54a91775f20443fb832b7", [:mix], [{:ecto_sql, "~> 3.6", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:ecto_sqlite3, "~> 0.9", [hex: :ecto_sqlite3, repo: "hexpm", optional: true]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.16", [hex: :postgrex, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "452eada8bfe0d0fefd0740ab5fa8cf3ef6c375df0b4a3c3805d179022a04738a"}, + "oban": {:hex, :oban, "2.17.6", "bac1dacd836edbf6a200ddd880db10faa2d39bb2e550ec6d19b3eb9c43852c2a", [:mix], [{:ecto_sql, "~> 3.10", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:ecto_sqlite3, "~> 0.9", [hex: :ecto_sqlite3, repo: "hexpm", optional: true]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.16", [hex: :postgrex, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "623f3554212e9a776e015156c47f076d66c7b74115ac47a7d3acba0294e65acb"}, + "openid_connect": {:hex, :openid_connect, "0.2.2", "c05055363330deab39ffd89e609db6b37752f255a93802006d83b45596189c0b", [:mix], [{:httpoison, "~> 1.2", [hex: :httpoison, repo: "hexpm", optional: false]}, {:jason, ">= 1.0.0", [hex: :jason, repo: "hexpm", optional: false]}, {:jose, "~> 1.8", [hex: :jose, repo: "hexpm", optional: false]}], "hexpm", "735769b6d592124b58edd0582554ce638524c0214cd783d8903d33357d74cc13"}, "p1_utils": {:hex, :p1_utils, "1.0.15", "731f76ae1f31f4554afb2ae629cb5589d53bd13efc72b11f5a7c3b1242f91046", [:rebar3], [], "hexpm", "1d308c3f37d7f770fb39abe3b86701b82d54414bc2499d9499edde3cb50bcf19"}, "parallel_stream": {:hex, :parallel_stream, "1.1.0", "f52f73eb344bc22de335992377413138405796e0d0ad99d995d9977ac29f1ca9", [:mix], [], "hexpm", "684fd19191aedfaf387bbabbeb8ff3c752f0220c8112eb907d797f4592d6e871"}, "parse_trans": {:hex, :parse_trans, "3.4.1", "6e6aa8167cb44cc8f39441d05193be6e6f4e7c2946cb2759f015f8c56b76e5ff", [:rebar3], [], "hexpm", "620a406ce75dada827b82e453c19cf06776be266f5a67cff34e1ef2cbb60e49a"}, "phoenix": {:hex, :phoenix, "1.7.11", "1d88fc6b05ab0c735b250932c4e6e33bfa1c186f76dcf623d8dd52f07d6379c7", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.7", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:websock_adapter, "~> 0.5.3", [hex: :websock_adapter, repo: "hexpm", optional: false]}], "hexpm", "b1ec57f2e40316b306708fe59b92a16b9f6f4bf50ccfa41aa8c7feb79e0ec02a"}, - "phoenix_ecto": {:hex, :phoenix_ecto, "4.4.3", "86e9878f833829c3f66da03d75254c155d91d72a201eb56ae83482328dc7ca93", [:mix], [{:ecto, "~> 3.5", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "d36c401206f3011fefd63d04e8ef626ec8791975d9d107f9a0817d426f61ac07"}, + "phoenix_ecto": {:hex, :phoenix_ecto, "4.5.1", "6fdbc334ea53620e71655664df6f33f670747b3a7a6c4041cdda3e2c32df6257", [:mix], [{:ecto, "~> 3.5", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.1", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "ebe43aa580db129e54408e719fb9659b7f9e0d52b965c5be26cdca416ecead28"}, "phoenix_html": {:hex, :phoenix_html, "3.3.3", "380b8fb45912b5638d2f1d925a3771b4516b9a78587249cabe394e0a5d579dc9", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "923ebe6fec6e2e3b3e569dfbdc6560de932cd54b000ada0208b5f45024bdd76c"}, - "phoenix_live_reload": {:hex, :phoenix_live_reload, "1.4.1", "2aff698f5e47369decde4357ba91fc9c37c6487a512b41732818f2204a8ef1d3", [: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", "9bffb834e7ddf08467fe54ae58b5785507aaba6255568ae22b4d46e2bb3615ab"}, - "phoenix_live_view": {:hex, :phoenix_live_view, "0.20.0", "3f3531c835e46a3b45b4c3ca4a09cef7ba1d0f0d0035eef751c7084b8adb1299", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.6.15 or ~> 1.7.0", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 3.3", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "29875f8a58fb031f2dc8f3be025c92ed78d342b46f9bbf6dfe579549d7c81050"}, + "phoenix_live_reload": {:hex, :phoenix_live_reload, "1.5.2", "354460993a480656b71c3887f5565f612b3bdbdd8688c83f9e6f512307067dd4", [:mix], [{:file_system, "~> 0.3 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.4", [hex: :phoenix, repo: "hexpm", optional: false]}], "hexpm", "2bb3722f327e14a7aa47b1acf27ed633c8cd27b167e18b8237954b9b4804af39"}, + "phoenix_live_view": {:hex, :phoenix_live_view, "0.20.14", "70fa101aa0539e81bed4238777498f6215e9dda3461bdaa067cad6908110c364", [:mix], [{:floki, "~> 0.36", [hex: :floki, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.6.15 or ~> 1.7.0", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 3.3 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.15", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "82f6d006c5264f979ed5eb75593d808bbe39020f20df2e78426f4f2d570e2402"}, "phoenix_pubsub": {:hex, :phoenix_pubsub, "2.1.3", "3168d78ba41835aecad272d5e8cd51aa87a7ac9eb836eabc42f6e57538e3731d", [:mix], [], "hexpm", "bba06bc1dcfd8cb086759f0edc94a8ba2bc8896d5331a1e2c2902bf8e36ee502"}, "phoenix_template": {:hex, :phoenix_template, "1.0.4", "e2092c132f3b5e5b2d49c96695342eb36d0ed514c5b252a77048d5969330d639", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}], "hexpm", "2c0c81f0e5c6753faf5cca2f229c9709919aba34fab866d3bc05060c9c444206"}, "phoenix_view": {:hex, :phoenix_view, "2.0.3", "4d32c4817fce933693741deeb99ef1392619f942633dde834a5163124813aad3", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}], "hexpm", "cd34049af41be2c627df99cd4eaa71fc52a328c0c3d8e7d4aa28f880c30e7f64"}, @@ -78,7 +82,7 @@ "plug_assign": {:hex, :plug_assign, "2.0.2", "19e827d254711a93b8ef1eab07b6b0932f2bc649f80b8245ad9e73e381a3064f", [:mix], [{:plug, "~> 1.15", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "0d8d72961d2d838aaddf020d49ad6f83270d7d9e2bc420458d33bb795d012810"}, "plug_canonical_host": {:hex, :plug_canonical_host, "2.0.3", "3d96c3340cc8a434eb6758a4a34de6c152bd781be96bb8439545da2d17ecf576", [:make, :mix], [{:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "aca98ac6d0036391b84d5a40af6f946c839fb0d588bf0064029a2e8931431ea6"}, "plug_crypto": {:hex, :plug_crypto, "2.0.0", "77515cc10af06645abbfb5e6ad7a3e9714f805ae118fa1a70205f80d2d70fe73", [:mix], [], "hexpm", "53695bae57cc4e54566d993eb01074e4d894b65a3766f1c43e2c61a1b0f45ea9"}, - "postgrex": {:hex, :postgrex, "0.17.4", "5777781f80f53b7c431a001c8dad83ee167bcebcf3a793e3906efff680ab62b3", [:mix], [{:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "6458f7d5b70652bc81c3ea759f91736c16a31be000f306d3c64bcdfe9a18b3cc"}, + "postgrex": {:hex, :postgrex, "0.17.5", "0483d054938a8dc069b21bdd636bf56c487404c241ce6c319c1f43588246b281", [:mix], [{:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "50b8b11afbb2c4095a3ba675b4f055c416d0f3d7de6633a595fc131a828a67eb"}, "ranch": {:hex, :ranch, "2.1.0", "2261f9ed9574dcfcc444106b9f6da155e6e540b2f82ba3d42b339b93673b72a3", [:make, :rebar3], [], "hexpm", "244ee3fa2a6175270d8e1fc59024fd9dbc76294a321057de8f803b1479e76916"}, "scrivener": {:hex, :scrivener, "2.7.2", "1d913c965ec352650a7f864ad7fd8d80462f76a32f33d57d1e48bc5e9d40aba2", [:mix], [], "hexpm", "7866a0ec4d40274efbee1db8bead13a995ea4926ecd8203345af8f90d2b620d9"}, "scrivener_ecto": {:hex, :scrivener_ecto, "2.7.0", "cf64b8cb8a96cd131cdbcecf64e7fd395e21aaa1cb0236c42a7c2e34b0dca580", [:mix], [{:ecto, "~> 3.3", [hex: :ecto, repo: "hexpm", optional: false]}, {:scrivener, "~> 2.4", [hex: :scrivener, repo: "hexpm", optional: false]}], "hexpm", "e809f171687806b0031129034352f5ae44849720c48dd839200adeaf0ac3e260"}, @@ -89,20 +93,21 @@ "table": {:hex, :table, "0.1.2", "87ad1125f5b70c5dea0307aa633194083eb5182ec537efc94e96af08937e14a8", [:mix], [], "hexpm", "7e99bc7efef806315c7e65640724bf165c3061cdc5d854060f74468367065029"}, "table_rex": {:hex, :table_rex, "4.0.0", "3c613a68ebdc6d4d1e731bc973c233500974ec3993c99fcdabb210407b90959b", [:mix], [], "hexpm", "c35c4d5612ca49ebb0344ea10387da4d2afe278387d4019e4d8111e815df8f55"}, "telemetry": {:hex, :telemetry, "1.2.1", "68fdfe8d8f05a8428483a97d7aab2f268aaff24b49e0f599faa091f1d4e7f61c", [:rebar3], [], "hexpm", "dad9ce9d8effc621708f99eac538ef1cbe05d6a874dd741de2e689c47feafed5"}, - "telemetry_metrics": {:hex, :telemetry_metrics, "0.6.1", "315d9163a1d4660aedc3fee73f33f1d355dcc76c5c3ab3d59e76e3edf80eef1f", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7be9e0871c41732c233be71e4be11b96e56177bf15dde64a8ac9ce72ac9834c6"}, + "telemetry_metrics": {:hex, :telemetry_metrics, "0.6.2", "2caabe9344ec17eafe5403304771c3539f3b6e2f7fb6a6f602558c825d0d0bfb", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "9b43db0dc33863930b9ef9d27137e78974756f5f198cae18409970ed6fa5b561"}, "telemetry_poller": {:hex, :telemetry_poller, "1.0.0", "db91bb424e07f2bb6e73926fcafbfcbcb295f0193e0a00e825e589a0a47e8453", [:rebar3], [{:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "b3a24eafd66c3f42da30fc3ca7dda1e9d546c12250a2d60d7b81d264fbec4f6e"}, - "telemetry_ui": {:hex, :telemetry_ui, "4.1.0", "d69be6a89fd78c7030011363dbed735afb558a925dac24ee2615aae588375d9e", [:mix], [{:ecto, "~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:ecto_sql, "~> 3.0", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:oban, "~> 2.13", [hex: :oban, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.4", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_ecto, "~> 4.4", [hex: :phoenix_ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 0.18", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 1.0 or ~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.16", [hex: :postgrex, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 0.6", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}, {:telemetry_poller, "~> 1.0", [hex: :telemetry_poller, repo: "hexpm", optional: false]}, {:timex, "~> 3.7", [hex: :timex, repo: "hexpm", optional: false]}, {:vega_lite, "~> 0.1", [hex: :vega_lite, repo: "hexpm", optional: false]}, {:vega_lite_convert, "~> 0.6", [hex: :vega_lite_convert, repo: "hexpm", optional: true]}, {:vix, "~> 0.16", [hex: :vix, repo: "hexpm", optional: true]}], "hexpm", "6e5af411bdc7bbd4ab88294c4f58391ce7ec6cba7119fcb3799e2ec2de7104fa"}, + "telemetry_ui": {:hex, :telemetry_ui, "4.2.0", "a1e883440818bb84a78718fbd9d5c6917988d5ff4e1c19687fd9ad3ab1a108e8", [:mix], [{:ecto, "~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:ecto_sql, "~> 3.0", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:oban, "~> 2.13", [hex: :oban, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.4", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_ecto, "~> 4.4", [hex: :phoenix_ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 3.0 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 0.18", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 1.0 or ~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.16", [hex: :postgrex, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 0.6", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}, {:telemetry_poller, "~> 1.0", [hex: :telemetry_poller, repo: "hexpm", optional: false]}, {:timex, "~> 3.7", [hex: :timex, repo: "hexpm", optional: false]}, {:vega_lite, "~> 0.1", [hex: :vega_lite, repo: "hexpm", optional: false]}, {:vega_lite_convert, "~> 0.6", [hex: :vega_lite_convert, repo: "hexpm", optional: true]}, {:vix, "~> 0.16", [hex: :vix, repo: "hexpm", optional: true]}], "hexpm", "b321a4915b91a9dc6c3763a2b5bd5e2f9425c7e4680203075684b327bfce9534"}, "tesla": {:hex, :tesla, "1.8.0", "d511a4f5c5e42538d97eef7c40ec4f3e44effdc5068206f42ed859e09e51d1fd", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:exjsx, ">= 3.0.0", [hex: :exjsx, repo: "hexpm", optional: true]}, {:finch, "~> 0.13", [hex: :finch, repo: "hexpm", optional: true]}, {:fuse, "~> 2.4", [hex: :fuse, repo: "hexpm", optional: true]}, {:gun, ">= 1.0.0", [hex: :gun, repo: "hexpm", optional: true]}, {:hackney, "~> 1.6", [hex: :hackney, repo: "hexpm", optional: true]}, {:ibrowse, "4.4.2", [hex: :ibrowse, repo: "hexpm", optional: true]}, {:jason, ">= 1.0.0", [hex: :jason, repo: "hexpm", optional: true]}, {:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.0", [hex: :mint, repo: "hexpm", optional: true]}, {:msgpax, "~> 2.3", [hex: :msgpax, repo: "hexpm", optional: true]}, {:poison, ">= 1.0.0", [hex: :poison, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "10501f360cd926a309501287470372af1a6e1cbed0f43949203a4c13300bc79f"}, - "thousand_island": {:hex, :thousand_island, "1.3.2", "bc27f9afba6e1a676dd36507d42e429935a142cf5ee69b8e3f90bff1383943cd", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "0e085b93012cd1057b378fce40cbfbf381ff6d957a382bfdd5eca1a98eec2535"}, + "thousand_island": {:hex, :thousand_island, "1.3.5", "6022b6338f1635b3d32406ff98d68b843ba73b3aa95cfc27154223244f3a6ca5", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "2be6954916fdfe4756af3239fb6b6d75d0b8063b5df03ba76fd8a4c87849e180"}, "timex": {:hex, :timex, "3.7.11", "bb95cb4eb1d06e27346325de506bcc6c30f9c6dea40d1ebe390b262fad1862d1", [:mix], [{:combine, "~> 0.10", [hex: :combine, repo: "hexpm", optional: false]}, {:gettext, "~> 0.20", [hex: :gettext, repo: "hexpm", optional: false]}, {:tzdata, "~> 1.1", [hex: :tzdata, repo: "hexpm", optional: false]}], "hexpm", "8b9024f7efbabaf9bd7aa04f65cf8dcd7c9818ca5737677c7b76acbc6a94d1aa"}, - "tls_certificate_check": {:hex, :tls_certificate_check, "1.21.0", "042ab2c0c860652bc5cf69c94e3a31f96676d14682e22ec7813bd173ceff1788", [:rebar3], [{:ssl_verify_fun, "~> 1.1", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm", "6cee6cffc35a390840d48d463541d50746a7b0e421acaadb833cfc7961e490e7"}, + "tls_certificate_check": {:hex, :tls_certificate_check, "1.22.1", "0f450cc1568a67a65ce5e15df53c53f9a098c3da081c5f126199a72505858dc1", [:rebar3], [{:ssl_verify_fun, "~> 1.1", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm", "3092be0babdc0e14c2e900542351e066c0fa5a9cf4b3597559ad1e67f07938c0"}, "tzdata": {:hex, :tzdata, "1.1.1", "20c8043476dfda8504952d00adac41c6eda23912278add38edc140ae0c5bcc46", [:mix], [{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "a69cec8352eafcd2e198dea28a34113b60fdc6cb57eb5ad65c10292a6ba89787"}, - "ueberauth": {:hex, :ueberauth, "0.10.7", "5a31cbe11e7ce5c7484d745dc9e1f11948e89662f8510d03c616de03df581ebd", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "0bccf73e2ffd6337971340832947ba232877aa8122dba4c95be9f729c8987377"}, + "ueberauth": {:hex, :ueberauth, "0.10.8", "ba78fbcbb27d811a6cd06ad851793aaf7d27c3b30c9e95349c2c362b344cd8f0", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "f2d3172e52821375bccb8460e5fa5cb91cfd60b19b636b6e57e9759b6f8c10c1"}, "ueberauth_auth0": {:hex, :ueberauth_auth0, "2.1.0", "0632d5844049fa2f26823f15e1120aa32f27df6f27ce515a4b04641736594bf4", [:mix], [{:oauth2, "~> 2.0", [hex: :oauth2, repo: "hexpm", optional: false]}, {:ueberauth, "~> 0.7", [hex: :ueberauth, repo: "hexpm", optional: false]}], "hexpm", "8d3b30fa27c95c9e82c30c4afb016251405706d2e9627e603c3c9787fd1314fc"}, "ueberauth_discord": {:hex, :ueberauth_discord, "0.7.0", "463f6dfe1ed10a76739331ce8e1dd3600ab611f10524dd828eb3aa50e76e9d43", [:mix], [{:oauth2, "~> 1.0 or ~> 2.0", [hex: :oauth2, repo: "hexpm", optional: false]}, {:ueberauth, "~> 0.7", [hex: :ueberauth, repo: "hexpm", optional: false]}], "hexpm", "d6f98ef91abb4ddceada4b7acba470e0e68c4d2de9735ff2f24172a8e19896b4"}, "ueberauth_github": {:hex, :ueberauth_github, "0.8.3", "1c478629b4c1dae446c68834b69194ad5cead3b6c67c913db6fdf64f37f0328f", [:mix], [{:oauth2, "~> 1.0 or ~> 2.0", [hex: :oauth2, repo: "hexpm", optional: false]}, {:ueberauth, "~> 0.7", [hex: :ueberauth, repo: "hexpm", optional: false]}], "hexpm", "ae0ab2879c32cfa51d7287a48219b262bfdab0b7ec6629f24160564247493cc6"}, "ueberauth_google": {:hex, :ueberauth_google, "0.12.1", "90cf49743588193334f7a00da252f92d90bfd178d766c0e4291361681fafec7d", [:mix], [{:oauth2, "~> 1.0 or ~> 2.0", [hex: :oauth2, repo: "hexpm", optional: false]}, {:ueberauth, "~> 0.10.0", [hex: :ueberauth, repo: "hexpm", optional: false]}], "hexpm", "7f7deacd679b2b66e3bffb68ecc77aa1b5396a0cbac2941815f253128e458c38"}, "ueberauth_microsoft": {:hex, :ueberauth_microsoft, "0.23.0", "5c78e02a83d821ee45f96216bb6140ba688cc79b8b26e7ff438e3abe24615e1d", [:mix], [{:oauth2, "~> 1.0 or ~> 2.0", [hex: :oauth2, repo: "hexpm", optional: false]}, {:ueberauth, "~> 0.7", [hex: :ueberauth, repo: "hexpm", optional: false]}], "hexpm", "0c08d98203e6d3069f30306f09a6cb55b95c2bda94d6f8e90f05bd442ee96b82"}, + "ueberauth_oidc": {:hex, :ueberauth_oidc, "0.1.7", "d610cbe5ef09881dff52126906b130307adcf02791ce158c1847fd50949b283a", [:mix], [{:httpoison, "~> 1.8", [hex: :httpoison, repo: "hexpm", optional: false]}, {:jose, "~> 1.11", [hex: :jose, repo: "hexpm", optional: false]}, {:openid_connect, "~> 0.2.2", [hex: :openid_connect, repo: "hexpm", optional: false]}, {:plug, "~> 1.11", [hex: :plug, repo: "hexpm", optional: false]}, {:ueberauth, "~> 0.7", [hex: :ueberauth, repo: "hexpm", optional: false]}], "hexpm", "34d612f66a5425af4142d6c9dece887c60188c31e1dc113e5ee8cecdc6c5e8a9"}, "unicode_util_compat": {:hex, :unicode_util_compat, "0.7.0", "bc84380c9ab48177092f43ac89e4dfa2c6d62b40b8bd132b1059ecc7232f9a78", [:rebar3], [], "hexpm", "25eee6d67df61960cf6a794239566599b09e17e668d3700247bc498638152521"}, "unsafe": {:hex, :unsafe, "1.0.2", "23c6be12f6c1605364801f4b47007c0c159497d0446ad378b5cf05f1855c0581", [:mix], [], "hexpm", "b485231683c3ab01a9cd44cb4a79f152c6f3bb87358439c6f68791b85c2df675"}, "vega_lite": {:hex, :vega_lite, "0.1.8", "7f6119126ecaf4bc2c1854084370d7091424f5cce4795fbac044eee9963f0752", [:mix], [{:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: false]}], "hexpm", "6c8a9271f850612dd8a90de8d1ebd433590ed07ffef76fc2397c240dc04d3fdc"}, diff --git a/package-lock.json b/package-lock.json index d105a6187..d3eb54982 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,15 +11,15 @@ "@babel/eslint-parser": "7.17.0", "@typescript-eslint/eslint-plugin": "5.12.1", "@typescript-eslint/parser": "5.12.1", - "ember-template-lint": "5.2.0", - "ember-template-lint-plugin-prettier": "4.1.0", + "ember-template-lint": "5.13.0", + "ember-template-lint-plugin-prettier": "5.0.0", "eslint": "8.10.0", "eslint-config-prettier": "8.4.0", "eslint-plugin-ember": "10.5.9", "eslint-plugin-mirego": "^1.0.0", "eslint-plugin-node": "11.1.0", "eslint-plugin-sonarjs": "0.12.0", - "prettier": "2.5.1", + "prettier": "3.2.5", "typescript": "4.7.4" }, "engines": { @@ -741,6 +741,18 @@ "node": ">=6.0.0" } }, + "node_modules/@babel/runtime": { + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.9.tgz", + "integrity": "sha512-0CX6F+BI2s9dkUqr08KFrAIZgNFj75rdBU/DjCyYLIaV/quFjkk6T+EJ2LkZHyZTbEV4L5p97mNkUsHl2wLFAw==", + "dev": true, + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@ember-data/rfc395-data": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/@ember-data/rfc395-data/-/rfc395-data-0.0.4.tgz", @@ -798,67 +810,67 @@ "dev": true }, "node_modules/@glimmer/global-context": { - "version": "0.83.1", - "resolved": "https://registry.npmjs.org/@glimmer/global-context/-/global-context-0.83.1.tgz", - "integrity": "sha512-OwlgqpbOJU73EjZOZdftab0fKbtdJ4x/QQeJseL9cvaAUiK3+w52M5ONFxD1T/yPBp2Mf7NCYqA/uL8tRbzY2A==", + "version": "0.84.3", + "resolved": "https://registry.npmjs.org/@glimmer/global-context/-/global-context-0.84.3.tgz", + "integrity": "sha512-8Oy9Wg5IZxMEeAnVmzD2NkObf89BeHoFSzJgJROE/deutd3rxg83mvlOez4zBBGYwnTb+VGU2LYRpet92egJjA==", "dev": true, "dependencies": { "@glimmer/env": "^0.1.7" } }, "node_modules/@glimmer/interfaces": { - "version": "0.83.1", - "resolved": "https://registry.npmjs.org/@glimmer/interfaces/-/interfaces-0.83.1.tgz", - "integrity": "sha512-rjAztghzX97v8I4rk3+NguM3XGYcFjc/GbJ8qrEj19KF2lUDoDBW1sB7f0tov3BD5HlrGXei/vOh4+DHfjeB5w==", + "version": "0.84.3", + "resolved": "https://registry.npmjs.org/@glimmer/interfaces/-/interfaces-0.84.3.tgz", + "integrity": "sha512-dk32ykoNojt0mvEaIW6Vli5MGTbQo58uy3Epj7ahCgTHmWOKuw/0G83f2UmFprRwFx689YTXG38I/vbpltEjzg==", "dev": true, "dependencies": { "@simple-dom/interface": "^1.4.0" } }, "node_modules/@glimmer/reference": { - "version": "0.83.1", - "resolved": "https://registry.npmjs.org/@glimmer/reference/-/reference-0.83.1.tgz", - "integrity": "sha512-BThEwDlMkJB1WBPWDrww+VxgGyDbwxh5FFPvGhkovvCZnCb7fAMUCt9pi6CUZtviugkWOBFtE9P4eZZbOLkXeg==", + "version": "0.84.3", + "resolved": "https://registry.npmjs.org/@glimmer/reference/-/reference-0.84.3.tgz", + "integrity": "sha512-lV+p/aWPVC8vUjmlvYVU7WQJsLh319SdXuAWoX/SE3pq340BJlAJiEcAc6q52y9JNhT57gMwtjMX96W5Xcx/qw==", "dev": true, "dependencies": { "@glimmer/env": "^0.1.7", - "@glimmer/global-context": "0.83.1", - "@glimmer/interfaces": "0.83.1", - "@glimmer/util": "0.83.1", - "@glimmer/validator": "0.83.1" + "@glimmer/global-context": "0.84.3", + "@glimmer/interfaces": "0.84.3", + "@glimmer/util": "0.84.3", + "@glimmer/validator": "0.84.3" } }, "node_modules/@glimmer/syntax": { - "version": "0.83.1", - "resolved": "https://registry.npmjs.org/@glimmer/syntax/-/syntax-0.83.1.tgz", - "integrity": "sha512-n3vEd0GtjtgkOsd2gqkSimp8ecqq5KrHyana/s1XJZvVAPD5rMWT9WvAVWG8XAktns8BxjwLIUoj/vkOfA+eHg==", + "version": "0.84.3", + "resolved": "https://registry.npmjs.org/@glimmer/syntax/-/syntax-0.84.3.tgz", + "integrity": "sha512-ioVbTic6ZisLxqTgRBL2PCjYZTFIwobifCustrozRU2xGDiYvVIL0vt25h2c1ioDsX59UgVlDkIK4YTAQQSd2A==", "dev": true, "dependencies": { - "@glimmer/interfaces": "0.83.1", - "@glimmer/util": "0.83.1", + "@glimmer/interfaces": "0.84.3", + "@glimmer/util": "0.84.3", "@handlebars/parser": "~2.0.0", "simple-html-tokenizer": "^0.5.11" } }, "node_modules/@glimmer/util": { - "version": "0.83.1", - "resolved": "https://registry.npmjs.org/@glimmer/util/-/util-0.83.1.tgz", - "integrity": "sha512-amvjtl9dvrkxsoitXAly9W5NUaLIE3A2J2tWhBWIL1Z6DOFotfX7ytIosOIcPhJLZCtiXPHzMutQRv0G/MSMsA==", + "version": "0.84.3", + "resolved": "https://registry.npmjs.org/@glimmer/util/-/util-0.84.3.tgz", + "integrity": "sha512-qFkh6s16ZSRuu2rfz3T4Wp0fylFj3HBsONGXQcrAdZjdUaIS6v3pNj6mecJ71qRgcym9Hbaq/7/fefIwECUiKw==", "dev": true, "dependencies": { "@glimmer/env": "0.1.7", - "@glimmer/interfaces": "0.83.1", + "@glimmer/interfaces": "0.84.3", "@simple-dom/interface": "^1.4.0" } }, "node_modules/@glimmer/validator": { - "version": "0.83.1", - "resolved": "https://registry.npmjs.org/@glimmer/validator/-/validator-0.83.1.tgz", - "integrity": "sha512-LaILSNnQgDHZpaUsfjVndbS1JfVn0xdTlJdFJblPbhoVklOBSReZVekens3EQ6xOr3BC612sRm1hBnEPixOY6A==", + "version": "0.84.3", + "resolved": "https://registry.npmjs.org/@glimmer/validator/-/validator-0.84.3.tgz", + "integrity": "sha512-RTBV4TokUB0vI31UC7ikpV7lOYpWUlyqaKV//pRC4pexYMlmqnVhkFrdiimB/R1XyNdUOQUmnIAcdic39NkbhQ==", "dev": true, "dependencies": { "@glimmer/env": "^0.1.7", - "@glimmer/global-context": "0.83.1" + "@glimmer/global-context": "0.84.3" } }, "node_modules/@handlebars/parser": { @@ -916,17 +928,17 @@ } }, "node_modules/@lint-todo/utils": { - "version": "13.1.0", - "resolved": "https://registry.npmjs.org/@lint-todo/utils/-/utils-13.1.0.tgz", - "integrity": "sha512-uzcZPIPH7hcs+hKMiHfp58MosJpI9sTTgl1pGYau4zq34q1ppswJ6nLeohv/cDhqEBrHjtvldt8zDnVJXRvBlA==", + "version": "13.1.1", + "resolved": "https://registry.npmjs.org/@lint-todo/utils/-/utils-13.1.1.tgz", + "integrity": "sha512-F5z53uvRIF4dYfFfJP3a2Cqg+4P1dgJchJsFnsZE0eZp0LK8X7g2J0CsJHRgns+skpXOlM7n5vFGwkWCWj8qJg==", "dev": true, "dependencies": { - "@types/eslint": "^7.2.13", + "@types/eslint": "^8.4.9", "find-up": "^5.0.0", "fs-extra": "^9.1.0", "proper-lockfile": "^4.1.2", "slash": "^3.0.0", - "tslib": "^2.4.0", + "tslib": "^2.4.1", "upath": "^2.0.1" }, "engines": { @@ -1004,9 +1016,9 @@ } }, "node_modules/@lint-todo/utils/node_modules/tslib": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", "dev": true }, "node_modules/@lint-todo/utils/node_modules/yocto-queue": { @@ -1056,6 +1068,18 @@ "node": ">= 8" } }, + "node_modules/@prettier/sync": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@prettier/sync/-/sync-0.2.1.tgz", + "integrity": "sha512-7ls1R6//+GPYD9vof1XaL5psViv83CwpdwlS8oUkWldYgbPhzZ3WgxIQMWqGyBmWPmoBfQg8C7jj7KI/ZuDHhQ==", + "dev": true, + "funding": { + "url": "https://github.com/prettier/prettier-synchronized?sponsor=1" + }, + "peerDependencies": { + "prettier": "^3.0.0" + } + }, "node_modules/@simple-dom/interface": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/@simple-dom/interface/-/interface-1.4.0.tgz", @@ -1063,9 +1087,9 @@ "dev": true }, "node_modules/@types/eslint": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-7.29.0.tgz", - "integrity": "sha512-VNcvioYDH8/FxaeTKkM4/TiTwt6pBV9E3OfGmvaw8tPl0rrHCJ4Ll15HRT+pMiFAf/MLQvAzC+6RzUMEL9Ceng==", + "version": "8.56.3", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.3.tgz", + "integrity": "sha512-PvSf1wfv2wJpVIFUMSb+i4PvqNYkB9Rkp9ZDO3oaWzq4SKhsQk4mrMBr3ZH06I0hKrVGLBacmgl8JM4WVjb9dg==", "dev": true, "dependencies": { "@types/estree": "*", @@ -1073,9 +1097,9 @@ } }, "node_modules/@types/estree": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.0.tgz", - "integrity": "sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", "dev": true }, "node_modules/@types/json-schema": { @@ -1091,9 +1115,9 @@ "dev": true }, "node_modules/@types/symlink-or-copy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@types/symlink-or-copy/-/symlink-or-copy-1.2.0.tgz", - "integrity": "sha512-Lja2xYuuf2B3knEsga8ShbOdsfNOtzT73GyJmZyY7eGl2+ajOqrs8yM5ze0fsSoYwvA6bw7/Qr7OZ7PEEmYwWg==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@types/symlink-or-copy/-/symlink-or-copy-1.2.2.tgz", + "integrity": "sha512-MQ1AnmTLOncwEf9IVU+B2e4Hchrku5N67NkgcAHW0p3sdzPe0FNMANxEm6OJUzPniEQGkeT3OROLlCwZJLWFZA==", "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { @@ -1438,19 +1462,38 @@ "dev": true }, "node_modules/aria-query": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", - "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", + "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", "dev": true, "dependencies": { - "deep-equal": "^2.0.5" + "dequal": "^2.0.3" + } + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/array-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz", - "integrity": "sha512-H3LU5RLiSsGXPhN+Nipar0iR0IofH+8r89G2y1tBKxQ/agagKyAjhkAFDRBfodP2caPrNKHpAWNIM/c9yeL7uA==", - "dev": true + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.2.tgz", + "integrity": "sha512-gUHx76KtnhEgB3HOuFYiCm3FIdEs6ocM2asHvNTkfu/Y09qQVrrVVaOKENmS2KkSaGoxgXNqC+ZVtR/n0MOkSA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/array-union": { "version": "2.1.0", @@ -1461,6 +1504,28 @@ "node": ">=8" } }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", + "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.2.1", + "get-intrinsic": "^1.2.3", + "is-array-buffer": "^3.0.4", + "is-shared-array-buffer": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/async": { "version": "2.6.4", "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", @@ -1556,10 +1621,13 @@ } }, "node_modules/available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", "dev": true, + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, "engines": { "node": ">= 0.4" }, @@ -2025,13 +2093,19 @@ } }, "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", "dev": true, "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -2163,9 +2237,9 @@ } }, "node_modules/cli-spinners": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.7.0.tgz", - "integrity": "sha512-qu3pN8Y3qHNgE2AFweciB1IfMnmZ/fsNTEE+NOFjmGB2F/7rLhnhzppvpCnN4FovtP26k8lHyy9ptEbNwWFLzw==", + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", "dev": true, "engines": { "node": ">=6" @@ -2275,10 +2349,13 @@ } }, "node_modules/date-fns": { - "version": "2.29.3", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.29.3.tgz", - "integrity": "sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA==", + "version": "2.30.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", + "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", "dev": true, + "dependencies": { + "@babel/runtime": "^7.21.0" + }, "engines": { "node": ">=0.11" }, @@ -2304,34 +2381,6 @@ } } }, - "node_modules/deep-equal": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.0.tgz", - "integrity": "sha512-RdpzE0Hv4lhowpIUKKMJfeH6C1pXdtT1/it80ubgWqwI3qpuxUBpC1S4hnHg+zjnuOoDkzUtUCEEkG+XG5l3Mw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "es-get-iterator": "^1.1.2", - "get-intrinsic": "^1.1.3", - "is-arguments": "^1.1.1", - "is-array-buffer": "^3.0.1", - "is-date-object": "^1.0.5", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "isarray": "^2.0.5", - "object-is": "^1.1.5", - "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.4.3", - "side-channel": "^1.0.4", - "which-boxed-primitive": "^1.0.2", - "which-collection": "^1.0.1", - "which-typed-array": "^1.1.9" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -2350,12 +2399,30 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/define-properties": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", - "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", "dev": true, "dependencies": { + "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" }, @@ -2366,6 +2433,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -2440,9 +2516,9 @@ } }, "node_modules/ember-cli-version-checker/node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", "dev": true, "dependencies": { "lru-cache": "^6.0.0" @@ -2461,9 +2537,9 @@ "dev": true }, "node_modules/ember-template-imports": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/ember-template-imports/-/ember-template-imports-3.4.1.tgz", - "integrity": "sha512-KXnBFTAVxCfXnSCUgd/iuic9ajWbmFkRUBEeorJAMqxvougsPoK22s5ygE9O3GnzYdPpMwn+8v+/NAGy8HRBGA==", + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/ember-template-imports/-/ember-template-imports-3.4.2.tgz", + "integrity": "sha512-OS8TUVG2kQYYwP3netunLVfeijPoOKIs1SvPQRTNOQX4Pu8xGGBEZmrv0U1YTnQn12Eg+p6w/0UdGbUnITjyzw==", "dev": true, "dependencies": { "babel-import-util": "^0.2.0", @@ -2481,29 +2557,29 @@ } }, "node_modules/ember-template-lint": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ember-template-lint/-/ember-template-lint-5.2.0.tgz", - "integrity": "sha512-A0wQ1cmaTshIiVhl90QFiaTp1aLw0jy8/uUNWNwD/0PnnaKAi4Oz/wbfjKX/4ZKnhFHgjTFeVyeve1ItoqR7cg==", - "dev": true, - "dependencies": { - "@lint-todo/utils": "^13.0.3", - "aria-query": "^5.0.2", - "chalk": "^5.1.2", - "ci-info": "^3.7.0", - "date-fns": "^2.29.2", - "ember-template-imports": "^3.4.0", - "ember-template-recast": "^6.1.3", + "version": "5.13.0", + "resolved": "https://registry.npmjs.org/ember-template-lint/-/ember-template-lint-5.13.0.tgz", + "integrity": "sha512-AYxz9S9fVZfHPmTsymc7NwsD7FVmDUZyfC+KYpxDlK0wic7JSQx2FNQNqQSBFRLOuzn7VQ0/+1pX6DGqKDGswg==", + "dev": true, + "dependencies": { + "@lint-todo/utils": "^13.1.1", + "aria-query": "^5.3.0", + "chalk": "^5.3.0", + "ci-info": "^3.8.0", + "date-fns": "^2.30.0", + "ember-template-imports": "^3.4.2", + "ember-template-recast": "^6.1.4", "eslint-formatter-kakoune": "^1.0.0", "find-up": "^6.3.0", "fuse.js": "^6.5.3", "get-stdin": "^9.0.0", - "globby": "^13.1.2", + "globby": "^13.2.2", "is-glob": "^4.0.3", - "language-tags": "^1.0.6", + "language-tags": "^1.0.8", "micromatch": "^4.0.5", - "resolve": "^1.22.1", + "resolve": "^1.22.3", "v8-compile-cache": "^2.3.0", - "yargs": "^17.5.1" + "yargs": "^17.7.2" }, "bin": { "ember-template-lint": "bin/ember-template-lint.js" @@ -2513,25 +2589,26 @@ } }, "node_modules/ember-template-lint-plugin-prettier": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ember-template-lint-plugin-prettier/-/ember-template-lint-plugin-prettier-4.1.0.tgz", - "integrity": "sha512-LGGn1SXS5vhH60Tp37D4yG8z9ftVMCSSBn5qst+7rjMtLAZuZYwq+q+fs46op745ds0NNtaj+3OzSpBj+RVL2w==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ember-template-lint-plugin-prettier/-/ember-template-lint-plugin-prettier-5.0.0.tgz", + "integrity": "sha512-aXUYM4yuIdPZ80+AsAU8QBwGSJJ/aAkRsNcQ5vI5HmXiBjzHlDc/ZhmP6iVcYuCmoA/3iKcssMAYwIDbuby4pg==", "dev": true, "dependencies": { + "@prettier/sync": "^0.2.1", "prettier-linter-helpers": "^1.0.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^16.0.0 || ^18.0.0 || >=20.0.0" }, "peerDependencies": { "ember-template-lint": ">= 4.0.0", - "prettier": ">= 1.18.1" + "prettier": ">= 3.0.0" } }, "node_modules/ember-template-lint/node_modules/chalk": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.2.0.tgz", - "integrity": "sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", "dev": true, "engines": { "node": "^12.17.0 || ^14.13 || >=16.0.0" @@ -2541,14 +2618,14 @@ } }, "node_modules/ember-template-recast": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/ember-template-recast/-/ember-template-recast-6.1.3.tgz", - "integrity": "sha512-45lkfjrWlrMPlOd5rLFeQeePZwAvcS//x1x15kaiQTlqQdYWiYNXwbpWHqV+p9fXY6bEjl6EbyPhG/zBkgh8MA==", + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/ember-template-recast/-/ember-template-recast-6.1.4.tgz", + "integrity": "sha512-fCh+rOK6z+/tsdkTbOE+e7f84P6ObnIRQrCCrnu21E4X05hPeradikIkRMhJdxn4NWrxitfZskQDd37TR/lsNQ==", "dev": true, "dependencies": { - "@glimmer/reference": "^0.83.1", - "@glimmer/syntax": "^0.83.1", - "@glimmer/validator": "^0.83.0", + "@glimmer/reference": "^0.84.3", + "@glimmer/syntax": "^0.84.3", + "@glimmer/validator": "^0.84.3", "async-promise-queue": "^1.0.5", "colors": "^1.4.0", "commander": "^8.3.0", @@ -2556,7 +2633,7 @@ "ora": "^5.4.0", "slash": "^3.0.0", "tmp": "^0.2.1", - "workerpool": "^6.1.5" + "workerpool": "^6.4.0" }, "bin": { "ember-template-recast": "lib/bin.js" @@ -2598,44 +2675,52 @@ "dev": true }, "node_modules/es-abstract": { - "version": "1.21.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.1.tgz", - "integrity": "sha512-QudMsPOz86xYz/1dG1OuGBKOELjCh99IIWHLzy5znUB6j8xG2yMA7bfTV86VSqKF+Y/H08vQPR+9jyXpuC6hfg==", - "dev": true, - "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "es-set-tostringtag": "^2.0.1", + "version": "1.22.4", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.4.tgz", + "integrity": "sha512-vZYJlk2u6qHYxBOTjAeg7qUxHdNfih64Uu2J8QqWgXZ2cri0ZpJAkzDUK/q593+mvKwlxyaxr6F1Q+3LKoQRgg==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "arraybuffer.prototype.slice": "^1.0.3", + "available-typed-arrays": "^1.0.6", + "call-bind": "^1.0.7", + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.0.2", "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "function.prototype.name": "^1.1.5", - "get-intrinsic": "^1.1.3", - "get-symbol-description": "^1.0.0", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.4", + "get-symbol-description": "^1.0.2", "globalthis": "^1.0.3", "gopd": "^1.0.1", - "has": "^1.0.3", - "has-property-descriptors": "^1.0.0", + "has-property-descriptors": "^1.0.2", "has-proto": "^1.0.1", "has-symbols": "^1.0.3", - "internal-slot": "^1.0.4", - "is-array-buffer": "^3.0.1", + "hasown": "^2.0.1", + "internal-slot": "^1.0.7", + "is-array-buffer": "^3.0.4", "is-callable": "^1.2.7", "is-negative-zero": "^2.0.2", "is-regex": "^1.1.4", "is-shared-array-buffer": "^1.0.2", "is-string": "^1.0.7", - "is-typed-array": "^1.1.10", + "is-typed-array": "^1.1.13", "is-weakref": "^1.0.2", - "object-inspect": "^1.12.2", + "object-inspect": "^1.13.1", "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.4.3", - "safe-regex-test": "^1.0.0", - "string.prototype.trimend": "^1.0.6", - "string.prototype.trimstart": "^1.0.6", + "object.assign": "^4.1.5", + "regexp.prototype.flags": "^1.5.2", + "safe-array-concat": "^1.1.0", + "safe-regex-test": "^1.0.3", + "string.prototype.trim": "^1.2.8", + "string.prototype.trimend": "^1.0.7", + "string.prototype.trimstart": "^1.0.7", + "typed-array-buffer": "^1.0.1", + "typed-array-byte-length": "^1.0.0", + "typed-array-byte-offset": "^1.0.0", "typed-array-length": "^1.0.4", "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.9" + "which-typed-array": "^1.1.14" }, "engines": { "node": ">= 0.4" @@ -2644,35 +2729,36 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/es-get-iterator": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", - "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "has-symbols": "^1.0.3", - "is-arguments": "^1.1.1", - "is-map": "^2.0.2", - "is-set": "^2.0.2", - "is-string": "^1.0.7", - "isarray": "^2.0.5", - "stop-iteration-iterator": "^1.0.0" + "get-intrinsic": "^1.2.4" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "engines": { + "node": ">= 0.4" } }, "node_modules/es-set-tostringtag": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", - "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", + "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", "dev": true, "dependencies": { - "get-intrinsic": "^1.1.3", - "has": "^1.0.3", - "has-tostringtag": "^1.0.0" + "get-intrinsic": "^1.2.4", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.1" }, "engines": { "node": ">= 0.4" @@ -3119,9 +3205,9 @@ "dev": true }, "node_modules/fast-glob": { - "version": "3.2.12", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", - "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "dev": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", @@ -3294,21 +3380,24 @@ "dev": true }, "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/function.prototype.name": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", - "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.0", - "functions-have-names": "^1.2.2" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" }, "engines": { "node": ">= 0.4" @@ -3361,14 +3450,19 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", - "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", "dev": true, "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.3" + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -3387,13 +3481,14 @@ } }, "node_modules/get-symbol-description": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", - "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", + "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" + "call-bind": "^1.0.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4" }, "engines": { "node": ">= 0.4" @@ -3457,14 +3552,14 @@ } }, "node_modules/globby": { - "version": "13.1.3", - "resolved": "https://registry.npmjs.org/globby/-/globby-13.1.3.tgz", - "integrity": "sha512-8krCNHXvlCgHDpegPzleMq07yMYTO2sXKASmZmquEYWEmCx6J5UTRbp5RwMJkTJGtcQ44YpiUYUiN0b9mzy8Bw==", + "version": "13.2.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-13.2.2.tgz", + "integrity": "sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==", "dev": true, "dependencies": { "dir-glob": "^3.0.1", - "fast-glob": "^3.2.11", - "ignore": "^5.2.0", + "fast-glob": "^3.3.0", + "ignore": "^5.2.4", "merge2": "^1.4.1", "slash": "^4.0.0" }, @@ -3500,23 +3595,11 @@ } }, "node_modules/graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "dev": true }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, "node_modules/has-bigints": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", @@ -3536,21 +3619,21 @@ } }, "node_modules/has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dev": true, "dependencies": { - "get-intrinsic": "^1.1.1" + "es-define-property": "^1.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", "dev": true, "engines": { "node": ">= 0.4" @@ -3572,12 +3655,12 @@ } }, "node_modules/has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "dev": true, "dependencies": { - "has-symbols": "^1.0.2" + "has-symbols": "^1.0.3" }, "engines": { "node": ">= 0.4" @@ -3610,6 +3693,18 @@ "resolve": "^1.10.0" } }, + "node_modules/hasown": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.1.tgz", + "integrity": "sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/heimdalljs": { "version": "0.2.6", "resolved": "https://registry.npmjs.org/heimdalljs/-/heimdalljs-0.2.6.tgz", @@ -3671,9 +3766,9 @@ ] }, "node_modules/ignore": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", - "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", "dev": true, "engines": { "node": ">= 4" @@ -3718,27 +3813,27 @@ "dev": true }, "node_modules/internal-slot": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", - "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", + "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", "dev": true, "dependencies": { - "get-intrinsic": "^1.2.0", - "has": "^1.0.3", + "es-errors": "^1.3.0", + "hasown": "^2.0.0", "side-channel": "^1.0.4" }, "engines": { "node": ">= 0.4" } }, - "node_modules/is-arguments": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", - "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "node_modules/is-array-buffer": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", + "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "get-intrinsic": "^1.2.1" }, "engines": { "node": ">= 0.4" @@ -3747,20 +3842,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-array-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.1.tgz", - "integrity": "sha512-ASfLknmY8Xa2XtB4wmbz13Wu202baeA18cJBCeCy0wXUHZF0IPyVEXqKEcd+t2fNSLLL1vC6k7lxZEojNbISXQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "is-typed-array": "^1.1.10" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-bigint": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", @@ -3802,12 +3883,12 @@ } }, "node_modules/is-core-module": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", - "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", "dev": true, "dependencies": { - "has": "^1.0.3" + "hasown": "^2.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -3867,19 +3948,10 @@ "node": ">=8" } }, - "node_modules/is-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", - "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-negative-zero": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", - "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", "dev": true, "engines": { "node": ">= 0.4" @@ -3928,22 +4000,16 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-set": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", - "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-shared-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", - "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", "dev": true, "dependencies": { - "call-bind": "^1.0.2" + "call-bind": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -3980,16 +4046,12 @@ } }, "node_modules/is-typed-array": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", - "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", "dev": true, "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" + "which-typed-array": "^1.1.14" }, "engines": { "node": ">= 0.4" @@ -4010,15 +4072,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-weakmap": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", - "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-weakref": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", @@ -4031,23 +4084,10 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-weakset": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz", - "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", "dev": true }, "node_modules/isexe": { @@ -4068,12 +4108,6 @@ "node": ">=0.10.0" } }, - "node_modules/isobject/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true - }, "node_modules/istextorbinary": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-2.1.0.tgz", @@ -4188,12 +4222,6 @@ "isobject": "^2.0.0" } }, - "node_modules/line-column/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true - }, "node_modules/locate-path": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", @@ -4426,26 +4454,10 @@ } }, "node_modules/object-inspect": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", - "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-is": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", - "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -4460,13 +4472,13 @@ } }, "node_modules/object.assign": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", - "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", "has-symbols": "^1.0.3", "object-keys": "^1.1.1" }, @@ -4702,6 +4714,15 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -4712,15 +4733,18 @@ } }, "node_modules/prettier": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.5.1.tgz", - "integrity": "sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==", + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz", + "integrity": "sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==", "dev": true, "bin": { - "prettier": "bin-prettier.js" + "prettier": "bin/prettier.cjs" }, "engines": { - "node": ">=10.13.0" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" } }, "node_modules/prettier-linter-helpers": { @@ -4817,9 +4841,9 @@ } }, "node_modules/readable-stream": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.1.tgz", - "integrity": "sha512-+rQmrWMYGA90yenhTYsLWAsLsqVC8osOw6PKE1HDYiO0gdPeKe/xDHNzIAIn4C91YQ6oenEhfYqqc1883qHbjQ==", + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "dev": true, "dependencies": { "inherits": "^2.0.3", @@ -4830,15 +4854,22 @@ "node": ">= 6" } }, + "node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", + "dev": true + }, "node_modules/regexp.prototype.flags": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", - "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", + "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "functions-have-names": "^1.2.2" + "call-bind": "^1.0.6", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "set-function-name": "^2.0.1" }, "engines": { "node": ">= 0.4" @@ -4878,12 +4909,12 @@ } }, "node_modules/resolve": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", "dev": true, "dependencies": { - "is-core-module": "^2.9.0", + "is-core-module": "^2.13.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, @@ -4995,6 +5026,30 @@ "queue-microtask": "^1.2.2" } }, + "node_modules/safe-array-concat": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.0.tgz", + "integrity": "sha512-ZdQ0Jeb9Ofti4hbt5lX3T2JcAamT9hfzYU1MNB+z/jaEbB6wfFfPIR/zEORmZqobkCCJhSjodobH6WHNmJ97dg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "get-intrinsic": "^1.2.2", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-array-concat/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, "node_modules/safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", @@ -5003,15 +5058,18 @@ "peer": true }, "node_modules/safe-regex-test": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", - "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", + "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", "is-regex": "^1.1.4" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -5025,6 +5083,38 @@ "semver": "bin/semver.js" } }, + "node_modules/set-function-length": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.1.tgz", + "integrity": "sha512-j4t6ccc+VsKwYHso+kElc5neZpjtq9EnRICFZtWyBsLojhmeF/ZBd/elqm22WJh/BziDe/SBiOeAt0m2mfLD0g==", + "dev": true, + "dependencies": { + "define-data-property": "^1.1.2", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.3", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -5047,14 +5137,18 @@ } }, "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.5.tgz", + "integrity": "sha512-QcgiIWV4WV7qWExbN5llt6frQB/lBven9pqliLXfGPB+K9ZYXxDozp0wLkHS24kWCm+6YXH/f0HhnObZnZOBnQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -5142,23 +5236,11 @@ "dev": true }, "node_modules/sprintf-js": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", - "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", "dev": true }, - "node_modules/stop-iteration-iterator": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", - "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==", - "dev": true, - "dependencies": { - "internal-slot": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -5203,47 +5285,65 @@ } }, "node_modules/string.prototype.matchall": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.8.tgz", - "integrity": "sha512-6zOCOcJ+RJAQshcTvXPHoxoQGONa3e/Lqx90wUA+wEzX78sg5Bo+1tQo4N0pohS0erG9qtCqJDjNCQBjeWVxyg==", + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.10.tgz", + "integrity": "sha512-rGXbGmOEosIQi6Qva94HUjgPs9vKW+dkG7Y8Q5O2OYkWL6wFaTRZO8zM4mhP94uX55wgyrXzfS2aGtGzUL7EJQ==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "get-intrinsic": "^1.1.3", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1", "has-symbols": "^1.0.3", - "internal-slot": "^1.0.3", - "regexp.prototype.flags": "^1.4.3", + "internal-slot": "^1.0.5", + "regexp.prototype.flags": "^1.5.0", + "set-function-name": "^2.0.0", "side-channel": "^1.0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/string.prototype.trim": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz", + "integrity": "sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/string.prototype.trimend": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", - "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz", + "integrity": "sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/string.prototype.trimstart": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", - "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz", + "integrity": "sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -5487,15 +5587,74 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/typed-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", + "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", + "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", + "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/typed-array-length": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", - "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.5.tgz", + "integrity": "sha512-yMi0PlwuznKHxKmcpoOdeLwxBoVPkqZxd7q2FgMkmD3bNwvF5VW0+UlUQ1k1vmktTu4Yu13Q0RIxEP8+B+wloA==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", + "call-bind": "^1.0.7", "for-each": "^0.3.3", - "is-typed-array": "^1.1.9" + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -5543,9 +5702,9 @@ } }, "node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, "engines": { "node": ">= 10.0.0" @@ -5599,9 +5758,9 @@ } }, "node_modules/validate-peer-dependencies/node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", "dev": true, "dependencies": { "lru-cache": "^6.0.0" @@ -5664,33 +5823,17 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/which-collection": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", - "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==", - "dev": true, - "dependencies": { - "is-map": "^2.0.1", - "is-set": "^2.0.1", - "is-weakmap": "^2.0.1", - "is-weakset": "^2.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/which-typed-array": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", - "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.14.tgz", + "integrity": "sha512-VnXFiIW8yNn9kIHN88xvZ4yOWchftKDsRJ8fEPacX/wl1lOvBrhsJ/OeJCXq7B0AaijRuqgzSKalJoPk+D8MPg==", "dev": true, "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", + "available-typed-arrays": "^1.0.6", + "call-bind": "^1.0.5", "for-each": "^0.3.3", "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0", - "is-typed-array": "^1.1.10" + "has-tostringtag": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -5709,9 +5852,9 @@ } }, "node_modules/workerpool": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.3.1.tgz", - "integrity": "sha512-0x7gJm1rhpn5SPG9NENOxPtbfUZZtK/qOg6gEdSqeDBA3dTeR91RJqSPjccPRCkhNfrnnl/dWxSSj5w9CtdzNA==", + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz", + "integrity": "sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==", "dev": true }, "node_modules/wrap-ansi": { @@ -5753,9 +5896,9 @@ "dev": true }, "node_modules/yargs": { - "version": "17.7.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.1.tgz", - "integrity": "sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==", + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dev": true, "dependencies": { "cliui": "^8.0.1", @@ -6369,6 +6512,15 @@ "dev": true, "peer": true }, + "@babel/runtime": { + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.9.tgz", + "integrity": "sha512-0CX6F+BI2s9dkUqr08KFrAIZgNFj75rdBU/DjCyYLIaV/quFjkk6T+EJ2LkZHyZTbEV4L5p97mNkUsHl2wLFAw==", + "dev": true, + "requires": { + "regenerator-runtime": "^0.14.0" + } + }, "@ember-data/rfc395-data": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/@ember-data/rfc395-data/-/rfc395-data-0.0.4.tgz", @@ -6416,67 +6568,67 @@ "dev": true }, "@glimmer/global-context": { - "version": "0.83.1", - "resolved": "https://registry.npmjs.org/@glimmer/global-context/-/global-context-0.83.1.tgz", - "integrity": "sha512-OwlgqpbOJU73EjZOZdftab0fKbtdJ4x/QQeJseL9cvaAUiK3+w52M5ONFxD1T/yPBp2Mf7NCYqA/uL8tRbzY2A==", + "version": "0.84.3", + "resolved": "https://registry.npmjs.org/@glimmer/global-context/-/global-context-0.84.3.tgz", + "integrity": "sha512-8Oy9Wg5IZxMEeAnVmzD2NkObf89BeHoFSzJgJROE/deutd3rxg83mvlOez4zBBGYwnTb+VGU2LYRpet92egJjA==", "dev": true, "requires": { "@glimmer/env": "^0.1.7" } }, "@glimmer/interfaces": { - "version": "0.83.1", - "resolved": "https://registry.npmjs.org/@glimmer/interfaces/-/interfaces-0.83.1.tgz", - "integrity": "sha512-rjAztghzX97v8I4rk3+NguM3XGYcFjc/GbJ8qrEj19KF2lUDoDBW1sB7f0tov3BD5HlrGXei/vOh4+DHfjeB5w==", + "version": "0.84.3", + "resolved": "https://registry.npmjs.org/@glimmer/interfaces/-/interfaces-0.84.3.tgz", + "integrity": "sha512-dk32ykoNojt0mvEaIW6Vli5MGTbQo58uy3Epj7ahCgTHmWOKuw/0G83f2UmFprRwFx689YTXG38I/vbpltEjzg==", "dev": true, "requires": { "@simple-dom/interface": "^1.4.0" } }, "@glimmer/reference": { - "version": "0.83.1", - "resolved": "https://registry.npmjs.org/@glimmer/reference/-/reference-0.83.1.tgz", - "integrity": "sha512-BThEwDlMkJB1WBPWDrww+VxgGyDbwxh5FFPvGhkovvCZnCb7fAMUCt9pi6CUZtviugkWOBFtE9P4eZZbOLkXeg==", + "version": "0.84.3", + "resolved": "https://registry.npmjs.org/@glimmer/reference/-/reference-0.84.3.tgz", + "integrity": "sha512-lV+p/aWPVC8vUjmlvYVU7WQJsLh319SdXuAWoX/SE3pq340BJlAJiEcAc6q52y9JNhT57gMwtjMX96W5Xcx/qw==", "dev": true, "requires": { "@glimmer/env": "^0.1.7", - "@glimmer/global-context": "0.83.1", - "@glimmer/interfaces": "0.83.1", - "@glimmer/util": "0.83.1", - "@glimmer/validator": "0.83.1" + "@glimmer/global-context": "0.84.3", + "@glimmer/interfaces": "0.84.3", + "@glimmer/util": "0.84.3", + "@glimmer/validator": "0.84.3" } }, "@glimmer/syntax": { - "version": "0.83.1", - "resolved": "https://registry.npmjs.org/@glimmer/syntax/-/syntax-0.83.1.tgz", - "integrity": "sha512-n3vEd0GtjtgkOsd2gqkSimp8ecqq5KrHyana/s1XJZvVAPD5rMWT9WvAVWG8XAktns8BxjwLIUoj/vkOfA+eHg==", + "version": "0.84.3", + "resolved": "https://registry.npmjs.org/@glimmer/syntax/-/syntax-0.84.3.tgz", + "integrity": "sha512-ioVbTic6ZisLxqTgRBL2PCjYZTFIwobifCustrozRU2xGDiYvVIL0vt25h2c1ioDsX59UgVlDkIK4YTAQQSd2A==", "dev": true, "requires": { - "@glimmer/interfaces": "0.83.1", - "@glimmer/util": "0.83.1", + "@glimmer/interfaces": "0.84.3", + "@glimmer/util": "0.84.3", "@handlebars/parser": "~2.0.0", "simple-html-tokenizer": "^0.5.11" } }, "@glimmer/util": { - "version": "0.83.1", - "resolved": "https://registry.npmjs.org/@glimmer/util/-/util-0.83.1.tgz", - "integrity": "sha512-amvjtl9dvrkxsoitXAly9W5NUaLIE3A2J2tWhBWIL1Z6DOFotfX7ytIosOIcPhJLZCtiXPHzMutQRv0G/MSMsA==", + "version": "0.84.3", + "resolved": "https://registry.npmjs.org/@glimmer/util/-/util-0.84.3.tgz", + "integrity": "sha512-qFkh6s16ZSRuu2rfz3T4Wp0fylFj3HBsONGXQcrAdZjdUaIS6v3pNj6mecJ71qRgcym9Hbaq/7/fefIwECUiKw==", "dev": true, "requires": { "@glimmer/env": "0.1.7", - "@glimmer/interfaces": "0.83.1", + "@glimmer/interfaces": "0.84.3", "@simple-dom/interface": "^1.4.0" } }, "@glimmer/validator": { - "version": "0.83.1", - "resolved": "https://registry.npmjs.org/@glimmer/validator/-/validator-0.83.1.tgz", - "integrity": "sha512-LaILSNnQgDHZpaUsfjVndbS1JfVn0xdTlJdFJblPbhoVklOBSReZVekens3EQ6xOr3BC612sRm1hBnEPixOY6A==", + "version": "0.84.3", + "resolved": "https://registry.npmjs.org/@glimmer/validator/-/validator-0.84.3.tgz", + "integrity": "sha512-RTBV4TokUB0vI31UC7ikpV7lOYpWUlyqaKV//pRC4pexYMlmqnVhkFrdiimB/R1XyNdUOQUmnIAcdic39NkbhQ==", "dev": true, "requires": { "@glimmer/env": "^0.1.7", - "@glimmer/global-context": "0.83.1" + "@glimmer/global-context": "0.84.3" } }, "@handlebars/parser": { @@ -6528,17 +6680,17 @@ } }, "@lint-todo/utils": { - "version": "13.1.0", - "resolved": "https://registry.npmjs.org/@lint-todo/utils/-/utils-13.1.0.tgz", - "integrity": "sha512-uzcZPIPH7hcs+hKMiHfp58MosJpI9sTTgl1pGYau4zq34q1ppswJ6nLeohv/cDhqEBrHjtvldt8zDnVJXRvBlA==", + "version": "13.1.1", + "resolved": "https://registry.npmjs.org/@lint-todo/utils/-/utils-13.1.1.tgz", + "integrity": "sha512-F5z53uvRIF4dYfFfJP3a2Cqg+4P1dgJchJsFnsZE0eZp0LK8X7g2J0CsJHRgns+skpXOlM7n5vFGwkWCWj8qJg==", "dev": true, "requires": { - "@types/eslint": "^7.2.13", + "@types/eslint": "^8.4.9", "find-up": "^5.0.0", "fs-extra": "^9.1.0", "proper-lockfile": "^4.1.2", "slash": "^3.0.0", - "tslib": "^2.4.0", + "tslib": "^2.4.1", "upath": "^2.0.1" }, "dependencies": { @@ -6586,9 +6738,9 @@ "dev": true }, "tslib": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", "dev": true }, "yocto-queue": { @@ -6625,6 +6777,13 @@ "fastq": "^1.6.0" } }, + "@prettier/sync": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@prettier/sync/-/sync-0.2.1.tgz", + "integrity": "sha512-7ls1R6//+GPYD9vof1XaL5psViv83CwpdwlS8oUkWldYgbPhzZ3WgxIQMWqGyBmWPmoBfQg8C7jj7KI/ZuDHhQ==", + "dev": true, + "requires": {} + }, "@simple-dom/interface": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/@simple-dom/interface/-/interface-1.4.0.tgz", @@ -6632,9 +6791,9 @@ "dev": true }, "@types/eslint": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-7.29.0.tgz", - "integrity": "sha512-VNcvioYDH8/FxaeTKkM4/TiTwt6pBV9E3OfGmvaw8tPl0rrHCJ4Ll15HRT+pMiFAf/MLQvAzC+6RzUMEL9Ceng==", + "version": "8.56.3", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.3.tgz", + "integrity": "sha512-PvSf1wfv2wJpVIFUMSb+i4PvqNYkB9Rkp9ZDO3oaWzq4SKhsQk4mrMBr3ZH06I0hKrVGLBacmgl8JM4WVjb9dg==", "dev": true, "requires": { "@types/estree": "*", @@ -6642,9 +6801,9 @@ } }, "@types/estree": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.0.tgz", - "integrity": "sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", "dev": true }, "@types/json-schema": { @@ -6660,9 +6819,9 @@ "dev": true }, "@types/symlink-or-copy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@types/symlink-or-copy/-/symlink-or-copy-1.2.0.tgz", - "integrity": "sha512-Lja2xYuuf2B3knEsga8ShbOdsfNOtzT73GyJmZyY7eGl2+ajOqrs8yM5ze0fsSoYwvA6bw7/Qr7OZ7PEEmYwWg==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@types/symlink-or-copy/-/symlink-or-copy-1.2.2.tgz", + "integrity": "sha512-MQ1AnmTLOncwEf9IVU+B2e4Hchrku5N67NkgcAHW0p3sdzPe0FNMANxEm6OJUzPniEQGkeT3OROLlCwZJLWFZA==", "dev": true }, "@typescript-eslint/eslint-plugin": { @@ -6880,18 +7039,28 @@ "dev": true }, "aria-query": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", - "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", + "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", + "dev": true, + "requires": { + "dequal": "^2.0.3" + } + }, + "array-buffer-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", "dev": true, "requires": { - "deep-equal": "^2.0.5" + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" } }, "array-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz", - "integrity": "sha512-H3LU5RLiSsGXPhN+Nipar0iR0IofH+8r89G2y1tBKxQ/agagKyAjhkAFDRBfodP2caPrNKHpAWNIM/c9yeL7uA==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.2.tgz", + "integrity": "sha512-gUHx76KtnhEgB3HOuFYiCm3FIdEs6ocM2asHvNTkfu/Y09qQVrrVVaOKENmS2KkSaGoxgXNqC+ZVtR/n0MOkSA==", "dev": true }, "array-union": { @@ -6900,6 +7069,22 @@ "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true }, + "arraybuffer.prototype.slice": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", + "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", + "dev": true, + "requires": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.2.1", + "get-intrinsic": "^1.2.3", + "is-array-buffer": "^3.0.4", + "is-shared-array-buffer": "^1.0.2" + } + }, "async": { "version": "2.6.4", "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", @@ -6990,10 +7175,13 @@ "dev": true }, "available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", - "dev": true + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, + "requires": { + "possible-typed-array-names": "^1.0.0" + } }, "babel-import-util": { "version": "0.2.0", @@ -7375,13 +7563,16 @@ } }, "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", "dev": true, "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" } }, "callsites": { @@ -7470,9 +7661,9 @@ } }, "cli-spinners": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.7.0.tgz", - "integrity": "sha512-qu3pN8Y3qHNgE2AFweciB1IfMnmZ/fsNTEE+NOFjmGB2F/7rLhnhzppvpCnN4FovtP26k8lHyy9ptEbNwWFLzw==", + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", "dev": true }, "cliui": { @@ -7557,10 +7748,13 @@ } }, "date-fns": { - "version": "2.29.3", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.29.3.tgz", - "integrity": "sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA==", - "dev": true + "version": "2.30.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", + "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", + "dev": true, + "requires": { + "@babel/runtime": "^7.21.0" + } }, "debug": { "version": "4.3.4", @@ -7571,31 +7765,6 @@ "ms": "2.1.2" } }, - "deep-equal": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.0.tgz", - "integrity": "sha512-RdpzE0Hv4lhowpIUKKMJfeH6C1pXdtT1/it80ubgWqwI3qpuxUBpC1S4hnHg+zjnuOoDkzUtUCEEkG+XG5l3Mw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "es-get-iterator": "^1.1.2", - "get-intrinsic": "^1.1.3", - "is-arguments": "^1.1.1", - "is-array-buffer": "^3.0.1", - "is-date-object": "^1.0.5", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "isarray": "^2.0.5", - "object-is": "^1.1.5", - "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.4.3", - "side-channel": "^1.0.4", - "which-boxed-primitive": "^1.0.2", - "which-collection": "^1.0.1", - "which-typed-array": "^1.1.9" - } - }, "deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -7611,16 +7780,34 @@ "clone": "^1.0.2" } }, + "define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "requires": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + } + }, "define-properties": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", - "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", "dev": true, "requires": { + "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" } }, + "dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "dev": true + }, "dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -7680,9 +7867,9 @@ }, "dependencies": { "semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", "dev": true, "requires": { "lru-cache": "^6.0.0" @@ -7697,9 +7884,9 @@ "dev": true }, "ember-template-imports": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/ember-template-imports/-/ember-template-imports-3.4.1.tgz", - "integrity": "sha512-KXnBFTAVxCfXnSCUgd/iuic9ajWbmFkRUBEeorJAMqxvougsPoK22s5ygE9O3GnzYdPpMwn+8v+/NAGy8HRBGA==", + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/ember-template-imports/-/ember-template-imports-3.4.2.tgz", + "integrity": "sha512-OS8TUVG2kQYYwP3netunLVfeijPoOKIs1SvPQRTNOQX4Pu8xGGBEZmrv0U1YTnQn12Eg+p6w/0UdGbUnITjyzw==", "dev": true, "requires": { "babel-import-util": "^0.2.0", @@ -7714,57 +7901,58 @@ } }, "ember-template-lint": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ember-template-lint/-/ember-template-lint-5.2.0.tgz", - "integrity": "sha512-A0wQ1cmaTshIiVhl90QFiaTp1aLw0jy8/uUNWNwD/0PnnaKAi4Oz/wbfjKX/4ZKnhFHgjTFeVyeve1ItoqR7cg==", - "dev": true, - "requires": { - "@lint-todo/utils": "^13.0.3", - "aria-query": "^5.0.2", - "chalk": "^5.1.2", - "ci-info": "^3.7.0", - "date-fns": "^2.29.2", - "ember-template-imports": "^3.4.0", - "ember-template-recast": "^6.1.3", + "version": "5.13.0", + "resolved": "https://registry.npmjs.org/ember-template-lint/-/ember-template-lint-5.13.0.tgz", + "integrity": "sha512-AYxz9S9fVZfHPmTsymc7NwsD7FVmDUZyfC+KYpxDlK0wic7JSQx2FNQNqQSBFRLOuzn7VQ0/+1pX6DGqKDGswg==", + "dev": true, + "requires": { + "@lint-todo/utils": "^13.1.1", + "aria-query": "^5.3.0", + "chalk": "^5.3.0", + "ci-info": "^3.8.0", + "date-fns": "^2.30.0", + "ember-template-imports": "^3.4.2", + "ember-template-recast": "^6.1.4", "eslint-formatter-kakoune": "^1.0.0", "find-up": "^6.3.0", "fuse.js": "^6.5.3", "get-stdin": "^9.0.0", - "globby": "^13.1.2", + "globby": "^13.2.2", "is-glob": "^4.0.3", - "language-tags": "^1.0.6", + "language-tags": "^1.0.8", "micromatch": "^4.0.5", - "resolve": "^1.22.1", + "resolve": "^1.22.3", "v8-compile-cache": "^2.3.0", - "yargs": "^17.5.1" + "yargs": "^17.7.2" }, "dependencies": { "chalk": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.2.0.tgz", - "integrity": "sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", "dev": true } } }, "ember-template-lint-plugin-prettier": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ember-template-lint-plugin-prettier/-/ember-template-lint-plugin-prettier-4.1.0.tgz", - "integrity": "sha512-LGGn1SXS5vhH60Tp37D4yG8z9ftVMCSSBn5qst+7rjMtLAZuZYwq+q+fs46op745ds0NNtaj+3OzSpBj+RVL2w==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ember-template-lint-plugin-prettier/-/ember-template-lint-plugin-prettier-5.0.0.tgz", + "integrity": "sha512-aXUYM4yuIdPZ80+AsAU8QBwGSJJ/aAkRsNcQ5vI5HmXiBjzHlDc/ZhmP6iVcYuCmoA/3iKcssMAYwIDbuby4pg==", "dev": true, "requires": { + "@prettier/sync": "^0.2.1", "prettier-linter-helpers": "^1.0.0" } }, "ember-template-recast": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/ember-template-recast/-/ember-template-recast-6.1.3.tgz", - "integrity": "sha512-45lkfjrWlrMPlOd5rLFeQeePZwAvcS//x1x15kaiQTlqQdYWiYNXwbpWHqV+p9fXY6bEjl6EbyPhG/zBkgh8MA==", + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/ember-template-recast/-/ember-template-recast-6.1.4.tgz", + "integrity": "sha512-fCh+rOK6z+/tsdkTbOE+e7f84P6ObnIRQrCCrnu21E4X05hPeradikIkRMhJdxn4NWrxitfZskQDd37TR/lsNQ==", "dev": true, "requires": { - "@glimmer/reference": "^0.83.1", - "@glimmer/syntax": "^0.83.1", - "@glimmer/validator": "^0.83.0", + "@glimmer/reference": "^0.84.3", + "@glimmer/syntax": "^0.84.3", + "@glimmer/validator": "^0.84.3", "async-promise-queue": "^1.0.5", "colors": "^1.4.0", "commander": "^8.3.0", @@ -7772,7 +7960,7 @@ "ora": "^5.4.0", "slash": "^3.0.0", "tmp": "^0.2.1", - "workerpool": "^6.1.5" + "workerpool": "^6.4.0" }, "dependencies": { "globby": { @@ -7804,72 +7992,78 @@ "dev": true }, "es-abstract": { - "version": "1.21.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.1.tgz", - "integrity": "sha512-QudMsPOz86xYz/1dG1OuGBKOELjCh99IIWHLzy5znUB6j8xG2yMA7bfTV86VSqKF+Y/H08vQPR+9jyXpuC6hfg==", - "dev": true, - "requires": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "es-set-tostringtag": "^2.0.1", + "version": "1.22.4", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.4.tgz", + "integrity": "sha512-vZYJlk2u6qHYxBOTjAeg7qUxHdNfih64Uu2J8QqWgXZ2cri0ZpJAkzDUK/q593+mvKwlxyaxr6F1Q+3LKoQRgg==", + "dev": true, + "requires": { + "array-buffer-byte-length": "^1.0.1", + "arraybuffer.prototype.slice": "^1.0.3", + "available-typed-arrays": "^1.0.6", + "call-bind": "^1.0.7", + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.0.2", "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "function.prototype.name": "^1.1.5", - "get-intrinsic": "^1.1.3", - "get-symbol-description": "^1.0.0", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.4", + "get-symbol-description": "^1.0.2", "globalthis": "^1.0.3", "gopd": "^1.0.1", - "has": "^1.0.3", - "has-property-descriptors": "^1.0.0", + "has-property-descriptors": "^1.0.2", "has-proto": "^1.0.1", "has-symbols": "^1.0.3", - "internal-slot": "^1.0.4", - "is-array-buffer": "^3.0.1", + "hasown": "^2.0.1", + "internal-slot": "^1.0.7", + "is-array-buffer": "^3.0.4", "is-callable": "^1.2.7", "is-negative-zero": "^2.0.2", "is-regex": "^1.1.4", "is-shared-array-buffer": "^1.0.2", "is-string": "^1.0.7", - "is-typed-array": "^1.1.10", + "is-typed-array": "^1.1.13", "is-weakref": "^1.0.2", - "object-inspect": "^1.12.2", + "object-inspect": "^1.13.1", "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.4.3", - "safe-regex-test": "^1.0.0", - "string.prototype.trimend": "^1.0.6", - "string.prototype.trimstart": "^1.0.6", + "object.assign": "^4.1.5", + "regexp.prototype.flags": "^1.5.2", + "safe-array-concat": "^1.1.0", + "safe-regex-test": "^1.0.3", + "string.prototype.trim": "^1.2.8", + "string.prototype.trimend": "^1.0.7", + "string.prototype.trimstart": "^1.0.7", + "typed-array-buffer": "^1.0.1", + "typed-array-byte-length": "^1.0.0", + "typed-array-byte-offset": "^1.0.0", "typed-array-length": "^1.0.4", "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.9" + "which-typed-array": "^1.1.14" } }, - "es-get-iterator": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", - "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", + "es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "has-symbols": "^1.0.3", - "is-arguments": "^1.1.1", - "is-map": "^2.0.2", - "is-set": "^2.0.2", - "is-string": "^1.0.7", - "isarray": "^2.0.5", - "stop-iteration-iterator": "^1.0.0" + "get-intrinsic": "^1.2.4" } }, + "es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true + }, "es-set-tostringtag": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", - "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", + "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", "dev": true, "requires": { - "get-intrinsic": "^1.1.3", - "has": "^1.0.3", - "has-tostringtag": "^1.0.0" + "get-intrinsic": "^1.2.4", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.1" } }, "es-to-primitive": { @@ -8199,9 +8393,9 @@ "dev": true }, "fast-glob": { - "version": "3.2.12", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", - "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "dev": true, "requires": { "@nodelib/fs.stat": "^2.0.2", @@ -8349,21 +8543,21 @@ "dev": true }, "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", "dev": true }, "function.prototype.name": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", - "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", "dev": true, "requires": { "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.0", - "functions-have-names": "^1.2.2" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" } }, "functional-red-black-tree": { @@ -8398,14 +8592,16 @@ "dev": true }, "get-intrinsic": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", - "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", "dev": true, "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.3" + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" } }, "get-stdin": { @@ -8415,13 +8611,14 @@ "dev": true }, "get-symbol-description": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", - "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", + "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" + "call-bind": "^1.0.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4" } }, "glob": { @@ -8464,14 +8661,14 @@ } }, "globby": { - "version": "13.1.3", - "resolved": "https://registry.npmjs.org/globby/-/globby-13.1.3.tgz", - "integrity": "sha512-8krCNHXvlCgHDpegPzleMq07yMYTO2sXKASmZmquEYWEmCx6J5UTRbp5RwMJkTJGtcQ44YpiUYUiN0b9mzy8Bw==", + "version": "13.2.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-13.2.2.tgz", + "integrity": "sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==", "dev": true, "requires": { "dir-glob": "^3.0.1", - "fast-glob": "^3.2.11", - "ignore": "^5.2.0", + "fast-glob": "^3.3.0", + "ignore": "^5.2.4", "merge2": "^1.4.1", "slash": "^4.0.0" }, @@ -8494,20 +8691,11 @@ } }, "graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "dev": true }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1" - } - }, "has-bigints": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", @@ -8521,18 +8709,18 @@ "dev": true }, "has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dev": true, "requires": { - "get-intrinsic": "^1.1.1" + "es-define-property": "^1.0.0" } }, "has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", "dev": true }, "has-symbols": { @@ -8542,12 +8730,12 @@ "dev": true }, "has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "dev": true, "requires": { - "has-symbols": "^1.0.2" + "has-symbols": "^1.0.3" } }, "hash-for-dep": { @@ -8576,6 +8764,15 @@ } } }, + "hasown": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.1.tgz", + "integrity": "sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==", + "dev": true, + "requires": { + "function-bind": "^1.1.2" + } + }, "heimdalljs": { "version": "0.2.6", "resolved": "https://registry.npmjs.org/heimdalljs/-/heimdalljs-0.2.6.tgz", @@ -8627,9 +8824,9 @@ "dev": true }, "ignore": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", - "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", "dev": true }, "import-fresh": { @@ -8665,35 +8862,24 @@ "dev": true }, "internal-slot": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", - "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", + "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", "dev": true, "requires": { - "get-intrinsic": "^1.2.0", - "has": "^1.0.3", + "es-errors": "^1.3.0", + "hasown": "^2.0.0", "side-channel": "^1.0.4" } }, - "is-arguments": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", - "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - } - }, "is-array-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.1.tgz", - "integrity": "sha512-ASfLknmY8Xa2XtB4wmbz13Wu202baeA18cJBCeCy0wXUHZF0IPyVEXqKEcd+t2fNSLLL1vC6k7lxZEojNbISXQ==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", + "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", "dev": true, "requires": { "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "is-typed-array": "^1.1.10" + "get-intrinsic": "^1.2.1" } }, "is-bigint": { @@ -8722,12 +8908,12 @@ "dev": true }, "is-core-module": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", - "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", "dev": true, "requires": { - "has": "^1.0.3" + "hasown": "^2.0.0" } }, "is-date-object": { @@ -8766,16 +8952,10 @@ "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", "dev": true }, - "is-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", - "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", - "dev": true - }, "is-negative-zero": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", - "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", "dev": true }, "is-number": { @@ -8803,19 +8983,13 @@ "has-tostringtag": "^1.0.0" } }, - "is-set": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", - "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", - "dev": true - }, "is-shared-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", - "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", "dev": true, "requires": { - "call-bind": "^1.0.2" + "call-bind": "^1.0.7" } }, "is-string": { @@ -8837,16 +9011,12 @@ } }, "is-typed-array": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", - "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", "dev": true, "requires": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" + "which-typed-array": "^1.1.14" } }, "is-unicode-supported": { @@ -8855,12 +9025,6 @@ "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", "dev": true }, - "is-weakmap": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", - "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==", - "dev": true - }, "is-weakref": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", @@ -8870,20 +9034,10 @@ "call-bind": "^1.0.2" } }, - "is-weakset": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz", - "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" - } - }, "isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", "dev": true }, "isexe": { @@ -8899,14 +9053,6 @@ "dev": true, "requires": { "isarray": "1.0.0" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true - } } }, "istextorbinary": { @@ -8998,14 +9144,6 @@ "requires": { "isarray": "^1.0.0", "isobject": "^2.0.0" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true - } } }, "locate-path": { @@ -9197,21 +9335,11 @@ "dev": true }, "object-inspect": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", - "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", "dev": true }, - "object-is": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", - "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - } - }, "object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", @@ -9219,13 +9347,13 @@ "dev": true }, "object.assign": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", - "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", "has-symbols": "^1.0.3", "object-keys": "^1.1.1" } @@ -9394,6 +9522,12 @@ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true }, + "possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "dev": true + }, "prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -9401,9 +9535,9 @@ "dev": true }, "prettier": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.5.1.tgz", - "integrity": "sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==", + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz", + "integrity": "sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==", "dev": true }, "prettier-linter-helpers": { @@ -9478,9 +9612,9 @@ } }, "readable-stream": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.1.tgz", - "integrity": "sha512-+rQmrWMYGA90yenhTYsLWAsLsqVC8osOw6PKE1HDYiO0gdPeKe/xDHNzIAIn4C91YQ6oenEhfYqqc1883qHbjQ==", + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "dev": true, "requires": { "inherits": "^2.0.3", @@ -9488,15 +9622,22 @@ "util-deprecate": "^1.0.1" } }, + "regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", + "dev": true + }, "regexp.prototype.flags": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", - "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", + "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "functions-have-names": "^1.2.2" + "call-bind": "^1.0.6", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "set-function-name": "^2.0.1" } }, "regexpp": { @@ -9518,12 +9659,12 @@ "dev": true }, "resolve": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", "dev": true, "requires": { - "is-core-module": "^2.9.0", + "is-core-module": "^2.13.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" } @@ -9590,6 +9731,26 @@ "queue-microtask": "^1.2.2" } }, + "safe-array-concat": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.0.tgz", + "integrity": "sha512-ZdQ0Jeb9Ofti4hbt5lX3T2JcAamT9hfzYU1MNB+z/jaEbB6wfFfPIR/zEORmZqobkCCJhSjodobH6WHNmJ97dg==", + "dev": true, + "requires": { + "call-bind": "^1.0.5", + "get-intrinsic": "^1.2.2", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "dependencies": { + "isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + } + } + }, "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", @@ -9598,13 +9759,13 @@ "peer": true }, "safe-regex-test": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", - "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", + "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", "is-regex": "^1.1.4" } }, @@ -9614,6 +9775,32 @@ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true }, + "set-function-length": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.1.tgz", + "integrity": "sha512-j4t6ccc+VsKwYHso+kElc5neZpjtq9EnRICFZtWyBsLojhmeF/ZBd/elqm22WJh/BziDe/SBiOeAt0m2mfLD0g==", + "dev": true, + "requires": { + "define-data-property": "^1.1.2", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.3", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.1" + } + }, + "set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, + "requires": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + } + }, "shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -9630,14 +9817,15 @@ "dev": true }, "side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.5.tgz", + "integrity": "sha512-QcgiIWV4WV7qWExbN5llt6frQB/lBven9pqliLXfGPB+K9ZYXxDozp0wLkHS24kWCm+6YXH/f0HhnObZnZOBnQ==", "dev": true, "requires": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" } }, "signal-exit": { @@ -9714,20 +9902,11 @@ "dev": true }, "sprintf-js": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", - "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", "dev": true }, - "stop-iteration-iterator": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", - "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==", - "dev": true, - "requires": { - "internal-slot": "^1.0.4" - } - }, "string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -9757,41 +9936,53 @@ } }, "string.prototype.matchall": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.8.tgz", - "integrity": "sha512-6zOCOcJ+RJAQshcTvXPHoxoQGONa3e/Lqx90wUA+wEzX78sg5Bo+1tQo4N0pohS0erG9qtCqJDjNCQBjeWVxyg==", + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.10.tgz", + "integrity": "sha512-rGXbGmOEosIQi6Qva94HUjgPs9vKW+dkG7Y8Q5O2OYkWL6wFaTRZO8zM4mhP94uX55wgyrXzfS2aGtGzUL7EJQ==", "dev": true, "requires": { "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "get-intrinsic": "^1.1.3", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1", "has-symbols": "^1.0.3", - "internal-slot": "^1.0.3", - "regexp.prototype.flags": "^1.4.3", + "internal-slot": "^1.0.5", + "regexp.prototype.flags": "^1.5.0", + "set-function-name": "^2.0.0", "side-channel": "^1.0.4" } }, + "string.prototype.trim": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz", + "integrity": "sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + } + }, "string.prototype.trimend": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", - "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz", + "integrity": "sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==", "dev": true, "requires": { "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" } }, "string.prototype.trimstart": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", - "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz", + "integrity": "sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==", "dev": true, "requires": { "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" } }, "strip-ansi": { @@ -9984,15 +10175,56 @@ "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true }, + "typed-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", + "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.13" + } + }, + "typed-array-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", + "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", + "dev": true, + "requires": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + } + }, + "typed-array-byte-offset": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", + "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", + "dev": true, + "requires": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + } + }, "typed-array-length": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", - "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.5.tgz", + "integrity": "sha512-yMi0PlwuznKHxKmcpoOdeLwxBoVPkqZxd7q2FgMkmD3bNwvF5VW0+UlUQ1k1vmktTu4Yu13Q0RIxEP8+B+wloA==", "dev": true, "requires": { - "call-bind": "^1.0.2", + "call-bind": "^1.0.7", "for-each": "^0.3.3", - "is-typed-array": "^1.1.9" + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0" } }, "typescript": { @@ -10024,9 +10256,9 @@ } }, "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true }, "upath": { @@ -10073,9 +10305,9 @@ }, "dependencies": { "semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", "dev": true, "requires": { "lru-cache": "^6.0.0" @@ -10125,30 +10357,17 @@ "is-symbol": "^1.0.3" } }, - "which-collection": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", - "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==", - "dev": true, - "requires": { - "is-map": "^2.0.1", - "is-set": "^2.0.1", - "is-weakmap": "^2.0.1", - "is-weakset": "^2.0.1" - } - }, "which-typed-array": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", - "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.14.tgz", + "integrity": "sha512-VnXFiIW8yNn9kIHN88xvZ4yOWchftKDsRJ8fEPacX/wl1lOvBrhsJ/OeJCXq7B0AaijRuqgzSKalJoPk+D8MPg==", "dev": true, "requires": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", + "available-typed-arrays": "^1.0.6", + "call-bind": "^1.0.5", "for-each": "^0.3.3", "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0", - "is-typed-array": "^1.1.10" + "has-tostringtag": "^1.0.1" } }, "word-wrap": { @@ -10158,9 +10377,9 @@ "dev": true }, "workerpool": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.3.1.tgz", - "integrity": "sha512-0x7gJm1rhpn5SPG9NENOxPtbfUZZtK/qOg6gEdSqeDBA3dTeR91RJqSPjccPRCkhNfrnnl/dWxSSj5w9CtdzNA==", + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz", + "integrity": "sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==", "dev": true }, "wrap-ansi": { @@ -10193,9 +10412,9 @@ "dev": true }, "yargs": { - "version": "17.7.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.1.tgz", - "integrity": "sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==", + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dev": true, "requires": { "cliui": "^8.0.1", diff --git a/package.json b/package.json index 2b969537f..3a1942bee 100644 --- a/package.json +++ b/package.json @@ -11,15 +11,15 @@ "@babel/eslint-parser": "7.17.0", "@typescript-eslint/eslint-plugin": "5.12.1", "@typescript-eslint/parser": "5.12.1", - "ember-template-lint": "5.2.0", - "ember-template-lint-plugin-prettier": "4.1.0", + "ember-template-lint": "5.13.0", + "ember-template-lint-plugin-prettier": "5.0.0", "eslint": "8.10.0", "eslint-config-prettier": "8.4.0", "eslint-plugin-ember": "10.5.9", "eslint-plugin-mirego": "^1.0.0", "eslint-plugin-node": "11.1.0", "eslint-plugin-sonarjs": "0.12.0", - "prettier": "2.5.1", + "prettier": "3.2.5", "typescript": "4.7.4" } } diff --git a/priv/repo/migrations/20240227025330_add_copy_on_update_translation_on_versions.exs b/priv/repo/migrations/20240227025330_add_copy_on_update_translation_on_versions.exs new file mode 100644 index 000000000..211f40507 --- /dev/null +++ b/priv/repo/migrations/20240227025330_add_copy_on_update_translation_on_versions.exs @@ -0,0 +1,10 @@ +defmodule Accent.Repo.Migrations.AddCopyOnUpdateTranslationOnVersions do + @moduledoc false + use Ecto.Migration + + def change do + alter table(:versions) do + add(:copy_on_update_translation, :boolean, default: false, null: false) + end + end +end diff --git a/priv/repo/migrations/20240315115937_add_non_nullable_checks.exs b/priv/repo/migrations/20240315115937_add_non_nullable_checks.exs new file mode 100644 index 000000000..f7ebf99ef --- /dev/null +++ b/priv/repo/migrations/20240315115937_add_non_nullable_checks.exs @@ -0,0 +1,86 @@ +defmodule Accent.Repo.Migrations.AddNonNullableChecks do + @moduledoc false + use Ecto.Migration + + def down do + end + + # credo:disable-for-next-line + def up do + drop(constraint(:documents, :documents_project_id_fkey)) + + alter table(:documents) do + modify(:path, :string, null: false) + modify(:format, :string, null: false) + modify(:project_id, references(:projects, type: :uuid), null: false) + end + + alter table(:languages) do + modify(:name, :string, null: false) + modify(:slug, :string, null: false) + modify(:iso_639_1, :string, null: false) + modify(:iso_639_3, :string, null: false) + modify(:locale, :string, null: false) + modify(:android_code, :string, null: false) + modify(:osx_code, :string, null: false) + modify(:osx_locale, :string, null: false) + end + + drop(constraint(:auth_access_tokens, :auth_access_tokens_user_id_fkey)) + + alter table(:auth_access_tokens) do + modify(:token, :string, null: false) + modify(:user_id, references(:users, type: :uuid), null: false) + end + + drop(constraint(:auth_providers, :auth_providers_user_id_fkey)) + + alter table(:auth_providers) do + modify(:name, :string, null: false) + modify(:uid, :string, null: false) + modify(:user_id, references(:users, type: :uuid), null: false) + end + + drop(constraint(:collaborators, :collaborators_project_id_fkey)) + + alter table(:collaborators) do + modify(:role, :string, null: false) + modify(:project_id, references(:projects, type: :uuid), null: false) + end + + drop(constraint(:comments, :comments_user_id_fkey)) + + alter table(:comments) do + modify(:text, :text, null: false) + modify(:user_id, references(:users, type: :uuid), null: false) + end + + alter table(:projects) do + modify(:name, :string, null: false) + modify(:locked_file_operations, :boolean, null: false, default: false) + modify(:sync_lock_version, :integer, null: false, default: 1) + end + + drop(constraint(:revisions, :revisions_project_id_fkey)) + drop(constraint(:revisions, :revisions_language_id_fkey)) + + alter table(:revisions) do + modify(:project_id, references(:projects, type: :uuid), null: false) + modify(:language_id, references(:languages, type: :uuid), null: false) + modify(:master, :boolean, null: false, default: true) + end + + alter table(:operations) do + modify(:rollbacked, :boolean, null: false, default: false) + modify(:batch, :boolean, null: false, default: false) + modify(:action, :string, null: false) + end + + alter table(:translations) do + modify(:key, :text, null: false) + modify(:removed, :boolean, null: false, default: false) + modify(:conflicted, :boolean, null: false, default: false) + modify(:comments_count, :integer, null: false, default: 0) + end + end +end diff --git a/test/auth/user_remote/authenticator_test.exs b/test/auth/user_remote/authenticator_test.exs index 7d2e75cdc..67ab00218 100644 --- a/test/auth/user_remote/authenticator_test.exs +++ b/test/auth/user_remote/authenticator_test.exs @@ -25,17 +25,17 @@ defmodule AccentTest.UserRemote.Authenticator do end test "normalize collaborators with email" do - assigner = Repo.insert!(%User{email: "foo@example.com"}) - language = Repo.insert!(%Language{name: "french"}) - project = Repo.insert!(%Project{main_color: "#f00", name: "My project", language_id: language.id}) + assigner = Factory.insert(User, email: "foo@example.com") + language = Factory.insert(Language) + project = Factory.insert(Project, language_id: language.id) collaborator = - Repo.insert!(%Collaborator{ + Factory.insert(Collaborator, project_id: project.id, role: "admin", assigner_id: assigner.id, email: "test@example.com" - }) + ) {:ok, _token} = Authenticator.authenticate(%{provider: :dummy, info: %{email: "test@example.com"}}) user = Repo.get_by(User, email: "test@example.com") @@ -45,17 +45,17 @@ defmodule AccentTest.UserRemote.Authenticator do end test "normalize collaborators with uppercased email" do - assigner = Repo.insert!(%User{email: "foo@example.com"}) - language = Repo.insert!(%Language{name: "french"}) - project = Repo.insert!(%Project{main_color: "#f00", name: "My project", language_id: language.id}) + assigner = Factory.insert(User, email: "foo@example.com") + language = Factory.insert(Language) + project = Factory.insert(Project, language_id: language.id) collaborator = - Repo.insert!(%Collaborator{ + Factory.insert(Collaborator, project_id: project.id, role: "admin", assigner_id: assigner.id, email: "test@example.com" - }) + ) {:ok, _token} = Authenticator.authenticate(%{provider: :dummy, info: %{email: "TeSt@eXamPle.com"}}) user = Repo.get_by(User, email: "test@example.com") diff --git a/test/auth/user_remote/persister_test.exs b/test/auth/user_remote/persister_test.exs index bd1d26dd7..88f2ce64a 100644 --- a/test/auth/user_remote/persister_test.exs +++ b/test/auth/user_remote/persister_test.exs @@ -18,8 +18,8 @@ defmodule AccentTest.UserRemote.Persister do end test "persist with existing user existing provider" do - existing_user = Repo.insert!(%User{email: @user.email}) - Repo.insert!(%AuthProvider{name: @user.provider, uid: @user.uid}) + existing_user = Factory.insert(User, email: @user.email) + Factory.insert(AuthProvider, name: @user.provider, uid: @user.uid) user = Persister.persist(@user) @@ -28,8 +28,8 @@ defmodule AccentTest.UserRemote.Persister do end test "persist with existing user new provider" do - existing_user = Repo.insert!(%User{email: @user.email}) - Repo.insert!(%AuthProvider{name: "dummy", uid: @user.email}) + existing_user = Factory.insert(User, email: @user.email) + Factory.insert(AuthProvider, name: "dummy", uid: @user.email) user = Persister.persist(@user) diff --git a/test/auth/user_remote/token_giver_test.exs b/test/auth/user_remote/token_giver_test.exs index d2701900f..c039b6284 100644 --- a/test/auth/user_remote/token_giver_test.exs +++ b/test/auth/user_remote/token_giver_test.exs @@ -7,15 +7,14 @@ defmodule AccentTest.UserRemote.TokenGiver do alias Accent.User alias Accent.UserRemote.TokenGiver - @user %User{email: "test@test.com"} @token %AccessToken{revoked_at: nil, token: "1234"} test "revoke existing token" do - user = Repo.insert!(@user) + user = Factory.insert(User) token = Repo.insert!(Map.put(@token, :user_id, user.id)) existing_revoked_token = - Repo.insert!(%AccessToken{token: "revoked", revoked_at: NaiveDateTime.utc_now(:second), user_id: user.id}) + Factory.insert(AccessToken, token: "revoked", revoked_at: NaiveDateTime.utc_now(:second), user_id: user.id) TokenGiver.grant_token(user) @@ -27,7 +26,7 @@ defmodule AccentTest.UserRemote.TokenGiver do end test "create token" do - user = Repo.insert!(@user) + user = Factory.insert(User) TokenGiver.grant_token(user) diff --git a/test/badge_generator_test.exs b/test/badge_generator_test.exs index fc3c2e72d..478219218 100644 --- a/test/badge_generator_test.exs +++ b/test/badge_generator_test.exs @@ -13,41 +13,41 @@ defmodule AccentTest.BadgeGenerator do alias Accent.Translation setup do - french_language = Repo.insert!(%Language{name: "french", slug: Ecto.UUID.generate()}) - project = Repo.insert!(%Project{main_color: "#f00", name: "My project", language_id: french_language.id}) - revision = Repo.insert!(%Revision{language_id: french_language.id, master: true, project_id: project.id}) - document = Repo.insert!(%Document{project_id: project.id, path: "test2", format: "json"}) + french_language = Factory.insert(Language) + project = Factory.insert(Project, language_id: french_language.id) + revision = Factory.insert(Revision, language_id: french_language.id, master: true, project_id: project.id) + document = Factory.insert(Document, project_id: project.id, path: "test2", format: "json") {:ok, [project: Repo.preload(project, :revisions), revision: revision, document: document]} end test "percentage_reviewed error", %{project: project, revision: revision, document: document} do - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, key: "a", conflicted: true, corrected_text: "initial", proposed_text: "initial", document_id: document.id - }) + ) - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, key: "b", conflicted: true, corrected_text: "initial", proposed_text: "initial", document_id: document.id - }) + ) - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, key: "c", conflicted: false, corrected_text: "initial", proposed_text: "initial", document_id: document.id - }) + ) response = [get: fn _url, _, _ -> {:ok, %{body: ""}} end] @@ -59,41 +59,41 @@ defmodule AccentTest.BadgeGenerator do end test "percentage_reviewed warning", %{project: project, revision: revision, document: document} do - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, key: "a", conflicted: true, corrected_text: "initial", proposed_text: "initial", document_id: document.id - }) + ) - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, key: "b", conflicted: false, corrected_text: "initial", proposed_text: "initial", document_id: document.id - }) + ) - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, key: "c", conflicted: false, corrected_text: "initial", proposed_text: "initial", document_id: document.id - }) + ) - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, key: "d", conflicted: false, corrected_text: "initial", proposed_text: "initial", document_id: document.id - }) + ) response = [get: fn _url, _, _ -> {:ok, %{body: ""}} end] @@ -105,41 +105,41 @@ defmodule AccentTest.BadgeGenerator do end test "percentage_reviewed success", %{project: project, revision: revision, document: document} do - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, key: "a", conflicted: false, corrected_text: "initial", proposed_text: "initial", document_id: document.id - }) + ) - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, key: "b", conflicted: false, corrected_text: "initial", proposed_text: "initial", document_id: document.id - }) + ) - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, key: "c", conflicted: false, corrected_text: "initial", proposed_text: "initial", document_id: document.id - }) + ) - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, key: "d", conflicted: false, corrected_text: "initial", proposed_text: "initial", document_id: document.id - }) + ) response = [get: fn _url, _, _ -> {:ok, %{body: ""}} end] @@ -151,41 +151,41 @@ defmodule AccentTest.BadgeGenerator do end test "translations_count", %{project: project, revision: revision, document: document} do - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, key: "a", conflicted: false, corrected_text: "initial", proposed_text: "initial", document_id: document.id - }) + ) - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, key: "b", conflicted: false, corrected_text: "initial", proposed_text: "initial", document_id: document.id - }) + ) - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, key: "c", conflicted: false, corrected_text: "initial", proposed_text: "initial", document_id: document.id - }) + ) - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, key: "d", conflicted: false, corrected_text: "initial", proposed_text: "initial", document_id: document.id - }) + ) response = [get: fn _url, _, _ -> {:ok, %{body: ""}} end] @@ -199,23 +199,23 @@ defmodule AccentTest.BadgeGenerator do end test "conflicts_count", %{project: project, revision: revision, document: document} do - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, key: "c", conflicted: true, corrected_text: "initial", proposed_text: "initial", document_id: document.id - }) + ) - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, key: "d", conflicted: true, corrected_text: "initial", proposed_text: "initial", document_id: document.id - }) + ) response = [get: fn _url, _, _ -> {:ok, %{body: ""}} end] @@ -229,23 +229,23 @@ defmodule AccentTest.BadgeGenerator do end test "reviewed_count", %{project: project, revision: revision, document: document} do - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, key: "c", conflicted: false, corrected_text: "initial", proposed_text: "initial", document_id: document.id - }) + ) - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, key: "d", conflicted: false, corrected_text: "initial", proposed_text: "initial", document_id: document.id - }) + ) response = [get: fn _url, _, _ -> {:ok, %{body: ""}} end] diff --git a/test/graphql/helpers/authorization_test.exs b/test/graphql/helpers/authorization_test.exs index 4749f3b08..c21db098c 100644 --- a/test/graphql/helpers/authorization_test.exs +++ b/test/graphql/helpers/authorization_test.exs @@ -15,31 +15,29 @@ defmodule AccentTest.GraphQL.Helpers.Authorization do alias Accent.User alias Accent.Version - @user %User{email: "test@test.com"} - setup do - user = Repo.insert!(@user) - language = Repo.insert!(%Language{name: "English", slug: Ecto.UUID.generate()}) + user = Factory.insert(User) + language = Factory.insert(Language) {:ok, project} = ProjectCreator.create(params: %{main_color: "#f00", name: "My project", language_id: language.id}, user: user) revision = project |> Repo.preload(:revisions) |> Map.get(:revisions) |> hd() - document = Repo.insert!(%Document{project_id: project.id, path: "test", format: "json"}) - version = Repo.insert!(%Version{project_id: project.id, name: "test", tag: "v1.0", user_id: user.id}) - translation = Repo.insert!(%Translation{revision_id: revision.id, key: "test", corrected_text: "bar"}) - collaborator = Repo.insert!(%Collaborator{project_id: project.id, user_id: user.id, role: "owner"}) + document = Factory.insert(Document, project_id: project.id, path: "test", format: "json") + version = Factory.insert(Version, project_id: project.id, name: "test", tag: "v1.0", user_id: user.id) + translation = Factory.insert(Translation, revision_id: revision.id, key: "test", corrected_text: "bar") + collaborator = Factory.insert(Collaborator, project_id: project.id, user_id: user.id, role: "owner") integration = - Repo.insert!(%Integration{ + Factory.insert(Integration, project_id: project.id, user_id: user.id, service: "slack", data: %{url: "http://example.com"} - }) + ) translation_comments_subscription = - Repo.insert!(%TranslationCommentsSubscription{translation_id: translation.id, user_id: user.id}) + Factory.insert(TranslationCommentsSubscription, translation_id: translation.id, user_id: user.id) {:ok, [ @@ -127,7 +125,7 @@ defmodule AccentTest.GraphQL.Helpers.Authorization do end test "unauthorized project root", %{project: project} do - user = Repo.insert!(%User{email: "test+2@test.com"}) + user = Factory.insert(User, email: "test+2@test.com") user = Map.put(user, :permissions, %{}) root = project args = %{} @@ -178,7 +176,7 @@ defmodule AccentTest.GraphQL.Helpers.Authorization do end test "unauthorized revision root", %{revision: revision} do - user = Repo.insert!(%User{email: "test+2@test.com"}) + user = Factory.insert(User, email: "test+2@test.com") user = Map.put(user, :permissions, %{}) root = revision args = %{} @@ -229,7 +227,7 @@ defmodule AccentTest.GraphQL.Helpers.Authorization do end test "unauthorized version root", %{version: version} do - user = Repo.insert!(%User{email: "test+2@test.com"}) + user = Factory.insert(User, email: "test+2@test.com") user = Map.put(user, :permissions, %{}) root = version args = %{} @@ -298,7 +296,7 @@ defmodule AccentTest.GraphQL.Helpers.Authorization do end test "unauthorized translation root", %{translation: translation} do - user = Repo.insert!(%User{email: "test+2@test.com"}) + user = Factory.insert(User, email: "test+2@test.com") user = Map.put(user, :permissions, %{}) root = translation args = %{} @@ -387,7 +385,7 @@ defmodule AccentTest.GraphQL.Helpers.Authorization do end test "authorized operation revision args", %{user: user, revision: revision, project: project} do - operation = Repo.insert!(%Operation{revision_id: revision.id, user_id: user.id, key: "test", text: "bar"}) + operation = Factory.insert(Operation, revision_id: revision.id, user_id: user.id, key: "test", text: "bar") user = Map.put(user, :permissions, %{project.id => "owner"}) root = nil @@ -401,7 +399,7 @@ defmodule AccentTest.GraphQL.Helpers.Authorization do end test "authorized operation translation args", %{user: user, translation: translation, project: project} do - operation = Repo.insert!(%Operation{translation_id: translation.id, user_id: user.id, key: "test", text: "bar"}) + operation = Factory.insert(Operation, translation_id: translation.id, user_id: user.id, key: "test", text: "bar") user = Map.put(user, :permissions, %{project.id => "owner"}) root = nil @@ -415,7 +413,7 @@ defmodule AccentTest.GraphQL.Helpers.Authorization do end test "authorized operation project args", %{user: user, project: project} do - operation = Repo.insert!(%Operation{project_id: project.id, user_id: user.id, key: "test", text: "bar"}) + operation = Factory.insert(Operation, project_id: project.id, user_id: user.id, key: "test", text: "bar") user = Map.put(user, :permissions, %{project.id => "owner"}) root = nil @@ -429,7 +427,7 @@ defmodule AccentTest.GraphQL.Helpers.Authorization do end test "unauthorized operation role", %{user: user, revision: revision, project: project} do - operation = Repo.insert!(%Operation{revision_id: revision.id, user_id: user.id, key: "test", text: "bar"}) + operation = Factory.insert(Operation, revision_id: revision.id, user_id: user.id, key: "test", text: "bar") user = Map.put(user, :permissions, %{project.id => "reviewer"}) root = nil diff --git a/test/graphql/requests/project_integrations_request_test.exs b/test/graphql/requests/project_integrations_request_test.exs index b0183db99..6815fe2c8 100644 --- a/test/graphql/requests/project_integrations_request_test.exs +++ b/test/graphql/requests/project_integrations_request_test.exs @@ -8,21 +8,12 @@ defmodule AccentTest.GraphQL.Requests.ProjectIntegrations do alias Accent.Repo alias Accent.User - @user %User{email: "test@test.com"} - setup do - user = Repo.insert!(@user) - - project = - Repo.insert!(%Project{ - main_color: "#f00", - name: "My project", - last_synced_at: DateTime.from_naive!(~N[2017-01-01T00:00:00], "Etc/UTC") - }) - + user = Factory.insert(User) + project = Factory.insert(Project, last_synced_at: DateTime.from_naive!(~N[2017-01-01T00:00:00], "Etc/UTC")) user = %{user | permissions: %{project.id => "admin"}} - Repo.insert!(%Collaborator{project_id: project.id, user_id: user.id, role: "admin"}) + Factory.insert(Collaborator, project_id: project.id, user_id: user.id, role: "admin") create_mutation = """ mutation IntegrationCreate( diff --git a/test/graphql/requests/project_revisions_request_test.exs b/test/graphql/requests/project_revisions_request_test.exs index 871528f6a..999067e4b 100644 --- a/test/graphql/requests/project_revisions_request_test.exs +++ b/test/graphql/requests/project_revisions_request_test.exs @@ -5,35 +5,25 @@ defmodule AccentTest.GraphQL.Requests.ProjectRevisions do alias Accent.Collaborator alias Accent.Language alias Accent.Project - alias Accent.Repo alias Accent.Revision alias Accent.User - @user %User{email: "test@test.com"} - setup do - user = Repo.insert!(@user) - french_language = Repo.insert!(%Language{name: "french", slug: Ecto.UUID.generate()}) - - project = - Repo.insert!(%Project{ - main_color: "#f00", - name: "My project", - last_synced_at: DateTime.from_naive!(~N[2017-01-01T00:00:00], "Etc/UTC") - }) - + user = Factory.insert(User) + french_language = Factory.insert(Language) + project = Factory.insert(Project, last_synced_at: DateTime.from_naive!(~N[2017-01-01T00:00:00], "Etc/UTC")) user = %{user | permissions: %{project.id => "admin"}} - Repo.insert!(%Collaborator{project_id: project.id, user_id: user.id, role: "admin"}) + Factory.insert(Collaborator, project_id: project.id, user_id: user.id, role: "admin") revision = - Repo.insert!(%Revision{ + Factory.insert(Revision, language_id: french_language.id, name: "foo", slug: "bar", project_id: project.id, master: true - }) + ) {:ok, [user: user, project: project, revision: revision]} end diff --git a/test/graphql/requests/projects_request_test.exs b/test/graphql/requests/projects_request_test.exs index f4fc66377..3d425bbe7 100644 --- a/test/graphql/requests/projects_request_test.exs +++ b/test/graphql/requests/projects_request_test.exs @@ -5,34 +5,25 @@ defmodule AccentTest.GraphQL.Requests.Projects do alias Accent.Collaborator alias Accent.Language alias Accent.Project - alias Accent.Repo alias Accent.Revision alias Accent.Translation alias Accent.User - @user %User{email: "test@test.com"} - setup do - user = Repo.insert!(@user) - french_language = Repo.insert!(%Language{name: "french", slug: Ecto.UUID.generate()}) - - project = - Repo.insert!(%Project{ - main_color: "#f00", - name: "My project", - last_synced_at: DateTime.from_naive!(~N[2017-01-01T00:00:00], "Etc/UTC") - }) + user = Factory.insert(User) + french_language = Factory.insert(Language) + project = Factory.insert(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"}) - revision = Repo.insert!(%Revision{language_id: french_language.id, project_id: project.id, master: true}) + Factory.insert(Collaborator, project_id: project.id, user_id: user.id, role: "admin") + revision = Factory.insert(Revision, language_id: french_language.id, project_id: project.id, master: true) {:ok, [user: user, project: project, language: french_language, revision: revision]} end test "list projects", %{user: user, project: project, revision: revision} do - Repo.insert!(%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}) + Factory.insert(Translation, revision_id: revision.id, key: "A", conflicted: true) + Factory.insert(Translation, revision_id: revision.id, key: "B", conflicted: true) + Factory.insert(Translation, revision_id: revision.id, key: "C", conflicted: false) {:ok, data} = Absinthe.run( @@ -44,9 +35,6 @@ defmodule AccentTest.GraphQL.Requests.Projects do id name lastSyncedAt - translationsCount - conflictsCount - reviewedCount } } } @@ -61,9 +49,5 @@ defmodule AccentTest.GraphQL.Requests.Projects do 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/test/graphql/resolvers/activity_test.exs b/test/graphql/resolvers/activity_test.exs index 7a638570f..ad5f59cdf 100644 --- a/test/graphql/resolvers/activity_test.exs +++ b/test/graphql/resolvers/activity_test.exs @@ -6,7 +6,6 @@ defmodule AccentTest.GraphQL.Resolvers.Activity do alias Accent.Language alias Accent.Operation alias Accent.Project - alias Accent.Repo alias Accent.Revision alias Accent.Translation alias Accent.User @@ -18,25 +17,23 @@ defmodule AccentTest.GraphQL.Resolvers.Activity do defstruct [:assigns] end - @user %User{email: "test@test.com"} - setup do - user = Repo.insert!(@user) - language = Repo.insert!(%Language{name: "french"}) - project = Repo.insert!(%Project{main_color: "#f00", name: "My project"}) + user = Factory.insert(User) + language = Factory.insert(Language) + project = Factory.insert(Project) - revision = Repo.insert!(%Revision{language_id: language.id, project_id: project.id, master: true}) + revision = Factory.insert(Revision, language_id: language.id, project_id: project.id, master: true) translation = - Repo.insert!(%Translation{revision_id: revision.id, key: "ok", corrected_text: "bar", proposed_text: "bar"}) + Factory.insert(Translation, revision_id: revision.id, key: "ok", corrected_text: "bar", proposed_text: "bar") {:ok, [user: user, project: project, revision: revision, translation: translation]} end test "list activities", %{user: user, project: project, translation: translation, revision: revision} do - operation = Repo.insert!(%Operation{user_id: user.id, project_id: project.id, action: "sync"}) + operation = Factory.insert(Operation, user_id: user.id, project_id: project.id, action: "sync") - Repo.insert!(%Operation{ + Factory.insert(Operation, user_id: user.id, translation_id: translation.id, revision_id: revision.id, @@ -44,7 +41,7 @@ defmodule AccentTest.GraphQL.Resolvers.Activity do text: "foo", action: "update", batch_operation_id: operation.id - }) + ) {:ok, %{entries: entries, meta: meta}} = Resolver.list_operations(operation, %{}, %{}) @@ -57,16 +54,16 @@ defmodule AccentTest.GraphQL.Resolvers.Activity do end test "list project", %{user: user, project: project, translation: translation, revision: revision} do - Repo.insert!(%Operation{ + Factory.insert(Operation, user_id: user.id, translation_id: translation.id, revision_id: revision.id, key: translation.key, text: "foo", action: "update" - }) + ) - Repo.insert!(%Operation{user_id: user.id, project_id: project.id, action: "sync"}) + Factory.insert(Operation, user_id: user.id, project_id: project.id, action: "sync") {:ok, %{entries: entries, meta: meta}} = Resolver.list_project(project, %{}, %{}) assert Enum.count(entries) == 2 @@ -78,9 +75,7 @@ defmodule AccentTest.GraphQL.Resolvers.Activity do end test "list project paginated", %{user: user, project: project} do - for _index <- 1..100 do - Repo.insert!(%Operation{user_id: user.id, project_id: project.id, action: "sync"}) - end + Factory.seed(Operation, 100, user_id: user.id, project_id: project.id, action: "sync") {:ok, %{entries: entries, meta: meta}} = Resolver.list_project(project, %{page: 3}, %{}) @@ -93,41 +88,41 @@ defmodule AccentTest.GraphQL.Resolvers.Activity do end test "list project from user", %{user: user, project: project} do - other_user = Repo.insert!(%User{email: "foo@bar.com"}) - Repo.insert!(%Operation{user_id: other_user.id, project_id: project.id, action: "sync"}) - Repo.insert!(%Operation{user_id: user.id, project_id: project.id, action: "sync"}) + other_user = Factory.insert(User, email: "foo@bar.com") + Factory.insert(Operation, user_id: other_user.id, project_id: project.id, action: "sync") + Factory.insert(Operation, user_id: user.id, project_id: project.id, action: "sync") {:ok, %{entries: entries}} = Resolver.list_project(project, %{user_id: other_user.id}, %{}) assert Enum.count(entries) == 1 end test "list project from batch", %{user: user, project: project} do - Repo.insert!(%Operation{user_id: user.id, project_id: project.id, action: "sync", batch: true}) - Repo.insert!(%Operation{user_id: user.id, project_id: project.id, action: "sync"}) + Factory.insert(Operation, user_id: user.id, project_id: project.id, action: "sync", batch: true) + Factory.insert(Operation, user_id: user.id, project_id: project.id, action: "sync") {:ok, %{entries: entries}} = Resolver.list_project(project, %{is_batch: true}, %{}) assert Enum.count(entries) == 1 end test "list project from action", %{user: user, project: project} do - Repo.insert!(%Operation{user_id: user.id, project_id: project.id, action: "delete_document"}) - Repo.insert!(%Operation{user_id: user.id, project_id: project.id, action: "sync"}) + Factory.insert(Operation, user_id: user.id, project_id: project.id, action: "delete_document") + Factory.insert(Operation, user_id: user.id, project_id: project.id, action: "sync") {:ok, %{entries: entries}} = Resolver.list_project(project, %{action: "sync"}, %{}) assert Enum.count(entries) == 1 end test "list translation", %{user: user, project: project, translation: translation, revision: revision} do - Repo.insert!(%Operation{ + Factory.insert(Operation, user_id: user.id, translation_id: translation.id, revision_id: revision.id, key: translation.key, text: "foo", action: "update" - }) + ) - Repo.insert!(%Operation{user_id: user.id, project_id: project.id, action: "sync"}) + Factory.insert(Operation, user_id: user.id, project_id: project.id, action: "sync") {:ok, %{entries: entries, meta: meta}} = Resolver.list_translation(translation, %{}, %{}) assert Enum.count(entries) == 1 @@ -139,32 +134,32 @@ defmodule AccentTest.GraphQL.Resolvers.Activity do end test "list translation from user", %{user: user, translation: translation} do - other_user = Repo.insert!(%User{email: "foo@bar.com"}) - Repo.insert!(%Operation{user_id: other_user.id, translation_id: translation.id, action: "update"}) - Repo.insert!(%Operation{user_id: user.id, translation_id: translation.id, action: "update"}) + other_user = Factory.insert(User, email: "foo@bar.com") + Factory.insert(Operation, user_id: other_user.id, translation_id: translation.id, action: "update") + Factory.insert(Operation, user_id: user.id, translation_id: translation.id, action: "update") {:ok, %{entries: entries}} = Resolver.list_translation(translation, %{user_id: other_user.id}, %{}) assert Enum.count(entries) == 1 end test "list translation from batch", %{user: user, translation: translation} do - Repo.insert!(%Operation{user_id: user.id, translation_id: translation.id, action: "sync", batch: true}) - Repo.insert!(%Operation{user_id: user.id, translation_id: translation.id, action: "update"}) + Factory.insert(Operation, user_id: user.id, translation_id: translation.id, action: "sync", batch: true) + Factory.insert(Operation, user_id: user.id, translation_id: translation.id, action: "update") {:ok, %{entries: entries}} = Resolver.list_translation(translation, %{is_batch: true}, %{}) assert Enum.count(entries) == 1 end test "list translation from action", %{user: user, translation: translation} do - Repo.insert!(%Operation{user_id: user.id, translation_id: translation.id, action: "delete_document"}) - Repo.insert!(%Operation{user_id: user.id, translation_id: translation.id, action: "update"}) + Factory.insert(Operation, user_id: user.id, translation_id: translation.id, action: "delete_document") + Factory.insert(Operation, user_id: user.id, translation_id: translation.id, action: "update") {:ok, %{entries: entries}} = Resolver.list_translation(translation, %{action: "update"}, %{}) assert Enum.count(entries) == 1 end test "show project", %{user: user, project: project} do - operation = Repo.insert!(%Operation{user_id: user.id, project_id: project.id, action: "sync"}) + operation = Factory.insert(Operation, user_id: user.id, project_id: project.id, action: "sync") {:ok, %{id: id}} = Resolver.show_project(project, %{id: operation.id}, %{}) diff --git a/test/graphql/resolvers/collaborator_test.exs b/test/graphql/resolvers/collaborator_test.exs index 02f8a0492..ef68bf61f 100644 --- a/test/graphql/resolvers/collaborator_test.exs +++ b/test/graphql/resolvers/collaborator_test.exs @@ -13,11 +13,9 @@ defmodule AccentTest.GraphQL.Resolvers.Collaborator do defstruct [:assigns] end - @user %User{email: "test@test.com"} - setup do - user = Repo.insert!(@user) - project = Repo.insert!(%Project{main_color: "#f00", name: "My project"}) + user = Factory.insert(User) + project = Factory.insert(Project) {:ok, [user: user, project: project]} end @@ -44,7 +42,7 @@ defmodule AccentTest.GraphQL.Resolvers.Collaborator do test "update", %{project: project, user: user} do context = %{context: %{conn: %PlugConn{assigns: %{current_user: user}}}} - collaborator = Repo.insert!(%Collaborator{email: "test@example.com", role: "reviewer", project_id: project.id}) + collaborator = Factory.insert(Collaborator, email: "test@example.com", role: "reviewer", project_id: project.id) {:ok, result} = Resolver.update(collaborator, %{role: "owner"}, context) @@ -54,7 +52,7 @@ defmodule AccentTest.GraphQL.Resolvers.Collaborator do test "delete", %{project: project, user: user} do context = %{context: %{conn: %PlugConn{assigns: %{current_user: user}}}} - collaborator = Repo.insert!(%Collaborator{email: "test@example.com", role: "reviewer", project_id: project.id}) + collaborator = Factory.insert(Collaborator, email: "test@example.com", role: "reviewer", project_id: project.id) {:ok, result} = Resolver.delete(collaborator, %{}, context) diff --git a/test/graphql/resolvers/comment_test.exs b/test/graphql/resolvers/comment_test.exs index e761c4410..107b483e5 100644 --- a/test/graphql/resolvers/comment_test.exs +++ b/test/graphql/resolvers/comment_test.exs @@ -16,17 +16,15 @@ defmodule AccentTest.GraphQL.Resolvers.Comment do defstruct [:assigns] end - @user %User{email: "test@test.com"} - setup do - user = Repo.insert!(@user) - french_language = Repo.insert!(%Language{name: "french"}) - project = Repo.insert!(%Project{main_color: "#f00", name: "My project"}) + user = Factory.insert(User) + french_language = Factory.insert(Language) + project = Factory.insert(Project) - revision = Repo.insert!(%Revision{language_id: french_language.id, project_id: project.id, master: true}) + revision = Factory.insert(Revision, language_id: french_language.id, project_id: project.id, master: true) translation = - Repo.insert!(%Translation{revision_id: revision.id, key: "ok", corrected_text: "bar", proposed_text: "bar"}) + Factory.insert(Translation, revision_id: revision.id, key: "ok", corrected_text: "bar", proposed_text: "bar") {:ok, [user: user, project: project, translation: translation]} end @@ -55,7 +53,7 @@ defmodule AccentTest.GraphQL.Resolvers.Comment do end test "delete", %{translation: translation, user: user} do - comment = Repo.insert!(%Comment{translation_id: translation.id, text: "test", user: user}) + comment = Factory.insert(Comment, translation_id: translation.id, text: "test", user: user) assert get_in(Repo.all(Comment), [Access.all(), Access.key(:id)]) == [comment.id] @@ -66,7 +64,7 @@ defmodule AccentTest.GraphQL.Resolvers.Comment do end test "update", %{translation: translation, user: user} do - comment = Repo.insert!(%Comment{translation_id: translation.id, text: "test", user: user}) + comment = Factory.insert(Comment, translation_id: translation.id, text: "test", user: user) assert get_in(Repo.all(Comment), [Access.all(), Access.key(:id)]) == [comment.id] @@ -77,7 +75,7 @@ defmodule AccentTest.GraphQL.Resolvers.Comment do end test "list project", %{project: project, translation: translation, user: user} do - comment = Repo.insert!(%Comment{translation_id: translation.id, text: "test", user: user}) + comment = Factory.insert(Comment, translation_id: translation.id, text: "test", user: user) {:ok, result} = Resolver.list_project(project, %{}, %{}) @@ -85,7 +83,7 @@ defmodule AccentTest.GraphQL.Resolvers.Comment do end test "list translation", %{translation: translation, user: user} do - comment = Repo.insert!(%Comment{translation_id: translation.id, text: "test", user: user}) + comment = Factory.insert(Comment, translation_id: translation.id, text: "test", user: user) {:ok, result} = Resolver.list_translation(translation, %{}, %{}) diff --git a/test/graphql/resolvers/document_test.exs b/test/graphql/resolvers/document_test.exs index 117e5db6c..94ea69b2f 100644 --- a/test/graphql/resolvers/document_test.exs +++ b/test/graphql/resolvers/document_test.exs @@ -16,34 +16,32 @@ defmodule AccentTest.GraphQL.Resolvers.Document do defstruct [:assigns] end - @user %User{email: "test@test.com"} - setup do - user = Repo.insert!(@user) - french_language = Repo.insert!(%Language{name: "french"}) - project = Repo.insert!(%Project{main_color: "#f00", name: "My project"}) + user = Factory.insert(User) + french_language = Factory.insert(Language) + project = Factory.insert(Project) - revision = Repo.insert!(%Revision{language_id: french_language.id, project_id: project.id, master: true}) + revision = Factory.insert(Revision, language_id: french_language.id, project_id: project.id, master: true) document = - Repo.insert!(%Document{ + Factory.insert(Document, project_id: project.id, path: "test", format: "json", updated_at: DateTime.from_unix!(1_432_560_368_868_569, :microsecond) - }) + ) {:ok, [user: user, project: project, document: document, revision: revision]} end test "delete", %{document: document, revision: revision, user: user} do - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, document_id: document.id, key: "ok", corrected_text: "bar", proposed_text: "bar" - }) + ) context = %{context: %{conn: %PlugConn{assigns: %{current_user: user}}}} {:ok, result} = Resolver.delete(document, %{}, context) @@ -71,12 +69,12 @@ defmodule AccentTest.GraphQL.Resolvers.Document do test "update with existing path", %{document: document, project: project, user: user} do other_document = - Repo.insert!(%Document{ + Factory.insert(Document, project_id: project.id, path: "test2", format: "json", updated_at: DateTime.add(document.updated_at, 3600, :second) - }) + ) context = %{context: %{conn: %PlugConn{assigns: %{current_user: user}}}} {:ok, result} = Resolver.update(document, %{path: other_document.path}, context) @@ -87,14 +85,14 @@ defmodule AccentTest.GraphQL.Resolvers.Document do end test "show project", %{document: document, project: project, revision: revision} do - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, document_id: document.id, key: "ok", corrected_text: "bar", proposed_text: "bar", conflicted: false - }) + ) {:ok, result} = Resolver.show_project(project, %{id: document.id}, %{}) @@ -106,32 +104,32 @@ defmodule AccentTest.GraphQL.Resolvers.Document do test "list project", %{document: document, project: project, revision: revision} do other_document = - Repo.insert!(%Document{ + Factory.insert(Document, project_id: project.id, path: "test2", format: "json", updated_at: DateTime.add(document.updated_at, 3600, :second) - }) + ) - _empty_document = Repo.insert!(%Document{project_id: project.id, path: "test3", format: "json"}) + _empty_document = Factory.insert(Document, project_id: project.id, path: "test3", format: "json") - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, document_id: document.id, key: "ok", corrected_text: "bar", proposed_text: "bar", conflicted: false - }) + ) - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, document_id: other_document.id, key: "ok", corrected_text: "bar", proposed_text: "bar", conflicted: true - }) + ) {:ok, result} = Resolver.list_project(project, %{exclude_empty_translations: true}, %{}) @@ -142,17 +140,17 @@ defmodule AccentTest.GraphQL.Resolvers.Document do end test "list project with many deleted documents", %{document: document, project: project, revision: revision} do - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, document_id: document.id, key: "ok", corrected_text: "bar", proposed_text: "bar", conflicted: false - }) + ) for i <- 1..80 do - Repo.insert!(%Document{project_id: project.id, path: "doc-#{i}", format: "json"}) + Factory.insert(Document, project_id: project.id, path: "doc-#{i}", format: "json") end {:ok, result} = Resolver.list_project(project, %{exclude_empty_translations: true}, %{}) diff --git a/test/graphql/resolvers/integration_test.exs b/test/graphql/resolvers/integration_test.exs index aef6ddf15..43ef90262 100644 --- a/test/graphql/resolvers/integration_test.exs +++ b/test/graphql/resolvers/integration_test.exs @@ -13,11 +13,9 @@ defmodule AccentTest.GraphQL.Resolvers.Integration do defstruct [:assigns] end - @user %User{email: "test@test.com"} - setup do - user = Repo.insert!(@user) - project = Repo.insert!(%Project{main_color: "#f00", name: "My project"}) + user = Factory.insert(User) + project = Factory.insert(Project) {:ok, [user: user, project: project]} end @@ -77,7 +75,8 @@ defmodule AccentTest.GraphQL.Resolvers.Integration do assert integration.errors == [ service: - {"is invalid", [validation: :inclusion, enum: ["slack", "github", "discord", "azure_storage_container"]]} + {"is invalid", + [validation: :inclusion, enum: ["slack", "github", "discord", "azure_storage_container", "aws_s3"]]} ] assert Repo.all(Integration) == [] @@ -87,13 +86,13 @@ defmodule AccentTest.GraphQL.Resolvers.Integration do context = %{context: %{conn: %PlugConn{assigns: %{current_user: user}}}} integration = - Repo.insert!(%Integration{ + Factory.insert(Integration, project_id: project.id, user_id: user.id, service: "slack", events: ["sync"], - data: %{url: "http://google.ca"} - }) + data: %{id: Ecto.UUID.generate(), url: "http://google.ca"} + ) {:ok, updated_integration} = Resolver.update(integration, %{data: %{url: "http://example.com/update"}}, context) @@ -104,13 +103,13 @@ defmodule AccentTest.GraphQL.Resolvers.Integration do context = %{context: %{conn: %PlugConn{assigns: %{current_user: user}}}} integration = - Repo.insert!(%Integration{ + Factory.insert(Integration, project_id: project.id, user_id: user.id, service: "slack", events: ["sync"], - data: %{url: "http://google.ca"} - }) + data: %{id: Ecto.UUID.generate(), url: "http://google.ca"} + ) {:ok, deleted_integration} = Resolver.delete(integration, %{}, context) diff --git a/test/graphql/resolvers/lint_test.exs b/test/graphql/resolvers/lint_test.exs index e07738019..fa1d7c544 100644 --- a/test/graphql/resolvers/lint_test.exs +++ b/test/graphql/resolvers/lint_test.exs @@ -7,7 +7,6 @@ defmodule AccentTest.GraphQL.Resolvers.Lint do alias Accent.Lint.Message alias Accent.Lint.Replacement alias Accent.Project - alias Accent.Repo alias Accent.Revision alias Accent.Translation alias Accent.User @@ -17,15 +16,13 @@ defmodule AccentTest.GraphQL.Resolvers.Lint do defstruct [:assigns] end - @user %User{email: "test@test.com"} - setup do - user = Repo.insert!(@user) - french_language = Repo.insert!(%Language{name: "french"}) - project = Repo.insert!(%Project{main_color: "#f00", name: "My project"}) + user = Factory.insert(User) + french_language = Factory.insert(Language) + project = Factory.insert(Project) revision = - Repo.insert!(%Revision{language_id: french_language.id, project_id: project.id, master: true, slug: "fr"}) + Factory.insert(Revision, language_id: french_language.id, project_id: project.id, master: true, slug: "fr") context = %{context: %{conn: %PlugConn{assigns: %{current_user: user}}}} @@ -34,23 +31,23 @@ defmodule AccentTest.GraphQL.Resolvers.Lint do test "lint", %{revision: revision, context: context} do master_translation = - Repo.insert!(%Translation{ + Factory.insert(Translation, revision: revision, conflicted: false, key: "ok2", corrected_text: "bar foo", proposed_text: "bar" - }) + ) translation = - Repo.insert!(%Translation{ + Factory.insert(Translation, revision: revision, master_translation: master_translation, conflicted: false, key: "ok", corrected_text: " bar foo", proposed_text: "bar" - }) + ) {:ok, result} = Resolver.lint_batched_translation(translation, %{}, context) diff --git a/test/graphql/resolvers/operation_test.exs b/test/graphql/resolvers/operation_test.exs index 51ff61127..26711b12d 100644 --- a/test/graphql/resolvers/operation_test.exs +++ b/test/graphql/resolvers/operation_test.exs @@ -12,14 +12,12 @@ defmodule AccentTest.GraphQL.Resolvers.Operation do alias Accent.Translation alias Accent.User - @user %User{email: "test@test.com"} - setup do - user = Repo.insert!(@user) - french_language = Repo.insert!(%Language{name: "french"}) - project = Repo.insert!(%Project{main_color: "#f00", name: "My project"}) + user = Factory.insert(User) + french_language = Factory.insert(Language) + project = Factory.insert(Project) - revision = Repo.insert!(%Revision{language_id: french_language.id, project_id: project.id, master: true}) + revision = Factory.insert(Revision, language_id: french_language.id, project_id: project.id, master: true) context = %{context: %{conn: %Plug.Conn{assigns: %{current_user: user}}}} {:ok, [user: user, project: project, revision: revision, context: context]} @@ -27,13 +25,13 @@ defmodule AccentTest.GraphQL.Resolvers.Operation do test "rollback", %{revision: revision, context: context} do translation = - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, conflicted: true, key: "ok", corrected_text: "baz", proposed_text: "bar" - }) + ) previous_translation = %PreviousTranslation{ conflicted: false, diff --git a/test/graphql/resolvers/permission_test.exs b/test/graphql/resolvers/permission_test.exs index 5de466204..a6bed8639 100644 --- a/test/graphql/resolvers/permission_test.exs +++ b/test/graphql/resolvers/permission_test.exs @@ -4,7 +4,6 @@ defmodule AccentTest.GraphQL.Resolvers.Permission do alias Accent.GraphQL.Resolvers.Permission, as: Resolver alias Accent.Project - alias Accent.Repo alias Accent.User defmodule PlugConn do @@ -12,11 +11,9 @@ defmodule AccentTest.GraphQL.Resolvers.Permission do defstruct [:assigns] end - @user %User{email: "test@test.com"} - setup do - user = Repo.insert!(@user) - project = Repo.insert!(%Project{main_color: "#f00", name: "My project"}) + user = Factory.insert(User) + project = Factory.insert(Project) {:ok, [user: user, project: project]} end diff --git a/test/graphql/resolvers/project_test.exs b/test/graphql/resolvers/project_test.exs index 1d7a6892d..de554e96a 100644 --- a/test/graphql/resolvers/project_test.exs +++ b/test/graphql/resolvers/project_test.exs @@ -2,6 +2,7 @@ defmodule AccentTest.GraphQL.Resolvers.Project do @moduledoc false use Accent.RepoCase, async: true + alias Accent.Collaborator alias Accent.GraphQL.Resolvers.Project, as: Resolver alias Accent.Language alias Accent.Operation @@ -17,14 +18,15 @@ defmodule AccentTest.GraphQL.Resolvers.Project do defstruct [:assigns] end - @user %User{email: "test@test.com"} - setup do - user = Repo.insert!(@user) - language = Repo.insert!(%Language{name: "English", slug: Ecto.UUID.generate()}) + user = Factory.insert(User) + language = Factory.insert(Language) {:ok, project} = - ProjectCreator.create(params: %{main_color: "#f00", name: "My project", language_id: language.id}, user: user) + ProjectCreator.create( + params: %{main_color: "#f00", name: "My project", language_id: language.id}, + user: user + ) user = %{user | permissions: %{project.id => "owner"}} @@ -37,7 +39,7 @@ defmodule AccentTest.GraphQL.Resolvers.Project do end test "list viewer", %{user: user, project: project} do - Repo.insert!(%Project{main_color: "#f00", name: "Other project"}) + Factory.insert(Project) {:ok, result} = Resolver.list_viewer(user, %{}, %{}) @@ -50,7 +52,7 @@ defmodule AccentTest.GraphQL.Resolvers.Project do end test "list viewer search", %{user: user, language: language} do - Repo.insert!(%Project{main_color: "#f00", name: "Other project"}) + Factory.insert(Project) {:ok, project_two} = ProjectCreator.create( @@ -112,26 +114,19 @@ defmodule AccentTest.GraphQL.Resolvers.Project do assert meta.previous_page == 1 end - test "list viewer ordering", %{user: user, language: language, project: project_one} do - Repo.insert!(%Project{main_color: "#f00", name: "Other project"}) - - {:ok, project_two} = - ProjectCreator.create( - params: %{main_color: "#f00", name: "X - My second project", language_id: language.id}, - user: user - ) + test "list viewer ordering", %{user: user, project: project_one} do + Factory.insert(Project) - {:ok, project_three} = - ProjectCreator.create( - params: %{main_color: "#f00", name: "A - My third project", language_id: language.id}, - user: user - ) + project_two = Factory.insert(Project, last_synced_at: ~U[2020-01-01T00:00:00Z]) + project_three = Factory.insert(Project, last_synced_at: ~U[2022-02-02T00:00:00Z]) + Factory.insert(Collaborator, project_id: project_two.id, user_id: user.id, role: "admin") + Factory.insert(Collaborator, project_id: project_three.id, user_id: user.id, role: "admin") {:ok, result} = Resolver.list_viewer(user, %{}, %{}) assert get_in(result, [:entries, Access.all(), Access.key(:id)]) == [ - project_three.id, project_one.id, + project_three.id, project_two.id ] end @@ -203,7 +198,7 @@ defmodule AccentTest.GraphQL.Resolvers.Project do test "get latest activity", %{user: user, project: project} do context = %{context: %{conn: %PlugConn{assigns: %{current_user: user}}}} - operation = Repo.insert!(%Operation{user_id: user.id, project_id: project.id, action: "sync"}) + operation = Factory.insert(Operation, user_id: user.id, project_id: project.id, action: "sync") {:ok, latest_activity} = Resolver.last_activity(project, %{}, context) @@ -212,7 +207,7 @@ defmodule AccentTest.GraphQL.Resolvers.Project do test "lint_translations", %{user: user, project: project} do [revision] = project.revisions - Repo.insert!(%Translation{revision_id: revision.id, key: "a", proposed_text: " A", corrected_text: " A"}) + Factory.insert(Translation, revision_id: revision.id, key: "a", proposed_text: " A", corrected_text: " A") context = %{context: %{conn: %PlugConn{assigns: %{current_user: user}}}} @@ -229,16 +224,16 @@ defmodule AccentTest.GraphQL.Resolvers.Project do test "lint_translations on current version only", %{user: user, project: project} do [revision] = project.revisions - version = Repo.insert!(%Version{project_id: project.id, name: "foo", tag: "bar", user_id: user.id}) - Repo.insert!(%Translation{revision_id: revision.id, key: "a", proposed_text: " A", corrected_text: " A"}) + version = Factory.insert(Version, project_id: project.id, name: "foo", tag: "bar", user_id: user.id) + Factory.insert(Translation, revision_id: revision.id, key: "a", proposed_text: " A", corrected_text: " A") - Repo.insert!(%Translation{ + Factory.insert(Translation, version_id: version.id, revision_id: revision.id, key: "b", proposed_text: " B", corrected_text: " B" - }) + ) context = %{context: %{conn: %PlugConn{assigns: %{current_user: user}}}} diff --git a/test/graphql/resolvers/revision_test.exs b/test/graphql/resolvers/revision_test.exs index 6a408f494..ff847f956 100644 --- a/test/graphql/resolvers/revision_test.exs +++ b/test/graphql/resolvers/revision_test.exs @@ -5,7 +5,6 @@ defmodule AccentTest.GraphQL.Resolvers.Revision do alias Accent.GraphQL.Resolvers.Revision, as: Resolver alias Accent.Language alias Accent.Project - alias Accent.Repo alias Accent.Revision alias Accent.Translation alias Accent.User @@ -15,23 +14,21 @@ defmodule AccentTest.GraphQL.Resolvers.Revision do defstruct [:assigns] end - @user %User{email: "test@test.com"} - setup do - user = Repo.insert!(@user) - french_language = Repo.insert!(%Language{name: "french"}) - english_language = Repo.insert!(%Language{name: "english"}) - project = Repo.insert!(%Project{main_color: "#f00", name: "My project"}) + user = Factory.insert(User) + french_language = Factory.insert(Language) + english_language = Factory.insert(Language, name: "english") + project = Factory.insert(Project) - master_revision = Repo.insert!(%Revision{language_id: french_language.id, project_id: project.id, master: true}) + master_revision = Factory.insert(Revision, language_id: french_language.id, project_id: project.id, master: true) slave_revision = - Repo.insert!(%Revision{ + Factory.insert(Revision, language_id: english_language.id, project_id: project.id, master: false, master_revision_id: master_revision.id - }) + ) {:ok, [user: user, project: project, master_revision: master_revision, slave_revision: slave_revision]} end @@ -50,7 +47,7 @@ defmodule AccentTest.GraphQL.Resolvers.Revision do test "create", %{project: project, user: user} do context = %{context: %{conn: %PlugConn{assigns: %{current_user: user}}}} - language = Repo.insert!(%Language{name: "spanish"}) + language = Factory.insert(Language, name: "spanish") {:ok, result} = Resolver.create(project, %{language_id: language.id}, context) @@ -75,13 +72,13 @@ defmodule AccentTest.GraphQL.Resolvers.Revision do test "correct all", %{master_revision: revision, user: user} do context = %{context: %{conn: %PlugConn{assigns: %{current_user: user}}}} - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, key: "ok", corrected_text: "bar", proposed_text: "bar", conflicted: true - }) + ) {:ok, result} = Resolver.correct_all(revision, %{}, context) @@ -93,13 +90,13 @@ defmodule AccentTest.GraphQL.Resolvers.Revision do test "uncorrect all", %{master_revision: revision, user: user} do context = %{context: %{conn: %PlugConn{assigns: %{current_user: user}}}} - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, key: "ok", corrected_text: "bar", proposed_text: "bar", conflicted: false - }) + ) {:ok, result} = Resolver.uncorrect_all(revision, %{}, context) diff --git a/test/graphql/resolvers/translation_comment_subscription_test.exs b/test/graphql/resolvers/translation_comment_subscription_test.exs index 834d6e1c5..c733f9036 100644 --- a/test/graphql/resolvers/translation_comment_subscription_test.exs +++ b/test/graphql/resolvers/translation_comment_subscription_test.exs @@ -20,21 +20,19 @@ defmodule AccentTest.GraphQL.Resolvers.TranslationCommentSubscription do defstruct [:assigns] end - @user %User{email: "test@test.com"} - setup do - user = Repo.insert!(@user) - french_language = Repo.insert!(%Language{name: "french"}) - project = Repo.insert!(%Project{main_color: "#f00", name: "My project"}) + user = Factory.insert(User) + french_language = Factory.insert(Language) + project = Factory.insert(Project) - revision = Repo.insert!(%Revision{language_id: french_language.id, project_id: project.id, master: true}) + revision = Factory.insert(Revision, language_id: french_language.id, project_id: project.id, master: true) {:ok, [user: user, project: project, revision: revision]} end test "create", %{user: user, revision: revision} do translation = - Repo.insert!(%Translation{revision_id: revision.id, key: "ok", corrected_text: "bar", proposed_text: "bar"}) + Factory.insert(Translation, revision_id: revision.id, key: "ok", corrected_text: "bar", proposed_text: "bar") context = %{context: %{conn: %PlugConn{assigns: %{current_user: user}}}} @@ -46,10 +44,10 @@ defmodule AccentTest.GraphQL.Resolvers.TranslationCommentSubscription do test "delete", %{user: user, revision: revision} do translation = - Repo.insert!(%Translation{revision_id: revision.id, key: "ok", corrected_text: "bar", proposed_text: "bar"}) + Factory.insert(Translation, revision_id: revision.id, key: "ok", corrected_text: "bar", proposed_text: "bar") context = %{context: %{conn: %PlugConn{assigns: %{current_user: user}}}} - subscription = Repo.insert!(%TranslationCommentsSubscription{user_id: user.id, translation_id: translation.id}) + subscription = Factory.insert(TranslationCommentsSubscription, user_id: user.id, translation_id: translation.id) {:ok, result} = Resolver.delete(subscription, %{}, context) diff --git a/test/graphql/resolvers/translation_test.exs b/test/graphql/resolvers/translation_test.exs index 347815723..7dea7e80f 100644 --- a/test/graphql/resolvers/translation_test.exs +++ b/test/graphql/resolvers/translation_test.exs @@ -17,14 +17,12 @@ defmodule AccentTest.GraphQL.Resolvers.Translation do defstruct [:assigns] end - @user %User{email: "test@test.com"} - setup do - user = Repo.insert!(@user) - french_language = Repo.insert!(%Language{name: "french"}) - project = Repo.insert!(%Project{main_color: "#f00", name: "My project"}) + user = Factory.insert(User) + french_language = Factory.insert(Language) + project = Factory.insert(Project) - revision = Repo.insert!(%Revision{language_id: french_language.id, project_id: project.id, master: true}) + revision = Factory.insert(Revision, language_id: french_language.id, project_id: project.id, master: true) context = %{context: %{conn: %PlugConn{assigns: %{current_user: user}}}} {:ok, [user: user, project: project, revision: revision, context: context]} @@ -42,13 +40,13 @@ defmodule AccentTest.GraphQL.Resolvers.Translation do test "correct", %{revision: revision, context: context} do translation = - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, conflicted: true, key: "ok", corrected_text: "bar", proposed_text: "bar" - }) + ) {:ok, result} = Resolver.correct(translation, %{text: "Corrected text"}, context) @@ -60,13 +58,13 @@ defmodule AccentTest.GraphQL.Resolvers.Translation do test "uncorrect", %{revision: revision, context: context} do translation = - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, conflicted: false, key: "ok", corrected_text: "bar", proposed_text: "bar" - }) + ) {:ok, result} = Resolver.uncorrect(translation, %{text: "baz"}, context) @@ -79,13 +77,13 @@ defmodule AccentTest.GraphQL.Resolvers.Translation do test "update", %{revision: revision, context: context} do translation = - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, conflicted: true, key: "ok", corrected_text: "bar", proposed_text: "bar" - }) + ) {:ok, result} = Resolver.update(translation, %{text: "Updated text"}, context) @@ -97,13 +95,13 @@ defmodule AccentTest.GraphQL.Resolvers.Translation do test "show project", %{project: project, revision: revision, context: context} do translation = - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, conflicted: true, key: "ok", corrected_text: "bar", proposed_text: "bar" - }) + ) {:ok, result} = Resolver.show_project(project, %{id: translation.id}, context) @@ -118,13 +116,13 @@ defmodule AccentTest.GraphQL.Resolvers.Translation do test "show project unknown project", %{revision: revision, context: context} do translation = - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, conflicted: true, key: "ok", corrected_text: "bar", proposed_text: "bar" - }) + ) {:ok, result} = Resolver.show_project(%Project{id: Ecto.UUID.generate()}, %{id: translation.id}, context) @@ -133,22 +131,22 @@ defmodule AccentTest.GraphQL.Resolvers.Translation do test "list revision", %{revision: revision, context: context} do translation = - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, conflicted: true, key: "ok", corrected_text: "bar", proposed_text: "bar" - }) + ) - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, conflicted: true, key: "hidden", corrected_text: "bar", proposed_text: "bar", locked: true - }) + ) {:ok, result} = Resolver.list_revision(revision, %{}, context) @@ -157,21 +155,21 @@ defmodule AccentTest.GraphQL.Resolvers.Translation do test "list revision with query", %{revision: revision, context: context} do translation = - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, conflicted: true, key: "ok", corrected_text: "bar", proposed_text: "bar" - }) + ) - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, conflicted: true, key: "aux", corrected_text: "foo", proposed_text: "foo" - }) + ) {:ok, result} = Resolver.list_revision(revision, %{query: "bar"}, context) @@ -179,27 +177,27 @@ defmodule AccentTest.GraphQL.Resolvers.Translation do end test "list revision with document", %{project: project, revision: revision, context: context} do - document = Repo.insert!(%Document{path: "bar", format: "json", project_id: project.id}) - other_document = Repo.insert!(%Document{path: "foo", format: "json", project_id: project.id}) + document = Factory.insert(Document, path: "bar", format: "json", project_id: project.id) + other_document = Factory.insert(Document, path: "foo", format: "json", project_id: project.id) translation = - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, conflicted: true, key: "ok", corrected_text: "bar", proposed_text: "bar", document_id: document.id - }) + ) - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, conflicted: true, key: "ok", corrected_text: "foo", proposed_text: "foo", document_id: other_document.id - }) + ) {:ok, result} = Resolver.list_revision(revision, %{document: document.id}, context) @@ -208,22 +206,22 @@ defmodule AccentTest.GraphQL.Resolvers.Translation do test "list revision with order", %{revision: revision, context: context} do translation = - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, conflicted: true, key: "aaaaaa", corrected_text: "bar", proposed_text: "bar" - }) + ) other_translation = - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, conflicted: true, key: "bbbbb", corrected_text: "foo", proposed_text: "foo" - }) + ) {:ok, result} = Resolver.list_revision(revision, %{order: "-key"}, context) @@ -232,21 +230,21 @@ defmodule AccentTest.GraphQL.Resolvers.Translation do test "list revision with conflicted", %{revision: revision, context: context} do translation = - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, conflicted: false, key: "bar", corrected_text: "bar", proposed_text: "bar" - }) + ) - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, conflicted: true, key: "foo", corrected_text: "foo", proposed_text: "foo" - }) + ) {:ok, result} = Resolver.list_revision(revision, %{is_conflicted: false}, context) @@ -254,27 +252,27 @@ defmodule AccentTest.GraphQL.Resolvers.Translation do end test "list revision with version", %{project: project, revision: revision, user: user, context: context} do - version = Repo.insert!(%Version{name: "bar", tag: "v1.0", project_id: project.id, user_id: user.id}) - other_version = Repo.insert!(%Version{name: "foo", tag: "v2.0", project_id: project.id, user_id: user.id}) + version = Factory.insert(Version, name: "bar", tag: "v1.0", project_id: project.id, user_id: user.id) + other_version = Factory.insert(Version, name: "foo", tag: "v2.0", project_id: project.id, user_id: user.id) translation = - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, conflicted: true, key: "ok", corrected_text: "bar", proposed_text: "bar", version_id: version.id - }) + ) - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, conflicted: true, key: "ok", corrected_text: "foo", proposed_text: "foo", version_id: other_version.id - }) + ) {:ok, result} = Resolver.list_revision(revision, %{version: version.id}, context) @@ -282,33 +280,33 @@ defmodule AccentTest.GraphQL.Resolvers.Translation do end test "related translations", %{project: project, revision: revision, context: context} do - english_language = Repo.insert!(%Language{name: "english"}) + english_language = Factory.insert(Language, name: "english") other_revision = - Repo.insert!(%Revision{ + Factory.insert(Revision, language_id: english_language.id, project_id: project.id, master: false, master_revision_id: revision.id - }) + ) translation = - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, conflicted: true, key: "ok", corrected_text: "bar", proposed_text: "bar" - }) + ) other_translation = - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: other_revision.id, conflicted: true, key: "ok", corrected_text: "foo", proposed_text: "foo" - }) + ) {:ok, result} = Resolver.related_translations(translation, %{}, context) @@ -316,33 +314,33 @@ defmodule AccentTest.GraphQL.Resolvers.Translation do end test "master translation", %{project: project, revision: revision, context: context} do - english_language = Repo.insert!(%Language{name: "english"}) + english_language = Factory.insert(Language, name: "english") other_revision = - Repo.insert!(%Revision{ + Factory.insert(Revision, language_id: english_language.id, project_id: project.id, master: false, master_revision_id: revision.id - }) + ) translation = - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, conflicted: true, key: "ok", corrected_text: "bar", proposed_text: "bar" - }) + ) other_translation = - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: other_revision.id, conflicted: true, key: "ok", corrected_text: "foo", proposed_text: "foo" - }) + ) {:ok, result} = Resolver.master_translation(other_translation, %{}, context) @@ -350,32 +348,32 @@ defmodule AccentTest.GraphQL.Resolvers.Translation do end test "master translation as master", %{project: project, revision: revision, context: context} do - english_language = Repo.insert!(%Language{name: "english"}) + english_language = Factory.insert(Language, name: "english") other_revision = - Repo.insert!(%Revision{ + Factory.insert(Revision, language_id: english_language.id, project_id: project.id, master: false, master_revision_id: revision.id - }) + ) translation = - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, conflicted: true, key: "ok", corrected_text: "bar", proposed_text: "bar" - }) + ) - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: other_revision.id, conflicted: true, key: "ok", corrected_text: "foo", proposed_text: "foo" - }) + ) {:ok, result} = Resolver.master_translation(translation, %{}, context) diff --git a/test/graphql/resolvers/version_test.exs b/test/graphql/resolvers/version_test.exs index 3b2f68209..9199bad79 100644 --- a/test/graphql/resolvers/version_test.exs +++ b/test/graphql/resolvers/version_test.exs @@ -4,7 +4,6 @@ defmodule AccentTest.GraphQL.Resolvers.Version do alias Accent.GraphQL.Resolvers.Version, as: Resolver alias Accent.Project - alias Accent.Repo alias Accent.User alias Accent.Version @@ -13,13 +12,11 @@ defmodule AccentTest.GraphQL.Resolvers.Version do defstruct [:assigns] end - @user %User{email: "test@test.com"} - setup do - user = Repo.insert!(@user) - project = Repo.insert!(%Project{main_color: "#f00", name: "My project"}) + user = Factory.insert(User) + project = Factory.insert(Project) - version = Repo.insert!(%Version{name: "version1", tag: "v1", project_id: project.id, user_id: user.id}) + version = Factory.insert(Version, name: "version1", tag: "v1", project_id: project.id, user_id: user.id) {:ok, [user: user, project: project, version: version]} end diff --git a/test/graphql/resolvers/viewer_test.exs b/test/graphql/resolvers/viewer_test.exs index 39585c0fb..e3714f23b 100644 --- a/test/graphql/resolvers/viewer_test.exs +++ b/test/graphql/resolvers/viewer_test.exs @@ -5,7 +5,6 @@ defmodule AccentTest.GraphQL.Resolvers.Viewer do alias Accent.GraphQL.Resolvers.Viewer, as: Resolver alias Accent.Language alias Accent.ProjectCreator - alias Accent.Repo alias Accent.User defmodule PlugConn do @@ -13,11 +12,9 @@ defmodule AccentTest.GraphQL.Resolvers.Viewer do defstruct [:assigns] end - @user %User{email: "test@test.com"} - setup do - user = Repo.insert!(@user) - language = Repo.insert!(%Language{name: "English", slug: Ecto.UUID.generate()}) + user = Factory.insert(User) + language = Factory.insert(Language) {:ok, project} = ProjectCreator.create(params: %{main_color: "#f00", name: "My project", language_id: language.id}, user: user) diff --git a/test/hook/hook_test.exs b/test/hook/hook_test.exs index 31a82b2fc..5dbba8e5f 100644 --- a/test/hook/hook_test.exs +++ b/test/hook/hook_test.exs @@ -4,12 +4,11 @@ defmodule AccentTest.Hook do alias Accent.Hook alias Accent.Project - alias Accent.Repo alias Accent.User setup do - project = Repo.insert!(%Project{main_color: "#f00", name: "Test"}) - user = Repo.insert!(%User{fullname: "Test", email: "foo@test.com"}) + project = Factory.insert(Project) + user = Factory.insert(User, fullname: "Test", email: "foo@test.com") payload = %{test: "hook"} context = %Hook.Context{project_id: project.id, user_id: user.id, event: "event", payload: payload} @@ -31,13 +30,4 @@ defmodule AccentTest.Hook do args: %{worker_args | "event" => "sync"} ) end - - test "unsupported event", %{context: context, worker_args: worker_args} do - Hook.outbound(%{context | event: "foobar"}) - - refute_enqueued( - worker: Hook.Outbounds.Mock, - args: %{worker_args | "event" => "foobar"} - ) - end end diff --git a/test/hook/outbounds/discord_test.exs b/test/hook/outbounds/discord_test.exs index f81da9b97..6882be206 100644 --- a/test/hook/outbounds/discord_test.exs +++ b/test/hook/outbounds/discord_test.exs @@ -1,26 +1,25 @@ defmodule AccentTest.Hook.Outbounds.Discord do @moduledoc false - use Accent.RepoCase, async: true + use Accent.RepoCase, async: false import Mock alias Accent.Hook.Outbounds.Discord alias Accent.Integration alias Accent.Project - alias Accent.Repo alias Accent.User setup do - project = Repo.insert!(%Project{main_color: "#f00", name: "Test"}) - user = Repo.insert!(%User{fullname: "Test", email: "foo@test.com"}) + project = Factory.insert(Project) + user = Factory.insert(User, fullname: "Test", email: "foo@test.com") - Repo.insert!(%Integration{ - project: project, - user: user, + Factory.insert(Integration, + project_id: project.id, + user_id: user.id, service: "discord", events: ["sync"], data: %{url: "http://example.com"} - }) + ) [project: project, user: user] end diff --git a/test/hook/outbounds/email_test.exs b/test/hook/outbounds/email_test.exs index b6e954ef7..677095554 100644 --- a/test/hook/outbounds/email_test.exs +++ b/test/hook/outbounds/email_test.exs @@ -17,20 +17,20 @@ defmodule AccentTest.Hook.Outbounds.Email do alias Accent.User setup do - language = Repo.insert!(%Language{name: "Test"}) - project = Repo.insert!(%Project{main_color: "#f00", name: "Test"}) - user = Repo.insert!(%User{fullname: "Test", email: "foo@test.com"}) - revision = Repo.insert!(%Revision{project_id: project.id, language_id: language.id, master: true}) + language = Factory.insert(Language, name: "Test") + project = Factory.insert(Project) + user = Factory.insert(User, fullname: "Test", email: "foo@test.com") + revision = Factory.insert(Revision, project_id: project.id, language_id: language.id, master: true) translation = - Repo.insert!(%Translation{key: "foo", corrected_text: "bar", proposed_text: "bar", revision_id: revision.id}) + Factory.insert(Translation, key: "foo", corrected_text: "bar", proposed_text: "bar", revision_id: revision.id) [project: project, translation: translation, user: user] end test "commenter subscribed", %{project: project, translation: translation, user: user} do - Repo.insert!(%TranslationCommentsSubscription{translation_id: translation.id, user_id: user.id}) - comment = Repo.insert!(%Comment{translation_id: translation.id, user_id: user.id, text: "This is a comment"}) + Factory.insert(TranslationCommentsSubscription, translation_id: translation.id, user_id: user.id) + comment = Factory.insert(Comment, translation_id: translation.id, user_id: user.id, text: "This is a comment") comment = Repo.preload(comment, [:user, translation: [revision: :project]]) payload = %{ @@ -52,9 +52,9 @@ defmodule AccentTest.Hook.Outbounds.Email do end test "comment", %{project: project, translation: translation, user: user} do - Repo.insert!(%TranslationCommentsSubscription{translation_id: translation.id, user_id: user.id}) - commenter = Repo.insert!(%User{fullname: "Commenter", email: "comment@test.com"}) - comment = Repo.insert!(%Comment{translation_id: translation.id, user_id: commenter.id, text: "This is a comment"}) + Factory.insert(TranslationCommentsSubscription, translation_id: translation.id, user_id: user.id) + commenter = Factory.insert(User, fullname: "Commenter", email: "comment@test.com") + comment = Factory.insert(Comment, translation_id: translation.id, user_id: commenter.id, text: "This is a comment") payload = %{ "text" => comment.text, @@ -75,7 +75,7 @@ defmodule AccentTest.Hook.Outbounds.Email do end test "collaborator", %{project: project, user: user} do - collaborator = Repo.insert!(%Collaborator{email: "collab@test.com", project_id: project.id}) + collaborator = Factory.insert(Collaborator, email: "collab@test.com", project_id: project.id) payload = %{ "collaborator" => %{ diff --git a/test/hook/outbounds/slack_test.exs b/test/hook/outbounds/slack_test.exs index 902d45df3..e29884b68 100644 --- a/test/hook/outbounds/slack_test.exs +++ b/test/hook/outbounds/slack_test.exs @@ -7,27 +7,26 @@ end defmodule AccentTest.Hook.Outbounds.Slack do @moduledoc false - use Accent.RepoCase, async: true + use Accent.RepoCase, async: false import Mock alias Accent.Hook.Outbounds.Slack alias Accent.Integration alias Accent.Project - alias Accent.Repo alias Accent.User setup do - project = Repo.insert!(%Project{main_color: "#f00", name: "Test"}) - user = Repo.insert!(%User{fullname: "Test", email: "foo@test.com"}) + project = Factory.insert(Project) + user = Factory.insert(User, fullname: "Test", email: "foo@test.com") - Repo.insert!(%Integration{ - project: project, - user: user, + Factory.insert(Integration, + project_id: project.id, + user_id: user.id, service: "slack", events: ["sync"], data: %{url: "http://example.com"} - }) + ) [project: project, user: user] end diff --git a/test/hook/outbounds/websocket_test.exs b/test/hook/outbounds/websocket_test.exs index 03faf3fa6..de7f09e15 100644 --- a/test/hook/outbounds/websocket_test.exs +++ b/test/hook/outbounds/websocket_test.exs @@ -15,13 +15,13 @@ defmodule AccentTest.Hook.Outbounds.Websocket do alias Accent.UserSocket setup do - language = Repo.insert!(%Language{name: "Test"}) - project = Repo.insert!(%Project{main_color: "#f00", name: "Test"}) - user = Repo.insert!(%User{fullname: "Test", email: "foo@test.com", permissions: %{project.id => "admin"}}) - revision = Repo.insert!(%Revision{project_id: project.id, language_id: language.id, master: true}) + language = Factory.insert(Language, name: "Test") + project = Factory.insert(Project) + user = Factory.insert(User, fullname: "Test", email: "foo@test.com", permissions: %{project.id => "admin"}) + revision = Factory.insert(Revision, project_id: project.id, language_id: language.id, master: true) translation = - Repo.insert!(%Translation{key: "foo", corrected_text: "bar", proposed_text: "bar", revision_id: revision.id}) + Factory.insert(Translation, key: "foo", corrected_text: "bar", proposed_text: "bar", revision_id: revision.id) {:ok, _, socket} = UserSocket @@ -32,8 +32,8 @@ defmodule AccentTest.Hook.Outbounds.Websocket do end test "comment", %{project: project, translation: translation, user: user} do - commenter = Repo.insert!(%User{fullname: "Commenter", email: "comment@test.com"}) - comment = Repo.insert!(%Comment{translation_id: translation.id, user_id: commenter.id, text: "This is a comment"}) + commenter = Factory.insert(User, fullname: "Commenter", email: "comment@test.com") + comment = Factory.insert(Comment, translation_id: translation.id, user_id: commenter.id, text: "This is a comment") comment = Repo.preload(comment, [:user, translation: [revision: :project]]) payload = %{ @@ -91,7 +91,7 @@ defmodule AccentTest.Hook.Outbounds.Websocket do end test "collaborator", %{project: project, user: user} do - collaborator = Repo.insert!(%Collaborator{email: "collab@test.com", project_id: project.id}) + collaborator = Factory.insert(Collaborator, email: "collab@test.com", project_id: project.id) payload = %{ "collaborator" => %{ diff --git a/test/langue/json/exceptions_test.exs b/test/langue/json/exceptions_test.exs index 2a18b2006..23920be6e 100644 --- a/test/langue/json/exceptions_test.exs +++ b/test/langue/json/exceptions_test.exs @@ -2,20 +2,28 @@ defmodule LangueTest.Formatter.Json.Exception do @moduledoc false use ExUnit.Case, async: true + alias Accent.FormatterTestHelper alias Langue.Formatter.Json + alias LangueTest.Formatter.Json.Expectation.DuplicateKey alias LangueTest.Formatter.Json.Expectation.InvalidFloatValue alias LangueTest.Formatter.Json.Expectation.InvalidIntegerValue Code.require_file("expectation_test.exs", __DIR__) test "invalid integer value" do - {expected_parse, result_parse} = Accent.FormatterTestHelper.test_serialize(InvalidIntegerValue, Json) + {expected_parse, result_parse} = FormatterTestHelper.test_serialize(InvalidIntegerValue, Json) assert expected_parse == result_parse end test "invalid float value" do - {expected_parse, result_parse} = Accent.FormatterTestHelper.test_serialize(InvalidFloatValue, Json) + {expected_parse, result_parse} = FormatterTestHelper.test_serialize(InvalidFloatValue, Json) + + assert expected_parse == result_parse + end + + test "duplicate key" do + {expected_parse, result_parse} = FormatterTestHelper.test_parse(DuplicateKey, Json) assert expected_parse == result_parse end diff --git a/test/langue/json/expectation_test.exs b/test/langue/json/expectation_test.exs index 5d039246e..d2a4e3cfa 100644 --- a/test/langue/json/expectation_test.exs +++ b/test/langue/json/expectation_test.exs @@ -126,6 +126,27 @@ defmodule LangueTest.Formatter.Json.Expectation do end end + defmodule DuplicateKey do + @moduledoc false + use Langue.Expectation.Case + + def render do + """ + { + "test": "foo", + "test": "bar", + "test": "baz" + } + """ + end + + def entries do + [ + %Entry{index: 1, key: "test", value: "foo", value_type: "string"} + ] + end + end + defmodule InvalidFloatValue do @moduledoc false use Langue.Expectation.Case diff --git a/test/machine_translations/machine_translations_test.exs b/test/machine_translations/machine_translations_test.exs index 059a84669..86ee22d19 100644 --- a/test/machine_translations/machine_translations_test.exs +++ b/test/machine_translations/machine_translations_test.exs @@ -12,7 +12,7 @@ defmodule AccentTest.MachineTranslations do %{body: body, url: "https://translation.googleapis.com/v3/projects/1234/:translateText"} -> assert Jason.decode!(body) === %{ "contents" => ["Test"], - "mimeType" => "text/html", + "mimeType" => "text/plain", "sourceLanguageCode" => "fr", "targetLanguageCode" => "en" } @@ -35,7 +35,7 @@ defmodule AccentTest.MachineTranslations do %{body: body, url: "https://translation.googleapis.com/v3/projects/1234/:translateText"} -> assert Jason.decode!(body) === %{ "contents" => [~s(Test %{placeholder} bla)], - "mimeType" => "text/html", + "mimeType" => "text/plain", "sourceLanguageCode" => "fr", "targetLanguageCode" => "en" } @@ -73,5 +73,52 @@ defmodule AccentTest.MachineTranslations do {:error, error} = MachineTranslations.translate(entries, source_language, target_language, config) assert error === "Something" end + + test "deepl" do + mock_global(fn + %{body: body, url: "https://api-free.deepl.com/v2/translate"} -> + assert Jason.decode!(body) === %{"source_lang" => "FR", "target_lang" => "EN", "text" => ["Test"]} + + %Tesla.Env{status: 200, body: %{"translations" => [%{"text" => "Translated"}]}} + end) + + entries = [%Langue.Entry{value: "Test", value_type: "string", key: "."}] + source_language = "fr" + target_language = "en" + provider_config = %{"key" => "test"} + config = %{"provider" => "deepl", "config" => provider_config} + + [entry] = MachineTranslations.translate(entries, source_language, target_language, config) + assert entry.value === "Translated" + end + + test "deepl error" do + mock_global(fn %{url: "https://api-free.deepl.com/v2/translate"} -> + %Tesla.Env{status: 400, body: "Something"} + end) + + entries = [%Langue.Entry{value: "Test", value_type: "string", key: "."}] + source_language = "fr" + target_language = "en" + provider_config = %{"key" => "test"} + config = %{"provider" => "deepl", "config" => provider_config} + + {:error, error} = MachineTranslations.translate(entries, source_language, target_language, config) + assert error === "Something" + end + + test "deepl detect source" do + mock_global(fn %{url: "https://api-free.deepl.com/v2/translate"} -> + %Tesla.Env{status: 400, body: "Something"} + end) + + entries = [%Langue.Entry{value: "Test", value_type: "string", key: "."}] + target_language = "en" + provider_config = %{"key" => "test"} + config = %{"provider" => "deepl", "config" => provider_config} + + {:error, error} = MachineTranslations.translate(entries, nil, target_language, config) + assert error === "Something" + end end end diff --git a/test/movement/builders/new_slave_test.exs b/test/movement/builders/new_slave_test.exs index a0af99af2..a3dea1695 100644 --- a/test/movement/builders/new_slave_test.exs +++ b/test/movement/builders/new_slave_test.exs @@ -12,24 +12,22 @@ defmodule AccentTest.Movement.Builders.NewSlave do alias Movement.Builders.NewSlave, as: NewSlaveBuilder alias Movement.Context - @user %User{email: "test@test.com"} - setup do - user = Repo.insert!(@user) - language = Repo.insert!(%Language{name: "English", slug: Ecto.UUID.generate()}) + user = Factory.insert(User) + language = Factory.insert(Language) {:ok, project} = ProjectCreator.create(params: %{main_color: "#f00", name: "My project", language_id: language.id}, user: user) revision = project |> Repo.preload(:revisions) |> Map.get(:revisions) |> hd() - document = Repo.insert!(%Document{project_id: project.id, path: "test", format: "json"}) + document = Factory.insert(Document, project_id: project.id, path: "test", format: "json") {:ok, [revision: revision, document: document, project: project]} end test "builder fetch translations and process operations", %{revision: revision, project: project, document: document} do translation = - Repo.insert!(%Translation{ + Factory.insert(Translation, key: "a", proposed_text: "A", corrected_text: "A", @@ -37,7 +35,7 @@ defmodule AccentTest.Movement.Builders.NewSlave do file_comment: "comment", revision_id: revision.id, document_id: document.id - }) + ) context = %Context{} @@ -70,7 +68,7 @@ defmodule AccentTest.Movement.Builders.NewSlave do document: document } do translation = - Repo.insert!(%Translation{ + Factory.insert(Translation, key: "a", proposed_text: "A", corrected_text: "A", @@ -78,7 +76,7 @@ defmodule AccentTest.Movement.Builders.NewSlave do file_comment: "comment", revision_id: revision.id, document_id: document.id - }) + ) context = %Context{} @@ -95,7 +93,7 @@ defmodule AccentTest.Movement.Builders.NewSlave do test "with removed translation", %{revision: revision, project: project, document: document} do translation = - Repo.insert!(%Translation{ + Factory.insert(Translation, key: "a", proposed_text: "A", corrected_text: "A", @@ -103,8 +101,12 @@ defmodule AccentTest.Movement.Builders.NewSlave do file_comment: "comment", revision_id: revision.id, document_id: document.id, + conflicted: false, + conflicted_text: "", + value_type: "string", + translated: true, removed: true - }) + ) context = %Context{} @@ -133,6 +135,7 @@ defmodule AccentTest.Movement.Builders.NewSlave do previous_translation: %PreviousTranslation{ value_type: "string", removed: true, + translated: true, conflicted: false, conflicted_text: "", corrected_text: "A", diff --git a/test/movement/builders/new_version_test.exs b/test/movement/builders/new_version_test.exs index f74f2b0c4..fee275c69 100644 --- a/test/movement/builders/new_version_test.exs +++ b/test/movement/builders/new_version_test.exs @@ -11,24 +11,22 @@ defmodule AccentTest.Movement.Builders.NewVersion do alias Accent.Version alias Movement.Builders.NewVersion, as: NewVersionBuilder - @user %User{email: "test@test.com"} - setup do - user = Repo.insert!(@user) - language = Repo.insert!(%Language{name: "English", slug: Ecto.UUID.generate()}) + user = Factory.insert(User) + language = Factory.insert(Language) {:ok, project} = ProjectCreator.create(params: %{main_color: "#f00", name: "My project", language_id: language.id}, user: user) revision = project |> Repo.preload(:revisions) |> Map.get(:revisions) |> hd() - document = Repo.insert!(%Document{project_id: project.id, path: "test", format: "json"}) + document = Factory.insert(Document, project_id: project.id, path: "test", format: "json") {:ok, [revision: revision, document: document, project: project, user: user]} end test "builder fetch translations and process operations", %{revision: revision, project: project, document: document} do translation = - Repo.insert!(%Translation{ + Factory.insert(Translation, key: "a", proposed_text: "A", corrected_text: "A", @@ -38,7 +36,7 @@ defmodule AccentTest.Movement.Builders.NewVersion do locked: true, revision_id: revision.id, document_id: document.id - }) + ) context = %Movement.Context{} @@ -70,10 +68,10 @@ defmodule AccentTest.Movement.Builders.NewVersion do end test "builder with existing version", %{revision: revision, project: project, document: document, user: user} do - version = Repo.insert!(%Version{user_id: user.id, tag: "v3.2", name: "Release", project_id: project.id}) + version = Factory.insert(Version, user_id: user.id, tag: "v3.2", name: "Release", project_id: project.id) translation = - Repo.insert!(%Translation{ + Factory.insert(Translation, key: "a", proposed_text: "A", corrected_text: "A", @@ -81,9 +79,9 @@ defmodule AccentTest.Movement.Builders.NewVersion do file_comment: "comment", revision_id: revision.id, document_id: document.id - }) + ) - Repo.insert!(%Translation{ + Factory.insert(Translation, key: "a", proposed_text: "A", corrected_text: "A", @@ -93,7 +91,7 @@ defmodule AccentTest.Movement.Builders.NewVersion do version_id: version.id, document_id: document.id, source_translation_id: translation.id - }) + ) context = %Movement.Context{} diff --git a/test/movement/builders/project_sync_test.exs b/test/movement/builders/project_sync_test.exs index df1d2f493..ec0fecd23 100644 --- a/test/movement/builders/project_sync_test.exs +++ b/test/movement/builders/project_sync_test.exs @@ -12,19 +12,17 @@ defmodule AccentTest.Movement.Builders.ProjectSync do alias Movement.Builders.ProjectSync, as: ProjectSyncBuilder alias Movement.Context - @user %User{email: "test@test.com"} - setup do - user = Repo.insert!(@user) - language = Repo.insert!(%Language{name: "English", slug: Ecto.UUID.generate()}) - other_language = Repo.insert!(%Language{name: "French", slug: Ecto.UUID.generate()}) + user = Factory.insert(User) + language = Factory.insert(Language) + other_language = Factory.insert(Language) {:ok, project} = ProjectCreator.create(params: %{main_color: "#f00", name: "My project", language_id: language.id}, user: user) revision = project |> Repo.preload(:revisions) |> Map.get(:revisions) |> hd() - other_revision = Repo.insert!(%Revision{master: false, project_id: project.id, language_id: other_language.id}) - document = Repo.insert!(%Document{project_id: project.id, path: "test", format: "json"}) + other_revision = Factory.insert(Revision, master: false, project_id: project.id, language_id: other_language.id) + document = Factory.insert(Document, project_id: project.id, path: "test", format: "json") {:ok, [revision: revision, document: document, project: project, other_revision: other_revision]} end @@ -35,9 +33,9 @@ defmodule AccentTest.Movement.Builders.ProjectSync do project: project, other_revision: other_revision } do - Repo.insert!(%Translation{key: "a", proposed_text: "A", revision_id: revision.id, document_id: document.id}) - Repo.insert!(%Translation{key: "b", proposed_text: "B", revision_id: revision.id, document_id: document.id}) - Repo.insert!(%Translation{key: "a", proposed_text: "C", revision_id: other_revision.id, document_id: document.id}) + Factory.insert(Translation, key: "a", proposed_text: "A", revision_id: revision.id, document_id: document.id) + Factory.insert(Translation, key: "b", proposed_text: "B", revision_id: revision.id, document_id: document.id) + Factory.insert(Translation, key: "a", proposed_text: "C", revision_id: other_revision.id, document_id: document.id) entries = [%Langue.Entry{key: "a", value: "B", value_type: "string"}] context = diff --git a/test/movement/builders/revision_correct_all_test.exs b/test/movement/builders/revision_correct_all_test.exs index eb88940b4..a2437d488 100644 --- a/test/movement/builders/revision_correct_all_test.exs +++ b/test/movement/builders/revision_correct_all_test.exs @@ -9,11 +9,9 @@ defmodule AccentTest.Movement.Builders.RevisionCorrectAll do alias Accent.User alias Movement.Builders.RevisionCorrectAll, as: RevisionCorrectAllBuilder - @user %User{email: "test@test.com"} - setup do - user = Repo.insert!(@user) - language = Repo.insert!(%Language{name: "French", slug: Ecto.UUID.generate()}) + user = Factory.insert(User) + language = Factory.insert(Language) {:ok, project} = ProjectCreator.create(params: %{main_color: "#f00", name: "My project", language_id: language.id}, user: user) @@ -24,7 +22,7 @@ defmodule AccentTest.Movement.Builders.RevisionCorrectAll do end test "builder fetch translations and correct conflict", %{revision: revision} do - translation = Repo.insert!(%Translation{key: "a", proposed_text: "A", conflicted: true, revision_id: revision.id}) + translation = Factory.insert(Translation, key: "a", proposed_text: "A", conflicted: true, revision_id: revision.id) context = %Movement.Context{} @@ -39,7 +37,7 @@ defmodule AccentTest.Movement.Builders.RevisionCorrectAll do end test "builder fetch translations and ignore corrected translation", %{revision: revision} do - Repo.insert!(%Translation{key: "a", proposed_text: "A", conflicted: false, revision_id: revision.id}) + Factory.insert(Translation, key: "a", proposed_text: "A", conflicted: false, revision_id: revision.id) context = %Movement.Context{} diff --git a/test/movement/builders/revision_merge_test.exs b/test/movement/builders/revision_merge_test.exs index 82d6d9009..a7075bcb7 100644 --- a/test/movement/builders/revision_merge_test.exs +++ b/test/movement/builders/revision_merge_test.exs @@ -11,20 +11,18 @@ defmodule AccentTest.Movement.Builders.RevisionMerge do alias Movement.Builders.RevisionMerge, as: RevisionMergeBuilder alias Movement.Context - @user %User{email: "test@test.com"} - test "builder fetch translations and use comparer" do - user = Repo.insert!(@user) - language = Repo.insert!(%Language{name: "English", slug: Ecto.UUID.generate()}) + user = Factory.insert(User) + language = Factory.insert(Language) {:ok, project} = ProjectCreator.create(params: %{main_color: "#f00", name: "My project", language_id: language.id}, user: user) revision = project |> Repo.preload(revisions: [:language]) |> Map.get(:revisions) |> hd() - document = Repo.insert!(%Document{project_id: project.id, path: "test", format: "json"}) + document = Factory.insert(Document, project_id: project.id, path: "test", format: "json") translation = - Repo.insert!(%Translation{key: "a", proposed_text: "A", revision_id: revision.id, document_id: document.id}) + Factory.insert(Translation, key: "a", proposed_text: "A", revision_id: revision.id, document_id: document.id) entries = [%Langue.Entry{key: "a", value: "B", value_type: "string"}] diff --git a/test/movement/builders/revision_sync_test.exs b/test/movement/builders/revision_sync_test.exs index 440668ddc..d6e2bd4b1 100644 --- a/test/movement/builders/revision_sync_test.exs +++ b/test/movement/builders/revision_sync_test.exs @@ -11,24 +11,22 @@ defmodule AccentTest.Movement.Builders.RevisionSync do alias Movement.Builders.RevisionSync, as: RevisionSyncBuilder alias Movement.Context - @user %User{email: "test@test.com"} - setup do - user = Repo.insert!(@user) - language = Repo.insert!(%Language{name: "English", slug: Ecto.UUID.generate()}) + user = Factory.insert(User) + language = Factory.insert(Language) {:ok, project} = ProjectCreator.create(params: %{main_color: "#f00", name: "My project", language_id: language.id}, user: user) revision = project |> Repo.preload(:revisions) |> Map.get(:revisions) |> hd() - document = Repo.insert!(%Document{project_id: project.id, path: "test", format: "json"}) + document = Factory.insert(Document, project_id: project.id, path: "test", format: "json") {:ok, [revision: revision, document: document]} end test "builder fetch translations and use comparer", %{revision: revision, document: document} do translation = - Repo.insert!(%Translation{key: "a", proposed_text: "A", revision_id: revision.id, document_id: document.id}) + Factory.insert(Translation, key: "a", proposed_text: "A", revision_id: revision.id, document_id: document.id) entries = [%Langue.Entry{key: "a", value: "B", value_type: "string"}] @@ -48,7 +46,7 @@ defmodule AccentTest.Movement.Builders.RevisionSync do test "builder fetch translations and process to remove with empty entries", %{revision: revision, document: document} do translation = - Repo.insert!(%Translation{key: "a", proposed_text: "A", revision_id: revision.id, document_id: document.id}) + Factory.insert(Translation, key: "a", proposed_text: "A", revision_id: revision.id, document_id: document.id) context = %Context{entries: []} @@ -66,13 +64,13 @@ defmodule AccentTest.Movement.Builders.RevisionSync do test "builder fetch translations and process to renew with entries", %{revision: revision, document: document} do translation = - Repo.insert!(%Translation{ + Factory.insert(Translation, key: "a", proposed_text: "A", revision_id: revision.id, document_id: document.id, removed: true - }) + ) entries = [%Langue.Entry{key: "a", value: "B", value_type: "string"}] diff --git a/test/movement/builders/revision_uncorrect_all_test.exs b/test/movement/builders/revision_uncorrect_all_test.exs index aad9767f0..851c52ba3 100644 --- a/test/movement/builders/revision_uncorrect_all_test.exs +++ b/test/movement/builders/revision_uncorrect_all_test.exs @@ -9,11 +9,9 @@ defmodule AccentTest.Movement.Builders.RevisionUncorrectAll do alias Accent.User alias Movement.Builders.RevisionUncorrectAll, as: RevisionUncorrectAllBuilder - @user %User{email: "test@test.com"} - setup do - user = Repo.insert!(@user) - language = Repo.insert!(%Language{name: "English", slug: Ecto.UUID.generate()}) + user = Factory.insert(User) + language = Factory.insert(Language) {:ok, project} = ProjectCreator.create(params: %{main_color: "#f00", name: "My project", language_id: language.id}, user: user) @@ -24,7 +22,7 @@ defmodule AccentTest.Movement.Builders.RevisionUncorrectAll do end test "builder fetch translations and uncorrect conflict", %{revision: revision} do - translation = Repo.insert!(%Translation{key: "a", proposed_text: "A", conflicted: false, revision_id: revision.id}) + translation = Factory.insert(Translation, key: "a", proposed_text: "A", conflicted: false, revision_id: revision.id) context = %Movement.Context{} @@ -39,7 +37,7 @@ defmodule AccentTest.Movement.Builders.RevisionUncorrectAll do end test "builder fetch translations and ignore conflicted translation", %{revision: revision} do - Repo.insert!(%Translation{key: "a", proposed_text: "A", conflicted: true, revision_id: revision.id}) + Factory.insert(Translation, key: "a", proposed_text: "A", conflicted: true, revision_id: revision.id) context = %Movement.Context{} diff --git a/test/movement/builders/rollback_test.exs b/test/movement/builders/rollback_test.exs index 6e1541aad..fa9a6ee2d 100644 --- a/test/movement/builders/rollback_test.exs +++ b/test/movement/builders/rollback_test.exs @@ -12,23 +12,21 @@ defmodule AccentTest.Movement.Builders.Rollback do alias Accent.User alias Movement.Builders.Rollback, as: RollbackBuilder - @user %User{email: "test@test.com"} - setup do - user = Repo.insert!(@user) - language = Repo.insert!(%Language{name: "English", slug: Ecto.UUID.generate()}) + user = Factory.insert(User) + language = Factory.insert(Language) {:ok, project} = ProjectCreator.create(params: %{main_color: "#f00", name: "My project", language_id: language.id}, user: user) revision = project |> Repo.preload(:revisions) |> Map.get(:revisions) |> hd() - document = Repo.insert!(%Document{project_id: project.id, path: "test", format: "json"}) + document = Factory.insert(Document, project_id: project.id, path: "test", format: "json") {:ok, [revision: revision, document: document, project: project]} end test "builder process operations for batch", %{project: project} do - operation = Repo.insert!(%Operation{project_id: project.id, batch: true, action: "sync"}) + operation = Factory.insert(Operation, project_id: project.id, batch: true, action: "sync") context = %Movement.Context{} @@ -43,16 +41,17 @@ defmodule AccentTest.Movement.Builders.Rollback do test "builder process operations for translation", %{project: project, revision: revision, document: document} do translation = - Repo.insert!(%Translation{ + Factory.insert(Translation, key: "A", proposed_text: "TEXT", conflicted_text: "Ex-TEXT", corrected_text: "LOL", + translated: true, removed: false, revision_id: revision.id, value_type: "string", placeholders: [] - }) + ) operation = %Operation{ @@ -88,6 +87,7 @@ defmodule AccentTest.Movement.Builders.Rollback do conflicted_text: translation.conflicted_text, conflicted: translation.conflicted, removed: translation.removed, + translated: translation.translated, placeholders: translation.placeholders } end diff --git a/test/movement/builders/slave_conflict_sync_test.exs b/test/movement/builders/slave_conflict_sync_test.exs index b060c4d65..41120d4de 100644 --- a/test/movement/builders/slave_conflict_sync_test.exs +++ b/test/movement/builders/slave_conflict_sync_test.exs @@ -12,19 +12,17 @@ defmodule AccentTest.Movement.Builders.SlaveConflictSync do alias Movement.Builders.SlaveConflictSync, as: SlaveConflictSyncBuilder alias Movement.Context - @user %User{email: "test@test.com"} - setup do - user = Repo.insert!(@user) - language = Repo.insert!(%Language{name: "English", slug: Ecto.UUID.generate()}) - other_language = Repo.insert!(%Language{name: "French", slug: Ecto.UUID.generate()}) + user = Factory.insert(User) + language = Factory.insert(Language) + other_language = Factory.insert(Language) {:ok, project} = ProjectCreator.create(params: %{main_color: "#f00", name: "My project", language_id: language.id}, user: user) revision = project |> Repo.preload(:revisions) |> Map.get(:revisions) |> hd() - other_revision = Repo.insert!(%Revision{project_id: project.id, language_id: other_language.id}) - document = Repo.insert!(%Document{project_id: project.id, path: "test", format: "json"}) + other_revision = Factory.insert(Revision, project_id: project.id, language_id: other_language.id) + document = Factory.insert(Document, project_id: project.id, path: "test", format: "json") {:ok, [project: project, revision: revision, document: document, other_revision: other_revision]} end @@ -35,10 +33,15 @@ defmodule AccentTest.Movement.Builders.SlaveConflictSync do other_revision: other_revision } do translation = - Repo.insert!(%Translation{key: "a", proposed_text: "A", revision_id: revision.id, document_id: document.id}) + Factory.insert(Translation, key: "a", proposed_text: "A", revision_id: revision.id, document_id: document.id) other_translation = - Repo.insert!(%Translation{key: "a", proposed_text: "C", revision_id: other_revision.id, document_id: document.id}) + Factory.insert(Translation, + key: "a", + proposed_text: "C", + revision_id: other_revision.id, + document_id: document.id + ) context = %Context{operations: [%{key: "a", action: "conflict_on_proposed"}]} @@ -60,18 +63,18 @@ defmodule AccentTest.Movement.Builders.SlaveConflictSync do document: document, other_revision: other_revision } do - other_document = Repo.insert!(%Document{project_id: project.id, path: "other", format: "json"}) + other_document = Factory.insert(Document, project_id: project.id, path: "other", format: "json") translation = - Repo.insert!(%Translation{key: "a", proposed_text: "A", revision_id: revision.id, document_id: document.id}) + Factory.insert(Translation, key: "a", proposed_text: "A", revision_id: revision.id, document_id: document.id) other_translation = - Repo.insert!(%Translation{ + Factory.insert(Translation, key: "a", proposed_text: "C", revision_id: other_revision.id, document_id: other_document.id - }) + ) context = %Context{operations: [%{key: "a", action: "conflict_on_proposed"}]} diff --git a/test/movement/builders/translation_update_test.exs b/test/movement/builders/translation_update_test.exs index 70c44e155..4cb7eec3e 100644 --- a/test/movement/builders/translation_update_test.exs +++ b/test/movement/builders/translation_update_test.exs @@ -2,7 +2,12 @@ defmodule AccentTest.Movement.Builders.TranslationUpdate do @moduledoc false use Accent.RepoCase, async: true + alias Accent.Language + alias Accent.ProjectCreator + alias Accent.Repo alias Accent.Translation + alias Accent.User + alias Accent.Version alias Movement.Builders.TranslationUpdate, as: TranslationUpdateBuilder alias Movement.Context @@ -30,6 +35,67 @@ defmodule AccentTest.Movement.Builders.TranslationUpdate do ] end + test "builder copy on latest version" do + user = Factory.insert(User, email: "test@test.com") + language = Factory.insert(Language) + + {:ok, project} = + ProjectCreator.create(params: %{main_color: "#f00", name: "My project", language_id: language.id}, user: user) + + revision = Repo.one!(Ecto.assoc(project, :revisions)) + + version = + Factory.insert(Version, + name: "1", + tag: "v1", + project_id: project.id, + user_id: user.id, + copy_on_update_translation: true + ) + + source_translation = + Factory.insert(Translation, + key: "a", + proposed_text: "A", + corrected_text: "A", + revision_id: revision.id, + version_id: nil + ) + + translation = + Factory.insert(Translation, + key: "a", + proposed_text: "A", + corrected_text: "A", + version_id: version.id, + revision_id: revision.id, + source_translation_id: source_translation.id + ) + + context = + %Context{} + |> Context.assign(:text, "Updated!") + |> Context.assign(:translation, translation) + |> TranslationUpdateBuilder.build() + + operations = Enum.map(context.operations, &Map.take(&1, [:key, :text, :action, :translation_id])) + + assert operations === [ + %{ + translation_id: translation.id, + key: "a", + text: "Updated!", + action: "update" + }, + %{ + translation_id: source_translation.id, + key: "a", + text: "Updated!", + action: "update" + } + ] + end + test "builder same text translated" do translation = %Translation{ key: "a", diff --git a/test/movement/down_test.exs b/test/movement/down_test.exs index 4165527d0..f52d90134 100644 --- a/test/movement/down_test.exs +++ b/test/movement/down_test.exs @@ -25,21 +25,21 @@ defmodule AccentTest.Migrator.Down do } translation = - Repo.insert!(%Translation{ + Factory.insert(Translation, key: "to_be_in_conflict", - revision: Repo.insert!(%Revision{}), + revision: Factory.insert(Revision), corrected_text: nil, proposed_text: "new proposed text", conflicted_text: "corrected_text", conflicted: true - }) + ) Migrator.down( - Repo.insert!(%Operation{ + Factory.insert(Operation, action: "conflict_on_corrected", translation: translation, previous_translation: PreviousTranslation.from_translation(previous_translation) - }) + ) ) new_translation = Repo.get!(Translation, translation.id) @@ -62,21 +62,21 @@ defmodule AccentTest.Migrator.Down do } translation = - Repo.insert!(%Translation{ + Factory.insert(Translation, key: "to_be_in_proposed", - revision: Repo.insert!(%Revision{}), + revision: Factory.insert(Revision), corrected_text: nil, proposed_text: "new proposed text", conflicted_text: "proposed_text", conflicted: true - }) + ) Migrator.down( - Repo.insert!(%Operation{ + Factory.insert(Operation, action: "conflict_on_proposed", translation: translation, previous_translation: PreviousTranslation.from_translation(previous_translation) - }) + ) ) new_translation = Repo.get!(Translation, translation.id) @@ -89,16 +89,16 @@ defmodule AccentTest.Migrator.Down do test ":new" do translation = - Repo.insert!(%Translation{ + Factory.insert(Translation, key: "to_be_added_down", - revision: Repo.insert!(%Revision{}), + revision: Factory.insert(Revision), corrected_text: nil, proposed_text: "new text", conflicted_text: nil, conflicted: true - }) + ) - Migrator.down(Repo.insert!(%Operation{action: "new", translation: translation})) + Migrator.down(Factory.insert(Operation, action: "new", translation: translation)) new_translation = Repo.get!(Translation, translation.id) @@ -107,16 +107,16 @@ defmodule AccentTest.Migrator.Down do test ":renew" do translation = - Repo.insert!(%Translation{ + Factory.insert(Translation, key: "to_be_added_down", - revision: Repo.insert!(%Revision{}), + revision: Factory.insert(Revision), corrected_text: nil, proposed_text: "new text", conflicted_text: nil, conflicted: true - }) + ) - Migrator.down(Repo.insert!(%Operation{action: "renew", translation: translation})) + Migrator.down(Factory.insert(Operation, action: "renew", translation: translation)) new_translation = Repo.get!(Translation, translation.id) @@ -125,18 +125,18 @@ defmodule AccentTest.Migrator.Down do test ":remove" do translation = - Repo.insert!(%Translation{ + Factory.insert(Translation, value_type: "", - revision: Repo.insert!(%Revision{}), + revision: Factory.insert(Revision), key: "to_be_added_down", corrected_text: nil, proposed_text: "new text", conflicted_text: nil, conflicted: true, placeholders: [] - }) + ) - Migrator.down(Repo.insert!(%Operation{action: "remove", translation: translation})) + Migrator.down(Factory.insert(Operation, action: "remove", translation: translation)) new_translation = Repo.get!(Translation, translation.id) diff --git a/test/movement/persisters/base_test.exs b/test/movement/persisters/base_test.exs index d7c523b4e..02d9c7add 100644 --- a/test/movement/persisters/base_test.exs +++ b/test/movement/persisters/base_test.exs @@ -15,8 +15,8 @@ defmodule AccentTest.Movement.Persisters.Base do alias Movement.Persisters.Base, as: BasePersister test "don’t overwrite revision" do - revision = Repo.insert!(%Revision{}) - revision_two = Repo.insert!(%Revision{}) + revision = Factory.insert(Revision) + revision_two = Factory.insert(Revision) translation = %Translation{ key: "a", @@ -55,10 +55,10 @@ defmodule AccentTest.Movement.Persisters.Base do end test "persist and execute operations" do - user = Repo.insert!(%User{email: "test@test.com"}) - revision = Repo.insert!(%Revision{}) + user = Factory.insert(User, email: "test@test.com") + revision = Factory.insert(Revision) - translation = Repo.insert!(%Translation{key: "a", proposed_text: "A", conflicted: true, revision_id: revision.id}) + translation = Factory.insert(Translation, key: "a", proposed_text: "A", conflicted: true, revision_id: revision.id) operations = [ %Movement.Operation{ @@ -92,10 +92,16 @@ defmodule AccentTest.Movement.Persisters.Base do end test "new operation with removed translation" do - revision = Repo.insert!(%Revision{}) + revision = Factory.insert(Revision) translation = - Repo.insert!(%Translation{key: "a", proposed_text: "A", conflicted: true, removed: true, revision_id: revision.id}) + Factory.insert(Translation, + key: "a", + proposed_text: "A", + conflicted: true, + removed: true, + revision_id: revision.id + ) operations = [ %Movement.Operation{ @@ -120,10 +126,16 @@ defmodule AccentTest.Movement.Persisters.Base do end test "version operation with source translation" do - revision = Repo.insert!(%Revision{}) + revision = Factory.insert(Revision) translation = - Repo.insert!(%Translation{key: "a", revision_id: revision.id, proposed_text: "A", conflicted: true, removed: true}) + Factory.insert(Translation, + key: "a", + revision_id: revision.id, + proposed_text: "A", + conflicted: true, + removed: true + ) operations = [ %Movement.Operation{ @@ -146,10 +158,16 @@ defmodule AccentTest.Movement.Persisters.Base do end test "version operation add operation on source translation" do - revision = Repo.insert!(%Revision{}) + revision = Factory.insert(Revision) translation = - Repo.insert!(%Translation{key: "a", revision_id: revision.id, proposed_text: "A", conflicted: true, removed: true}) + Factory.insert(Translation, + key: "a", + revision_id: revision.id, + proposed_text: "A", + conflicted: true, + removed: true + ) operations = [ %Movement.Operation{ @@ -177,20 +195,20 @@ defmodule AccentTest.Movement.Persisters.Base do end test "update operation add operation on version source translation" do - user = Repo.insert!(%User{email: "user@example.com"}) - project = Repo.insert!(%Project{main_color: "#f00", name: "project"}) - revision = Repo.insert!(%Revision{project_id: project.id}) - version = Repo.insert!(%Version{name: "foo", tag: "0.1", project: project, user: user}) + user = Factory.insert(User, email: "user@example.com") + project = Factory.insert(Project, main_color: "#f00", name: "project") + revision = Factory.insert(Revision, project_id: project.id) + version = Factory.insert(Version, name: "foo", tag: "0.1", project: project, user: user) translation = - Repo.insert!(%Translation{ + Factory.insert(Translation, key: "a", revision_id: revision.id, proposed_text: "A", conflicted: true, removed: true, version: version - }) + ) operations = [ %Movement.Operation{ diff --git a/test/movement/persisters/new_slave_test.exs b/test/movement/persisters/new_slave_test.exs index 47329bda9..dcdc4fadf 100644 --- a/test/movement/persisters/new_slave_test.exs +++ b/test/movement/persisters/new_slave_test.exs @@ -8,11 +8,9 @@ defmodule AccentTest.Movement.Persisters.NewSlave do alias Accent.User alias Movement.Persisters.NewSlave, as: NewSlavePersister - @user %User{email: "test@test.com"} - setup do - user = Repo.insert!(@user) - language = Repo.insert!(%Language{name: "English", slug: Ecto.UUID.generate()}) + user = Factory.insert(User) + language = Factory.insert(Language) {:ok, project} = ProjectCreator.create(params: %{main_color: "#f00", name: "My project", language_id: language.id}, user: user) @@ -23,7 +21,7 @@ defmodule AccentTest.Movement.Persisters.NewSlave do end test "create revision success", %{project: project, revision: master_revision} do - new_language = Repo.insert!(%Language{name: "French", slug: Ecto.UUID.generate()}) + new_language = Factory.insert(Language) {:ok, {context, _}} = NewSlavePersister.persist(%Movement.Context{ diff --git a/test/movement/persisters/new_version_test.exs b/test/movement/persisters/new_version_test.exs index 66ebd8fd3..d4c4999d9 100644 --- a/test/movement/persisters/new_version_test.exs +++ b/test/movement/persisters/new_version_test.exs @@ -15,11 +15,9 @@ defmodule AccentTest.Movement.Persisters.NewVersion do alias Movement.Context alias Movement.Persisters.NewVersion, as: NewVersionPersister - @user %User{email: "test@test.com"} - setup do - user = Repo.insert!(@user) - language = Repo.insert!(%Language{name: "English", slug: Ecto.UUID.generate()}) + user = Factory.insert(User) + language = Factory.insert(Language) {:ok, project} = ProjectCreator.create( @@ -28,7 +26,7 @@ defmodule AccentTest.Movement.Persisters.NewVersion do ) revision = project |> Repo.preload(:revisions) |> Map.get(:revisions) |> hd() - document = Repo.insert!(%Document{project_id: project.id, path: "test", format: "json"}) + document = Factory.insert(Document, project_id: project.id, path: "test", format: "json") {:ok, [revision: revision, document: document, project: project, user: user]} end @@ -40,7 +38,7 @@ defmodule AccentTest.Movement.Persisters.NewVersion do document: document } do translation = - Repo.insert!(%Translation{ + Factory.insert(Translation, key: "a", proposed_text: "A", corrected_text: "A", @@ -51,7 +49,7 @@ defmodule AccentTest.Movement.Persisters.NewVersion do conflicted: true, revision_id: revision.id, document_id: document.id - }) + ) operations = [ %Movement.Operation{ diff --git a/test/movement/persisters/project_state_change_worker_test.exs b/test/movement/persisters/project_hook_worker_test.exs similarity index 72% rename from test/movement/persisters/project_state_change_worker_test.exs rename to test/movement/persisters/project_hook_worker_test.exs index f4f1a9772..03c08f21a 100644 --- a/test/movement/persisters/project_state_change_worker_test.exs +++ b/test/movement/persisters/project_hook_worker_test.exs @@ -1,4 +1,4 @@ -defmodule Movement.Persisters.ProjectStateChangeWorkerTest do +defmodule Movement.Persisters.ProjectHookWorkerTest do use Accent.RepoCase, async: true alias Accent.Document @@ -7,17 +7,17 @@ defmodule Movement.Persisters.ProjectStateChangeWorkerTest do alias Accent.Repo alias Accent.Translation alias Accent.User - alias Movement.Persisters.ProjectStateChangeWorker, as: Worker + alias Movement.Persisters.ProjectHookWorker, as: Worker setup do - user = Repo.insert!(%User{email: "test@test.com"}) - language = Repo.insert!(%Language{name: "English", slug: Ecto.UUID.generate()}) + user = Factory.insert(User, email: "test@test.com") + language = Factory.insert(Language) {:ok, project} = ProjectCreator.create(params: %{main_color: "#f00", name: "My project", language_id: language.id}, user: user) revision = project |> Repo.preload(:revisions) |> Map.get(:revisions) |> hd() - document = Repo.insert!(%Document{project_id: project.id, path: "test", format: "json"}) + document = Factory.insert(Document, project_id: project.id, path: "test", format: "json") {:ok, [revision: revision, document: document, project: project, user: user]} end @@ -26,11 +26,9 @@ defmodule Movement.Persisters.ProjectStateChangeWorkerTest do args = %{ "project_id" => project.id, "previous_project_state" => %{ - "project" => %{ - "translations_count" => 0, - "reviewed_count" => 0, - "conflicts_count" => 0 - } + "translations_count" => 0, + "reviewed_count" => 0, + "conflicts_count" => 0 } } @@ -40,24 +38,22 @@ defmodule Movement.Persisters.ProjectStateChangeWorkerTest do end test "new_conflicts", %{user: user, project: project, revision: revision, document: document} do - Repo.insert!(%Translation{ + Factory.insert(Translation, key: "a", proposed_text: "A", conflicted: true, corrected_text: "Test", revision_id: revision.id, document_id: document.id - }) + ) args = %{ "project_id" => project.id, "user_id" => user.id, "previous_project_state" => %{ - "project" => %{ - "translations_count" => 0, - "reviewed_count" => 0, - "conflicts_count" => 0 - } + "translations_count" => 0, + "reviewed_count" => 0, + "conflicts_count" => 0 } } @@ -79,24 +75,22 @@ defmodule Movement.Persisters.ProjectStateChangeWorkerTest do end test "complete_review", %{user: user, project: project, revision: revision, document: document} do - Repo.insert!(%Translation{ + Factory.insert(Translation, key: "a", proposed_text: "A", conflicted: false, corrected_text: "Test", revision_id: revision.id, document_id: document.id - }) + ) args = %{ "project_id" => project.id, "user_id" => user.id, "previous_project_state" => %{ - "project" => %{ - "translations_count" => 1, - "reviewed_count" => 0, - "conflicts_count" => 1 - } + "translations_count" => 1, + "reviewed_count" => 0, + "conflicts_count" => 1 } } diff --git a/test/movement/persisters/project_sync_test.exs b/test/movement/persisters/project_sync_test.exs index b4f8b9754..d023d5a52 100644 --- a/test/movement/persisters/project_sync_test.exs +++ b/test/movement/persisters/project_sync_test.exs @@ -14,24 +14,22 @@ defmodule AccentTest.Movement.Persisters.ProjectSync do alias Movement.Context alias Movement.Persisters.ProjectSync, as: ProjectSyncPersister - @user %User{email: "test@test.com"} - setup do - user = Repo.insert!(@user) - language = Repo.insert!(%Language{name: "English", slug: Ecto.UUID.generate()}) + user = Factory.insert(User) + language = Factory.insert(Language) {:ok, project} = ProjectCreator.create(params: %{main_color: "#f00", name: "My project", language_id: language.id}, user: user) revision = project |> Repo.preload(:revisions) |> Map.get(:revisions) |> hd() - document = Repo.insert!(%Document{project_id: project.id, path: "test", format: "json"}) + document = Factory.insert(Document, project_id: project.id, path: "test", format: "json") {:ok, [project: project, document: document, revision: revision, user: user]} end test "persist operations", %{project: project, revision: revision, document: document, user: user} do translation = - Repo.insert!(%Translation{key: "a", proposed_text: "A", revision_id: revision.id, document_id: document.id}) + Factory.insert(Translation, key: "a", proposed_text: "A", revision_id: revision.id, document_id: document.id) operations = [ %Movement.Operation{ diff --git a/test/movement/persisters/rollback_test.exs b/test/movement/persisters/rollback_test.exs index 18f2c4d76..7e0eb77eb 100644 --- a/test/movement/persisters/rollback_test.exs +++ b/test/movement/persisters/rollback_test.exs @@ -15,34 +15,32 @@ defmodule AccentTest.Movement.Persisters.Rollback do alias Movement.Context alias Movement.Persisters.Rollback, as: RollbackPersister - @user %User{email: "test@test.com"} - setup do - user = Repo.insert!(@user) - language = Repo.insert!(%Language{name: "English", slug: Ecto.UUID.generate()}) + user = Factory.insert(User) + language = Factory.insert(Language) {:ok, project} = ProjectCreator.create(params: %{main_color: "#f00", name: "My project", language_id: language.id}, user: user) revision = project |> Repo.preload(:revisions) |> Map.get(:revisions) |> hd() - document = Repo.insert!(%Document{project_id: project.id, path: "test", format: "json"}) + document = Factory.insert(Document, project_id: project.id, path: "test", format: "json") {:ok, [project: project, document: document, revision: revision, user: user]} end test "persist operations", %{project: project, revision: revision, document: document, user: user} do translation = - Repo.insert!(%Translation{ + Factory.insert(Translation, key: "a", proposed_text: "A", conflicted: false, corrected_text: "Test", revision_id: revision.id, document_id: document.id - }) + ) operation = - Repo.insert!(%Accent.Operation{ + Factory.insert(Operation, text: "B", inserted_at: DateTime.utc_now(), updated_at: DateTime.utc_now(), @@ -52,7 +50,7 @@ defmodule AccentTest.Movement.Persisters.Rollback do translation_id: translation.id, revision_id: translation.revision_id, project_id: project.id - }) + ) operations = [ %Movement.Operation{ @@ -97,26 +95,26 @@ defmodule AccentTest.Movement.Persisters.Rollback do test "rollback batch", %{revision: revision} do translation = - Repo.insert!(%Translation{ + Factory.insert(Translation, key: "a", corrected_text: "B", conflicted: true, revision_id: revision.id, revision: revision - }) + ) - Repo.insert!(%Operation{ + Factory.insert(Operation, action: "new", key: "a", text: "B", translation_id: translation.id, revision_id: revision.id - }) + ) - batch_operation = Repo.insert!(%Operation{action: "sync", batch: true, revision_id: revision.id}) + batch_operation = Factory.insert(Operation, action: "sync", batch: true, revision_id: revision.id) operation = - Repo.insert!(%Operation{ + Factory.insert(Operation, action: "update", key: "a", text: "UPDATED", @@ -124,7 +122,7 @@ defmodule AccentTest.Movement.Persisters.Rollback do translation_id: translation.id, revision_id: revision.id, batch_operation_id: batch_operation.id - }) + ) rollback_operation = %Movement.Operation{ action: "rollback", @@ -147,24 +145,24 @@ defmodule AccentTest.Movement.Persisters.Rollback do test "rollback rollback does nothing", %{revision: revision} do translation = - Repo.insert!(%Translation{ + Factory.insert(Translation, key: "a", corrected_text: "B", conflicted: true, revision_id: revision.id, revision: revision - }) + ) - Repo.insert!(%Operation{ + Factory.insert(Operation, action: "new", key: "a", text: "B", translation_id: translation.id, revision_id: revision.id - }) + ) operation = - Repo.insert!(%Operation{ + Factory.insert(Operation, action: "update", key: "a", text: "UPDATED", @@ -172,17 +170,17 @@ defmodule AccentTest.Movement.Persisters.Rollback do translation_id: translation.id, revision_id: revision.id, rollbacked: true - }) + ) rollback_operation = - Repo.insert!(%Operation{ + Factory.insert(Operation, action: "rollback", key: "a", previous_translation: PreviousTranslation.from_translation(translation), translation_id: translation.id, revision_id: revision.id, rollbacked_operation_id: operation.id - }) + ) rollback_rollback_operation = %Movement.Operation{ action: "rollback", diff --git a/test/movement/up_test.exs b/test/movement/up_test.exs index 0d306884b..7ae570965 100644 --- a/test/movement/up_test.exs +++ b/test/movement/up_test.exs @@ -15,13 +15,13 @@ defmodule AccentTest.Movement.Migrator.Up do end test ":correct" do - user = Repo.insert!(%User{}) - revision = Repo.insert!(%Revision{}) + user = Factory.insert(User) + revision = Factory.insert(Revision) translation = - Repo.insert!(%Translation{ + Factory.insert(Translation, key: "to_be_corrected", - revision: Repo.insert!(%Revision{}), + revision: Factory.insert(Revision), file_comment: "", corrected_text: nil, proposed_text: "proposed_text", @@ -29,7 +29,7 @@ defmodule AccentTest.Movement.Migrator.Up do conflicted: true, value_type: "string", removed: false - }) + ) Migrator.up(%Operation{ id: Ecto.UUID.generate(), @@ -51,13 +51,13 @@ defmodule AccentTest.Movement.Migrator.Up do end test ":merge_on_proposed_force" do - user = Repo.insert!(%User{}) - revision = Repo.insert!(%Revision{}) + user = Factory.insert(User) + revision = Factory.insert(Revision) translation = - Repo.insert!(%Translation{ + Factory.insert(Translation, key: "to_be_merged", - revision: Repo.insert!(%Revision{}), + revision: Factory.insert(Revision), file_comment: "", corrected_text: "corrected_text", proposed_text: "proposed_text", @@ -65,7 +65,7 @@ defmodule AccentTest.Movement.Migrator.Up do conflicted_text: nil, conflicted: true, removed: false - }) + ) Migrator.up(%Operation{ id: Ecto.UUID.generate(), @@ -86,19 +86,19 @@ defmodule AccentTest.Movement.Migrator.Up do end test ":merge_on_corrected" do - user = Repo.insert!(%User{}) - revision = Repo.insert!(%Revision{}) + user = Factory.insert(User) + revision = Factory.insert(Revision) translation = - Repo.insert!(%Translation{ + Factory.insert(Translation, key: "to_be_merged", - revision: Repo.insert!(%Revision{}), + revision: Factory.insert(Revision), corrected_text: "corrected_text", proposed_text: "proposed_text", conflicted_text: nil, value_type: "string", conflicted: true - }) + ) Migrator.up(%Operation{ action: "merge_on_corrected", @@ -118,9 +118,9 @@ defmodule AccentTest.Movement.Migrator.Up do test ":uncorrect" do translation = - Repo.insert!(%Translation{ + Factory.insert(Translation, key: "to_be_uncorrected", - revision: Repo.insert!(%Revision{}), + revision: Factory.insert(Revision), file_comment: "", file_index: 1, corrected_text: "new proposed text", @@ -129,7 +129,7 @@ defmodule AccentTest.Movement.Migrator.Up do conflicted: false, removed: false, value_type: "string" - }) + ) Migrator.up(%Operation{ action: "uncorrect_conflict", @@ -149,9 +149,9 @@ defmodule AccentTest.Movement.Migrator.Up do test ":uncorrect with same corrected and proposed" do translation = - Repo.insert!(%Translation{ + Factory.insert(Translation, key: "to_be_uncorrected", - revision: Repo.insert!(%Revision{}), + revision: Factory.insert(Revision), file_comment: "", file_index: 1, corrected_text: "proposed_text", @@ -161,7 +161,7 @@ defmodule AccentTest.Movement.Migrator.Up do conflicted: false, translated: true, removed: false - }) + ) Migrator.up(%Operation{ action: "uncorrect_conflict", @@ -181,16 +181,16 @@ defmodule AccentTest.Movement.Migrator.Up do test ":conflict_on_corrected" do translation = - Repo.insert!(%Translation{ + Factory.insert(Translation, key: "to_be_in_conflict", - revision: Repo.insert!(%Revision{}), + revision: Factory.insert(Revision), file_comment: "", file_index: 1, corrected_text: "corrected_text", proposed_text: "proposed_text", conflicted: false, removed: false - }) + ) Migrator.up(%Operation{ action: "conflict_on_corrected", @@ -210,16 +210,16 @@ defmodule AccentTest.Movement.Migrator.Up do test ":conflict_on_slave" do translation = - Repo.insert!(%Translation{ + Factory.insert(Translation, key: "to_be_in_conflict", - revision: Repo.insert!(%Revision{}), + revision: Factory.insert(Revision), file_comment: "", file_index: 1, corrected_text: "corrected_text", proposed_text: "proposed_text", conflicted: false, removed: false - }) + ) Migrator.up(%Operation{ action: "conflict_on_slave", @@ -238,14 +238,14 @@ defmodule AccentTest.Movement.Migrator.Up do test ":remove" do translation = - Repo.insert!(%Translation{ + Factory.insert(Translation, key: "to_be_removed", - revision: Repo.insert!(%Revision{}), + revision: Factory.insert(Revision), corrected_text: "corrected_text", proposed_text: "proposed_text", conflicted: false, removed: false - }) + ) Migrator.up(%Operation{ action: "remove", @@ -260,22 +260,23 @@ defmodule AccentTest.Movement.Migrator.Up do test ":renew" do translation = - Repo.insert!(%Translation{ + Factory.insert(Translation, key: "to_be_renewed", - revision: Repo.insert!(%Revision{}), + revision_id: Factory.insert(Revision).id, corrected_text: "corrected_text", proposed_text: "proposed_text", conflicted: false, removed: true - }) + ) operation = - Repo.insert!(%Operation{ + Factory.insert(Operation, action: "renew", - translation: translation, + translation_id: translation.id, previous_translation: PreviousTranslation.from_translation(translation) - }) + ) + operation = Repo.preload(operation, [:translation]) Migrator.up(operation) updated_translation = Repo.get(Translation, translation.id) @@ -285,21 +286,23 @@ defmodule AccentTest.Movement.Migrator.Up do test ":rollback" do translation = - Repo.insert!(%Translation{ + Factory.insert(Translation, key: "to_be_rollbacked", - revision: Repo.insert!(%Revision{}), + revision_id: Factory.insert(Revision).id, corrected_text: "corrected_text", proposed_text: "proposed_text", conflicted: false, removed: true - }) + ) operation = - Repo.insert!(%Operation{ + Factory.insert(Operation, action: "rollback", - translation: translation, + translation_id: translation.id, previous_translation: PreviousTranslation.from_translation(%{translation | corrected_text: "previous"}) - }) + ) + + operation = Repo.preload(operation, [:translation]) Migrator.up(operation) @@ -310,10 +313,10 @@ defmodule AccentTest.Movement.Migrator.Up do test ":conflict_on_proposed" do translation = - Repo.insert!(%Translation{ + Factory.insert(Translation, value_type: "", key: "to_be_conflict_on_proposed", - revision: Repo.insert!(%Revision{}), + revision: Factory.insert(Revision), file_comment: "", file_index: 1, corrected_text: "corrected_text", @@ -321,7 +324,7 @@ defmodule AccentTest.Movement.Migrator.Up do conflicted: true, removed: false, placeholders: [] - }) + ) Migrator.up(%Operation{ value_type: "", @@ -345,15 +348,15 @@ defmodule AccentTest.Movement.Migrator.Up do test ":updated_proposed" do translation = - Repo.insert!(%Translation{ + Factory.insert(Translation, key: "updated_proposed", - revision: Repo.insert!(%Revision{}), + revision: Factory.insert(Revision), corrected_text: "corrected_text", proposed_text: "proposed_text", conflicted_text: "conflict", conflicted: true, removed: false - }) + ) Migrator.up(%Operation{ action: "update_proposed", diff --git a/test/plugs/assign_current_user_test.exs b/test/plugs/assign_current_user_test.exs index 055964bac..88253d4ef 100644 --- a/test/plugs/assign_current_user_test.exs +++ b/test/plugs/assign_current_user_test.exs @@ -5,12 +5,8 @@ defmodule AccentTest.Plugs.AssignCurrentUser do alias Accent.AccessToken alias Accent.Plugs.AssignCurrentUser - alias Accent.Repo alias Accent.User - @user %User{email: "test@test.com"} - @token %AccessToken{revoked_at: nil, token: "1234"} - defp call_plug(token) do :get |> conn("/foo") @@ -20,11 +16,11 @@ defmodule AccentTest.Plugs.AssignCurrentUser do test "assign current_user" do user = - @user - |> Repo.insert!() + User + |> Factory.insert() |> Map.put(:permissions, %{}) - token = Repo.insert!(Map.put(@token, :user_id, user.id)) + token = Factory.insert(AccessToken, user_id: user.id) assigned_user = token.token diff --git a/test/plugs/movement_context_parser_test.exs b/test/plugs/movement_context_parser_test.exs index 0e44eacd9..b22efb3a5 100644 --- a/test/plugs/movement_context_parser_test.exs +++ b/test/plugs/movement_context_parser_test.exs @@ -30,16 +30,15 @@ defmodule AccentTest.Plugs.MovementContextParser do %Plug.Upload{content_type: "text/plain", filename: "unicode.strings", path: "test/support/invalid_unicode.strings"} end - @user %User{email: "test@test.com"} setup do - user = Repo.insert!(@user) - language = Repo.insert!(%Language{name: "English", slug: Ecto.UUID.generate()}) + user = Factory.insert(User) + language = Factory.insert(Language) {:ok, project} = ProjectCreator.create(params: %{main_color: "#f00", name: "My project", language_id: language.id}, user: user) revision = project |> Repo.preload(:revisions) |> Map.get(:revisions) |> hd() - document = Repo.insert!(%Document{project_id: project.id, path: "test", format: "json"}) + document = Factory.insert(Document, project_id: project.id, path: "test", format: "json") {:ok, [project: project, document: document, revision: revision, language: language, user: user]} end diff --git a/test/scopes/translation_test.exs b/test/scopes/translation_test.exs index b846b6837..36b29d6cf 100644 --- a/test/scopes/translation_test.exs +++ b/test/scopes/translation_test.exs @@ -5,21 +5,20 @@ defmodule AccentTest.Scopes.Translation do alias Accent.Document alias Accent.Operation alias Accent.Project - alias Accent.Repo alias Accent.Scopes.Translation, as: Scope alias Accent.Translation doctest Accent.Scopes.Translation setup do - project = Repo.insert!(%Project{main_color: "#f00", name: "My project"}) + project = Factory.insert(Project) {:ok, [project: project]} end describe "parse_added_last_sync/3" do test "existing sync", %{project: project} do - sync = Repo.insert!(%Operation{project: project, action: "sync"}) + sync = Factory.insert(Operation, project_id: project.id, action: "sync") query = Scope.parse_added_last_sync(Translation, true, project.id, nil) @@ -28,9 +27,9 @@ defmodule AccentTest.Scopes.Translation do end test "existing sync with document", %{project: project} do - document = Repo.insert!(%Document{project_id: project.id, path: "my-test", format: "xliff_1_2"}) - sync = Repo.insert!(%Operation{project: project, action: "sync", document: document}) - _other_sync = Repo.insert!(%Operation{project: project, action: "sync"}) + document = Factory.insert(Document, project_id: project.id, path: "my-test", format: "xliff_1_2") + sync = Factory.insert(Operation, project_id: project.id, action: "sync", document_id: document.id) + _other_sync = Factory.insert(Operation, project_id: project.id, action: "sync") query = Scope.parse_added_last_sync(Translation, true, project.id, document.id) @@ -39,9 +38,14 @@ defmodule AccentTest.Scopes.Translation do end test "many sync", %{project: project} do - _ = Repo.insert!(%Operation{project: project, action: "sync", inserted_at: ~U[2018-01-02T00:00:00.000000Z]}) - sync = Repo.insert!(%Operation{project: project, action: "sync", inserted_at: ~U[2018-01-03T00:00:00.000000Z]}) - _ = Repo.insert!(%Operation{project: project, action: "sync", inserted_at: ~U[2018-01-01T00:00:00.000000Z]}) + _ = + Factory.insert(Operation, project_id: project.id, action: "sync", inserted_at: ~U[2018-01-02T00:00:00.000000Z]) + + sync = + Factory.insert(Operation, project_id: project.id, action: "sync", inserted_at: ~U[2018-01-03T00:00:00.000000Z]) + + _ = + Factory.insert(Operation, project_id: project.id, action: "sync", inserted_at: ~U[2018-01-01T00:00:00.000000Z]) query = Scope.parse_added_last_sync(Translation, true, project.id, nil) diff --git a/test/scopes/version_test.exs b/test/scopes/version_test.exs index afc0ce451..7b8044034 100644 --- a/test/scopes/version_test.exs +++ b/test/scopes/version_test.exs @@ -16,12 +16,12 @@ defmodule AccentTest.Scopes.Version do end defp insert_version(tag, project, user) do - Repo.insert!(%Version{name: "foo", tag: tag, project_id: project.id, user_id: user.id}) + Factory.insert(Version, name: "foo", tag: tag, project_id: project.id, user_id: user.id) end setup do - user = Repo.insert!(%User{email: "test@test.com"}) - project = Repo.insert!(%Project{main_color: "#f00", name: "My project"}) + user = Factory.insert(User, email: "test@test.com") + project = Factory.insert(Project) {:ok, [user: user, project: project]} end diff --git a/test/services/collaborator_creator_test.exs b/test/services/collaborator_creator_test.exs index 2121782f0..f7528d3ab 100644 --- a/test/services/collaborator_creator_test.exs +++ b/test/services/collaborator_creator_test.exs @@ -5,58 +5,56 @@ defmodule AccentTest.CollaboratorCreator do alias Accent.Collaborator alias Accent.CollaboratorCreator alias Accent.Project - alias Accent.Repo alias Accent.User + @email Faker.Internet.email() + test "create unknown email" do - email = "test@test.com" - project = Repo.insert!(%Project{main_color: "#f00", name: "com"}) - assigner = Repo.insert!(%User{email: "lol@test.com"}) + project = Factory.insert(Project) + assigner = Factory.insert(User) role = "admin" {:ok, collaborator} = CollaboratorCreator.create(%{ - "email" => email, + "email" => @email, "assigner_id" => assigner.id, "role" => role, "project_id" => project.id }) - assert collaborator.email === email + assert collaborator.email === @email assert collaborator.assigner_id === assigner.id assert collaborator.role === role end test "create known email" do - email = "test@test.com" - project = Repo.insert!(%Project{main_color: "#f00", name: "com"}) - user = Repo.insert!(%User{email: email}) - assigner = Repo.insert!(%User{email: "lol@test.com"}) + project = Factory.insert(Project) + user = Factory.insert(User, email: @email) + assigner = Factory.insert(User) role = "admin" {:ok, collaborator} = CollaboratorCreator.create(%{ - "email" => email, + "email" => @email, "assigner_id" => assigner.id, "role" => role, "project_id" => project.id }) - assert collaborator.email === email + assert collaborator.email === @email assert collaborator.user_id === user.id assert collaborator.assigner_id === assigner.id assert collaborator.role === role end test "create invalid role" do - email = "test@test.com" - project = Repo.insert!(%Project{main_color: "#f00", name: "com"}) - assigner = Repo.insert!(%User{email: "lol@test.com"}) + project = Factory.insert(Project) + assigner = Factory.insert(User) role = "test123" {:error, collaborator} = CollaboratorCreator.create(%{ - "email" => email, + "email" => @email, "assigner_id" => assigner.id, "role" => role, "project_id" => project.id @@ -70,8 +68,8 @@ defmodule AccentTest.CollaboratorCreator do test "create with insensitive email" do email = "TEST@test.com" - project = Repo.insert!(%Project{main_color: "#f00", name: "com"}) - assigner = Repo.insert!(%User{email: "lol@test.com"}) + project = Factory.insert(Project) + assigner = Factory.insert(User) role = "admin" {:ok, collaborator} = @@ -86,32 +84,30 @@ defmodule AccentTest.CollaboratorCreator do end test "create with leading and trailing spaces in email" do - email = " test@test.com " - project = Repo.insert!(%Project{main_color: "#f00", name: "com"}) - assigner = Repo.insert!(%User{email: "lol@test.com"}) + project = Factory.insert(Project) + assigner = Factory.insert(User) role = "admin" {:ok, collaborator} = CollaboratorCreator.create(%{ - "email" => email, + "email" => " #{@email} ", "assigner_id" => assigner.id, "role" => role, "project_id" => project.id }) - assert collaborator.email === "test@test.com" + assert collaborator.email === @email end test "cannot create with already used email for project" do - email = "test@test.com" - project = Repo.insert!(%Project{main_color: "#f00", name: "com"}) - assigner = Repo.insert!(%User{email: "lol@test.com"}) + project = Factory.insert(Project) + assigner = Factory.insert(User) role = "admin" - Repo.insert!(%Collaborator{email: email, assigner_id: assigner.id, role: role, project_id: project.id}) + Factory.insert(Collaborator, email: @email, assigner_id: assigner.id, role: role, project_id: project.id) {:error, changeset} = CollaboratorCreator.create(%{ - "email" => email, + "email" => @email, "assigner_id" => assigner.id, "role" => role, "project_id" => project.id diff --git a/test/services/collaborator_normalizer_test.exs b/test/services/collaborator_normalizer_test.exs index 34a82707e..ad4bcba26 100644 --- a/test/services/collaborator_normalizer_test.exs +++ b/test/services/collaborator_normalizer_test.exs @@ -9,15 +9,32 @@ defmodule AccentTest.CollaboratorNormalizer do alias Accent.Repo alias Accent.User alias Accent.UserRemote.CollaboratorNormalizer + alias Faker.Internet test "create with many collaborations" do - project = Repo.insert!(%Project{main_color: "#f00", name: "Ha"}) - project2 = Repo.insert!(%Project{main_color: "#f00", name: "Oh"}) - assigner = Repo.insert!(%User{email: "assigner@test.com"}) + project = Factory.insert(Project) + project2 = Factory.insert(Project) + assigner = Factory.insert(User) collaborators = [ - %Collaborator{role: "admin", project_id: project.id, assigner_id: assigner.id}, - %Collaborator{role: "developer", project_id: project2.id, assigner_id: assigner.id} + struct!( + Collaborator, + Factory.build(Collaborator, + email: Internet.email(), + role: "admin", + project_id: project.id, + assigner_id: assigner.id + ) + ), + struct!( + Collaborator, + Factory.build(Collaborator, + email: Internet.email(), + role: "developer", + project_id: project2.id, + assigner_id: assigner.id + ) + ) ] collaborator_ids = @@ -26,7 +43,7 @@ defmodule AccentTest.CollaboratorNormalizer do |> Enum.map(&Repo.insert!/1) |> Enum.map(&Map.get(&1, :id)) - new_user = Repo.insert!(%User{email: "test@test.com"}) + new_user = Factory.insert(User, email: "test@test.com") %User{} = CollaboratorNormalizer.normalize(new_user) @@ -36,13 +53,29 @@ defmodule AccentTest.CollaboratorNormalizer do end test "create with case insensitive email" do - project = Repo.insert!(%Project{main_color: "#f00", name: "Ha"}) - project2 = Repo.insert!(%Project{main_color: "#f00", name: "Oh"}) - assigner = Repo.insert!(%User{email: "assigner@test.com"}) + project = Factory.insert(Project) + project2 = Factory.insert(Project) + assigner = Factory.insert(User) collaborators = [ - %Collaborator{role: "admin", project_id: project.id, assigner_id: assigner.id}, - %Collaborator{role: "developer", project_id: project2.id, assigner_id: assigner.id} + struct!( + Collaborator, + Factory.build(Collaborator, + email: Internet.email(), + role: "admin", + project_id: project.id, + assigner_id: assigner.id + ) + ), + struct!( + Collaborator, + Factory.build(Collaborator, + email: Internet.email(), + role: "developer", + project_id: project2.id, + assigner_id: assigner.id + ) + ) ] collaborator_ids = @@ -51,7 +84,7 @@ defmodule AccentTest.CollaboratorNormalizer do |> Enum.map(&Repo.insert!/1) |> Enum.map(&Map.get(&1, :id)) - new_user = Repo.insert!(%User{email: "Test@test.com"}) + new_user = Factory.insert(User, email: "Test@test.com") %User{} = CollaboratorNormalizer.normalize(new_user) @@ -61,7 +94,7 @@ defmodule AccentTest.CollaboratorNormalizer do end test "create without collaborations" do - new_user = Repo.insert!(%User{email: "Test@test.com"}) + new_user = Factory.insert(User, email: "Test@test.com") %User{} = CollaboratorNormalizer.normalize(new_user) diff --git a/test/services/collaborator_updater_test.exs b/test/services/collaborator_updater_test.exs index 7bfa90d2e..bc6efde0b 100644 --- a/test/services/collaborator_updater_test.exs +++ b/test/services/collaborator_updater_test.exs @@ -5,20 +5,20 @@ defmodule AccentTest.CollaboratorUpdater do alias Accent.Collaborator alias Accent.CollaboratorUpdater alias Accent.Project - alias Accent.Repo alias Accent.User test "update" do - email = "test@test.com" - project = Repo.insert!(%Project{main_color: "#f00", name: "com"}) - assigner = Repo.insert!(%User{email: "lol@test.com"}) + project = Factory.insert(Project) + assigner = Factory.insert(User) role = "admin" - collaborator = Repo.insert!(%Collaborator{role: role, assigner: assigner, project: project, email: email}) + + collaborator = + Factory.insert(Collaborator, role: role, assigner_id: assigner.id, project_id: project.id, email: assigner.email) {:ok, updated_collaborator} = CollaboratorUpdater.update(collaborator, %{"role" => "reviewer"}) assert updated_collaborator.email === collaborator.email - assert updated_collaborator.assigner_id === collaborator.assigner.id + assert updated_collaborator.assigner_id === collaborator.assigner_id assert updated_collaborator.role === "reviewer" end end diff --git a/test/services/integration_manager_test.exs b/test/services/integration_manager_test.exs index 2f3f18b69..806540e9d 100644 --- a/test/services/integration_manager_test.exs +++ b/test/services/integration_manager_test.exs @@ -1,6 +1,6 @@ defmodule AccentTest.IntegrationManager do @moduledoc false - use Accent.RepoCase, async: true + use Accent.RepoCase, async: false import Mock @@ -17,11 +17,19 @@ defmodule AccentTest.IntegrationManager do describe "execute" do setup do - project = Repo.insert!(%Project{main_color: "red", name: "com"}) - user = Repo.insert!(%User{email: "test@test.com"}) - language = Repo.insert!(%Language{slug: "fr-custom", name: "Fr"}) - revision = Repo.insert!(%Revision{project: project, language: language}) - document = Repo.insert!(%Document{project: project, path: "foo", format: "gettext"}) + project = Factory.insert(Project) + user = Factory.insert(User) + language = Factory.insert(Language, slug: "fr-custom") + + revision = + Factory.insert(Revision, + master: true, + master_revision_id: nil, + project_id: project.id, + language_id: language.id + ) + + document = Factory.insert(Document, project_id: project.id, path: "foo", format: "gettext") {:ok, [project: project, user: user, language: language, revision: revision, document: document]} end @@ -32,30 +40,30 @@ defmodule AccentTest.IntegrationManager do document: document, project: project } do - version = Repo.insert!(%Version{project: project, tag: "1.2.45", name: "vNext", user: user}) + version = Factory.insert(Version, project_id: project.id, tag: "1.2.45", name: "vNext", user_id: user.id) - Repo.insert!(%Translation{ - revision: revision, - document: document, + Factory.insert(Translation, + revision_id: revision.id, + document_id: document.id, key: "key", corrected_text: "value latest" - }) + ) - Repo.insert!(%Translation{ - revision: revision, - version: version, - document: document, + Factory.insert(Translation, + revision_id: revision.id, + version_id: version.id, + document_id: document.id, key: "key", corrected_text: "value v1.2.45" - }) + ) integration = - Repo.insert!(%Integration{ - project: project, - user: user, + Factory.insert(Integration, + project_id: project.id, + user_id: user.id, service: "azure_storage_container", data: %{azure_storage_container_sas: "http://azure.blob.test/container?sas=1234"} - }) + ) with_mock HTTPoison, put: fn url, {:file, file}, headers -> @@ -87,15 +95,20 @@ defmodule AccentTest.IntegrationManager do document: document, project: project } do - Repo.insert!(%Translation{revision: revision, document: document, key: "key", corrected_text: "value"}) + Factory.insert(Translation, + revision_id: revision.id, + document_id: document.id, + key: "key", + corrected_text: "value" + ) integration = - Repo.insert!(%Integration{ - project: project, - user: user, + Factory.insert(Integration, + project_id: project.id, + user_id: user.id, service: "azure_storage_container", data: %{azure_storage_container_sas: "http://azure.blob.test/container?sas=1234"} - }) + ) with_mock HTTPoison, put: fn url, body, headers -> diff --git a/test/services/operation_batcher_test.exs b/test/services/operation_batcher_test.exs index ab2d4ad9b..4e16527fe 100644 --- a/test/services/operation_batcher_test.exs +++ b/test/services/operation_batcher_test.exs @@ -12,44 +12,43 @@ defmodule AccentTest.OperationBatcher do alias Accent.User setup do - user = Repo.insert!(%User{}) - revision = Repo.insert!(%Revision{}) - - translation_one = - Repo.insert!(%Translation{key: "a", conflicted: true, revision_id: revision.id, revision: revision}) - - translation_two = - Repo.insert!(%Translation{key: "b", conflicted: true, revision_id: revision.id, revision: revision}) + user = Factory.insert(User) + revision = Factory.insert(Revision) + translation_one = Factory.insert(Translation, key: "a", conflicted: true, revision_id: revision.id) + translation_two = Factory.insert(Translation, key: "b", conflicted: true, revision_id: revision.id) [user: user, revision: revision, translations: [translation_one, translation_two]] end test "create batch with close operations", %{user: user, revision: revision, translations: [translation_one, _]} do operations = - [ - %Operation{ - action: "correct_conflict", - key: "a", - text: "B", - translation_id: translation_one.id, - user_id: user.id, - revision_id: revision.id, - inserted_at: DateTime.utc_now() - } - ] - |> Enum.map(&Repo.insert!/1) - |> Enum.map(&Map.get(&1, :id)) + Enum.map( + [ + Factory.insert(Operation, + action: "correct_conflict", + key: "a", + text: "B", + translation_id: translation_one.id, + user_id: user.id, + revision_id: revision.id, + project_id: revision.project_id, + inserted_at: DateTime.utc_now() + ) + ], + &Map.get(&1, :id) + ) operation = - Repo.insert!(%Operation{ + Factory.insert(Operation, action: "correct_conflict", key: "a", - text: "B", + text: "C", translation_id: translation_one.id, user_id: user.id, revision_id: revision.id, + project_id: revision.project_id, inserted_at: DateTime.utc_now() - }) + ) batch_responses = OperationBatcher.batch(operation) @@ -74,58 +73,63 @@ defmodule AccentTest.OperationBatcher do translations: [translation_one, translation_two] } do batch_operation = - Repo.insert!(%Operation{ + Factory.insert(Operation, action: "batch_correct_conflict", user_id: user.id, revision_id: revision.id, + project_id: revision.project_id, stats: [%{"count" => 2, "action" => "correct_conflict"}], inserted_at: DateTime.utc_now() |> DateTime.to_naive() |> NaiveDateTime.add(-960, :second) |> DateTime.from_naive!("Etc/UTC") - }) + ) operations = - [ - %Operation{ - action: "correct_conflict", - key: "a", - text: "B", - translation_id: translation_one.id, - user_id: user.id, - revision_id: revision.id, - batch_operation_id: batch_operation.id, - inserted_at: - DateTime.utc_now() - |> DateTime.to_naive() - |> NaiveDateTime.add(-960, :second) - |> DateTime.from_naive!("Etc/UTC") - }, - %Operation{ - action: "correct_conflict", - key: "b", - text: "C", - translation_id: translation_two.id, - user_id: user.id, - revision_id: revision.id, - batch_operation_id: batch_operation.id, - inserted_at: DateTime.utc_now() - } - ] - |> Enum.map(&Repo.insert!/1) - |> Enum.map(&Map.get(&1, :id)) + Enum.map( + [ + Factory.insert(Operation, + action: "correct_conflict", + key: "a", + text: "B", + translation_id: translation_one.id, + user_id: user.id, + revision_id: revision.id, + project_id: revision.project_id, + batch_operation_id: batch_operation.id, + inserted_at: + DateTime.utc_now() + |> DateTime.to_naive() + |> NaiveDateTime.add(-960, :second) + |> DateTime.from_naive!("Etc/UTC") + ), + Factory.insert(Operation, + action: "correct_conflict", + key: "b", + text: "C", + translation_id: translation_two.id, + user_id: user.id, + revision_id: revision.id, + project_id: revision.project_id, + batch_operation_id: batch_operation.id, + inserted_at: DateTime.utc_now() + ) + ], + &Map.get(&1, :id) + ) operation = - Repo.insert!(%Operation{ + Factory.insert(Operation, action: "correct_conflict", key: "a", text: "B", translation_id: translation_one.id, user_id: user.id, revision_id: revision.id, + project_id: revision.project_id, inserted_at: DateTime.utc_now() - }) + ) batch_responses = Accent.OperationBatcher.batch(operation) @@ -158,6 +162,7 @@ defmodule AccentTest.OperationBatcher do translation_id: translation_one.id, user_id: user.id, revision_id: revision.id, + project_id: revision.project_id, inserted_at: DateTime.utc_now() |> DateTime.to_naive() @@ -171,6 +176,7 @@ defmodule AccentTest.OperationBatcher do translation_id: translation_two.id, user_id: user.id, revision_id: revision.id, + project_id: revision.project_id, inserted_at: DateTime.utc_now() |> DateTime.to_naive() @@ -182,15 +188,16 @@ defmodule AccentTest.OperationBatcher do |> Enum.map(&Map.get(&1, :id)) operation = - Repo.insert!(%Operation{ + Factory.insert(Operation, action: "correct_conflict", key: "a", text: "B", translation_id: translation_one.id, user_id: user.id, revision_id: revision.id, + project_id: revision.project_id, inserted_at: DateTime.utc_now() - }) + ) batch_responses = Accent.OperationBatcher.batch(operation) diff --git a/test/services/project_creator_test.exs b/test/services/project_creator_test.exs index 7f15e29f5..5c7a55a6a 100644 --- a/test/services/project_creator_test.exs +++ b/test/services/project_creator_test.exs @@ -10,8 +10,8 @@ defmodule AccentTest.ProjectCreator do require Ecto.Query test "create with language and user" do - language = Repo.insert!(%Language{name: "french"}) - user = Repo.insert!(%User{email: "lol@test.com"}) + language = Factory.insert(Language) + user = Factory.insert(User) params = %{"main_color" => "#f00", "name" => "OK", "language_id" => language.id} {:ok, project} = ProjectCreator.create(params: params, user: user) @@ -23,8 +23,8 @@ defmodule AccentTest.ProjectCreator do end test "create owner collaborator" do - language = Repo.insert!(%Language{name: "french"}) - user = Repo.insert!(%User{email: "lol@test.com"}) + language = Factory.insert(Language) + user = Factory.insert(User) params = %{"main_color" => "#f00", "name" => "OK", "language_id" => language.id} {:ok, project} = ProjectCreator.create(params: params, user: user) @@ -34,8 +34,8 @@ defmodule AccentTest.ProjectCreator do end test "create bot collaborator" do - language = Repo.insert!(%Language{name: "french"}) - user = Repo.insert!(%User{email: "lol@test.com"}) + language = Factory.insert(Language) + user = Factory.insert(User) params = %{"main_color" => "#f00", "name" => "OK", "language_id" => language.id} {:ok, project} = ProjectCreator.create(params: params, user: user) diff --git a/test/services/project_deleter_test.exs b/test/services/project_deleter_test.exs index 0a6528fe1..50ae1f828 100644 --- a/test/services/project_deleter_test.exs +++ b/test/services/project_deleter_test.exs @@ -3,13 +3,21 @@ defmodule AccentTest.ProjectDeleter do use Accent.RepoCase, async: true alias Accent.Collaborator + alias Accent.Language + alias Accent.Operation alias Accent.Project alias Accent.ProjectDeleter alias Accent.Repo + alias Accent.Revision - test "create with language and user" do - project = Repo.insert!(%Project{main_color: "#f00", name: "french"}) - collaborator = Repo.insert!(%Collaborator{project_id: project.id, role: "reviewer"}) + test "delete collaborators and operations" do + project = Factory.insert(Project) + language = Factory.insert(Language) + revision = Factory.insert(Revision, language_id: language.id, project_id: project.id) + collaborator = Factory.insert(Collaborator, project_id: project.id, role: "reviewer") + + Factory.insert(Operation, project_id: project.id, action: "sync") + Factory.insert(Operation, project_id: project.id, revision_id: revision.id, action: "merge") assert project |> Ecto.assoc(:all_collaborators) @@ -18,6 +26,8 @@ defmodule AccentTest.ProjectDeleter do {:ok, project} = ProjectDeleter.delete(project: project) - assert Repo.all(Ecto.assoc(project, :all_collaborators)) === [] + assert Repo.aggregate(Ecto.assoc(project, :all_collaborators), :count) === 0 + assert Repo.aggregate(Ecto.assoc(project, :operations), :count) === 0 + assert Repo.aggregate(Ecto.assoc(revision, :operations), :count) === 0 end end diff --git a/test/services/revision_deleter_test.exs b/test/services/revision_deleter_test.exs index c808c5d25..901b3ce9d 100644 --- a/test/services/revision_deleter_test.exs +++ b/test/services/revision_deleter_test.exs @@ -11,19 +11,19 @@ defmodule AccentTest.RevisionDeleter do alias Accent.Translation setup do - project = Repo.insert!(%Project{main_color: "#f00", name: "My project"}) - french_language = Repo.insert!(%Language{name: "french"}) - english_language = Repo.insert!(%Language{name: "english"}) + project = Factory.insert(Project) + french_language = Factory.insert(Language) + english_language = Factory.insert(Language) - master_revision = Repo.insert!(%Revision{language_id: french_language.id, project_id: project.id, master: true}) + master_revision = Factory.insert(Revision, language_id: french_language.id, project_id: project.id, master: true) slave_revision = - Repo.insert!(%Revision{ + Factory.insert(Revision, language_id: english_language.id, project_id: project.id, master: false, master_revision_id: master_revision.id - }) + ) {:ok, [master_revision: master_revision, slave_revision: slave_revision]} end @@ -41,7 +41,7 @@ defmodule AccentTest.RevisionDeleter do end test "delete operations", %{slave_revision: revision} do - operation = Repo.insert!(%Operation{action: "new", key: "a", revision_id: revision.id}) + operation = Factory.insert(Operation, action: "new", key: "a", revision_id: revision.id) Accent.Revisions.DeleteWorker.perform(%Oban.Job{args: %{"revision_id" => revision.id}}) @@ -49,7 +49,7 @@ defmodule AccentTest.RevisionDeleter do end test "delete translations", %{slave_revision: revision} do - translation = Repo.insert!(%Translation{key: "a", revision_id: revision.id}) + translation = Factory.insert(Translation, key: "a", revision_id: revision.id) Accent.Revisions.DeleteWorker.perform(%Oban.Job{args: %{"revision_id" => revision.id}}) diff --git a/test/services/revision_master_promoter_test.exs b/test/services/revision_master_promoter_test.exs index edbaac0c6..1473788ef 100644 --- a/test/services/revision_master_promoter_test.exs +++ b/test/services/revision_master_promoter_test.exs @@ -9,19 +9,19 @@ defmodule AccentTest.RevisionMasterPromoter do alias Accent.RevisionManager setup do - french_language = Repo.insert!(%Language{name: "french"}) - english_language = Repo.insert!(%Language{name: "english"}) - project = Repo.insert!(%Project{main_color: "#f00", name: "My project"}) + french_language = Factory.insert(Language) + english_language = Factory.insert(Language) + project = Factory.insert(Project) - master_revision = Repo.insert!(%Revision{language_id: french_language.id, project_id: project.id, master: true}) + master_revision = Factory.insert(Revision, language_id: french_language.id, project_id: project.id, master: true) slave_revision = - Repo.insert!(%Revision{ + Factory.insert(Revision, language_id: english_language.id, project_id: project.id, master: false, master_revision_id: master_revision.id - }) + ) {:ok, [master_revision: master_revision, slave_revision: slave_revision]} end diff --git a/test/services/translations_renderer_test.exs b/test/services/translations_renderer_test.exs index cc977e729..e2c87e89c 100644 --- a/test/services/translations_renderer_test.exs +++ b/test/services/translations_renderer_test.exs @@ -10,11 +10,9 @@ defmodule AccentTest.TranslationsRenderer do alias Accent.TranslationsRenderer alias Accent.User - @user %User{email: "test@test.com"} - setup do - user = Repo.insert!(@user) - language = Repo.insert!(%Language{name: "English", slug: Ecto.UUID.generate()}) + user = Factory.insert(User) + language = Factory.insert(Language) {:ok, project} = ProjectCreator.create(params: %{main_color: "#f00", name: "My project", language_id: language.id}, user: user) @@ -30,16 +28,16 @@ defmodule AccentTest.TranslationsRenderer do end test "render json with filename", %{project: project, revision: revision} do - document = Repo.insert!(%Document{project_id: project.id, path: "my-test", format: "json"}) + document = Factory.insert(Document, project_id: project.id, path: "my-test", format: "json") translation = - Repo.insert!(%Translation{ + Factory.insert(Translation, key: "a", proposed_text: "B", corrected_text: "A", revision_id: revision.id, document_id: document.id - }) + ) %{render: render} = TranslationsRenderer.render_translations(%{ @@ -60,28 +58,25 @@ defmodule AccentTest.TranslationsRenderer do end test "render json with runtime error", %{project: project, revision: revision} do - document = Repo.insert!(%Document{project_id: project.id, path: "my-test", format: "json"}) + document = Factory.insert(Document, project_id: project.id, path: "my-test", format: "json") translations = - Enum.map( - [ - %Translation{ - key: "a.nested.foo", - proposed_text: "B", - corrected_text: "A", - revision_id: revision.id, - document_id: document.id - }, - %Translation{ - key: "a.nested", - proposed_text: "C", - corrected_text: "D", - revision_id: revision.id, - document_id: document.id - } - ], - &Repo.insert!/1 - ) + [ + Factory.insert(Translation, + key: "a.nested.foo", + proposed_text: "B", + corrected_text: "A", + revision_id: revision.id, + document_id: document.id + ), + Factory.insert(Translation, + key: "a.nested", + proposed_text: "C", + corrected_text: "D", + revision_id: revision.id, + document_id: document.id + ) + ] %{render: render} = TranslationsRenderer.render_translations(%{ @@ -97,16 +92,16 @@ defmodule AccentTest.TranslationsRenderer do if Langue.Formatter.Rails.enabled?() do test "render rails with locale", %{project: project, revision: revision} do - document = Repo.insert!(%Document{project_id: project.id, path: "my-test", format: "rails_yml"}) + document = Factory.insert(Document, project_id: project.id, path: "my-test", format: "rails_yml") translation = - Repo.insert!(%Translation{ + Factory.insert(Translation, key: "a", proposed_text: "A", corrected_text: "A", revision_id: revision.id, document_id: document.id - }) + ) %{render: render} = TranslationsRenderer.render_translations(%{ @@ -128,16 +123,16 @@ defmodule AccentTest.TranslationsRenderer do test "render xliff and revision overrides on source revision", %{project: project, revision: revision} do revision = Repo.update!(Ecto.Changeset.change(revision, %{slug: "testtest"})) - document = Repo.insert!(%Document{project_id: project.id, path: "my-test", format: "xliff_1_2"}) + document = Factory.insert(Document, project_id: project.id, path: "my-test", format: "xliff_1_2") translation = - Repo.insert!(%Translation{ + Factory.insert(Translation, key: "a", proposed_text: "A", corrected_text: "A", revision_id: revision.id, document_id: document.id - }) + ) %{render: render} = TranslationsRenderer.render_translations(%{ diff --git a/test/support/channel_case.ex b/test/support/channel_case.ex index 89e330d08..bfbb4444c 100644 --- a/test/support/channel_case.ex +++ b/test/support/channel_case.ex @@ -12,6 +12,8 @@ defmodule Accent.ChannelCase do # Import conveniences for testing with connections import Phoenix.ChannelTest + alias Accent.Factory + # The default endpoint for testing @endpoint Endpoint diff --git a/test/support/conn_case.ex b/test/support/conn_case.ex index ed4c54ac7..4661b37bc 100644 --- a/test/support/conn_case.ex +++ b/test/support/conn_case.ex @@ -16,8 +16,6 @@ defmodule Accent.ConnCase do use ExUnit.CaseTemplate alias Accent.Endpoint - alias Accent.Repo - alias Ecto.Adapters.SQL.Sandbox alias Phoenix.ConnTest using do @@ -29,18 +27,21 @@ defmodule Accent.ConnCase do import Phoenix.ConnTest import Plug.Conn + alias Accent.Factory + # The default endpoint for testing @endpoint Endpoint end end setup tags do - :ok = Sandbox.checkout(Repo) - - unless tags[:async] do - Sandbox.mode(Repo, {:shared, self()}) - end + setup_sandbox(tags) {:ok, conn: ConnTest.build_conn()} end + + def setup_sandbox(tags) do + pid = Ecto.Adapters.SQL.Sandbox.start_owner!(Accent.Repo, shared: not tags[:async]) + on_exit(fn -> Ecto.Adapters.SQL.Sandbox.stop_owner(pid) end) + end end diff --git a/test/support/factory.ex b/test/support/factory.ex new file mode 100644 index 000000000..d2cfe3d63 --- /dev/null +++ b/test/support/factory.ex @@ -0,0 +1,48 @@ +defmodule Accent.Factory do + @moduledoc false + use Factori, + repo: Accent.Repo, + mappings: [ + Accent.Factory.Mappings.Document, + Accent.Factory.Mappings.Operation, + Accent.Factory.Mappings.Translation, + Accent.Factory.Mappings.Project, + Factori.Mapping.Embed, + Factori.Mapping.Enum, + Factori.Mapping.Faker + ] + + defmodule Mappings do + @moduledoc false + defmodule Project do + @moduledoc false + @behaviour Factori.Mapping + + def match(%{table_name: "projects", name: :locked_file_operations}), do: false + end + + defmodule Document do + @moduledoc false + @behaviour Factori.Mapping + + def match(%{table_name: "documents", name: :format}), do: "json" + def match(%{table_name: "documents", name: :path}), do: "translations" + end + + defmodule Operation do + @moduledoc false + @behaviour Factori.Mapping + + def match(%{table_name: "operations", name: :rollbacked}), do: false + def match(%{table_name: "operations", name: :batch}), do: false + end + + defmodule Translation do + @moduledoc false + @behaviour Factori.Mapping + + def match(%{table_name: "translations", name: :locked}), do: false + def match(%{table_name: "translations", name: :removed}), do: false + end + end +end diff --git a/test/support/mocks.ex b/test/support/mocks.ex index e70aba497..516b67afa 100644 --- a/test/support/mocks.ex +++ b/test/support/mocks.ex @@ -1,7 +1,14 @@ defmodule Accent.Hook.Outbounds.Mock do @moduledoc false + @behaviour Accent.Hook.Events + use Oban.Worker, queue: :hook + @impl Accent.Hook.Events + def registered_events do + :all + end + @impl Oban.Worker def perform(_job) do :ok diff --git a/test/support/repo_case.ex b/test/support/repo_case.ex index 445e6fc60..f955d58d2 100644 --- a/test/support/repo_case.ex +++ b/test/support/repo_case.ex @@ -6,6 +6,8 @@ defmodule Accent.RepoCase do quote do use Oban.Testing, repo: Accent.Repo + alias Accent.Factory + def to_worker_args(struct) do struct |> Jason.encode!() @@ -15,12 +17,13 @@ defmodule Accent.RepoCase do end setup tags do - :ok = Ecto.Adapters.SQL.Sandbox.checkout(Accent.Repo) - - unless tags[:async] do - Ecto.Adapters.SQL.Sandbox.mode(Accent.Repo, {:shared, self()}) - end + setup_sandbox(tags) :ok end + + def setup_sandbox(tags) do + pid = Ecto.Adapters.SQL.Sandbox.start_owner!(Accent.Repo, shared: not tags[:async]) + on_exit(fn -> Ecto.Adapters.SQL.Sandbox.stop_owner(pid) end) + end end diff --git a/test/test_helper.exs b/test/test_helper.exs index aec5171a1..12ed268a4 100644 --- a/test/test_helper.exs +++ b/test/test_helper.exs @@ -1,3 +1,5 @@ +alias Ecto.Adapters.SQL.Sandbox + defmodule Accent.FormatterTestHelper do @moduledoc false def test_parse(variant, parser) do @@ -50,4 +52,9 @@ defmodule Langue.Expectation.Case do end ExUnit.start() -Ecto.Adapters.SQL.Sandbox.mode(Accent.Repo, :manual) + +Sandbox.checkout(Accent.Repo) +Accent.Factory.bootstrap() +Sandbox.checkin(Accent.Repo) + +Sandbox.mode(Accent.Repo, :manual) diff --git a/test/web/channels/project_channel_test.exs b/test/web/channels/project_channel_test.exs index 84e148ca6..e4d504f10 100644 --- a/test/web/channels/project_channel_test.exs +++ b/test/web/channels/project_channel_test.exs @@ -5,15 +5,14 @@ defmodule AccentTest.ProjectChannel do alias Accent.AccessToken alias Accent.Collaborator alias Accent.Project - alias Accent.Repo alias Accent.User alias Accent.UserSocket setup do - user = Repo.insert!(%User{email: "test@test.com"}) - project = Repo.insert!(%Project{main_color: "#f00", name: "My project"}) - access_token = Repo.insert!(%AccessToken{user_id: user.id, token: "test-token"}) - Repo.insert!(%Collaborator{project_id: project.id, user_id: user.id, role: "admin"}) + user = Factory.insert(User, email: "test@test.com") + project = Factory.insert(Project) + access_token = Factory.insert(AccessToken, user_id: user.id, token: "test-token") + Factory.insert(Collaborator, project_id: project.id, user_id: user.id, role: "admin") socket = socket(UserSocket, "will-autenticated-user", %{}) {:ok, socket} = UserSocket.connect(%{"token" => "Bearer #{access_token.token}"}, socket) @@ -33,8 +32,8 @@ defmodule AccentTest.ProjectChannel do end test "join with unauthorized user", %{project: project} do - user = Repo.insert!(%User{email: "test2@test.com"}) - access_token = Repo.insert!(%AccessToken{user_id: user.id, token: "test-token-2"}) + user = Factory.insert(User, email: "test2@test.com") + access_token = Factory.insert(AccessToken, user_id: user.id, token: "test-token-2") socket = socket(UserSocket, "unauthorized-user", %{}) {:ok, socket} = UserSocket.connect(%{"token" => "Bearer #{access_token.token}"}, socket) diff --git a/test/web/channels/user_socket_test.exs b/test/web/channels/user_socket_test.exs index 83d174d0d..1cb377b6f 100644 --- a/test/web/channels/user_socket_test.exs +++ b/test/web/channels/user_socket_test.exs @@ -2,12 +2,11 @@ defmodule AccentTest.UserSocket do use Accent.ChannelCase, async: true alias Accent.AccessToken - alias Accent.Repo alias Accent.User alias Accent.UserSocket setup do - user = Repo.insert!(%User{email: "test@test.com"}) + user = Factory.insert(User, email: "test@test.com") {:ok, user: user} end @@ -20,7 +19,7 @@ defmodule AccentTest.UserSocket do end test "connect with valid token", %{user: user} do - access_token = Repo.insert!(%AccessToken{user_id: user.id, token: "test-token"}) + access_token = Factory.insert(AccessToken, user_id: user.id, token: "test-token") socket = socket(UserSocket, "nonautenticated-user", %{}) {:ok, socket} = UserSocket.connect(%{"token" => "Bearer #{access_token.token}"}, socket) diff --git a/test/web/controllers/badge_controller_test.exs b/test/web/controllers/badge_controller_test.exs index c847283da..ccc1710de 100644 --- a/test/web/controllers/badge_controller_test.exs +++ b/test/web/controllers/badge_controller_test.exs @@ -4,7 +4,6 @@ defmodule AccentTest.BadgeController do import Mock alias Accent.Project - alias Accent.Repo defp behave_like_valid_response(response) do assert response.status == 200 @@ -14,7 +13,7 @@ defmodule AccentTest.BadgeController do setup do id = Ecto.UUID.generate() - project = Repo.insert!(%Project{id: id, name: "project", main_color: "#f00"}) + project = Factory.insert(Project, id: id, name: "project", main_color: "#f00") badge_generate_mock = [generate: fn _, _ -> {:ok, ""} end] {:ok, %{project: project, badge_generate_mock: badge_generate_mock}} diff --git a/test/web/controllers/export_controller_test.exs b/test/web/controllers/export_controller_test.exs index b7454a9bf..96364a20c 100644 --- a/test/web/controllers/export_controller_test.exs +++ b/test/web/controllers/export_controller_test.exs @@ -4,34 +4,31 @@ defmodule AccentTest.ExportController do alias Accent.Document alias Accent.Language alias Accent.Project - alias Accent.Repo alias Accent.Revision alias Accent.Translation alias Accent.User alias Accent.Version - @user %User{email: "test@test.com"} - setup do - user = Repo.insert!(@user) - french_language = Repo.insert!(%Language{name: "french", slug: Ecto.UUID.generate()}) - project = Repo.insert!(%Project{main_color: "#f00", name: "My project"}) + user = Factory.insert(User) + french_language = Factory.insert(Language) + project = Factory.insert(Project) - revision = Repo.insert!(%Revision{language_id: french_language.id, project_id: project.id, master: true}) + revision = Factory.insert(Revision, language_id: french_language.id, project_id: project.id, master: true) {:ok, [user: user, project: project, revision: revision, language: french_language]} end test "export inline", %{conn: conn, project: project, revision: revision, language: language} do - document = Repo.insert!(%Document{project_id: project.id, path: "test2", format: "json"}) + document = Factory.insert(Document, project_id: project.id, path: "test2", format: "json") - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, key: "ok", corrected_text: "bar", proposed_text: "bar", document_id: document.id - }) + ) params = %{ inline_render: true, @@ -53,15 +50,15 @@ defmodule AccentTest.ExportController do end test "export basic", %{conn: conn, project: project, revision: revision, language: language} do - document = Repo.insert!(%Document{project_id: project.id, path: "test2", format: "json"}) + document = Factory.insert(Document, project_id: project.id, path: "test2", format: "json") - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, key: "ok", corrected_text: "bar", proposed_text: "bar", document_id: document.id - }) + ) params = %{ project_id: project.id, @@ -82,8 +79,8 @@ defmodule AccentTest.ExportController do end test "export unknown language for the project", %{conn: conn, project: project} do - document = Repo.insert!(%Document{project_id: project.id, path: "test2", format: "json"}) - language = Repo.insert!(%Language{name: "chinese", slug: Ecto.UUID.generate()}) + document = Factory.insert(Document, project_id: project.id, path: "test2", format: "json") + language = Factory.insert(Language) params = %{ project_id: project.id, @@ -98,24 +95,24 @@ defmodule AccentTest.ExportController do end test "export document", %{conn: conn, project: project, revision: revision, language: language} do - document = Repo.insert!(%Document{project_id: project.id, path: "test2", format: "json"}) - other_document = Repo.insert!(%Document{project_id: project.id, path: "test3", format: "json"}) + document = Factory.insert(Document, project_id: project.id, path: "test2", format: "json") + other_document = Factory.insert(Document, project_id: project.id, path: "test3", format: "json") - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, key: "ok", corrected_text: "bar", proposed_text: "bar", document_id: document.id - }) + ) - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, key: "test", corrected_text: "foo", proposed_text: "foo", document_id: other_document.id - }) + ) params = %{ project_id: project.id, @@ -143,25 +140,25 @@ defmodule AccentTest.ExportController do end test "export version", %{conn: conn, user: user, project: project, revision: revision, language: language} do - version = Repo.insert!(%Version{project_id: project.id, user_id: user.id, name: "Current", tag: "master"}) - document = Repo.insert!(%Document{project_id: project.id, path: "test2", format: "json"}) + version = Factory.insert(Version, project_id: project.id, user_id: user.id, name: "Current", tag: "master") + document = Factory.insert(Document, project_id: project.id, path: "test2", format: "json") - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, key: "ok", corrected_text: "bar", proposed_text: "bar", document_id: document.id - }) + ) - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, key: "test", corrected_text: "foo", proposed_text: "foo", document_id: document.id, version_id: version.id - }) + ) params = %{ version: "master", @@ -181,25 +178,25 @@ defmodule AccentTest.ExportController do end test "export without version", %{conn: conn, user: user, project: project, revision: revision, language: language} do - version = Repo.insert!(%Version{project_id: project.id, user_id: user.id, name: "Current", tag: "master"}) - document = Repo.insert!(%Document{project_id: project.id, path: "test2", format: "json"}) + version = Factory.insert(Version, project_id: project.id, user_id: user.id, name: "Current", tag: "master") + document = Factory.insert(Document, project_id: project.id, path: "test2", format: "json") - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, key: "ok", corrected_text: "bar", proposed_text: "bar", document_id: document.id - }) + ) - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, key: "test", corrected_text: "foo", proposed_text: "foo", document_id: document.id, version_id: version.id - }) + ) params = %{ project_id: project.id, @@ -218,7 +215,7 @@ defmodule AccentTest.ExportController do end test "export with unknown version", %{conn: conn, project: project, language: language} do - document = Repo.insert!(%Document{project_id: project.id, path: "test2", format: "json"}) + document = Factory.insert(Document, project_id: project.id, path: "test2", format: "json") params = %{ version: "foo", @@ -234,23 +231,23 @@ defmodule AccentTest.ExportController do end test "export with order", %{conn: conn, project: project, revision: revision, language: language} do - document = Repo.insert!(%Document{project_id: project.id, path: "test2", format: "json"}) + document = Factory.insert(Document, project_id: project.id, path: "test2", format: "json") - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, key: "ok", corrected_text: "bar", proposed_text: "bar", document_id: document.id - }) + ) - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, key: "test", corrected_text: "foo", proposed_text: "foo", document_id: document.id - }) + ) params = %{ order_by: "key", @@ -271,25 +268,25 @@ defmodule AccentTest.ExportController do end test "export with default order", %{conn: conn, project: project, revision: revision, language: language} do - document = Repo.insert!(%Document{project_id: project.id, path: "test2", format: "json"}) + document = Factory.insert(Document, project_id: project.id, path: "test2", format: "json") - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, key: "ok", corrected_text: "bar", proposed_text: "bar", document_id: document.id, file_index: 2 - }) + ) - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, key: "test", corrected_text: "foo", proposed_text: "foo", document_id: document.id, file_index: 1 - }) + ) params = %{ order_by: "", @@ -310,27 +307,29 @@ defmodule AccentTest.ExportController do end if Langue.Formatter.Rails.enabled?() do + alias Accent.Repo + test "export with language overrides", %{conn: conn, project: project, revision: revision} do revision = Repo.update!(Ecto.Changeset.change(revision, %{slug: "testtest"})) - document = Repo.insert!(%Document{project_id: project.id, path: "test2", format: "rails_yml"}) + document = Factory.insert(Document, project_id: project.id, path: "test2", format: "rails_yml") - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, key: "ok", corrected_text: "bar", proposed_text: "bar", document_id: document.id, file_index: 2 - }) + ) - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, key: "test", corrected_text: "foo", proposed_text: "foo", document_id: document.id, file_index: 1 - }) + ) params = %{ order_by: "", @@ -356,9 +355,9 @@ defmodule AccentTest.ExportController do revision: revision, language: language } do - document = Repo.insert!(%Document{project_id: project.id, path: "test", format: "android_xml"}) + document = Factory.insert(Document, project_id: project.id, path: "test", format: "android_xml") - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, key: "days.one", corrected_text: "bar", @@ -366,9 +365,9 @@ defmodule AccentTest.ExportController do plural: true, document_id: document.id, file_index: 2 - }) + ) - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, key: "days.other", corrected_text: "foo", @@ -376,7 +375,7 @@ defmodule AccentTest.ExportController do plural: true, document_id: document.id, file_index: 1 - }) + ) params = %{ order_by: "", diff --git a/test/web/controllers/export_jipt_controller_test.exs b/test/web/controllers/export_jipt_controller_test.exs index c80ead15d..2303c2225 100644 --- a/test/web/controllers/export_jipt_controller_test.exs +++ b/test/web/controllers/export_jipt_controller_test.exs @@ -4,33 +4,30 @@ defmodule AccentTest.ExportJIPTController do alias Accent.Document alias Accent.Language alias Accent.Project - alias Accent.Repo alias Accent.Revision alias Accent.Translation alias Accent.User - @user %User{email: "test@test.com"} - setup do - user = Repo.insert!(@user) - french_language = Repo.insert!(%Language{name: "french", slug: Ecto.UUID.generate()}) - project = Repo.insert!(%Project{main_color: "#f00", name: "My project"}) + user = Factory.insert(User) + french_language = Factory.insert(Language) + project = Factory.insert(Project) - revision = Repo.insert!(%Revision{language_id: french_language.id, project_id: project.id, master: true}) + revision = Factory.insert(Revision, language_id: french_language.id, project_id: project.id, master: true) {:ok, [user: user, project: project, revision: revision, language: french_language]} end test "export inline", %{conn: conn, project: project, revision: revision, language: language} do - document = Repo.insert!(%Document{project_id: project.id, path: "test2", format: "json"}) + document = Factory.insert(Document, project_id: project.id, path: "test2", format: "json") - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, key: "ok", corrected_text: "bar", proposed_text: "bar", document_id: document.id - }) + ) params = %{ inline_render: true, @@ -52,15 +49,15 @@ defmodule AccentTest.ExportJIPTController do end test "export basic", %{conn: conn, project: project, revision: revision, language: language} do - document = Repo.insert!(%Document{project_id: project.id, path: "test2", format: "json"}) + document = Factory.insert(Document, project_id: project.id, path: "test2", format: "json") - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, key: "ok", corrected_text: "bar", proposed_text: "bar", document_id: document.id - }) + ) params = %{ project_id: project.id, @@ -81,24 +78,24 @@ defmodule AccentTest.ExportJIPTController do end test "export document", %{conn: conn, project: project, revision: revision, language: language} do - document = Repo.insert!(%Document{project_id: project.id, path: "test2", format: "json"}) - other_document = Repo.insert!(%Document{project_id: project.id, path: "test3", format: "json"}) + document = Factory.insert(Document, project_id: project.id, path: "test2", format: "json") + other_document = Factory.insert(Document, project_id: project.id, path: "test3", format: "json") - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, key: "ok", corrected_text: "bar", proposed_text: "bar", document_id: document.id - }) + ) - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, key: "test", corrected_text: "foo", proposed_text: "foo", document_id: other_document.id - }) + ) params = %{ project_id: project.id, @@ -127,27 +124,29 @@ defmodule AccentTest.ExportJIPTController do end if Langue.Formatter.Rails.enabled?() do + alias Accent.Repo + test "export with language overrides", %{conn: conn, project: project, revision: revision, language: language} do revision = Repo.update!(Ecto.Changeset.change(revision, %{slug: "testtest"})) - document = Repo.insert!(%Document{project_id: project.id, path: "test2", format: "rails_yml"}) + document = Factory.insert(Document, project_id: project.id, path: "test2", format: "rails_yml") - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, key: "ok", corrected_text: "bar", proposed_text: "bar", document_id: document.id, file_index: 2 - }) + ) - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, key: "test", corrected_text: "foo", proposed_text: "foo", document_id: document.id, file_index: 1 - }) + ) params = %{ order_by: "", diff --git a/test/web/controllers/format_controller_test.exs b/test/web/controllers/format_controller_test.exs index 18246b828..7639d330e 100644 --- a/test/web/controllers/format_controller_test.exs +++ b/test/web/controllers/format_controller_test.exs @@ -5,17 +5,14 @@ defmodule AccentTest.FormatController do alias Accent.Document alias Accent.Language alias Accent.Project - alias Accent.Repo alias Accent.Revision alias Accent.Translation alias Accent.User - @user %User{email: "test@test.com"} - setup do - user = Repo.insert!(@user) - access_token = Repo.insert!(%AccessToken{user_id: user.id, token: "test-token"}) - project = Repo.insert!(%Project{main_color: "#f00", name: "My project"}) + user = Factory.insert(User) + access_token = Factory.insert(AccessToken, user_id: user.id) + project = Factory.insert(Project) {:ok, [user: user, project: project, access_token: access_token]} end @@ -74,8 +71,8 @@ defmodule AccentTest.FormatController do end test "format order_by same as export", %{conn: conn, project: project, access_token: access_token} do - french_language = Repo.insert!(%Language{name: "french", slug: Ecto.UUID.generate()}) - revision = Repo.insert!(%Revision{language_id: french_language.id, project_id: project.id, master: true}) + french_language = Factory.insert(Language) + revision = Factory.insert(Revision, language_id: french_language.id, project_id: project.id, master: true) file = %Plug.Upload{ content_type: "application/json", @@ -97,7 +94,7 @@ defmodule AccentTest.FormatController do |> put_req_header("authorization", "Bearer #{access_token.token}") |> post(format_path(conn, :format), body) - document = Repo.insert!(%Document{project_id: project.id, path: "ordering", format: "json"}) + document = Factory.insert(Document, project_id: project.id, path: "ordering", format: "json") params = %{ order_by: "key", @@ -110,13 +107,13 @@ defmodule AccentTest.FormatController do content = Jason.decode!(File.read!(file.path)) for {key, value} <- content do - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, key: key, corrected_text: value, proposed_text: value, document_id: document.id - }) + ) end export_response = diff --git a/test/web/controllers/lint_controller_test.exs b/test/web/controllers/lint_controller_test.exs index ac3903093..d6f164ba1 100644 --- a/test/web/controllers/lint_controller_test.exs +++ b/test/web/controllers/lint_controller_test.exs @@ -6,30 +6,27 @@ defmodule AccentTest.LintController do alias Accent.Document alias Accent.Language alias Accent.Project - alias Accent.Repo alias Accent.Revision alias Accent.User - @user %User{email: "test@test.com"} - def file(filename \\ "simple.json") do %Plug.Upload{content_type: "application/json", filename: filename, path: "test/support/formatter/json/lint.json"} end setup do - user = Repo.insert!(@user) - access_token = Repo.insert!(%AccessToken{user_id: user.id, token: "test-token"}) - french_language = Repo.insert!(%Language{name: "french", slug: Ecto.UUID.generate()}) - project = Repo.insert!(%Project{main_color: "#f00", name: "My project"}) + user = Factory.insert(User) + access_token = Factory.insert(AccessToken, user_id: user.id, token: "test-token") + french_language = Factory.insert(Language) + project = Factory.insert(Project) - Repo.insert!(%Collaborator{project_id: project.id, user_id: user.id, role: "admin"}) - revision = Repo.insert!(%Revision{language_id: french_language.id, project_id: project.id, master: true}) + Factory.insert(Collaborator, project_id: project.id, user_id: user.id, role: "admin") + revision = Factory.insert(Revision, language_id: french_language.id, project_id: project.id, master: true) {:ok, [access_token: access_token, user: user, project: project, revision: revision, language: french_language]} end test "lint document", %{access_token: access_token, conn: conn, project: project, language: language} do - document = Repo.insert!(%Document{project_id: project.id, path: "test2", format: "json"}) + document = Factory.insert(Document, project_id: project.id, path: "test2", format: "json") body = %{ file: file(), diff --git a/test/web/controllers/merge_controller_mock_test.exs b/test/web/controllers/merge_controller_mock_test.exs index e264e468a..24938144a 100644 --- a/test/web/controllers/merge_controller_mock_test.exs +++ b/test/web/controllers/merge_controller_mock_test.exs @@ -9,29 +9,26 @@ defmodule AccentTest.MergeControllerMock do alias Accent.Document alias Accent.Language alias Accent.Project - alias Accent.Repo alias Accent.Revision alias Accent.User - @user %User{email: "test@test.com"} - def file(filename \\ "simple.json") do %Plug.Upload{content_type: "application/json", filename: filename, path: "test/support/formatter/json/simple.json"} end setup do - user = Repo.insert!(@user) - access_token = Repo.insert!(%AccessToken{user_id: user.id, token: "test-token"}) - french_language = Repo.insert!(%Language{name: "french", slug: Ecto.UUID.generate()}) - project = Repo.insert!(%Project{main_color: "#f00", name: "My project"}) + user = Factory.insert(User) + access_token = Factory.insert(AccessToken, user_id: user.id, token: "test-token") + french_language = Factory.insert(Language) + project = Factory.insert(Project) - 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}) + Factory.insert(Collaborator, project_id: project.id, user_id: user.id, role: "admin") + Factory.insert(Revision, language_id: french_language.id, project_id: project.id, master: true) {:ok, [access_token: access_token, project: project, language: french_language]} end test "sync with failure", %{access_token: access_token, conn: conn, project: project, language: language} do - document = Repo.insert!(%Document{project_id: project.id, path: "test2", format: "json"}) + document = Factory.insert(Document, project_id: project.id, path: "test2", format: "json") body = %{ file: file(), diff --git a/test/web/controllers/merge_controller_test.exs b/test/web/controllers/merge_controller_test.exs index 290e8eb2c..2e0733571 100644 --- a/test/web/controllers/merge_controller_test.exs +++ b/test/web/controllers/merge_controller_test.exs @@ -14,20 +14,18 @@ defmodule AccentTest.MergeController do alias Accent.Translation alias Accent.User - @user %User{email: "test@test.com"} - def file(filename \\ "simple.json") do %Plug.Upload{content_type: "application/json", filename: filename, path: "test/support/formatter/json/simple.json"} end setup do - user = Repo.insert!(@user) - access_token = Repo.insert!(%AccessToken{user_id: user.id, token: "test-token"}) - french_language = Repo.insert!(%Language{name: "french", slug: Ecto.UUID.generate()}) - project = Repo.insert!(%Project{main_color: "#f00", name: "My project"}) + user = Factory.insert(User) + access_token = Factory.insert(AccessToken, user_id: user.id, token: "test-token") + french_language = Factory.insert(Language) + project = Factory.insert(Project) - Repo.insert!(%Collaborator{project_id: project.id, user_id: user.id, role: "admin"}) - revision = Repo.insert!(%Revision{language_id: french_language.id, project_id: project.id, master: true}) + Factory.insert(Collaborator, project_id: project.id, user_id: user.id, role: "admin") + revision = Factory.insert(Revision, language_id: french_language.id, project_id: project.id, master: true) {:ok, [access_token: access_token, user: user, project: project, revision: revision, language: french_language]} end @@ -40,16 +38,16 @@ defmodule AccentTest.MergeController do revision: revision, language: language } do - document = Repo.insert!(%Document{project_id: project.id, path: "test2", format: "json"}) + document = Factory.insert(Document, project_id: project.id, path: "test2", format: "json") - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, key: "test", conflicted: true, corrected_text: "initial", proposed_text: "initial", document_id: document.id - }) + ) body = %{ file: file(), @@ -66,15 +64,7 @@ defmodule AccentTest.MergeController do assert response.status == 200 - assert_enqueued( - worker: Accent.Hook.Outbounds.Mock, - args: %{ - "event" => "add_translations", - "payload" => %{"language_name" => "french", "merge_type" => nil}, - "project_id" => project.id, - "user_id" => user.id - } - ) + assert_enqueued(worker: Movement.Persisters.ProjectHookWorker) merge_on_proposed_operation = Repo.one(from(o in Operation, where: [action: ^"merge_on_proposed"])) merge_operation = Repo.one(from(o in Operation, where: [action: ^"merge"])) @@ -91,16 +81,16 @@ defmodule AccentTest.MergeController do revision: revision, language: language } do - document = Repo.insert!(%Document{project_id: project.id, path: "test2", format: "json"}) + document = Factory.insert(Document, project_id: project.id, path: "test2", format: "json") - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, key: "test", conflicted: false, corrected_text: "initial", proposed_text: "initial", document_id: document.id - }) + ) body = %{ file: file(), @@ -133,16 +123,16 @@ defmodule AccentTest.MergeController do revision: revision, language: language } do - document = Repo.insert!(%Document{project_id: project.id, path: "test2", format: "json"}) + document = Factory.insert(Document, project_id: project.id, path: "test2", format: "json") - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, key: "test", conflicted: false, corrected_text: "initial", proposed_text: "modified", document_id: document.id - }) + ) body = %{ file: file(), @@ -160,15 +150,7 @@ defmodule AccentTest.MergeController do assert response.status == 200 - assert_enqueued( - worker: Accent.Hook.Outbounds.Mock, - args: %{ - "event" => "add_translations", - "payload" => %{"language_name" => "french", "merge_type" => nil}, - "project_id" => project.id, - "user_id" => user.id - } - ) + assert_enqueued(worker: Movement.Persisters.ProjectHookWorker) merge_on_corrected_force_operation = Repo.one(from(o in Operation, where: [action: ^"merge_on_corrected_force"])) merge_operation = Repo.one(from(o in Operation, where: [action: ^"merge"])) @@ -187,16 +169,16 @@ defmodule AccentTest.MergeController do revision: revision, language: language } do - document = Repo.insert!(%Document{project_id: project.id, path: "test2", format: "json"}) + document = Factory.insert(Document, project_id: project.id, path: "test2", format: "json") - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, key: "test", conflicted: true, corrected_text: "initial", proposed_text: "initial", document_id: document.id - }) + ) body = %{ file: file(), @@ -213,15 +195,7 @@ defmodule AccentTest.MergeController do assert response.status == 200 - assert_enqueued( - worker: Accent.Hook.Outbounds.Mock, - args: %{ - "event" => "add_translations", - "payload" => %{"language_name" => "french", "merge_type" => nil}, - "project_id" => project.id, - "user_id" => user.id - } - ) + assert_enqueued(worker: Movement.Persisters.ProjectHookWorker) merge_on_proposed_operation = Repo.one(from(o in Operation, where: [action: ^"merge_on_proposed"])) merge_operation = Repo.one(from(o in Operation, where: [action: ^"merge"])) diff --git a/test/web/controllers/peek_controller_test.exs b/test/web/controllers/peek_controller_test.exs index f249f4adc..9a05566bd 100644 --- a/test/web/controllers/peek_controller_test.exs +++ b/test/web/controllers/peek_controller_test.exs @@ -6,40 +6,37 @@ defmodule AccentTest.PeekController do alias Accent.Document alias Accent.Language alias Accent.Project - alias Accent.Repo alias Accent.Revision alias Accent.Translation alias Accent.User - @user %User{email: "test@test.com"} - def file(filename \\ "simple.json") do %Plug.Upload{content_type: "application/json", filename: filename, path: "test/support/formatter/json/simple.json"} end setup do - user = Repo.insert!(@user) - access_token = Repo.insert!(%AccessToken{user_id: user.id, token: "test-token"}) - french_language = Repo.insert!(%Language{name: "french", slug: Ecto.UUID.generate()}) - project = Repo.insert!(%Project{main_color: "#f00", name: "My project"}) + user = Factory.insert(User) + access_token = Factory.insert(AccessToken, user_id: user.id, token: "test-token") + french_language = Factory.insert(Language) + project = Factory.insert(Project) - Repo.insert!(%Collaborator{project_id: project.id, user_id: user.id, role: "admin"}) - revision = Repo.insert!(%Revision{language_id: french_language.id, project_id: project.id, master: true}) + Factory.insert(Collaborator, project_id: project.id, user_id: user.id, role: "admin") + revision = Factory.insert(Revision, language_id: french_language.id, project_id: project.id, master: true) {:ok, [access_token: access_token, user: user, project: project, revision: revision, language: french_language]} end test "merge", %{access_token: access_token, conn: conn, project: project, revision: revision, language: language} do - document = Repo.insert!(%Document{project_id: project.id, path: "test2", format: "json"}) + document = Factory.insert(Document, project_id: project.id, path: "test2", format: "json") - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, key: "test", conflicted: true, corrected_text: "initial", proposed_text: "initial", document_id: document.id - }) + ) body = %{ file: file(), @@ -74,16 +71,16 @@ defmodule AccentTest.PeekController do revision: revision, language: language } do - document = Repo.insert!(%Document{project_id: project.id, path: "test2", format: "json"}) + document = Factory.insert(Document, project_id: project.id, path: "test2", format: "json") - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, key: "test", conflicted: true, corrected_text: "initial", proposed_text: "initial", document_id: document.id - }) + ) body = %{ file: file(), @@ -118,16 +115,16 @@ defmodule AccentTest.PeekController do revision: revision, language: language } do - document = Repo.insert!(%Document{project_id: project.id, path: "test2", format: "json"}) + document = Factory.insert(Document, project_id: project.id, path: "test2", format: "json") - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, key: "test", conflicted: false, corrected_text: "initial", proposed_text: "initial", document_id: document.id - }) + ) body = %{ file: file(), @@ -155,16 +152,16 @@ defmodule AccentTest.PeekController do revision: revision, language: language } do - document = Repo.insert!(%Document{project_id: project.id, path: "test2", format: "json"}) + document = Factory.insert(Document, project_id: project.id, path: "test2", format: "json") - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, key: "test", conflicted: false, corrected_text: "initial", proposed_text: "initial", document_id: document.id - }) + ) body = %{ file: file(), @@ -194,16 +191,16 @@ defmodule AccentTest.PeekController do end test "sync", %{access_token: access_token, conn: conn, project: project, revision: revision, language: language} do - document = Repo.insert!(%Document{project_id: project.id, path: "test2", format: "json"}) + document = Factory.insert(Document, project_id: project.id, path: "test2", format: "json") - Repo.insert!(%Translation{ + Factory.insert(Translation, revision_id: revision.id, key: "test", conflicted: true, corrected_text: "initial", proposed_text: "initial", document_id: document.id - }) + ) body = %{ file: file(), diff --git a/test/web/controllers/sync_controller_mock_test.exs b/test/web/controllers/sync_controller_mock_test.exs index b4e6703c8..90bf1cd03 100644 --- a/test/web/controllers/sync_controller_mock_test.exs +++ b/test/web/controllers/sync_controller_mock_test.exs @@ -8,24 +8,21 @@ defmodule AccentTest.SyncControllerMock do alias Accent.Collaborator alias Accent.Language alias Accent.Project - alias Accent.Repo alias Accent.Revision alias Accent.User - @user %User{email: "test@test.com"} - def file(filename \\ "simple.json") do %Plug.Upload{content_type: "application/json", filename: filename, path: "test/support/formatter/json/simple.json"} end setup do - user = Repo.insert!(@user) - access_token = Repo.insert!(%AccessToken{user_id: user.id, token: "test-token"}) - french_language = Repo.insert!(%Language{name: "french", slug: Ecto.UUID.generate()}) - project = Repo.insert!(%Project{main_color: "#f00", name: "My project"}) + user = Factory.insert(User) + access_token = Factory.insert(AccessToken, user_id: user.id, token: "test-token") + french_language = Factory.insert(Language) + project = Factory.insert(Project) - 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}) + Factory.insert(Collaborator, project_id: project.id, user_id: user.id, role: "admin") + Factory.insert(Revision, language_id: french_language.id, project_id: project.id, master: true) {:ok, [access_token: access_token, project: project, language: french_language]} end diff --git a/test/web/controllers/sync_controller_test.exs b/test/web/controllers/sync_controller_test.exs index c56bdb814..bd700f92d 100644 --- a/test/web/controllers/sync_controller_test.exs +++ b/test/web/controllers/sync_controller_test.exs @@ -13,20 +13,18 @@ defmodule AccentTest.SyncController do alias Accent.Revision alias Accent.User - @user %User{email: "test@test.com"} - def file(filename \\ "simple.json") do %Plug.Upload{content_type: "application/json", filename: filename, path: "test/support/formatter/json/simple.json"} end setup do - user = Repo.insert!(@user) - access_token = Repo.insert!(%AccessToken{user_id: user.id, token: "test-token"}) - french_language = Repo.insert!(%Language{name: "french", slug: Ecto.UUID.generate()}) - project = Repo.insert!(%Project{main_color: "#f00", name: "My project"}) + user = Factory.insert(User) + access_token = Factory.insert(AccessToken, user_id: user.id, token: "test-token") + french_language = Factory.insert(Language) + project = Factory.insert(Project) - 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}) + Factory.insert(Collaborator, project_id: project.id, user_id: user.id, role: "admin") + Factory.insert(Revision, language_id: french_language.id, project_id: project.id, master: true) {:ok, [access_token: access_token, user: user, project: project, language: french_language]} end @@ -52,18 +50,7 @@ defmodule AccentTest.SyncController do assert response.status == 200 - assert_enqueued( - worker: Accent.Hook.Outbounds.Mock, - args: %{ - "event" => "sync", - "payload" => %{ - "batch_operation_stats" => [%{"action" => "new", "count" => 3}], - "document_path" => "simple" - }, - "project_id" => project.id, - "user_id" => user.id - } - ) + assert_enqueued(worker: Movement.Persisters.ProjectHookWorker) assert Enum.map(Repo.all(Document), &Map.get(&1, :path)) == ["simple"] diff --git a/vendor/language_tool/lib/language_tool/backend.ex b/vendor/language_tool/lib/language_tool/backend.ex index 4a581eaa3..e1b28a39f 100644 --- a/vendor/language_tool/lib/language_tool/backend.ex +++ b/vendor/language_tool/lib/language_tool/backend.ex @@ -26,6 +26,7 @@ defmodule LanguageTool.Backend do backend else Logger.warning("LanguageTool could not be started. Install JRE and build the jar in #{jar_file()} to enable it") + nil end end @@ -81,17 +82,29 @@ defmodule LanguageTool.Backend do end defp process_check(process, lang, text) do - lang = sanitize_lang(lang) - Exile.Process.write(process, IO.iodata_to_binary([String.pad_trailing(lang, 7), text, "\n"])) + write_process(process, lang, text) - with {:ok, data} <- Exile.Process.read(process), + with {:ok, data} <- read_process_until_result(process), {:ok, data} <- Jason.decode(data) do data else - _ -> nil + _ -> + nil + end + end + + defp read_process_until_result(process) do + case Exile.Process.read(process) do + {:ok, "\n"} -> read_process_until_result(process) + result -> result end end + defp write_process(process, lang, text) do + lang = sanitize_lang(lang) + Exile.Process.write(process, IO.iodata_to_binary([String.pad_trailing(lang, 7), text, "\n"])) + end + defp sanitize_lang(lang) do if lang === "en" do "en-US" diff --git a/webapp/.ember-cli b/webapp/.ember-cli index aeb9593ce..163515bbb 100644 --- a/webapp/.ember-cli +++ b/webapp/.ember-cli @@ -1,4 +1,4 @@ { "disableAnalytics": false, - "usePods": true + "isTypeScriptProject": true } diff --git a/webapp/.template-lintrc.js b/webapp/.template-lintrc.js index 28a0a4e74..1d872321d 100644 --- a/webapp/.template-lintrc.js +++ b/webapp/.template-lintrc.js @@ -3,6 +3,9 @@ module.exports = { plugins: ["ember-template-lint-plugin-prettier"], extends: ["recommended", "ember-template-lint-plugin-prettier:recommended"], + ignore: [ + 'webapp/app/templates/components/jipt-example' + ], rules: { 'attribute-indentation': {'open-invocation-max-len': 120}, 'block-indentation': 2, @@ -13,6 +16,7 @@ module.exports = { 'link-rel-noopener': true, 'no-abstract-roles': true, 'no-bare-strings': true, + 'block-indentation': false, 'no-potential-path-strings': false, 'no-yield-only': false, 'no-autofocus-attribute': false, @@ -34,6 +38,7 @@ module.exports = { 'no-shadowed-elements': true, 'no-trailing-spaces': true, 'no-triple-curlies': false, + 'no-inline-styles': false, 'no-unused-block-params': true, quotes: false, 'require-valid-alt-text': false, @@ -41,7 +46,7 @@ module.exports = { 'require-button-type': false, 'self-closing-void-elements': false, 'simple-unless': false, - 'style-concatenation': true, + 'style-concatenation': false, 'table-groups': true, 'template-length': [true, {min: 1, max: 200}], } diff --git a/webapp/MODULE_REPORT.md b/webapp/MODULE_REPORT.md new file mode 100644 index 000000000..9cadde035 --- /dev/null +++ b/webapp/MODULE_REPORT.md @@ -0,0 +1,42 @@ +## Module Report +### Unknown Global + +**Global**: `Ember.onerror` + +**Location**: `app/services/raven.js` at line 89 + +```js + enableGlobalErrorCatching() { + if (this.isRavenUsable && !this.globalErrorCatchingInitialized) { + const _oldOnError = Ember.onerror; + + Ember.onerror = (error) => { +``` + +### Unknown Global + +**Global**: `Ember.onerror` + +**Location**: `app/services/raven.js` at line 89 + +```js + enableGlobalErrorCatching() { + if (this.isRavenUsable && !this.globalErrorCatchingInitialized) { + const _oldOnError = Ember.onerror; + + Ember.onerror = (error) => { +``` + +### Unknown Global + +**Global**: `Ember.onerror` + +**Location**: `app/services/raven.js` at line 91 + +```js + const _oldOnError = Ember.onerror; + + Ember.onerror = (error) => { + if (this._ignoreError(error)) { + return; +``` diff --git a/webapp/app/app.js b/webapp/app/app.js index d8e2088b6..e08f51c26 100644 --- a/webapp/app/app.js +++ b/webapp/app/app.js @@ -5,7 +5,6 @@ import config from './config/environment'; export default class App extends Application { modulePrefix = config.modulePrefix; - podModulePrefix = config.podModulePrefix; Resolver = Resolver; } diff --git a/webapp/app/component-helpers/percentage.ts b/webapp/app/component-helpers/percentage.ts index c961cb13e..1edc82026 100644 --- a/webapp/app/component-helpers/percentage.ts +++ b/webapp/app/component-helpers/percentage.ts @@ -2,7 +2,7 @@ export default (count: number, total: number) => { const percentage = (count / total) * 100; if (percentage) { - if (percentage % 1 !== 0) return percentage.toFixed(2); + if (percentage % 1 !== 0) return Number(percentage.toFixed(2)); return percentage; } diff --git a/webapp/app/pods/components/acc-avatar-img/component.ts b/webapp/app/components/acc-avatar-img/component.ts similarity index 100% rename from webapp/app/pods/components/acc-avatar-img/component.ts rename to webapp/app/components/acc-avatar-img/component.ts diff --git a/webapp/app/pods/components/acc-badge/component.ts b/webapp/app/components/acc-badge/component.ts similarity index 100% rename from webapp/app/pods/components/acc-badge/component.ts rename to webapp/app/components/acc-badge/component.ts diff --git a/webapp/app/components/acc-emoji-picker/component.ts b/webapp/app/components/acc-emoji-picker/component.ts new file mode 100644 index 000000000..2b7da0e5d --- /dev/null +++ b/webapp/app/components/acc-emoji-picker/component.ts @@ -0,0 +1,30 @@ +import Component from '@glimmer/component'; +import {action} from '@ember/object'; +import {tracked} from '@glimmer/tracking'; +import {Picker} from 'emoji-picker-element'; + +interface Args { + onPicked: (value: string) => void; +} + +export default class EmojiPicker extends Component { + @tracked + picker?: Picker; + + @action + togglePicker() { + if (this.picker) { + this.picker = undefined; + } else { + this.picker = new Picker({locale: 'fr'}); + this._bindClick(this.picker); + } + } + + _bindClick(picker: Picker) { + picker.addEventListener('emoji-click', (event: CustomEvent) => { + this.args.onPicked(event.detail.unicode); + this.togglePicker(); + }); + } +} diff --git a/webapp/app/pods/components/acc-flash-message/component.ts b/webapp/app/components/acc-flash-message/component.ts similarity index 100% rename from webapp/app/pods/components/acc-flash-message/component.ts rename to webapp/app/components/acc-flash-message/component.ts diff --git a/webapp/app/pods/components/acc-modal/component.ts b/webapp/app/components/acc-modal/component.ts similarity index 100% rename from webapp/app/pods/components/acc-modal/component.ts rename to webapp/app/components/acc-modal/component.ts diff --git a/webapp/app/pods/components/acc-select/component.ts b/webapp/app/components/acc-select/component.ts similarity index 100% rename from webapp/app/pods/components/acc-select/component.ts rename to webapp/app/components/acc-select/component.ts diff --git a/webapp/app/pods/components/activity-item/component.ts b/webapp/app/components/activity-item/component.ts similarity index 98% rename from webapp/app/pods/components/activity-item/component.ts rename to webapp/app/components/activity-item/component.ts index 3f5adc2c5..3c3f8a9b3 100644 --- a/webapp/app/pods/components/activity-item/component.ts +++ b/webapp/app/components/activity-item/component.ts @@ -28,7 +28,7 @@ const ACTIONS_ICON_PATHS = { remove: 'assets/x.svg', new_comment: 'assets/bubble.svg', new_slave: 'assets/language.svg', - document_delete: 'assets/file.svg', + document_delete: 'assets/file.svg' }; const MAXIMUM_COMPACT_BATCH_OPERATION_DOCUMENT_PATHS = 6; @@ -171,7 +171,7 @@ export default class ActivityItem extends Component { 'correct_all', 'batch_correct_conflict', 'batch_update', - 'conflict_on_slave', + 'conflict_on_slave' ]; return ( diff --git a/webapp/app/pods/components/activity-item/stats/component.ts b/webapp/app/components/activity-item/stats/component.ts similarity index 100% rename from webapp/app/pods/components/activity-item/stats/component.ts rename to webapp/app/components/activity-item/stats/component.ts diff --git a/webapp/app/pods/components/application-footer/component.ts b/webapp/app/components/application-footer/component.ts similarity index 100% rename from webapp/app/pods/components/application-footer/component.ts rename to webapp/app/components/application-footer/component.ts diff --git a/webapp/app/pods/components/async-button/component.ts b/webapp/app/components/async-button/component.ts similarity index 100% rename from webapp/app/pods/components/async-button/component.ts rename to webapp/app/components/async-button/component.ts diff --git a/webapp/app/pods/components/azure-push-form/component.ts b/webapp/app/components/azure-push-form/component.ts similarity index 91% rename from webapp/app/pods/components/azure-push-form/component.ts rename to webapp/app/components/azure-push-form/component.ts index ef532f5a2..f71d498a0 100644 --- a/webapp/app/pods/components/azure-push-form/component.ts +++ b/webapp/app/components/azure-push-form/component.ts @@ -7,7 +7,7 @@ interface Args { project: any; onPush: ({ targetVersion, - specificVersion, + specificVersion }: { targetVersion: string; specificVersion: string | null; @@ -19,18 +19,18 @@ export default class AzurePushForm extends Component { { value: 'LATEST', label: - 'components.project_settings.integrations.target_version.options.latest', + 'components.project_settings.integrations.target_version.options.latest' }, { value: 'SPECIFIC', label: - 'components.project_settings.integrations.target_version.options.specific', + 'components.project_settings.integrations.target_version.options.specific' }, { value: 'ALL', label: - 'components.project_settings.integrations.target_version.options.all', - }, + 'components.project_settings.integrations.target_version.options.all' + } ]; @tracked @@ -48,7 +48,7 @@ export default class AzurePushForm extends Component { await this.args.onPush({ targetVersion: this.targetVersion, - specificVersion: this.specificVersion, + specificVersion: this.specificVersion }); this.isSubmitting = false; diff --git a/webapp/app/pods/components/commit-file/component.ts b/webapp/app/components/commit-file/component.ts similarity index 97% rename from webapp/app/pods/components/commit-file/component.ts rename to webapp/app/components/commit-file/component.ts index b88d6cdb0..ba3828c7f 100644 --- a/webapp/app/pods/components/commit-file/component.ts +++ b/webapp/app/components/commit-file/component.ts @@ -19,7 +19,7 @@ const DEFAULT_PROPERTIES = { file: null, fileSource: null, documentPath: null, - documentFormat: 'json', + documentFormat: 'json' }; interface Args { @@ -140,7 +140,7 @@ export default class CommitFile extends Component { return this.args.revisions.map( ({id, language}: {id: string; language: {name: string}}) => ({ label: language.name, - value: id, + value: id }) ); } @@ -152,14 +152,14 @@ export default class CommitFile extends Component { get mappedMergeTypes() { return this.mergeTypes.map((name) => ({ label: name, - value: name, + value: name })); } get mappedSyncTypes() { return this.syncTypes.map((name) => ({ label: name, - value: name, + value: name })); } @@ -167,12 +167,12 @@ export default class CommitFile extends Component { return [ { label: this.intl.t('components.commit_file.no_version_label'), - value: null, + value: null }, ...this.args.versions.map(({id, tag}: {id: string; tag: string}) => ({ label: tag, - value: id, - })), + value: id + })) ]; } @@ -187,7 +187,7 @@ export default class CommitFile extends Component { return this.globalState.documentFormats.map(({slug, name}) => ({ value: slug, - label: name, + label: name })); } @@ -251,7 +251,7 @@ export default class CommitFile extends Component { revision: this.revision, mergeType: this.mergeType.value, syncType: this.syncType.value, - mergeOptions: this.correctOnMerge ? ['correct'] : [], + mergeOptions: this.correctOnMerge ? ['correct'] : [] }); this.onCommitingDone(); @@ -273,7 +273,7 @@ export default class CommitFile extends Component { version: this.version && this.version.tag, mergeType: this.mergeType.value, syncType: this.syncType.value, - mergeOptions: this.correctOnMerge ? ['correct'] : [], + mergeOptions: this.correctOnMerge ? ['correct'] : [] }); this.onPeekingDone(); diff --git a/webapp/app/pods/components/conflicts-filters/component.ts b/webapp/app/components/conflicts-filters/component.ts similarity index 53% rename from webapp/app/pods/components/conflicts-filters/component.ts rename to webapp/app/components/conflicts-filters/component.ts index d66fcf43a..4a6a5886f 100644 --- a/webapp/app/pods/components/conflicts-filters/component.ts +++ b/webapp/app/components/conflicts-filters/component.ts @@ -3,11 +3,9 @@ import {inject as service} from '@ember/service'; import {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 {PaginationMeta} from 'accent-webapp/components/resource-pagination/component'; import {tracked} from '@glimmer/tracking'; -import {restartableTask} from 'ember-concurrency-decorators'; -import {timeout} from 'ember-concurrency'; -import {perform} from 'ember-concurrency-ts'; +import {timeout, restartableTask} from 'ember-concurrency'; const DEBOUNCE_OFFSET = 1000; // ms @@ -16,12 +14,16 @@ interface Args { conflicts: any; document: any; documents: any; + relatedRevisions: any; + defaultRelatedRevisions: any[]; + revisions: any; version: any; versions: any; query: any; + withAdvancedFilters: boolean; onChangeDocument: () => void; - onChangeReference: () => void; onChangeVersion: () => void; + onChangeRevisions: () => void; onChangeQuery: (query: string) => void; } @@ -32,20 +34,29 @@ export default class ConflictsFilters extends Component { @gt('args.documents.length', 1) showDocumentsSelect: boolean; + @gt('args.revisions.length', 1) + showRevisionsSelect: boolean; + @gt('args.versions.length', 0) showVersionsSelect: boolean; + get showSomeFilters() { + return this.showDocumentsSelect || this.showVersionsSelect; + } + + @tracked + displayAdvancedFilters = this.args.withAdvancedFilters; + @tracked debouncedQuery = this.args.query; - @restartableTask - *debounceQuery(query: string) { + debounceQuery = restartableTask(async (query: string) => { this.debouncedQuery = query; - yield timeout(DEBOUNCE_OFFSET); + await timeout(DEBOUNCE_OFFSET); this.args.onChangeQuery(this.debouncedQuery); - } + }); get mappedDocuments() { if (!this.args.documents) return []; @@ -53,7 +64,7 @@ export default class ConflictsFilters extends Component { const documents = this.args.documents.map( ({id, path}: {id: string; path: string}) => ({ label: path, - value: id, + value: id }) ); @@ -61,12 +72,35 @@ export default class ConflictsFilters extends Component { label: this.intl.t( 'components.conflicts_filters.document_default_option_text' ), - value: '', + value: '' }); return documents; } + get relatedRevisionsValue() { + if (this.args.relatedRevisions.length === 0) { + const revisionIds = this.args.defaultRelatedRevisions.map( + ({id}: any) => id + ); + return this.mappedRevisions.filter(({value}: {value: string}) => + revisionIds.includes(value) + ); + } + + return this.mappedRevisions.filter(({value}: {value: string}) => + this.args.relatedRevisions?.includes(value) + ); + } + + get mappedRevisionsOptions() { + const values = this.relatedRevisionsValue.map(({value}: any) => value); + + return this.mappedRevisions.filter( + ({value}: {value: string}) => !values.includes(value) + ); + } + get documentValue() { return this.mappedDocuments.find( ({value}: {value: string}) => value === this.args.document @@ -77,7 +111,7 @@ export default class ConflictsFilters extends Component { const versions = this.args.versions.map( ({id, tag}: {id: string; tag: string}) => ({ label: tag, - value: id, + value: id }) ); @@ -85,12 +119,26 @@ export default class ConflictsFilters extends Component { label: this.intl.t( 'components.conflicts_filters.version_default_option_text' ), - value: '', + value: '' }); return versions; } + get mappedRevisions() { + return this.args.revisions.map( + (revision: { + id: string; + name: string | null; + slug: string | null; + language: {slug: string; name: string}; + }) => ({ + label: revision.name || revision.language.name, + value: revision.id + }) + ); + } + get versionValue() { return this.mappedVersions.find( ({value}: {value: string}) => value === this.args.version @@ -101,7 +149,12 @@ export default class ConflictsFilters extends Component { setDebouncedQuery(event: Event) { const target = event.target as HTMLInputElement; - perform(this.debounceQuery, target.value); + this.debounceQuery.perform(target.value); + } + + @action + toggleAdvancedFilters() { + this.displayAdvancedFilters = !this.displayAdvancedFilters; } @action diff --git a/webapp/app/components/conflicts-list/advanced-filters/component.ts b/webapp/app/components/conflicts-list/advanced-filters/component.ts new file mode 100644 index 000000000..1d2a10bd4 --- /dev/null +++ b/webapp/app/components/conflicts-list/advanced-filters/component.ts @@ -0,0 +1,21 @@ +import Component from '@glimmer/component'; + +interface Args { + revisions: any[]; + isTextEmptyFilter: boolean; + isTextNotEmptyFilter: boolean; + isAddedLastSyncFilter: boolean; + isNotTranslatedFilter: boolean; + isCommentedOnFilter: boolean; + onChangeAdvancedFilterBoolean: ( + key: + | 'isTextEmpty' + | 'isTextNotEmpty' + | 'isAddedLastSync' + | 'isCommentedOn' + | 'isNotTranslated', + event: InputEvent + ) => void; +} + +export default class AdvancedFilters extends Component {} diff --git a/webapp/app/components/conflicts-list/component.ts b/webapp/app/components/conflicts-list/component.ts new file mode 100644 index 000000000..d98f1cf58 --- /dev/null +++ b/webapp/app/components/conflicts-list/component.ts @@ -0,0 +1,58 @@ +import {tracked} from '@glimmer/tracking'; +import {action} from '@ember/object'; +import Component from '@glimmer/component'; + +interface Args { + permissions: Record; + project: any; + groupedTranslations: any; + version: any; + versions: any[]; + query: any; + onCorrect: (conflict: any, textInput: string) => Promise; + onCopyTranslation: ( + text: string, + sourceLanguageSlug: string, + targetLanguageSlug: string + ) => void; +} + +export default class ConflictsList extends Component { + @tracked + selectedTranslationId: string | null = null; + + get currentVersion() { + if (!this.args.versions) return; + if (!this.args.version) return; + + return this.args.versions.find( + (version) => version.id === this.args.version + ); + } + + get revisions() { + if (this.args.groupedTranslations.length === 0) return []; + + return this.args.groupedTranslations[0].translations.map( + ({revision}: any) => revision + ); + } + + get mappedRevisions() { + if (this.args.groupedTranslations.length === 0) return []; + + return this.args.groupedTranslations[0].translations.map( + ({revision}: any) => { + return { + name: revision.name || revision.language.name, + slug: revision.slug || revision.language.slug + }; + } + ); + } + + @action + handleFocus(id: string) { + this.selectedTranslationId = id; + } +} diff --git a/webapp/app/components/conflicts-list/group/component.ts b/webapp/app/components/conflicts-list/group/component.ts new file mode 100644 index 000000000..b24276351 --- /dev/null +++ b/webapp/app/components/conflicts-list/group/component.ts @@ -0,0 +1,29 @@ +import {action} from '@ember/object'; +import Component from '@glimmer/component'; +import parsedKeyProperty from 'accent-webapp/computed-macros/parsed-key'; + +interface Args { + selectedTranslationId: string | null; + groupedTranslation: { + key: string; + translations: any[]; + }; + onFocus: (id: string) => void; +} + +export default class ConflictsListGroup extends Component { + translationKey = parsedKeyProperty(this.args.groupedTranslation.key); + + get masterTranslation() { + return this.args.groupedTranslation.translations[0]; + } + + get isFocused() { + return this.masterTranslation.id === this.args.selectedTranslationId; + } + + @action + handleFocus() { + this.args.onFocus(this.masterTranslation.id); + } +} diff --git a/webapp/app/components/conflicts-list/item/component.ts b/webapp/app/components/conflicts-list/item/component.ts new file mode 100644 index 000000000..02ec285da --- /dev/null +++ b/webapp/app/components/conflicts-list/item/component.ts @@ -0,0 +1,192 @@ +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'; +import {MutationResponse} from 'accent-webapp/services/apollo-mutate'; + +interface Translation { + id: string; + key: string; + conflictedText: string; + correctedText: string; + isConflicted: boolean; + revision: { + name: string | null; + slug: string | null; + rtl: boolean | null; + isMaster: boolean; + language: { + name: string; + slug: string; + rtl: boolean; + }; + }; +} + +interface Args { + permissions: Record; + index: number; + project: any; + prompts: any[]; + translation: Translation; + onFocus: () => void; + onBlur: () => void; + onCorrect: (translation: any, textInput: string) => Promise; + onUpdate: (translation: any, textInput: string) => Promise; + onUncorrect: ( + translation: any, + textInput: string + ) => Promise; +} + +export default class ConflictsListItem extends Component { + @empty('args.translation.conflictedText') + emptyPreviousText: boolean; + + @tracked + textInput = this.args.translation.correctedText; + + @tracked + conflictResolved = false; + + @tracked + isCorrectLoading = false; + + @tracked + isUncorrectLoading = false; + + @tracked + isUpdateLoading = false; + + @tracked + error = false; + + @tracked + inputDisabled = false; + + translationKey = parsedKeyProperty(this.args.translation.key); + textOriginal = this.args.translation.correctedText; + + get showOriginalButton() { + return this.textInput !== this.textOriginal; + } + + get revisionTextDirRtl() { + return this.args.translation.revision.rtl !== null + ? this.args.translation.revision.rtl + : this.args.translation.revision.language.rtl; + } + + get revisionSlug() { + return ( + this.args.translation.revision.slug || + this.args.translation.revision.language.slug + ); + } + + @action + changeTranslationText(text: string) { + this.textInput = text; + } + + @action + setOriginalText() { + this.textInput = this.textOriginal; + } + + @action + onUpdatingText() { + this.inputDisabled = true; + } + + @action + onUpdateText(value: string) { + this.textInput = value; + this.inputDisabled = false; + } + + @action + async correctConflict() { + this.onCorrectLoading(); + + const response = await this.args.onCorrect( + this.args.translation, + this.textInput + ); + + if (response.errors) { + this.onError(); + } else { + this.onCorrectSuccess(); + } + } + + @action + async uncorrectConflict() { + this.onUncorrectLoading(); + + const response = await this.args.onUncorrect( + this.args.translation, + this.textInput + ); + + if (response.errors) { + this.onError(); + } else { + this.onUncorrectSuccess(); + } + } + + @action + async updateConflict() { + this.onUpdateLoading(); + + const response = await this.args.onUpdate( + this.args.translation, + this.textInput + ); + + if (response.errors) { + this.onError(); + } else { + this.onUpdateSuccess(); + } + } + + private onCorrectLoading() { + this.error = false; + this.isCorrectLoading = true; + } + + private onUncorrectLoading() { + this.error = false; + this.isUncorrectLoading = true; + } + + private onUpdateLoading() { + this.error = false; + this.isUpdateLoading = true; + } + + private onError() { + this.error = true; + this.isUpdateLoading = false; + this.isCorrectLoading = false; + this.isUncorrectLoading = false; + } + + private onCorrectSuccess() { + this.conflictResolved = true; + this.isCorrectLoading = false; + } + + private onUncorrectSuccess() { + this.conflictResolved = false; + this.isCorrectLoading = false; + } + + private onUpdateSuccess() { + this.isUpdateLoading = false; + } +} diff --git a/webapp/app/pods/components/dashboard-revisions/component.ts b/webapp/app/components/dashboard-revisions/component.ts similarity index 100% rename from webapp/app/pods/components/dashboard-revisions/component.ts rename to webapp/app/components/dashboard-revisions/component.ts diff --git a/webapp/app/pods/components/dashboard-revisions/item/component.ts b/webapp/app/components/dashboard-revisions/item/component.ts similarity index 94% rename from webapp/app/pods/components/dashboard-revisions/item/component.ts rename to webapp/app/components/dashboard-revisions/item/component.ts index a3749ef1c..2db73b43c 100644 --- a/webapp/app/pods/components/dashboard-revisions/item/component.ts +++ b/webapp/app/components/dashboard-revisions/item/component.ts @@ -58,10 +58,10 @@ export default class DashboardRevisionsItem extends Component { ); } - get reviewsCount() { - const {conflictsCount, translationsCount} = this.args.revision; + get toReviewCount() { + const {reviewedCount, translationsCount} = this.args.revision; - return translationsCount - conflictsCount; + return translationsCount - reviewedCount; } get languageName() { diff --git a/webapp/app/pods/components/date-tag/component.ts b/webapp/app/components/date-tag/component.ts similarity index 94% rename from webapp/app/pods/components/date-tag/component.ts rename to webapp/app/components/date-tag/component.ts index 6df8d1aa1..498ada246 100644 --- a/webapp/app/pods/components/date-tag/component.ts +++ b/webapp/app/components/date-tag/component.ts @@ -1,6 +1,6 @@ import {inject as service} from '@ember/service'; import Component from '@glimmer/component'; -import dateFormat from 'date-fns/format'; +import {format as dateFormat} from 'date-fns'; import IntlService from 'ember-intl/services/intl'; interface Args { diff --git a/webapp/app/pods/components/documents-add-button/component.ts b/webapp/app/components/documents-add-button/component.ts similarity index 100% rename from webapp/app/pods/components/documents-add-button/component.ts rename to webapp/app/components/documents-add-button/component.ts diff --git a/webapp/app/pods/components/documents-list/component.ts b/webapp/app/components/documents-list/component.ts similarity index 100% rename from webapp/app/pods/components/documents-list/component.ts rename to webapp/app/components/documents-list/component.ts diff --git a/webapp/app/pods/components/documents-list/item/component.ts b/webapp/app/components/documents-list/item/component.ts similarity index 100% rename from webapp/app/pods/components/documents-list/item/component.ts rename to webapp/app/components/documents-list/item/component.ts diff --git a/webapp/app/pods/components/documents-machine-translations-button/component.ts b/webapp/app/components/documents-machine-translations-button/component.ts similarity index 100% rename from webapp/app/pods/components/documents-machine-translations-button/component.ts rename to webapp/app/components/documents-machine-translations-button/component.ts diff --git a/webapp/app/pods/components/dummy-login-form/component.ts b/webapp/app/components/dummy-login-form/component.ts similarity index 100% rename from webapp/app/pods/components/dummy-login-form/component.ts rename to webapp/app/components/dummy-login-form/component.ts diff --git a/webapp/app/pods/components/empty-content/component.ts b/webapp/app/components/empty-content/component.ts similarity index 100% rename from webapp/app/pods/components/empty-content/component.ts rename to webapp/app/components/empty-content/component.ts diff --git a/webapp/app/pods/components/error-section/component.ts b/webapp/app/components/error-section/component.ts similarity index 100% rename from webapp/app/pods/components/error-section/component.ts rename to webapp/app/components/error-section/component.ts diff --git a/webapp/app/pods/components/file-export-all/component.ts b/webapp/app/components/file-export-all/component.ts similarity index 94% rename from webapp/app/pods/components/file-export-all/component.ts rename to webapp/app/components/file-export-all/component.ts index 1a98440a1..a8049449c 100644 --- a/webapp/app/pods/components/file-export-all/component.ts +++ b/webapp/app/components/file-export-all/component.ts @@ -41,8 +41,8 @@ export default class FileExport extends Component { filters: { isTextEmptyFilter: this.args.isTextEmptyFilter, isAddedLastSyncFilter: this.args.isAddedLastSyncFilter, - isConflictedFilter: this.args.isConflictedFilter, - }, + isConflictedFilter: this.args.isConflictedFilter + } }); this.content = data; diff --git a/webapp/app/pods/components/file-export/component.ts b/webapp/app/components/file-export/component.ts similarity index 95% rename from webapp/app/pods/components/file-export/component.ts rename to webapp/app/components/file-export/component.ts index 738b494c4..f6b013f3c 100644 --- a/webapp/app/pods/components/file-export/component.ts +++ b/webapp/app/components/file-export/component.ts @@ -43,8 +43,8 @@ export default class FileExport extends Component { filters: { isTextEmptyFilter: this.args.isTextEmptyFilter, isAddedLastSyncFilter: this.args.isAddedLastSyncFilter, - isConflictedFilter: this.args.isConflictedFilter, - }, + isConflictedFilter: this.args.isConflictedFilter + } }); this.content = data; diff --git a/webapp/app/pods/components/file-input/component.ts b/webapp/app/components/file-input/component.ts similarity index 100% rename from webapp/app/pods/components/file-input/component.ts rename to webapp/app/components/file-input/component.ts diff --git a/webapp/app/pods/components/flash-messages-list/component.ts b/webapp/app/components/flash-messages-list/component.ts similarity index 100% rename from webapp/app/pods/components/flash-messages-list/component.ts rename to webapp/app/components/flash-messages-list/component.ts diff --git a/webapp/app/pods/components/highlight-render/component.ts b/webapp/app/components/highlight-render/component.ts similarity index 98% rename from webapp/app/pods/components/highlight-render/component.ts rename to webapp/app/components/highlight-render/component.ts index f77081b8e..76deca1d7 100644 --- a/webapp/app/pods/components/highlight-render/component.ts +++ b/webapp/app/components/highlight-render/component.ts @@ -3,7 +3,7 @@ import {action} from '@ember/object'; import hljs from 'highlight.js'; hljs.configure({ - languages: ['javascript', 'json', 'php', 'xml', 'yaml', 'properties'], + languages: ['javascript', 'json', 'php', 'xml', 'yaml', 'properties'] }); interface Args { diff --git a/webapp/app/pods/components/html-textarea/component.ts b/webapp/app/components/html-textarea/component.ts similarity index 82% rename from webapp/app/pods/components/html-textarea/component.ts rename to webapp/app/components/html-textarea/component.ts index 0daec3834..119310383 100644 --- a/webapp/app/pods/components/html-textarea/component.ts +++ b/webapp/app/components/html-textarea/component.ts @@ -1,9 +1,7 @@ import {action} from '@ember/object'; import Component from '@glimmer/component'; import pell from 'pell'; -import {restartableTask} from 'ember-concurrency-decorators'; -import {timeout} from 'ember-concurrency'; -import {perform} from 'ember-concurrency-ts'; +import {timeout, restartableTask} from 'ember-concurrency'; const DEBOUNCE_OFFSET = 1000; // ms @@ -54,12 +52,12 @@ export default class HTMLTextarea extends Component { { icon: '✗', title: 'Clear', - result: clear(pell), - }, + result: clear(pell) + } ], onChange: (text) => { - perform(this.debounceChange, text); - }, + this.debounceChangeTask.perform(text); + } }); this.content = pellInstance.querySelector('.pell-content'); @@ -75,10 +73,9 @@ export default class HTMLTextarea extends Component { } } - @restartableTask - *debounceChange(text: string) { - yield timeout(DEBOUNCE_OFFSET); + debounceChangeTask = restartableTask(async (text: string) => { + await timeout(DEBOUNCE_OFFSET); this.args.onChange(text); - } + }); } diff --git a/webapp/app/pods/components/improve-prompt/component.ts b/webapp/app/components/improve-prompt/component.ts similarity index 83% rename from webapp/app/pods/components/improve-prompt/component.ts rename to webapp/app/components/improve-prompt/component.ts index 3c89e8c03..69cfebc1b 100644 --- a/webapp/app/pods/components/improve-prompt/component.ts +++ b/webapp/app/components/improve-prompt/component.ts @@ -2,8 +2,7 @@ import Component from '@glimmer/component'; import {inject as service} from '@ember/service'; import {action} from '@ember/object'; import {tracked} from '@glimmer/tracking'; -import {dropTask} from 'ember-concurrency-decorators'; -import {taskFor} from 'ember-concurrency-ts'; +import {dropTask} from 'ember-concurrency'; import Apollo from 'accent-webapp/services/apollo'; import improveTextPromptMutation from 'accent-webapp/queries/improve-text-prompt'; @@ -44,7 +43,7 @@ export default class ImprovePrompt extends Component { promptOpened = false; get isSubmitting() { - return taskFor(this.submitTask).isRunning; + return this.submitTask.isRunning; } @action @@ -64,23 +63,22 @@ export default class ImprovePrompt extends Component { this.promptOpened = false; } - @dropTask - *fetchPromptOptions() { + fetchPromptOptions = dropTask(async () => { const variables = {projectId: this.args.project.id}; - const {data} = yield this.apollo.client.query({ + const {data} = await this.apollo.client.query({ query: projectPrompts, fetchPolicy: 'network-only', - variables, + variables }); if (!data.viewer.project.prompts) return; this.promptOptions = data.viewer.project.prompts.map((prompt: Prompt) => ({ label: prompt.name, - value: prompt.id, + value: prompt.id })); this.promptOptionValue = this.promptOptions[0]; - } + }); @action onPromptClose() { @@ -93,8 +91,7 @@ export default class ImprovePrompt extends Component { this.promptOpened = true; } - @dropTask - *submitTask(promptId?: string) { + submitTask = dropTask(async (promptId?: string) => { if (!promptId && !this.promptOptionValue) return; if (!this.promptOpened) this.args.onUpdatingText(); @@ -102,11 +99,11 @@ export default class ImprovePrompt extends Component { const variables = { text: this.args.text, - promptId: promptId || this.promptOptionValue?.value, + promptId: promptId || this.promptOptionValue?.value }; - const {data} = yield this.apollo.client.mutate({ + const {data} = await this.apollo.client.mutate({ mutation: improveTextPromptMutation, - variables, + variables }); if (data.improveTextWithPrompt?.text) { @@ -116,5 +113,5 @@ export default class ImprovePrompt extends Component { this.args.onUpdateText(data.improveTextWithPrompt.text); } } - } + }); } diff --git a/webapp/app/pods/components/inline-machine-translate/component.ts b/webapp/app/components/inline-machine-translate/component.ts similarity index 72% rename from webapp/app/pods/components/inline-machine-translate/component.ts rename to webapp/app/components/inline-machine-translate/component.ts index a2ebb7b64..5f2e7d5eb 100644 --- a/webapp/app/pods/components/inline-machine-translate/component.ts +++ b/webapp/app/components/inline-machine-translate/component.ts @@ -1,7 +1,6 @@ import Component from '@glimmer/component'; import {inject as service} from '@ember/service'; -import {dropTask} from 'ember-concurrency-decorators'; -import {taskFor} from 'ember-concurrency-ts'; +import {dropTask} from 'ember-concurrency'; import Apollo from 'accent-webapp/services/apollo'; import projectTranslateTextQuery from 'accent-webapp/queries/translate-text-project'; @@ -18,26 +17,25 @@ export default class ImprovePrompt extends Component { apollo: Apollo; get isSubmitting() { - return taskFor(this.submitTask).isRunning; + return this.submitTask.isRunning; } - @dropTask - *submitTask(targetLanguageSlug: string) { + submitTask = dropTask(async (targetLanguageSlug: string) => { this.args.onUpdatingText(); const variables = { projectId: this.args.project.id, text: this.args.text, - targetLanguageSlug, + targetLanguageSlug }; - const {data} = yield this.apollo.client.query({ + const {data} = await this.apollo.client.query({ query: projectTranslateTextQuery, - variables, + variables }); if (data.viewer.project.translatedText?.text) { this.args.onUpdateText(data.viewer.project.translatedText?.text); } - } + }); } diff --git a/webapp/app/pods/components/jipt-back-to-translations/component.ts b/webapp/app/components/jipt-back-to-translations/component.ts similarity index 100% rename from webapp/app/pods/components/jipt-back-to-translations/component.ts rename to webapp/app/components/jipt-back-to-translations/component.ts diff --git a/webapp/app/components/jipt-example/component.ts b/webapp/app/components/jipt-example/component.ts new file mode 100644 index 000000000..d5cd1ca2c --- /dev/null +++ b/webapp/app/components/jipt-example/component.ts @@ -0,0 +1,40 @@ +import Component from '@glimmer/component'; + +interface ArgsTranslation { + key: string; + document: { + path: string; + }; +} + +interface Args { + project: { + id: string; + name: string; + revision: { + translations: { + entries: ArgsTranslation[]; + }; + }; + }; +} + +export default class JIPTExample extends Component { + get scriptSrc() { + return `${window.location.origin}/static/jipt/index.js`; + } + + get imageSrc() { + return 'data:image/jpeg;base64,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'; + } + + get scriptContent() { + return `window.accent=window.accent||function(){(accent.q=accent.q||[]).push(arguments);}; + accent('init',{h:'${window.location.origin}',i:'${this.args.project.id}'});`; + } + + get translationKey() { + const translation = this.args.project.revision.translations.entries[0]; + return `{^${translation.key}@${translation.document.path}}`; + } +} diff --git a/webapp/app/pods/components/jipt-export/component.ts b/webapp/app/components/jipt-export/component.ts similarity index 93% rename from webapp/app/pods/components/jipt-export/component.ts rename to webapp/app/components/jipt-export/component.ts index c0d5634b2..deedae82d 100644 --- a/webapp/app/pods/components/jipt-export/component.ts +++ b/webapp/app/components/jipt-export/component.ts @@ -25,7 +25,7 @@ export default class JIPTExport extends Component { project: this.args.project, document: this.args.document, version: this.args.version, - documentFormat: this.args.documentFormat, + documentFormat: this.args.documentFormat }); this.content = data; diff --git a/webapp/app/pods/components/jipt-header/component.ts b/webapp/app/components/jipt-header/component.ts similarity index 100% rename from webapp/app/pods/components/jipt-header/component.ts rename to webapp/app/components/jipt-header/component.ts diff --git a/webapp/app/pods/components/jipt-translations-filtered-title/component.ts b/webapp/app/components/jipt-translations-filtered-title/component.ts similarity index 100% rename from webapp/app/pods/components/jipt-translations-filtered-title/component.ts rename to webapp/app/components/jipt-translations-filtered-title/component.ts diff --git a/webapp/app/pods/components/jipt-translations-list/component.ts b/webapp/app/components/jipt-translations-list/component.ts similarity index 100% rename from webapp/app/pods/components/jipt-translations-list/component.ts rename to webapp/app/components/jipt-translations-list/component.ts diff --git a/webapp/app/pods/components/jipt-translations-list/item/component.ts b/webapp/app/components/jipt-translations-list/item/component.ts similarity index 100% rename from webapp/app/pods/components/jipt-translations-list/item/component.ts rename to webapp/app/components/jipt-translations-list/item/component.ts diff --git a/webapp/app/pods/components/lint-options/component.ts b/webapp/app/components/lint-options/component.ts similarity index 81% rename from webapp/app/pods/components/lint-options/component.ts rename to webapp/app/components/lint-options/component.ts index dea52f161..cf0508a09 100644 --- a/webapp/app/pods/components/lint-options/component.ts +++ b/webapp/app/components/lint-options/component.ts @@ -1,13 +1,10 @@ import {action} from '@ember/object'; import {inject as service} from '@ember/service'; -import {gt} 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'; -import {restartableTask} from 'ember-concurrency-decorators'; -import {timeout} from 'ember-concurrency'; -import {perform} from 'ember-concurrency-ts'; +import {timeout, restartableTask} from 'ember-concurrency'; const DEBOUNCE_OFFSET = 1000; // ms @@ -30,23 +27,28 @@ export default class RevisionExportOptions extends Component { @service('global-state') globalState: GlobalState; - @gt('mappedDocuments.length', 1) - showDocuments: boolean; + get showDocuments() { + return this.mappedDocuments.length > 1; + } - @gt('mappedVersions.length', 1) - showVersions: boolean; + get showVersions() { + return this.mappedVersions.length > 1; + } + + get showSomeFilters() { + return this.showDocuments || this.showVersions; + } @tracked debouncedQuery = this.args.query; - @restartableTask - *debounceQuery(query: string) { + debounceQuery = restartableTask(async (query: string) => { this.debouncedQuery = query; - yield timeout(DEBOUNCE_OFFSET); + await timeout(DEBOUNCE_OFFSET); this.args.onChangeQuery(this.debouncedQuery); - } + }); get documentValue() { return ( @@ -62,7 +64,7 @@ export default class RevisionExportOptions extends Component { return this.args.documents.map( ({id, path}: {id: string; path: string}) => ({ label: path, - value: id, + value: id }) ); } @@ -81,16 +83,16 @@ export default class RevisionExportOptions extends Component { memo.concat([ { label: tag, - value: tag, - }, + value: tag + } ]), [ { label: this.intl.t( 'components.revision_export_options.default_version' ), - value: '', - }, + value: '' + } ] ); } @@ -113,7 +115,7 @@ export default class RevisionExportOptions extends Component { setDebouncedQuery(event: Event) { const target = event.target as HTMLInputElement; - perform(this.debounceQuery, target.value); + this.debounceQuery.perform(target.value); } @action diff --git a/webapp/app/components/lint-translations-page/component.ts b/webapp/app/components/lint-translations-page/component.ts new file mode 100644 index 000000000..68f91595d --- /dev/null +++ b/webapp/app/components/lint-translations-page/component.ts @@ -0,0 +1,68 @@ +import {inject as service} from '@ember/service'; +import {tracked} from '@glimmer/tracking'; +import Component from '@glimmer/component'; +import {restartableTask} from 'ember-concurrency'; +import translationUpdateQuery from 'accent-webapp/queries/update-translation'; +import Apollo from 'accent-webapp/services/apollo'; + +interface Args { + project: any; + lintTranslations: any[]; + permissions: Record; +} + +interface Stat { + title: string; + count: number; +} + +export default class LintTranslationsPage extends Component { + @service('apollo') + apollo: Apollo; + + @tracked + fixLintMessageRunningTranslationId: string | null = null; + + get lintTranslationsStatsCount() { + return this.lintTranslationsStats.reduce( + (total, stat) => stat.count + total, + 0 + ); + } + + get lintTranslationsStats() { + const stats = this.args.lintTranslations.reduce((acc, lintTranslation) => { + lintTranslation.messages.forEach((message: {check: string}) => { + if (acc[message.check]) { + acc[message.check]++; + } else { + acc[message.check] = 1; + } + }); + + return acc; + }, {}); + + return Object.entries(stats).map(([title, count]) => ({ + title, + count + })) as Stat[]; + } + + fixLintMessageTask = restartableTask( + async (translation: {id: string}, message: any) => { + this.fixLintMessageRunningTranslationId = translation.id; + + await this.apollo.client.mutate({ + mutation: translationUpdateQuery, + refetchQueries: ['Lint'], + variables: { + text: message.replacement.value, + translationId: translation.id + } + }); + + this.fixLintMessageRunningTranslationId = null; + } + ); +} diff --git a/webapp/app/pods/components/lint-translations-page/item/component.ts b/webapp/app/components/lint-translations-page/item/component.ts similarity index 85% rename from webapp/app/pods/components/lint-translations-page/item/component.ts rename to webapp/app/components/lint-translations-page/item/component.ts index b9ae443f3..545cf6eee 100644 --- a/webapp/app/pods/components/lint-translations-page/item/component.ts +++ b/webapp/app/components/lint-translations-page/item/component.ts @@ -4,10 +4,11 @@ import parsedKeyProperty from 'accent-webapp/computed-macros/parsed-key'; interface Args { lintTranslation: any; project: any; + fix?: (lintTranslation: any, message: any) => void; } const escape = document.createElement('textarea'); -const escapeHTML = (html: string) => { +const escapeHTML = (html: string): string => { escape.textContent = html; return escape.innerHTML; }; @@ -15,6 +16,14 @@ const escapeHTML = (html: string) => { export default class LintTranslationsPageItem extends Component { translationKey = parsedKeyProperty(this.args.lintTranslation.translation.key); + get allReplacable() { + return this.args.lintTranslation.messages.every( + (message: {replacement: object | null}) => { + return Boolean(message.replacement); + } + ); + } + get messages() { const mapSet = new Set(); return this.args.lintTranslation.messages.flatMap((message: any) => { @@ -30,7 +39,7 @@ export default class LintTranslationsPageItem extends Component { get annotatedText() { let offsetTotal = 0; - let text = this.args.lintTranslation.messages + let text = Array.from(this.args.lintTranslation.messages) .sort((a: any, b: any) => a.offset || 0 >= b.offset || 0) .reduce((text: string, message: any) => { if (message.length) { @@ -64,7 +73,7 @@ export default class LintTranslationsPageItem extends Component { } else { return text; } - }, this.args.lintTranslation.messages[0].text); + }, this.args.lintTranslation.messages[0].text) as string; text = escapeHTML(text); text = text.replaceAll('(span data-underline)', ''); diff --git a/webapp/app/pods/components/loading-content/component.ts b/webapp/app/components/loading-content/component.ts similarity index 100% rename from webapp/app/pods/components/loading-content/component.ts rename to webapp/app/components/loading-content/component.ts diff --git a/webapp/app/pods/components/login-forms/component.ts b/webapp/app/components/login-forms/component.ts similarity index 93% rename from webapp/app/pods/components/login-forms/component.ts rename to webapp/app/components/login-forms/component.ts index 2e1c168c1..66f6fb1c4 100644 --- a/webapp/app/pods/components/login-forms/component.ts +++ b/webapp/app/components/login-forms/component.ts @@ -21,6 +21,7 @@ export default class LoginForms extends Component { discordUrl = `${config.API.AUTHENTICATION_PATH}/discord`; microsoftUrl = `${config.API.AUTHENTICATION_PATH}/microsoft`; auth0Url = `${config.API.AUTHENTICATION_PATH}/auth0`; + oidcUrl = `${config.API.AUTHENTICATION_PATH}/oidc`; get version() { return config.version === '__VERSION__' ? 'dev' : config.version; @@ -62,6 +63,10 @@ export default class LoginForms extends Component { return this.providerIds.includes('microsoft'); } + get oidcLoginEnabled() { + return this.providerIds.includes('oidc'); + } + get dummyUrl() { return `${config.API.AUTHENTICATION_PATH}/dummy/callback?email=${this.username}`; } diff --git a/webapp/app/pods/components/machine-translations-document-translate/component.ts b/webapp/app/components/machine-translations-document-translate/component.ts similarity index 92% rename from webapp/app/pods/components/machine-translations-document-translate/component.ts rename to webapp/app/components/machine-translations-document-translate/component.ts index 53851623f..ed860ff76 100644 --- a/webapp/app/pods/components/machine-translations-document-translate/component.ts +++ b/webapp/app/components/machine-translations-document-translate/component.ts @@ -3,11 +3,10 @@ import {inject as service} from '@ember/service'; import {action} from '@ember/object'; import {tracked} from '@glimmer/tracking'; import {htmlSafe} from '@ember/template'; -import {dropTask} from 'ember-concurrency-decorators'; +import {dropTask} from 'ember-concurrency'; import GlobalState from 'accent-webapp/services/global-state'; import LanguageSearcher from 'accent-webapp/services/language-searcher'; import FileSaver from 'accent-webapp/services/file-saver'; -import {taskFor} from 'ember-concurrency-ts'; import Exporter from 'accent-webapp/services/exporter'; interface Project { @@ -40,7 +39,7 @@ interface Args { fromLanguage: string, toLanguage: string, documentFormat: string - ) => void; + ) => Promise; } export default class MachineTranslationsTranslateUploadForm extends Component { @@ -79,7 +78,7 @@ export default class MachineTranslationsTranslateUploadForm extends Component ({ value: slug, - label: name, + label: name })); } @@ -133,7 +132,7 @@ export default class MachineTranslationsTranslateUploadForm extends Component { + await this.renderDocument(); if (this.sameLanguages) return; - yield this.args.onTranslate( + await this.args.onTranslate( this.fromRevision.value, this.toRevision.value, this.documentFormat.value ); - } + }); @action async renderDocument() { @@ -173,7 +171,7 @@ export default class MachineTranslationsTranslateUploadForm extends Component void; + onFileReset: () => Promise; onFileChange: ( file: File, fromLanguage: string, toLanguage: string, documentFormat: string - ) => void; + ) => Promise; } const preventDefault = (event: Event) => event.preventDefault(); @@ -60,7 +59,7 @@ export default class MachineTranslationsTranslateUploadForm extends Component ({ value: slug, - label: name, + label: name })); } @@ -99,11 +98,10 @@ export default class MachineTranslationsTranslateUploadForm extends Component { this.fileContent = null; - yield this.args.onFileReset(); + await this.args.onFileReset(); this.file = files[0]; @@ -120,7 +118,7 @@ export default class MachineTranslationsTranslateUploadForm extends Component { if (!this.file) return; - yield this.args.onFileChange( + await this.args.onFileChange( this.file, this.fromLanguage.value, this.toLanguage.value, this.documentFormat.value ); - } + }); @action exportFile() { if (!this.file || !this.args.translatedFileContent) return; const blob = new Blob([this.args.translatedFileContent as BlobPart], { - type: 'charset=utf-8', + type: 'charset=utf-8' }); this.fileSaver.saveAs(blob, this.file.name); diff --git a/webapp/app/pods/components/operations-peek/component.ts b/webapp/app/components/operations-peek/component.ts similarity index 96% rename from webapp/app/pods/components/operations-peek/component.ts rename to webapp/app/components/operations-peek/component.ts index 2cea413c7..2492f1b00 100644 --- a/webapp/app/pods/components/operations-peek/component.ts +++ b/webapp/app/components/operations-peek/component.ts @@ -14,7 +14,7 @@ export default class RevisionOperations extends Component { return this.args.revisionOperations.map((revisionOperation: any) => { return { label: revisionOperation.language.name, - value: revisionOperation.language.id, + value: revisionOperation.language.id }; }); } diff --git a/webapp/app/pods/components/operations-peek/item/component.ts b/webapp/app/components/operations-peek/item/component.ts similarity index 100% rename from webapp/app/pods/components/operations-peek/item/component.ts rename to webapp/app/components/operations-peek/item/component.ts diff --git a/webapp/app/pods/components/phoenix-channel-listener/component.ts b/webapp/app/components/phoenix-channel-listener/component.ts similarity index 100% rename from webapp/app/pods/components/phoenix-channel-listener/component.ts rename to webapp/app/components/phoenix-channel-listener/component.ts diff --git a/webapp/app/pods/components/project-activities-filter/component.ts b/webapp/app/components/project-activities-filter/component.ts similarity index 94% rename from webapp/app/pods/components/project-activities-filter/component.ts rename to webapp/app/components/project-activities-filter/component.ts index c3092a052..fc6138b49 100644 --- a/webapp/app/pods/components/project-activities-filter/component.ts +++ b/webapp/app/components/project-activities-filter/component.ts @@ -37,7 +37,7 @@ export default class ProjectActivitiesFilter extends Component { 'conflict_on_proposed', 'conflict_on_corrected', 'conflict_on_slave', - 'document_delete', + 'document_delete' ]; get mappedActions() { @@ -45,7 +45,7 @@ export default class ProjectActivitiesFilter extends Component { (key) => { return { value: key, - label: this.intl.t(`${ACTIONS_PREFIX}${key}`), + label: this.intl.t(`${ACTIONS_PREFIX}${key}`) }; } ); @@ -54,7 +54,7 @@ export default class ProjectActivitiesFilter extends Component { label: this.intl.t( 'components.project_activities_filter.actions_default_option_text' ), - value: '', + value: '' }); return actions; @@ -67,14 +67,14 @@ export default class ProjectActivitiesFilter extends Component { .filter((collaborator: any) => !collaborator.isPending) .map(({user: {fullname, id}}: {user: any}) => ({ label: fullname, - value: id, + value: id })); users.unshift({ label: this.intl.t( 'components.project_activities_filter.collaborators_default_option_text' ), - value: '', + value: '' }); return users; @@ -86,7 +86,7 @@ export default class ProjectActivitiesFilter extends Component { const versions = this.args.versions.map( ({tag, id}: {tag: string; id: string}) => ({ label: tag, - value: id, + value: id }) ); @@ -94,7 +94,7 @@ export default class ProjectActivitiesFilter extends Component { label: this.intl.t( 'components.project_activities_filter.versions_default_option_text' ), - value: '', + value: '' }); return versions; diff --git a/webapp/app/pods/components/project-activities-list/component.ts b/webapp/app/components/project-activities-list/component.ts similarity index 100% rename from webapp/app/pods/components/project-activities-list/component.ts rename to webapp/app/components/project-activities-list/component.ts diff --git a/webapp/app/pods/components/project-activity/component.ts b/webapp/app/components/project-activity/component.ts similarity index 98% rename from webapp/app/pods/components/project-activity/component.ts rename to webapp/app/components/project-activity/component.ts index 2678f7cf6..f7216c576 100644 --- a/webapp/app/pods/components/project-activity/component.ts +++ b/webapp/app/components/project-activity/component.ts @@ -23,7 +23,7 @@ const ROLLBACKABLE_ACTIONS = [ 'conflict_on_corrected', 'conflict_on_proposed', 'merge_on_proposed', - 'merge_on_corrected', + 'merge_on_corrected' ]; interface Args { @@ -169,12 +169,12 @@ export default class ProjectActivity extends Component { const variables = { projectId: this.args.project.id, activityId: this.args.activity.id, - page, + page }; const {data} = await this.apollo.client.query({ query: activityActivitiesQuery, - variables, + variables }); const operations = data.viewer.project.activity.operations; diff --git a/webapp/app/pods/components/project-comments-list/component.ts b/webapp/app/components/project-comments-list/component.ts similarity index 95% rename from webapp/app/pods/components/project-comments-list/component.ts rename to webapp/app/components/project-comments-list/component.ts index 3c5739a1b..7123b4664 100644 --- a/webapp/app/pods/components/project-comments-list/component.ts +++ b/webapp/app/components/project-comments-list/component.ts @@ -34,7 +34,7 @@ export default class ProjectCommentsList extends Component { return Object.keys(this.commentsByTranslationId).map((translationId) => { return { items: this.commentsByTranslationId[translationId], - value: this.translationsById[translationId], + value: this.translationsById[translationId] }; }); } diff --git a/webapp/app/pods/components/project-comments-list/item/component.ts b/webapp/app/components/project-comments-list/item/component.ts similarity index 100% rename from webapp/app/pods/components/project-comments-list/item/component.ts rename to webapp/app/components/project-comments-list/item/component.ts diff --git a/webapp/app/pods/components/project-create-form/component.ts b/webapp/app/components/project-create-form/component.ts similarity index 96% rename from webapp/app/pods/components/project-create-form/component.ts rename to webapp/app/components/project-create-form/component.ts index 02a6c1ccb..ffdcae552 100644 --- a/webapp/app/pods/components/project-create-form/component.ts +++ b/webapp/app/components/project-create-form/component.ts @@ -13,7 +13,7 @@ interface Args { languageId, name, mainColor, - logo, + logo }: { languageId: string; name: string; @@ -60,8 +60,8 @@ export default class ProjectCreateForm extends Component { } @action - logoPicked(selection: {emoji: string}) { - this.logo = selection.emoji; + logoPicked(selection: string) { + this.logo = selection; } @action diff --git a/webapp/app/pods/components/project-file-operation/component.ts b/webapp/app/components/project-file-operation/component.ts similarity index 100% rename from webapp/app/pods/components/project-file-operation/component.ts rename to webapp/app/components/project-file-operation/component.ts diff --git a/webapp/app/pods/components/project-header/component.ts b/webapp/app/components/project-header/component.ts similarity index 81% rename from webapp/app/pods/components/project-header/component.ts rename to webapp/app/components/project-header/component.ts index e972db1a2..774eae29b 100644 --- a/webapp/app/pods/components/project-header/component.ts +++ b/webapp/app/components/project-header/component.ts @@ -5,9 +5,7 @@ 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'; -import {perform} from 'ember-concurrency-ts'; +import {timeout, restartableTask} from 'ember-concurrency'; const DEBOUNCE_OFFSET = 500; // ms @@ -45,28 +43,27 @@ export default class ProjectsHeader extends Component { return this.args.project.revisions[0].id; } - @restartableTask - *debounceQuery(query: string) { + debounceQuery = restartableTask(async (query: string) => { this.debouncedQuery = query; if (!this.debouncedQuery) return; - yield timeout(DEBOUNCE_OFFSET); + await timeout(DEBOUNCE_OFFSET); this.router.transitionTo( 'logged-in.project.revision.translations', this.args.project.id, this.selectedRevision, { - queryParams: {query}, + queryParams: {query} } ); - } + }); @action setDebouncedQuery(event: Event) { const target = event.target as HTMLInputElement; - perform(this.debounceQuery, target.value); + this.debounceQuery.perform(target.value); } @action diff --git a/webapp/app/pods/components/project-logo/component.ts b/webapp/app/components/project-logo/component.ts similarity index 100% rename from webapp/app/pods/components/project-logo/component.ts rename to webapp/app/components/project-logo/component.ts diff --git a/webapp/app/pods/components/project-navigation/component.ts b/webapp/app/components/project-navigation/component.ts similarity index 100% rename from webapp/app/pods/components/project-navigation/component.ts rename to webapp/app/components/project-navigation/component.ts diff --git a/webapp/app/pods/components/project-navigation/list/component.ts b/webapp/app/components/project-navigation/list/component.ts similarity index 100% rename from webapp/app/pods/components/project-navigation/list/component.ts rename to webapp/app/components/project-navigation/list/component.ts diff --git a/webapp/app/pods/components/project-settings/api-token/component.ts b/webapp/app/components/project-settings/api-token/component.ts similarity index 89% rename from webapp/app/pods/components/project-settings/api-token/component.ts rename to webapp/app/components/project-settings/api-token/component.ts index 3853d2a85..163a7196b 100644 --- a/webapp/app/pods/components/project-settings/api-token/component.ts +++ b/webapp/app/components/project-settings/api-token/component.ts @@ -3,7 +3,6 @@ import {inject as service} from '@ember/service'; import {action} from '@ember/object'; import {tracked} from '@glimmer/tracking'; import {dropTask} from 'ember-concurrency'; -import {taskFor} from 'ember-concurrency-ts'; import IntlService from 'ember-intl/services/intl'; import {CreateApiTokenResponse} from 'accent-webapp/queries/create-api-token'; @@ -14,7 +13,7 @@ interface Args { name: string; pictureUrl: string | null; permissions: string[]; - }) => void; + }) => Promise; onRevoke: (args: {id: string}) => void; } @@ -43,21 +42,20 @@ export default class APIToken extends Component { } get isSubmitting() { - return taskFor(this.submitTask).isRunning; + return this.submitTask.isRunning; } get isSubmitDisabled() { return !this.apiTokenName || this.apiTokenName.length === 0; } - @dropTask - *submitTask() { + submitTask = dropTask(async () => { if (!this.apiTokenName) return; - const response: CreateApiTokenResponse = yield this.args.onCreate({ + const response: CreateApiTokenResponse = await this.args.onCreate({ name: this.apiTokenName, pictureUrl: this.apiTokenPictureUrl, - permissions: this.apiTokenPermissions, + permissions: this.apiTokenPermissions }); if (response.apiToken) { @@ -66,7 +64,7 @@ export default class APIToken extends Component { this.showPermissionsInput = false; this.unselectAllPermissions(); } - } + }); @action changePermission() { diff --git a/webapp/app/pods/components/project-settings/api-token/item/component.ts b/webapp/app/components/project-settings/api-token/item/component.ts similarity index 77% rename from webapp/app/pods/components/project-settings/api-token/item/component.ts rename to webapp/app/components/project-settings/api-token/item/component.ts index c1cd0e41d..18743dae4 100644 --- a/webapp/app/pods/components/project-settings/api-token/item/component.ts +++ b/webapp/app/components/project-settings/api-token/item/component.ts @@ -3,12 +3,11 @@ import {inject as service} from '@ember/service'; import {action} from '@ember/object'; import {tracked} from '@glimmer/tracking'; import {dropTask} from 'ember-concurrency'; -import {taskFor} from 'ember-concurrency-ts'; import IntlService from 'ember-intl/services/intl'; interface Args { token: any; - onRevoke: (args: {id: string}) => void; + onRevoke: (args: {id: string}) => Promise; } export default class APITokenItem extends Component { @@ -19,11 +18,10 @@ export default class APITokenItem extends Component { showPermissions = false; get isRevoking() { - return taskFor(this.revokeTask).isRunning; + return this.revokeTask.isRunning; } - @dropTask - *revokeTask() { + revokeTask = dropTask(async () => { const message = this.intl.t( 'components.project_settings.api_token.revoke_confirm' ); @@ -33,8 +31,8 @@ export default class APITokenItem extends Component { return; } - yield this.args.onRevoke(this.args.token); - } + await this.args.onRevoke(this.args.token); + }); @action togglePermissions() { diff --git a/webapp/app/pods/components/project-settings/badges/component.ts b/webapp/app/components/project-settings/badges/component.ts similarity index 100% rename from webapp/app/pods/components/project-settings/badges/component.ts rename to webapp/app/components/project-settings/badges/component.ts diff --git a/webapp/app/pods/components/project-settings/collaborators/component.ts b/webapp/app/components/project-settings/collaborators/component.ts similarity index 100% rename from webapp/app/pods/components/project-settings/collaborators/component.ts rename to webapp/app/components/project-settings/collaborators/component.ts diff --git a/webapp/app/pods/components/project-settings/collaborators/create-form/component.ts b/webapp/app/components/project-settings/collaborators/create-form/component.ts similarity index 89% rename from webapp/app/pods/components/project-settings/collaborators/create-form/component.ts rename to webapp/app/components/project-settings/collaborators/create-form/component.ts index 27ccd8397..e3b4bd0ff 100644 --- a/webapp/app/pods/components/project-settings/collaborators/create-form/component.ts +++ b/webapp/app/components/project-settings/collaborators/create-form/component.ts @@ -4,7 +4,7 @@ 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'; -import {dropTask} from 'ember-concurrency-decorators'; +import {dropTask} from 'ember-concurrency'; interface Args { project: any; @@ -39,7 +39,7 @@ export default class CreateForm extends Component { get mappedPossibleRoles() { return this.possibleRoles.map((value) => ({ label: this.intl.t(`general.roles.${value}`), - value, + value })); } @@ -47,17 +47,16 @@ export default class CreateForm extends Component { return this.mappedPossibleRoles.find(({value}) => value === this.role); } - @dropTask - *submitTask() { + submitTask = dropTask(async () => { if (!this.email || !this.role) return; this.isCreating = true; - yield this.args.onCreate({email: this.email, role: this.role}); + await this.args.onCreate({email: this.email, role: this.role}); this.email = ''; this.isCreating = false; - } + }); @action setRole({value}: {value: string}) { diff --git a/webapp/app/pods/components/project-settings/collaborators/list/component.ts b/webapp/app/components/project-settings/collaborators/list/component.ts similarity index 100% rename from webapp/app/pods/components/project-settings/collaborators/list/component.ts rename to webapp/app/components/project-settings/collaborators/list/component.ts diff --git a/webapp/app/pods/components/project-settings/collaborators/list/item/component.ts b/webapp/app/components/project-settings/collaborators/list/item/component.ts similarity index 99% rename from webapp/app/pods/components/project-settings/collaborators/list/item/component.ts rename to webapp/app/components/project-settings/collaborators/list/item/component.ts index 2d07fed8d..02de405b2 100644 --- a/webapp/app/pods/components/project-settings/collaborators/list/item/component.ts +++ b/webapp/app/components/project-settings/collaborators/list/item/component.ts @@ -40,7 +40,7 @@ export default class CollaboratorsListItem extends Component { get mappedPossibleRoles() { return this.possibleRoles.map((value) => ({ label: this.intl.t(`general.roles.${value}`), - value, + value })); } diff --git a/webapp/app/pods/components/project-settings/delete-form/component.ts b/webapp/app/components/project-settings/delete-form/component.ts similarity index 100% rename from webapp/app/pods/components/project-settings/delete-form/component.ts rename to webapp/app/components/project-settings/delete-form/component.ts diff --git a/webapp/app/pods/components/project-settings/form/component.ts b/webapp/app/components/project-settings/form/component.ts similarity index 94% rename from webapp/app/pods/components/project-settings/form/component.ts rename to webapp/app/components/project-settings/form/component.ts index d821e5f95..66fb16c93 100644 --- a/webapp/app/pods/components/project-settings/form/component.ts +++ b/webapp/app/components/project-settings/form/component.ts @@ -13,7 +13,7 @@ interface Args { isFileOperationsLocked, name, mainColor, - logo, + logo }: { isFileOperationsLocked: boolean; name: string; @@ -48,8 +48,8 @@ export default class ProjectSettingsForm extends Component { isFileOperationsLocked = this.args.project.isFileOperationsLocked; @action - logoPicked(selection: {emoji: string}) { - this.logo = selection.emoji; + logoPicked(selection: string) { + this.logo = selection; } @action @@ -61,7 +61,7 @@ export default class ProjectSettingsForm extends Component { isFileOperationsLocked: this.isFileOperationsLocked, name: this.name, mainColor: this.mainColor, - logo: this.logo, + logo: this.logo }); this.isUpdatingProject = false; @@ -75,7 +75,7 @@ export default class ProjectSettingsForm extends Component { isFileOperationsLocked: this.isFileOperationsLocked, name: this.name, mainColor: this.mainColor, - logo: this.logo, + logo: this.logo }); this.isUpdatingProject = false; diff --git a/webapp/app/pods/components/project-settings/integrations/component.ts b/webapp/app/components/project-settings/integrations/component.ts similarity index 100% rename from webapp/app/pods/components/project-settings/integrations/component.ts rename to webapp/app/components/project-settings/integrations/component.ts diff --git a/webapp/app/components/project-settings/integrations/form/aws-s3/component.ts b/webapp/app/components/project-settings/integrations/form/aws-s3/component.ts new file mode 100644 index 000000000..13e52a511 --- /dev/null +++ b/webapp/app/components/project-settings/integrations/form/aws-s3/component.ts @@ -0,0 +1,67 @@ +import Component from '@glimmer/component'; +import {action} from '@ember/object'; + +interface Args { + errors: any; + project: any; + bucket: string | null; + pathPrefix: string | null; + onChangeBucket: (value: string) => void; + onChangePathPrefix: (value: string) => void; + onChangeRegion: (value: string) => void; + onChangeAccessKeyId: (value: string) => void; + onChangeSecretAccessKey: (value: string) => void; +} + +export default class AwsS3 extends Component { + get policyContent() { + const bucket = this.args.bucket || '-'; + const pathPrefix = this.args.pathPrefix || '/'; + + return `{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": ["s3:PutObject"], + "Resource": "arn:aws:s3:::${bucket}${pathPrefix}*" + } + ] +}`; + } + + @action + changeBucket(event: Event) { + const target = event.target as HTMLInputElement; + + this.args.onChangeBucket(target.value); + } + + @action + changePathPrefix(event: Event) { + const target = event.target as HTMLInputElement; + + this.args.onChangePathPrefix(target.value); + } + + @action + changeRegion(event: Event) { + const target = event.target as HTMLInputElement; + + this.args.onChangeRegion(target.value); + } + + @action + changeAccessKeyId(event: Event) { + const target = event.target as HTMLInputElement; + + this.args.onChangeAccessKeyId(target.value); + } + + @action + changeSecretAccessKey(event: Event) { + const target = event.target as HTMLInputElement; + + this.args.onChangeSecretAccessKey(target.value); + } +} diff --git a/webapp/app/pods/components/project-settings/integrations/form/azure-storage-container/component.ts b/webapp/app/components/project-settings/integrations/form/azure-storage-container/component.ts similarity index 100% rename from webapp/app/pods/components/project-settings/integrations/form/azure-storage-container/component.ts rename to webapp/app/components/project-settings/integrations/form/azure-storage-container/component.ts diff --git a/webapp/app/pods/components/project-settings/integrations/form/component.ts b/webapp/app/components/project-settings/integrations/form/component.ts similarity index 65% rename from webapp/app/pods/components/project-settings/integrations/form/component.ts rename to webapp/app/components/project-settings/integrations/form/component.ts index c875a720e..0fc10a60c 100644 --- a/webapp/app/pods/components/project-settings/integrations/form/component.ts +++ b/webapp/app/components/project-settings/integrations/form/component.ts @@ -7,9 +7,10 @@ import {tracked} from '@glimmer/tracking'; const LOGOS = { AZURE_STORAGE_CONTAINER: 'assets/services/azure.svg', + AWS_S3: 'assets/services/aws-s3.svg', DISCORD: 'assets/services/discord.svg', GITHUB: 'assets/services/github.svg', - SLACK: 'assets/services/slack.svg', + SLACK: 'assets/services/slack.svg' }; interface Args { @@ -19,7 +20,7 @@ interface Args { service, events, integration, - data: {url, azureStorageContainerSas}, + data: {url, azureStorageContainerSas} }: { service: any; events: any; @@ -27,6 +28,11 @@ interface Args { data: { url: string; azureStorageContainerSas: string; + awsS3Bucket: string; + awsS3PathPrefix: string; + awsS3Region: string; + awsS3AccessKeyId: string; + awsS3SecretAccessKey: string; }; }) => Promise<{errors: any}>; onCancel: () => void; @@ -62,7 +68,22 @@ export default class IntegrationsForm extends Component { @tracked azureStorageContainerSasBaseUrl: string; - services = ['AZURE_STORAGE_CONTAINER', 'SLACK', 'DISCORD']; + @tracked + awsS3Bucket: string; + + @tracked + awsS3PathPrefix: string; + + @tracked + awsS3Region: string; + + @tracked + awsS3AccessKeyId: string; + + @tracked + awsS3SecretAccessKey: string; + + services = ['AWS_S3', 'AZURE_STORAGE_CONTAINER', 'SLACK', 'DISCORD']; @not('url') emptyUrl: boolean; @@ -81,7 +102,7 @@ export default class IntegrationsForm extends Component { return this.services.map((value) => { return { label: this.intl.t(`general.integration_services.${value}`), - value, + value }; }); } @@ -100,8 +121,8 @@ export default class IntegrationsForm extends Component { service: this.args.selectedServiceValue || this.services[0], events: [], data: { - url: this.url, - }, + url: this.url + } }; } @@ -109,6 +130,10 @@ export default class IntegrationsForm extends Component { this.url = this.integration.data.url; this.events = this.integration.events; this.azureStorageContainerSasBaseUrl = this.integration.data.sasBaseUrl; + this.awsS3Bucket = this.integration.data.bucket; + this.awsS3PathPrefix = this.integration.data.pathPrefix; + this.awsS3Region = this.integration.data.region; + this.awsS3AccessKeyId = this.integration.data.accessKeyId; } @action @@ -132,8 +157,33 @@ export default class IntegrationsForm extends Component { } @action - setAzureStorageContainerSas(sas: string) { - this.azureStorageContainerSas = sas; + setAzureStorageContainerSas(value: string) { + this.azureStorageContainerSas = value; + } + + @action + setAwsS3Bucket(value: string) { + this.awsS3Bucket = value; + } + + @action + setAwsS3PathPrefix(value: string) { + this.awsS3PathPrefix = value; + } + + @action + setAwsS3Region(value: string) { + this.awsS3Region = value; + } + + @action + setAwsS3AccessKeyId(value: string) { + this.awsS3AccessKeyId = value; + } + + @action + setAwsS3SecretAccessKey(value: string) { + this.awsS3SecretAccessKey = value; } @action @@ -147,7 +197,12 @@ export default class IntegrationsForm extends Component { data: { url: this.url, azureStorageContainerSas: this.azureStorageContainerSas, - }, + awsS3Bucket: this.awsS3Bucket, + awsS3PathPrefix: this.awsS3PathPrefix, + awsS3Region: this.awsS3Region, + awsS3AccessKeyId: this.awsS3AccessKeyId, + awsS3SecretAccessKey: this.awsS3SecretAccessKey + } }); this.isSubmiting = false; diff --git a/webapp/app/pods/components/project-settings/integrations/form/data-control-checkboxes/component.ts b/webapp/app/components/project-settings/integrations/form/data-control-checkboxes/component.ts similarity index 82% rename from webapp/app/pods/components/project-settings/integrations/form/data-control-checkboxes/component.ts rename to webapp/app/components/project-settings/integrations/form/data-control-checkboxes/component.ts index 569edd7b4..d34b08f5a 100644 --- a/webapp/app/pods/components/project-settings/integrations/form/data-control-checkboxes/component.ts +++ b/webapp/app/components/project-settings/integrations/form/data-control-checkboxes/component.ts @@ -17,18 +17,23 @@ export default class DataControlCheckboxes extends Component { allEvents = [ { value: 'SYNC', - label: 'components.project_settings.integrations.events.options.sync', + label: 'components.project_settings.integrations.events.options.sync' }, { value: 'NEW_CONFLICTS', label: - 'components.project_settings.integrations.events.options.new_conflicts', + 'components.project_settings.integrations.events.options.new_conflicts' }, { value: 'COMPLETE_REVIEW', label: - 'components.project_settings.integrations.events.options.complete_review', + 'components.project_settings.integrations.events.options.complete_review' }, + { + value: 'INTEGRATION_EXECUTE_AZURE_STORAGE_CONTAINER', + label: + 'components.project_settings.integrations.events.options.integration_execute_azure_storage_container' + } ]; @tracked diff --git a/webapp/app/pods/components/project-settings/integrations/form/discord/component.ts b/webapp/app/components/project-settings/integrations/form/discord/component.ts similarity index 100% rename from webapp/app/pods/components/project-settings/integrations/form/discord/component.ts rename to webapp/app/components/project-settings/integrations/form/discord/component.ts diff --git a/webapp/app/pods/components/project-settings/integrations/form/slack/component.ts b/webapp/app/components/project-settings/integrations/form/slack/component.ts similarity index 100% rename from webapp/app/pods/components/project-settings/integrations/form/slack/component.ts rename to webapp/app/components/project-settings/integrations/form/slack/component.ts diff --git a/webapp/app/pods/components/project-settings/integrations/list/component.ts b/webapp/app/components/project-settings/integrations/list/component.ts similarity index 100% rename from webapp/app/pods/components/project-settings/integrations/list/component.ts rename to webapp/app/components/project-settings/integrations/list/component.ts diff --git a/webapp/app/pods/components/project-settings/integrations/list/item/component.ts b/webapp/app/components/project-settings/integrations/list/item/component.ts similarity index 92% rename from webapp/app/pods/components/project-settings/integrations/list/item/component.ts rename to webapp/app/components/project-settings/integrations/list/item/component.ts index fc34b6beb..881737a77 100644 --- a/webapp/app/pods/components/project-settings/integrations/list/item/component.ts +++ b/webapp/app/components/project-settings/integrations/list/item/component.ts @@ -4,12 +4,13 @@ import {tracked} from '@glimmer/tracking'; const LOGOS = { AZURE_STORAGE_CONTAINER: 'assets/services/azure.svg', + AWS_S3: 'assets/services/aws-s3.svg', DISCORD: 'assets/services/discord.svg', GITHUB: 'assets/services/github.svg', - SLACK: 'assets/services/slack.svg', + SLACK: 'assets/services/slack.svg' }; -const EXECUTABLE_SERVICES = ['AZURE_STORAGE_CONTAINER']; +const EXECUTABLE_SERVICES = ['AZURE_STORAGE_CONTAINER', 'AWS_S3']; interface Args { project: any; diff --git a/webapp/app/components/project-settings/integrations/list/item/execute/aws-s3/component.ts b/webapp/app/components/project-settings/integrations/list/item/execute/aws-s3/component.ts new file mode 100644 index 000000000..141ff28f0 --- /dev/null +++ b/webapp/app/components/project-settings/integrations/list/item/execute/aws-s3/component.ts @@ -0,0 +1,110 @@ +import {inject as service} from '@ember/service'; +import {action} from '@ember/object'; +import {readOnly} from '@ember/object/computed'; +import {tracked} from '@glimmer/tracking'; +import Component from '@glimmer/component'; +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 executeIntegration from 'accent-webapp/queries/execute-integration'; + +const FLASH_MESSAGE_CREATE_SUCCESS = + 'pods.project.edit.flash_messages.integration_execute_success'; +const FLASH_MESSAGE_CREATE_ERROR = + 'pods.project.edit.flash_messages.integration_execute_error'; + +interface Args { + close: () => void; + integration: { + id: string; + }; +} + +export default class IntegrationExecuteAwsS3 extends Component { + @service('intl') + intl: IntlService; + + @service('apollo-mutate') + apolloMutate: ApolloMutate; + + @service('flash-messages') + flashMessages: FlashMessages; + + @readOnly('model.projectModel.project') + project: any; + + @tracked + error = false; + + allTargetVersions = [ + { + value: 'LATEST', + label: + 'components.project_settings.integrations.execute.aws_s3.target_version.options.latest' + }, + { + value: 'SPECIFIC', + label: + 'components.project_settings.integrations.execute.aws_s3.target_version.options.specific' + } + ]; + + @tracked + targetVersion = this.allTargetVersions[0].value; + + @tracked + tag: string | null = null; + + @tracked + isSubmitting = false; + + @action + setTargetVersion(targetVersion: string) { + this.tag = null; + this.targetVersion = targetVersion; + } + + @action + setTag(event: Event) { + const target = event.target as HTMLInputElement; + + this.tag = target.value; + } + + @action + autofocus(input: HTMLInputElement) { + input.focus(); + } + + @action + async submit() { + const confirmMessage = this.intl.t( + 'components.project_settings.integrations.execute.aws_s3.submit_confirm' + ); + /* eslint-disable-next-line no-alert */ + if (!window.confirm(confirmMessage)) { + return; + } + + const response = await this.apolloMutate.mutate({ + mutation: executeIntegration, + refetchQueries: ['ProjectServiceIntegrations'], + variables: { + integrationId: this.args.integration.id, + azureStorageContainer: { + tag: this.tag, + targetVersion: this.targetVersion + } + } + }); + + if (response.errors) { + this.flashMessages.error(this.intl.t(FLASH_MESSAGE_CREATE_ERROR)); + } else { + this.args.close(); + this.flashMessages.success(this.intl.t(FLASH_MESSAGE_CREATE_SUCCESS)); + } + + return response; + } +} diff --git a/webapp/app/pods/components/project-settings/integrations/list/item/execute/azure-storage-container/component.ts b/webapp/app/components/project-settings/integrations/list/item/execute/azure-storage-container/component.ts similarity index 93% rename from webapp/app/pods/components/project-settings/integrations/list/item/execute/azure-storage-container/component.ts rename to webapp/app/components/project-settings/integrations/list/item/execute/azure-storage-container/component.ts index 209facb94..90e4d05a2 100644 --- a/webapp/app/pods/components/project-settings/integrations/list/item/execute/azure-storage-container/component.ts +++ b/webapp/app/components/project-settings/integrations/list/item/execute/azure-storage-container/component.ts @@ -40,13 +40,13 @@ export default class IntegrationExecuteAzureStorageContainer extends Component void; + onDelete: () => Promise; onSave: ({ provider, enabledActions, usePlatform, - configKey, + configKey }: { provider: string; enabledActions: string[]; @@ -29,8 +28,7 @@ const PROVIDERS = ['google_translate', 'deepl']; /* eslint-disable camelcase */ const LOGOS = { deepl: 'assets/machine_translations_providers/deepl.svg', - google_translate: - 'assets/machine_translations_providers/google_translate.svg', + google_translate: 'assets/machine_translations_providers/google_translate.svg' }; export default class ProjectSettingsMachineTranslations extends Component { @@ -67,18 +65,18 @@ export default class ProjectSettingsMachineTranslations extends Component } get isSubmitting() { - return taskFor(this.submit).isRunning; + return this.submit.isRunning; } get isRemoving() { - return taskFor(this.remove).isRunning; + return this.remove.isRunning; } get mappedProviders() { return PROVIDERS.map((value) => { return { label: this.intl.t(`general.machine_translations_providers.${value}`), - value, + value }; }); } @@ -128,18 +126,16 @@ export default class ProjectSettingsMachineTranslations extends Component this.configKey = (event.target as HTMLInputElement).value; } - @dropTask - *submit() { - yield this.args.onSave({ + submit = dropTask(async () => { + await this.args.onSave({ provider: this.provider, enabledActions: this.enabledActions, usePlatform: this.usePlatform, - configKey: this.configKey, + configKey: this.configKey }); - } + }); - @dropTask - *remove() { - yield this.args.onDelete(); - } + remove = dropTask(async () => { + await this.args.onDelete(); + }); } diff --git a/webapp/app/pods/components/project-settings/manage-languages/component.ts b/webapp/app/components/project-settings/manage-languages/component.ts similarity index 100% rename from webapp/app/pods/components/project-settings/manage-languages/component.ts rename to webapp/app/components/project-settings/manage-languages/component.ts diff --git a/webapp/app/pods/components/project-settings/manage-languages/create-form/component.ts b/webapp/app/components/project-settings/manage-languages/create-form/component.ts similarity index 98% rename from webapp/app/pods/components/project-settings/manage-languages/create-form/component.ts rename to webapp/app/components/project-settings/manage-languages/create-form/component.ts index ff8328703..c8810c184 100644 --- a/webapp/app/pods/components/project-settings/manage-languages/create-form/component.ts +++ b/webapp/app/components/project-settings/manage-languages/create-form/component.ts @@ -63,7 +63,7 @@ export default class CreateForm extends Component { await this.args.onCreate(this.language, { machineTranslationsEnabled: this.machineTranslationsEnabled, - defaultNull: this.defaultNull, + defaultNull: this.defaultNull }); this.isLoading = false; diff --git a/webapp/app/pods/components/project-settings/manage-languages/overview/component.ts b/webapp/app/components/project-settings/manage-languages/overview/component.ts similarity index 100% rename from webapp/app/pods/components/project-settings/manage-languages/overview/component.ts rename to webapp/app/components/project-settings/manage-languages/overview/component.ts diff --git a/webapp/app/pods/components/project-settings/manage-languages/overview/item/component.ts b/webapp/app/components/project-settings/manage-languages/overview/item/component.ts similarity index 100% rename from webapp/app/pods/components/project-settings/manage-languages/overview/item/component.ts rename to webapp/app/components/project-settings/manage-languages/overview/item/component.ts diff --git a/webapp/app/pods/components/project-settings/prompts/config/component.ts b/webapp/app/components/project-settings/prompts/config/component.ts similarity index 66% rename from webapp/app/pods/components/project-settings/prompts/config/component.ts rename to webapp/app/components/project-settings/prompts/config/component.ts index 978e31477..29ce57791 100644 --- a/webapp/app/pods/components/project-settings/prompts/config/component.ts +++ b/webapp/app/components/project-settings/prompts/config/component.ts @@ -4,19 +4,20 @@ import Component from '@glimmer/component'; import {tracked} from '@glimmer/tracking'; import GlobalState from 'accent-webapp/services/global-state'; import FlashMessages from 'ember-cli-flash/services/flash-messages'; -import {dropTask} from 'ember-concurrency-decorators'; -import {taskFor} from 'ember-concurrency-ts'; +import {dropTask} from 'ember-concurrency'; import IntlService from 'ember-intl/services/intl'; interface Args { project: any; - onDelete: () => void; + onDelete: () => Promise; onSave: ({ provider, configKey, + usePlatform }: { provider: string; configKey: string | null; + usePlatform: boolean; }) => Promise; } @@ -24,10 +25,10 @@ const PROVIDERS = ['openai']; /* eslint-disable camelcase */ const LOGOS = { - openai: 'assets/prompts_providers/openai.svg', + openai: 'assets/prompts_providers/openai.svg' }; -export default class ProjectSettingsMachineTranslations extends Component { +export default class ProjectSettingsPromptsConfig extends Component { @service('global-state') globalState: GlobalState; @@ -38,10 +39,10 @@ export default class ProjectSettingsMachineTranslations extends Component intl: IntlService; @tracked - provider = this.args.project.promptsConfig?.provider || 'openai'; + provider = this.args.project.promptConfig?.provider || 'openai'; @tracked - usePlatform = this.args.project.promptsConfig?.usePlatform || false; + usePlatform = this.args.project.promptConfig?.usePlatform || false; @tracked configKey: any; @@ -51,18 +52,18 @@ export default class ProjectSettingsMachineTranslations extends Component } get isSubmitting() { - return taskFor(this.submit).isRunning; + return this.submit.isRunning; } get isRemoving() { - return taskFor(this.remove).isRunning; + return this.remove.isRunning; } get mappedProviders() { return PROVIDERS.map((value) => { return { label: this.intl.t(`general.prompts_providers.${value}`), - value, + value }; }); } @@ -87,16 +88,23 @@ export default class ProjectSettingsMachineTranslations extends Component this.configKey = (event.target as HTMLInputElement).value; } - @dropTask - *submit() { - yield this.args.onSave({ + @action + onUsePlatformChange(event: InputEvent) { + const checked = (event.target as HTMLInputElement).checked; + + if (checked) this.configKey = null; + this.usePlatform = checked; + } + + submit = dropTask(async () => { + await this.args.onSave({ provider: this.provider, configKey: this.configKey, + usePlatform: this.usePlatform }); - } + }); - @dropTask - *remove() { - yield this.args.onDelete(); - } + remove = dropTask(async () => { + await this.args.onDelete(); + }); } diff --git a/webapp/app/pods/components/project-settings/prompts/item/component.ts b/webapp/app/components/project-settings/prompts/item/component.ts similarity index 73% rename from webapp/app/pods/components/project-settings/prompts/item/component.ts rename to webapp/app/components/project-settings/prompts/item/component.ts index 8008b6f90..6ee8d13b4 100644 --- a/webapp/app/pods/components/project-settings/prompts/item/component.ts +++ b/webapp/app/components/project-settings/prompts/item/component.ts @@ -1,20 +1,19 @@ import Component from '@glimmer/component'; -import {dropTask} from 'ember-concurrency-decorators'; +import {dropTask} from 'ember-concurrency'; import IntlService from 'ember-intl/services/intl'; import {inject as service} from '@ember/service'; interface Args { project: any; prompt: any; - onDelete: (id: string) => void; + onDelete: (id: string) => Promise; } export default class ProjectSettingsPromptsItem extends Component { @service('intl') intl: IntlService; - @dropTask - *deletePrompt() { + deletePrompt = dropTask(async () => { const message = this.intl.t( 'components.project_settings.prompts.delete_confirm' ); @@ -24,6 +23,6 @@ export default class ProjectSettingsPromptsItem extends Component { return; } - yield this.args.onDelete(this.args.prompt.id); - } + await this.args.onDelete(this.args.prompt.id); + }); } diff --git a/webapp/app/pods/components/project-settings/title/component.ts b/webapp/app/components/project-settings/title/component.ts similarity index 100% rename from webapp/app/pods/components/project-settings/title/component.ts rename to webapp/app/components/project-settings/title/component.ts diff --git a/webapp/app/pods/components/projects-filters/component.ts b/webapp/app/components/projects-filters/component.ts similarity index 73% rename from webapp/app/pods/components/projects-filters/component.ts rename to webapp/app/components/projects-filters/component.ts index d550e5b40..9558c4254 100644 --- a/webapp/app/pods/components/projects-filters/component.ts +++ b/webapp/app/components/projects-filters/component.ts @@ -2,9 +2,7 @@ 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 {perform} from 'ember-concurrency-ts'; +import {timeout, restartableTask} from 'ember-concurrency'; import {tracked} from '@glimmer/tracking'; const DEBOUNCE_OFFSET = 1000; // ms @@ -22,20 +20,19 @@ export default class ProjectsFilter extends Component { @tracked debouncedQuery: string = this.args.query; - @restartableTask - *debounceQuery(query: string) { + debounceQueryTask = restartableTask(async (query: string) => { this.debouncedQuery = query; - yield timeout(DEBOUNCE_OFFSET); + await timeout(DEBOUNCE_OFFSET); this.args.onChangeQuery(query); - } + }); @action setDebouncedQuery(event: Event) { const target = event.target as HTMLInputElement; - perform(this.debounceQuery, target.value); + this.debounceQueryTask.perform(target.value); } @action diff --git a/webapp/app/pods/components/projects-header/component.ts b/webapp/app/components/projects-header/component.ts similarity index 81% rename from webapp/app/pods/components/projects-header/component.ts rename to webapp/app/components/projects-header/component.ts index e972db1a2..774eae29b 100644 --- a/webapp/app/pods/components/projects-header/component.ts +++ b/webapp/app/components/projects-header/component.ts @@ -5,9 +5,7 @@ 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'; -import {perform} from 'ember-concurrency-ts'; +import {timeout, restartableTask} from 'ember-concurrency'; const DEBOUNCE_OFFSET = 500; // ms @@ -45,28 +43,27 @@ export default class ProjectsHeader extends Component { return this.args.project.revisions[0].id; } - @restartableTask - *debounceQuery(query: string) { + debounceQuery = restartableTask(async (query: string) => { this.debouncedQuery = query; if (!this.debouncedQuery) return; - yield timeout(DEBOUNCE_OFFSET); + await timeout(DEBOUNCE_OFFSET); this.router.transitionTo( 'logged-in.project.revision.translations', this.args.project.id, this.selectedRevision, { - queryParams: {query}, + queryParams: {query} } ); - } + }); @action setDebouncedQuery(event: Event) { const target = event.target as HTMLInputElement; - perform(this.debounceQuery, target.value); + this.debounceQuery.perform(target.value); } @action diff --git a/webapp/app/pods/components/projects-list/component.ts b/webapp/app/components/projects-list/component.ts similarity index 100% rename from webapp/app/pods/components/projects-list/component.ts rename to webapp/app/components/projects-list/component.ts diff --git a/webapp/app/components/projects-list/item/component.ts b/webapp/app/components/projects-list/item/component.ts new file mode 100644 index 000000000..d8ac6a656 --- /dev/null +++ b/webapp/app/components/projects-list/item/component.ts @@ -0,0 +1,11 @@ +import Component from '@glimmer/component'; + +interface Args { + project: any; +} + +export default class ProjectsListItem extends Component { + get colorPrimary() { + return `--color-primary: ${this.args.project.mainColor}`; + } +} diff --git a/webapp/app/pods/components/prompt-create-form/component.ts b/webapp/app/components/prompt-create-form/component.ts similarity index 92% rename from webapp/app/pods/components/prompt-create-form/component.ts rename to webapp/app/components/prompt-create-form/component.ts index 2250281fe..312f59015 100644 --- a/webapp/app/pods/components/prompt-create-form/component.ts +++ b/webapp/app/components/prompt-create-form/component.ts @@ -8,7 +8,7 @@ interface Args { onCreate: ({ content, name, - quickAccess, + quickAccess }: { content: string; name: string; @@ -57,8 +57,8 @@ export default class PromptCreateForm extends Component { } @action - setQuickAccess(selection: {emoji: string}) { - this.quickAccess = selection.emoji; + setQuickAccess(selection: string) { + this.quickAccess = selection; } @action diff --git a/webapp/app/pods/components/prompt-update-form/component.ts b/webapp/app/components/prompt-update-form/component.ts similarity index 92% rename from webapp/app/pods/components/prompt-update-form/component.ts rename to webapp/app/components/prompt-update-form/component.ts index 29f28fbe7..a9f41ad9b 100644 --- a/webapp/app/pods/components/prompt-update-form/component.ts +++ b/webapp/app/components/prompt-update-form/component.ts @@ -9,7 +9,7 @@ interface Args { onUpdate: ({ content, name, - quickAccess, + quickAccess }: { content: string; name: string; @@ -58,8 +58,8 @@ export default class PromptUpdateForm extends Component { } @action - setQuickAccess(selection: {emoji: string}) { - this.quickAccess = selection.emoji; + setQuickAccess(selection: string) { + this.quickAccess = selection; } @action diff --git a/webapp/app/pods/components/recent-project-cache/component.ts b/webapp/app/components/recent-project-cache/component.ts similarity index 70% rename from webapp/app/pods/components/recent-project-cache/component.ts rename to webapp/app/components/recent-project-cache/component.ts index 64ae2a255..67a0a28b2 100644 --- a/webapp/app/pods/components/recent-project-cache/component.ts +++ b/webapp/app/components/recent-project-cache/component.ts @@ -1,7 +1,6 @@ import Component from '@glimmer/component'; import {inject as service} from '@ember/service'; -import {dropTask} from 'ember-concurrency-decorators'; -import {timeout} from 'ember-concurrency'; +import {timeout, dropTask} from 'ember-concurrency'; import RecentProjects from 'accent-webapp/services/recent-projects'; @@ -15,9 +14,8 @@ export default class RecentProjectCache extends Component { @service('recent-projects') recentProjects: RecentProjects; - @dropTask - *persistRecentProject() { - yield timeout(DEBOUNCE_ADD); + persistRecentProject = dropTask(async () => { + await timeout(DEBOUNCE_ADD); this.recentProjects.add(this.args.project.id); - } + }); } diff --git a/webapp/app/pods/components/recent-projects-list/component.ts b/webapp/app/components/recent-projects-list/component.ts similarity index 100% rename from webapp/app/pods/components/recent-projects-list/component.ts rename to webapp/app/components/recent-projects-list/component.ts diff --git a/webapp/app/pods/components/recent-projects-list/item/component.ts b/webapp/app/components/recent-projects-list/item/component.ts similarity index 100% rename from webapp/app/pods/components/recent-projects-list/item/component.ts rename to webapp/app/components/recent-projects-list/item/component.ts diff --git a/webapp/app/pods/components/related-translations-list/component.ts b/webapp/app/components/related-translations-list/component.ts similarity index 100% rename from webapp/app/pods/components/related-translations-list/component.ts rename to webapp/app/components/related-translations-list/component.ts diff --git a/webapp/app/pods/components/related-translations-list/item/component.ts b/webapp/app/components/related-translations-list/item/component.ts similarity index 100% rename from webapp/app/pods/components/related-translations-list/item/component.ts rename to webapp/app/components/related-translations-list/item/component.ts diff --git a/webapp/app/pods/components/removed-translation-edit/component.ts b/webapp/app/components/removed-translation-edit/component.ts similarity index 100% rename from webapp/app/pods/components/removed-translation-edit/component.ts rename to webapp/app/components/removed-translation-edit/component.ts diff --git a/webapp/app/pods/components/resource-pagination/component.ts b/webapp/app/components/resource-pagination/component.ts similarity index 100% rename from webapp/app/pods/components/resource-pagination/component.ts rename to webapp/app/components/resource-pagination/component.ts diff --git a/webapp/app/pods/components/review-progress-bar/component.ts b/webapp/app/components/review-progress-bar/component.ts similarity index 100% rename from webapp/app/pods/components/review-progress-bar/component.ts rename to webapp/app/components/review-progress-bar/component.ts diff --git a/webapp/app/pods/components/revision-export-options/advanced-filters/component.ts b/webapp/app/components/revision-export-options/advanced-filters/component.ts similarity index 100% rename from webapp/app/pods/components/revision-export-options/advanced-filters/component.ts rename to webapp/app/components/revision-export-options/advanced-filters/component.ts diff --git a/webapp/app/pods/components/revision-export-options/component.ts b/webapp/app/components/revision-export-options/component.ts similarity index 92% rename from webapp/app/pods/components/revision-export-options/component.ts rename to webapp/app/components/revision-export-options/component.ts index 2f7e3b80f..18c392d92 100644 --- a/webapp/app/pods/components/revision-export-options/component.ts +++ b/webapp/app/components/revision-export-options/component.ts @@ -52,14 +52,12 @@ export default class RevisionExportOptions extends Component { return [ { value: '', - label: this.intl.t( - 'components.revision_export_options.orders.original' - ), + label: this.intl.t('components.revision_export_options.orders.original') }, { value: 'key', - label: this.intl.t('components.revision_export_options.orders.az'), - }, + label: this.intl.t('components.revision_export_options.orders.az') + } ]; } @@ -74,7 +72,7 @@ export default class RevisionExportOptions extends Component { return this.globalState.documentFormats.map(({slug, name}) => ({ value: slug, - label: name, + label: name })); } @@ -82,9 +80,9 @@ export default class RevisionExportOptions extends Component { return [ { value: '', - label: this.intl.t('components.revision_export_options.default_format'), + label: this.intl.t('components.revision_export_options.default_format') }, - ...this.formattedDocumentFormats, + ...this.formattedDocumentFormats ]; } @@ -103,14 +101,14 @@ export default class RevisionExportOptions extends Component { ({ id, name, - language, + language }: { id: string; name: string | null; language: any; }) => ({ label: name || language.name, - value: id, + value: id }) ); } @@ -129,7 +127,7 @@ export default class RevisionExportOptions extends Component { return this.args.documents.map( ({id, path}: {id: string; path: string}) => ({ label: path, - value: id, + value: id }) ); } @@ -148,16 +146,16 @@ export default class RevisionExportOptions extends Component { memo.concat([ { label: tag, - value: tag, - }, + value: tag + } ]), [ { label: this.intl.t( 'components.revision_export_options.default_version' ), - value: '', - }, + value: '' + } ] ); } diff --git a/webapp/app/pods/components/revision-selector/component.ts b/webapp/app/components/revision-selector/component.ts similarity index 100% rename from webapp/app/pods/components/revision-selector/component.ts rename to webapp/app/components/revision-selector/component.ts diff --git a/webapp/app/pods/components/revision-update-form/component.ts b/webapp/app/components/revision-update-form/component.ts similarity index 100% rename from webapp/app/pods/components/revision-update-form/component.ts rename to webapp/app/components/revision-update-form/component.ts diff --git a/webapp/app/pods/components/skeleton-ui/content/component.ts b/webapp/app/components/skeleton-ui/content/component.ts similarity index 100% rename from webapp/app/pods/components/skeleton-ui/content/component.ts rename to webapp/app/components/skeleton-ui/content/component.ts diff --git a/webapp/app/pods/components/skeleton-ui/progress-line/component.ts b/webapp/app/components/skeleton-ui/progress-line/component.ts similarity index 100% rename from webapp/app/pods/components/skeleton-ui/progress-line/component.ts rename to webapp/app/components/skeleton-ui/progress-line/component.ts diff --git a/webapp/app/pods/components/skeleton-ui/project-activities-filter/component.ts b/webapp/app/components/skeleton-ui/project-activities-filter/component.ts similarity index 100% rename from webapp/app/pods/components/skeleton-ui/project-activities-filter/component.ts rename to webapp/app/components/skeleton-ui/project-activities-filter/component.ts diff --git a/webapp/app/pods/components/time-ago-in-words-tag/component.ts b/webapp/app/components/time-ago-in-words-tag/component.ts similarity index 95% rename from webapp/app/pods/components/time-ago-in-words-tag/component.ts rename to webapp/app/components/time-ago-in-words-tag/component.ts index bc4d35e1b..383a99721 100644 --- a/webapp/app/pods/components/time-ago-in-words-tag/component.ts +++ b/webapp/app/components/time-ago-in-words-tag/component.ts @@ -1,6 +1,6 @@ import {inject as service} from '@ember/service'; import Component from '@glimmer/component'; -import dateFormat from 'date-fns/format'; +import {format as dateFormat} from 'date-fns'; import IntlService from 'ember-intl/services/intl'; interface Args { diff --git a/webapp/app/pods/components/translation-activities-list/component.ts b/webapp/app/components/translation-activities-list/component.ts similarity index 100% rename from webapp/app/pods/components/translation-activities-list/component.ts rename to webapp/app/components/translation-activities-list/component.ts diff --git a/webapp/app/pods/components/translation-comment-delete/component.ts b/webapp/app/components/translation-comment-delete/component.ts similarity index 100% rename from webapp/app/pods/components/translation-comment-delete/component.ts rename to webapp/app/components/translation-comment-delete/component.ts diff --git a/webapp/app/pods/components/translation-comment-form/component.ts b/webapp/app/components/translation-comment-form/component.ts similarity index 69% rename from webapp/app/pods/components/translation-comment-form/component.ts rename to webapp/app/components/translation-comment-form/component.ts index 4a56d5bcd..00b12f9ad 100644 --- a/webapp/app/pods/components/translation-comment-form/component.ts +++ b/webapp/app/components/translation-comment-form/component.ts @@ -1,10 +1,8 @@ import Component from '@glimmer/component'; import {action} from '@ember/object'; import {tracked} from '@glimmer/tracking'; -import {dropTask} from 'ember-concurrency-decorators'; -import {timeout} from 'ember-concurrency'; +import {timeout, dropTask} from 'ember-concurrency'; import {MutationResponse} from 'accent-webapp/services/apollo-mutate'; -import {taskFor} from 'ember-concurrency-ts'; interface Args { value?: string; @@ -21,23 +19,22 @@ export default class TranslationCommentForm extends Component { error = false; get isSubmitting() { - return taskFor(this.submitTask).isRunning; + return this.submitTask.isRunning; } - @dropTask - *submitTask(event?: Event): any { + submitTask = dropTask(async (event?: Event) => { this.error = false; event?.preventDefault(); - yield timeout(SUBMIT_DEBOUNCE); - const response = yield this.args.onSubmit(this.text); + await timeout(SUBMIT_DEBOUNCE); + const response = await this.args.onSubmit(this.text); if (response.errors) { this.error = true; } else { this.text = ''; } - } + }); @action setText(event: KeyboardEvent) { diff --git a/webapp/app/pods/components/translation-comments-list/component.ts b/webapp/app/components/translation-comments-list/component.ts similarity index 100% rename from webapp/app/pods/components/translation-comments-list/component.ts rename to webapp/app/components/translation-comments-list/component.ts diff --git a/webapp/app/pods/components/translation-comments-list/item/component.ts b/webapp/app/components/translation-comments-list/item/component.ts similarity index 82% rename from webapp/app/pods/components/translation-comments-list/item/component.ts rename to webapp/app/components/translation-comments-list/item/component.ts index 602671de9..b4be84fb7 100644 --- a/webapp/app/pods/components/translation-comments-list/item/component.ts +++ b/webapp/app/components/translation-comments-list/item/component.ts @@ -5,13 +5,13 @@ import Component from '@glimmer/component'; import MarkdownIt from 'markdown-it'; import {htmlSafe} from '@ember/template'; import Session from 'accent-webapp/services/session'; -import {dropTask} from 'ember-concurrency-decorators'; +import {dropTask} from 'ember-concurrency'; import {tracked} from '@glimmer/tracking'; const markdown = MarkdownIt({ html: false, linkify: true, - typographer: true, + typographer: true }); interface Args { @@ -57,15 +57,13 @@ export default class TranslationsCommentsListItem extends Component { element.querySelector('textarea')?.focus(); } - @dropTask - *deleteComment() { - yield this.args.onDeleteComment(this.args.comment); - } + deleteComment = dropTask(async () => { + await this.args.onDeleteComment(this.args.comment); + }); - @dropTask - *updateComment(text: string) { - yield this.args.onUpdateComment({...this.args.comment, text}); + updateComment = dropTask(async (text: string) => { + await this.args.onUpdateComment({...this.args.comment, text}); this.editComment = false; - } + }); } diff --git a/webapp/app/pods/components/translation-comments-subscriptions/component.ts b/webapp/app/components/translation-comments-subscriptions/component.ts similarity index 100% rename from webapp/app/pods/components/translation-comments-subscriptions/component.ts rename to webapp/app/components/translation-comments-subscriptions/component.ts diff --git a/webapp/app/pods/components/translation-comments-subscriptions/item/component.ts b/webapp/app/components/translation-comments-subscriptions/item/component.ts similarity index 100% rename from webapp/app/pods/components/translation-comments-subscriptions/item/component.ts rename to webapp/app/components/translation-comments-subscriptions/item/component.ts diff --git a/webapp/app/pods/components/translation-conversation/component.ts b/webapp/app/components/translation-conversation/component.ts similarity index 100% rename from webapp/app/pods/components/translation-conversation/component.ts rename to webapp/app/components/translation-conversation/component.ts diff --git a/webapp/app/pods/components/translation-edit/component.ts b/webapp/app/components/translation-edit/component.ts similarity index 96% rename from webapp/app/pods/components/translation-edit/component.ts rename to webapp/app/components/translation-edit/component.ts index bd6b16be2..6ec254f14 100644 --- a/webapp/app/pods/components/translation-edit/component.ts +++ b/webapp/app/components/translation-edit/component.ts @@ -78,9 +78,10 @@ export default class TranslationEdit extends Component { } @action - onUpdateText(value: string) { - this.text = value; + onUpdateText(text: string) { + this.text = text; this.inputDisabled = false; + this.args.onChangeText?.(text); } @action diff --git a/webapp/app/pods/components/translation-edit/form/component.ts b/webapp/app/components/translation-edit/form/component.ts similarity index 77% rename from webapp/app/pods/components/translation-edit/form/component.ts rename to webapp/app/components/translation-edit/form/component.ts index 1e5082bc3..d421d4ad4 100644 --- a/webapp/app/pods/components/translation-edit/form/component.ts +++ b/webapp/app/components/translation-edit/form/component.ts @@ -1,21 +1,20 @@ import {inject as service} from '@ember/service'; import {equal} from '@ember/object/computed'; +import {next} from '@ember/runloop'; 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 {perform} from 'ember-concurrency-ts'; -import {timeout, TaskGenerator} from 'ember-concurrency'; +import {timeout, restartableTask} from 'ember-concurrency'; import MarkdownIt from 'markdown-it'; import {htmlSafe} from '@ember/template'; const markdown = MarkdownIt({ html: false, linkify: true, - typographer: true, + typographer: true }); const DEBOUNCE_LINT_MESSAGES = 800; @@ -51,7 +50,7 @@ export default class TranslationEditForm extends Component { @tracked lintTranslation = { translation: {id: this.args.translationId, text: this.args.value}, - messages: this.args.lintMessages, + messages: this.args.lintMessages }; @tracked @@ -107,6 +106,21 @@ export default class TranslationEditForm extends Component { this.args.onKeyUp?.(value); } + @action + handleFocus() { + this.args.onFocus?.(); + } + + @action + handleBlur() { + next(this, () => this.args.onBlur?.()); + } + + @action + handleSubmit() { + this.args.onSubmit(); + } + @action changeText(event: Event) { const target = event.target as HTMLInputElement; @@ -118,32 +132,29 @@ export default class TranslationEditForm extends Component { this.args.onEscape?.(); } - @restartableTask - *onUpdateValue( - _element: HTMLElement, - [value]: string[] - ): TaskGenerator { - yield timeout(DEBOUNCE_LINT_MESSAGES); + onUpdateValue = restartableTask( + async (_element: HTMLElement, [value]: string[]) => { + await timeout(DEBOUNCE_LINT_MESSAGES); - yield perform(this.fetchLintMessagesTask, value); - } + await this.fetchLintMessagesTask.perform(value); + } + ); - @restartableTask - *fetchLintMessagesTask(value: string) { - const {data} = yield this.apollo.client.query({ + fetchLintMessagesTask = restartableTask(async (value: string) => { + const {data} = await this.apollo.client.query({ fetchPolicy: 'network-only', query: translationLintQuery, variables: { text: value, projectId: this.args.projectId, - translationId: this.args.translationId, - }, + translationId: this.args.translationId + } }); this.lintTranslation = Object.assign(this.lintTranslation, { - messages: data.viewer.project.translation.lintMessages, + messages: data.viewer.project.translation.lintMessages }); - } + }); @action replaceText(value: string) { diff --git a/webapp/app/pods/components/translation-edit/helpers/component.ts b/webapp/app/components/translation-edit/helpers/component.ts similarity index 77% rename from webapp/app/pods/components/translation-edit/helpers/component.ts rename to webapp/app/components/translation-edit/helpers/component.ts index a90cdcde4..5a4b38727 100644 --- a/webapp/app/pods/components/translation-edit/helpers/component.ts +++ b/webapp/app/components/translation-edit/helpers/component.ts @@ -6,9 +6,11 @@ interface Args { export default class TranslationEditHelpers extends Component { get machineTranslationLanguages() { + if (!this.args.revisions) return []; + return this.args.revisions.map((revision: any) => ({ name: revision.name || revision.language.name, - slug: revision.slug || revision.language.slug, + slug: revision.slug || revision.language.slug })); } } diff --git a/webapp/app/pods/components/translation-editions-list/component.ts b/webapp/app/components/translation-editions-list/component.ts similarity index 100% rename from webapp/app/pods/components/translation-editions-list/component.ts rename to webapp/app/components/translation-editions-list/component.ts diff --git a/webapp/app/pods/components/translation-editions-list/item/component.ts b/webapp/app/components/translation-editions-list/item/component.ts similarity index 100% rename from webapp/app/pods/components/translation-editions-list/item/component.ts rename to webapp/app/components/translation-editions-list/item/component.ts diff --git a/webapp/app/pods/components/translation-navigation/component.ts b/webapp/app/components/translation-navigation/component.ts similarity index 100% rename from webapp/app/pods/components/translation-navigation/component.ts rename to webapp/app/components/translation-navigation/component.ts diff --git a/webapp/app/pods/components/translation-splash-title/component.ts b/webapp/app/components/translation-splash-title/component.ts similarity index 100% rename from webapp/app/pods/components/translation-splash-title/component.ts rename to webapp/app/components/translation-splash-title/component.ts diff --git a/webapp/app/pods/components/translations-filter/advanced-filters/component.ts b/webapp/app/components/translations-filter/advanced-filters/component.ts similarity index 100% rename from webapp/app/pods/components/translations-filter/advanced-filters/component.ts rename to webapp/app/components/translations-filter/advanced-filters/component.ts diff --git a/webapp/app/pods/components/translations-filter/component.ts b/webapp/app/components/translations-filter/component.ts similarity index 87% rename from webapp/app/pods/components/translations-filter/component.ts rename to webapp/app/components/translations-filter/component.ts index f50055ac3..fe95f82f9 100644 --- a/webapp/app/pods/components/translations-filter/component.ts +++ b/webapp/app/components/translations-filter/component.ts @@ -4,9 +4,7 @@ import {gt} from '@ember/object/computed'; import Component from '@glimmer/component'; import IntlService from 'ember-intl/services/intl'; import {tracked} from '@glimmer/tracking'; -import {restartableTask} from 'ember-concurrency-decorators'; -import {timeout} from 'ember-concurrency'; -import {perform} from 'ember-concurrency-ts'; +import {timeout, restartableTask} from 'ember-concurrency'; const DEBOUNCE_OFFSET = 1000; // ms @@ -25,6 +23,7 @@ interface Args { isCommentedOnFilter: boolean; isConflictedFilter: boolean; isTranslatedFilter: boolean; + jipt?: boolean; onChangeQuery: (query: string) => void; onChangeDocument: () => void; onChangeVersion: () => void; @@ -53,7 +52,7 @@ export default class TranslationsFilter extends Component { const documents = this.args.documents.map( ({id, path}: {id: string; path: string}) => ({ label: path, - value: id, + value: id }) ); @@ -61,7 +60,7 @@ export default class TranslationsFilter extends Component { label: this.intl.t( 'components.translations_filter.document_default_option_text' ), - value: '', + value: '' }); return documents; @@ -77,7 +76,7 @@ export default class TranslationsFilter extends Component { const versions = this.args.versions.map( ({id, tag}: {id: string; tag: string}) => ({ label: tag, - value: id, + value: id }) ); @@ -85,7 +84,7 @@ export default class TranslationsFilter extends Component { label: this.intl.t( 'components.translations_filter.version_default_option_text' ), - value: '', + value: '' }); return versions; @@ -101,17 +100,16 @@ export default class TranslationsFilter extends Component { setDebouncedQuery(event: Event) { const target = event.target as HTMLInputElement; - perform(this.debounceQuery, target.value); + this.debounceQuery.perform(target.value); } - @restartableTask - *debounceQuery(query: string) { + debounceQuery = restartableTask(async (query: string) => { this.debouncedQuery = query; - yield timeout(DEBOUNCE_OFFSET); + await timeout(DEBOUNCE_OFFSET); this.args.onChangeQuery(query); - } + }); @action submitForm(event: Event) { diff --git a/webapp/app/pods/components/translations-list/component.ts b/webapp/app/components/translations-list/component.ts similarity index 100% rename from webapp/app/pods/components/translations-list/component.ts rename to webapp/app/components/translations-list/component.ts diff --git a/webapp/app/pods/components/translations-list/item/component.ts b/webapp/app/components/translations-list/item/component.ts similarity index 100% rename from webapp/app/pods/components/translations-list/item/component.ts rename to webapp/app/components/translations-list/item/component.ts diff --git a/webapp/app/pods/components/version-create-form/component.ts b/webapp/app/components/version-create-form/component.ts similarity index 66% rename from webapp/app/pods/components/version-create-form/component.ts rename to webapp/app/components/version-create-form/component.ts index 4d63b5cda..009e0bf8f 100644 --- a/webapp/app/pods/components/version-create-form/component.ts +++ b/webapp/app/components/version-create-form/component.ts @@ -5,7 +5,7 @@ import {tracked} from '@glimmer/tracking'; interface Args { error: boolean; project: any; - onCreate: ({name, tag}: {name: string; tag: string}) => Promise; + onCreate: (args: object) => Promise; } export default class VersionCreateForm extends Component { @@ -15,6 +15,9 @@ export default class VersionCreateForm extends Component { @tracked tag = ''; + @tracked + copyOnUpdateTranslation = true; + @tracked isCreating = false; @@ -32,14 +35,21 @@ export default class VersionCreateForm extends Component { this.tag = target.value; } + @action + setCopyOnUpdateTranslation(event: Event) { + const target = event.target as HTMLInputElement; + this.copyOnUpdateTranslation = target.checked; + } + @action async submit() { this.isCreating = true; - const tag = this.tag; - const name = this.name; - - await this.args.onCreate({tag, name}); + await this.args.onCreate({ + tag: this.tag, + name: this.name, + copyOnUpdateTranslation: this.copyOnUpdateTranslation + }); this.isCreating = false; } diff --git a/webapp/app/pods/components/version-update-form/component.ts b/webapp/app/components/version-update-form/component.ts similarity index 62% rename from webapp/app/pods/components/version-update-form/component.ts rename to webapp/app/components/version-update-form/component.ts index be65fb31c..26f2f94a1 100644 --- a/webapp/app/pods/components/version-update-form/component.ts +++ b/webapp/app/components/version-update-form/component.ts @@ -6,7 +6,11 @@ interface Args { version: any; error: boolean; project: any; - onUpdate: ({tag, name}: {tag: string; name: string}) => Promise; + onUpdate: (args: { + tag: string; + name: string; + copyOnUpdateTranslation: boolean; + }) => Promise; } export default class VersionUpdateForm extends Component { @@ -16,6 +20,9 @@ export default class VersionUpdateForm extends Component { @tracked tag = this.args.version.tag; + @tracked + copyOnUpdateTranslation = this.args.version.copyOnUpdateTranslation; + @tracked isSubmitting = false; @@ -23,14 +30,21 @@ export default class VersionUpdateForm extends Component { async submit() { this.isSubmitting = true; - const tag = this.tag; - const name = this.name; - - await this.args.onUpdate({tag, name}); + await this.args.onUpdate({ + tag: this.tag, + name: this.name, + copyOnUpdateTranslation: this.copyOnUpdateTranslation + }); if (!this.isDestroyed) this.isSubmitting = false; } + @action + setCopyOnUpdateTranslation(event: Event) { + const target = event.target as HTMLInputElement; + this.copyOnUpdateTranslation = target.checked; + } + @action setName(event: Event) { const target = event.target as HTMLInputElement; diff --git a/webapp/app/pods/components/versions-add-button/component.ts b/webapp/app/components/versions-add-button/component.ts similarity index 100% rename from webapp/app/pods/components/versions-add-button/component.ts rename to webapp/app/components/versions-add-button/component.ts diff --git a/webapp/app/pods/components/versions-list/component.ts b/webapp/app/components/versions-list/component.ts similarity index 100% rename from webapp/app/pods/components/versions-list/component.ts rename to webapp/app/components/versions-list/component.ts diff --git a/webapp/app/pods/components/versions-list/item/component.ts b/webapp/app/components/versions-list/item/component.ts similarity index 100% rename from webapp/app/pods/components/versions-list/item/component.ts rename to webapp/app/components/versions-list/item/component.ts diff --git a/webapp/app/pods/components/welcome-project/component.ts b/webapp/app/components/welcome-project/component.ts similarity index 100% rename from webapp/app/pods/components/welcome-project/component.ts rename to webapp/app/components/welcome-project/component.ts diff --git a/webapp/app/computed-macros/parsed-key.ts b/webapp/app/computed-macros/parsed-key.ts index 0e7d031fd..1045ad0ae 100644 --- a/webapp/app/computed-macros/parsed-key.ts +++ b/webapp/app/computed-macros/parsed-key.ts @@ -11,6 +11,6 @@ export default (key: string): ParsedKey => { return { value: isSplitted ? splittedKey[1] : key, - prefix: isSplitted ? splittedKey[0] : '', + prefix: isSplitted ? splittedKey[0] : '' }; }; diff --git a/webapp/app/config/environment.d.ts b/webapp/app/config/environment.d.ts index db7c72465..69d64852a 100644 --- a/webapp/app/config/environment.d.ts +++ b/webapp/app/config/environment.d.ts @@ -8,7 +8,6 @@ declare const config: { environment: any; modulePrefix: string; - podModulePrefix: string; locationType: string; rootURL: string; version: string; diff --git a/webapp/app/pods/error/controller.ts b/webapp/app/controllers/error.ts similarity index 100% rename from webapp/app/pods/error/controller.ts rename to webapp/app/controllers/error.ts diff --git a/webapp/app/pods/logged-in/controller.ts b/webapp/app/controllers/logged-in.ts similarity index 100% rename from webapp/app/pods/logged-in/controller.ts rename to webapp/app/controllers/logged-in.ts diff --git a/webapp/app/pods/logged-in/jipt/controller.ts b/webapp/app/controllers/logged-in/jipt.ts similarity index 91% rename from webapp/app/pods/logged-in/jipt/controller.ts rename to webapp/app/controllers/logged-in/jipt.ts index 3bca76bdb..6fa31c40c 100644 --- a/webapp/app/pods/logged-in/jipt/controller.ts +++ b/webapp/app/controllers/logged-in/jipt.ts @@ -6,11 +6,15 @@ import {readOnly} from '@ember/object/computed'; import Color from 'color'; import RouterService from '@ember/routing/router-service'; import {tracked} from '@glimmer/tracking'; +import GlobalState from 'accent-webapp/services/global-state'; export default class JIPTController extends Controller { @service('router') router: RouterService; + @service('global-state') + globalState: GlobalState; + queryParams = ['revisionId']; @tracked @@ -28,7 +32,7 @@ export default class JIPTController extends Controller { @readOnly('model.project.revisions') revisions: any; - constructor(...args: any) { + constructor(...args: any[]) { super(...args); window.addEventListener( @@ -42,7 +46,7 @@ export default class JIPTController extends Controller { } if (payload.data.jipt && payload.data.selectIds) { this.router.transitionTo('logged-in.jipt.index', { - queryParams: {translationIds: payload.data.selectIds}, + queryParams: {translationIds: payload.data.selectIds} }); } }, diff --git a/webapp/app/pods/logged-in/jipt/index/controller.ts b/webapp/app/controllers/logged-in/jipt/index.ts similarity index 89% rename from webapp/app/pods/logged-in/jipt/index/controller.ts rename to webapp/app/controllers/logged-in/jipt/index.ts index e22ae959a..d1dd9d317 100644 --- a/webapp/app/pods/logged-in/jipt/index/controller.ts +++ b/webapp/app/controllers/logged-in/jipt/index.ts @@ -53,15 +53,15 @@ export default class IndexController extends Controller { } @action - changeVersion(versionId: string) { + changeVersion(element: HTMLSelectElement) { this.page = 1; - this.version = versionId; + this.version = element.value; } @action - changeDocument(documentId: string) { + changeDocument(element: HTMLSelectElement) { this.page = 1; - this.document = documentId; + this.document = element.value; } @action diff --git a/webapp/app/pods/logged-in/jipt/translation/controller.ts b/webapp/app/controllers/logged-in/jipt/translation.ts similarity index 100% rename from webapp/app/pods/logged-in/jipt/translation/controller.ts rename to webapp/app/controllers/logged-in/jipt/translation.ts diff --git a/webapp/app/pods/logged-in/jipt/translation/index/controller.ts b/webapp/app/controllers/logged-in/jipt/translation/index.ts similarity index 97% rename from webapp/app/pods/logged-in/jipt/translation/index/controller.ts rename to webapp/app/controllers/logged-in/jipt/translation/index.ts index d2a5cd855..8d53ccf41 100644 --- a/webapp/app/pods/logged-in/jipt/translation/index/controller.ts +++ b/webapp/app/controllers/logged-in/jipt/translation/index.ts @@ -62,8 +62,8 @@ export default class IndexController extends Controller { mutation: translationCorrectQuery, variables: { translationId: conflict.id, - text, - }, + text + } }); if (response.errors) { @@ -81,14 +81,15 @@ export default class IndexController extends Controller { } @action - async uncorrectConflict() { + async uncorrectConflict(text: string) { const conflict = this.model.translation; const response = await this.apolloMutate.mutate({ mutation: translationUncorrectQuery, variables: { translationId: conflict.id, - }, + text + } }); if (response.errors) { @@ -113,8 +114,8 @@ export default class IndexController extends Controller { mutation: translationUpdateQuery, variables: { translationId: translation.id, - text, - }, + text + } }); if (response.errors) { diff --git a/webapp/app/pods/logged-in/project/controller.ts b/webapp/app/controllers/logged-in/project.ts similarity index 100% rename from webapp/app/pods/logged-in/project/controller.ts rename to webapp/app/controllers/logged-in/project.ts diff --git a/webapp/app/pods/logged-in/project/activities/controller.ts b/webapp/app/controllers/logged-in/project/activities.ts similarity index 98% rename from webapp/app/pods/logged-in/project/activities/controller.ts rename to webapp/app/controllers/logged-in/project/activities.ts index c7262246c..d320d1da8 100644 --- a/webapp/app/pods/logged-in/project/activities/controller.ts +++ b/webapp/app/controllers/logged-in/project/activities.ts @@ -26,7 +26,7 @@ export default class ActivitiesController extends Controller { 'actionFilter', 'userFilter', 'page', - 'versionFilter', + 'versionFilter' ]; @tracked diff --git a/webapp/app/pods/logged-in/project/activity/controller.ts b/webapp/app/controllers/logged-in/project/activity.ts similarity index 96% rename from webapp/app/pods/logged-in/project/activity/controller.ts rename to webapp/app/controllers/logged-in/project/activity.ts index 828716a76..e4dc236c1 100644 --- a/webapp/app/pods/logged-in/project/activity/controller.ts +++ b/webapp/app/controllers/logged-in/project/activity.ts @@ -41,8 +41,8 @@ export default class ActivityController extends Controller { const response = await this.apolloMutate.mutate({ mutation: operationRollbackQuery, variables: { - operationId: this.model.activity.id, - }, + operationId: this.model.activity.id + } }); if (response.errors) { diff --git a/webapp/app/pods/logged-in/project/collaborators/controller.ts b/webapp/app/controllers/logged-in/project/collaborators.ts similarity index 95% rename from webapp/app/pods/logged-in/project/collaborators/controller.ts rename to webapp/app/controllers/logged-in/project/collaborators.ts index e9023e93f..5963dcc81 100644 --- a/webapp/app/pods/logged-in/project/collaborators/controller.ts +++ b/webapp/app/controllers/logged-in/project/collaborators.ts @@ -58,8 +58,8 @@ export default class CollaboratorsController extends Controller { variables: { projectId: project.id, email, - role, - }, + role + } }); } @@ -71,8 +71,8 @@ export default class CollaboratorsController extends Controller { errorMessage: FLASH_MESSAGE_COLLABORATOR_UPDATE_ERROR, variables: { collaboratorId: collaborator.id, - role, - }, + role + } }); } @@ -83,8 +83,8 @@ export default class CollaboratorsController extends Controller { successMessage: FLASH_MESSAGE_COLLABORATOR_REMOVE_SUCCESS, errorMessage: FLASH_MESSAGE_COLLABORATOR_REMOVE_ERROR, variables: { - collaboratorId: collaborator.id, - }, + collaboratorId: collaborator.id + } }); } @@ -92,7 +92,7 @@ export default class CollaboratorsController extends Controller { mutation, variables, successMessage, - errorMessage, + errorMessage }: { mutation: any; variables: any; @@ -102,7 +102,7 @@ export default class CollaboratorsController extends Controller { const response = await this.apolloMutate.mutate({ mutation, variables, - refetchQueries: ['ProjectCollaborators'], + refetchQueries: ['ProjectCollaborators'] }); if (response.errors) { diff --git a/webapp/app/pods/logged-in/project/comments/controller.ts b/webapp/app/controllers/logged-in/project/comments.ts similarity index 96% rename from webapp/app/pods/logged-in/project/comments/controller.ts rename to webapp/app/controllers/logged-in/project/comments.ts index 27034135a..52554462a 100644 --- a/webapp/app/pods/logged-in/project/comments/controller.ts +++ b/webapp/app/controllers/logged-in/project/comments.ts @@ -49,8 +49,8 @@ export default class CommentsController extends Controller { refetchQueries: ['ProjectComments'], variables: { commentId: comment.id, - text: comment.text, - }, + text: comment.text + } }); } @@ -60,8 +60,8 @@ export default class CommentsController extends Controller { mutation: commentDeleteQuery, refetchQueries: ['ProjectComments'], variables: { - commentId: comment.id, - }, + commentId: comment.id + } }); if (response.errors) { diff --git a/webapp/app/controllers/logged-in/project/conflicts.ts b/webapp/app/controllers/logged-in/project/conflicts.ts new file mode 100644 index 000000000..ae352e67e --- /dev/null +++ b/webapp/app/controllers/logged-in/project/conflicts.ts @@ -0,0 +1,212 @@ +import {action} from '@ember/object'; +import {inject as service} from '@ember/service'; +import {readOnly, equal, and} from '@ember/object/computed'; +import Controller from '@ember/controller'; +import translationCorrectQuery from 'accent-webapp/queries/correct-translation'; +import translationUncorrectQuery from 'accent-webapp/queries/uncorrect-translation'; +import translationUpdateQuery from 'accent-webapp/queries/update-translation'; +import IntlService from 'ember-intl/services/intl'; +import FlashMessages from 'ember-cli-flash/services/flash-messages'; +import Apollo from 'accent-webapp/services/apollo'; +import ApolloMutate from 'accent-webapp/services/apollo-mutate'; +import GlobalState from 'accent-webapp/services/global-state'; +import {tracked} from '@glimmer/tracking'; + +const FLASH_MESSAGE_CORRECT_SUCCESS = + 'pods.project.conflicts.flash_messages.correct_success'; +const FLASH_MESSAGE_CORRECT_ERROR = + 'pods.project.conflicts.flash_messages.correct_error'; +const FLASH_MESSAGE_UNCORRECT_SUCCESS = + 'pods.project.conflicts.flash_messages.uncorrect_success'; +const FLASH_MESSAGE_UNCORRECT_ERROR = + 'pods.project.conflicts.flash_messages.uncorrect_error'; +const FLASH_MESSAGE_UPDATE_SUCCESS = + 'pods.project.conflicts.flash_messages.update_success'; +const FLASH_MESSAGE_UPDATE_ERROR = + 'pods.project.conflicts.flash_messages.update_error'; + +export default class ConflictsController extends Controller { + @tracked + model: any; + + @service('intl') + intl: IntlService; + + @service('flash-messages') + flashMessages: FlashMessages; + + @service('apollo') + apollo: Apollo; + + @service('apollo-mutate') + apolloMutate: ApolloMutate; + + @service('global-state') + globalState: GlobalState; + + queryParams = [ + 'page', + 'query', + 'document', + 'version', + 'relatedRevisions', + 'isTextEmpty', + 'isTextNotEmpty', + 'isAddedLastSync', + 'isCommentedOn', + 'isTranslatedFilter' + ]; + + @tracked + query = ''; + + @tracked + document: string | null = null; + + @tracked + version: string | null = null; + + @tracked + relatedRevisions: string[] = []; + + @tracked + isTextEmpty: 'true' | null = null; + + @tracked + isTextNotEmpty: 'true' | null = null; + + @tracked + isAddedLastSync: 'true' | null = null; + + @tracked + isTranslated: 'true' | null = null; + + @tracked + isCommentedOn: 'true' | null = null; + + @tracked + page = 1; + + @readOnly('globalState.permissions') + permissions: any; + + @equal('model.groupedTranslations.entries', undefined) + emptyEntries: boolean; + + @and('emptyEntries', 'model.loading') + showLoading: boolean; + + @and('emptyEntries', 'model.loading') + showSkeleton: boolean; + + get withAdvancedFilters() { + return [ + this.isTextEmpty, + this.isTextNotEmpty, + this.isAddedLastSync, + this.isCommentedOn, + this.isTranslated + ].filter((filter) => filter === 'true').length; + } + + @action + changeAdvancedFilterBoolean( + key: + | 'isTextEmpty' + | 'isTextNotEmpty' + | 'isAddedLastSync' + | 'isCommentedOn' + | 'isTranslated', + event: InputEvent + ) { + this[key] = (event.target as HTMLInputElement).checked ? 'true' : null; + } + + @action + async correctConflict(conflict: any, text: string) { + const response = await this.apolloMutate.mutate({ + mutation: translationCorrectQuery, + variables: { + translationId: conflict.id, + text + } + }); + + if (response.errors) { + this.flashMessages.error(this.intl.t(FLASH_MESSAGE_CORRECT_ERROR)); + } else { + this.flashMessages.success(this.intl.t(FLASH_MESSAGE_CORRECT_SUCCESS)); + } + + return response; + } + + @action + async uncorrectConflict(conflict: any, text: string) { + const response = await this.apolloMutate.mutate({ + mutation: translationUncorrectQuery, + variables: { + translationId: conflict.id, + text + } + }); + + if (response.errors) { + this.flashMessages.error(this.intl.t(FLASH_MESSAGE_UNCORRECT_ERROR)); + } else { + this.flashMessages.success(this.intl.t(FLASH_MESSAGE_UNCORRECT_SUCCESS)); + } + + return response; + } + + @action + async updateConflict(conflict: any, text: string) { + const response = await this.apolloMutate.mutate({ + mutation: translationUpdateQuery, + variables: { + translationId: conflict.id, + text + } + }); + + if (response.errors) { + this.flashMessages.error(this.intl.t(FLASH_MESSAGE_UPDATE_ERROR)); + } else { + this.flashMessages.success(this.intl.t(FLASH_MESSAGE_UPDATE_SUCCESS)); + } + + return response; + } + + @action + changeQuery(query: string) { + this.page = 1; + this.query = query; + } + + @action + changeDocument(select: HTMLSelectElement) { + this.page = 1; + this.document = select.value ? select.value : null; + } + + @action + changeVersion(select: HTMLSelectElement) { + this.page = 1; + this.version = select.value ? select.value : null; + } + + @action + changeRelatedRevisions(choices: Array<{value: string}>) { + this.page = 1; + this.relatedRevisions = choices.map(({value}) => value); + } + + @action + selectPage(page: number) { + window.scrollTo(0, 0); + + this.page = page; + } +} diff --git a/webapp/app/pods/logged-in/project/edit/api-token/controller.ts b/webapp/app/controllers/logged-in/project/edit/api-token.ts similarity index 95% rename from webapp/app/pods/logged-in/project/edit/api-token/controller.ts rename to webapp/app/controllers/logged-in/project/edit/api-token.ts index 4851d8f53..468012627 100644 --- a/webapp/app/pods/logged-in/project/edit/api-token/controller.ts +++ b/webapp/app/controllers/logged-in/project/edit/api-token.ts @@ -51,7 +51,7 @@ export default class APITokenController extends Controller { async createApiToken({ name, pictureUrl, - permissions, + permissions }: { name: string; pictureUrl: string | null; @@ -67,8 +67,8 @@ export default class APITokenController extends Controller { projectId: project.id, pictureUrl, name, - permissions, - }, + permissions + } }); } @@ -79,8 +79,8 @@ export default class APITokenController extends Controller { successMessage: FLASH_MESSAGE_API_TOKEN_REVOKE_SUCCESS, errorMessage: FLASH_MESSAGE_API_TOKEN_REVOKE_ERROR, variables: { - id: apiToken.id, - }, + id: apiToken.id + } }); } @@ -88,7 +88,7 @@ export default class APITokenController extends Controller { mutation, variables, successMessage, - errorMessage, + errorMessage }: { mutation: any; variables: any; @@ -98,7 +98,7 @@ export default class APITokenController extends Controller { const response = await this.apolloMutate.mutate({ mutation, variables, - refetchQueries: ['ProjectApiToken'], + refetchQueries: ['ProjectApiToken'] }); if (response.errors) { diff --git a/webapp/app/pods/logged-in/project/edit/badges/controller.ts b/webapp/app/controllers/logged-in/project/edit/badges.ts similarity index 100% rename from webapp/app/pods/logged-in/project/edit/badges/controller.ts rename to webapp/app/controllers/logged-in/project/edit/badges.ts diff --git a/webapp/app/pods/logged-in/project/edit/index/controller.ts b/webapp/app/controllers/logged-in/project/edit/index.ts similarity index 90% rename from webapp/app/pods/logged-in/project/edit/index/controller.ts rename to webapp/app/controllers/logged-in/project/edit/index.ts index 33322302f..8fec65d9a 100644 --- a/webapp/app/pods/logged-in/project/edit/index/controller.ts +++ b/webapp/app/controllers/logged-in/project/edit/index.ts @@ -9,6 +9,7 @@ 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 RouterService from '@ember/routing/router-service'; const FLASH_MESSAGE_PREFIX = 'pods.project.edit.flash_messages.'; const FLASH_MESSAGE_PROJECT_SUCCESS = `${FLASH_MESSAGE_PREFIX}update_success`; @@ -29,6 +30,9 @@ export default class ProjectEditIndexController extends Controller { @service('global-state') globalState: GlobalState; + @service('router') + router: RouterService; + @readOnly('model.project') project: any; @@ -48,8 +52,8 @@ export default class ProjectEditIndexController extends Controller { const response = await this.apolloMutate.mutate({ mutation: projectDeleteQuery, variables: { - projectId: project.id, - }, + projectId: project.id + } }); if (response.errors) { @@ -59,7 +63,7 @@ export default class ProjectEditIndexController extends Controller { this.intl.t(FLASH_MESSAGE_DELETE_PROJECT_SUCCESS) ); - this.transitionToRoute('logged-in.projects'); + this.router.transitionTo('logged-in.projects'); } return response; @@ -75,8 +79,8 @@ export default class ProjectEditIndexController extends Controller { errorMessage: FLASH_MESSAGE_PROJECT_ERROR, variables: { projectId: project.id, - ...projectAttributes, - }, + ...projectAttributes + } }); } @@ -84,7 +88,7 @@ export default class ProjectEditIndexController extends Controller { mutation, variables, successMessage, - errorMessage, + errorMessage }: { mutation: any; variables: any; @@ -94,7 +98,7 @@ export default class ProjectEditIndexController extends Controller { const response = await this.apolloMutate.mutate({ mutation, variables, - refetchQueries: ['ProjectEdit'], + refetchQueries: ['ProjectEdit'] }); if (response.errors) { diff --git a/webapp/app/pods/logged-in/project/edit/jipt/controller.ts b/webapp/app/controllers/logged-in/project/edit/jipt.ts similarity index 100% rename from webapp/app/pods/logged-in/project/edit/jipt/controller.ts rename to webapp/app/controllers/logged-in/project/edit/jipt.ts diff --git a/webapp/app/pods/logged-in/project/edit/machine-translations/controller.ts b/webapp/app/controllers/logged-in/project/edit/machine-translations.ts similarity index 94% rename from webapp/app/pods/logged-in/project/edit/machine-translations/controller.ts rename to webapp/app/controllers/logged-in/project/edit/machine-translations.ts index 0ccf96d64..b6fa03b00 100644 --- a/webapp/app/pods/logged-in/project/edit/machine-translations/controller.ts +++ b/webapp/app/controllers/logged-in/project/edit/machine-translations.ts @@ -8,7 +8,7 @@ import FlashMessages from 'ember-cli-flash/services/flash-messages'; import ApolloMutate from 'accent-webapp/services/apollo-mutate'; import machineTranslationsConfigSaveQuery, { - SaveProjectMachineTranslationsConfigVariables, + SaveProjectMachineTranslationsConfigVariables } from 'accent-webapp/queries/save-project-machine-translations-config'; import machineTranslationsConfigDeleteQuery from 'accent-webapp/queries/delete-project-machine-translations-config'; @@ -51,7 +51,7 @@ export default class MachineTranslationController extends Controller { mutation: machineTranslationsConfigSaveQuery, successMessage: FLASH_MESSAGE_CONFIG_SUCCESS, errorMessage: FLASH_MESSAGE_CONFIG_ERROR, - variables: {...config, projectId: this.project.id}, + variables: {...config, projectId: this.project.id} }); } @@ -61,7 +61,7 @@ export default class MachineTranslationController extends Controller { mutation: machineTranslationsConfigDeleteQuery, successMessage: FLASH_MESSAGE_CONFIG_REMOVE_SUCCESS, errorMessage: FLASH_MESSAGE_CONFIG_REMOVE_ERROR, - variables: {projectId: this.project.id}, + variables: {projectId: this.project.id} }); } @@ -69,7 +69,7 @@ export default class MachineTranslationController extends Controller { mutation, variables, successMessage, - errorMessage, + errorMessage }: { mutation: any; variables: any; @@ -79,7 +79,7 @@ export default class MachineTranslationController extends Controller { const response = await this.apolloMutate.mutate({ mutation, variables, - refetchQueries: ['Project', 'ProjectMachineTranslationsConfig'], + refetchQueries: ['Project', 'ProjectMachineTranslationsConfig'] }); if (response.errors) { diff --git a/webapp/app/pods/logged-in/project/edit/prompts/controller.ts b/webapp/app/controllers/logged-in/project/edit/prompts.ts similarity index 79% rename from webapp/app/pods/logged-in/project/edit/prompts/controller.ts rename to webapp/app/controllers/logged-in/project/edit/prompts.ts index 1e9d52496..9779b6663 100644 --- a/webapp/app/pods/logged-in/project/edit/prompts/controller.ts +++ b/webapp/app/controllers/logged-in/project/edit/prompts.ts @@ -8,14 +8,12 @@ import FlashMessages from 'ember-cli-flash/services/flash-messages'; import ApolloMutate from 'accent-webapp/services/apollo-mutate'; import promptConfigSaveQuery, { - SaveProjectPromptConfigVariables, + SaveProjectPromptConfigVariables } from 'accent-webapp/queries/save-project-prompt-config'; import promptConfigDeleteQuery from 'accent-webapp/queries/delete-project-prompt-config'; import promptDeleteQuery from 'accent-webapp/queries/delete-project-prompt'; -import projectPromptConfigQuery, { - ProjectPromptConfigResponse, -} from 'accent-webapp/queries/project-prompt-config'; -import {InMemoryCache} from 'apollo-boost'; +import projectPromptConfigQuery from 'accent-webapp/queries/project-prompt-config'; +import {InMemoryCache} from '@apollo/client/cache'; const FLASH_MESSAGE_PREFIX = 'pods.project.edit.flash_messages.'; const FLASH_MESSAGE_CONFIG_SUCCESS = `${FLASH_MESSAGE_PREFIX}prompts_config_success`; @@ -59,7 +57,7 @@ export default class PromptsController extends Controller { mutation: promptConfigSaveQuery, successMessage: FLASH_MESSAGE_CONFIG_SUCCESS, errorMessage: FLASH_MESSAGE_CONFIG_ERROR, - variables: {...config, projectId: this.project.id}, + variables: {...config, projectId: this.project.id} }); } @@ -69,7 +67,7 @@ export default class PromptsController extends Controller { mutation: promptConfigDeleteQuery, successMessage: FLASH_MESSAGE_CONFIG_REMOVE_SUCCESS, errorMessage: FLASH_MESSAGE_CONFIG_REMOVE_ERROR, - variables: {projectId: this.project.id}, + variables: {projectId: this.project.id} }); } @@ -79,7 +77,7 @@ export default class PromptsController extends Controller { mutation: promptDeleteQuery, successMessage: FLASH_MESSAGE_PROMPT_REMOVE_SUCCESS, errorMessage: FLASH_MESSAGE_PROMPT_REMOVE_ERROR, - variables: {promptId}, + variables: {promptId} }); } @@ -87,7 +85,7 @@ export default class PromptsController extends Controller { mutation, variables, successMessage, - errorMessage, + errorMessage }: { mutation: any; variables: any; @@ -97,7 +95,7 @@ export default class PromptsController extends Controller { const response = await this.apolloMutate.mutate({ mutation, variables, - refetchQueries: ['Project', 'ProjectPromptConfig'], + refetchQueries: ['Project', 'ProjectPromptConfig'] }); if (response.errors) { @@ -113,7 +111,7 @@ export default class PromptsController extends Controller { mutation, variables, successMessage, - errorMessage, + errorMessage }: { mutation: any; variables: any; @@ -125,22 +123,26 @@ export default class PromptsController extends Controller { variables, refetchQueries: ['Project'], update: (cache: InMemoryCache) => { - const data = cache.readQuery({ - query: projectPromptConfigQuery, - variables: {projectId: this.project.id}, - }) as ProjectPromptConfigResponse; - - const prompts = data.viewer.project.prompts.filter( - (prompt) => prompt.id !== variables.promptId + cache.updateQuery( + { + query: projectPromptConfigQuery, + variables: {projectId: this.project.id} + }, + (data) => { + return { + viewer: { + ...data.viewer, + project: { + ...data.viewer.project, + prompts: data.viewer.project.prompts.filter( + (prompt: any) => prompt.id !== variables.promptId + ) + } + } + }; + } ); - data.viewer.project.prompts = prompts; - - cache.writeQuery({ - query: projectPromptConfigQuery, - variables: {projectId: this.project.id}, - data, - }); - }, + } }); if (response.errors) { diff --git a/webapp/app/pods/logged-in/project/edit/prompts/edit/controller.ts b/webapp/app/controllers/logged-in/project/edit/prompts/edit.ts similarity index 97% rename from webapp/app/pods/logged-in/project/edit/prompts/edit/controller.ts rename to webapp/app/controllers/logged-in/project/edit/prompts/edit.ts index fd72a58c0..195ea2207 100644 --- a/webapp/app/pods/logged-in/project/edit/prompts/edit/controller.ts +++ b/webapp/app/controllers/logged-in/project/edit/prompts/edit.ts @@ -50,7 +50,7 @@ export default class PromptsEditController extends Controller { async update({ content, name, - quickAccess, + quickAccess }: { name: string | null; content: string; @@ -60,7 +60,7 @@ export default class PromptsEditController extends Controller { mutation: promptUpdateQuery, successMessage: FLASH_MESSAGE_PROMPT_UPDATE_SUCCESS, errorMessage: FLASH_MESSAGE_PROMPT_UPDATE_ERROR, - variables: {id: this.prompt.id, content, name, quickAccess}, + variables: {id: this.prompt.id, content, name, quickAccess} }); } @@ -68,7 +68,7 @@ export default class PromptsEditController extends Controller { mutation, variables, successMessage, - errorMessage, + errorMessage }: { mutation: any; variables: any; @@ -79,7 +79,7 @@ export default class PromptsEditController extends Controller { const response = await this.apolloMutate.mutate({ mutation, - variables, + variables }); if (response.errors) { diff --git a/webapp/app/pods/logged-in/project/edit/prompts/new/controller.ts b/webapp/app/controllers/logged-in/project/edit/prompts/new.ts similarity index 77% rename from webapp/app/pods/logged-in/project/edit/prompts/new/controller.ts rename to webapp/app/controllers/logged-in/project/edit/prompts/new.ts index 3b98546af..4531d13cc 100644 --- a/webapp/app/pods/logged-in/project/edit/prompts/new/controller.ts +++ b/webapp/app/controllers/logged-in/project/edit/prompts/new.ts @@ -10,12 +10,10 @@ import ApolloMutate from 'accent-webapp/services/apollo-mutate'; import RouterService from '@ember/routing/router-service'; import promptCreateQuery, { - CreatePromptResponse, + CreatePromptResponse } from 'accent-webapp/queries/create-project-prompt'; -import projectPromptConfigQuery, { - ProjectPromptConfigResponse, -} from 'accent-webapp/queries/project-prompt-config'; -import {InMemoryCache} from 'apollo-boost'; +import projectPromptConfigQuery from 'accent-webapp/queries/project-prompt-config'; +import {InMemoryCache} from '@apollo/client/cache'; const FLASH_MESSAGE_PREFIX = 'pods.project.edit.flash_messages.'; const FLASH_MESSAGE_PROMPT_CREATE_SUCCESS = `${FLASH_MESSAGE_PREFIX}prompts_create_success`; @@ -50,7 +48,7 @@ export default class PromptsNewController extends Controller { async create({ content, name, - quickAccess, + quickAccess }: { name: string | null; content: string; @@ -60,7 +58,7 @@ export default class PromptsNewController extends Controller { mutation: promptCreateQuery, successMessage: FLASH_MESSAGE_PROMPT_CREATE_SUCCESS, errorMessage: FLASH_MESSAGE_PROMPT_CREATE_ERROR, - variables: {id: this.project.id, content, name, quickAccess}, + variables: {id: this.project.id, content, name, quickAccess} }); } @@ -68,7 +66,7 @@ export default class PromptsNewController extends Controller { mutation, variables, successMessage, - errorMessage, + errorMessage }: { mutation: any; variables: any; @@ -84,24 +82,29 @@ export default class PromptsNewController extends Controller { update: ( cache: InMemoryCache, { - data: {createProjectPrompt}, + data: {createProjectPrompt} }: {data: {createProjectPrompt: CreatePromptResponse}} ) => { - const data = cache.readQuery({ - query: projectPromptConfigQuery, - variables: {projectId: this.project.id}, - }) as ProjectPromptConfigResponse; - const prompts = data.viewer.project.prompts.concat([ - createProjectPrompt.prompt, - ]); - data.viewer.project.prompts = prompts; - - cache.writeQuery({ - query: projectPromptConfigQuery, - variables: {projectId: this.project.id}, - data, - }); - }, + cache.updateQuery( + { + query: projectPromptConfigQuery, + variables: {projectId: this.project.id} + }, + (data) => { + return { + viewer: { + ...data.viewer, + project: { + ...data.viewer.project, + prompts: data.viewer.project.prompts.concat([ + createProjectPrompt.prompt + ]) + } + } + }; + } + ); + } }); if (response.errors) { diff --git a/webapp/app/pods/logged-in/project/edit/service-integrations/controller.ts b/webapp/app/controllers/logged-in/project/edit/service-integrations.ts similarity index 94% rename from webapp/app/pods/logged-in/project/edit/service-integrations/controller.ts rename to webapp/app/controllers/logged-in/project/edit/service-integrations.ts index 862a8918a..314988256 100644 --- a/webapp/app/pods/logged-in/project/edit/service-integrations/controller.ts +++ b/webapp/app/controllers/logged-in/project/edit/service-integrations.ts @@ -48,7 +48,7 @@ export default class ServiceIntegrationsController extends Controller { async createIntegration({ data, events, - service, + service }: { data: any; events: any; @@ -64,8 +64,8 @@ export default class ServiceIntegrationsController extends Controller { projectId: project.id, data, events, - service, - }, + service + } }); } @@ -74,7 +74,7 @@ export default class ServiceIntegrationsController extends Controller { integration, data, events, - service, + service }: { integration: any; data: any; @@ -89,8 +89,8 @@ export default class ServiceIntegrationsController extends Controller { integrationId: integration.id, data, events, - service, - }, + service + } }); } @@ -101,8 +101,8 @@ export default class ServiceIntegrationsController extends Controller { successMessage: FLASH_MESSAGE_INTEGRATION_REMOVE_SUCCESS, errorMessage: FLASH_MESSAGE_INTEGRATION_REMOVE_ERROR, variables: { - integrationId: integration.id, - }, + integrationId: integration.id + } }); } @@ -110,7 +110,7 @@ export default class ServiceIntegrationsController extends Controller { mutation, variables, successMessage, - errorMessage, + errorMessage }: { mutation: any; variables: any; @@ -120,7 +120,7 @@ export default class ServiceIntegrationsController extends Controller { const response = await this.apolloMutate.mutate({ mutation, variables, - refetchQueries: ['ProjectServiceIntegrations'], + refetchQueries: ['ProjectServiceIntegrations'] }); if (response.errors) { diff --git a/webapp/app/pods/logged-in/project/files/controller.ts b/webapp/app/controllers/logged-in/project/files.ts similarity index 97% rename from webapp/app/pods/logged-in/project/files/controller.ts rename to webapp/app/controllers/logged-in/project/files.ts index 575223c3c..e5e3f1dda 100644 --- a/webapp/app/pods/logged-in/project/files/controller.ts +++ b/webapp/app/controllers/logged-in/project/files.ts @@ -52,8 +52,8 @@ export default class FilesController extends Controller { const response = await this.apolloMutate.mutate({ mutation: documentDeleteQuery, variables: { - documentId: documentEntity.id, - }, + documentId: documentEntity.id + } }); if (response.errors) { @@ -70,8 +70,8 @@ export default class FilesController extends Controller { mutation: documentUpdateQuery, variables: { documentId: documentEntity.id, - path, - }, + path + } }); if (response.errors) { diff --git a/webapp/app/pods/logged-in/project/files/add-translations/controller.ts b/webapp/app/controllers/logged-in/project/files/add-translations.ts similarity index 97% rename from webapp/app/pods/logged-in/project/files/add-translations/controller.ts rename to webapp/app/controllers/logged-in/project/files/add-translations.ts index 27f5f52a8..b5c23ec29 100644 --- a/webapp/app/pods/logged-in/project/files/add-translations/controller.ts +++ b/webapp/app/controllers/logged-in/project/files/add-translations.ts @@ -90,7 +90,7 @@ export default class AddTranslationsController extends Controller { revision, version, mergeType, - mergeOptions, + mergeOptions }: { fileSource: any; documentFormat: string; @@ -111,7 +111,7 @@ export default class AddTranslationsController extends Controller { documentPath, documentFormat, mergeType, - mergeOptions, + mergeOptions }); this.revisionOperations = revisionOperations; @@ -123,7 +123,7 @@ export default class AddTranslationsController extends Controller { revision, documentFormat, mergeType, - mergeOptions, + mergeOptions }: { fileSource: any; revision: any; @@ -143,7 +143,7 @@ export default class AddTranslationsController extends Controller { documentPath, documentFormat, mergeType, - mergeOptions, + mergeOptions }); this.flashMessages.success(this.intl.t(FLASH_MESSAGE_CREATE_SUCCESS)); diff --git a/webapp/app/pods/logged-in/project/files/export-all/controller.ts b/webapp/app/controllers/logged-in/project/files/export-all.ts similarity index 98% rename from webapp/app/pods/logged-in/project/files/export-all/controller.ts rename to webapp/app/controllers/logged-in/project/files/export-all.ts index 6b9b581f8..2c823bd8c 100644 --- a/webapp/app/pods/logged-in/project/files/export-all/controller.ts +++ b/webapp/app/controllers/logged-in/project/files/export-all.ts @@ -31,7 +31,7 @@ export default class ExportAllController extends Controller { 'versionFilter', 'isTextEmpty', 'isAddedLastSync', - 'isConflictedFilter', + 'isConflictedFilter' ]; @tracked @@ -135,7 +135,7 @@ export default class ExportAllController extends Controller { @action exportFile() { const blob = new Blob([this.fileRender], { - type: 'charset=utf-8', + type: 'charset=utf-8' }); const filename = `${this.document.path}.${this.fileExtension}`; diff --git a/webapp/app/pods/logged-in/project/files/export/controller.ts b/webapp/app/controllers/logged-in/project/files/export.ts similarity index 98% rename from webapp/app/pods/logged-in/project/files/export/controller.ts rename to webapp/app/controllers/logged-in/project/files/export.ts index df326c49d..56c2b8c8e 100644 --- a/webapp/app/pods/logged-in/project/files/export/controller.ts +++ b/webapp/app/controllers/logged-in/project/files/export.ts @@ -31,7 +31,7 @@ export default class ExportController extends Controller { 'versionFilter', 'isTextEmpty', 'isAddedLastSync', - 'isConflictedFilter', + 'isConflictedFilter' ]; @tracked @@ -144,7 +144,7 @@ export default class ExportController extends Controller { @action exportFile() { const blob = new Blob([this.fileRender], { - type: 'charset=utf-8', + type: 'charset=utf-8' }); const filename = `${this.document.path}.${this.fileExtension}`; diff --git a/webapp/app/pods/logged-in/project/files/jipt/controller.ts b/webapp/app/controllers/logged-in/project/files/jipt.ts similarity index 98% rename from webapp/app/pods/logged-in/project/files/jipt/controller.ts rename to webapp/app/controllers/logged-in/project/files/jipt.ts index bbd75a8cf..575b9ddad 100644 --- a/webapp/app/pods/logged-in/project/files/jipt/controller.ts +++ b/webapp/app/controllers/logged-in/project/files/jipt.ts @@ -90,7 +90,7 @@ export default class JIPTController extends Controller { @action exportFile() { const blob = new Blob([this.fileRender], { - type: 'charset=utf-8', + type: 'charset=utf-8' }); const filename = `${this.document.path}.${this.fileExtension}`; diff --git a/webapp/app/pods/logged-in/project/files/machine-translations/controller.ts b/webapp/app/controllers/logged-in/project/files/machine-translations.ts similarity index 98% rename from webapp/app/pods/logged-in/project/files/machine-translations/controller.ts rename to webapp/app/controllers/logged-in/project/files/machine-translations.ts index 78b7ef77c..292335c90 100644 --- a/webapp/app/pods/logged-in/project/files/machine-translations/controller.ts +++ b/webapp/app/controllers/logged-in/project/files/machine-translations.ts @@ -69,7 +69,7 @@ export default class MachineTranslationsController extends Controller { documentId: this.model.fileId, fromLanguage, toLanguage, - documentFormat, + documentFormat }); this.translatedFileContent = content; } catch (error) { diff --git a/webapp/app/pods/logged-in/project/files/new-machine-translations/controller.ts b/webapp/app/controllers/logged-in/project/files/new-machine-translations.ts similarity index 98% rename from webapp/app/pods/logged-in/project/files/new-machine-translations/controller.ts rename to webapp/app/controllers/logged-in/project/files/new-machine-translations.ts index 45478ed69..51d169ae6 100644 --- a/webapp/app/pods/logged-in/project/files/new-machine-translations/controller.ts +++ b/webapp/app/controllers/logged-in/project/files/new-machine-translations.ts @@ -52,7 +52,7 @@ export default class NewMachineTranslationsController extends Controller { file, fromLanguage, toLanguage, - documentFormat, + documentFormat }); this.translatedFileContent = content; } catch (error) { diff --git a/webapp/app/pods/logged-in/project/files/new-sync/controller.ts b/webapp/app/controllers/logged-in/project/files/new-sync.ts similarity index 97% rename from webapp/app/pods/logged-in/project/files/new-sync/controller.ts rename to webapp/app/controllers/logged-in/project/files/new-sync.ts index c0ef72674..0a10f2353 100644 --- a/webapp/app/pods/logged-in/project/files/new-sync/controller.ts +++ b/webapp/app/controllers/logged-in/project/files/new-sync.ts @@ -73,7 +73,7 @@ export default class NewSyncController extends Controller { documentPath, revision, version, - syncType, + syncType }: { fileSource: any; documentFormat: any; @@ -94,7 +94,7 @@ export default class NewSyncController extends Controller { file, documentPath, documentFormat, - syncType, + syncType }); this.revisionOperations = revisionOperations; @@ -107,7 +107,7 @@ export default class NewSyncController extends Controller { documentPath, revision, version, - syncType, + syncType }: { fileSource: any; documentFormat: any; @@ -127,7 +127,7 @@ export default class NewSyncController extends Controller { version, documentPath, documentFormat, - syncType, + syncType }); this.flashMessages.success(this.intl.t(FLASH_MESSAGE_CREATE_SUCCESS)); diff --git a/webapp/app/pods/logged-in/project/files/sync/controller.ts b/webapp/app/controllers/logged-in/project/files/sync.ts similarity index 98% rename from webapp/app/pods/logged-in/project/files/sync/controller.ts rename to webapp/app/controllers/logged-in/project/files/sync.ts index e2121b5a0..b45dcc559 100644 --- a/webapp/app/pods/logged-in/project/files/sync/controller.ts +++ b/webapp/app/controllers/logged-in/project/files/sync.ts @@ -88,7 +88,7 @@ export default class SyncController extends Controller { documentFormat, revision, version, - syncType, + syncType }: { fileSource: any; documentFormat: any; @@ -108,7 +108,7 @@ export default class SyncController extends Controller { file, documentPath, documentFormat, - syncType, + syncType }); this.revisionOperations = revisionOperations; @@ -120,7 +120,7 @@ export default class SyncController extends Controller { documentFormat, revision, version, - syncType, + syncType }: { fileSource: any; documentFormat: any; @@ -140,7 +140,7 @@ export default class SyncController extends Controller { file, documentPath, documentFormat, - syncType, + syncType }); this.flashMessages.success(this.intl.t(FLASH_MESSAGE_CREATE_SUCCESS)); diff --git a/webapp/app/pods/logged-in/project/index/controller.ts b/webapp/app/controllers/logged-in/project/index.ts similarity index 97% rename from webapp/app/pods/logged-in/project/index/controller.ts rename to webapp/app/controllers/logged-in/project/index.ts index 389b8706a..0b63ed8a1 100644 --- a/webapp/app/pods/logged-in/project/index/controller.ts +++ b/webapp/app/controllers/logged-in/project/index.ts @@ -59,7 +59,7 @@ export default class ProjectIndexController extends Controller { const response = await this.apolloMutate.mutate({ mutation: correctAllRevisionQuery, variables: {revisionId: revision.id}, - refetchQueries: ['Dashboard'], + refetchQueries: ['Dashboard'] }); if (response.errors) { @@ -78,7 +78,7 @@ export default class ProjectIndexController extends Controller { const response = await this.apolloMutate.mutate({ mutation: uncorrectAllRevisionQuery, variables: {revisionId: revision.id}, - refetchQueries: ['Dashboard'], + refetchQueries: ['Dashboard'] }); if (response.errors) { diff --git a/webapp/app/pods/logged-in/project/manage-languages/controller.ts b/webapp/app/controllers/logged-in/project/manage-languages.ts similarity index 97% rename from webapp/app/pods/logged-in/project/manage-languages/controller.ts rename to webapp/app/controllers/logged-in/project/manage-languages.ts index 0897047b5..966a5ff6b 100644 --- a/webapp/app/pods/logged-in/project/manage-languages/controller.ts +++ b/webapp/app/controllers/logged-in/project/manage-languages.ts @@ -72,8 +72,8 @@ export default class ManageLanguagesController extends Controller { const response = await this.apolloMutate.mutate({ mutation: revisionDeleteQuery, variables: { - revisionId: revision.id, - }, + revisionId: revision.id + } }); if (response.errors) { @@ -94,8 +94,8 @@ export default class ManageLanguagesController extends Controller { const response = await this.apolloMutate.mutate({ mutation: revisionMasterPromoteQuery, variables: { - revisionId: revision.id, - }, + revisionId: revision.id + } }); if (response.errors) { @@ -126,8 +126,8 @@ export default class ManageLanguagesController extends Controller { projectId: project.id, languageId, defaultNull: options.defaultNull, - machineTranslationsEnabled: options.machineTranslationsEnabled, - }, + machineTranslationsEnabled: options.machineTranslationsEnabled + } }); if (response.errors) { diff --git a/webapp/app/pods/logged-in/project/manage-languages/edit/controller.ts b/webapp/app/controllers/logged-in/project/manage-languages/edit.ts similarity index 97% rename from webapp/app/pods/logged-in/project/manage-languages/edit/controller.ts rename to webapp/app/controllers/logged-in/project/manage-languages/edit.ts index 3beb37535..adcc68d78 100644 --- a/webapp/app/pods/logged-in/project/manage-languages/edit/controller.ts +++ b/webapp/app/controllers/logged-in/project/manage-languages/edit.ts @@ -52,8 +52,8 @@ export default class ManageLanguagesEditController extends Controller { mutation: revisionUpdateQuery, variables: { revisionId: this.revision.id, - ...revisionAttributes, - }, + ...revisionAttributes + } }); if (response.errors) { diff --git a/webapp/app/pods/logged-in/project/revision/controller.ts b/webapp/app/controllers/logged-in/project/revision.ts similarity index 100% rename from webapp/app/pods/logged-in/project/revision/controller.ts rename to webapp/app/controllers/logged-in/project/revision.ts diff --git a/webapp/app/pods/logged-in/project/revision/lint-translations/controller.ts b/webapp/app/controllers/logged-in/project/revision/lint-translations.ts similarity index 100% rename from webapp/app/pods/logged-in/project/revision/lint-translations/controller.ts rename to webapp/app/controllers/logged-in/project/revision/lint-translations.ts diff --git a/webapp/app/pods/logged-in/project/revision/translations/controller.ts b/webapp/app/controllers/logged-in/project/revision/translations.ts similarity index 97% rename from webapp/app/pods/logged-in/project/revision/translations/controller.ts rename to webapp/app/controllers/logged-in/project/revision/translations.ts index fea9a4b6d..ba3ec9fed 100644 --- a/webapp/app/pods/logged-in/project/revision/translations/controller.ts +++ b/webapp/app/controllers/logged-in/project/revision/translations.ts @@ -37,7 +37,7 @@ export default class TranslationsController extends Controller { 'isAddedLastSync', 'isCommentedOn', 'isConflictedFilter', - 'isTranslatedFilter', + 'isTranslatedFilter' ]; @tracked @@ -95,7 +95,7 @@ export default class TranslationsController extends Controller { this.isAddedLastSync, this.isCommentedOn, this.isConflicted, - this.isTranslated, + this.isTranslated ].filter((filter) => filter === 'true').length; } @@ -144,8 +144,8 @@ export default class TranslationsController extends Controller { mutation: translationUpdateQuery, variables: { translationId: translation.id, - text, - }, + text + } }); if (response.errors) { diff --git a/webapp/app/pods/logged-in/project/translation/controller.ts b/webapp/app/controllers/logged-in/project/translation.ts similarity index 100% rename from webapp/app/pods/logged-in/project/translation/controller.ts rename to webapp/app/controllers/logged-in/project/translation.ts diff --git a/webapp/app/pods/logged-in/project/translation/activities/controller.ts b/webapp/app/controllers/logged-in/project/translation/activities.ts similarity index 100% rename from webapp/app/pods/logged-in/project/translation/activities/controller.ts rename to webapp/app/controllers/logged-in/project/translation/activities.ts diff --git a/webapp/app/pods/logged-in/project/translation/comments/controller.ts b/webapp/app/controllers/logged-in/project/translation/comments.ts similarity index 94% rename from webapp/app/pods/logged-in/project/translation/comments/controller.ts rename to webapp/app/controllers/logged-in/project/translation/comments.ts index a0412794d..751ed09c7 100644 --- a/webapp/app/pods/logged-in/project/translation/comments/controller.ts +++ b/webapp/app/controllers/logged-in/project/translation/comments.ts @@ -58,8 +58,8 @@ export default class CommentsController extends Controller { refetchQueries: ['TranslationComments'], variables: { translationId: translation.id, - text, - }, + text + } }); } @@ -70,8 +70,8 @@ export default class CommentsController extends Controller { refetchQueries: ['TranslationComments'], variables: { commentId: comment.id, - text: comment.text, - }, + text: comment.text + } }); } @@ -81,8 +81,8 @@ export default class CommentsController extends Controller { mutation: commentDeleteQuery, refetchQueries: ['TranslationComments'], variables: { - commentId: comment.id, - }, + commentId: comment.id + } }); if (response.errors) { @@ -103,8 +103,8 @@ export default class CommentsController extends Controller { refetchQueries: ['TranslationComments'], variables: { translationId: translation.id, - userId: user.id, - }, + userId: user.id + } }); } @@ -114,8 +114,8 @@ export default class CommentsController extends Controller { mutation: translationCommentsSubscriptionDeleteQuery, refetchQueries: ['TranslationComments'], variables: { - translationCommentsSubscripitionId: subscription.id, - }, + translationCommentsSubscripitionId: subscription.id + } }); } diff --git a/webapp/app/pods/logged-in/project/translation/editions/controller.ts b/webapp/app/controllers/logged-in/project/translation/editions.ts similarity index 95% rename from webapp/app/pods/logged-in/project/translation/editions/controller.ts rename to webapp/app/controllers/logged-in/project/translation/editions.ts index f2eb24589..0347d67c4 100644 --- a/webapp/app/pods/logged-in/project/translation/editions/controller.ts +++ b/webapp/app/controllers/logged-in/project/translation/editions.ts @@ -29,7 +29,7 @@ export default class TranslationEditionsController extends Controller { @readOnly('globalState.permissions') permissions: any; - @readOnly('model.revisionModel.project.revisions') + @readOnly('model.translationModel.revisions') revisions: any; @equal('model.translations', undefined) @@ -50,8 +50,8 @@ export default class TranslationEditionsController extends Controller { mutation: translationUpdateQuery, variables: { translationId: translation.id, - text, - }, + text + } }); if (response.errors) { diff --git a/webapp/app/pods/logged-in/project/translation/index/controller.ts b/webapp/app/controllers/logged-in/project/translation/index.ts similarity index 97% rename from webapp/app/pods/logged-in/project/translation/index/controller.ts rename to webapp/app/controllers/logged-in/project/translation/index.ts index 33e84a4cb..62a1df965 100644 --- a/webapp/app/pods/logged-in/project/translation/index/controller.ts +++ b/webapp/app/controllers/logged-in/project/translation/index.ts @@ -53,8 +53,8 @@ export default class IndexController extends Controller { mutation: translationCorrectQuery, variables: { translationId: conflict.id, - text, - }, + text + } }); if (response.errors) { @@ -72,8 +72,8 @@ export default class IndexController extends Controller { mutation: translationUncorrectQuery, variables: { translationId: conflict.id, - text, - }, + text + } }); if (response.errors) { @@ -91,8 +91,8 @@ export default class IndexController extends Controller { mutation: translationUpdateQuery, variables: { translationId: translation.id, - text, - }, + text + } }); if (response.errors) { @@ -108,8 +108,8 @@ export default class IndexController extends Controller { mutation: translationUpdateQuery, variables: { translationId: translation.id, - text, - }, + text + } }); if (response.errors) { diff --git a/webapp/app/pods/logged-in/project/versions/controller.ts b/webapp/app/controllers/logged-in/project/versions.ts similarity index 100% rename from webapp/app/pods/logged-in/project/versions/controller.ts rename to webapp/app/controllers/logged-in/project/versions.ts diff --git a/webapp/app/pods/logged-in/project/versions/edit/controller.ts b/webapp/app/controllers/logged-in/project/versions/edit.ts similarity index 88% rename from webapp/app/pods/logged-in/project/versions/edit/controller.ts rename to webapp/app/controllers/logged-in/project/versions/edit.ts index 26c2b0868..60577b6ab 100644 --- a/webapp/app/pods/logged-in/project/versions/edit/controller.ts +++ b/webapp/app/controllers/logged-in/project/versions/edit.ts @@ -60,11 +60,16 @@ export default class EditController extends Controller { } @action - async update({name, tag}: {name: string; tag: string}) { + async update(args: { + name: string; + tag: string; + copyOnUpdateTranslation: boolean; + }) { this.error = false; - name = name || ''; - tag = tag || ''; + const name = args.name || ''; + const tag = args.tag || ''; + const copyOnUpdateTranslation = args.copyOnUpdateTranslation || false; const id = this.version.id; const response = await this.apolloMutate.mutate({ @@ -73,7 +78,8 @@ export default class EditController extends Controller { id, name, tag, - }, + copyOnUpdateTranslation + } }); if (response.errors) { diff --git a/webapp/app/pods/logged-in/project/versions/export/controller.ts b/webapp/app/controllers/logged-in/project/versions/export.ts similarity index 98% rename from webapp/app/pods/logged-in/project/versions/export/controller.ts rename to webapp/app/controllers/logged-in/project/versions/export.ts index 1446de079..0f054ebfc 100644 --- a/webapp/app/pods/logged-in/project/versions/export/controller.ts +++ b/webapp/app/controllers/logged-in/project/versions/export.ts @@ -24,7 +24,7 @@ export default class ExportController extends Controller { 'revisionFilter', 'documentFilter', 'documentFormatFilter', - 'orderByFilter', + 'orderByFilter' ]; @tracked @@ -118,7 +118,7 @@ export default class ExportController extends Controller { exportFile() { const blob = new Blob([this.fileRender], { - type: 'charset=utf-8', + type: 'charset=utf-8' }); const filename = `${this.document.path}.${this.fileExtension}`; diff --git a/webapp/app/pods/logged-in/project/versions/new/controller.ts b/webapp/app/controllers/logged-in/project/versions/new.ts similarity index 86% rename from webapp/app/pods/logged-in/project/versions/new/controller.ts rename to webapp/app/controllers/logged-in/project/versions/new.ts index 9255228ab..a1b11d8f2 100644 --- a/webapp/app/pods/logged-in/project/versions/new/controller.ts +++ b/webapp/app/controllers/logged-in/project/versions/new.ts @@ -46,11 +46,16 @@ export default class NewController extends Controller { } @action - async create({name, tag}: {name: string; tag: string}) { + async create(args: { + name: string; + tag: string; + copyOnUpdateTranslation: boolean; + }) { this.error = false; - name = name || ''; - tag = tag || ''; + const name = args.name || ''; + const tag = args.tag || ''; + const copyOnUpdateTranslation = args.copyOnUpdateTranslation || false; const projectId = this.project.id; const response = await this.apolloMutate.mutate({ @@ -59,7 +64,8 @@ export default class NewController extends Controller { projectId, name, tag, - }, + copyOnUpdateTranslation + } }); if (response.errors) { diff --git a/webapp/app/pods/logged-in/projects/controller.ts b/webapp/app/controllers/logged-in/projects.ts similarity index 100% rename from webapp/app/pods/logged-in/projects/controller.ts rename to webapp/app/controllers/logged-in/projects.ts diff --git a/webapp/app/pods/logged-in/projects/new/controller.ts b/webapp/app/controllers/logged-in/projects/new.ts similarity index 96% rename from webapp/app/pods/logged-in/projects/new/controller.ts rename to webapp/app/controllers/logged-in/projects/new.ts index 18e778645..08202031a 100644 --- a/webapp/app/pods/logged-in/projects/new/controller.ts +++ b/webapp/app/controllers/logged-in/projects/new.ts @@ -5,7 +5,7 @@ import RouterService from '@ember/routing/router-service'; import projectCreateQuery, { CreateProjectVariables, - CreateProjectResponse, + CreateProjectResponse } from 'accent-webapp/queries/create-project'; import ApolloMutate from 'accent-webapp/services/apollo-mutate'; import Session from 'accent-webapp/services/session'; @@ -40,8 +40,8 @@ export default class ProjectsNewController extends Controller { mutation: projectCreateQuery, variables: { ...projectAttributes, - name, - }, + name + } }); if (response.errors) { diff --git a/webapp/app/pods/login/controller.ts b/webapp/app/controllers/login.ts similarity index 100% rename from webapp/app/pods/login/controller.ts rename to webapp/app/controllers/login.ts diff --git a/webapp/app/pods/not-found/controller.ts b/webapp/app/controllers/not-found.ts similarity index 100% rename from webapp/app/pods/not-found/controller.ts rename to webapp/app/controllers/not-found.ts diff --git a/webapp/app/formats.js b/webapp/app/formats.js deleted file mode 100644 index 5144c1d6d..000000000 --- a/webapp/app/formats.js +++ /dev/null @@ -1,24 +0,0 @@ -export default { - time: { - hhmmss: { - hour: 'numeric', - minute: 'numeric', - second: 'numeric', - }, - }, - date: { - hhmmss: { - hour: 'numeric', - minute: 'numeric', - second: 'numeric', - }, - }, - number: { - USD: { - style: 'currency', - currency: 'USD', - minimumFractionDigits: 2, - maximumFractionDigits: 2, - }, - }, -}; diff --git a/webapp/app/helpers/string-diff.ts b/webapp/app/helpers/string-diff.ts index 6fdb87eca..23a3036ed 100644 --- a/webapp/app/helpers/string-diff.ts +++ b/webapp/app/helpers/string-diff.ts @@ -42,7 +42,7 @@ const escape = { '"': '"', "'": ''', '`': '`', - '=': '=', + '=': '=' }; const escapeChar = (chr: keyof typeof escape) => { diff --git a/webapp/app/helpers/time-ago-in-words.ts b/webapp/app/helpers/time-ago-in-words.ts index 29f30aa83..c43526f48 100644 --- a/webapp/app/helpers/time-ago-in-words.ts +++ b/webapp/app/helpers/time-ago-in-words.ts @@ -1,16 +1,16 @@ import {isBlank} from '@ember/utils'; import {helper} from '@ember/component/helper'; -import formatDistanceToNow from 'date-fns/formatDistanceToNow'; +import {formatDistanceToNow} from 'date-fns'; import {frCA, enUS} from 'date-fns/locale'; const LOCALES = { 'fr-ca': frCA, - 'en-us': enUS, + 'en-us': enUS } as any; const OPTIONS = { addSuffix: true, - includeSeconds: false, + includeSeconds: false }; const timeAgoInWords = ([date]: [string]) => { @@ -19,7 +19,7 @@ const timeAgoInWords = ([date]: [string]) => { const options = { locale, - ...OPTIONS, + ...OPTIONS }; 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 83885b8a8..fd3b9825c 100644 --- a/webapp/app/instance-initializers/raven-setup.js +++ b/webapp/app/instance-initializers/raven-setup.js @@ -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 d87a6594f..cbe08d881 100644 --- a/webapp/app/locales/en-us.json +++ b/webapp/app/locales/en-us.json @@ -62,6 +62,7 @@ "slack": "Login with Slack →", "discord": "Login with Discord →", "microsoft": "Login with Microsoft →", + "oidc": "Login with OpenID Connect →", "dummy": "Enter an email and login →" }, "dummy_login_form": { @@ -141,16 +142,26 @@ "reload_button": "Reload" }, "conflicts_filters": { + "advanced_filters_button": "Advanced filters", "total_entries_count": "{count, plural, =0 {No strings to review} =1 {1 string to review} other {# strings to review}}", "reference_default_option_text": "No reference language", "version_default_option_text": "Latest version", "document_default_option_text": "All documents", - "input_placeholder_text": "Search for a string" + "input_placeholder_text": "Search for a string", + "advanced_filters_title": "Advanced filters", + "advanced_filters": { + "empty": "Text is empty (\"\" or null value)", + "not_empty": "Text is not empty", + "added_last_sync": "Strings added last sync", + "commented_on": "Strings with comments", + "conflicted": "To review", + "translated": "To translate" + } }, - "conflicts_items": { - "translations_version_notice": "You are viewing strings to review for the version", + "conflicts_list": { + "translations_version_notice": "You are viewing the strings to be reviewed in the version", "correct_all_button": "Mark all strings as reviewed for this language", - "no_translations": "No strings to review for: {query}", + "no_translations": "No strings found for: {query}", "all_reviewed_title": "All reviewed", "all_reviewed_subtitle": "All strings have been marked as reviewed" }, @@ -206,7 +217,9 @@ "rtl_badge": "RTL", "rtl": "Right to left text", "correct_all_button": "Mark all strings as reviewed", - "uncorrect_all_button": "Put all strings back in review" + "uncorrect_all_button": "Put all strings back in review", + "stats_translated": "translated", + "stats_to_review": "to review" } }, "date_tag": { @@ -404,6 +417,7 @@ "title": "AI Assistant", "help": "Instructions will be available on all string inputs to help you improve your content. The clearer the instructions you give to the assistant, to better the output will be.", "new_button": "Add a new instruction", + "use_platform_label": "Use the platform config if available", "config_key_help_present": "Config key has been set, but the value will never be exposed via the API.", "config_key_help_not_present": "Once saved, the config key will never be shown.", "delete_confirm": "Are you sure you want to delete this instruction?" @@ -428,7 +442,8 @@ "jipt": { "title": "Just In Place Translations", "integration_help": "This steps will walk you throught the setup you need to have in your project to translate your strings in your browser, inside your project.", - "integration_link": "See official guides on how to integrate live editing in your website ->", + "demo_help": "See a static HTML page that renders the first string of your project in different context. The Accent live integration can be seen at the bottom of the page. Note that the live example use your real project’s data.", + "demo_link": "Open example →", "add_language_title": "Add the pseudo language to your project", "add_language_image_1": "Here is a language like you already have in your project:", "add_language_image_2": "Here is the pseudo language named \"accent\" that act as a normal translation in your project:", @@ -472,6 +487,7 @@ "developer_text": "Can make file operations: Sync, add translations and preview those operations in the UI.", "owner_text": "With the same roles as the admin, the owners are people who the project belongs to.", "reviewer_text": "Can do every tasks except those listed in the above roles. Review, update strings, comments, etc.", + "translator_text": "Translate strings and make updates on documents. The translator is not included in the review process.", "title": "Collaborators" }, "collaborators_item": { @@ -494,9 +510,19 @@ "last_executed_at": "Last executed at:", "data": { "azure_storage_container_sas": "SAS URL", + "aws_s3_bucket": "Bucket name", + "aws_s3_path_prefix": "Path prefix", + "aws_s3_region": "Region", + "aws_s3_access_key_id": "Access Key ID", + "aws_s3_secret_access_key": "Secret Access Key", + "aws_s3_minimum_policy": "Minimum policy", "url": "URL" }, "empty_description": { + "aws_s3": { + "title": "AWS S3", + "text": "Upload your files in Amazon Web Services S3 to serve them directly in your application" + }, "azure_storage_container": { "title": "Azure Storage Container", "text": "Upload your files in Azure Storage Container to serve them directly in your application" @@ -510,21 +536,33 @@ "text": "Post your project’s notifications in Slack" } }, - "token_how": "How?", - "github_webhook_url_how": "How?", - "github_webhook_accent_cli_1": "You need to have a valid accent-cli setup for the hook to work.", - "github_webhook_accent_cli_2": "The accent.json file at the root of your project will be used.", - "github_webhook_url": "Make sure to add the webhook in your project’s settings", "webhook_url_how": "How to obtain a webhook URL?", "events": { "title": "Which events would you like to trigger this webhook?", "options": { "sync": "Sync with any changes", "new_conflicts": "New strings to review", - "complete_review": "Project is 100% reviewed" + "complete_review": "Project is 100% reviewed", + "integration_execute_azure_storage_container": "Files uploaded to Azure Storage Container" } }, "execute": { + "aws_s3": { + "title": "Upload files to AWS S3", + "cancel_button": "Cancel", + "error": "Error while pushing to your bucket. Check your credentials and try again.", + "push_button": "Upload", + "bucket": "Bucket", + "path_prefix": "Path prefix", + "submit_confirm": "Uploading files to AWS S3 can override existing files if you upload for the latest or an already uploaded version tag.", + "target_version": { + "label": "Target Version", + "options": { + "latest": "Latest Version", + "specific": "Specific Version" + } + } + }, "azure_storage_container": { "title": "Upload files to Azure Storage Container", "cancel_button": "Cancel", @@ -661,6 +699,8 @@ "error": "Invalid version", "cancel_button": "Cancel", "name_label": "Name:", + "copy_on_update_translation_help": "Everytime a translation in this version is updated, the same text will be applied to the latest translation. This will make sure that a fix in frozen version will also be present in the latest version without any required actions by the developer or the reviewer.", + "copy_on_update_translation_label": "Copy on update translation", "tag_label": "Tag:", "save_button": "Create" }, @@ -668,6 +708,8 @@ "title": "Update version", "error": "Invalid version", "cancel_button": "Cancel", + "copy_on_update_translation_help": "Everytime a translation in this version is updated, the same text will be applied to the latest translation. This will make sure that a fix in frozen version will also be present in the latest version without any required actions by the developer or the reviewer.", + "copy_on_update_translation_label": "Copy on update translation", "name_label": "Name:", "tag_label": "Tag:", "save_button": "Update" @@ -721,6 +763,7 @@ "translations_link_title": "All strings", "lint_link_title": "Checks", "conflicts_link_title": "Review", + "translate_link_title": "Translate", "dashboard_link_title": "Dashboard", "settings_link_title": "Settings", "sync_link_title": "Files", @@ -999,7 +1042,8 @@ "integration_services": { "DISCORD": "Discord", "SLACK": "Slack", - "AZURE_STORAGE_CONTAINER": "Azure Storage Container" + "AZURE_STORAGE_CONTAINER": "Azure Storage Container", + "AWS_S3": "AWS S3" }, "search_input_placeholder_text": "Search for a string…" }, @@ -1090,7 +1134,9 @@ "unsupported_source_and_target": "The string could not be translated: Unsupported source {source} and target {target}" }, "correct_error": "The string could not be marked as reviewed", - "correct_success": "The string as been marked as reviewed with success" + "correct_success": "The string as been marked as reviewed with success", + "update_error": "The string could not be updated", + "update_success": "The string has been updated with success" } }, "edit": { @@ -1105,6 +1151,8 @@ "collaborator_update_success": "The collaborator has been updated with success", "integration_add_error": "The integration could not be added", "integration_add_success": "The integration has been added with success", + "integration_execute_error": "The integration could not be executed", + "integration_execute_success": "The integration has been executed with success", "integration_update_error": "The integration could not be updated", "integration_update_success": "The integration has been updated with success", "integration_remove_error": "The integration could not be removed", diff --git a/webapp/app/locales/fr-ca.json b/webapp/app/locales/fr-ca.json index 382543322..1d413b944 100644 --- a/webapp/app/locales/fr-ca.json +++ b/webapp/app/locales/fr-ca.json @@ -78,6 +78,7 @@ "slack": "Se connecter avec Slack →", "discord": "Se connecter avec Discord →", "microsoft": "Se connecter avec Microsoft →", + "oidc": "Connectez-vous avec OIDC →", "dummy": "Entrez un courriel et connectez-vous →" }, "dummy_login_form": { @@ -157,13 +158,23 @@ "reload_button": "Recharger" }, "conflicts_filters": { + "advanced_filters_button": "Filtres avancés", "total_entries_count": "{count, plural, =0 {Aucune chaîne à vérifier} =1 {1 chaîne à vérifier} other {# chaînes à vérifier}}", "reference_default_option_text": "Pas de langue de référence", "version_default_option_text": "Dernière version", "document_default_option_text": "Tous les documents", - "input_placeholder_text": "Rechercher une chaîne" + "input_placeholder_text": "Rechercher une chaîne", + "advanced_filters_title": "Filtres avancés", + "advanced_filters": { + "empty": "Le texte est vide (\"\" ou valeur nulle)", + "not_empty": "Le texte n’est pas vide", + "added_last_sync": "Ajoutées à la dernière synchronisation", + "commented_on": "Chaînes avec commentaires", + "conflicted": "À réviser", + "translated": "À traduire" + } }, - "conflicts_items": { + "conflicts_list": { "translations_version_notice": "Vous consultez les textes à réviser de la version", "correct_all_button": "Marquer toutes les chaînes comme révisées pour cette langue", "no_translations": "Aucune chaîne à examiner pour : {query}", @@ -222,7 +233,9 @@ "rtl_badge": "RTL", "rtl": "Texte de droite à gauche", "correct_all_button": "Marquer toutes les chaînes comme vérifiées", - "uncorrect_all_button": "Remettre toutes les chaînes à réviser" + "uncorrect_all_button": "Remettre toutes les chaînes à réviser", + "stats_translated": "traduits", + "stats_to_review": "à réviser" } }, "date_tag": { @@ -392,6 +405,7 @@ "prompts": { "title": "Assistant IA", "help": "Des instructions seront disponibles sur chaque entrée de chaîne pour vous aider à améliorer votre contenu. Plus les instructions que vous donnez à l’assistant sont claires, meilleur sera le résultat.", + "use_platform_label": "Utilisez la configuration de la plate-forme si disponible", "new_button": "Ajouter une nouvelle instruction", "config_key_help_present": "La clé de configuration a été définie, mais la valeur ne sera jamais exposée via l’API.", "config_key_help_not_present": "Une fois enregistrée, la clé de configuration ne sera jamais affichée.", @@ -444,7 +458,8 @@ "jipt": { "title": "Traductions JIPT", "integration_help": "Cette étape vous guidera à travers la configuration dont vous avez besoin dans votre projet pour traduire vos chaînes dans votre navigateur, à l’intérieur de votre projet.", - "integration_link": "Voir les guides officiels sur la façon d’intégrer l’édition en direct dans votre site Web ->", + "demo_help": "Voir une page HTML statique qui montre la première chaîne de votre projet dans un contexte différent. L’intégration d’Accent est visible en bas de la page. Notez que l’exemple utilise les vraies données de votre projet.", + "demo_link": "Ouvrir l’exemple →", "add_language_title": "Ajoutez le pseudo langage à votre projet", "add_language_image_1": "Voici un langage comme vous en avez déjà dans votre projet :", "add_language_image_2": "Voici le pseudo langage nommé \"accent\" qui agit comme une traduction normale dans votre projet :", @@ -488,6 +503,7 @@ "developer_text": "Peut effectuer des opérations sur les fichiers : synchroniser, ajouter des traductions et prévisualiser ces opérations dans l’interface utilisateur.", "owner_text": "Avec les mêmes rôles que l’administrateur, les propriétaires sont les personnes à qui appartient le projet.", "reviewer_text": "Peut effectuer toutes les tâches sauf celles énumérées dans les rôles ci-dessus. Réviser, mettre à jour les chaînes, les commentaires, etc.", + "translator_text": "Traduire des chaînes et effectuez des mises à jour sur les fichiers. Le traducteur n’est pas inclus dans le processus de révision.", "title": "Collaborateurs" }, "collaborators_item": { @@ -510,9 +526,19 @@ "delete": "Supprimer", "data": { "azure_storage_container_sas": "SAS URL", + "aws_s3_bucket": "Nom du bucket", + "aws_s3_path_prefix": "Préfix", + "aws_s3_region": "Région", + "aws_s3_access_key_id": "Access Key ID", + "aws_s3_secret_access_key": "Secret Access Key", + "aws_s3_minimum_policy": "Permissions minimums", "url": "URL" }, "empty_description": { + "aws_s3": { + "title": "AWS S3", + "text": "Téléchargez vos fichiers dans Amazon Web Service S3 pour les servir directement dans votre application" + }, "azure_storage_container": { "title": "Azure Storage Container", "text": "Téléchargez vos fichiers dans Azure Storage Container pour les servir directement dans votre application" @@ -526,21 +552,33 @@ "text": "Publiez les notifications de votre projet dans Slack" } }, - "token_how": "Comment?", - "github_webhook_url_how": "Comment?", - "github_webhook_accent_cli_1": "Vous devez avoir une configuration accent-cli valide pour le crochet au travail.", - "github_webhook_accent_cli_2": "Le accent.json fichier à la racine de votre projet sera utilisé.", - "github_webhook_url": "Assurez-vous d’ajouter le webhook dans les paramètres de votre projet", "webhook_url_how": "Comment obtenir une URL de webhook ?", "events": { "title": "Quels événements souhaitez-vous déclencher ce webhook ?", "options": { "sync": "Synchroniser avec n’importe quelles modifications", "new_conflicts": "Nouvelles chaîne à réviser", - "complete_review": "Le projet est revu à 100%" + "complete_review": "Le projet est revu à 100%", + "integration_execute_azure_storage_container": "Fichiers téléversés sur Azure Storage Container" } }, "execute": { + "aws_s3": { + "title": "Publier sur AWS S3", + "cancel_button": "Annuler", + "error": "Une erreur s’est produite lors de la publication sur Azure. Veuillez vérifier vos informations d’identification et réessayer.", + "push_button": "Publier", + "bucket": "Nom du bucket", + "path_prefix": "Préfix", + "submit_confirm": "La publication de fichiers vers AWS S3 peut remplacer les fichiers existants si vous publiez la dernière version ou une version déjà publiée.", + "target_version": { + "label": "Version Cible", + "options": { + "latest": "Dernière version", + "specific": "Version spécifique" + } + } + }, "azure_storage_container": { "title": "Publier sur Azure Storage Container", "cancel_button": "Annuler", @@ -675,6 +713,8 @@ "title": "Nouvelle version", "text": "La création d’une version crée un instantané de toutes les chaînes actives (révisées ou non) pour être visible avec la certitude qu’il restera intact. Cela peut être utile lors de la maintenance de plusieurs versions de la même application.", "error": "Version invalide", + "copy_on_update_translation_help": "Chaque fois qu'une traduction dans cette version est mise à jour, le même texte sera appliqué à la traduction source (dernière version). Cela garantira qu'un correctif dans la version sera également présent dans la dernière version sans aucune action requise de la part du développeur ou le traducteur.", + "copy_on_update_translation_label": "Copie sur mise à jour de la traduction", "cancel_button": "Annuler", "name_label": "Nom:", "tag_label": "Étiquette:", @@ -683,6 +723,8 @@ "version_update_form": { "title": "Version de mise à jour", "error": "Version invalide", + "copy_on_update_translation_help": "Chaque fois qu'une traduction dans cette version est mise à jour, le même texte sera appliqué à la traduction source (dernière version). Cela garantira qu'un correctif dans la version sera également présent dans la dernière version sans aucune action requise de la part du développeur ou le traducteur.", + "copy_on_update_translation_label": "Copie sur mise à jour de la traduction", "cancel_button": "Annuler", "name_label": "Nom:", "tag_label": "Étiquette:", @@ -720,6 +762,7 @@ "manage_languages_link_title": "Langues", "translations_link_title": "Chaînes", "lint_link_title": "Vérifier", + "translate_link_title": "Traduire", "conflicts_link_title": "Réviser", "dashboard_link_title": "Tableau de bord", "settings_link_title": "Paramètres", @@ -853,7 +896,7 @@ "source_translation": "Voir la dernière version de la chaîne", "correct_button": "Mettre à jour et marquer comme révisé", "previous_text": "Texte précédent :", - "uncorrect_button": "Remettre à révisée", + "uncorrect_button": "Remettre à réviser", "uneditable": "Le texte n’est pas modifiable, car il a été marqué comme révisé", "update_text": "Mettre à jour le texte", "form": { @@ -999,7 +1042,8 @@ "integration_services": { "DISCORD": "Discord", "SLACK": "Slack", - "AZURE_STORAGE_CONTAINER": "Azure Storage Container" + "AZURE_STORAGE_CONTAINER": "Azure Storage Container", + "AWS_S3": "AWS S3" }, "search_input_placeholder_text": "Rechercher une chaîne…" }, @@ -1085,6 +1129,8 @@ "revision_correct_error": "Une erreur s’est produite lors du marquage de toutes les chaînes dans cette langue comme révisées", "correct_error": "Impossible de marquer la chaîne comme vérifiée", "correct_success": "La chaîne a été marquée comme révisée avec succès", + "update_error": "La chaîne n’a pas pu être mise à jour", + "update_success": "La chaîne a été mise à jour avec succès", "translate_provider_error": "La chaîne n’a pas pu être traduite : {provider}", "translate_error": { "unsupported_target": "La chaîne n’a pas pu être traduite : Langue non prise en charge {target}", @@ -1121,6 +1167,8 @@ "integration_update_success": "L’intégration a été mise à jour avec succès", "integration_remove_error": "L’intégration n’a pas pu être supprimée", "integration_remove_success": "L’intégration a été supprimée avec succès", + "integration_execute_error": "L’intégration n’a pas pu être exécutée", + "integration_execute_success": "L’intégration a été exécutée avec succès", "machine_translations_config_error": "La configuration n’a pas pu être mise à jour", "machine_translations_config_success": "La configuration a été mise à jour avec succès", "update_error": "Le projet n’a pas pu être mis à jour", diff --git a/webapp/app/pods/components/acc-emoji-picker/component.ts b/webapp/app/pods/components/acc-emoji-picker/component.ts deleted file mode 100644 index 10bd49adf..000000000 --- a/webapp/app/pods/components/acc-emoji-picker/component.ts +++ /dev/null @@ -1,37 +0,0 @@ -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.isPickerVisible() - ? 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 deleted file mode 100644 index 6a41f2522..000000000 --- a/webapp/app/pods/components/acc-emoji-picker/template.hbs +++ /dev/null @@ -1,5 +0,0 @@ - \ No newline at end of file diff --git a/webapp/app/pods/components/conflicts-filters/styles.scss b/webapp/app/pods/components/conflicts-filters/styles.scss deleted file mode 100644 index 6f4282b60..000000000 --- a/webapp/app/pods/components/conflicts-filters/styles.scss +++ /dev/null @@ -1,66 +0,0 @@ -.filters-wrapper { - display: flex; - justify-content: space-between; - align-items: flex-start; -} - -.filters-content { - flex-grow: 1; - margin-right: 15px; -} - -.queryForm { - position: relative; -} - -.totalEntries { - flex-shrink: 0; - margin-top: 10px; - color: var(--color-grey); - font-size: 12px; -} - -.search-icon { - position: absolute; - top: 50%; - margin-top: -10px; - left: 7px; - width: 20px; - height: 20px; - stroke: #b7b7b7; -} - -.input { - @extend %textInput; - width: 100%; - padding: 7px 7px 7px 30px; - font-family: var(--font-primary); - font-size: 14px; - color: var(--color-black); - - &:focus { - box-shadow: inset 0 1px 2px rgba(#000, 0.1), 0 1px 2px var(--shadow-color); - } - - &::placeholder { - color: var(--color-grey); - } -} - -.totalEntries { - margin-top: 10px; - color: var(--color-grey); - font-size: 12px; -} - -@media (max-width: 440px) { - .filters-wrapper { - flex-direction: column; - } - - .queryForm, - .filters-content { - width: 100%; - margin-right: 0; - } -} diff --git a/webapp/app/pods/components/conflicts-filters/template.hbs b/webapp/app/pods/components/conflicts-filters/template.hbs deleted file mode 100644 index ef6dcbf4c..000000000 --- a/webapp/app/pods/components/conflicts-filters/template.hbs +++ /dev/null @@ -1,58 +0,0 @@ -
-
-
-
-
- {{inline-svg '/assets/search.svg' local-class='search-icon'}} - - -
- -
-
- {{#if this.showDocumentsSelect}} -
-
- -
-
- {{/if}} - - {{#if this.showVersionsSelect}} -
-
- -
-
- {{/if}} -
-
-
- - {{#if @meta.totalEntries}} - - {{t 'components.conflicts_filters.total_entries_count' count=@meta.totalEntries}} - - {{/if}} -
-
-
\ No newline at end of file diff --git a/webapp/app/pods/components/conflicts-list/component.ts b/webapp/app/pods/components/conflicts-list/component.ts deleted file mode 100644 index dff789463..000000000 --- a/webapp/app/pods/components/conflicts-list/component.ts +++ /dev/null @@ -1,27 +0,0 @@ -import Component from '@glimmer/component'; - -interface Args { - permissions: Record; - project: any; - conflicts: any; - version: any; - versions: any[]; - query: any; - onCorrect: (conflict: any, textInput: string) => Promise; - onCopyTranslation: ( - text: string, - sourceLanguageSlug: string, - targetLanguageSlug: string - ) => void; -} - -export default class ConflictsItems extends Component { - get currentVersion() { - if (!this.args.versions) return; - if (!this.args.version) return; - - return this.args.versions.find( - (version) => version.id === this.args.version - ); - } -} diff --git a/webapp/app/pods/components/conflicts-list/item/component.ts b/webapp/app/pods/components/conflicts-list/item/component.ts deleted file mode 100644 index bdcc9e20e..000000000 --- a/webapp/app/pods/components/conflicts-list/item/component.ts +++ /dev/null @@ -1,182 +0,0 @@ -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 {dropTask} from 'ember-concurrency-decorators'; -import {tracked} from '@glimmer/tracking'; -import {MutationResponse} from 'accent-webapp/services/apollo-mutate'; - -interface Conflict { - id: string; - key: string; - conflictedText: string; - correctedText: string; - revision: { - name: string | null; - slug: string | null; - rtl: boolean | null; - isMaster: boolean; - language: { - name: string; - slug: string; - rtl: boolean; - }; - }; - relatedTranslations: Array<{ - id: string; - correctedText: string; - revision: { - isMaster: boolean; - }; - }>; -} - -interface Args { - permissions: Record; - index: number; - project: any; - prompts: any[]; - conflict: Conflict; - onCorrect: (conflict: any, textInput: string) => Promise; - onCopyTranslation: ( - text: string, - sourceLanguageSlug: string | null, - targetLanguageSlug: string - ) => Promise<{text: string | null}>; -} - -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 - inputDisabled = false; - - conflictKey = parsedKeyProperty(this.args.conflict.key); - textOriginal = this.args.conflict.correctedText; - - get relatedTranslations() { - const masterConflict = this.args.conflict.relatedTranslations.find( - (translation) => translation.revision.isMaster - ); - if (!masterConflict) return []; - - return this.args.conflict.relatedTranslations.filter((translation) => { - return ( - translation.id === masterConflict.id || - translation.correctedText !== masterConflict.correctedText - ); - }); - } - - get showTextDiff() { - if (!this.args.conflict.conflictedText) return false; - - return this.textInput !== this.args.conflict.conflictedText; - } - - get showOriginalButton() { - return this.textInput !== this.textOriginal; - } - - get revisionName() { - return ( - this.args.conflict.revision.name || - this.args.conflict.revision.language.name - ); - } - - get revisionSlug() { - return ( - this.args.conflict.revision.slug || - this.args.conflict.revision.language.slug - ); - } - - get revisionTextDirRtl() { - return this.args.conflict.revision.rtl !== null - ? this.args.conflict.revision.rtl - : this.args.conflict.revision.language.rtl; - } - - @action - changeTranslationText(text: string) { - this.textInput = text; - } - - @action - setOriginalText() { - this.textInput = this.textOriginal; - } - - @action - onUpdatingText() { - this.inputDisabled = true; - } - - @action - onUpdateText(value: string) { - this.textInput = value; - this.inputDisabled = false; - } - - @dropTask - *copyTranslationTask(text: string, sourceLanguageSlug: string): any { - this.inputDisabled = true; - - const copyTranslation = yield this.args.onCopyTranslation( - text, - sourceLanguageSlug, - this.revisionSlug - ); - - this.inputDisabled = false; - - if (copyTranslation.text) { - this.textInput = copyTranslation.text; - } - } - - @action - async correct() { - this.onLoading(); - - const response = await this.args.onCorrect( - this.args.conflict, - this.textInput - ); - - if (response.errors) { - this.onError(); - } else { - this.onCorrectSuccess(); - } - } - - 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/conflicts-list/item/related-translation/component.ts b/webapp/app/pods/components/conflicts-list/item/related-translation/component.ts deleted file mode 100644 index 778ef6d65..000000000 --- a/webapp/app/pods/components/conflicts-list/item/related-translation/component.ts +++ /dev/null @@ -1,42 +0,0 @@ -import Component from '@glimmer/component'; -import {action} from '@ember/object'; - -interface Args { - project: any; - translation: any; - onCopyTranslation: (text: string, languageSlug: string) => void; -} - -const MAX_TEXT_LENGTH = 600; - -export default class ConflictItemRelatedTranslation extends Component { - get text() { - const text = this.args.translation.correctedText; - - if (text.length < MAX_TEXT_LENGTH) return text; - - return `${text.substring(0, MAX_TEXT_LENGTH - 1)}…`; - } - - get revisionName() { - return ( - this.args.translation.revision.slug || - this.args.translation.revision.language.slug - ); - } - - @action - translate() { - this.args.onCopyTranslation( - this.args.translation.correctedText, - this.revisionSlug - ); - } - - private get revisionSlug() { - return ( - this.args.translation.revision.slug || - this.args.translation.revision.language.slug - ); - } -} diff --git a/webapp/app/pods/components/conflicts-list/item/related-translation/styles.scss b/webapp/app/pods/components/conflicts-list/item/related-translation/styles.scss deleted file mode 100644 index a1eb07f87..000000000 --- a/webapp/app/pods/components/conflicts-list/item/related-translation/styles.scss +++ /dev/null @@ -1,107 +0,0 @@ -.item { - display: flex; - align-items: flex-start; - flex-direction: row; - padding: 5px 0 3px; - color: var(--color-grey); - font-size: 13px; -} - -.item-link { - display: inline-flex; - place-items: center; - flex-shrink: 0; - margin-right: 2px; - color: var(--color-black); - opacity: 0.8; - text-decoration: none; - padding: 1px 5px; - background: var(--background-light-highlight); - border-radius: var(--border-radius); - font-size: 11px; - transition: 0.2s ease-in-out; - transition-property: opacity; - - &:focus, - &:hover { - opacity: 1; - } -} - -.item-text { - width: 100%; - display: flex; - align-items: flex-start; -} - -.item-text-content { - display: block; - white-space: pre-wrap; - margin: 0 0 0 5px; - color: var(--color-black); - opacity: 0.8; - font-size: 12px; -} - -.item-actions { - margin-left: 6px; - flex-shrink: 0; - flex-grow: 0; -} - -.item-actions-link { - display: inline-flex; - align-items: center; - justify-content: center; - border-radius: 50%; - height: 17px; - width: 17px; - padding: 3px; - background: transparent; - color: var(--color-black); - background: var(--color-primary-opacity-20); - line-height: 1; -} - -.item-actions-link--loading { - pointer-events: none; - background: transparent; - - &:focus, - &:hover { - background: transparent; - } -} - -.item-actions-flag--link, -.item-actions-link { - cursor: pointer; - - &:focus, - &:hover { - background: var(--background-light-highlight); - } -} - -.item-actions-flag { - position: relative; - top: -1px; - padding: 0 5px; - margin-left: 0; - margin-right: 5px; - width: auto; - border-radius: 5px; - border: 1px solid var(--background-light-highlight); - font-size: 10px; - text-transform: uppercase; - text-decoration: none; - - &:last-of-type { - margin-right: 0; - } -} - -.item-actions-icon { - width: 10px; - height: 10px; -} diff --git a/webapp/app/pods/components/conflicts-list/item/related-translation/template.hbs b/webapp/app/pods/components/conflicts-list/item/related-translation/template.hbs deleted file mode 100644 index 794040a87..000000000 --- a/webapp/app/pods/components/conflicts-list/item/related-translation/template.hbs +++ /dev/null @@ -1,17 +0,0 @@ -
- - {{this.revisionName}} - - -
- {{this.text}} - -
- {{#if (get @permissions 'machine_translations_translate')}} - - {{/if}} -
-
-
\ No newline at end of file diff --git a/webapp/app/pods/components/conflicts-list/item/styles.scss b/webapp/app/pods/components/conflicts-list/item/styles.scss deleted file mode 100644 index f873aaa5c..000000000 --- a/webapp/app/pods/components/conflicts-list/item/styles.scss +++ /dev/null @@ -1,341 +0,0 @@ -.root { - &:nth-child(even) { - background: var(--background-light); - } -} - -.conflict-item { - padding: 10px; - margin-bottom: 15px; - border-radius: var(--border-radius); - - &:hover { - .form-helpers { - pointer-events: all; - opacity: 1; - } - } -} - -.revert-button { - :global(.label) { - padding-left: 3px; - padding-right: 3px; - } -} - -.item-details__column { - position: relative; -} - -.item-details { - display: flex; - flex-direction: column; - - &[data-dir='rtl'] { - .item-details__column { - align-items: flex-end; - } - .item-details__column:first-of-type { - margin-right: 0; - margin-left: 15px; - } - - .item-key { - margin-right: 0; - margin-left: 15px; - flex-direction: row-reverse; - } - - .item-key-prefix::before { - content: ''; - } - - .item-key-prefix::after { - content: '/'; - } - } -} - -.item-details__column { - display: flex; - flex-direction: column; - align-items: flex-start; -} - -.item-details__column:first-of-type { - margin-right: 15px; -} - -.item-detail-conflict { - display: flex; - width: 100%; -} - -.item-detail-conflict-actions { - margin-left: 6px; - flex-shrink: 0; - flex-grow: 1; -} - -.item-detail-conflict-actions-flag, -.item-detail-conflict-actions-link { - display: inline-flex; - align-items: center; - justify-content: center; - margin-left: 3px; - border-radius: 50%; - width: 24px; - height: 24px; - background: transparent; - color: var(--color-black); - line-height: 1; -} - -.item-detail-conflict-actions-link--loading { - pointer-events: none; - background: transparent; - - &:focus, - &:hover { - background: transparent; - } -} - -.item-detail-conflict-actions-flag--link, -.item-detail-conflict-actions-link { - cursor: pointer; - - &:focus, - &:hover { - background: var(--background-light-highlight); - } -} - -.item-detail-conflict-actions-flag { - position: relative; - top: -1px; - padding: 0 5px; - margin-left: 0; - margin-right: 5px; - width: auto; - border-radius: 5px; - border: 1px solid var(--background-light-highlight); - font-size: 10px; - text-transform: uppercase; - text-decoration: none; - - &:last-of-type { - margin-right: 0; - } -} - -.item-detail-conflict-actions-flag--link { - &:focus, - &:hover { - color: var(--content-background); - border-color: var(--color-primary); - background: var(--color-primary); - } -} - -.item-detail-conflict-actions-icon { - width: 12px; - height: 12px; -} - -.conflict-item.resolved { - padding: 5px 10px; - margin: 5px 0; - background: hsl( - var(--color-green-hue), - var(--color-green-saturation), - var(--color-highlight-lighteness) - ); - - .item-key-prefix { - opacity: 0.7; - color: var(--color-green); - } - - .item-key { - margin-bottom: 0; - font-size: 12px; - color: var(--color-green); - } -} - -.conflict-item.errored { - .textInput { - border-color: var(--color-error); - } -} - -.error { - font-size: 12px; - font-weight: bold; - color: var(--color-error); -} - -.item-key-prefix { - display: inline-flex; - font-size: 11px; - color: #959595; - gap: 6px; - font-weight: 300; - - &::before { - content: '/'; - } -} - -.item-key { - display: flex; - align-items: center; - gap: 5px; - margin-bottom: 12px; - font-family: var(--font-monospace); - word-break: break-all; - transition: 0.2s ease-in-out; - transition-property: color; - margin-right: 15px; - line-height: 1.5; - font-size: 11px; - color: var(--color-primary); -} - -.key { - text-decoration: none; -} - -.textResolved { - display: flex; - align-items: flex-start; -} - -.textResolved-content { - flex-grow: 1; -} - -.textResolved-text { - margin-bottom: 5px; - font-size: 13px; -} - -.textDiff { - padding: 8px 0 3px; - color: var(--color-grey); -} - -.textDiff { - white-space: pre-wrap; - word-break: break-word; - font-size: 12px; -} - -.button-submit { - display: flex; - justify-content: flex-end; - position: absolute; - gap: 10px; - top: 10px; - right: 10px; - z-index: 3; - - &[data-dir='rtl'] { - right: auto; - left: 7px; - flex-direction: row-reverse; - } -} - -.item-revision { - flex-shrink: 0; - margin-right: 4px; - color: var(--color-black); - opacity: 0.6; - text-decoration: none; - font-weight: bold; - font-size: 12px; - text-align: right; - - &:focus, - &:hover { - opacity: 1; - color: var(--color-primary); - } -} - -.item-revision { - opacity: 1; - padding: 4px 0 3px; - margin: 0 9px 0 0; - font-size: 13px; -} - -.textInput { - flex-grow: 1; - flex-shrink: 0; - width: 100%; -} - -.item-text { - display: block; - width: 100%; - color: var(--color-black); - line-height: 1.4; - padding: 3px 10px 10px 0; - font-size: 13px; - line-height: 1.6; - cursor: pointer; - word-break: break-word; - - &:focus, - &:hover { - outline: none; - opacity: 0.8; - } -} - -.conflictedText-references { - width: 100%; - padding-left: 4px; -} - -.conflictedText-references-conflicted { - display: flex; - align-items: flex-start; - margin-top: 7px; - font-size: 12px; - color: var(--color-black); -} - -.form-helpers { - pointer-events: none; - opacity: 0; - position: relative; - z-index: 1; - transition: 0.2s ease-in-out; - transition-property: opacity; -} - -.conflictedText-references-conflicted-label { - display: flex; - align-items: center; - justify-content: flex-end; - flex-shrink: 0; - margin-right: 10px; - margin-top: 4px; - font-weight: 500; - font-size: 11px; - text-align: right; -} - -.conflictedText-references-conflicted-value { - white-space: pre-wrap; -} - -.conflictedText-references-conflicted-icon { - width: 12px; - height: 12px; -} diff --git a/webapp/app/pods/components/conflicts-list/item/template.hbs b/webapp/app/pods/components/conflicts-list/item/template.hbs deleted file mode 100644 index 5620604a2..000000000 --- a/webapp/app/pods/components/conflicts-list/item/template.hbs +++ /dev/null @@ -1,123 +0,0 @@ -
-
-
  • - {{#if this.resolved}} -
    - - - {{this.conflictKey.value}} - - {{#if this.conflictKey.prefix}} - {{this.conflictKey.prefix}} - {{else}} - {{@conflict.document.path}} - {{/if}} - - - - -
    - {{#if this.error}} -
    - {{t 'components.conflict_item.uncorrect_error_text'}} -
    - {{/if}} -
    -
    - {{else}} -
    -
    - - - {{this.conflictKey.value}} - - {{#if this.conflictKey.prefix}} - {{this.conflictKey.prefix}} - {{else}} - {{@conflict.document.path}} - {{/if}} - - - - - {{#if this.error}} -
    - {{t 'components.conflict_item.correct_error_text'}} -
    - {{/if}} -
    -
    -
    - - {{#component form.submit}} -
    - {{#if this.showOriginalButton}} - - {{inline-svg '/assets/revert.svg' class='button-icon'}} - - {{/if}} - -
    - -
    - - {{#if (get @permissions 'correct_translation')}} - - {{inline-svg '/assets/check.svg' class='button-icon'}} - - {{/if}} -
    - {{/component}} -
    -
    - -
    - {{#if this.showTextDiff}} -
    - - {{inline-svg '/assets/diff.svg' local-class='conflictedText-references-conflicted-icon'}} - - -
    {{string-diff this.textInput @conflict.conflictedText}}
    -
    - {{/if}} - - {{#if @conflict.relatedTranslations}} - {{#each this.relatedTranslations key='id' as |relatedTranslation|}} - - {{/each}} - {{/if}} -
    -
    -
    - {{/if}} -
  • -
    -
    \ No newline at end of file diff --git a/webapp/app/pods/components/conflicts-list/template.hbs b/webapp/app/pods/components/conflicts-list/template.hbs deleted file mode 100644 index 6e25ce219..000000000 --- a/webapp/app/pods/components/conflicts-list/template.hbs +++ /dev/null @@ -1,35 +0,0 @@ -
      - {{#if this.currentVersion}} -
      - - {{t 'components.conflicts_items.translations_version_notice'}} - {{this.currentVersion.tag}} -
      - {{/if}} - {{#each @conflicts key='id' as |conflict index|}} - - {{else if @query}} - - {{else}} -
      - - -
      - {{t 'components.conflicts_items.all_reviewed_title'}} -
      - -
      - {{t 'components.conflicts_items.all_reviewed_subtitle'}} -
      -
      - {{/each}} -
    \ No newline at end of file diff --git a/webapp/app/pods/components/conflicts-page/component.ts b/webapp/app/pods/components/conflicts-page/component.ts deleted file mode 100644 index 5bd84c7cd..000000000 --- a/webapp/app/pods/components/conflicts-page/component.ts +++ /dev/null @@ -1,29 +0,0 @@ -import Component from '@glimmer/component'; - -interface Args { - project: any; - revision: any; - translations: any; - isLoading: boolean; - showLoading: boolean; - document: any; - version: any; - permissions: Record; - documents: any; - versions: any; - showSkeleton: boolean; - query: any; - reference: any; - referenceRevision: any; - referenceRevisions: any; - onCorrect: () => void; - onCopyTranslation: () => void; - onCorrectAll: () => void; - onSelectPage: () => void; - onChangeDocument: () => void; - onChangeVersion: () => 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 deleted file mode 100644 index b74dc0868..000000000 --- a/webapp/app/pods/components/conflicts-page/styles.scss +++ /dev/null @@ -1,3 +0,0 @@ -.conflicts-page { - background: var(--content-background); -} diff --git a/webapp/app/pods/components/conflicts-page/template.hbs b/webapp/app/pods/components/conflicts-page/template.hbs deleted file mode 100644 index a9f0ff179..000000000 --- a/webapp/app/pods/components/conflicts-page/template.hbs +++ /dev/null @@ -1,38 +0,0 @@ -
    - - - {{#if @isLoading}} - - {{/if}} - - {{#if @showSkeleton}} - - {{else if @showLoading}} - - {{else}} - - - {{/if}} -
    \ No newline at end of file diff --git a/webapp/app/pods/components/date-tag/template.hbs b/webapp/app/pods/components/date-tag/template.hbs deleted file mode 100644 index ed12ea38f..000000000 --- a/webapp/app/pods/components/date-tag/template.hbs +++ /dev/null @@ -1,5 +0,0 @@ - - - \ No newline at end of file diff --git a/webapp/app/pods/components/inline-machine-translate/styles.scss b/webapp/app/pods/components/inline-machine-translate/styles.scss deleted file mode 100644 index d30370201..000000000 --- a/webapp/app/pods/components/inline-machine-translate/styles.scss +++ /dev/null @@ -1,74 +0,0 @@ -.prompt-button { - position: relative; - display: flex; - align-items: center; - - > .button { - transition: opacity 0.2s ease-in-out; - box-shadow: none; - opacity: 0.7; - border-radius: var(--border-radius); - } - - > button:focus, - > button:hover { - transform: translate3d(0, 0, 0); - } - - &:focus, - &:hover { - outline: none; - - > .button { - opacity: 1; - } - - .prompt-button-quick-access[data-rtl] { - left: 36px; - right: auto; - } - - .prompt-button-quick-access { - opacity: 1; - right: 36px; - padding: 0 10px; - pointer-events: all; - } - } -} - -.prompt-button-quick-access[data-rtl] { - left: 0; - right: auto; - justify-content: flex-start; -} - -.prompt-button-quick-access { - background: var(--input-background); - opacity: 0; - pointer-events: none; - right: 0; - display: flex; - gap: 0; - justify-content: flex-end; - align-items: center; - position: absolute; - top: 0; - transition: all 0.2s ease-in-out; - - > button { - font-size: 11px; - flex-shrink: 0; - } - - > button:focus, - > button:hover { - background: var(--background-light); - transform: translate3d(0, 0, 0); - } - - > button :global(.label) { - padding-left: 8px; - padding-right: 8px; - } -} diff --git a/webapp/app/pods/components/inline-machine-translate/template.hbs b/webapp/app/pods/components/inline-machine-translate/template.hbs deleted file mode 100644 index 9df40296c..000000000 --- a/webapp/app/pods/components/inline-machine-translate/template.hbs +++ /dev/null @@ -1,19 +0,0 @@ -{{#if @languages}} -
    -
    - {{#each @languages as |language|}} - - {{language.slug}} - - {{/each}} -
    - - -
    -{{/if}} \ No newline at end of file diff --git a/webapp/app/pods/components/lint-options/template.hbs b/webapp/app/pods/components/lint-options/template.hbs deleted file mode 100644 index 789feba1a..000000000 --- a/webapp/app/pods/components/lint-options/template.hbs +++ /dev/null @@ -1,38 +0,0 @@ -
    -
    -
    -
    -
    - {{inline-svg '/assets/search.svg' local-class='search-icon'}} - - -
    - -
    - {{#if this.showDocuments}} -
    -
    - -
    -
    - {{/if}} - - {{#if this.showVersions}} -
    -
    - -
    -
    - {{/if}} -
    -
    -
    -
    -
    \ No newline at end of file diff --git a/webapp/app/pods/components/lint-translations-page/component.ts b/webapp/app/pods/components/lint-translations-page/component.ts deleted file mode 100644 index bfde43f3f..000000000 --- a/webapp/app/pods/components/lint-translations-page/component.ts +++ /dev/null @@ -1,40 +0,0 @@ -import Component from '@glimmer/component'; - -interface Args { - project: any; - lintTranslations: any[]; - permissions: Record; -} - -interface Stat { - title: string; - count: number; -} - -export default class LintTranslationsPage extends Component { - get lintTranslationsStatsCount() { - return this.lintTranslationsStats.reduce( - (total, stat) => stat.count + total, - 0 - ); - } - - get lintTranslationsStats() { - const stats = this.args.lintTranslations.reduce((acc, lintTranslation) => { - lintTranslation.messages.forEach((message: {check: string}) => { - if (acc[message.check]) { - acc[message.check]++; - } else { - acc[message.check] = 1; - } - }); - - return acc; - }, {}); - - return Object.entries(stats).map(([title, count]) => ({ - title, - count, - })) as Stat[]; - } -} diff --git a/webapp/app/pods/components/lint-translations-page/item/template.hbs b/webapp/app/pods/components/lint-translations-page/item/template.hbs deleted file mode 100644 index c926fe712..000000000 --- a/webapp/app/pods/components/lint-translations-page/item/template.hbs +++ /dev/null @@ -1,34 +0,0 @@ -{{#if @lintTranslation.messages}} -
    -
      - {{#each this.messages as |message|}} - - {{#if message.message}} - {{message.message}} - {{else}} - {{t (concat 'components.translation_edit.lint_message.checks.' message.check)}} - {{/if}} - - {{/each}} -
    - - {{#if @project}} -
    - - - {{this.translationKey.value}} - - {{#if this.translationKey.prefix}} - {{this.translationKey.prefix}} - {{else}} - {{@lintTranslation.translation.document.path}} - {{/if}} - - - -
    - {{/if}} - -
    {{{this.annotatedText}}}
    -
    -{{/if}} \ No newline at end of file diff --git a/webapp/app/pods/components/project-settings/integrations/form/azure-storage-container/styles.scss b/webapp/app/pods/components/project-settings/integrations/form/azure-storage-container/styles.scss deleted file mode 100644 index 7ad947c92..000000000 --- a/webapp/app/pods/components/project-settings/integrations/form/azure-storage-container/styles.scss +++ /dev/null @@ -1,60 +0,0 @@ -.instructions { - border-top: 1px solid var(--background-light-highlight); - padding-top: 10px; - margin: 20px 0 10px; -} - -.instructions-text { - margin-top: 7px; - font-style: italic; - color: #555; - - a { - font-family: var(--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: var(--font-monospace); - font-size: 11px; -} diff --git a/webapp/app/pods/components/project-settings/prompts/config/template.hbs b/webapp/app/pods/components/project-settings/prompts/config/template.hbs deleted file mode 100644 index 33d00eebc..000000000 --- a/webapp/app/pods/components/project-settings/prompts/config/template.hbs +++ /dev/null @@ -1,39 +0,0 @@ -
    -
    - {{inline-svg this.logoProvider local-class='logo'}} - - - {{#if @project.promptConfig}} - {{inline-svg 'assets/check.svg' local-class='check'}} - {{/if}} -
    - -

    - {{#if @project.promptConfig}} - {{t 'components.project_settings.prompts.config_key_help_present'}} - {{else}} - {{t 'components.project_settings.prompts.config_key_help_not_present'}} - {{/if}} -

    - - -
    - -
    - {{#if @project.promptConfig}} - - {{t 'components.project_settings.integrations.delete'}} - - {{/if}} - - - {{t 'components.project_settings.integrations.save'}} - -
    \ No newline at end of file diff --git a/webapp/app/pods/components/project-settings/prompts/template.hbs b/webapp/app/pods/components/project-settings/prompts/template.hbs deleted file mode 100644 index ff2133ff3..000000000 --- a/webapp/app/pods/components/project-settings/prompts/template.hbs +++ /dev/null @@ -1,28 +0,0 @@ -
    -
    -

    - {{t 'components.project_settings.prompts.title'}} -

    -

    - - {{t 'components.project_settings.prompts.help'}} -

    - -
      - {{#each @prompts as |prompt|}} -
    • - -
    • - {{/each}} -
    - - - {{inline-svg '/assets/add.svg' class='button-icon'}} - {{t 'components.project_settings.prompts.new_button'}} - -
    - -
    - -
    -
    \ No newline at end of file diff --git a/webapp/app/pods/components/projects-list/item/component.ts b/webapp/app/pods/components/projects-list/item/component.ts deleted file mode 100644 index 46563da74..000000000 --- a/webapp/app/pods/components/projects-list/item/component.ts +++ /dev/null @@ -1,50 +0,0 @@ -import Component from '@glimmer/component'; -import {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 { - @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.args.project.id} { - --color-primary: ${this.args.project.mainColor}; - } - `; - } - - get totalStrings() { - return this.args.project.translationsCount; - } - - get totalConflicts() { - return this.args.project.conflictsCount; - } - - get totalReviewed() { - return ( - this.args.project.translationsCount - this.args.project.conflictsCount - ); - } - - get correctedKeysPercentage() { - return percentage( - this.totalStrings - this.totalConflicts, - this.totalStrings - ); - } -} diff --git a/webapp/app/pods/components/projects-list/template.hbs b/webapp/app/pods/components/projects-list/template.hbs deleted file mode 100644 index 73a23677e..000000000 --- a/webapp/app/pods/components/projects-list/template.hbs +++ /dev/null @@ -1,23 +0,0 @@ -
      - {{#each @projects key='id' as |project index|}} -
    • - - - -
    • - {{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}} -
    \ No newline at end of file diff --git a/webapp/app/pods/components/translations-list/template.hbs b/webapp/app/pods/components/translations-list/template.hbs deleted file mode 100644 index 0bb8931d2..000000000 --- a/webapp/app/pods/components/translations-list/template.hbs +++ /dev/null @@ -1,35 +0,0 @@ -
      - {{#if this.currentVersion}} -
      - - {{t 'components.translations_list.translations_version_notice'}} - {{this.currentVersion.tag}} -
      - {{/if}} - - {{#each @translations key='id' as |translation|}} - - {{else if @query}} - - {{else if @withAdvancedFilters}} - - {{else}} - - {{inline-svg 'assets/empty.svg' local-class='icon'}} - {{t 'components.translations_list.no_translations'}} -
      - {{t 'components.translations_list.maybe_sync_before'}} - - {{t 'components.translations_list.maybe_sync_link'}} - -
      -
      - {{/each}} -
    \ No newline at end of file diff --git a/webapp/app/pods/logged-in/jipt/template.hbs b/webapp/app/pods/logged-in/jipt/template.hbs deleted file mode 100644 index 319be03b7..000000000 --- a/webapp/app/pods/logged-in/jipt/template.hbs +++ /dev/null @@ -1,13 +0,0 @@ - - -
    - - - - - {{outlet}} -
    \ No newline at end of file diff --git a/webapp/app/pods/logged-in/project/revision/conflicts/controller.ts b/webapp/app/pods/logged-in/project/revision/conflicts/controller.ts deleted file mode 100644 index 5d1e9d8c5..000000000 --- a/webapp/app/pods/logged-in/project/revision/conflicts/controller.ts +++ /dev/null @@ -1,159 +0,0 @@ -import {camelize} from '@ember/string'; -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 IntlService from 'ember-intl/services/intl'; -import FlashMessages from 'ember-cli-flash/services/flash-messages'; -import Apollo from 'accent-webapp/services/apollo'; -import ApolloMutate from 'accent-webapp/services/apollo-mutate'; -import GlobalState from 'accent-webapp/services/global-state'; -import {tracked} from '@glimmer/tracking'; -import projectTranslateTextQuery from 'accent-webapp/queries/translate-text-project'; - -const FLASH_MESSAGE_CORRECT_SUCCESS = - 'pods.project.conflicts.flash_messages.correct_success'; -const FLASH_MESSAGE_CORRECT_ERROR = - 'pods.project.conflicts.flash_messages.correct_error'; -const FLASH_MESSAGE_TRANSLATE_ERROR_PREFIX = - 'pods.project.conflicts.flash_messages.translate_error'; -const FLASH_MESSAGE_TRANSLATE_PROVIDER_ERROR = - 'pods.project.conflicts.flash_messages.translate_provider_error'; - -export default class ConflictsController extends Controller { - @tracked - model: any; - - @service('intl') - intl: IntlService; - - @service('flash-messages') - flashMessages: FlashMessages; - - @service('apollo') - apollo: Apollo; - - @service('apollo-mutate') - apolloMutate: ApolloMutate; - - @service('global-state') - globalState: GlobalState; - - queryParams = ['page', 'query', 'document', 'version']; - - @tracked - query = ''; - - @tracked - document: string | null = null; - - @tracked - version: string | null = null; - - @tracked - page = 1; - - @readOnly('globalState.permissions') - permissions: any; - - @equal('model.translations.entries', undefined) - emptyEntries: boolean; - - @readOnly('model.revisionModel.project.revisions') - revisions: any; - - @empty('document') - emptyDocument: boolean; - - @equal('query', '') - emptyQuery: boolean; - - @and('emptyEntries', 'model.loading') - showLoading: boolean; - - @and('emptyEntries', 'model.loading', 'emptyQuery', 'emptyDocument') - showSkeleton: boolean; - - @action - async copyTranslation( - text: string, - sourceLanguageSlug: string, - targetLanguageSlug: string - ) { - const {data} = await this.apollo.client.query({ - fetchPolicy: 'network-only', - query: projectTranslateTextQuery, - variables: { - text, - sourceLanguageSlug, - targetLanguageSlug, - projectId: this.model.project.id, - }, - }); - - if (data.viewer?.project?.translatedText?.text) { - return data.viewer.project.translatedText; - } else if (data.viewer?.project?.translatedText?.error) { - const error = data.viewer?.project?.translatedText?.error; - const source = sourceLanguageSlug; - const target = targetLanguageSlug; - - this.flashMessages.error( - this.intl.t(`${FLASH_MESSAGE_TRANSLATE_ERROR_PREFIX}.${error}`, { - source, - target, - }) - ); - } else { - const provider = camelize(data.viewer?.project?.translatedText?.provider); - this.flashMessages.error( - this.intl.t(FLASH_MESSAGE_TRANSLATE_PROVIDER_ERROR, {provider}) - ); - } - } - - @action - async correctConflict(conflict: any, text: string) { - const response = await this.apolloMutate.mutate({ - mutation: translationCorrectQuery, - variables: { - translationId: conflict.id, - text, - }, - }); - - if (response.errors) { - this.flashMessages.error(this.intl.t(FLASH_MESSAGE_CORRECT_ERROR)); - } else { - this.flashMessages.success(this.intl.t(FLASH_MESSAGE_CORRECT_SUCCESS)); - } - - return response; - } - - @action - changeQuery(query: string) { - this.page = 1; - this.query = query; - } - - @action - changeDocument(select: HTMLSelectElement) { - this.page = 1; - this.document = select.value ? select.value : null; - } - - @action - changeVersion(select: HTMLSelectElement) { - this.page = 1; - this.version = select.value ? select.value : null; - } - - @action - selectPage(page: number) { - window.scrollTo(0, 0); - - this.page = page; - } -} diff --git a/webapp/app/pods/logged-in/project/revision/conflicts/template.hbs b/webapp/app/pods/logged-in/project/revision/conflicts/template.hbs deleted file mode 100644 index c7f2f0913..000000000 --- a/webapp/app/pods/logged-in/project/revision/conflicts/template.hbs +++ /dev/null @@ -1,21 +0,0 @@ - \ No newline at end of file diff --git a/webapp/app/queries/activity-activities.ts b/webapp/app/queries/activity-activities.ts index 8c3ae9c21..52d88a0b9 100644 --- a/webapp/app/queries/activity-activities.ts +++ b/webapp/app/queries/activity-activities.ts @@ -1,4 +1,4 @@ -import gql from 'graphql-tag'; +import {gql} from '@apollo/client/core'; export default gql` query ActivityActivities($projectId: ID!, $activityId: ID!, $page: Int) { diff --git a/webapp/app/queries/authentication-providers.ts b/webapp/app/queries/authentication-providers.ts index e7b8467f2..72b8219a3 100644 --- a/webapp/app/queries/authentication-providers.ts +++ b/webapp/app/queries/authentication-providers.ts @@ -1,4 +1,4 @@ -import gql from 'graphql-tag'; +import {gql} from '@apollo/client/core'; export default gql` query AuthenticationProviders { diff --git a/webapp/app/queries/conflicts.ts b/webapp/app/queries/conflicts.ts index 28086e7e9..04fada702 100644 --- a/webapp/app/queries/conflicts.ts +++ b/webapp/app/queries/conflicts.ts @@ -1,13 +1,18 @@ -import gql from 'graphql-tag'; +import {gql} from '@apollo/client/core'; export default gql` query Conflicts( $projectId: ID! - $revisionId: ID! $query: String $page: Int $document: ID + $relatedRevisions: [ID!] $version: ID + $isTextEmpty: Boolean + $isTextNotEmpty: Boolean + $isAddedLastSync: Boolean + $isCommentedOn: Boolean + $isTranslated: Boolean ) { viewer { project(id: $projectId) { @@ -34,30 +39,60 @@ export default gql` name } - revision(id: $revisionId) { + revisions { id + isMaster + slug + name + + language { + id + slug + name + } + } + + groupedTranslations( + query: $query + page: $page + pageSize: 20 + document: $document + version: $version + relatedRevisions: $relatedRevisions + isConflicted: true + isTextEmpty: $isTextEmpty + isTextNotEmpty: $isTextNotEmpty + isAddedLastSync: $isAddedLastSync + isTranslated: $isTranslated + isCommentedOn: $isCommentedOn + ) { + meta { + totalEntries + totalPages + currentPage + nextPage + previousPage + } - translations( - query: $query - page: $page - pageSize: 20 - document: $document - version: $version - isConflicted: true - ) { - meta { - totalEntries - totalPages - currentPage - nextPage - previousPage + revisions { + id + } + + entries { + key + document { + id + path } - entries { + + translations { id key conflictedText correctedText valueType + isConflicted + isTranslated lintMessages { text @@ -83,31 +118,6 @@ export default gql` rtl } } - - relatedTranslations { - id - correctedText - isConflicted - revision { - id - isMaster - name - slug - rtl - - language { - id - name - slug - rtl - } - } - } - - document { - id - path - } } } } diff --git a/webapp/app/queries/correct-all-revision.ts b/webapp/app/queries/correct-all-revision.ts index 251b5e4d7..21f84ff9e 100644 --- a/webapp/app/queries/correct-all-revision.ts +++ b/webapp/app/queries/correct-all-revision.ts @@ -1,4 +1,4 @@ -import gql from 'graphql-tag'; +import {gql} from '@apollo/client/core'; export default gql` mutation CorrectAll($revisionId: ID!) { diff --git a/webapp/app/queries/correct-translation.ts b/webapp/app/queries/correct-translation.ts index 392ba4296..7d94bc026 100644 --- a/webapp/app/queries/correct-translation.ts +++ b/webapp/app/queries/correct-translation.ts @@ -1,4 +1,4 @@ -import gql from 'graphql-tag'; +import {gql} from '@apollo/client/core'; export default gql` mutation TranslationCorrect($translationId: ID!, $text: String!) { diff --git a/webapp/app/queries/create-api-token.ts b/webapp/app/queries/create-api-token.ts index 3205b2733..a5cd40d65 100644 --- a/webapp/app/queries/create-api-token.ts +++ b/webapp/app/queries/create-api-token.ts @@ -1,4 +1,4 @@ -import gql from 'graphql-tag'; +import {gql} from '@apollo/client/core'; export interface CreateApiTokenVariables { name: string; diff --git a/webapp/app/queries/create-collaborator.ts b/webapp/app/queries/create-collaborator.ts index dd758b729..d6edf2347 100644 --- a/webapp/app/queries/create-collaborator.ts +++ b/webapp/app/queries/create-collaborator.ts @@ -1,4 +1,4 @@ -import gql from 'graphql-tag'; +import {gql} from '@apollo/client/core'; export default gql` mutation CollaboratorCreate($role: Role!, $email: String!, $projectId: ID!) { diff --git a/webapp/app/queries/create-comment.ts b/webapp/app/queries/create-comment.ts index 9a580a1b6..27063f119 100644 --- a/webapp/app/queries/create-comment.ts +++ b/webapp/app/queries/create-comment.ts @@ -1,4 +1,4 @@ -import gql from 'graphql-tag'; +import {gql} from '@apollo/client/core'; export default gql` mutation CommentCreate($translationId: ID!, $text: String!) { diff --git a/webapp/app/queries/create-integration.ts b/webapp/app/queries/create-integration.ts index 4e0053259..7e024ca1d 100644 --- a/webapp/app/queries/create-integration.ts +++ b/webapp/app/queries/create-integration.ts @@ -1,4 +1,4 @@ -import gql from 'graphql-tag'; +import {gql} from '@apollo/client/core'; export default gql` mutation IntegrationCreate( diff --git a/webapp/app/queries/create-project-prompt.ts b/webapp/app/queries/create-project-prompt.ts index c5ff6189d..3db7f4185 100644 --- a/webapp/app/queries/create-project-prompt.ts +++ b/webapp/app/queries/create-project-prompt.ts @@ -1,4 +1,4 @@ -import gql from 'graphql-tag'; +import {gql} from '@apollo/client/core'; export interface CreatePromptResponse { prompt: { diff --git a/webapp/app/queries/create-project.ts b/webapp/app/queries/create-project.ts index 19ab2091f..aec02850f 100644 --- a/webapp/app/queries/create-project.ts +++ b/webapp/app/queries/create-project.ts @@ -1,4 +1,4 @@ -import gql from 'graphql-tag'; +import {gql} from '@apollo/client/core'; export interface CreateProjectVariables { name: string; diff --git a/webapp/app/queries/create-revision.ts b/webapp/app/queries/create-revision.ts index 51073a03c..cdeddaf18 100644 --- a/webapp/app/queries/create-revision.ts +++ b/webapp/app/queries/create-revision.ts @@ -1,4 +1,4 @@ -import gql from 'graphql-tag'; +import {gql} from '@apollo/client/core'; export default gql` mutation RevisionCreate( diff --git a/webapp/app/queries/create-translation-comments-subscription.ts b/webapp/app/queries/create-translation-comments-subscription.ts index 124d0e7ce..3e97f6b9c 100644 --- a/webapp/app/queries/create-translation-comments-subscription.ts +++ b/webapp/app/queries/create-translation-comments-subscription.ts @@ -1,4 +1,4 @@ -import gql from 'graphql-tag'; +import {gql} from '@apollo/client/core'; export default gql` mutation TranslationCommentsSubscriptionCreate( diff --git a/webapp/app/queries/create-version.ts b/webapp/app/queries/create-version.ts index 9f6dc2e18..274150dcb 100644 --- a/webapp/app/queries/create-version.ts +++ b/webapp/app/queries/create-version.ts @@ -1,8 +1,18 @@ -import gql from 'graphql-tag'; +import {gql} from '@apollo/client/core'; export default gql` - mutation VersionCreate($name: String!, $tag: String!, $projectId: ID!) { - createVersion(name: $name, tag: $tag, projectId: $projectId) { + mutation VersionCreate( + $name: String! + $tag: String! + $projectId: ID! + $copyOnUpdateTranslation: Boolean! + ) { + createVersion( + name: $name + tag: $tag + projectId: $projectId + copyOnUpdateTranslation: $copyOnUpdateTranslation + ) { version { id } diff --git a/webapp/app/queries/delete-collaborator.ts b/webapp/app/queries/delete-collaborator.ts index 0dfeaf015..f02404b58 100644 --- a/webapp/app/queries/delete-collaborator.ts +++ b/webapp/app/queries/delete-collaborator.ts @@ -1,4 +1,4 @@ -import gql from 'graphql-tag'; +import {gql} from '@apollo/client/core'; export default gql` mutation CollaboratorDelete($collaboratorId: ID!) { diff --git a/webapp/app/queries/delete-comment.ts b/webapp/app/queries/delete-comment.ts index 88edf4cc1..c807f9a3c 100644 --- a/webapp/app/queries/delete-comment.ts +++ b/webapp/app/queries/delete-comment.ts @@ -1,4 +1,4 @@ -import gql from 'graphql-tag'; +import {gql} from '@apollo/client/core'; export default gql` mutation CommentDelete($commentId: ID!) { diff --git a/webapp/app/queries/delete-document.ts b/webapp/app/queries/delete-document.ts index 767fd09b9..690648ef2 100644 --- a/webapp/app/queries/delete-document.ts +++ b/webapp/app/queries/delete-document.ts @@ -1,4 +1,4 @@ -import gql from 'graphql-tag'; +import {gql} from '@apollo/client/core'; export default gql` mutation DocumentDelete($documentId: ID!) { diff --git a/webapp/app/queries/delete-integration.ts b/webapp/app/queries/delete-integration.ts index 0059bfca8..5a5c9dffa 100644 --- a/webapp/app/queries/delete-integration.ts +++ b/webapp/app/queries/delete-integration.ts @@ -1,4 +1,4 @@ -import gql from 'graphql-tag'; +import {gql} from '@apollo/client/core'; export default gql` mutation IntegrationDelete($integrationId: ID!) { diff --git a/webapp/app/queries/delete-project-machine-translations-config.ts b/webapp/app/queries/delete-project-machine-translations-config.ts index c5252642c..3cccbb669 100644 --- a/webapp/app/queries/delete-project-machine-translations-config.ts +++ b/webapp/app/queries/delete-project-machine-translations-config.ts @@ -1,4 +1,4 @@ -import gql from 'graphql-tag'; +import {gql} from '@apollo/client/core'; export interface DeleteProjectMachineTranslationsConfigVariables { projectId: string; diff --git a/webapp/app/queries/delete-project-prompt-config.ts b/webapp/app/queries/delete-project-prompt-config.ts index 7fa590485..616872c12 100644 --- a/webapp/app/queries/delete-project-prompt-config.ts +++ b/webapp/app/queries/delete-project-prompt-config.ts @@ -1,4 +1,4 @@ -import gql from 'graphql-tag'; +import {gql} from '@apollo/client/core'; export interface DeleteProjectPromptConfigVariables { projectId: string; diff --git a/webapp/app/queries/delete-project-prompt.ts b/webapp/app/queries/delete-project-prompt.ts index 5d811db47..9702d62cc 100644 --- a/webapp/app/queries/delete-project-prompt.ts +++ b/webapp/app/queries/delete-project-prompt.ts @@ -1,4 +1,4 @@ -import gql from 'graphql-tag'; +import {gql} from '@apollo/client/core'; export interface DeleteProjectPromptVariables { promptId: string; diff --git a/webapp/app/queries/delete-project.ts b/webapp/app/queries/delete-project.ts index 21cd493fc..cb08840af 100644 --- a/webapp/app/queries/delete-project.ts +++ b/webapp/app/queries/delete-project.ts @@ -1,4 +1,4 @@ -import gql from 'graphql-tag'; +import {gql} from '@apollo/client/core'; export default gql` mutation ProjectDelete($projectId: ID!) { diff --git a/webapp/app/queries/delete-revision.ts b/webapp/app/queries/delete-revision.ts index da70549cd..e1dd4fec6 100644 --- a/webapp/app/queries/delete-revision.ts +++ b/webapp/app/queries/delete-revision.ts @@ -1,4 +1,4 @@ -import gql from 'graphql-tag'; +import {gql} from '@apollo/client/core'; export default gql` mutation RevisionDelete($revisionId: ID!) { diff --git a/webapp/app/queries/delete-translation-comments-subscription.ts b/webapp/app/queries/delete-translation-comments-subscription.ts index 266d62484..1293d33d2 100644 --- a/webapp/app/queries/delete-translation-comments-subscription.ts +++ b/webapp/app/queries/delete-translation-comments-subscription.ts @@ -1,4 +1,4 @@ -import gql from 'graphql-tag'; +import {gql} from '@apollo/client/core'; export default gql` mutation TranslationCommentsSubscriptionDelete( diff --git a/webapp/app/queries/execute-integration.ts b/webapp/app/queries/execute-integration.ts index 504754810..032d06d9f 100644 --- a/webapp/app/queries/execute-integration.ts +++ b/webapp/app/queries/execute-integration.ts @@ -1,13 +1,15 @@ -import gql from 'graphql-tag'; +import {gql} from '@apollo/client/core'; export default gql` mutation IntegrationExecute( $integrationId: ID! $azureStorageContainer: ProjectIntegrationExecuteAzureStorageContainerInput + $awsS3: ProjectIntegrationExecuteAwsS3Input ) { executeProjectIntegration( id: $integrationId azureStorageContainer: $azureStorageContainer + awsS3: $awsS3 ) { projectIntegration: result { id diff --git a/webapp/app/queries/improve-text-prompt.ts b/webapp/app/queries/improve-text-prompt.ts index 27e2e88e7..f895c5715 100644 --- a/webapp/app/queries/improve-text-prompt.ts +++ b/webapp/app/queries/improve-text-prompt.ts @@ -1,4 +1,4 @@ -import gql from 'graphql-tag'; +import {gql} from '@apollo/client/core'; export default gql` mutation TextPromptImprove($promptId: ID!, $text: String!) { diff --git a/webapp/app/queries/jipt-example.ts b/webapp/app/queries/jipt-example.ts new file mode 100644 index 000000000..d30bdec48 --- /dev/null +++ b/webapp/app/queries/jipt-example.ts @@ -0,0 +1,27 @@ +import {gql} from '@apollo/client/core'; + +export default gql` + query JIPTExample($projectId: ID!) { + viewer { + project(id: $projectId) { + id + name + mainColor + + revision { + id + translations(pageSize: 1) { + entries { + id + key + document { + id + path + } + } + } + } + } + } + } +`; diff --git a/webapp/app/queries/jipt-project.ts b/webapp/app/queries/jipt-project.ts index 025f25eb5..78e24c974 100644 --- a/webapp/app/queries/jipt-project.ts +++ b/webapp/app/queries/jipt-project.ts @@ -1,4 +1,4 @@ -import gql from 'graphql-tag'; +import {gql} from '@apollo/client/core'; export default gql` query Project($projectId: ID!, $revisionId: ID) { diff --git a/webapp/app/queries/jipt-translations.ts b/webapp/app/queries/jipt-translations.ts index a6d4ff613..77b731d67 100644 --- a/webapp/app/queries/jipt-translations.ts +++ b/webapp/app/queries/jipt-translations.ts @@ -1,4 +1,4 @@ -import gql from 'graphql-tag'; +import {gql} from '@apollo/client/core'; export default gql` query Translations( diff --git a/webapp/app/queries/languages-search.ts b/webapp/app/queries/languages-search.ts index 2681fde06..072bcd948 100644 --- a/webapp/app/queries/languages-search.ts +++ b/webapp/app/queries/languages-search.ts @@ -1,4 +1,4 @@ -import gql from 'graphql-tag'; +import {gql} from '@apollo/client/core'; export default gql` query LanguagesSearch($query: String!) { diff --git a/webapp/app/queries/lint-translation.ts b/webapp/app/queries/lint-translation.ts index 3f4075f4a..28ae607d2 100644 --- a/webapp/app/queries/lint-translation.ts +++ b/webapp/app/queries/lint-translation.ts @@ -1,4 +1,4 @@ -import gql from 'graphql-tag'; +import {gql} from '@apollo/client/core'; export default gql` query LintTranslation($projectId: ID!, $text: String, $translationId: ID!) { diff --git a/webapp/app/queries/lint-translations.ts b/webapp/app/queries/lint-translations.ts index 7483373c4..1973df500 100644 --- a/webapp/app/queries/lint-translations.ts +++ b/webapp/app/queries/lint-translations.ts @@ -1,4 +1,4 @@ -import gql from 'graphql-tag'; +import {gql} from '@apollo/client/core'; export default gql` query Lint( diff --git a/webapp/app/queries/project-activities.ts b/webapp/app/queries/project-activities.ts index c4af2dd52..b18ab6d1a 100644 --- a/webapp/app/queries/project-activities.ts +++ b/webapp/app/queries/project-activities.ts @@ -1,4 +1,4 @@ -import gql from 'graphql-tag'; +import {gql} from '@apollo/client/core'; export default gql` query ProjectActivities( diff --git a/webapp/app/queries/project-activity.ts b/webapp/app/queries/project-activity.ts index 6b9470810..dbd4101cf 100644 --- a/webapp/app/queries/project-activity.ts +++ b/webapp/app/queries/project-activity.ts @@ -1,4 +1,4 @@ -import gql from 'graphql-tag'; +import {gql} from '@apollo/client/core'; export default gql` query ProjectActivity($projectId: ID!, $activityId: ID!) { diff --git a/webapp/app/queries/project-api-token.ts b/webapp/app/queries/project-api-token.ts index a3c4af84b..2c3a71155 100644 --- a/webapp/app/queries/project-api-token.ts +++ b/webapp/app/queries/project-api-token.ts @@ -1,4 +1,4 @@ -import gql from 'graphql-tag'; +import {gql} from '@apollo/client/core'; export default gql` query ProjectApiToken($projectId: ID!) { diff --git a/webapp/app/queries/project-collaborators.ts b/webapp/app/queries/project-collaborators.ts index bbc98f6c3..e2aa05218 100644 --- a/webapp/app/queries/project-collaborators.ts +++ b/webapp/app/queries/project-collaborators.ts @@ -1,4 +1,4 @@ -import gql from 'graphql-tag'; +import {gql} from '@apollo/client/core'; export default gql` query ProjectCollaborators($projectId: ID!) { diff --git a/webapp/app/queries/project-comments.ts b/webapp/app/queries/project-comments.ts index b01248c4b..43759d7ac 100644 --- a/webapp/app/queries/project-comments.ts +++ b/webapp/app/queries/project-comments.ts @@ -1,4 +1,4 @@ -import gql from 'graphql-tag'; +import {gql} from '@apollo/client/core'; export default gql` query ProjectComments($projectId: ID!, $page: Int) { diff --git a/webapp/app/queries/project-dashboard.ts b/webapp/app/queries/project-dashboard.ts index cc8beeef3..089dd7431 100644 --- a/webapp/app/queries/project-dashboard.ts +++ b/webapp/app/queries/project-dashboard.ts @@ -1,4 +1,4 @@ -import gql from 'graphql-tag'; +import {gql} from '@apollo/client/core'; export interface ProjectDashboardQueryVariables { projectId: string; @@ -21,6 +21,7 @@ export interface ProjectDashboardQueryResponse { id: string; conflictsCount: number; reviewedCount: number; + translatedCount: number; translationsCount: number; isMaster: boolean; name: string; @@ -131,6 +132,7 @@ export default gql` id conflictsCount reviewedCount + translatedCount translationsCount isMaster name diff --git a/webapp/app/queries/project-documents.ts b/webapp/app/queries/project-documents.ts index 46808ff89..320a5ad15 100644 --- a/webapp/app/queries/project-documents.ts +++ b/webapp/app/queries/project-documents.ts @@ -1,4 +1,4 @@ -import gql from 'graphql-tag'; +import {gql} from '@apollo/client/core'; export default gql` query ProjectDocuments( diff --git a/webapp/app/queries/project-edit.ts b/webapp/app/queries/project-edit.ts index 2ac6269ce..ec9b410df 100644 --- a/webapp/app/queries/project-edit.ts +++ b/webapp/app/queries/project-edit.ts @@ -1,4 +1,4 @@ -import gql from 'graphql-tag'; +import {gql} from '@apollo/client/core'; export default gql` query ProjectEdit($projectId: ID!) { @@ -9,6 +9,9 @@ export default gql` mainColor logo isFileOperationsLocked + integrations { + id + } } } } diff --git a/webapp/app/queries/project-machine-translations-config.ts b/webapp/app/queries/project-machine-translations-config.ts index 24a8dc315..1ef34b983 100644 --- a/webapp/app/queries/project-machine-translations-config.ts +++ b/webapp/app/queries/project-machine-translations-config.ts @@ -1,4 +1,4 @@ -import gql from 'graphql-tag'; +import {gql} from '@apollo/client/core'; export default gql` query ProjectMachineTranslationsConfig($projectId: ID!) { @@ -7,8 +7,8 @@ export default gql` id machineTranslationsConfig { provider - usePlatform enabledActions + usePlatform useConfigKey } } diff --git a/webapp/app/queries/project-new-language.ts b/webapp/app/queries/project-new-language.ts index b8a856ee5..b53f01a70 100644 --- a/webapp/app/queries/project-new-language.ts +++ b/webapp/app/queries/project-new-language.ts @@ -1,4 +1,4 @@ -import gql from 'graphql-tag'; +import {gql} from '@apollo/client/core'; export default gql` query ProjectNewLanguage($projectId: ID!) { diff --git a/webapp/app/queries/project-prompt-config.ts b/webapp/app/queries/project-prompt-config.ts index 95e6c578e..0a499b48c 100644 --- a/webapp/app/queries/project-prompt-config.ts +++ b/webapp/app/queries/project-prompt-config.ts @@ -1,4 +1,4 @@ -import gql from 'graphql-tag'; +import {gql} from '@apollo/client/core'; export interface ProjectPromptConfigResponse { viewer: { @@ -31,6 +31,8 @@ export default gql` promptConfig { provider + usePlatform + useConfigKey } } } diff --git a/webapp/app/queries/project-prompts.ts b/webapp/app/queries/project-prompts.ts index 12eb6543c..c85834554 100644 --- a/webapp/app/queries/project-prompts.ts +++ b/webapp/app/queries/project-prompts.ts @@ -1,4 +1,4 @@ -import gql from 'graphql-tag'; +import {gql} from '@apollo/client/core'; export default gql` query ProjectPrompts($projectId: ID!) { diff --git a/webapp/app/queries/project-service-integrations.ts b/webapp/app/queries/project-service-integrations.ts index 95a8aaf38..0d71fe80b 100644 --- a/webapp/app/queries/project-service-integrations.ts +++ b/webapp/app/queries/project-service-integrations.ts @@ -1,4 +1,4 @@ -import gql from 'graphql-tag'; +import {gql} from '@apollo/client/core'; export default gql` query ProjectServiceIntegrations($projectId: ID!) { @@ -27,6 +27,17 @@ export default gql` } } + ... on ProjectIntegrationAwsS3 { + lastExecutedAt + data { + id + bucket + pathPrefix + region + accessKeyId + } + } + ... on ProjectIntegrationAzureStorageContainer { lastExecutedAt data { diff --git a/webapp/app/queries/project-versions.ts b/webapp/app/queries/project-versions.ts index 1c633b19e..ccdfcd5e6 100644 --- a/webapp/app/queries/project-versions.ts +++ b/webapp/app/queries/project-versions.ts @@ -1,4 +1,4 @@ -import gql from 'graphql-tag'; +import {gql} from '@apollo/client/core'; export default gql` query ProjectVersions($projectId: ID!, $page: Int) { @@ -28,6 +28,7 @@ export default gql` name tag insertedAt + copyOnUpdateTranslation user { id diff --git a/webapp/app/queries/project.ts b/webapp/app/queries/project.ts index 80356355e..ca58a9b6e 100644 --- a/webapp/app/queries/project.ts +++ b/webapp/app/queries/project.ts @@ -1,4 +1,4 @@ -import gql from 'graphql-tag'; +import {gql} from '@apollo/client/core'; export interface ProjectQueryVariables { projectId: string; diff --git a/webapp/app/queries/projects.ts b/webapp/app/queries/projects.ts index 8935eb269..40530b964 100644 --- a/webapp/app/queries/projects.ts +++ b/webapp/app/queries/projects.ts @@ -1,4 +1,4 @@ -import gql from 'graphql-tag'; +import {gql} from '@apollo/client/core'; export default gql` query Projects($query: String, $page: Int, $nodeIds: [ID!]) { @@ -35,8 +35,6 @@ export default gql` lastSyncedAt mainColor logo - translationsCount - conflictsCount } } } diff --git a/webapp/app/queries/promote-master-revision.ts b/webapp/app/queries/promote-master-revision.ts index 8820a2d28..72e8dabbc 100644 --- a/webapp/app/queries/promote-master-revision.ts +++ b/webapp/app/queries/promote-master-revision.ts @@ -1,4 +1,4 @@ -import gql from 'graphql-tag'; +import {gql} from '@apollo/client/core'; export default gql` mutation RevisionMasterPromote($revisionId: ID!) { diff --git a/webapp/app/queries/related-translations.ts b/webapp/app/queries/related-translations.ts index f871f9878..b616375af 100644 --- a/webapp/app/queries/related-translations.ts +++ b/webapp/app/queries/related-translations.ts @@ -1,4 +1,4 @@ -import gql from 'graphql-tag'; +import {gql} from '@apollo/client/core'; export default gql` query RelatedTranslations($projectId: ID!, $translationId: ID!) { diff --git a/webapp/app/queries/revoke-api-token.ts b/webapp/app/queries/revoke-api-token.ts index 078bb4a22..f4cd60bf3 100644 --- a/webapp/app/queries/revoke-api-token.ts +++ b/webapp/app/queries/revoke-api-token.ts @@ -1,4 +1,4 @@ -import gql from 'graphql-tag'; +import {gql} from '@apollo/client/core'; export interface RevokeApiTokenVariables { id: string; diff --git a/webapp/app/queries/rollback-operation.ts b/webapp/app/queries/rollback-operation.ts index e2b63cdae..e8f7d7ff1 100644 --- a/webapp/app/queries/rollback-operation.ts +++ b/webapp/app/queries/rollback-operation.ts @@ -1,4 +1,4 @@ -import gql from 'graphql-tag'; +import {gql} from '@apollo/client/core'; export default gql` mutation OperationRollback($operationId: ID!) { diff --git a/webapp/app/queries/save-project-machine-translations-config.ts b/webapp/app/queries/save-project-machine-translations-config.ts index de1f54039..f794ed777 100644 --- a/webapp/app/queries/save-project-machine-translations-config.ts +++ b/webapp/app/queries/save-project-machine-translations-config.ts @@ -1,4 +1,4 @@ -import gql from 'graphql-tag'; +import {gql} from '@apollo/client/core'; export interface SaveProjectMachineTranslationsConfigVariables { projectId: string; diff --git a/webapp/app/queries/save-project-prompt-config.ts b/webapp/app/queries/save-project-prompt-config.ts index 1d0c08363..f88cd6638 100644 --- a/webapp/app/queries/save-project-prompt-config.ts +++ b/webapp/app/queries/save-project-prompt-config.ts @@ -1,9 +1,10 @@ -import gql from 'graphql-tag'; +import {gql} from '@apollo/client/core'; export interface SaveProjectPromptConfigVariables { projectId: string; provider: string; configKey: string; + usePlatform: boolean; } export interface SaveProjectPromptConfigResponse { @@ -18,11 +19,13 @@ export default gql` mutation ProjectPromptConfigSave( $provider: String! $configKey: String + $usePlatform: Boolean! $projectId: ID! ) { saveProjectPromptConfig( provider: $provider configKey: $configKey + usePlatform: $usePlatform projectId: $projectId ) { project { diff --git a/webapp/app/queries/translate-text-project.ts b/webapp/app/queries/translate-text-project.ts index 077617837..99e646693 100644 --- a/webapp/app/queries/translate-text-project.ts +++ b/webapp/app/queries/translate-text-project.ts @@ -1,4 +1,4 @@ -import gql from 'graphql-tag'; +import {gql} from '@apollo/client/core'; export default gql` query TranslateTextProject( diff --git a/webapp/app/queries/translation-activities.ts b/webapp/app/queries/translation-activities.ts index 7da2e1d85..3eb28bbc5 100644 --- a/webapp/app/queries/translation-activities.ts +++ b/webapp/app/queries/translation-activities.ts @@ -1,4 +1,4 @@ -import gql from 'graphql-tag'; +import {gql} from '@apollo/client/core'; export default gql` query TranslationActivities( diff --git a/webapp/app/queries/translation-comments.ts b/webapp/app/queries/translation-comments.ts index 921f0e2d8..6867ff35a 100644 --- a/webapp/app/queries/translation-comments.ts +++ b/webapp/app/queries/translation-comments.ts @@ -1,4 +1,4 @@ -import gql from 'graphql-tag'; +import {gql} from '@apollo/client/core'; export default gql` query TranslationComments($projectId: ID!, $translationId: ID!, $page: Int) { diff --git a/webapp/app/queries/translation-editions.ts b/webapp/app/queries/translation-editions.ts index b3d68debf..534d5c962 100644 --- a/webapp/app/queries/translation-editions.ts +++ b/webapp/app/queries/translation-editions.ts @@ -1,4 +1,4 @@ -import gql from 'graphql-tag'; +import {gql} from '@apollo/client/core'; export default gql` query Translations($projectId: ID!, $translationId: ID!) { @@ -41,18 +41,6 @@ export default gql` tag } - revision { - id - slug - rtl - - language { - id - slug - rtl - } - } - document { id path diff --git a/webapp/app/queries/translation.ts b/webapp/app/queries/translation.ts index 38700a7de..59180cd7d 100644 --- a/webapp/app/queries/translation.ts +++ b/webapp/app/queries/translation.ts @@ -1,4 +1,4 @@ -import gql from 'graphql-tag'; +import {gql} from '@apollo/client/core'; export default gql` query Translation($projectId: ID!, $translationId: ID!) { diff --git a/webapp/app/queries/translations.ts b/webapp/app/queries/translations.ts index 88432710d..77ab048c3 100644 --- a/webapp/app/queries/translations.ts +++ b/webapp/app/queries/translations.ts @@ -1,4 +1,4 @@ -import gql from 'graphql-tag'; +import {gql} from '@apollo/client/core'; export default gql` query Translations( @@ -44,6 +44,7 @@ export default gql` id translations( query: $query + pageSize: 20 page: $page document: $document version: $version @@ -93,6 +94,7 @@ export default gql` rtl } } + document { id path diff --git a/webapp/app/queries/uncorrect-all-revision.ts b/webapp/app/queries/uncorrect-all-revision.ts index f97ffea7a..2a7369b28 100644 --- a/webapp/app/queries/uncorrect-all-revision.ts +++ b/webapp/app/queries/uncorrect-all-revision.ts @@ -1,4 +1,4 @@ -import gql from 'graphql-tag'; +import {gql} from '@apollo/client/core'; export default gql` mutation UncorrectAll($revisionId: ID!) { diff --git a/webapp/app/queries/uncorrect-translation.ts b/webapp/app/queries/uncorrect-translation.ts index b89d47213..bf8dc6956 100644 --- a/webapp/app/queries/uncorrect-translation.ts +++ b/webapp/app/queries/uncorrect-translation.ts @@ -1,4 +1,4 @@ -import gql from 'graphql-tag'; +import {gql} from '@apollo/client/core'; export default gql` mutation TranslationUncorrect($translationId: ID!, $text: String!) { diff --git a/webapp/app/queries/update-collaborator.ts b/webapp/app/queries/update-collaborator.ts index f69aab83b..ad5c0bfac 100644 --- a/webapp/app/queries/update-collaborator.ts +++ b/webapp/app/queries/update-collaborator.ts @@ -1,4 +1,4 @@ -import gql from 'graphql-tag'; +import {gql} from '@apollo/client/core'; export default gql` mutation CollaboratorUpdate($collaboratorId: ID!, $role: Role!) { diff --git a/webapp/app/queries/update-comment.ts b/webapp/app/queries/update-comment.ts index ad844ccc6..a294d7df8 100644 --- a/webapp/app/queries/update-comment.ts +++ b/webapp/app/queries/update-comment.ts @@ -1,4 +1,4 @@ -import gql from 'graphql-tag'; +import {gql} from '@apollo/client/core'; export default gql` mutation CommentUpdate($commentId: ID!, $text: String!) { diff --git a/webapp/app/queries/update-document.ts b/webapp/app/queries/update-document.ts index 368a5f7ed..ce577424d 100644 --- a/webapp/app/queries/update-document.ts +++ b/webapp/app/queries/update-document.ts @@ -1,4 +1,4 @@ -import gql from 'graphql-tag'; +import {gql} from '@apollo/client/core'; export default gql` mutation DocumentUpdate($documentId: ID!, $path: String!) { diff --git a/webapp/app/queries/update-integration.ts b/webapp/app/queries/update-integration.ts index 17b52b318..e523e1d64 100644 --- a/webapp/app/queries/update-integration.ts +++ b/webapp/app/queries/update-integration.ts @@ -1,4 +1,4 @@ -import gql from 'graphql-tag'; +import {gql} from '@apollo/client/core'; export default gql` mutation IntegrationUpdate( diff --git a/webapp/app/queries/update-project-prompt.ts b/webapp/app/queries/update-project-prompt.ts index 063d8f1c9..edc29ec56 100644 --- a/webapp/app/queries/update-project-prompt.ts +++ b/webapp/app/queries/update-project-prompt.ts @@ -1,4 +1,4 @@ -import gql from 'graphql-tag'; +import {gql} from '@apollo/client/core'; export default gql` mutation PromptUpdate( diff --git a/webapp/app/queries/update-project.ts b/webapp/app/queries/update-project.ts index 1a2f79d16..1453318b1 100644 --- a/webapp/app/queries/update-project.ts +++ b/webapp/app/queries/update-project.ts @@ -1,4 +1,4 @@ -import gql from 'graphql-tag'; +import {gql} from '@apollo/client/core'; export default gql` mutation ProjectUpdate( diff --git a/webapp/app/queries/update-revision.ts b/webapp/app/queries/update-revision.ts index 46f9cac70..b5b648f13 100644 --- a/webapp/app/queries/update-revision.ts +++ b/webapp/app/queries/update-revision.ts @@ -1,4 +1,4 @@ -import gql from 'graphql-tag'; +import {gql} from '@apollo/client/core'; export default gql` mutation RevisionUpdate($revisionId: ID!, $name: String, $slug: String) { diff --git a/webapp/app/queries/update-translation.ts b/webapp/app/queries/update-translation.ts index aaaafeb9a..9a2c6eee0 100644 --- a/webapp/app/queries/update-translation.ts +++ b/webapp/app/queries/update-translation.ts @@ -1,4 +1,4 @@ -import gql from 'graphql-tag'; +import {gql} from '@apollo/client/core'; export default gql` mutation TranslationUpdate($translationId: ID!, $text: String!) { diff --git a/webapp/app/queries/update-version.ts b/webapp/app/queries/update-version.ts index 408250a68..53f0c880f 100644 --- a/webapp/app/queries/update-version.ts +++ b/webapp/app/queries/update-version.ts @@ -1,8 +1,18 @@ -import gql from 'graphql-tag'; +import {gql} from '@apollo/client/core'; export default gql` - mutation VersionUpdate($id: ID!, $name: String!, $tag: String!) { - updateVersion(id: $id, name: $name, tag: $tag) { + mutation VersionUpdate( + $id: ID! + $name: String! + $tag: String! + $copyOnUpdateTranslation: Boolean! + ) { + updateVersion( + id: $id + name: $name + tag: $tag + copyOnUpdateTranslation: $copyOnUpdateTranslation + ) { version { id name diff --git a/webapp/app/router.js b/webapp/app/router.js index 3b10a73f4..2f57d08ba 100644 --- a/webapp/app/router.js +++ b/webapp/app/router.js @@ -11,6 +11,8 @@ export default Router.map(function () { this.route('login', {path: ''}); this.route('logged-in', {path: 'app'}, function () { + this.route('jipt-example', {path: 'projects/:projectId/jipt-example'}); + this.route('jipt', {path: 'projects/:projectId/jipt'}, function () { this.route( 'translation', @@ -54,7 +56,7 @@ export default Router.map(function () { this.route('export', {path: ':fileId/export'}); this.route('jipt', {path: ':fileId/jipt'}); this.route('machine-translations', { - path: ':fileId/machine-translations', + path: ':fileId/machine-translations' }); }); this.route('versions', function () { @@ -64,9 +66,10 @@ export default Router.map(function () { }); this.route('comments', {path: 'conversation'}); + this.route('conflicts'); + this.route('revision', {path: 'revisions/:revisionId'}, function () { this.route('translations'); - this.route('conflicts'); this.route('lint-translations'); }); diff --git a/webapp/app/pods/application/route.ts b/webapp/app/routes/application.ts similarity index 100% rename from webapp/app/pods/application/route.ts rename to webapp/app/routes/application.ts diff --git a/webapp/app/pods/logged-in/route.ts b/webapp/app/routes/logged-in.ts similarity index 73% rename from webapp/app/pods/logged-in/route.ts rename to webapp/app/routes/logged-in.ts index 78bae430f..c0765c507 100644 --- a/webapp/app/pods/logged-in/route.ts +++ b/webapp/app/routes/logged-in.ts @@ -2,18 +2,22 @@ import {inject as service} from '@ember/service'; import Route from '@ember/routing/route'; import Raven from 'raven-js'; import Session from 'accent-webapp/services/session'; +import RouterService from '@ember/routing/router-service'; export default class LoggedInRoute extends Route { @service('session') session: Session; + @service('router') + router: RouterService; + afterModel() { Raven.setUserContext(this.session.credentials.user); } redirect() { if (!this.session.isAuthenticated) { - this.transitionTo('login'); + this.router.transitionTo('login'); } } } diff --git a/webapp/app/routes/logged-in/jipt-example.ts b/webapp/app/routes/logged-in/jipt-example.ts new file mode 100644 index 000000000..5925f43f8 --- /dev/null +++ b/webapp/app/routes/logged-in/jipt-example.ts @@ -0,0 +1,42 @@ +import Route from '@ember/routing/route'; +import {inject as service} from '@ember/service'; + +import jiptExampleQuery from 'accent-webapp/queries/jipt-example'; +import ApolloSubscription, { + Subscription +} from 'accent-webapp/services/apollo-subscription'; + +export default class JIPTExampleRoute extends Route { + @service('apollo-subscription') + apolloSubscription: ApolloSubscription; + + subscription: Subscription; + + model(params: any) { + (window as any).accentJiptInit = { + h: window.location.origin, + i: params.projectId + }; + + this.subscription = this.apolloSubscription.graphql( + () => this.modelFor(this.routeName), + jiptExampleQuery, + { + props: (data) => ({ + project: data.viewer.project + }), + options: { + variables: { + projectId: params.projectId + } + } + } + ); + + return this.subscription.currentResult(); + } + + deactivate() { + this.apolloSubscription.clearSubscription(this.subscription); + } +} diff --git a/webapp/app/pods/logged-in/jipt/route.ts b/webapp/app/routes/logged-in/jipt.ts similarity index 93% rename from webapp/app/pods/logged-in/jipt/route.ts rename to webapp/app/routes/logged-in/jipt.ts index 059a98379..3320939fe 100644 --- a/webapp/app/pods/logged-in/jipt/route.ts +++ b/webapp/app/routes/logged-in/jipt.ts @@ -3,7 +3,7 @@ import {inject as service} from '@ember/service'; import projectQuery from 'accent-webapp/queries/jipt-project'; import ApolloSubscription, { - Subscription, + Subscription } from 'accent-webapp/services/apollo-subscription'; import JIPT from 'accent-webapp/services/jipt'; import GlobalState from 'accent-webapp/services/global-state'; @@ -20,8 +20,8 @@ export default class JIPTRoute extends Route { queryParams = { revisionId: { - refreshModel: true, - }, + refreshModel: true + } }; subscription: Subscription; @@ -35,9 +35,9 @@ export default class JIPTRoute extends Route { options: { variables: { projectId: params.projectId, - revisionId: params.revisionId, - }, - }, + revisionId: params.revisionId + } + } } ); @@ -50,6 +50,7 @@ export default class JIPTRoute extends Route { private props(data: any) { if (!data.viewer || !data.viewer.project) return {permissions: []}; + this.globalState.mainColor = data.viewer.project.mainColor; this.jipt.listTranslations( data.viewer.project.revision.translations.entries, @@ -65,7 +66,6 @@ export default class JIPTRoute extends Route { ); this.globalState.permissions = permissions; - this.globalState.mainColor = data.viewer.project.mainColor; return {project: data.viewer.project, permissions, roles: data.roles}; } diff --git a/webapp/app/pods/logged-in/jipt/index/route.ts b/webapp/app/routes/logged-in/jipt/index.ts similarity index 71% rename from webapp/app/pods/logged-in/jipt/index/route.ts rename to webapp/app/routes/logged-in/jipt/index.ts index b31b460f9..e0c2d8e9d 100644 --- a/webapp/app/pods/logged-in/jipt/index/route.ts +++ b/webapp/app/routes/logged-in/jipt/index.ts @@ -3,11 +3,11 @@ import Route from '@ember/routing/route'; import translationsQuery from 'accent-webapp/queries/jipt-translations'; import ApolloSubscription, { - Subscription, + Subscription } from 'accent-webapp/services/apollo-subscription'; import RouteParams from 'accent-webapp/services/route-params'; -import Transition from '@ember/routing/-private/transition'; -import IndexController from 'accent-webapp/pods/logged-in/jipt/index/controller'; +import Transition from '@ember/routing/transition'; +import IndexController from 'accent-webapp/controllers/logged-in/jipt/index'; export default class IndexRoute extends Route { @service('apollo-subscription') @@ -18,17 +18,17 @@ export default class IndexRoute extends Route { queryParams = { query: { - refreshModel: true, + refreshModel: true }, page: { - refreshModel: true, + refreshModel: true }, document: { - refreshModel: true, + refreshModel: true }, version: { - refreshModel: true, - }, + refreshModel: true + } }; subscription: Subscription; @@ -38,10 +38,18 @@ export default class IndexRoute extends Route { query, page, document, - version, + version }: {query: any; page: number; document: any; version: any}, transition: Transition ) { + if (this.subscription) + this.apolloSubscription.clearSubscription(this.subscription); + + const projectId = this.routeParams.fetch( + transition, + 'logged-in.jipt' + ).projectId; + this.subscription = this.apolloSubscription.graphql( () => this.modelFor(this.routeName), translationsQuery, @@ -51,23 +59,19 @@ export default class IndexRoute extends Route { documents: data.viewer.project.documents.entries, versions: data.viewer.project.versions.entries, translations: data.viewer.project.revision.translations, - selectedTranslationIds: this.routeParams.fetch( - transition, - 'logged-in.jipt' - ).transitionIds, + selectedTranslationIds: transition?.to?.queryParams.translationIds }), options: { fetchPolicy: 'cache-and-network', variables: { - projectId: this.routeParams.fetch(transition, 'logged-in.jipt') - .projectId, - revisionId: transition.to.queryParams.revisionId, + projectId, + revisionId: transition?.to?.queryParams.revisionId, query, page, document, - version, - }, - }, + version + } + } } ); diff --git a/webapp/app/pods/logged-in/jipt/translation/route.ts b/webapp/app/routes/logged-in/jipt/translation.ts similarity index 79% rename from webapp/app/pods/logged-in/jipt/translation/route.ts rename to webapp/app/routes/logged-in/jipt/translation.ts index 2f1417a68..451516da6 100644 --- a/webapp/app/pods/logged-in/jipt/translation/route.ts +++ b/webapp/app/routes/logged-in/jipt/translation.ts @@ -3,10 +3,10 @@ import Route from '@ember/routing/route'; import translationQuery from 'accent-webapp/queries/translation'; import ApolloSubscription, { - Subscription, + Subscription } from 'accent-webapp/services/apollo-subscription'; import RouteParams from 'accent-webapp/services/route-params'; -import Transition from '@ember/routing/-private/transition'; +import Transition from '@ember/routing/transition'; export default class TranslationRoute extends Route { @service('apollo-subscription') @@ -18,6 +18,9 @@ export default class TranslationRoute extends Route { subscription: Subscription; model({translationId}: {translationId: string}, transition: Transition) { + if (this.subscription) + this.apolloSubscription.clearSubscription(this.subscription); + this.subscription = this.apolloSubscription.graphql( () => this.modelFor(this.routeName), translationQuery, @@ -25,15 +28,17 @@ export default class TranslationRoute extends Route { props: (data) => ({ project: data.viewer.project, translation: data.viewer.project.translation, + revisions: data.viewer.project.revisions, + prompts: data.viewer.project.prompts }), options: { fetchPolicy: 'cache-and-network', variables: { projectId: this.routeParams.fetch(transition, 'logged-in.jipt') .projectId, - translationId, - }, - }, + translationId + } + } } ); diff --git a/webapp/app/pods/logged-in/jipt/translation/index/route.ts b/webapp/app/routes/logged-in/jipt/translation/index.ts similarity index 100% rename from webapp/app/pods/logged-in/jipt/translation/index/route.ts rename to webapp/app/routes/logged-in/jipt/translation/index.ts diff --git a/webapp/app/pods/logged-in/project/route.ts b/webapp/app/routes/logged-in/project.ts similarity index 89% rename from webapp/app/pods/logged-in/project/route.ts rename to webapp/app/routes/logged-in/project.ts index e30dfedc5..32e8d43fb 100644 --- a/webapp/app/pods/logged-in/project/route.ts +++ b/webapp/app/routes/logged-in/project.ts @@ -6,17 +6,13 @@ import projectQuery, { ProjectQueryResponse, ProjectQueryResponseProject, ProjectQueryResponseRole, - ProjectQueryResponseDocumentFormat, + ProjectQueryResponseDocumentFormat } from 'accent-webapp/queries/project'; import GlobalState from 'accent-webapp/services/global-state'; import ApolloSubscription, { - Subscription, + Subscription } from 'accent-webapp/services/apollo-subscription'; -interface RouteParams { - projectId: string; -} - interface Model { project?: ProjectQueryResponseProject; permissions: object; @@ -33,7 +29,7 @@ export default class ProjectRoute extends Route { subscription: Subscription; - model(params: RouteParams): Model { + model(params: any): Model { const props = (data: any) => this.transformData(data); this.subscription = this.apolloSubscription.graphql( @@ -43,9 +39,9 @@ export default class ProjectRoute extends Route { props, options: { variables: { - projectId: params.projectId, - }, - }, + projectId: params.projectId + } + } } ); @@ -88,7 +84,7 @@ export default class ProjectRoute extends Route { project: data.viewer.project, permissions, roles: data.roles, - documentFormats: data.documentFormats, + documentFormats: data.documentFormats }; } } diff --git a/webapp/app/pods/logged-in/project/activities/route.ts b/webapp/app/routes/logged-in/project/activities.ts similarity index 80% rename from webapp/app/pods/logged-in/project/activities/route.ts rename to webapp/app/routes/logged-in/project/activities.ts index 72f915536..c6d3f586c 100644 --- a/webapp/app/pods/logged-in/project/activities/route.ts +++ b/webapp/app/routes/logged-in/project/activities.ts @@ -4,11 +4,11 @@ import Route from '@ember/routing/route'; import projectActivitiesQuery from 'accent-webapp/queries/project-activities'; import RouteParams from 'accent-webapp/services/route-params'; -import Transition from '@ember/routing/-private/transition'; +import Transition from '@ember/routing/transition'; import ApolloSubscription, { - Subscription, + Subscription } from 'accent-webapp/services/apollo-subscription'; -import ActivitiesController from 'accent-webapp/pods/logged-in/project/activities/controller'; +import ActivitiesController from 'accent-webapp/controllers/logged-in/project/activities'; export default class ActivitiesRoute extends Route { @service('apollo-subscription') @@ -19,20 +19,20 @@ export default class ActivitiesRoute extends Route { queryParams = { batchFilter: { - refreshModel: true, + refreshModel: true }, actionFilter: { - refreshModel: true, + refreshModel: true }, userFilter: { - refreshModel: true, + refreshModel: true }, versionFilter: { - refreshModel: true, + refreshModel: true }, page: { - refreshModel: true, - }, + refreshModel: true + } }; subscription: Subscription; @@ -43,7 +43,7 @@ export default class ActivitiesRoute extends Route { actionFilter, userFilter, versionFilter, - page, + page }: { batchFilter: any; actionFilter: any; @@ -53,6 +53,9 @@ export default class ActivitiesRoute extends Route { }, transition: Transition ) { + if (this.subscription) + this.apolloSubscription.clearSubscription(this.subscription); + this.subscription = this.apolloSubscription.graphql( () => this.modelFor(this.routeName), projectActivitiesQuery, @@ -61,7 +64,7 @@ export default class ActivitiesRoute extends Route { project: data.viewer.project, activities: data.viewer.project.activities, collaborators: data.viewer.project.collaborators, - versions: data.viewer.project.versions.entries, + versions: data.viewer.project.versions.entries }), options: { fetchPolicy: 'cache-and-network', @@ -72,9 +75,9 @@ export default class ActivitiesRoute extends Route { action: actionFilter === '' ? null : actionFilter, userId: userFilter === '' ? null : userFilter, versionId: versionFilter === '' ? null : versionFilter, - page, - }, - }, + page + } + } } ); diff --git a/webapp/app/pods/logged-in/project/activity/route.ts b/webapp/app/routes/logged-in/project/activity.ts similarity index 82% rename from webapp/app/pods/logged-in/project/activity/route.ts rename to webapp/app/routes/logged-in/project/activity.ts index cba38334d..eeb9a3187 100644 --- a/webapp/app/pods/logged-in/project/activity/route.ts +++ b/webapp/app/routes/logged-in/project/activity.ts @@ -5,9 +5,9 @@ import Route from '@ember/routing/route'; import projectActivityQuery from 'accent-webapp/queries/project-activity'; import RouteParams from 'accent-webapp/services/route-params'; import ApolloSubscription, { - Subscription, + Subscription } from 'accent-webapp/services/apollo-subscription'; -import Transition from '@ember/routing/-private/transition'; +import Transition from '@ember/routing/transition'; export default class Activity extends Route { @service('apollo-subscription') @@ -19,22 +19,25 @@ export default class Activity extends Route { subscription: Subscription; model({activityId}: {activityId: string}, transition: Transition) { + if (this.subscription) + this.apolloSubscription.clearSubscription(this.subscription); + this.subscription = this.apolloSubscription.graphql( () => this.modelFor(this.routeName), projectActivityQuery, { props: (data) => ({ project: data.viewer.project, - activity: data.viewer.project.activity, + activity: data.viewer.project.activity }), options: { fetchPolicy: 'cache-and-network', variables: { projectId: this.routeParams.fetch(transition, 'logged-in.project') .projectId, - activityId, - }, - }, + activityId + } + } } ); diff --git a/webapp/app/pods/logged-in/project/collaborators/route.ts b/webapp/app/routes/logged-in/project/collaborators.ts similarity index 82% rename from webapp/app/pods/logged-in/project/collaborators/route.ts rename to webapp/app/routes/logged-in/project/collaborators.ts index f7d052476..677a21298 100644 --- a/webapp/app/pods/logged-in/project/collaborators/route.ts +++ b/webapp/app/routes/logged-in/project/collaborators.ts @@ -5,9 +5,9 @@ import Route from '@ember/routing/route'; import projectCollaboratorsQuery from 'accent-webapp/queries/project-collaborators'; import RouteParams from 'accent-webapp/services/route-params'; import ApolloSubscription, { - Subscription, + Subscription } from 'accent-webapp/services/apollo-subscription'; -import Transition from '@ember/routing/-private/transition'; +import Transition from '@ember/routing/transition'; export default class CollaboratorsRoute extends Route { @service('apollo-subscription') @@ -19,20 +19,23 @@ export default class CollaboratorsRoute extends Route { subscription: Subscription; model(_params: any, transition: Transition) { + if (this.subscription) + this.apolloSubscription.clearSubscription(this.subscription); + this.subscription = this.apolloSubscription.graphql( () => this.modelFor(this.routeName), projectCollaboratorsQuery, { props: (data) => ({ - project: data.viewer.project, + project: data.viewer.project }), options: { fetchPolicy: 'cache-and-network', variables: { projectId: this.routeParams.fetch(transition, 'logged-in.project') - .projectId, - }, - }, + .projectId + } + } } ); diff --git a/webapp/app/pods/logged-in/project/comments/route.ts b/webapp/app/routes/logged-in/project/comments.ts similarity index 78% rename from webapp/app/pods/logged-in/project/comments/route.ts rename to webapp/app/routes/logged-in/project/comments.ts index 5d69a97df..2f493353a 100644 --- a/webapp/app/pods/logged-in/project/comments/route.ts +++ b/webapp/app/routes/logged-in/project/comments.ts @@ -4,10 +4,10 @@ import Route from '@ember/routing/route'; import projectCommentsQuery from 'accent-webapp/queries/project-comments'; import RouteParams from 'accent-webapp/services/route-params'; import ApolloSubscription, { - Subscription, + Subscription } from 'accent-webapp/services/apollo-subscription'; -import Transition from '@ember/routing/-private/transition'; -import CommentsController from 'accent-webapp/pods/logged-in/project/comments/controller'; +import Transition from '@ember/routing/transition'; +import CommentsController from 'accent-webapp/controllers/logged-in/project/comments'; export default class CommentsRoute extends Route { @service('apollo-subscription') @@ -18,13 +18,16 @@ export default class CommentsRoute extends Route { queryParams = { page: { - refreshModel: true, - }, + refreshModel: true + } }; subscription: Subscription; model({page}: {page: string}, transition: Transition) { + if (this.subscription) + this.apolloSubscription.clearSubscription(this.subscription); + const pageNumber = page ? parseInt(page, 10) : null; this.subscription = this.apolloSubscription.graphql( @@ -33,16 +36,16 @@ export default class CommentsRoute extends Route { { props: (data) => ({ comments: data.viewer.project.comments, - project: data.viewer.project, + project: data.viewer.project }), options: { fetchPolicy: 'cache-and-network', variables: { projectId: this.routeParams.fetch(transition, 'logged-in.project') .projectId, - page: pageNumber, - }, - }, + page: pageNumber + } + } } ); diff --git a/webapp/app/pods/logged-in/project/revision/conflicts/route.ts b/webapp/app/routes/logged-in/project/conflicts.ts similarity index 54% rename from webapp/app/pods/logged-in/project/revision/conflicts/route.ts rename to webapp/app/routes/logged-in/project/conflicts.ts index e4b2a3507..847156085 100644 --- a/webapp/app/pods/logged-in/project/revision/conflicts/route.ts +++ b/webapp/app/routes/logged-in/project/conflicts.ts @@ -4,11 +4,11 @@ import Route from '@ember/routing/route'; import translationsQuery from 'accent-webapp/queries/conflicts'; import ApolloSubscription, { - Subscription, + 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 Transition from '@ember/routing/transition'; +import ConflictsController from 'accent-webapp/controllers/logged-in/project/conflicts'; import RouterService from '@ember/routing/router-service'; export default class ConflictsRoute extends Route { @@ -23,57 +23,71 @@ export default class ConflictsRoute extends Route { queryParams = { query: { - refreshModel: true, + refreshModel: true }, page: { - refreshModel: true, + refreshModel: true }, document: { - refreshModel: true, + refreshModel: true }, version: { - refreshModel: true, + refreshModel: true }, + relatedRevisions: { + refreshModel: true + }, + isTextEmpty: { + refreshModel: true + }, + isTextNotEmpty: { + refreshModel: true + }, + isAddedLastSync: { + refreshModel: true + }, + isCommentedOn: { + refreshModel: true + }, + isConflicted: { + refreshModel: true + }, + isTranslated: { + refreshModel: true + } }; subscription: Subscription; - model( - { - query, - page, - document, - version, - }: {query: any; page: number; document: any; version: any}, - transition: Transition - ) { + 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; + params.isTranslated = params.isTranslated === 'true' ? false : null; + this.subscription = this.apolloSubscription.graphql( () => this.modelFor(this.routeName), translationsQuery, { props: (data) => ({ - revisionModel: this.modelFor('logged-in.project.revision'), + projectModel: this.modelFor('logged-in.project'), + prompts: data.viewer.project.prompts, documents: data.viewer.project.documents.entries, versions: data.viewer.project.versions.entries, - prompts: data.viewer.project.prompts, + revisions: data.viewer.project.revisions, + relatedRevisions: data.viewer.project.groupedTranslations.revisions, project: data.viewer.project, - translations: data.viewer.project.revision.translations, + groupedTranslations: data.viewer.project.groupedTranslations }), 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, - version, - }, - }, + ...params + } + } } ); @@ -98,30 +112,4 @@ export default class ConflictsRoute extends Route { onRefresh() { this.refresh(); } - - @action - onRevisionChange({revisionId}: {revisionId: string}) { - const {project} = this.modelFor('logged-in.project') as {project: any}; - - this.apolloSubscription.clearSubscription(this.subscription); - - this.router.transitionTo( - 'logged-in.project.revision.conflicts', - project.id, - revisionId, - { - queryParams: this.fetchQueryParams( - this.controller as ConflictsController - ), - } - ); - } - - private fetchQueryParams(controller: ConflictsController) { - const query = controller.query; - - return { - query, - }; - } } diff --git a/webapp/app/pods/logged-in/project/edit/api-token/route.ts b/webapp/app/routes/logged-in/project/edit/api-token.ts similarity index 81% rename from webapp/app/pods/logged-in/project/edit/api-token/route.ts rename to webapp/app/routes/logged-in/project/edit/api-token.ts index f126021e3..9ad088cc7 100644 --- a/webapp/app/pods/logged-in/project/edit/api-token/route.ts +++ b/webapp/app/routes/logged-in/project/edit/api-token.ts @@ -4,9 +4,9 @@ import Route from '@ember/routing/route'; import projectApiTokenQuery from 'accent-webapp/queries/project-api-token'; import RouteParams from 'accent-webapp/services/route-params'; import ApolloSubscription, { - Subscription, + Subscription } from 'accent-webapp/services/apollo-subscription'; -import Transition from '@ember/routing/-private/transition'; +import Transition from '@ember/routing/transition'; export default class APITokenRoute extends Route { @service('apollo-subscription') @@ -18,6 +18,9 @@ export default class APITokenRoute extends Route { subscription: Subscription; model(_params: any, transition: Transition) { + if (this.subscription) + this.apolloSubscription.clearSubscription(this.subscription); + this.subscription = this.apolloSubscription.graphql( () => this.modelFor(this.routeName), projectApiTokenQuery, @@ -25,15 +28,15 @@ export default class APITokenRoute extends Route { props: (data) => ({ project: data.viewer.project, accessToken: data.viewer.accessToken, - apiToken: data.viewer.project.apiTokens, + apiToken: data.viewer.project.apiTokens }), options: { fetchPolicy: 'cache-and-network', variables: { projectId: this.routeParams.fetch(transition, 'logged-in.project') - .projectId, - }, - }, + .projectId + } + } } ); diff --git a/webapp/app/pods/logged-in/project/edit/badges/route.ts b/webapp/app/routes/logged-in/project/edit/badges.ts similarity index 82% rename from webapp/app/pods/logged-in/project/edit/badges/route.ts rename to webapp/app/routes/logged-in/project/edit/badges.ts index 4e8a38c87..83f32d222 100644 --- a/webapp/app/pods/logged-in/project/edit/badges/route.ts +++ b/webapp/app/routes/logged-in/project/edit/badges.ts @@ -5,9 +5,9 @@ import Route from '@ember/routing/route'; import projectEditQuery from 'accent-webapp/queries/project-edit'; import RouteParams from 'accent-webapp/services/route-params'; import ApolloSubscription, { - Subscription, + Subscription } from 'accent-webapp/services/apollo-subscription'; -import Transition from '@ember/routing/-private/transition'; +import Transition from '@ember/routing/transition'; export default class BadgesRoute extends Route { @service('apollo-subscription') @@ -19,20 +19,23 @@ export default class BadgesRoute extends Route { subscription: Subscription; model(_params: any, transition: Transition) { + if (this.subscription) + this.apolloSubscription.clearSubscription(this.subscription); + this.subscription = this.apolloSubscription.graphql( () => this.modelFor(this.routeName), projectEditQuery, { props: (data) => ({ - project: data.viewer.project, + project: data.viewer.project }), options: { fetchPolicy: 'cache-and-network', variables: { projectId: this.routeParams.fetch(transition, 'logged-in.project') - .projectId, - }, - }, + .projectId + } + } } ); diff --git a/webapp/app/pods/logged-in/project/edit/index/route.ts b/webapp/app/routes/logged-in/project/edit/index.ts similarity index 82% rename from webapp/app/pods/logged-in/project/edit/index/route.ts rename to webapp/app/routes/logged-in/project/edit/index.ts index 357670959..cc0792a58 100644 --- a/webapp/app/pods/logged-in/project/edit/index/route.ts +++ b/webapp/app/routes/logged-in/project/edit/index.ts @@ -5,9 +5,9 @@ import Route from '@ember/routing/route'; import projectEditQuery from 'accent-webapp/queries/project-edit'; import RouteParams from 'accent-webapp/services/route-params'; import ApolloSubscription, { - Subscription, + Subscription } from 'accent-webapp/services/apollo-subscription'; -import Transition from '@ember/routing/-private/transition'; +import Transition from '@ember/routing/transition'; export default class ProjectEditIndexRoute extends Route { @service('apollo-subscription') @@ -19,20 +19,23 @@ export default class ProjectEditIndexRoute extends Route { subscription: Subscription; model(_params: any, transition: Transition) { + if (this.subscription) + this.apolloSubscription.clearSubscription(this.subscription); + this.subscription = this.apolloSubscription.graphql( () => this.modelFor(this.routeName), projectEditQuery, { props: (data) => ({ - project: data.viewer.project, + project: data.viewer.project }), options: { fetchPolicy: 'cache-and-network', variables: { projectId: this.routeParams.fetch(transition, 'logged-in.project') - .projectId, - }, - }, + .projectId + } + } } ); diff --git a/webapp/app/pods/logged-in/project/edit/jipt/route.ts b/webapp/app/routes/logged-in/project/edit/jipt.ts similarity index 100% rename from webapp/app/pods/logged-in/project/edit/jipt/route.ts rename to webapp/app/routes/logged-in/project/edit/jipt.ts diff --git a/webapp/app/pods/logged-in/project/edit/machine-translations/route.ts b/webapp/app/routes/logged-in/project/edit/machine-translations.ts similarity index 82% rename from webapp/app/pods/logged-in/project/edit/machine-translations/route.ts rename to webapp/app/routes/logged-in/project/edit/machine-translations.ts index 7be5e829b..c8800d61f 100644 --- a/webapp/app/pods/logged-in/project/edit/machine-translations/route.ts +++ b/webapp/app/routes/logged-in/project/edit/machine-translations.ts @@ -4,9 +4,9 @@ import Route from '@ember/routing/route'; import projectMachineTranslationsConfigQuery from 'accent-webapp/queries/project-machine-translations-config'; import RouteParams from 'accent-webapp/services/route-params'; import ApolloSubscription, { - Subscription, + Subscription } from 'accent-webapp/services/apollo-subscription'; -import Transition from '@ember/routing/-private/transition'; +import Transition from '@ember/routing/transition'; export default class MachineTranslationsRoute extends Route { @service('apollo-subscription') @@ -18,20 +18,23 @@ export default class MachineTranslationsRoute extends Route { subscription: Subscription; model(_params: any, transition: Transition) { + if (this.subscription) + this.apolloSubscription.clearSubscription(this.subscription); + this.subscription = this.apolloSubscription.graphql( () => this.modelFor(this.routeName), projectMachineTranslationsConfigQuery, { props: (data) => ({ - project: data.viewer.project, + project: data.viewer.project }), options: { fetchPolicy: 'cache-and-network', variables: { projectId: this.routeParams.fetch(transition, 'logged-in.project') - .projectId, - }, - }, + .projectId + } + } } ); diff --git a/webapp/app/pods/logged-in/project/edit/prompts/route.ts b/webapp/app/routes/logged-in/project/edit/prompts.ts similarity index 81% rename from webapp/app/pods/logged-in/project/edit/prompts/route.ts rename to webapp/app/routes/logged-in/project/edit/prompts.ts index 6dad2f21d..7d0d5de4e 100644 --- a/webapp/app/pods/logged-in/project/edit/prompts/route.ts +++ b/webapp/app/routes/logged-in/project/edit/prompts.ts @@ -4,9 +4,9 @@ import Route from '@ember/routing/route'; import projectPromptConfigQuery from 'accent-webapp/queries/project-prompt-config'; import RouteParams from 'accent-webapp/services/route-params'; import ApolloSubscription, { - Subscription, + Subscription } from 'accent-webapp/services/apollo-subscription'; -import Transition from '@ember/routing/-private/transition'; +import Transition from '@ember/routing/transition'; export default class PomptsRoute extends Route { @service('apollo-subscription') @@ -18,21 +18,24 @@ export default class PomptsRoute extends Route { subscription: Subscription; model(_params: any, transition: Transition) { + if (this.subscription) + this.apolloSubscription.clearSubscription(this.subscription); + this.subscription = this.apolloSubscription.graphql( () => this.modelFor(this.routeName), projectPromptConfigQuery, { props: (data) => ({ project: data.viewer.project, - prompts: data.viewer.project.prompts, + prompts: data.viewer.project.prompts }), options: { fetchPolicy: 'cache-and-network', variables: { projectId: this.routeParams.fetch(transition, 'logged-in.project') - .projectId, - }, - }, + .projectId + } + } } ); diff --git a/webapp/app/pods/logged-in/project/edit/prompts/edit/route.ts b/webapp/app/routes/logged-in/project/edit/prompts/edit.ts similarity index 94% rename from webapp/app/pods/logged-in/project/edit/prompts/edit/route.ts rename to webapp/app/routes/logged-in/project/edit/prompts/edit.ts index bb3ea8023..06a3cde51 100644 --- a/webapp/app/pods/logged-in/project/edit/prompts/edit/route.ts +++ b/webapp/app/routes/logged-in/project/edit/prompts/edit.ts @@ -5,7 +5,7 @@ export default class PromptEditRoute extends Route { return { projectModel: this.modelFor('logged-in.project'), promptsModel: this.modelFor('logged-in.project.edit.prompts'), - promptId, + promptId }; } } diff --git a/webapp/app/pods/logged-in/project/edit/prompts/new/route.ts b/webapp/app/routes/logged-in/project/edit/prompts/new.ts similarity index 70% rename from webapp/app/pods/logged-in/project/edit/prompts/new/route.ts rename to webapp/app/routes/logged-in/project/edit/prompts/new.ts index cce03c27d..31cf4fa0f 100644 --- a/webapp/app/pods/logged-in/project/edit/prompts/new/route.ts +++ b/webapp/app/routes/logged-in/project/edit/prompts/new.ts @@ -3,7 +3,7 @@ import Route from '@ember/routing/route'; export default class PromptNewRoute extends Route { model() { return { - projectModel: this.modelFor('logged-in.project'), + projectModel: this.modelFor('logged-in.project') }; } } diff --git a/webapp/app/pods/logged-in/project/edit/service-integrations/route.ts b/webapp/app/routes/logged-in/project/edit/service-integrations.ts similarity index 82% rename from webapp/app/pods/logged-in/project/edit/service-integrations/route.ts rename to webapp/app/routes/logged-in/project/edit/service-integrations.ts index 2d464cc3f..172a517fc 100644 --- a/webapp/app/pods/logged-in/project/edit/service-integrations/route.ts +++ b/webapp/app/routes/logged-in/project/edit/service-integrations.ts @@ -5,9 +5,9 @@ import Route from '@ember/routing/route'; import projectServiceIntegrationsQuery from 'accent-webapp/queries/project-service-integrations'; import RouteParams from 'accent-webapp/services/route-params'; import ApolloSubscription, { - Subscription, + Subscription } from 'accent-webapp/services/apollo-subscription'; -import Transition from '@ember/routing/-private/transition'; +import Transition from '@ember/routing/transition'; export default class ServiceIntegrationsController extends Route { @service('apollo-subscription') @@ -19,20 +19,23 @@ export default class ServiceIntegrationsController extends Route { subscription: Subscription; model(_params: any, transition: Transition) { + if (this.subscription) + this.apolloSubscription.clearSubscription(this.subscription); + this.subscription = this.apolloSubscription.graphql( () => this.modelFor(this.routeName), projectServiceIntegrationsQuery, { props: (data) => ({ - project: data.viewer.project, + project: data.viewer.project }), options: { fetchPolicy: 'cache-and-network', variables: { projectId: this.routeParams.fetch(transition, 'logged-in.project') - .projectId, - }, - }, + .projectId + } + } } ); diff --git a/webapp/app/pods/logged-in/project/files/route.ts b/webapp/app/routes/logged-in/project/files.ts similarity index 81% rename from webapp/app/pods/logged-in/project/files/route.ts rename to webapp/app/routes/logged-in/project/files.ts index 80ae2705e..3d12d9317 100644 --- a/webapp/app/pods/logged-in/project/files/route.ts +++ b/webapp/app/routes/logged-in/project/files.ts @@ -5,9 +5,9 @@ import Route from '@ember/routing/route'; import projectDocumentsQuery from 'accent-webapp/queries/project-documents'; import RouteParams from 'accent-webapp/services/route-params'; import ApolloSubscription, { - Subscription, + Subscription } from 'accent-webapp/services/apollo-subscription'; -import Transition from '@ember/routing/-private/transition'; +import Transition from '@ember/routing/transition'; export default class FilesRoute extends Route { @service('apollo-subscription') @@ -18,11 +18,11 @@ export default class FilesRoute extends Route { queryParams = { page: { - refreshModel: true, + refreshModel: true }, excludeEmptyTranslations: { - refreshModel: true, - }, + refreshModel: true + } }; subscription: Subscription; @@ -30,10 +30,13 @@ export default class FilesRoute extends Route { model( { page, - excludeEmptyTranslations, + excludeEmptyTranslations }: {page: string; excludeEmptyTranslations: boolean}, transition: Transition ) { + if (this.subscription) + this.apolloSubscription.clearSubscription(this.subscription); + const pageNumber = page ? parseInt(page, 10) : null; this.subscription = this.apolloSubscription.graphql( @@ -43,7 +46,7 @@ export default class FilesRoute extends Route { props: (data) => ({ project: data.viewer.project, documents: data.viewer.project.documents, - versions: data.viewer.project.versions, + versions: data.viewer.project.versions }), options: { fetchPolicy: 'cache-and-network', @@ -51,9 +54,9 @@ export default class FilesRoute extends Route { projectId: this.routeParams.fetch(transition, 'logged-in.project') .projectId, excludeEmptyTranslations, - page: pageNumber, - }, - }, + page: pageNumber + } + } } ); diff --git a/webapp/app/pods/logged-in/project/files/add-translations/route.ts b/webapp/app/routes/logged-in/project/files/add-translations.ts similarity index 77% rename from webapp/app/pods/logged-in/project/files/add-translations/route.ts rename to webapp/app/routes/logged-in/project/files/add-translations.ts index 19a000612..161f0bb8e 100644 --- a/webapp/app/pods/logged-in/project/files/add-translations/route.ts +++ b/webapp/app/routes/logged-in/project/files/add-translations.ts @@ -1,12 +1,12 @@ import Route from '@ember/routing/route'; -import AddTranslationsController from 'accent-webapp/pods/logged-in/project/files/add-translations/controller'; +import AddTranslationsController from 'accent-webapp/controllers/logged-in/project/files/add-translations'; export default class AddTranslationsRoute extends Route { model({fileId}: {fileId: string}) { return { projectModel: this.modelFor('logged-in.project'), fileModel: this.modelFor('logged-in.project.files'), - fileId, + fileId }; } diff --git a/webapp/app/pods/logged-in/project/files/export-all/route.ts b/webapp/app/routes/logged-in/project/files/export-all.ts similarity index 66% rename from webapp/app/pods/logged-in/project/files/export-all/route.ts rename to webapp/app/routes/logged-in/project/files/export-all.ts index 9a74aa97e..8d3a81858 100644 --- a/webapp/app/pods/logged-in/project/files/export-all/route.ts +++ b/webapp/app/routes/logged-in/project/files/export-all.ts @@ -1,8 +1,8 @@ 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'; -import Transition from '@ember/routing/-private/transition'; +import ExportController from 'accent-webapp/controllers/logged-in/project/files/export'; +import Transition from '@ember/routing/transition'; export default class ExportRoute extends Route { @service('exporter') @@ -10,33 +10,33 @@ export default class ExportRoute extends Route { queryParams = { revisionFilter: { - refreshModel: true, + refreshModel: true }, documentFormatFilter: { - refreshModel: true, + refreshModel: true }, versionFilter: { - refreshModel: true, + refreshModel: true }, orderByFilter: { - refreshModel: true, + refreshModel: true }, isTextEmpty: { - refreshModel: true, + refreshModel: true }, isAddedLastSync: { - refreshModel: true, + refreshModel: true }, isConflicted: { - refreshModel: true, - }, + refreshModel: true + } }; model(_params: unknown, transition: Transition) { return { from: transition.from, projectModel: this.modelFor('logged-in.project'), - fileModel: this.modelFor('logged-in.project.files'), + fileModel: this.modelFor('logged-in.project.files') }; } diff --git a/webapp/app/pods/logged-in/project/files/export/route.ts b/webapp/app/routes/logged-in/project/files/export.ts similarity index 70% rename from webapp/app/pods/logged-in/project/files/export/route.ts rename to webapp/app/routes/logged-in/project/files/export.ts index 5c1a8ef80..f942d9a4b 100644 --- a/webapp/app/pods/logged-in/project/files/export/route.ts +++ b/webapp/app/routes/logged-in/project/files/export.ts @@ -1,8 +1,8 @@ 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'; -import Transition from '@ember/routing/-private/transition'; +import ExportController from 'accent-webapp/controllers/logged-in/project/files/export'; +import Transition from '@ember/routing/transition'; export default class ExportRoute extends Route { @service('exporter') @@ -10,26 +10,26 @@ export default class ExportRoute extends Route { queryParams = { revisionFilter: { - refreshModel: true, + refreshModel: true }, documentFormatFilter: { - refreshModel: true, + refreshModel: true }, versionFilter: { - refreshModel: true, + refreshModel: true }, orderByFilter: { - refreshModel: true, + refreshModel: true }, isTextEmpty: { - refreshModel: true, + refreshModel: true }, isAddedLastSync: { - refreshModel: true, + refreshModel: true }, isConflicted: { - refreshModel: true, - }, + refreshModel: true + } }; model({fileId}: {fileId: string}, transition: Transition) { @@ -37,7 +37,7 @@ export default class ExportRoute extends Route { from: transition.from, projectModel: this.modelFor('logged-in.project'), fileModel: this.modelFor('logged-in.project.files'), - fileId, + fileId }; } diff --git a/webapp/app/pods/logged-in/project/files/jipt/route.ts b/webapp/app/routes/logged-in/project/files/jipt.ts similarity index 82% rename from webapp/app/pods/logged-in/project/files/jipt/route.ts rename to webapp/app/routes/logged-in/project/files/jipt.ts index b36bdb0ac..70b9b405e 100644 --- a/webapp/app/pods/logged-in/project/files/jipt/route.ts +++ b/webapp/app/routes/logged-in/project/files/jipt.ts @@ -1,7 +1,7 @@ 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'; +import JIPTController from 'accent-webapp/controllers/logged-in/project/files/jipt'; export default class JIPTRoute extends Route { @service('exporter') @@ -9,15 +9,15 @@ export default class JIPTRoute extends Route { queryParams = { documentFormatFilter: { - refreshModel: true, - }, + refreshModel: true + } }; model({fileId}: {fileId: string}) { return { projectModel: this.modelFor('logged-in.project'), fileModel: this.modelFor('logged-in.project.files'), - fileId, + fileId }; } diff --git a/webapp/app/pods/logged-in/project/files/machine-translations/route.ts b/webapp/app/routes/logged-in/project/files/machine-translations.ts similarity index 77% rename from webapp/app/pods/logged-in/project/files/machine-translations/route.ts rename to webapp/app/routes/logged-in/project/files/machine-translations.ts index 53705aee5..3bff2e4e9 100644 --- a/webapp/app/pods/logged-in/project/files/machine-translations/route.ts +++ b/webapp/app/routes/logged-in/project/files/machine-translations.ts @@ -1,12 +1,12 @@ import Route from '@ember/routing/route'; -import MachineTranslationsController from 'accent-webapp/pods/logged-in/project/files/machine-translations/controller'; +import MachineTranslationsController from 'accent-webapp/controllers/logged-in/project/files/machine-translations'; export default class MachineTranslationsRoute extends Route { model({fileId}: {fileId: string}) { return { projectModel: this.modelFor('logged-in.project'), fileModel: this.modelFor('logged-in.project.files'), - fileId, + fileId }; } diff --git a/webapp/app/pods/logged-in/project/files/new-machine-translations/route.ts b/webapp/app/routes/logged-in/project/files/new-machine-translations.ts similarity index 69% rename from webapp/app/pods/logged-in/project/files/new-machine-translations/route.ts rename to webapp/app/routes/logged-in/project/files/new-machine-translations.ts index f1adb602e..2b162fcc5 100644 --- a/webapp/app/pods/logged-in/project/files/new-machine-translations/route.ts +++ b/webapp/app/routes/logged-in/project/files/new-machine-translations.ts @@ -1,5 +1,5 @@ import Route from '@ember/routing/route'; -import NewMachineTranslationsController from 'accent-webapp/pods/logged-in/project/files/new-machine-translations/controller'; +import NewMachineTranslationsController from 'accent-webapp/controllers/logged-in/project/files/new-machine-translations'; export default class NewMachineTranslationsRoute extends Route { resetController( diff --git a/webapp/app/pods/logged-in/project/files/new-sync/route.ts b/webapp/app/routes/logged-in/project/files/new-sync.ts similarity index 76% rename from webapp/app/pods/logged-in/project/files/new-sync/route.ts rename to webapp/app/routes/logged-in/project/files/new-sync.ts index 0d360b5ff..ae48d730d 100644 --- a/webapp/app/pods/logged-in/project/files/new-sync/route.ts +++ b/webapp/app/routes/logged-in/project/files/new-sync.ts @@ -1,5 +1,5 @@ import Route from '@ember/routing/route'; -import NewSyncController from 'accent-webapp/pods/logged-in/project/files/new-sync/controller'; +import NewSyncController from 'accent-webapp/controllers/logged-in/project/files/new-sync'; export default class NewSyncRoute extends Route { model() { diff --git a/webapp/app/pods/logged-in/project/files/sync/route.ts b/webapp/app/routes/logged-in/project/files/sync.ts similarity index 80% rename from webapp/app/pods/logged-in/project/files/sync/route.ts rename to webapp/app/routes/logged-in/project/files/sync.ts index 9d2774dbb..4b47f8f7b 100644 --- a/webapp/app/pods/logged-in/project/files/sync/route.ts +++ b/webapp/app/routes/logged-in/project/files/sync.ts @@ -1,12 +1,12 @@ import Route from '@ember/routing/route'; -import SyncController from 'accent-webapp/pods/logged-in/project/files/sync/controller'; +import SyncController from 'accent-webapp/controllers/logged-in/project/files/sync'; export default class SyncRoute extends Route { model({fileId}: {fileId: string}) { return { projectModel: this.modelFor('logged-in.project'), fileModel: this.modelFor('logged-in.project.files'), - fileId, + fileId }; } diff --git a/webapp/app/pods/logged-in/project/index/route.ts b/webapp/app/routes/logged-in/project/index.ts similarity index 84% rename from webapp/app/pods/logged-in/project/index/route.ts rename to webapp/app/routes/logged-in/project/index.ts index fe94ec948..0e3b95c23 100644 --- a/webapp/app/pods/logged-in/project/index/route.ts +++ b/webapp/app/routes/logged-in/project/index.ts @@ -4,9 +4,9 @@ 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, + Subscription } from 'accent-webapp/services/apollo-subscription'; -import Transition from '@ember/routing/-private/transition'; +import Transition from '@ember/routing/transition'; export default class ProjectIndexRoute extends Route { @service('apollo-subscription') @@ -18,6 +18,9 @@ export default class ProjectIndexRoute extends Route { subscription: Subscription; model(_params: object, transition: Transition) { + if (this.subscription) + this.apolloSubscription.clearSubscription(this.subscription); + const props = (data: any) => ({project: data.viewer.project}); this.subscription = this.apolloSubscription.graphql( @@ -29,9 +32,9 @@ export default class ProjectIndexRoute extends Route { fetchPolicy: 'cache-and-network', variables: { projectId: this.routeParams.fetch(transition, 'logged-in.project') - .projectId, - }, - }, + .projectId + } + } } ); diff --git a/webapp/app/pods/logged-in/project/manage-languages/route.ts b/webapp/app/routes/logged-in/project/manage-languages.ts similarity index 79% rename from webapp/app/pods/logged-in/project/manage-languages/route.ts rename to webapp/app/routes/logged-in/project/manage-languages.ts index 4212dba94..e01c7b752 100644 --- a/webapp/app/pods/logged-in/project/manage-languages/route.ts +++ b/webapp/app/routes/logged-in/project/manage-languages.ts @@ -5,10 +5,10 @@ import Route from '@ember/routing/route'; import projectNewLanguageQuery from 'accent-webapp/queries/project-new-language'; import RouteParams from 'accent-webapp/services/route-params'; import ApolloSubscription, { - Subscription, + Subscription } from 'accent-webapp/services/apollo-subscription'; -import Transition from '@ember/routing/-private/transition'; -import ManageLanguagesController from 'accent-webapp/pods/logged-in/project/manage-languages/controller'; +import Transition from '@ember/routing/transition'; +import ManageLanguagesController from 'accent-webapp/controllers/logged-in/project/manage-languages'; export default class ManageLanguagesRoute extends Route { @service('apollo-subscription') @@ -20,21 +20,24 @@ export default class ManageLanguagesRoute extends Route { subscription: Subscription; model(_params: any, transition: Transition) { + if (this.subscription) + this.apolloSubscription.clearSubscription(this.subscription); + this.subscription = this.apolloSubscription.graphql( () => this.modelFor(this.routeName), projectNewLanguageQuery, { props: (data) => ({ project: data.viewer.project, - languages: data.languages.entries, + languages: data.languages.entries }), options: { fetchPolicy: 'cache-and-network', variables: { projectId: this.routeParams.fetch(transition, 'logged-in.project') - .projectId, - }, - }, + .projectId + } + } } ); diff --git a/webapp/app/pods/logged-in/project/manage-languages/edit/route.ts b/webapp/app/routes/logged-in/project/manage-languages/edit.ts similarity index 93% rename from webapp/app/pods/logged-in/project/manage-languages/edit/route.ts rename to webapp/app/routes/logged-in/project/manage-languages/edit.ts index 71f27fa18..0b313027c 100644 --- a/webapp/app/pods/logged-in/project/manage-languages/edit/route.ts +++ b/webapp/app/routes/logged-in/project/manage-languages/edit.ts @@ -4,7 +4,7 @@ export default class ManageLanguagesEditController extends Route { model({revisionId}: {revisionId: string}) { return { revisionsModel: this.modelFor('logged-in.project.manage-languages'), - revisionId, + revisionId }; } } diff --git a/webapp/app/pods/logged-in/project/revision/route.ts b/webapp/app/routes/logged-in/project/revision.ts similarity index 100% rename from webapp/app/pods/logged-in/project/revision/route.ts rename to webapp/app/routes/logged-in/project/revision.ts diff --git a/webapp/app/pods/logged-in/project/revision/lint-translations/route.ts b/webapp/app/routes/logged-in/project/revision/lint-translations.ts similarity index 84% rename from webapp/app/pods/logged-in/project/revision/lint-translations/route.ts rename to webapp/app/routes/logged-in/project/revision/lint-translations.ts index 8f44705f6..d70291027 100644 --- a/webapp/app/pods/logged-in/project/revision/lint-translations/route.ts +++ b/webapp/app/routes/logged-in/project/revision/lint-translations.ts @@ -5,11 +5,11 @@ import GlobalState from 'accent-webapp/services/global-state'; import lintQuery from 'accent-webapp/queries/lint-translations'; import ApolloSubscription, { - Subscription, + Subscription } from 'accent-webapp/services/apollo-subscription'; import RouteParams from 'accent-webapp/services/route-params'; -import Transition from '@ember/routing/-private/transition'; -import LintTranslationsController from 'accent-webapp/pods/logged-in/project/revision/lint-translations/controller'; +import Transition from '@ember/routing/transition'; +import LintTranslationsController from 'accent-webapp/controllers/logged-in/project/revision/lint-translations'; import RouterService from '@ember/routing/router-service'; export default class LintRoute extends Route { @@ -29,20 +29,23 @@ export default class LintRoute extends Route { queryParams = { documentFilter: { - refreshModel: true, + refreshModel: true }, versionFilter: { - refreshModel: true, + refreshModel: true }, ruleFilter: { - refreshModel: true, + refreshModel: true }, query: { - refreshModel: true, - }, + refreshModel: true + } }; model(params: any, transition: Transition) { + if (this.subscription) + this.apolloSubscription.clearSubscription(this.subscription); + this.subscription = this.apolloSubscription.graphql( () => this.modelFor(this.routeName), lintQuery, @@ -51,7 +54,7 @@ export default class LintRoute extends Route { project: data.viewer.project, documents: data.viewer.project.documents, versions: data.viewer.project.versions, - lintTranslations: data.viewer.project.lintTranslations, + lintTranslations: data.viewer.project.lintTranslations }), options: { fetchPolicy: 'cache-and-network', @@ -65,9 +68,9 @@ export default class LintRoute extends Route { ruleIds: params.ruleFilter, query: params.query, projectId: this.routeParams.fetch(transition, 'logged-in.project') - .projectId, - }, - }, + .projectId + } + } } ); @@ -87,7 +90,7 @@ export default class LintRoute extends Route { { queryParams: this.fetchQueryParams( this.controller as LintTranslationsController - ), + ) } ); } @@ -96,7 +99,7 @@ export default class LintRoute extends Route { const query = controller.query; return { - query, + query }; } } diff --git a/webapp/app/pods/logged-in/project/revision/translations/route.ts b/webapp/app/routes/logged-in/project/revision/translations.ts similarity index 84% rename from webapp/app/pods/logged-in/project/revision/translations/route.ts rename to webapp/app/routes/logged-in/project/revision/translations.ts index efc385578..64219f916 100644 --- a/webapp/app/pods/logged-in/project/revision/translations/route.ts +++ b/webapp/app/routes/logged-in/project/revision/translations.ts @@ -4,12 +4,12 @@ import Route from '@ember/routing/route'; import translationsQuery from 'accent-webapp/queries/translations'; import ApolloSubscription, { - Subscription, + 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 TranslationsController from 'accent-webapp/controllers/logged-in/project/revision/translations'; import RouterService from '@ember/routing/router-service'; -import Transition from '@ember/routing/-private/transition'; +import Transition from '@ember/routing/transition'; export default class TranslationsRoute extends Route { @service('apollo-subscription') @@ -23,40 +23,43 @@ export default class TranslationsRoute extends Route { queryParams = { query: { - refreshModel: true, + refreshModel: true }, page: { - refreshModel: true, + refreshModel: true }, document: { - refreshModel: true, + refreshModel: true }, version: { - refreshModel: true, + refreshModel: true }, isTextEmpty: { - refreshModel: true, + refreshModel: true }, isTextNotEmpty: { - refreshModel: true, + refreshModel: true }, isAddedLastSync: { - refreshModel: true, + refreshModel: true }, isCommentedOn: { - refreshModel: true, + refreshModel: true }, isConflicted: { - refreshModel: true, + refreshModel: true }, isTranslated: { - refreshModel: true, - }, + refreshModel: true + } }; subscription: Subscription; model(params: any, transition: Transition) { + if (this.subscription) + this.apolloSubscription.clearSubscription(this.subscription); + params.isTextEmpty = params.isTextEmpty === 'true' ? true : null; params.isTextNotEmpty = params.isTextNotEmpty === 'true' ? true : null; params.isAddedLastSync = params.isAddedLastSync === 'true' ? true : null; @@ -74,7 +77,7 @@ export default class TranslationsRoute extends Route { prompts: data.viewer.project.prompts, documents: data.viewer.project.documents.entries, versions: data.viewer.project.versions.entries, - translations: data.viewer.project.revision.translations, + translations: data.viewer.project.revision.translations }), options: { fetchPolicy: 'cache-and-network', @@ -85,9 +88,9 @@ export default class TranslationsRoute extends Route { transition, 'logged-in.project.revision' ).revisionId, - ...params, - }, - }, + ...params + } + } } ); @@ -121,7 +124,7 @@ export default class TranslationsRoute extends Route { { queryParams: this.fetchQueryParams( this.controller as TranslationsController - ), + ) } ); } @@ -130,7 +133,7 @@ export default class TranslationsRoute extends Route { const query = controller.query; return { - query, + query }; } } diff --git a/webapp/app/pods/logged-in/project/translation/route.ts b/webapp/app/routes/logged-in/project/translation.ts similarity index 83% rename from webapp/app/pods/logged-in/project/translation/route.ts rename to webapp/app/routes/logged-in/project/translation.ts index 4dde10485..636d9c0ed 100644 --- a/webapp/app/pods/logged-in/project/translation/route.ts +++ b/webapp/app/routes/logged-in/project/translation.ts @@ -3,10 +3,10 @@ import Route from '@ember/routing/route'; import translationQuery from 'accent-webapp/queries/translation'; import ApolloSubscription, { - Subscription, + Subscription } from 'accent-webapp/services/apollo-subscription'; import RouteParams from 'accent-webapp/services/route-params'; -import Transition from '@ember/routing/-private/transition'; +import Transition from '@ember/routing/transition'; export default class TranslationsRoute extends Route { @service('apollo-subscription') @@ -18,6 +18,9 @@ export default class TranslationsRoute extends Route { subscription: Subscription; model({translationId}: {translationId: string}, transition: Transition) { + if (this.subscription) + this.apolloSubscription.clearSubscription(this.subscription); + this.subscription = this.apolloSubscription.graphql( () => this.modelFor(this.routeName), translationQuery, @@ -28,16 +31,16 @@ export default class TranslationsRoute extends Route { translation: data.viewer.project.translation, prompts: data.viewer.project.prompts, relatedTranslations: - data.viewer.project.translation.relatedTranslations, + data.viewer.project.translation.relatedTranslations }), options: { fetchPolicy: 'cache-and-network', variables: { projectId: this.routeParams.fetch(transition, 'logged-in.project') .projectId, - translationId, - }, - }, + translationId + } + } } ); diff --git a/webapp/app/pods/logged-in/project/translation/activities/route.ts b/webapp/app/routes/logged-in/project/translation/activities.ts similarity index 83% rename from webapp/app/pods/logged-in/project/translation/activities/route.ts rename to webapp/app/routes/logged-in/project/translation/activities.ts index f8da240a1..479d50b53 100644 --- a/webapp/app/pods/logged-in/project/translation/activities/route.ts +++ b/webapp/app/routes/logged-in/project/translation/activities.ts @@ -4,11 +4,11 @@ import Route from '@ember/routing/route'; import translationActivitiesQuery from 'accent-webapp/queries/translation-activities'; import ApolloSubscription, { - Subscription, + Subscription } from 'accent-webapp/services/apollo-subscription'; import RouteParams from 'accent-webapp/services/route-params'; -import Transition from '@ember/routing/-private/transition'; -import ActivitiesController from 'accent-webapp/pods/logged-in/project/activities/controller'; +import Transition from '@ember/routing/transition'; +import ActivitiesController from 'accent-webapp/controllers/logged-in/project/activities'; export default class ActivitiesRoute extends Route { @service('apollo-subscription') @@ -19,20 +19,23 @@ export default class ActivitiesRoute extends Route { queryParams = { page: { - refreshModel: true, - }, + refreshModel: true + } }; subscription: Subscription; model({page}: {page: string}, transition: Transition) { + if (this.subscription) + this.apolloSubscription.clearSubscription(this.subscription); + this.subscription = this.apolloSubscription.graphql( () => this.modelFor(this.routeName), translationActivitiesQuery, { props: (data) => ({ project: data.viewer.project, - activities: data.viewer.project.translation.activities, + activities: data.viewer.project.translation.activities }), options: { fetchPolicy: 'cache-and-network', @@ -43,9 +46,9 @@ export default class ActivitiesRoute extends Route { transition, 'logged-in.project.translation' ).translationId, - page, - }, - }, + page + } + } } ); diff --git a/webapp/app/pods/logged-in/project/translation/comments/route.ts b/webapp/app/routes/logged-in/project/translation/comments.ts similarity index 84% rename from webapp/app/pods/logged-in/project/translation/comments/route.ts rename to webapp/app/routes/logged-in/project/translation/comments.ts index 62330fc49..acac08777 100644 --- a/webapp/app/pods/logged-in/project/translation/comments/route.ts +++ b/webapp/app/routes/logged-in/project/translation/comments.ts @@ -4,11 +4,11 @@ import Route from '@ember/routing/route'; import translationCommentsQuery from 'accent-webapp/queries/translation-comments'; import ApolloSubscription, { - Subscription, + Subscription } from 'accent-webapp/services/apollo-subscription'; import RouteParams from 'accent-webapp/services/route-params'; -import Transition from '@ember/routing/-private/transition'; -import CommentsController from 'accent-webapp/pods/logged-in/project/comments/controller'; +import Transition from '@ember/routing/transition'; +import CommentsController from 'accent-webapp/controllers/logged-in/project/comments'; export default class CommentsRoute extends Route { @service('apollo-subscription') @@ -19,13 +19,16 @@ export default class CommentsRoute extends Route { queryParams = { page: { - refreshModel: true, - }, + refreshModel: true + } }; subscription: Subscription; model({page}: {page: string}, transition: Transition) { + if (this.subscription) + this.apolloSubscription.clearSubscription(this.subscription); + const pageNumber = page ? parseInt(page, 10) : null; this.subscription = this.apolloSubscription.graphql( @@ -37,7 +40,7 @@ export default class CommentsRoute extends Route { comments: data.viewer.project.translation.comments, collaborators: data.viewer.project.collaborators, commentsSubscriptions: - data.viewer.project.translation.commentsSubscriptions, + data.viewer.project.translation.commentsSubscriptions }), options: { fetchPolicy: 'cache-and-network', @@ -48,9 +51,9 @@ export default class CommentsRoute extends Route { transition, 'logged-in.project.translation' ).translationId, - page: pageNumber, - }, - }, + page: pageNumber + } + } } ); diff --git a/webapp/app/pods/logged-in/project/translation/editions/route.ts b/webapp/app/routes/logged-in/project/translation/editions.ts similarity index 81% rename from webapp/app/pods/logged-in/project/translation/editions/route.ts rename to webapp/app/routes/logged-in/project/translation/editions.ts index 38a4489ae..50d3ec402 100644 --- a/webapp/app/pods/logged-in/project/translation/editions/route.ts +++ b/webapp/app/routes/logged-in/project/translation/editions.ts @@ -3,12 +3,12 @@ import Route from '@ember/routing/route'; import translationEditionsQuery from 'accent-webapp/queries/translation-editions'; import ApolloSubscription, { - Subscription, + 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 TranslationsController from 'accent-webapp/controllers/logged-in/project/revision/translations'; import RouterService from '@ember/routing/router-service'; -import Transition from '@ember/routing/-private/transition'; +import Transition from '@ember/routing/transition'; export default class TranslationEditionsRoute extends Route { @service('apollo-subscription') @@ -23,15 +23,18 @@ export default class TranslationEditionsRoute extends Route { subscription: Subscription; model(_params: any, transition: Transition) { + if (this.subscription) + this.apolloSubscription.clearSubscription(this.subscription); + this.subscription = this.apolloSubscription.graphql( () => this.modelFor(this.routeName), translationEditionsQuery, { props: (data) => ({ - revisionModel: this.modelFor('logged-in.project.revision'), + translationModel: this.modelFor('logged-in.project.translation'), project: data.viewer.project, prompts: data.viewer.project.prompts, - translations: data.viewer.project.translation.editions, + translations: data.viewer.project.translation.editions }), options: { fetchPolicy: 'cache-and-network', @@ -41,9 +44,9 @@ export default class TranslationEditionsRoute extends Route { translationId: this.routeParams.fetch( transition, 'logged-in.project.translation' - ).translationId, - }, - }, + ).translationId + } + } } ); diff --git a/webapp/app/pods/logged-in/project/translation/index/route.ts b/webapp/app/routes/logged-in/project/translation/index.ts similarity index 100% rename from webapp/app/pods/logged-in/project/translation/index/route.ts rename to webapp/app/routes/logged-in/project/translation/index.ts diff --git a/webapp/app/pods/logged-in/project/versions/route.ts b/webapp/app/routes/logged-in/project/versions.ts similarity index 82% rename from webapp/app/pods/logged-in/project/versions/route.ts rename to webapp/app/routes/logged-in/project/versions.ts index dac0c5b3b..0487e8854 100644 --- a/webapp/app/pods/logged-in/project/versions/route.ts +++ b/webapp/app/routes/logged-in/project/versions.ts @@ -4,10 +4,10 @@ import Route from '@ember/routing/route'; import projectVersionsQuery from 'accent-webapp/queries/project-versions'; import ApolloSubscription, { - Subscription, + Subscription } from 'accent-webapp/services/apollo-subscription'; import RouteParams from 'accent-webapp/services/route-params'; -import Transition from '@ember/routing/-private/transition'; +import Transition from '@ember/routing/transition'; export default class VersionsRoute extends Route { @service('apollo-subscription') @@ -18,13 +18,16 @@ export default class VersionsRoute extends Route { queryParams = { page: { - refreshModel: true, - }, + refreshModel: true + } }; subscription: Subscription; model({page}: {page: string}, transition: Transition) { + if (this.subscription) + this.apolloSubscription.clearSubscription(this.subscription); + const pageNumber = page ? parseInt(page, 10) : null; this.subscription = this.apolloSubscription.graphql( @@ -34,16 +37,16 @@ export default class VersionsRoute extends Route { props: (data) => ({ project: data.viewer.project, versions: data.viewer.project.versions, - documents: data.viewer.project.documents, + documents: data.viewer.project.documents }), options: { fetchPolicy: 'cache-and-network', variables: { projectId: this.routeParams.fetch(transition, 'logged-in.project') .projectId, - page: pageNumber, - }, - }, + page: pageNumber + } + } } ); diff --git a/webapp/app/pods/logged-in/project/versions/edit/route.ts b/webapp/app/routes/logged-in/project/versions/edit.ts similarity index 94% rename from webapp/app/pods/logged-in/project/versions/edit/route.ts rename to webapp/app/routes/logged-in/project/versions/edit.ts index f03a94a26..9a88e1f5a 100644 --- a/webapp/app/pods/logged-in/project/versions/edit/route.ts +++ b/webapp/app/routes/logged-in/project/versions/edit.ts @@ -5,7 +5,7 @@ export default class EditRoute extends Route { return { projectModel: this.modelFor('logged-in.project'), versionModel: this.modelFor('logged-in.project.versions'), - versionId, + versionId }; } } diff --git a/webapp/app/pods/logged-in/project/versions/export/route.ts b/webapp/app/routes/logged-in/project/versions/export.ts similarity index 76% rename from webapp/app/pods/logged-in/project/versions/export/route.ts rename to webapp/app/routes/logged-in/project/versions/export.ts index c18941338..829fdb6d8 100644 --- a/webapp/app/pods/logged-in/project/versions/export/route.ts +++ b/webapp/app/routes/logged-in/project/versions/export.ts @@ -1,7 +1,7 @@ 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/versions/export/controller'; +import ExportController from 'accent-webapp/controllers/logged-in/project/versions/export'; export default class ExportRoute extends Route { @service('exporter') @@ -9,24 +9,24 @@ export default class ExportRoute extends Route { queryParams = { revisionFilter: { - refreshModel: true, + refreshModel: true }, documentFilter: { - refreshModel: true, + refreshModel: true }, documentFormatFilter: { - refreshModel: true, + refreshModel: true }, orderByFilter: { - refreshModel: true, - }, + refreshModel: true + } }; model({versionId}: {versionId: string}) { return { projectModel: this.modelFor('logged-in.project'), versionModel: this.modelFor('logged-in.project.versions'), - versionId, + versionId }; } diff --git a/webapp/app/pods/logged-in/project/versions/new/route.ts b/webapp/app/routes/logged-in/project/versions/new.ts similarity index 76% rename from webapp/app/pods/logged-in/project/versions/new/route.ts rename to webapp/app/routes/logged-in/project/versions/new.ts index 526d53b5b..7acf3f020 100644 --- a/webapp/app/pods/logged-in/project/versions/new/route.ts +++ b/webapp/app/routes/logged-in/project/versions/new.ts @@ -1,5 +1,5 @@ import Route from '@ember/routing/route'; -import NewController from 'accent-webapp/pods/logged-in/project/versions/new/controller'; +import NewController from 'accent-webapp/controllers/logged-in/project/versions/new'; export default class NewRoute extends Route { model() { diff --git a/webapp/app/pods/logged-in/projects/route.ts b/webapp/app/routes/logged-in/projects.ts similarity index 85% rename from webapp/app/pods/logged-in/projects/route.ts rename to webapp/app/routes/logged-in/projects.ts index a8ddf3cb7..65141c0c3 100644 --- a/webapp/app/pods/logged-in/projects/route.ts +++ b/webapp/app/routes/logged-in/projects.ts @@ -4,10 +4,11 @@ import {inject as service} from '@ember/service'; import projectsQuery from 'accent-webapp/queries/projects'; import Session from 'accent-webapp/services/session'; import ApolloSubscription, { - Subscription, + Subscription } from 'accent-webapp/services/apollo-subscription'; -import ProjectsController from 'accent-webapp/pods/logged-in/projects/controller'; +import ProjectsController from 'accent-webapp/controllers/logged-in/projects'; import RecentProjects from 'accent-webapp/services/recent-projects'; +import RouterService from '@ember/routing/router-service'; const transformData = (data: any, recentProjectIds: string[]) => { const permissions = data.viewer.permissions.reduce( @@ -30,7 +31,7 @@ const transformData = (data: any, recentProjectIds: string[]) => { projects: data.viewer.projects, languages: data.languages.entries, recentProjects, - permissions, + permissions }; }; @@ -44,13 +45,16 @@ export default class ProjectsRoute extends Route { @service('apollo-subscription') apolloSubscription: ApolloSubscription; + @service('router') + router: RouterService; + queryParams = { query: { - refreshModel: true, + refreshModel: true }, page: { - refreshModel: true, - }, + refreshModel: true + } }; subscription: Subscription; @@ -80,9 +84,9 @@ export default class ProjectsRoute extends Route { variables: { page, query, - nodeIds: recentProjectIds, - }, - }, + nodeIds: recentProjectIds + } + } } ); @@ -91,7 +95,7 @@ export default class ProjectsRoute extends Route { redirect() { if (!this.session.isAuthenticated) { - this.transitionTo('login'); + this.router.transitionTo('login'); } } diff --git a/webapp/app/pods/logged-in/projects/new/route.ts b/webapp/app/routes/logged-in/projects/new.ts similarity index 79% rename from webapp/app/pods/logged-in/projects/new/route.ts rename to webapp/app/routes/logged-in/projects/new.ts index e8274bd6b..a8fe80172 100644 --- a/webapp/app/pods/logged-in/projects/new/route.ts +++ b/webapp/app/routes/logged-in/projects/new.ts @@ -1,5 +1,5 @@ import Route from '@ember/routing/route'; -import Controller from './controller'; +import Controller from 'accent-webapp/controllers/logged-in/projects/new'; export default class ProjectsNewRoute extends Route { model() { diff --git a/webapp/app/pods/login/route.ts b/webapp/app/routes/login.ts similarity index 76% rename from webapp/app/pods/login/route.ts rename to webapp/app/routes/login.ts index c61d2ccd5..ac4a9ad00 100644 --- a/webapp/app/pods/login/route.ts +++ b/webapp/app/routes/login.ts @@ -3,20 +3,27 @@ import Route from '@ember/routing/route'; import authenticationProvidersQuery from 'accent-webapp/queries/authentication-providers'; import ApolloSubscription, { - Subscription, + Subscription } from 'accent-webapp/services/apollo-subscription'; import Session from 'accent-webapp/services/session'; +import RouterService from '@ember/routing/router-service'; export default class LoginRoute extends Route { @service('session') session: Session; + @service('router') + router: RouterService; + @service('apollo-subscription') apolloSubscription: ApolloSubscription; subscription: Subscription; model() { + if (this.subscription) + this.apolloSubscription.clearSubscription(this.subscription); + this.subscription = this.apolloSubscription.graphql( () => this.modelFor(this.routeName), authenticationProvidersQuery, @@ -32,7 +39,7 @@ export default class LoginRoute extends Route { redirect() { if (this.session.isAuthenticated) { - this.transitionTo('logged-in.projects'); + this.router.transitionTo('logged-in.projects'); } } } diff --git a/webapp/app/services/apollo-mutate.ts b/webapp/app/services/apollo-mutate.ts index 966c43d2c..3912cb9de 100644 --- a/webapp/app/services/apollo-mutate.ts +++ b/webapp/app/services/apollo-mutate.ts @@ -15,9 +15,7 @@ export default class ApolloMutate extends Service { const operationName = Object.keys(data)[0]; if (!data[operationName]?.errors?.length) { - data[operationName].errors = null; - - return data[operationName]; + return {...data[operationName], errors: null}; } return data[operationName]; diff --git a/webapp/app/services/apollo-subscription.ts b/webapp/app/services/apollo-subscription.ts index 1caab938e..20b2d64e5 100644 --- a/webapp/app/services/apollo-subscription.ts +++ b/webapp/app/services/apollo-subscription.ts @@ -34,7 +34,7 @@ export class Subscription { currentResult() { const queryObservable = this.queryObservable; - const result = queryObservable.currentResult(); + const result = queryObservable.getCurrentResult(); const mappedResult = this.mapResult(result, this.props); return mappedResult; @@ -51,7 +51,7 @@ export class Subscription { return this.apollo.client.watchQuery({ query, - ...options, + ...options }); } @@ -79,7 +79,7 @@ export class Subscription { refetch: this.queryObservable.refetch, fetchMore: this.queryObservable.fetchMore, startPolling: this.queryObservable.startPolling, - stopPolling: this.queryObservable.stopPolling, + stopPolling: this.queryObservable.stopPolling }; } else { return result; diff --git a/webapp/app/services/apollo.ts b/webapp/app/services/apollo.ts index 3b9cfb8c5..f143c9b67 100644 --- a/webapp/app/services/apollo.ts +++ b/webapp/app/services/apollo.ts @@ -1,42 +1,21 @@ import Service, {inject as service} from '@ember/service'; import RouterService from '@ember/routing/router-service'; -import {ApolloClient} from 'apollo-client'; -import {BatchHttpLink} from 'apollo-link-batch-http'; -import { - IntrospectionFragmentMatcher, - InMemoryCache, - from, - ApolloLink, -} from 'apollo-boost'; + +import {InMemoryCache} from '@apollo/client/cache'; +import {ApolloClient} from '@apollo/client/core'; +import {ApolloLink} from '@apollo/client/link/core'; +import {BatchHttpLink} from '@apollo/client/link/batch-http'; import Session from 'accent-webapp/services/session'; const dataIdFromObject = (result: {id?: string; __typename: string}) => { if (result.id && result.__typename) return `${result.__typename}${result.id}`; - return null; + return false; }; -const fragmentMatcher = new IntrospectionFragmentMatcher({ - introspectionQueryResultData: { - __schema: { - types: [ - { - kind: 'INTERFACE', - name: 'ProjectIntegration', - possibleTypes: [ - {name: 'ProjectIntegrationAzureStorageContainer'}, - {name: 'ProjectIntegrationDiscord'}, - {name: 'ProjectIntegrationSlack'}, - ], - }, - ], - }, - }, -}); - const uri = '/graphql'; -const cache = new InMemoryCache({dataIdFromObject, fragmentMatcher}); +const cache = new InMemoryCache({dataIdFromObject}); const link = new BatchHttpLink({uri, batchInterval: 1, batchMax: 1}); const absintheBatchLink = new ApolloLink((operation, forward) => { @@ -51,8 +30,8 @@ const authLink = (getSession: any) => { operation.setContext(({headers = {}}: any) => ({ headers: { ...headers, - authorization: `Bearer ${token}`, - }, + authorization: `Bearer ${token}` + } })); } @@ -68,8 +47,12 @@ export default class Apollo extends Service { session: Session; client = new ApolloClient({ - link: from([authLink(() => this.session), absintheBatchLink, link]), - cache, + link: ApolloLink.from([ + authLink(() => this.session), + absintheBatchLink, + link + ]), + cache }); } diff --git a/webapp/app/services/authenticated-request.ts b/webapp/app/services/authenticated-request.ts index 90c97d0d6..9a964a8af 100644 --- a/webapp/app/services/authenticated-request.ts +++ b/webapp/app/services/authenticated-request.ts @@ -38,7 +38,7 @@ export default class AuthenticatedRequest extends Service { fetchOptions.method = 'POST'; fetchOptions.headers = { - Authorization: `Bearer ${this.session.credentials.token}`, + Authorization: `Bearer ${this.session.credentials.token}` }; const response = await fetch(url, fetchOptions); @@ -70,7 +70,7 @@ export default class AuthenticatedRequest extends Service { const options: RequestInit = {}; options.headers = { - Authorization: `Bearer ${this.session.credentials.token}`, + Authorization: `Bearer ${this.session.credentials.token}` }; const response = await fetch(url, options); @@ -89,7 +89,7 @@ export default class AuthenticatedRequest extends Service { fetchOptions.method = 'POST'; fetchOptions.headers = { - Authorization: `Bearer ${this.session.credentials.token}`, + Authorization: `Bearer ${this.session.credentials.token}` }; fetchOptions.body = this.setupFormFile(options); diff --git a/webapp/app/services/exporter.ts b/webapp/app/services/exporter.ts index 0b8c27d20..1705cbb4c 100644 --- a/webapp/app/services/exporter.ts +++ b/webapp/app/services/exporter.ts @@ -57,7 +57,7 @@ export default class Exporter extends Service { document_format: (documentFormat || document.format).toLowerCase(), 'filters[is_text_empty]': options.filters?.isTextEmptyFilter, 'filters[is_added_last_sync]': options.filters?.isAddedLastSyncFilter, - 'filters[is_conflicted]': options.filters?.isConflictedFilter, + 'filters[is_conflicted]': options.filters?.isConflictedFilter })}` ); /* eslint-enable camelcase */ @@ -79,7 +79,7 @@ export default class Exporter extends Service { document_format: documentFormat.toLowerCase(), 'filters[is_text_empty]': options.filters?.isTextEmptyFilter, 'filters[is_added_last_sync]': options.filters?.isAddedLastSyncFilter, - 'filters[is_conflicted]': options.filters?.isConflictedFilter, + 'filters[is_conflicted]': options.filters?.isConflictedFilter })}` ); /* eslint-enable camelcase */ @@ -96,7 +96,7 @@ export default class Exporter extends Service { project_id: project.id, version, document_path: document.path, - document_format: documentFormat, + document_format: documentFormat })}` ); /* eslint-enable camelcase */ diff --git a/webapp/app/services/jipt.ts b/webapp/app/services/jipt.ts index 4a62473be..743e5438b 100644 --- a/webapp/app/services/jipt.ts +++ b/webapp/app/services/jipt.ts @@ -13,7 +13,7 @@ export default class JIPT extends Service { text: translation.correctedText, id: translation.id, key, - isConflicted: translation.isConflicted, + isConflicted: translation.isConflicted }; return memo; }, @@ -31,7 +31,7 @@ export default class JIPT extends Service { changeText(translationId: string, text: string) { const payload = { translationId, - text, + text }; window.parent.postMessage({jipt: true, action: 'changeText', payload}, '*'); @@ -40,7 +40,7 @@ export default class JIPT extends Service { updateTranslation(translationId: string, translation: any) { const payload = { translationId, - ...translation, + ...translation }; window.parent.postMessage( diff --git a/webapp/app/services/language-searcher.ts b/webapp/app/services/language-searcher.ts index 9846f1bb1..caa036d23 100644 --- a/webapp/app/services/language-searcher.ts +++ b/webapp/app/services/language-searcher.ts @@ -11,15 +11,15 @@ export default class LanguageSearcher extends Service { async search({term}: {term: string}) { const searchQuery = { query: searchLanguagesQuery, - variables: {query: term}, + variables: {query: term} }; if (term.length < MINIMUM_TERM_LENGTH) return []; const { data: { - languages: {entries}, - }, + languages: {entries} + } } = await this.apollo.client.query(searchQuery); return entries; diff --git a/webapp/app/services/machine-translations.ts b/webapp/app/services/machine-translations.ts index 61b5008fe..ea076d55e 100644 --- a/webapp/app/services/machine-translations.ts +++ b/webapp/app/services/machine-translations.ts @@ -28,7 +28,7 @@ export default class MachineTranslations extends Service { documentId, toLanguage, fromLanguage, - documentFormat, + documentFormat }: TranslateDocumentOptions) { const url = fmt( config.API.MACHINE_TRANSLATIONS_TRANSLATE_DOCUMENT_PROJECT_PATH, @@ -47,7 +47,7 @@ export default class MachineTranslations extends Service { file, toLanguage, fromLanguage, - documentFormat, + documentFormat }: TranslateFileOptions) { const url = fmt( config.API.MACHINE_TRANSLATIONS_TRANSLATE_FILE_PROJECT_PATH, @@ -58,7 +58,7 @@ export default class MachineTranslations extends Service { ); return this.authenticatedRequest.machineTranslationsTranslateFile(url, { - file, + file }); } } diff --git a/webapp/app/services/merger.ts b/webapp/app/services/merger.ts index 3755a1794..5299ce436 100644 --- a/webapp/app/services/merger.ts +++ b/webapp/app/services/merger.ts @@ -24,7 +24,7 @@ export default class Merger extends Service { documentPath, documentFormat, mergeType, - mergeOptions, + mergeOptions }: MergeOptions) { const language = revision.language; const url = fmt( @@ -40,7 +40,7 @@ export default class Merger extends Service { return this.authenticatedRequest.commit(url, { file, documentPath, - documentFormat, + documentFormat }); } } diff --git a/webapp/app/services/peeker.ts b/webapp/app/services/peeker.ts index a97862805..308504e65 100644 --- a/webapp/app/services/peeker.ts +++ b/webapp/app/services/peeker.ts @@ -46,7 +46,7 @@ export default class Peeker extends Service { file, documentPath, documentFormat, - syncType, + syncType }: SyncOptions) { const url = fmt( config.API.SYNC_PEEK_PROJECT_PATH, @@ -58,12 +58,12 @@ export default class Peeker extends Service { documentFormat = documentFormat.toLowerCase(); const { - data: {operations, stats}, + data: {operations, stats} } = await this.authenticatedRequest.peek(url, { file, documentPath, version, - documentFormat, + documentFormat }); return revisions.map((revision) => @@ -79,7 +79,7 @@ export default class Peeker extends Service { mergeType, documentPath, documentFormat, - mergeOptions, + mergeOptions }: MergeOptions) { const url = fmt( config.API.MERGE_PEEK_PROJECT_PATH, @@ -92,12 +92,12 @@ export default class Peeker extends Service { documentFormat = documentFormat.toLowerCase(); const { - data: {operations, stats}, + data: {operations, stats} } = await this.authenticatedRequest.peek(url, { file, version, documentPath, - documentFormat, + documentFormat }); return [this.mapOperations(revision, operations, stats)]; @@ -111,7 +111,7 @@ export default class Peeker extends Service { return { language: revision.language, stats: this.mapOperationStats(stats[revision.id]), - operations: this.mapOperationItems(operations[revision.id]), + operations: this.mapOperationItems(operations[revision.id]) }; } @@ -133,7 +133,7 @@ export default class Peeker extends Service { action: operation.action, key: operation.key, text: operation.text, - previousText: operation['previous-text'], + previousText: operation['previous-text'] }; }); } diff --git a/webapp/app/services/phoenix.ts b/webapp/app/services/phoenix.ts index d4004c326..2abee845c 100644 --- a/webapp/app/services/phoenix.ts +++ b/webapp/app/services/phoenix.ts @@ -45,7 +45,7 @@ export default class Phoenix extends Service { socket({token}: {token: string}) { const socket = new Socket('/socket', { - params: {token}, + params: {token} }); socket.connect(); @@ -81,7 +81,7 @@ export default class Phoenix extends Service { const events = { sync: this.handleSync, create_collaborator: this.handleCreateCollaborator, - create_comment: this.handleCreateComment, + create_comment: this.handleCreateComment }; /* eslint-enable camelcase */ @@ -100,7 +100,7 @@ export default class Phoenix extends Service { /* eslint camelcase:0 */ this.showFlashMessage('sync', { user: user.name, - documentPath: payload.document_path, + documentPath: payload.document_path }); /* eslint camelcase:1 */ } @@ -108,7 +108,7 @@ export default class Phoenix extends Service { private handleCreateCollaborator({payload, user}: WebsocketMessage) { this.showFlashMessage('create_collaborator', { user: user.name, - collaboratorEmail: payload?.collaborator?.email, + collaboratorEmail: payload?.collaborator?.email }); } @@ -116,7 +116,7 @@ export default class Phoenix extends Service { this.showFlashMessage('create_comment', { user: user.name, commentText: payload.text, - translationKey: payload?.translation?.key, + translationKey: payload?.translation?.key }); } diff --git a/webapp/app/services/raven.js b/webapp/app/services/raven.js index c9a7b427c..fc739a809 100644 --- a/webapp/app/services/raven.js +++ b/webapp/app/services/raven.js @@ -108,16 +108,16 @@ export default Service.extend({ if (typeOf(reason) === 'error') { this.captureException(reason, { extra: { - context: label || this.unhandledPromiseErrorMessage, - }, + context: label || this.unhandledPromiseErrorMessage + } }); this.didCaptureException(reason); } else { this.captureMessage(this._extractMessage(reason), { extra: { reason, - context: label, - }, + context: label + } }); } }); @@ -199,5 +199,5 @@ export default Service.extend({ return false; } } - }, + } }); diff --git a/webapp/app/services/session/creator.ts b/webapp/app/services/session/creator.ts index fd6ea2c55..b4a6be8c3 100644 --- a/webapp/app/services/session/creator.ts +++ b/webapp/app/services/session/creator.ts @@ -7,7 +7,7 @@ export default class SessionCreator extends Service { method: 'POST', headers: { 'Content-Type': 'application/json', - Authorization: `Bearer ${token}`, + Authorization: `Bearer ${token}` }, body: JSON.stringify({ query: ` @@ -21,8 +21,8 @@ export default class SessionCreator extends Service { } } } - `, - }), + ` + }) }; const response = await fetch('/graphql', options); diff --git a/webapp/app/services/syncer.ts b/webapp/app/services/syncer.ts index 22e192014..7677ce635 100644 --- a/webapp/app/services/syncer.ts +++ b/webapp/app/services/syncer.ts @@ -24,7 +24,7 @@ export default class Syncer extends Service { file, documentPath, documentFormat, - syncType, + syncType }: SyncOptions) { const url = fmt( config.API.SYNC_PROJECT_PATH, @@ -39,7 +39,7 @@ export default class Syncer extends Service { documentPath, documentFormat, version, - syncType, + syncType }); } } diff --git a/webapp/app/styles/app.scss b/webapp/app/styles/app.scss index 5fa8d38a5..574c62ded 100644 --- a/webapp/app/styles/app.scss +++ b/webapp/app/styles/app.scss @@ -5,7 +5,6 @@ @import 'highlight-theme'; @import 'html-components/button'; -@import 'html-components/emoji-picker'; @import 'html-components/filters'; @import 'html-components/power-select'; @import 'html-components/pell'; @@ -14,7 +13,8 @@ font-family: 'Inter'; font-style: normal; font-weight: 100; - src: url('fonts/Inter-Thin.woff2') format('woff2'), + src: + url('fonts/Inter-Thin.woff2') format('woff2'), url('fonts/Inter-Thin.woff') format('woff'); } @@ -22,7 +22,8 @@ font-family: 'Inter'; font-style: italic; font-weight: 100; - src: url('fonts/Inter-ThinItalic.woff2') format('woff2'), + src: + url('fonts/Inter-ThinItalic.woff2') format('woff2'), url('fonts/Inter-ThinItalic.woff') format('woff'); } @@ -30,7 +31,8 @@ font-family: 'Inter'; font-style: normal; font-weight: 200; - src: url('fonts/Inter-ExtraLight.woff2') format('woff2'), + src: + url('fonts/Inter-ExtraLight.woff2') format('woff2'), url('fonts/Inter-ExtraLight.woff') format('woff'); } @@ -38,7 +40,8 @@ font-family: 'Inter'; font-style: italic; font-weight: 200; - src: url('fonts/Inter-ExtraLightItalic.woff2') format('woff2'), + src: + url('fonts/Inter-ExtraLightItalic.woff2') format('woff2'), url('fonts/Inter-ExtraLightItalic.woff') format('woff'); } @@ -46,7 +49,8 @@ font-family: 'Inter'; font-style: normal; font-weight: 300; - src: url('fonts/Inter-Light.woff2') format('woff2'), + src: + url('fonts/Inter-Light.woff2') format('woff2'), url('fonts/Inter-Light.woff') format('woff'); } @@ -54,7 +58,8 @@ font-family: 'Inter'; font-style: italic; font-weight: 300; - src: url('fonts/Inter-LightItalic.woff2') format('woff2'), + src: + url('fonts/Inter-LightItalic.woff2') format('woff2'), url('fonts/Inter-LightItalic.woff') format('woff'); } @@ -62,7 +67,8 @@ font-family: 'Inter'; font-style: normal; font-weight: 400; - src: url('fonts/Inter-Regular.woff2') format('woff2'), + src: + url('fonts/Inter-Regular.woff2') format('woff2'), url('fonts/Inter-Regular.woff') format('woff'); } @@ -70,7 +76,8 @@ font-family: 'Inter'; font-style: italic; font-weight: 400; - src: url('fonts/Inter-Italic.woff2') format('woff2'), + src: + url('fonts/Inter-Italic.woff2') format('woff2'), url('fonts/Inter-Italic.woff') format('woff'); } @@ -78,7 +85,8 @@ font-family: 'Inter'; font-style: normal; font-weight: 500; - src: url('fonts/Inter-Medium.woff2') format('woff2'), + src: + url('fonts/Inter-Medium.woff2') format('woff2'), url('fonts/Inter-Medium.woff') format('woff'); } @@ -86,7 +94,8 @@ font-family: 'Inter'; font-style: italic; font-weight: 500; - src: url('fonts/Inter-MediumItalic.woff2') format('woff2'), + src: + url('fonts/Inter-MediumItalic.woff2') format('woff2'), url('fonts/Inter-MediumItalic.woff') format('woff'); } @@ -94,14 +103,16 @@ font-family: 'Inter'; font-style: normal; font-weight: 600; - src: url('fonts/Inter-SemiBold.woff2') format('woff2'), + src: + url('fonts/Inter-SemiBold.woff2') format('woff2'), url('fonts/Inter-SemiBold.woff') format('woff'); } @font-face { font-family: 'Inter'; font-style: italic; font-weight: 600; - src: url('fonts/Inter-SemiBoldItalic.woff2') format('woff2'), + src: + url('fonts/Inter-SemiBoldItalic.woff2') format('woff2'), url('fonts/Inter-SemiBoldItalic.woff') format('woff'); } @@ -109,7 +120,8 @@ font-family: 'Inter'; font-style: normal; font-weight: 700; - src: url('fonts/Inter-Bold.woff2') format('woff2'), + src: + url('fonts/Inter-Bold.woff2') format('woff2'), url('fonts/Inter-Bold.woff') format('woff'); } @@ -117,7 +129,8 @@ font-family: 'Inter'; font-style: italic; font-weight: 700; - src: url('fonts/Inter-BoldItalic.woff2') format('woff2'), + src: + url('fonts/Inter-BoldItalic.woff2') format('woff2'), url('fonts/Inter-BoldItalic.woff') format('woff'); } @@ -125,7 +138,8 @@ font-family: 'Fira Code'; font-weight: 300; font-style: normal; - src: url('fonts/FiraCode-Light.woff2') format('woff2'), + src: + url('fonts/FiraCode-Light.woff2') format('woff2'), url('fonts/FiraCode-Light.woff') format('woff'); } @@ -133,7 +147,8 @@ font-family: 'Fira Code'; font-weight: 400; font-style: normal; - src: url('fonts/FiraCode-Regular.woff2') format('woff2'), + src: + url('fonts/FiraCode-Regular.woff2') format('woff2'), url('fonts/FiraCode-Regular.woff') format('woff'); } @@ -141,7 +156,8 @@ font-family: 'Fira Code'; font-weight: 500; font-style: normal; - src: url('fonts/FiraCode-Medium.woff2') format('woff2'), + src: + url('fonts/FiraCode-Medium.woff2') format('woff2'), url('fonts/FiraCode-Medium.woff') format('woff'); } @@ -149,7 +165,8 @@ font-family: 'Fira Code'; font-weight: 700; font-style: normal; - src: url('fonts/FiraCode-Bold.woff2') format('woff2'), + src: + url('fonts/FiraCode-Bold.woff2') format('woff2'), url('fonts/FiraCode-Bold.woff') format('woff'); } @@ -345,6 +362,21 @@ input[type='radio'] { border-radius: 18px; } +emoji-picker { + --num-columns: 9; + --emoji-size: 1.3rem; + --background: var(--background-light); + --border-color: var(--background-light-highlight); + --input-border-color: transparent; + --input-padding: 4px 0; + --outline-size: 0; + --input-font-color: var(--text-color-normal); + --input-placeholder-color: var(--color-grey); + --indicator-color: hsl(var(--accent-hue), 55%, 55%); + --button-hover-background: var(--background-light-highlight); + --button-active-background: var(--background-light-highlight); +} + :global(.app) { display: flex; min-height: 100vh; diff --git a/webapp/app/pods/components/acc-avatar-img/styles.scss b/webapp/app/styles/components/acc-avatar-img.scss similarity index 100% rename from webapp/app/pods/components/acc-avatar-img/styles.scss rename to webapp/app/styles/components/acc-avatar-img.scss diff --git a/webapp/app/pods/components/acc-badge/styles.scss b/webapp/app/styles/components/acc-badge.scss similarity index 100% rename from webapp/app/pods/components/acc-badge/styles.scss rename to webapp/app/styles/components/acc-badge.scss diff --git a/webapp/app/styles/components/acc-emoji-picker.scss b/webapp/app/styles/components/acc-emoji-picker.scss new file mode 100644 index 000000000..2ae85d1d0 --- /dev/null +++ b/webapp/app/styles/components/acc-emoji-picker.scss @@ -0,0 +1,71 @@ +.wrapper { + display: flex; + align-items: flex-start; + justify-content: center; + position: fixed; + z-index: 4000; + height: 100vh; + left: 0; + right: 0; + top: 0; + overflow-y: scroll; + padding: 130px 30px 100px; +} + +.overlay { + position: fixed; + top: 0; + left: 0; + bottom: 0; + right: 0; + min-height: calc(100vh - 130px); + background-color: #000; + opacity: 0.6; + + animation-name: animate-overlay; + animation-timing-function: ease-in-out; + animation-duration: 0.2s; + animation-delay: 0; + animation-fill-mode: forwards; +} + +.container { + display: block; + position: relative; + z-index: 3; + border-radius: var(--border-radius); + overflow: hidden; + box-shadow: 0 2px 20px 0 var(--shadow-color); + + animation-name: animate-content; + animation-timing-function: ease-in-out; + animation-duration: 0.3s; + animation-delay: 0; + animation-fill-mode: forwards; +} + +@media (max-width: 440px) { + .wrapper { + padding: 30px 10px; + } +} + +@keyframes animate-content { + 0% { + opacity: 0; + transform: translateY(10px); + } + 100% { + opacity: 1; + transform: translateY(0); + } +} + +@keyframes animate-overlay { + 0% { + opacity: 0; + } + 100% { + opacity: 0.6; + } +} diff --git a/webapp/app/pods/components/acc-flash-message/styles.scss b/webapp/app/styles/components/acc-flash-message.scss similarity index 100% rename from webapp/app/pods/components/acc-flash-message/styles.scss rename to webapp/app/styles/components/acc-flash-message.scss diff --git a/webapp/app/pods/components/acc-modal/styles.scss b/webapp/app/styles/components/acc-modal.scss similarity index 100% rename from webapp/app/pods/components/acc-modal/styles.scss rename to webapp/app/styles/components/acc-modal.scss diff --git a/webapp/app/pods/components/acc-select/styles.scss b/webapp/app/styles/components/acc-select.scss similarity index 100% rename from webapp/app/pods/components/acc-select/styles.scss rename to webapp/app/styles/components/acc-select.scss diff --git a/webapp/app/pods/components/acc-wrapper/styles.scss b/webapp/app/styles/components/acc-wrapper.scss similarity index 100% rename from webapp/app/pods/components/acc-wrapper/styles.scss rename to webapp/app/styles/components/acc-wrapper.scss diff --git a/webapp/app/pods/components/acc-wrapper/content/styles.scss b/webapp/app/styles/components/acc-wrapper/content.scss similarity index 100% rename from webapp/app/pods/components/acc-wrapper/content/styles.scss rename to webapp/app/styles/components/acc-wrapper/content.scss diff --git a/webapp/app/pods/components/acc-wrapper/projects/styles.scss b/webapp/app/styles/components/acc-wrapper/projects.scss similarity index 100% rename from webapp/app/pods/components/acc-wrapper/projects/styles.scss rename to webapp/app/styles/components/acc-wrapper/projects.scss diff --git a/webapp/app/pods/components/acc-wrapper/sidebar/styles.scss b/webapp/app/styles/components/acc-wrapper/sidebar.scss similarity index 100% rename from webapp/app/pods/components/acc-wrapper/sidebar/styles.scss rename to webapp/app/styles/components/acc-wrapper/sidebar.scss diff --git a/webapp/app/pods/components/activity-item/styles.scss b/webapp/app/styles/components/activity-item.scss similarity index 100% rename from webapp/app/pods/components/activity-item/styles.scss rename to webapp/app/styles/components/activity-item.scss diff --git a/webapp/app/pods/components/application-footer/styles.scss b/webapp/app/styles/components/application-footer.scss similarity index 96% rename from webapp/app/pods/components/application-footer/styles.scss rename to webapp/app/styles/components/application-footer.scss index 242fa2929..a0cf6a16f 100644 --- a/webapp/app/pods/components/application-footer/styles.scss +++ b/webapp/app/styles/components/application-footer.scss @@ -73,7 +73,9 @@ background: none; opacity: 0.2; color: var(--text-color-normal); - transition: color 0.2s ease-in-out, opacity 0.2s ease-in-out, + transition: + color 0.2s ease-in-out, + opacity 0.2s ease-in-out, transform 0.2s ease-in; &:focus, diff --git a/webapp/app/pods/components/async-button/styles.scss b/webapp/app/styles/components/async-button.scss similarity index 90% rename from webapp/app/pods/components/async-button/styles.scss rename to webapp/app/styles/components/async-button.scss index 8941d3236..2b4e2cec5 100644 --- a/webapp/app/pods/components/async-button/styles.scss +++ b/webapp/app/styles/components/async-button.scss @@ -26,6 +26,13 @@ } } + &:global(.button--iconOnly) { + .label { + padding-left: 5px; + padding-right: 5px; + } + } + &:global(.button--small) { &.button--loading { .loading { diff --git a/webapp/app/pods/components/azure-push-form/styles.scss b/webapp/app/styles/components/azure-push-form.scss similarity index 100% rename from webapp/app/pods/components/azure-push-form/styles.scss rename to webapp/app/styles/components/azure-push-form.scss diff --git a/webapp/app/pods/components/commit-file/styles.scss b/webapp/app/styles/components/commit-file.scss similarity index 100% rename from webapp/app/pods/components/commit-file/styles.scss rename to webapp/app/styles/components/commit-file.scss diff --git a/webapp/app/styles/components/conflicts-filters.scss b/webapp/app/styles/components/conflicts-filters.scss new file mode 100644 index 000000000..a04e7f1f5 --- /dev/null +++ b/webapp/app/styles/components/conflicts-filters.scss @@ -0,0 +1,76 @@ +.conflicts-filters { + :global(.filters) { + margin-bottom: 20px; + + :global(.ember-power-select-multiple-trigger) { + width: 100%; + border-width: 2px; + margin-bottom: 10px; + &:focus { + border-width: 2px; + } + } + } +} + +.search-icon { + position: absolute; + top: 50%; + margin-top: -10px; + left: 7px; + width: 20px; + height: 20px; + stroke: #b7b7b7; +} + +.input { + @extend %textInput; + width: 100%; + padding: 7px 7px 7px 30px; + font-family: var(--font-primary); + font-size: 14px; + color: var(--color-black); + + &:focus { + box-shadow: + inset 0 1px 2px rgba(#000, 0.1), + 0 1px 2px var(--shadow-color); + } + + &::placeholder { + color: var(--color-grey); + } +} + +button.advancedFilters { + position: relative; + box-shadow: none; + flex-shrink: 0; + &:focus, + &:hover { + transform: translate3d(0, 0, 0); + } +} + +.advancedFilters-badge { + position: absolute; + top: -4px; + right: -7px; + background: var(--color-primary); + border-radius: var(--border-radius); + padding: 0 4px 1px; + color: #fff; + font-size: 10px; +} + +@media (max-width: 440px) { + .filters-wrapper { + flex-direction: column; + } + + .queryForm, + .filters-content { + width: 100%; + margin-right: 0; + } +} diff --git a/webapp/app/pods/components/conflicts-list/styles.scss b/webapp/app/styles/components/conflicts-list.scss similarity index 56% rename from webapp/app/pods/components/conflicts-list/styles.scss rename to webapp/app/styles/components/conflicts-list.scss index 65422a437..23d758fa3 100644 --- a/webapp/app/pods/components/conflicts-list/styles.scss +++ b/webapp/app/styles/components/conflicts-list.scss @@ -1,9 +1,17 @@ -.conflicts-items { - position: relative; - margin-top: 20px; +.conflicts-header { + position: sticky; + padding: 14px 0 0 15px; + top: 0; + z-index: 4; + display: grid; + grid-template-columns: repeat(var(--group-columns-count, 1), 1fr); + font-size: 16px; + font-weight: bold; + margin: 0 0 10px -14px; + background: var(--content-background); } -.conflicts-items-version { +.conflicts-list-version { margin: 0 0 15px; padding: 15px; border-radius: var(--border-radius); @@ -16,14 +24,25 @@ color: var(--color-blue); } -.conflicts-items-version-tag { +.conflicts-list-version-tag { display: inline-flex; align-items: center; margin-left: 2px; font-size: 11px; font-family: var(--font-monospace); font-weight: 600; - text-transform: capitalize; + text-transform: none; +} + +.conflicts-header-item { + padding-bottom: 10px; +} + +.conflicts-header-item-slug { + font-weight: normal; + opacity: 0.6; + margin-left: 2px; + font-size: 12px; } .all-reviewed { @@ -43,7 +62,3 @@ font-size: 12px; color: var(--color-grey); } - -.empty-content { - margin-top: 40px; -} diff --git a/webapp/app/styles/components/conflicts-list/advanced-filters.scss b/webapp/app/styles/components/conflicts-list/advanced-filters.scss new file mode 100644 index 000000000..9e08e73f7 --- /dev/null +++ b/webapp/app/styles/components/conflicts-list/advanced-filters.scss @@ -0,0 +1,31 @@ +.conflicts-list-advanced-filters { + margin: 15px 0 0 0; + display: flex; + flex-direction: column; +} + +.title { + text-transform: uppercase; + color: var(--text-color-normal); + font-size: 11px; + font-weight: bold; +} + +.label { + display: flex; + align-items: flex-start; + width: 100%; + max-width: 250px; + margin-top: 10px; + font-size: 12px; + + input { + margin-right: 6px; + } +} + +.labels { + display: flex; + flex-wrap: wrap; + max-width: 960px; +} diff --git a/webapp/app/styles/components/conflicts-list/group.scss b/webapp/app/styles/components/conflicts-list/group.scss new file mode 100644 index 000000000..998b642e4 --- /dev/null +++ b/webapp/app/styles/components/conflicts-list/group.scss @@ -0,0 +1,111 @@ +.item { + --grid-item-reviewed-opacity: 0.5; + --grid-item-actions-opacity: 0; + border-bottom: 1px solid var(--background-light-highlight); + transition: 0.2s ease-in-out; + transition-property: border-color; + background: var(--content-background); + + :global(.lint-translations-item) { + display: none; + padding: 2px 6px; + border-radius: var(--border-radius); + margin: 0 5px 5px; + + background: var(--background-light); + } + + &.item--focus { + background: var(--background-light); + + :global(.lint-translations-item) { + display: block; + } + + .item-key { + transform: translateY(2px); + } + + --grid-item-reviewed-opacity: 1; + --grid-item-actions-opacity: 1; + } +} + +.item-grid { + display: grid; + grid-template-columns: repeat(var(--group-columns-count, 1), 1fr); +} + +.item-grid-item { + --border-color: var(--background-light-highlight); + position: relative; + padding: 0; + border-left: 2px solid var(--border-color); + opacity: 1; + + &.item-grid-item--translated { + --border-color: var(--color-warning); + opacity: 1; + } + + &.item-grid-item--reviewed { + --border-color: var(--color-green); + opacity: var(--grid-item-reviewed-opacity); + } + + &:hover { + opacity: 1; + } + + &::before { + position: absolute; + content: ''; + top: -24px; + left: -2px; + height: 32px; + width: 2px; + background: var(--border-color); + } +} + +.item-key-prefix { + display: inline-flex; + font-size: 11px; + color: #959595; + gap: 6px; + font-weight: 300; + flex-shrink: 0; + + &::before { + content: '/'; + } +} + +.item-key { + position: sticky; + top: 46px; + display: inline-flex; + align-items: flex-start; + gap: 5px; + background: var(--content-background); + padding: 2px 6px; + text-decoration: none; + font-family: var(--font-monospace); + box-shadow: 0 2px 4px var(--shadow-color); + border-radius: var(--border-radius); + font-weight: 600; + z-index: 2; + word-break: break-all; + transition: 0.2s ease-in-out; + transition-property: color; + margin-left: 4px; + line-height: 1.5; + font-size: 11px; + color: var(--text-color-normal); + transition: 0.2s ease-in-out; + transition-property: transform; +} + +.key { + text-decoration: none; +} diff --git a/webapp/app/styles/components/conflicts-list/item.scss b/webapp/app/styles/components/conflicts-list/item.scss new file mode 100644 index 000000000..edaca841d --- /dev/null +++ b/webapp/app/styles/components/conflicts-list/item.scss @@ -0,0 +1,142 @@ +.translation-item { + &:hover { + .form-helpers { + pointer-events: all; + opacity: 1; + } + .button-submit { + pointer-events: all; + opacity: 1; + } + } +} + +.revert-button { + position: absolute; + right: 8px; + top: -30px; + + :global(.label) { + padding-left: 3px; + padding-right: 3px; + } +} + +.item-details__column { + position: relative; +} + +.item-details { + display: flex; + flex-direction: column; + + &[data-dir='rtl'] { + .revert-button { + right: auto; + left: 8px; + } + + .item-details__column { + align-items: flex-end; + } + + .item-details__column:first-of-type { + margin-right: 0; + margin-left: 15px; + } + + .item-key { + margin-right: 0; + margin-left: 15px; + flex-direction: row-reverse; + } + + .item-key-prefix::before { + content: ''; + } + + .item-key-prefix::after { + content: '/'; + } + } +} + +.item-details__column { + display: flex; + flex-direction: column; + align-items: flex-start; +} + +.item-details__column:first-of-type { + margin-right: 15px; +} + +.translation-item.resolved { + background: var(--color-primary-opacity-10); +} + +.translation-item.errored { + .textInput { + border-color: var(--color-error); + } +} + +.error { + font-size: 12px; + font-weight: bold; + color: var(--color-error); +} + +.button-submit { + display: flex; + justify-content: flex-end; + position: absolute; + pointer-events: none; + opacity: var(--grid-item-actions-opacity); + gap: 0; + bottom: 15px; + right: 10px; + z-index: 3; + transition: 0.2s ease-in-out; + transition-property: opacity; + + &[data-dir='rtl'] { + right: auto; + left: 7px; + flex-direction: row-reverse; + } +} + +.textInput { + flex-grow: 1; + flex-shrink: 0; + width: 100%; + font-size: 13px; +} + +.item-text { + display: block; + width: 100%; + color: var(--color-black); + line-height: 1.4; + padding: 3px 10px 10px 0; + font-size: 13px; + line-height: 1.6; + cursor: pointer; + word-break: break-word; + + &:focus, + &:hover { + outline: none; + opacity: 0.8; + } +} + +.form-helpers { + pointer-events: none; + opacity: 0; + position: relative; + z-index: 1; + transition: 0.2s ease-in-out; + transition-property: opacity; +} diff --git a/webapp/app/pods/components/dashboard-revisions/styles.scss b/webapp/app/styles/components/dashboard-revisions.scss similarity index 93% rename from webapp/app/pods/components/dashboard-revisions/styles.scss rename to webapp/app/styles/components/dashboard-revisions.scss index 1faec244e..b7f603634 100644 --- a/webapp/app/pods/components/dashboard-revisions/styles.scss +++ b/webapp/app/styles/components/dashboard-revisions.scss @@ -37,7 +37,7 @@ align-items: center; justify-content: center; width: 100%; - margin: 20px auto 40px; + margin: 0 auto 10px; } .numberStat-reviewPercentage { @@ -92,17 +92,15 @@ .stats-title { display: flex; - justify-content: space-between; + justify-content: center; align-items: center; - margin-bottom: 0; + margin-bottom: 10px; padding-bottom: 2px; - margin-left: -8px; } .slaves { display: flex; - flex-wrap: wrap; - align-items: flex-start; + flex-direction: column; } .empty-slaves-button { @@ -111,7 +109,9 @@ max-width: 340px; padding: 15px; background: var(--content-background); - box-shadow: 0 1px 4px var(--shadow-color), 0 7px 12px var(--shadow-color); + box-shadow: + 0 1px 4px var(--shadow-color), + 0 7px 12px var(--shadow-color); border-radius: var(--border-radius); color: var(--color-primary); text-decoration: none; @@ -146,12 +146,13 @@ } .master { - margin: 0 0 10px; + margin: 25px 0 0; } .stats-title-links { display: flex; justify-content: flex-end; + gap: 5px; .button { margin-left: 10px; diff --git a/webapp/app/pods/components/dashboard-revisions/item/styles.scss b/webapp/app/styles/components/dashboard-revisions/item.scss similarity index 72% rename from webapp/app/pods/components/dashboard-revisions/item/styles.scss rename to webapp/app/styles/components/dashboard-revisions/item.scss index 9a320b1bc..bd89aa507 100644 --- a/webapp/app/pods/components/dashboard-revisions/item/styles.scss +++ b/webapp/app/styles/components/dashboard-revisions/item.scss @@ -2,18 +2,13 @@ transition: 0.2s ease-in-out; transition-property: box-shadow; position: relative; - flex: 1 1 calc(50% - 20px); justify-content: space-between; - max-width: 50%; - margin-bottom: 20px; - margin-right: 20px; + width: 100%; + margin-bottom: 10px; border-radius: var(--border-radius); - border: 1px solid var(--background-light-highlight); - - &:nth-child(even) { - flex: 1 1 50%; - margin-right: 0; - } + box-shadow: + 0 6px 25px var(--shadow-color), + 0 2px 7px var(--shadow-color); } .dashboard-revisions-item.low-percentage { @@ -62,8 +57,7 @@ .language { display: flex; - align-items: flex-end; - justify-content: space-between; + flex-direction: column; color: var(--color-grey); } @@ -82,21 +76,43 @@ } .language-reviewedPercentage { - display: block; - margin-top: 5px; + display: flex; + align-items: baseline; + gap: 4px; font-weight: normal; - font-size: 25px; + font-size: 22px; color: var(--color-grey); + letter-spacing: -2px; +} + +.language-reviewedPercentage-symbol { + font-size: 13px; } .reviewedStats { - padding: 2px 0 1px 7px; - border-radius: var(--border-radius); + display: flex; + align-items: baseline; + justify-content: space-between; + gap: 10px; color: var(--color-grey); font-size: 12px; font-family: var(--font-monospace); } +.reviewedStats-translatedCount, +.reviewedStats-translationsCount, +.reviewedStats-reviewedCount { + font-family: var(--font-primary); + color: var(--color-grey); + margin: 0 3px; + font-size: 11px; + text-decoration: none; +} + +.reviewedStats-reviewedCount { + font-weight: bold; +} + .actionsButton { transition: 0.2s ease-in-out; transition-property: opacity; @@ -114,17 +130,18 @@ &:focus, &:hover { .actionsButton-icon { - stroke: var(--color-primary); + opacity: 1; } } } .actionsButton-icon { stroke: var(--color-grey); + opacity: 0.4; transition: 0.2s ease-in-out; - transition-property: stroke; - width: 15px; - height: 15px; + transition-property: stroke, opacity; + width: 13px; + height: 13px; } .actions { @@ -132,6 +149,10 @@ display: flex; flex-direction: column; gap: 4px; + + :global(.button) { + justify-content: center; + } } .actionItem-text { diff --git a/webapp/app/pods/components/documents-list/styles.scss b/webapp/app/styles/components/documents-list.scss similarity index 100% rename from webapp/app/pods/components/documents-list/styles.scss rename to webapp/app/styles/components/documents-list.scss diff --git a/webapp/app/pods/components/documents-list/item/styles.scss b/webapp/app/styles/components/documents-list/item.scss similarity index 100% rename from webapp/app/pods/components/documents-list/item/styles.scss rename to webapp/app/styles/components/documents-list/item.scss diff --git a/webapp/app/pods/components/documents-machine-translations-button/styles.scss b/webapp/app/styles/components/documents-machine-translations-button.scss similarity index 100% rename from webapp/app/pods/components/documents-machine-translations-button/styles.scss rename to webapp/app/styles/components/documents-machine-translations-button.scss diff --git a/webapp/app/pods/components/dummy-login-form/styles.scss b/webapp/app/styles/components/dummy-login-form.scss similarity index 100% rename from webapp/app/pods/components/dummy-login-form/styles.scss rename to webapp/app/styles/components/dummy-login-form.scss diff --git a/webapp/app/pods/components/empty-content/styles.scss b/webapp/app/styles/components/empty-content.scss similarity index 100% rename from webapp/app/pods/components/empty-content/styles.scss rename to webapp/app/styles/components/empty-content.scss diff --git a/webapp/app/pods/components/error-section/styles.scss b/webapp/app/styles/components/error-section.scss similarity index 100% rename from webapp/app/pods/components/error-section/styles.scss rename to webapp/app/styles/components/error-section.scss diff --git a/webapp/app/pods/components/flash-messages-list/styles.scss b/webapp/app/styles/components/flash-messages-list.scss similarity index 100% rename from webapp/app/pods/components/flash-messages-list/styles.scss rename to webapp/app/styles/components/flash-messages-list.scss diff --git a/webapp/app/pods/components/google-login-form/styles.scss b/webapp/app/styles/components/google-login-form.scss similarity index 100% rename from webapp/app/pods/components/google-login-form/styles.scss rename to webapp/app/styles/components/google-login-form.scss diff --git a/webapp/app/pods/components/highlight-render/styles.scss b/webapp/app/styles/components/highlight-render.scss similarity index 100% rename from webapp/app/pods/components/highlight-render/styles.scss rename to webapp/app/styles/components/highlight-render.scss diff --git a/webapp/app/pods/components/improve-prompt/styles.scss b/webapp/app/styles/components/improve-prompt.scss similarity index 95% rename from webapp/app/pods/components/improve-prompt/styles.scss rename to webapp/app/styles/components/improve-prompt.scss index b6c176a51..9d3084c26 100644 --- a/webapp/app/pods/components/improve-prompt/styles.scss +++ b/webapp/app/styles/components/improve-prompt.scss @@ -64,13 +64,13 @@ button.button { opacity: 1; } .prompt-button-quick-access[data-rtl] { - left: 36px; + transform: translateX(36px); right: auto; } .prompt-button-quick-access { opacity: 1; - right: 36px; + transform: translateX(-36px); padding: 0 7px; top: -1px; pointer-events: all; @@ -87,6 +87,7 @@ button.button { background: var(--input-background); opacity: 0; pointer-events: none; + transform: translateX(0); right: 0; display: flex; gap: 4px; diff --git a/webapp/app/styles/components/inline-machine-translate.scss b/webapp/app/styles/components/inline-machine-translate.scss new file mode 100644 index 000000000..e69de29bb diff --git a/webapp/app/pods/components/jipt-back-to-translations/styles.scss b/webapp/app/styles/components/jipt-back-to-translations.scss similarity index 100% rename from webapp/app/pods/components/jipt-back-to-translations/styles.scss rename to webapp/app/styles/components/jipt-back-to-translations.scss diff --git a/webapp/app/styles/components/jipt-example.scss b/webapp/app/styles/components/jipt-example.scss new file mode 100644 index 000000000..36a93804e --- /dev/null +++ b/webapp/app/styles/components/jipt-example.scss @@ -0,0 +1,123 @@ +.browser-mockup { + position: relative; + border-top: 2em solid rgba(230, 230, 230, 0.5); + box-shadow: 0 0.1em 1em 0 rgba(0, 0, 0, 0.4); + position: relative; + border-radius: 8px; + margin: 70px auto; + flex: 1; + max-width: 800px; +} + +.browser-back-link { + position: absolute; + top: -24px; + right: 10px; + font-size: 11px; + color: #2a2d87; + text-shadow: 0 1px 1px rgba(#fff, 0.2); + opacity: 0.6; + text-decoration: none; +} + +.browser-mockup:before { + display: block; + position: absolute; + content: ''; + top: -1.25em; + left: 1em; + width: 0.5em; + height: 0.5em; + border-radius: 50%; + background-color: #f44; + box-shadow: + 0 0 0 2px #f44, + 1.5em 0 0 2px #9b3, + 3em 0 0 2px #fb5; +} + +.browser-content { + background: #fff; + padding: 30px; + border-radius: 0 0 8px 8px; +} + +.browser-content h1 { + font-weight: bold; + font-size: 25px; + padding-bottom: 8px; + border-bottom: 1px solid #eee; + margin-bottom: 20px; +} + +.browser-content h2 { + font-weight: bold; + font-size: 20px; + padding-bottom: 5px; + margin-top: 10px; + margin-bottom: 12px; + border-bottom: 1px solid #eee; +} + +.tag-inner-wrapper { + display: flex; + gap: 5px; + align-items: center; +} + +.tag-attributes-wrapper { + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 5px; + margin-bottom: 25px; +} + +.tag { + display: inline-flex; + color: #888; + font-size: 11px; + font-family: var(--font-monospace); +} + +.browser-content pre { + background: #eee; + padding: 10px 14px; + opacity: 0.7; + border-radius: 4px; + font-size: 11px; + margin-bottom: 15px; + white-space: pre-line; +} + +.browser-content img { + width: 100%; + max-width: 200px; + display: block; + border-radius: 4px; +} + +.browser-content input[type='submit'] { + border-radius: 50px; + padding: 3px 10px; + border: 2px solid #555; + background: linear-gradient(to bottom, #e2e2e2, #bcbcbc); + box-shadow: inset 0 1px 0 rgba(#fff, 0.5); +} + +.browser-content input[type='text'] { + border-radius: 5px; + padding: 5px 10px; + border: 2px solid #555; + background: #fff; + max-width: 300px; + width: 100%; + box-shadow: inset 0 1px 1px rgba(#000, 0.1); +} + +.wrapper { + background: linear-gradient(to right, #4453ad, #2a2d87); + display: flex; + height: 100dvh; + align-items: flex-start; +} diff --git a/webapp/app/pods/components/jipt-header/styles.scss b/webapp/app/styles/components/jipt-header.scss similarity index 100% rename from webapp/app/pods/components/jipt-header/styles.scss rename to webapp/app/styles/components/jipt-header.scss diff --git a/webapp/app/pods/components/jipt-translation/styles.scss b/webapp/app/styles/components/jipt-translation.scss similarity index 100% rename from webapp/app/pods/components/jipt-translation/styles.scss rename to webapp/app/styles/components/jipt-translation.scss diff --git a/webapp/app/pods/components/jipt-translations-filtered-title/styles.scss b/webapp/app/styles/components/jipt-translations-filtered-title.scss similarity index 100% rename from webapp/app/pods/components/jipt-translations-filtered-title/styles.scss rename to webapp/app/styles/components/jipt-translations-filtered-title.scss diff --git a/webapp/app/pods/components/jipt-translations-list/styles.scss b/webapp/app/styles/components/jipt-translations-list.scss similarity index 82% rename from webapp/app/pods/components/jipt-translations-list/styles.scss rename to webapp/app/styles/components/jipt-translations-list.scss index f4f0c2946..5374b96d1 100644 --- a/webapp/app/pods/components/jipt-translations-list/styles.scss +++ b/webapp/app/styles/components/jipt-translations-list.scss @@ -1,8 +1,3 @@ -.jipt-translations-list { - margin: 20px 0; - border-top: 1px solid #eee; -} - .item { display: block; border-bottom: 1px solid #eee; diff --git a/webapp/app/pods/components/jipt-translations-list/item/styles.scss b/webapp/app/styles/components/jipt-translations-list/item.scss similarity index 58% rename from webapp/app/pods/components/jipt-translations-list/item/styles.scss rename to webapp/app/styles/components/jipt-translations-list/item.scss index 3038bd0d0..3a57e7c48 100644 --- a/webapp/app/pods/components/jipt-translations-list/item/styles.scss +++ b/webapp/app/styles/components/jipt-translations-list/item.scss @@ -1,5 +1,6 @@ .item-text { - display: block; + display: flex; + flex-direction: column; text-overflow: ellipsis; overflow-x: hidden; color: var(--text-color-normal); @@ -9,4 +10,10 @@ color: var(--color-grey); font-style: italic; } + + .item-key { + opacity: 0.5; + font-size: 11px; + font-family: var(--font-monospace); + } } diff --git a/webapp/app/pods/components/lint-options/styles.scss b/webapp/app/styles/components/lint-options.scss similarity index 85% rename from webapp/app/pods/components/lint-options/styles.scss rename to webapp/app/styles/components/lint-options.scss index 34ea70ed4..50970589b 100644 --- a/webapp/app/pods/components/lint-options/styles.scss +++ b/webapp/app/styles/components/lint-options.scss @@ -17,7 +17,9 @@ color: var(--color-black); &:focus { - box-shadow: inset 0 1px 2px rgba(#000, 0.1), 0 1px 2px var(--shadow-color); + box-shadow: + inset 0 1px 2px rgba(#000, 0.1), + 0 1px 2px var(--shadow-color); } &::placeholder { diff --git a/webapp/app/pods/components/lint-translations-page/styles.scss b/webapp/app/styles/components/lint-translations-page.scss similarity index 82% rename from webapp/app/pods/components/lint-translations-page/styles.scss rename to webapp/app/styles/components/lint-translations-page.scss index a7b86be5d..a79c0a651 100644 --- a/webapp/app/pods/components/lint-translations-page/styles.scss +++ b/webapp/app/styles/components/lint-translations-page.scss @@ -23,6 +23,12 @@ .item { margin-bottom: 20px; + transition: 0.2s ease-in-out; + transition-property: opacity; +} + +.item--fixing { + opacity: 0.5; } .icon-warning { @@ -46,10 +52,9 @@ .stats-item { display: inline-flex; gap: 4px; - padding: 2px 12px; + padding: 4px 12px; border-radius: 30px; - border: 1px solid var(--background-light-highlight); - background: var(--background-light); + background: var(--background-light-highlight); color: var(--text-color-normal); font-size: 12px; cursor: default; diff --git a/webapp/app/pods/components/lint-translations-page/item/styles.scss b/webapp/app/styles/components/lint-translations-page/item.scss similarity index 86% rename from webapp/app/pods/components/lint-translations-page/item/styles.scss rename to webapp/app/styles/components/lint-translations-page/item.scss index 63c1687b2..261e14bf6 100644 --- a/webapp/app/pods/components/lint-translations-page/item/styles.scss +++ b/webapp/app/styles/components/lint-translations-page/item.scss @@ -13,11 +13,26 @@ flex-direction: column; } +.messages-item { + display: flex; + gap: 4px; + align-items: center; +} + .description { color: var(--color-error); font-size: 12px; } +.button-fix { + width: max-content; + + &:focus, + &:hover { + --button-text-hover-color: var(--color-green); + } +} + .item-language { font-size: 11px; font-weight: bold; @@ -94,6 +109,15 @@ } } +.item-diff-text { + font-size: 13px; + color: var(--text-color-normal); + + > div { + display: inline; + } +} + .item-text { strong { color: var(--color-green); diff --git a/webapp/app/pods/components/loading-content/styles.scss b/webapp/app/styles/components/loading-content.scss similarity index 100% rename from webapp/app/pods/components/loading-content/styles.scss rename to webapp/app/styles/components/loading-content.scss diff --git a/webapp/app/pods/components/login-forms/styles.scss b/webapp/app/styles/components/login-forms.scss similarity index 95% rename from webapp/app/pods/components/login-forms/styles.scss rename to webapp/app/styles/components/login-forms.scss index dfe12e818..373f29688 100644 --- a/webapp/app/pods/components/login-forms/styles.scss +++ b/webapp/app/styles/components/login-forms.scss @@ -7,7 +7,9 @@ padding: 30px 30px 20px 30px; border-radius: 6px; background: var(--content-background); - box-shadow: 0 1px 4px var(--shadow-color), 0 7px 12px var(--shadow-color); + box-shadow: + 0 1px 4px var(--shadow-color), + 0 7px 12px var(--shadow-color); .text { max-width: 300px; @@ -218,6 +220,13 @@ a.loginButton { color: #03a5f0; background: lighten(#03a5f0, 48%); } + + &.loginButton--oidc { + border-color: #f7931e; + text-shadow: none; + color: #f7931e; + background: lighten(#f7931e, 48%); + } } .loginButton-logo { diff --git a/webapp/app/pods/components/machine-translations-document-translate/styles.scss b/webapp/app/styles/components/machine-translations-document-translate.scss similarity index 100% rename from webapp/app/pods/components/machine-translations-document-translate/styles.scss rename to webapp/app/styles/components/machine-translations-document-translate.scss diff --git a/webapp/app/pods/components/machine-translations-translate-upload-form/styles.scss b/webapp/app/styles/components/machine-translations-translate-upload-form.scss similarity index 100% rename from webapp/app/pods/components/machine-translations-translate-upload-form/styles.scss rename to webapp/app/styles/components/machine-translations-translate-upload-form.scss diff --git a/webapp/app/pods/components/operations-peek/styles.scss b/webapp/app/styles/components/operations-peek.scss similarity index 100% rename from webapp/app/pods/components/operations-peek/styles.scss rename to webapp/app/styles/components/operations-peek.scss diff --git a/webapp/app/pods/components/operations-peek/item/styles.scss b/webapp/app/styles/components/operations-peek/item.scss similarity index 93% rename from webapp/app/pods/components/operations-peek/item/styles.scss rename to webapp/app/styles/components/operations-peek/item.scss index 68cf9d5c9..b83efd6b9 100644 --- a/webapp/app/pods/components/operations-peek/item/styles.scss +++ b/webapp/app/styles/components/operations-peek/item.scss @@ -11,7 +11,9 @@ color: var(--color-black); &:focus { - box-shadow: inset 0 1px 2px rgba(#000, 0.1), 0 1px 2px var(--shadow-color); + box-shadow: + inset 0 1px 2px rgba(#000, 0.1), + 0 1px 2px var(--shadow-color); } &::placeholder { diff --git a/webapp/app/pods/components/page-title/styles.scss b/webapp/app/styles/components/page-title.scss similarity index 100% rename from webapp/app/pods/components/page-title/styles.scss rename to webapp/app/styles/components/page-title.scss diff --git a/webapp/app/pods/components/page-title/end/styles.scss b/webapp/app/styles/components/page-title/end.scss similarity index 100% rename from webapp/app/pods/components/page-title/end/styles.scss rename to webapp/app/styles/components/page-title/end.scss diff --git a/webapp/app/pods/components/project-activities-filter/styles.scss b/webapp/app/styles/components/project-activities-filter.scss similarity index 100% rename from webapp/app/pods/components/project-activities-filter/styles.scss rename to webapp/app/styles/components/project-activities-filter.scss diff --git a/webapp/app/pods/components/project-activities-list/styles.scss b/webapp/app/styles/components/project-activities-list.scss similarity index 100% rename from webapp/app/pods/components/project-activities-list/styles.scss rename to webapp/app/styles/components/project-activities-list.scss diff --git a/webapp/app/pods/components/project-activity/styles.scss b/webapp/app/styles/components/project-activity.scss similarity index 95% rename from webapp/app/pods/components/project-activity/styles.scss rename to webapp/app/styles/components/project-activity.scss index 5c255bd57..4e64c8082 100644 --- a/webapp/app/pods/components/project-activity/styles.scss +++ b/webapp/app/styles/components/project-activity.scss @@ -68,12 +68,6 @@ color: var(--color-primary); } -.details-associations-overflow { - max-height: 400px; - overflow-y: scroll; - margin-top: -12px; -} - .details-associations-pagination { border-top: 1px solid var(--content-background-border); } @@ -96,7 +90,9 @@ margin-right: 20px; padding: 13px; background: var(--content-background); - box-shadow: 0 1px 2px var(--shadow-color), 0 5px 10px var(--shadow-color); + box-shadow: + 0 1px 2px var(--shadow-color), + 0 5px 10px var(--shadow-color); border-radius: var(--border-radius); } diff --git a/webapp/app/pods/components/project-comments-list/styles.scss b/webapp/app/styles/components/project-comments-list.scss similarity index 100% rename from webapp/app/pods/components/project-comments-list/styles.scss rename to webapp/app/styles/components/project-comments-list.scss diff --git a/webapp/app/pods/components/project-comments-list/item/styles.scss b/webapp/app/styles/components/project-comments-list/item.scss similarity index 100% rename from webapp/app/pods/components/project-comments-list/item/styles.scss rename to webapp/app/styles/components/project-comments-list/item.scss diff --git a/webapp/app/pods/components/project-create-form/styles.scss b/webapp/app/styles/components/project-create-form.scss similarity index 98% rename from webapp/app/pods/components/project-create-form/styles.scss rename to webapp/app/styles/components/project-create-form.scss index a3dfa51c8..05aecd27d 100644 --- a/webapp/app/pods/components/project-create-form/styles.scss +++ b/webapp/app/styles/components/project-create-form.scss @@ -41,10 +41,10 @@ .colorInput { @extend %textInput; - width: 48px; margin-right: 5px; + width: 48px; height: 40px; - padding: 10px 14px; + padding: 5px 11px; cursor: pointer; } diff --git a/webapp/app/pods/components/project-file-operation/styles.scss b/webapp/app/styles/components/project-file-operation.scss similarity index 100% rename from webapp/app/pods/components/project-file-operation/styles.scss rename to webapp/app/styles/components/project-file-operation.scss diff --git a/webapp/app/pods/components/project-header/styles.scss b/webapp/app/styles/components/project-header.scss similarity index 100% rename from webapp/app/pods/components/project-header/styles.scss rename to webapp/app/styles/components/project-header.scss diff --git a/webapp/app/pods/components/project-navigation/styles.scss b/webapp/app/styles/components/project-navigation.scss similarity index 87% rename from webapp/app/pods/components/project-navigation/styles.scss rename to webapp/app/styles/components/project-navigation.scss index 9c7ec920d..092ae92ea 100644 --- a/webapp/app/pods/components/project-navigation/styles.scss +++ b/webapp/app/styles/components/project-navigation.scss @@ -40,16 +40,16 @@ } .project { - padding: 20px 0 20px 16px; + padding: 20px 10px 20px 16px; margin-left: 0; position: relative; display: flex; - align-items: flex-start; - font-size: 18px; + align-items: center; + font-size: 15px; font-weight: 700; color: var(--color-black); text-decoration: none; - line-height: 1; + line-height: 1.2; } .project-logo { @@ -59,13 +59,11 @@ top: 2px; font-size: 22px; margin-right: 10px; - line-height: 1.1; + line-height: 1.2; svg { - position: relative; - top: -2px; - width: 25px; - height: 25px; + width: 22px; + height: 22px; circle { fill: var(--logo-background); diff --git a/webapp/app/pods/components/project-navigation/list/styles.scss b/webapp/app/styles/components/project-navigation/list.scss similarity index 95% rename from webapp/app/pods/components/project-navigation/list/styles.scss rename to webapp/app/styles/components/project-navigation/list.scss index af1ac5c7b..c98a82277 100644 --- a/webapp/app/pods/components/project-navigation/list/styles.scss +++ b/webapp/app/styles/components/project-navigation/list.scss @@ -34,7 +34,7 @@ } :global([data-theme='dark']) .list-item-link:global(.active) { - color: rgba(255, 255, 255, 0.4); + color: var(--color-primary); } .list-item-link { @@ -43,11 +43,10 @@ position: relative; gap: 10px; left: 1px; - padding: 5px 12px 4px; + padding: 7px 12px 6px; text-decoration: none; font-size: 13px; border-radius: var(--border-radius); - margin-bottom: 3px; color: var(--text-color-normal); &:hover, diff --git a/webapp/app/pods/components/project-settings/api-token/styles.scss b/webapp/app/styles/components/project-settings/api-token.scss similarity index 100% rename from webapp/app/pods/components/project-settings/api-token/styles.scss rename to webapp/app/styles/components/project-settings/api-token.scss diff --git a/webapp/app/pods/components/project-settings/api-token/item/styles.scss b/webapp/app/styles/components/project-settings/api-token/item.scss similarity index 100% rename from webapp/app/pods/components/project-settings/api-token/item/styles.scss rename to webapp/app/styles/components/project-settings/api-token/item.scss diff --git a/webapp/app/pods/components/project-settings/back-link/styles.scss b/webapp/app/styles/components/project-settings/back-link.scss similarity index 100% rename from webapp/app/pods/components/project-settings/back-link/styles.scss rename to webapp/app/styles/components/project-settings/back-link.scss diff --git a/webapp/app/pods/components/project-settings/badges/styles.scss b/webapp/app/styles/components/project-settings/badges.scss similarity index 100% rename from webapp/app/pods/components/project-settings/badges/styles.scss rename to webapp/app/styles/components/project-settings/badges.scss diff --git a/webapp/app/pods/components/project-settings/collaborators/styles.scss b/webapp/app/styles/components/project-settings/collaborators.scss similarity index 88% rename from webapp/app/pods/components/project-settings/collaborators/styles.scss rename to webapp/app/styles/components/project-settings/collaborators.scss index c9e842803..cf8503fb1 100644 --- a/webapp/app/pods/components/project-settings/collaborators/styles.scss +++ b/webapp/app/styles/components/project-settings/collaborators.scss @@ -28,8 +28,15 @@ border-left: 1px solid var(--background-light-highlight); } +.rolesList-icon { + width: 13px; + height: 13px; +} + .rolesList-title { - display: block; + display: flex; + align-items: center; + gap: 5px; padding-bottom: 5px; margin: 15px 0 0; color: var(--color-primary); diff --git a/webapp/app/pods/components/project-settings/collaborators/create-form/styles.scss b/webapp/app/styles/components/project-settings/collaborators/create-form.scss similarity index 100% rename from webapp/app/pods/components/project-settings/collaborators/create-form/styles.scss rename to webapp/app/styles/components/project-settings/collaborators/create-form.scss diff --git a/webapp/app/pods/components/project-settings/collaborators/list/item/styles.scss b/webapp/app/styles/components/project-settings/collaborators/list/item.scss similarity index 100% rename from webapp/app/pods/components/project-settings/collaborators/list/item/styles.scss rename to webapp/app/styles/components/project-settings/collaborators/list/item.scss diff --git a/webapp/app/pods/components/project-settings/delete-form/styles.scss b/webapp/app/styles/components/project-settings/delete-form.scss similarity index 100% rename from webapp/app/pods/components/project-settings/delete-form/styles.scss rename to webapp/app/styles/components/project-settings/delete-form.scss diff --git a/webapp/app/pods/components/project-settings/form/styles.scss b/webapp/app/styles/components/project-settings/form.scss similarity index 96% rename from webapp/app/pods/components/project-settings/form/styles.scss rename to webapp/app/styles/components/project-settings/form.scss index 9d9b947e9..9c8acc882 100644 --- a/webapp/app/pods/components/project-settings/form/styles.scss +++ b/webapp/app/styles/components/project-settings/form.scss @@ -6,7 +6,6 @@ @extend %textInput; max-width: 350px; width: 100%; - margin-right: 5px; flex-grow: 0; flex-shrink: 1; padding: 10px; @@ -16,15 +15,15 @@ .colorInput { @extend %textInput; - margin-right: 5px; width: 48px; height: 40px; - padding: 10px 14px; + padding: 5px 11px; } .field { display: flex; margin-bottom: 15px; + gap: 8px; } .lock { diff --git a/webapp/app/pods/components/project-settings/integrations/styles.scss b/webapp/app/styles/components/project-settings/integrations.scss similarity index 87% rename from webapp/app/pods/components/project-settings/integrations/styles.scss rename to webapp/app/styles/components/project-settings/integrations.scss index 418615754..da8d07888 100644 --- a/webapp/app/pods/components/project-settings/integrations/styles.scss +++ b/webapp/app/styles/components/project-settings/integrations.scss @@ -23,7 +23,7 @@ .empty-description { display: grid; - grid-template-columns: 1fr 1fr 1fr; + grid-template-columns: 1fr 1fr 1fr 1fr; gap: 30px; margin-top: 20px; } @@ -35,6 +35,7 @@ text-align: center; border: 1px solid var(--background-light-highlight); background: var(--background-light); + color: var(--text-color-normal); border-radius: var(--border-radius); padding: 20px 30px; gap: 2px; @@ -53,7 +54,9 @@ &:focus, &:hover { - box-shadow: 0 1px 6px var(--shadow-color), 0 2px 19px var(--shadow-color); + box-shadow: + 0 1px 6px var(--shadow-color), + 0 2px 19px var(--shadow-color); } } @@ -70,7 +73,7 @@ color: var(--color-black); } -@media (max-width: 940px) { +@media (max-width: 1140px) { .empty-description { grid-template-columns: 1fr 1fr; gap: 15px; diff --git a/webapp/app/pods/components/project-settings/integrations/form/styles.scss b/webapp/app/styles/components/project-settings/integrations/form.scss similarity index 100% rename from webapp/app/pods/components/project-settings/integrations/form/styles.scss rename to webapp/app/styles/components/project-settings/integrations/form.scss diff --git a/webapp/app/styles/components/project-settings/integrations/form/aws-s3.scss b/webapp/app/styles/components/project-settings/integrations/form/aws-s3.scss new file mode 100644 index 000000000..7984b260b --- /dev/null +++ b/webapp/app/styles/components/project-settings/integrations/form/aws-s3.scss @@ -0,0 +1,32 @@ +.container { + display: flex; + align-items: flex-start; + gap: 15px; +} + +.form { + width: 100%; + max-width: 400px; +} + +.policy { + width: 100%; +} + +.policy-title { + display: block; + font-weight: bold; + font-size: 13px; + margin-bottom: 6px; +} +.policy-render { + background: var(--content-background); + border: 1px solid var(--background-light-highlight); + border-radius: var(--border-radius); +} + +@media (max-width: 600px) { + .container { + flex-wrap: wrap; + } +} diff --git a/webapp/app/pods/components/project-settings/integrations/form/data-control-checkboxes/styles.scss b/webapp/app/styles/components/project-settings/integrations/form/data-control-checkboxes.scss similarity index 100% rename from webapp/app/pods/components/project-settings/integrations/form/data-control-checkboxes/styles.scss rename to webapp/app/styles/components/project-settings/integrations/form/data-control-checkboxes.scss diff --git a/webapp/app/pods/components/project-settings/integrations/form/data-control-text/styles.scss b/webapp/app/styles/components/project-settings/integrations/form/data-control-text.scss similarity index 97% rename from webapp/app/pods/components/project-settings/integrations/form/data-control-text/styles.scss rename to webapp/app/styles/components/project-settings/integrations/form/data-control-text.scss index 1b6c57e51..3e5c5cfff 100644 --- a/webapp/app/pods/components/project-settings/integrations/form/data-control-text/styles.scss +++ b/webapp/app/styles/components/project-settings/integrations/form/data-control-text.scss @@ -1,5 +1,5 @@ .data-control { - margin-bottom: 15px; + margin-bottom: 10px; } .data-title { diff --git a/webapp/app/pods/components/project-settings/integrations/list/styles.scss b/webapp/app/styles/components/project-settings/integrations/list.scss similarity index 100% rename from webapp/app/pods/components/project-settings/integrations/list/styles.scss rename to webapp/app/styles/components/project-settings/integrations/list.scss diff --git a/webapp/app/pods/components/project-settings/integrations/list/item/styles.scss b/webapp/app/styles/components/project-settings/integrations/list/item.scss similarity index 100% rename from webapp/app/pods/components/project-settings/integrations/list/item/styles.scss rename to webapp/app/styles/components/project-settings/integrations/list/item.scss diff --git a/webapp/app/styles/components/project-settings/integrations/list/item/execute/aws-s3.scss b/webapp/app/styles/components/project-settings/integrations/list/item/execute/aws-s3.scss new file mode 100644 index 000000000..f199956c1 --- /dev/null +++ b/webapp/app/styles/components/project-settings/integrations/list/item/execute/aws-s3.scss @@ -0,0 +1,103 @@ +.aws-push-form { + padding: 20px; + background: var(--content-background); +} + +.title { + margin-bottom: 20px; + text-align: center; + line-height: 1.2; + font-size: 27px; + font-weight: 300; + color: var(--color-primary); +} + +.info { + display: flex; + flex-direction: column; + gap: 10px; + margin-bottom: 10px; + padding-bottom: 16px; + border-bottom: 1px solid var(--background-light-highlight); + font-size: 13px; + + div { + display: flex; + flex-direction: column; + gap: 2px; + } + + span { + font-size: 12px; + font-family: var(--font-monospace); + opacity: 0.6; + } +} + +.text { + font-size: 13px; + margin-bottom: 20px; + color: #555; +} + +.textInput { + @extend %textInput; + flex-grow: 1; + flex-shrink: 1; + padding: 10px; + min-width: 250px; + width: 100%; + font-size: 12px; + font-family: var(--font-primary); +} + +.errors { + margin-bottom: 15px; + padding-bottom: 5px; +} + +.error { + margin-bottom: 5px; + color: var(--color-error); + font-size: 13px; + font-weight: bold; +} + +.formActions { + display: flex; + justify-content: flex-end; + padding-top: 20px; +} + +.data-control { + .radio { + display: inline-flex; + align-items: center; + margin-right: 10px; + border: 1px solid var(--background-light-highlight); + padding: 4px 6px; + border-radius: var(--border-radius); + background: var(--input-background); + cursor: pointer; + font-size: 12px; + transition: 0.2s ease-in-out; + transition-property: background; + + &:hover, + &:focus { + background: var(--background-light); + } + + input { + margin-right: 5px; + cursor: pointer; + } + } +} + +.data-title { + display: block; + margin-bottom: 5px; + font-size: 13px; + font-weight: bold; +} diff --git a/webapp/app/pods/components/project-settings/integrations/list/item/execute/azure-storage-container/styles.scss b/webapp/app/styles/components/project-settings/integrations/list/item/execute/azure-storage-container.scss similarity index 100% rename from webapp/app/pods/components/project-settings/integrations/list/item/execute/azure-storage-container/styles.scss rename to webapp/app/styles/components/project-settings/integrations/list/item/execute/azure-storage-container.scss diff --git a/webapp/app/pods/components/project-settings/jipt/styles.scss b/webapp/app/styles/components/project-settings/jipt.scss similarity index 90% rename from webapp/app/pods/components/project-settings/jipt/styles.scss rename to webapp/app/styles/components/project-settings/jipt.scss index 9dd93c893..4e39008b8 100644 --- a/webapp/app/pods/components/project-settings/jipt/styles.scss +++ b/webapp/app/styles/components/project-settings/jipt.scss @@ -1,5 +1,12 @@ .project-settings-jipt { margin-top: 30px; + + hr { + margin: 20px 0; + border: 0; + height: 1px; + background: var(--background-light-highlight); + } } .text { diff --git a/webapp/app/pods/components/project-settings/links-list/styles.scss b/webapp/app/styles/components/project-settings/links-list.scss similarity index 85% rename from webapp/app/pods/components/project-settings/links-list/styles.scss rename to webapp/app/styles/components/project-settings/links-list.scss index 5271851e7..81fc2a22a 100644 --- a/webapp/app/pods/components/project-settings/links-list/styles.scss +++ b/webapp/app/styles/components/project-settings/links-list.scss @@ -19,12 +19,15 @@ background: var(--content-background); border-radius: var(--border-radius); color: var(--color-black); - box-shadow: 0 1px 4px var(--shadow-color), 0 9px 19px var(--shadow-color); + box-shadow: + 0 1px 4px var(--shadow-color), + 0 9px 19px var(--shadow-color); text-decoration: none; font-weight: 600; font-size: 13px; transition: 0.2s ease-in-out; transition-property: background, box-shadow, color, transform; + overflow: hidden; strong { padding: 10px 20px 5px; @@ -33,9 +36,10 @@ p { display: block; width: 100%; - padding: 10px 20px; + padding: 10px 20px 10px 19px; margin-top: 10px; font-size: 11px; + font-weight: 400; border-top: 1px solid var(--content-background-border); color: var(--color-grey); background: var(--background-light); @@ -46,7 +50,9 @@ &:focus, &:hover { color: var(--color-primary); - box-shadow: 0 3px 8px var(--shadow-color), 0 9px 12px var(--shadow-color); + box-shadow: + 0 3px 8px var(--shadow-color), + 0 9px 12px var(--shadow-color); transform: scale(1.02); .link-check { @@ -60,6 +66,10 @@ height: 14px; } +.link-check-text { + font-size: 11px; +} + .link-check { position: absolute; top: 7px; @@ -75,12 +85,12 @@ } .link-icon { - width: 20px; - height: 20px; + width: 30px; + height: 30px; margin: 20px 20px 0; transition: 0.2s ease-in-out; transition-property: stroke; - opacity: 0.6; + opacity: 0.8; stroke: var(--color-black); transition: 0.2s ease-in-out; transition-property: stroke; diff --git a/webapp/app/pods/components/project-settings/machine-translations/styles.scss b/webapp/app/styles/components/project-settings/machine-translations.scss similarity index 100% rename from webapp/app/pods/components/project-settings/machine-translations/styles.scss rename to webapp/app/styles/components/project-settings/machine-translations.scss diff --git a/webapp/app/pods/components/project-settings/manage-languages/styles.scss b/webapp/app/styles/components/project-settings/manage-languages.scss similarity index 100% rename from webapp/app/pods/components/project-settings/manage-languages/styles.scss rename to webapp/app/styles/components/project-settings/manage-languages.scss diff --git a/webapp/app/pods/components/project-settings/manage-languages/create-form/styles.scss b/webapp/app/styles/components/project-settings/manage-languages/create-form.scss similarity index 83% rename from webapp/app/pods/components/project-settings/manage-languages/create-form/styles.scss rename to webapp/app/styles/components/project-settings/manage-languages/create-form.scss index d9ab3ecbd..8eec7d755 100644 --- a/webapp/app/pods/components/project-settings/manage-languages/create-form/styles.scss +++ b/webapp/app/styles/components/project-settings/manage-languages/create-form.scss @@ -34,7 +34,11 @@ } .optionLabel-icon { - width: 15px; + width: 22px; margin-left: 3px; transform: rotate(45deg); + background: var(--color-primary-opacity-25); + border-radius: 50%; + padding: 3px; + color: var(--color-primary); } diff --git a/webapp/app/pods/components/project-settings/manage-languages/overview/styles.scss b/webapp/app/styles/components/project-settings/manage-languages/overview.scss similarity index 100% rename from webapp/app/pods/components/project-settings/manage-languages/overview/styles.scss rename to webapp/app/styles/components/project-settings/manage-languages/overview.scss diff --git a/webapp/app/pods/components/project-settings/manage-languages/overview/item/styles.scss b/webapp/app/styles/components/project-settings/manage-languages/overview/item.scss similarity index 100% rename from webapp/app/pods/components/project-settings/manage-languages/overview/item/styles.scss rename to webapp/app/styles/components/project-settings/manage-languages/overview/item.scss diff --git a/webapp/app/pods/components/project-settings/prompts/styles.scss b/webapp/app/styles/components/project-settings/prompts.scss similarity index 78% rename from webapp/app/pods/components/project-settings/prompts/styles.scss rename to webapp/app/styles/components/project-settings/prompts.scss index d29a65808..c165870d8 100644 --- a/webapp/app/pods/components/project-settings/prompts/styles.scss +++ b/webapp/app/styles/components/project-settings/prompts.scss @@ -1,11 +1,11 @@ .wrapper { display: flex; + flex-direction: column; margin-top: 25px; } .content { - flex: 1 1 auto; - padding-right: 30px; + margin-top: 20px; } .list { @@ -13,10 +13,10 @@ flex-direction: column; gap: 10px; margin-bottom: 20px; + max-width: 450px; } .config { - flex: 0 1 auto; max-width: 450px; width: 100%; } @@ -30,5 +30,5 @@ .text { display: block; font-size: 13px; - padding-bottom: 22px; + margin-bottom: 12px; } diff --git a/webapp/app/pods/components/project-settings/prompts/config/styles.scss b/webapp/app/styles/components/project-settings/prompts/config.scss similarity index 83% rename from webapp/app/pods/components/project-settings/prompts/config/styles.scss rename to webapp/app/styles/components/project-settings/prompts/config.scss index 54fe10c81..04b3d1ce4 100644 --- a/webapp/app/pods/components/project-settings/prompts/config/styles.scss +++ b/webapp/app/styles/components/project-settings/prompts/config.scss @@ -1,5 +1,4 @@ .form { - margin-top: 25px; padding: 16px; border-radius: var(--border-radius); background: var(--background-light); @@ -31,7 +30,6 @@ } .select select { - background: transparent; border: 1px solid var(--background-light-highlight); padding: 7px 10px; font-weight: bold; @@ -67,9 +65,25 @@ font-size: 12px; } +.options { + margin: 10px 0 0; + display: flex; + flex-direction: column; + gap: 5px; +} + +.option-checkbox { + display: flex; + align-items: center; + width: 100%; + gap: 8px; + font-size: 12px; + font-weight: bold; +} + .actions { display: flex; justify-content: flex-end; gap: 12px; - margin-top: 20px; + margin-top: 6px; } diff --git a/webapp/app/pods/components/project-settings/prompts/item/styles.scss b/webapp/app/styles/components/project-settings/prompts/item.scss similarity index 100% rename from webapp/app/pods/components/project-settings/prompts/item/styles.scss rename to webapp/app/styles/components/project-settings/prompts/item.scss diff --git a/webapp/app/pods/components/project-settings/title/styles.scss b/webapp/app/styles/components/project-settings/title.scss similarity index 100% rename from webapp/app/pods/components/project-settings/title/styles.scss rename to webapp/app/styles/components/project-settings/title.scss diff --git a/webapp/app/pods/components/projects-filters/styles.scss b/webapp/app/styles/components/projects-filters.scss similarity index 97% rename from webapp/app/pods/components/projects-filters/styles.scss rename to webapp/app/styles/components/projects-filters.scss index 8f332d19a..374eb1733 100644 --- a/webapp/app/pods/components/projects-filters/styles.scss +++ b/webapp/app/styles/components/projects-filters.scss @@ -1,4 +1,4 @@ -div.filters { +.filters:global(.filters) { margin: 20px auto 0; padding: 0 20px; max-width: var(--screen-lg); diff --git a/webapp/app/pods/components/projects-header/styles.scss b/webapp/app/styles/components/projects-header.scss similarity index 100% rename from webapp/app/pods/components/projects-header/styles.scss rename to webapp/app/styles/components/projects-header.scss diff --git a/webapp/app/pods/components/projects-list/styles.scss b/webapp/app/styles/components/projects-list.scss similarity index 91% rename from webapp/app/pods/components/projects-list/styles.scss rename to webapp/app/styles/components/projects-list.scss index 2c924a8b9..025a0c18d 100644 --- a/webapp/app/pods/components/projects-list/styles.scss +++ b/webapp/app/styles/components/projects-list.scss @@ -8,8 +8,8 @@ } .item { - flex: 1 1 calc(50% - 10px); - max-width: 50%; + flex: 1 1 calc(33.3% - 10px); + max-width: 33.3%; } .item-link { diff --git a/webapp/app/pods/components/projects-list/item/styles.scss b/webapp/app/styles/components/projects-list/item.scss similarity index 58% rename from webapp/app/pods/components/projects-list/item/styles.scss rename to webapp/app/styles/components/projects-list/item.scss index b6599678e..4a2b93c67 100644 --- a/webapp/app/pods/components/projects-list/item/styles.scss +++ b/webapp/app/styles/components/projects-list/item.scss @@ -1,37 +1,7 @@ -.projects-list-item.low-percentage { - .language-reviewedPercentage { - color: var(--color-error); - } - - .progress { - color: var(--color-error); - } -} - -.projects-list-item.medium-percentage { - .language-reviewedPercentage { - color: var(--color-warning); - } - - .progress { - color: var(--color-warning); - } -} - -.projects-list-item.high-percentage { - .language-reviewedPercentage { - color: var(--color-success); - } - - .progress { - color: var(--color-success); - } -} - .projects-list-item { padding: 12px 15px; transition: 0.2s ease-in-out; - transition-property: box-shadow; + transition-property: box-shadow, border-color; border-radius: var(--border-radius); border: 1px solid var(--content-background-border); background: var(--content-background); @@ -39,6 +9,14 @@ &:focus, &:hover { + box-shadow: 0 4px 15px var(--shadow-color); + border-color: color-mix(in srgb, var(--color-primary) 20%, transparent); + border-bottom-color: color-mix( + in srgb, + var(--color-primary) 25%, + transparent + ); + .projectName { color: var(--color-primary); } @@ -87,12 +65,4 @@ display: flex; justify-content: space-between; align-items: center; - margin-bottom: 6px; -} - -.numberStat-totals { - padding: 2px 0 1px 7px; - color: var(--color-black); - font-size: 12px; - font-family: var(--font-monospace); } diff --git a/webapp/app/pods/components/prompt-create-form/styles.scss b/webapp/app/styles/components/prompt-create-form.scss similarity index 93% rename from webapp/app/pods/components/prompt-create-form/styles.scss rename to webapp/app/styles/components/prompt-create-form.scss index 10cab4a86..1aa312bb1 100644 --- a/webapp/app/pods/components/prompt-create-form/styles.scss +++ b/webapp/app/styles/components/prompt-create-form.scss @@ -25,7 +25,8 @@ .quickAccess-picker-empty { width: 23px; - opacity: 0.2; + opacity: 0.7; + color: var(--text-color-normal); } .quickAccess-picker-remove { @@ -37,6 +38,7 @@ top: 0; opacity: 0.5; padding: 0; + color: var(--text-color-normal); } .quickAccess-picker-remove-icon { width: 13px; diff --git a/webapp/app/pods/components/prompt-update-form/styles.scss b/webapp/app/styles/components/prompt-update-form.scss similarity index 93% rename from webapp/app/pods/components/prompt-update-form/styles.scss rename to webapp/app/styles/components/prompt-update-form.scss index 6fabcc981..9f38c2d8c 100644 --- a/webapp/app/pods/components/prompt-update-form/styles.scss +++ b/webapp/app/styles/components/prompt-update-form.scss @@ -25,7 +25,8 @@ .quickAccess-picker-empty { width: 23px; - opacity: 0.2; + opacity: 0.7; + color: var(--text-color-normal); } .quickAccess-picker-remove { @@ -37,6 +38,7 @@ top: 0; opacity: 0.5; padding: 0; + color: var(--text-color-normal); } .quickAccess-picker-remove-icon { width: 13px; diff --git a/webapp/app/pods/components/recent-projects-list/styles.scss b/webapp/app/styles/components/recent-projects-list.scss similarity index 89% rename from webapp/app/pods/components/recent-projects-list/styles.scss rename to webapp/app/styles/components/recent-projects-list.scss index 88c714bf1..de696c494 100644 --- a/webapp/app/pods/components/recent-projects-list/styles.scss +++ b/webapp/app/styles/components/recent-projects-list.scss @@ -23,12 +23,11 @@ .item-link { display: block; - padding: 4px 10px 5px; - background: var(--background-light); + padding: 3px 8px 4px; + border: 1px solid var(--background-light-highlight); border-radius: var(--border-radius); text-decoration: none; font-weight: 600; - box-shadow: 0 1px 2px var(--shadow-color); transition: 0.2s ease-in-out; transition-property: background, box-shadow; diff --git a/webapp/app/pods/components/recent-projects-list/item/styles.scss b/webapp/app/styles/components/recent-projects-list/item.scss similarity index 100% rename from webapp/app/pods/components/recent-projects-list/item/styles.scss rename to webapp/app/styles/components/recent-projects-list/item.scss diff --git a/webapp/app/pods/components/related-translations-list/styles.scss b/webapp/app/styles/components/related-translations-list.scss similarity index 100% rename from webapp/app/pods/components/related-translations-list/styles.scss rename to webapp/app/styles/components/related-translations-list.scss diff --git a/webapp/app/pods/components/related-translations-list/item/styles.scss b/webapp/app/styles/components/related-translations-list/item.scss similarity index 100% rename from webapp/app/pods/components/related-translations-list/item/styles.scss rename to webapp/app/styles/components/related-translations-list/item.scss diff --git a/webapp/app/pods/components/removed-translation-edit/styles.scss b/webapp/app/styles/components/removed-translation-edit.scss similarity index 100% rename from webapp/app/pods/components/removed-translation-edit/styles.scss rename to webapp/app/styles/components/removed-translation-edit.scss diff --git a/webapp/app/pods/components/resource-pagination/styles.scss b/webapp/app/styles/components/resource-pagination.scss similarity index 100% rename from webapp/app/pods/components/resource-pagination/styles.scss rename to webapp/app/styles/components/resource-pagination.scss diff --git a/webapp/app/pods/components/review-progress-bar/styles.scss b/webapp/app/styles/components/review-progress-bar.scss similarity index 100% rename from webapp/app/pods/components/review-progress-bar/styles.scss rename to webapp/app/styles/components/review-progress-bar.scss diff --git a/webapp/app/pods/components/revision-export-options/styles.scss b/webapp/app/styles/components/revision-export-options.scss similarity index 97% rename from webapp/app/pods/components/revision-export-options/styles.scss rename to webapp/app/styles/components/revision-export-options.scss index 7d1a7d65b..77ffd3c5c 100644 --- a/webapp/app/pods/components/revision-export-options/styles.scss +++ b/webapp/app/styles/components/revision-export-options.scss @@ -7,6 +7,7 @@ .exportOptions { display: flex; justify-content: space-between; + width: 100%; } .exportOptions-advancedFilters { diff --git a/webapp/app/pods/components/revision-export-options/advanced-filters/styles.scss b/webapp/app/styles/components/revision-export-options/advanced-filters.scss similarity index 100% rename from webapp/app/pods/components/revision-export-options/advanced-filters/styles.scss rename to webapp/app/styles/components/revision-export-options/advanced-filters.scss diff --git a/webapp/app/pods/components/revision-selector/styles.scss b/webapp/app/styles/components/revision-selector.scss similarity index 88% rename from webapp/app/pods/components/revision-selector/styles.scss rename to webapp/app/styles/components/revision-selector.scss index dd7a96127..fecd744ca 100644 --- a/webapp/app/pods/components/revision-selector/styles.scss +++ b/webapp/app/styles/components/revision-selector.scss @@ -2,6 +2,14 @@ position: relative; margin-bottom: 15px; + &.revision-selector--jipt { + margin-bottom: 0; + + .overlay { + border-radius: 0; + } + } + select { padding: 10px 10px 10px 7px; padding-bottom: 25px; diff --git a/webapp/app/pods/components/revision-update-form/styles.scss b/webapp/app/styles/components/revision-update-form.scss similarity index 100% rename from webapp/app/pods/components/revision-update-form/styles.scss rename to webapp/app/styles/components/revision-update-form.scss diff --git a/webapp/app/pods/components/skeleton-ui/styles.scss b/webapp/app/styles/components/skeleton-ui.scss similarity index 100% rename from webapp/app/pods/components/skeleton-ui/styles.scss rename to webapp/app/styles/components/skeleton-ui.scss diff --git a/webapp/app/pods/components/skeleton-ui/activities-list/styles.scss b/webapp/app/styles/components/skeleton-ui/activities-list.scss similarity index 100% rename from webapp/app/pods/components/skeleton-ui/activities-list/styles.scss rename to webapp/app/styles/components/skeleton-ui/activities-list.scss diff --git a/webapp/app/pods/components/skeleton-ui/conflicts-items/styles.scss b/webapp/app/styles/components/skeleton-ui/conflicts-items.scss similarity index 100% rename from webapp/app/pods/components/skeleton-ui/conflicts-items/styles.scss rename to webapp/app/styles/components/skeleton-ui/conflicts-items.scss diff --git a/webapp/app/pods/components/skeleton-ui/documents-list/styles.scss b/webapp/app/styles/components/skeleton-ui/documents-list.scss similarity index 100% rename from webapp/app/pods/components/skeleton-ui/documents-list/styles.scss rename to webapp/app/styles/components/skeleton-ui/documents-list.scss diff --git a/webapp/app/pods/components/skeleton-ui/progress-line/styles.scss b/webapp/app/styles/components/skeleton-ui/progress-line.scss similarity index 100% rename from webapp/app/pods/components/skeleton-ui/progress-line/styles.scss rename to webapp/app/styles/components/skeleton-ui/progress-line.scss diff --git a/webapp/app/pods/components/skeleton-ui/project-activities-filter/styles.scss b/webapp/app/styles/components/skeleton-ui/project-activities-filter.scss similarity index 100% rename from webapp/app/pods/components/skeleton-ui/project-activities-filter/styles.scss rename to webapp/app/styles/components/skeleton-ui/project-activities-filter.scss diff --git a/webapp/app/pods/components/skeleton-ui/project-comments-list/styles.scss b/webapp/app/styles/components/skeleton-ui/project-comments-list.scss similarity index 100% rename from webapp/app/pods/components/skeleton-ui/project-comments-list/styles.scss rename to webapp/app/styles/components/skeleton-ui/project-comments-list.scss diff --git a/webapp/app/pods/components/skeleton-ui/project-navigation/styles.scss b/webapp/app/styles/components/skeleton-ui/project-navigation.scss similarity index 100% rename from webapp/app/pods/components/skeleton-ui/project-navigation/styles.scss rename to webapp/app/styles/components/skeleton-ui/project-navigation.scss diff --git a/webapp/app/pods/components/skeleton-ui/translation-comments-list/styles.scss b/webapp/app/styles/components/skeleton-ui/translation-comments-list.scss similarity index 100% rename from webapp/app/pods/components/skeleton-ui/translation-comments-list/styles.scss rename to webapp/app/styles/components/skeleton-ui/translation-comments-list.scss diff --git a/webapp/app/pods/components/skeleton-ui/translation-splash-title/styles.scss b/webapp/app/styles/components/skeleton-ui/translation-splash-title.scss similarity index 100% rename from webapp/app/pods/components/skeleton-ui/translation-splash-title/styles.scss rename to webapp/app/styles/components/skeleton-ui/translation-splash-title.scss diff --git a/webapp/app/pods/components/skeleton-ui/translations-list/styles.scss b/webapp/app/styles/components/skeleton-ui/translations-list.scss similarity index 100% rename from webapp/app/pods/components/skeleton-ui/translations-list/styles.scss rename to webapp/app/styles/components/skeleton-ui/translations-list.scss diff --git a/webapp/app/pods/components/skeleton-ui/versions-list/styles.scss b/webapp/app/styles/components/skeleton-ui/versions-list.scss similarity index 100% rename from webapp/app/pods/components/skeleton-ui/versions-list/styles.scss rename to webapp/app/styles/components/skeleton-ui/versions-list.scss diff --git a/webapp/app/pods/components/translation-activities-list/styles.scss b/webapp/app/styles/components/translation-activities-list.scss similarity index 100% rename from webapp/app/pods/components/translation-activities-list/styles.scss rename to webapp/app/styles/components/translation-activities-list.scss diff --git a/webapp/app/pods/components/translation-comment-delete/styles.scss b/webapp/app/styles/components/translation-comment-delete.scss similarity index 100% rename from webapp/app/pods/components/translation-comment-delete/styles.scss rename to webapp/app/styles/components/translation-comment-delete.scss diff --git a/webapp/app/pods/components/translation-comment-form/styles.scss b/webapp/app/styles/components/translation-comment-form.scss similarity index 100% rename from webapp/app/pods/components/translation-comment-form/styles.scss rename to webapp/app/styles/components/translation-comment-form.scss diff --git a/webapp/app/pods/components/translation-comments-list/styles.scss b/webapp/app/styles/components/translation-comments-list.scss similarity index 89% rename from webapp/app/pods/components/translation-comments-list/styles.scss rename to webapp/app/styles/components/translation-comments-list.scss index 0184ffacc..6bac29eb4 100644 --- a/webapp/app/pods/components/translation-comments-list/styles.scss +++ b/webapp/app/styles/components/translation-comments-list.scss @@ -1,6 +1,8 @@ .translation-comments-list { position: relative; - box-shadow: 0 1px 4px var(--shadow-color), 0 9px 19px var(--shadow-color); + box-shadow: + 0 1px 4px var(--shadow-color), + 0 9px 19px var(--shadow-color); background: var(--background-light); border-radius: var(--border-radius); } diff --git a/webapp/app/pods/components/translation-comments-list/item/styles.scss b/webapp/app/styles/components/translation-comments-list/item.scss similarity index 100% rename from webapp/app/pods/components/translation-comments-list/item/styles.scss rename to webapp/app/styles/components/translation-comments-list/item.scss diff --git a/webapp/app/pods/components/translation-comments-subscriptions/styles.scss b/webapp/app/styles/components/translation-comments-subscriptions.scss similarity index 100% rename from webapp/app/pods/components/translation-comments-subscriptions/styles.scss rename to webapp/app/styles/components/translation-comments-subscriptions.scss diff --git a/webapp/app/pods/components/translation-comments-subscriptions/item/styles.scss b/webapp/app/styles/components/translation-comments-subscriptions/item.scss similarity index 100% rename from webapp/app/pods/components/translation-comments-subscriptions/item/styles.scss rename to webapp/app/styles/components/translation-comments-subscriptions/item.scss diff --git a/webapp/app/pods/components/translation-conversation/styles.scss b/webapp/app/styles/components/translation-conversation.scss similarity index 100% rename from webapp/app/pods/components/translation-conversation/styles.scss rename to webapp/app/styles/components/translation-conversation.scss diff --git a/webapp/app/pods/components/translation-edit/styles.scss b/webapp/app/styles/components/translation-edit.scss similarity index 98% rename from webapp/app/pods/components/translation-edit/styles.scss rename to webapp/app/styles/components/translation-edit.scss index 8e0b398a9..09264e300 100644 --- a/webapp/app/pods/components/translation-edit/styles.scss +++ b/webapp/app/styles/components/translation-edit.scss @@ -2,7 +2,7 @@ width: 100%; } -.full-width { +.jipt { padding-right: 15px; padding-left: 15px; } diff --git a/webapp/app/pods/components/translation-edit/form/styles.scss b/webapp/app/styles/components/translation-edit/form.scss similarity index 88% rename from webapp/app/pods/components/translation-edit/form/styles.scss rename to webapp/app/styles/components/translation-edit/form.scss index 4273fd00d..66962adfd 100644 --- a/webapp/app/pods/components/translation-edit/form/styles.scss +++ b/webapp/app/styles/components/translation-edit/form.scss @@ -74,12 +74,21 @@ width: 100%; height: 100%; padding: 10px 130px 10px 10px; - font-size: 12px; &[dir='rtl'] { padding: 10px 10px 10px 130px; } + &.inputText--borderless { + border-color: transparent; + background: transparent; + + &:focus { + border-color: transparent; + background: transparent; + } + } + &::placeholder { opacity: 0.2; font-style: italic; @@ -122,7 +131,9 @@ font-size: 12px; color: var(--text-color-normal); opacity: 0.8; - transition: color 0.2s ease-in-out, opacity 0.2s ease-in-out; + transition: + color 0.2s ease-in-out, + opacity 0.2s ease-in-out; &.placeholders-item--warning { opacity: 1; @@ -176,3 +187,12 @@ margin-right: 6px; stroke: var(--color-black); } + +.lint-messages { + transition: 0.2s ease-in-out; + transition-property: opacity; +} + +.lint-messages--loading { + opacity: 0.5; +} diff --git a/webapp/app/pods/components/translation-edit/helpers/styles.scss b/webapp/app/styles/components/translation-edit/helpers.scss similarity index 100% rename from webapp/app/pods/components/translation-edit/helpers/styles.scss rename to webapp/app/styles/components/translation-edit/helpers.scss diff --git a/webapp/app/pods/components/translation-editions-list/styles.scss b/webapp/app/styles/components/translation-editions-list.scss similarity index 50% rename from webapp/app/pods/components/translation-editions-list/styles.scss rename to webapp/app/styles/components/translation-editions-list.scss index b3381f679..2ba260253 100644 --- a/webapp/app/pods/components/translation-editions-list/styles.scss +++ b/webapp/app/styles/components/translation-editions-list.scss @@ -2,13 +2,6 @@ margin-top: 20px; } -.icon { - display: block; - width: 50px; - height: 50px; - margin-bottom: 10px; -} - .empty-content { margin-top: 20px; } diff --git a/webapp/app/pods/components/translation-editions-list/item/styles.scss b/webapp/app/styles/components/translation-editions-list/item.scss similarity index 100% rename from webapp/app/pods/components/translation-editions-list/item/styles.scss rename to webapp/app/styles/components/translation-editions-list/item.scss diff --git a/webapp/app/pods/components/translation-index/styles.scss b/webapp/app/styles/components/translation-index.scss similarity index 96% rename from webapp/app/pods/components/translation-index/styles.scss rename to webapp/app/styles/components/translation-index.scss index 2c0bc943c..8e3a140ca 100644 --- a/webapp/app/pods/components/translation-index/styles.scss +++ b/webapp/app/styles/components/translation-index.scss @@ -1,6 +1,6 @@ .wrapper { display: flex; - margin-top: 30px; + margin-top: 10px; & > div:first-of-type { margin-right: 40px; diff --git a/webapp/app/pods/components/translation-navigation/styles.scss b/webapp/app/styles/components/translation-navigation.scss similarity index 79% rename from webapp/app/pods/components/translation-navigation/styles.scss rename to webapp/app/styles/components/translation-navigation.scss index c2116f793..cc9e99242 100644 --- a/webapp/app/pods/components/translation-navigation/styles.scss +++ b/webapp/app/styles/components/translation-navigation.scss @@ -1,19 +1,15 @@ .navigation--alt { - border-bottom: 1px solid var(--input-border-color); - .navigation-list-item { margin-right: 6px; } .navigation-list-item-link { - position: relative; - top: 1px; - padding: 10px 15px 8px 10px; - border-bottom: 2px solid transparent; + padding: 2px 11px 2px 10px; + border-radius: var(--border-radius); &:global(.active) { - border-bottom-color: var(--color-primary); - color: var(--color-primary); + background: var(--background-light-highlight); + opacity: 0.7; } } } @@ -21,7 +17,6 @@ .navigation-list { display: flex; align-items: stretch; - min-height: 40px; position: relative; left: -6px; z-index: 10; @@ -45,21 +40,19 @@ position: relative; padding: 5px 5px 6px 3px; text-decoration: none; - font-size: 14px; + font-size: 13px; font-weight: 600; color: var(--color-black); &:focus, &:hover, :global(&.active) { - color: var(--color-primary); - .navigation-list-item-link-text { opacity: 1; } .navigation-list-item-link-icon { - stroke: var(--color-primary); + stroke: currentColor; } } } @@ -73,9 +66,9 @@ .navigation-list-item-link-icon { transition: 0.2s ease-in-out; transition-property: stroke; - width: 16px; - height: 16px; - margin-right: 7px; + width: 12px; + height: 12px; + margin-right: 5px; opacity: 0.6; stroke: var(--color-black); } diff --git a/webapp/app/pods/components/translation-splash-title/styles.scss b/webapp/app/styles/components/translation-splash-title.scss similarity index 100% rename from webapp/app/pods/components/translation-splash-title/styles.scss rename to webapp/app/styles/components/translation-splash-title.scss diff --git a/webapp/app/pods/components/translations-filter/styles.scss b/webapp/app/styles/components/translations-filter.scss similarity index 81% rename from webapp/app/pods/components/translations-filter/styles.scss rename to webapp/app/styles/components/translations-filter.scss index 6c111128d..525aa8d8d 100644 --- a/webapp/app/pods/components/translations-filter/styles.scss +++ b/webapp/app/styles/components/translations-filter.scss @@ -4,11 +4,6 @@ align-items: flex-start; } -.filters-content { - flex-grow: 1; - margin-right: 15px; -} - .queryForm { position: relative; } @@ -32,7 +27,9 @@ color: var(--color-black); &:focus { - box-shadow: inset 0 1px 2px rgba(#000, 0.1), 0 1px 2px var(--shadow-color); + box-shadow: + inset 0 1px 2px rgba(#000, 0.1), + 0 1px 2px var(--shadow-color); } &::placeholder { @@ -43,6 +40,7 @@ button.advancedFilters { position: relative; box-shadow: none; + flex-shrink: 0; &:focus, &:hover { transform: translate3d(0, 0, 0); @@ -60,13 +58,6 @@ button.advancedFilters { font-size: 10px; } -.totalEntries { - flex-shrink: 0; - margin-top: 10px; - color: var(--color-grey); - font-size: 12px; -} - @media (max-width: 440px) { .filters-wrapper { flex-direction: column; diff --git a/webapp/app/pods/components/translations-filter/advanced-filters/styles.scss b/webapp/app/styles/components/translations-filter/advanced-filters.scss similarity index 100% rename from webapp/app/pods/components/translations-filter/advanced-filters/styles.scss rename to webapp/app/styles/components/translations-filter/advanced-filters.scss diff --git a/webapp/app/pods/components/translations-list/styles.scss b/webapp/app/styles/components/translations-list.scss similarity index 100% rename from webapp/app/pods/components/translations-list/styles.scss rename to webapp/app/styles/components/translations-list.scss diff --git a/webapp/app/pods/components/translations-list/item/styles.scss b/webapp/app/styles/components/translations-list/item.scss similarity index 98% rename from webapp/app/pods/components/translations-list/item/styles.scss rename to webapp/app/styles/components/translations-list/item.scss index 45b2b6cbc..87b81155d 100644 --- a/webapp/app/pods/components/translations-list/item/styles.scss +++ b/webapp/app/styles/components/translations-list/item.scss @@ -160,6 +160,7 @@ .item-meta { display: flex; align-items: center; + gap: 3px; } .item-text { @@ -193,7 +194,7 @@ .item-updatedAt { opacity: 0; - transform: translateX(-10px); + transform: translateX(-5px); margin-left: 5px; color: var(--color-grey); font-size: 11px; diff --git a/webapp/app/pods/components/version-create-form/styles.scss b/webapp/app/styles/components/version-create-form.scss similarity index 83% rename from webapp/app/pods/components/version-create-form/styles.scss rename to webapp/app/styles/components/version-create-form.scss index c9e05c208..ea3535572 100644 --- a/webapp/app/pods/components/version-create-form/styles.scss +++ b/webapp/app/styles/components/version-create-form.scss @@ -51,6 +51,18 @@ font-size: 13px; } +.formItem-checkbox { + margin-bottom: 4px; + display: flex; + align-items: center; + gap: 6px; +} + +.formItem-help { + font-size: 11px; + opacity: 0.6; +} + .formActions { padding-top: 10px; } diff --git a/webapp/app/pods/components/version-update-form/styles.scss b/webapp/app/styles/components/version-update-form.scss similarity index 83% rename from webapp/app/pods/components/version-update-form/styles.scss rename to webapp/app/styles/components/version-update-form.scss index 292153c88..e3f609623 100644 --- a/webapp/app/pods/components/version-update-form/styles.scss +++ b/webapp/app/styles/components/version-update-form.scss @@ -51,6 +51,18 @@ font-size: 13px; } +.formItem-checkbox { + margin-bottom: 4px; + display: flex; + align-items: center; + gap: 6px; +} + +.formItem-help { + font-size: 11px; + opacity: 0.6; +} + .formActions { padding-top: 10px; } diff --git a/webapp/app/pods/components/versions-list/styles.scss b/webapp/app/styles/components/versions-list.scss similarity index 100% rename from webapp/app/pods/components/versions-list/styles.scss rename to webapp/app/styles/components/versions-list.scss diff --git a/webapp/app/pods/components/versions-list/item/styles.scss b/webapp/app/styles/components/versions-list/item.scss similarity index 100% rename from webapp/app/pods/components/versions-list/item/styles.scss rename to webapp/app/styles/components/versions-list/item.scss diff --git a/webapp/app/pods/components/welcome-project/styles.scss b/webapp/app/styles/components/welcome-project.scss similarity index 88% rename from webapp/app/pods/components/welcome-project/styles.scss rename to webapp/app/styles/components/welcome-project.scss index 2f44273ef..182b190e7 100644 --- a/webapp/app/pods/components/welcome-project/styles.scss +++ b/webapp/app/styles/components/welcome-project.scss @@ -51,7 +51,9 @@ padding: 20px; margin-bottom: 10px; margin-right: 10px; - box-shadow: 0 4px 8px var(--shadow-color), 0 5px 15px var(--shadow-color); + box-shadow: + 0 4px 8px var(--shadow-color), + 0 5px 15px var(--shadow-color); border-radius: var(--border-radius); color: var(--color-primary); text-decoration: none; @@ -62,7 +64,9 @@ &:focus, &:hover { background: var(--color-primary-opacity-10); - box-shadow: 0 1px 6px var(--shadow-color), 0 5px 18px var(--shadow-color); + box-shadow: + 0 1px 6px var(--shadow-color), + 0 5px 18px var(--shadow-color); } } diff --git a/webapp/app/styles/html-components/button.scss b/webapp/app/styles/html-components/button.scss index 934c24cad..ad7c3b0fb 100644 --- a/webapp/app/styles/html-components/button.scss +++ b/webapp/app/styles/html-components/button.scss @@ -76,6 +76,18 @@ } } +.button--blue { + --button-text-color: var(--color-blue); +} + +.button--green { + --button-text-color: var(--color-green); +} + +.button--grey { + --button-text-color: var(--color-grey); +} + .button--grey, .button--success, .button--black, @@ -104,7 +116,9 @@ padding: 5px 12px; background: var(--button-background-color); border: 1px solid var(--button-border-color); - box-shadow: 0 1px 2px var(--shadow-color), 0 2px 6px var(--shadow-color); + box-shadow: + 0 1px 2px var(--shadow-color), + 0 2px 6px var(--shadow-color); text-shadow: 0 1px 1px var(--shadow-color); color: var(--button-text-color); @@ -172,8 +186,8 @@ } &.button--grey { - --button-text-hover-color: #fff; - --button-text-color: #fff; + --button-text-hover-color: var(--color-black); + --button-text-color: var(--color-black); --button-background-color: var(--background-light); --button-background-hover-color: darken(#ccc, 4%); --button-border-color: darken(#ccc, 4%); @@ -235,20 +249,13 @@ } } -.button--grey { - color: #000; - border-color: var(--background-light); - - &.button--loading svg.loading { - fill: #8a8a8a; - } +.button--borderLess { + border-color: transparent; +} - &:hover, - &:focus { - color: darken(#8a8a8a, 10%); - background: lighten(#8a8a8a, 43%); - border-color: var(--background-light-highlight); - } +.button--grey { + --button-text-color: var(--color-grey); + --button-text-hover-color: var(--color-grey); } .button--green { diff --git a/webapp/app/styles/html-components/emoji-picker.scss b/webapp/app/styles/html-components/emoji-picker.scss deleted file mode 100644 index f0377a011..000000000 --- a/webapp/app/styles/html-components/emoji-picker.scss +++ /dev/null @@ -1,59 +0,0 @@ -div.emoji-picker__wrapper { - z-index: 3001; - border: 0; - box-shadow: 0 3px 15px var(--shadow-color); - overflow: hidden; - - .emoji-picker__tab-body h2 { - display: none; - } - - .emoji-picker__variant-overlay { - background: rgba(#fff, 0.7); - } - - .emoji-picker__variant-popup-close-button { - display: none; - } - - .emoji-picker__variant-popup { - border-radius: var(--border-radius); - box-shadow: 0 3px 10px rgba(#3a3a3a, 0.1); - } - - .emoji-picker__search { - border-color: transparent; - box-shadow: 0 3px 10px rgba(#3a3a3a, 0.1); - } - - .emoji-picker__search:focus { - box-shadow: 0 2px 4px rgba(#3a3a3a, 0.1); - } - - .emoji-picker__emoji:focus, - .emoji-picker__emoji:hover, - .emoji-picker__tab:hover { - background: #eee; - } - - .emoji-picker__tab.active { - background: #bbb; - } - - .emoji-picker__search { - padding-left: 0.6em; - } - - .emoji-picker__tab svg, - .emoji-picker__tab path { - box-sizing: content-box; - } - - .emoji-picker__search-container { - margin: 0.5em 0.5em 0; - } - - .emoji-picker__search-icon { - top: 5px; - } -} diff --git a/webapp/app/styles/html-components/filters.scss b/webapp/app/styles/html-components/filters.scss index 1dd37ea14..75aa58464 100644 --- a/webapp/app/styles/html-components/filters.scss +++ b/webapp/app/styles/html-components/filters.scss @@ -1,19 +1,23 @@ .filters { padding: 15px; - border-radius: 0 0 3px 3px; background: var(--background-light); border-radius: var(--border-radius); border: 1px solid var(--background-light-highlight); margin-top: -2px; + &.filters--jipt { + border-radius: 0; + } + &.filters--transparent { background: none; border-color: transparent; box-shadow: none; + padding: 0; } .ember-power-select-trigger { - padding: 5px 10px; + padding: 5px 27px 5px 5px; background: var(--content-background); box-shadow: none; border: 1px solid transparent; @@ -30,13 +34,28 @@ .filters-wrapper { position: relative; + display: flex; + justify-content: space-between; + align-items: flex-start; +} + +.filters-content { + display: flex; + flex-direction: column; + gap: 10px; + flex-grow: 1; +} + +.queryForm { + position: relative; + display: flex; + gap: 10px; } .queryForm-filters { display: flex; justify-content: space-between; align-items: center; - margin-top: 6px; } .queryForm-filters-column { diff --git a/webapp/app/styles/html-components/power-select.scss b/webapp/app/styles/html-components/power-select.scss index f2e86b76c..4519dd9cf 100644 --- a/webapp/app/styles/html-components/power-select.scss +++ b/webapp/app/styles/html-components/power-select.scss @@ -70,6 +70,65 @@ } } +.ember-power-select-multiple-options + .ember-power-select-multiple-option:first-of-type { + span[role='button'] { + display: none; + } +} + +.ember-power-select-multiple-options { + margin: 0; + padding: 0; + display: flex; + flex-wrap: wrap; + gap: 4px; + align-items: center; + list-style: none; + + & li.ember-power-select-trigger-multiple-input-container { + flex-grow: 1; + display: flex; + + & input { + flex-grow: 1; + } + } +} + +.ember-power-select-trigger-multiple-input { + font-family: inherit; + font-size: inherit; + border: none; + line-height: inherit; + -webkit-appearance: none; + outline: none; + padding: 0; + background-color: transparent; + text-indent: 2px; +} + +html[data-theme='dark'] .ember-power-select-multiple-option { + color: var(--color-primary); +} + +.ember-power-select-multiple-option { + display: inline-block; + background: var(--color-primary-opacity-25); + color: var(--color-primary-darken-50); + border-radius: var(--border-radius); + + padding: 3px 9px; + font-size: 14px; +} + +.ember-power-select-multiple-remove-btn { + cursor: pointer; + &:not(:hover) { + opacity: 0.5; + } +} + .ember-power-select-status-icon { position: absolute; right: 0; diff --git a/webapp/app/pods/application/template.hbs b/webapp/app/templates/application.hbs similarity index 100% rename from webapp/app/pods/application/template.hbs rename to webapp/app/templates/application.hbs diff --git a/webapp/app/pods/components/acc-avatar-img/template.hbs b/webapp/app/templates/components/acc-avatar-img.hbs similarity index 100% rename from webapp/app/pods/components/acc-avatar-img/template.hbs rename to webapp/app/templates/components/acc-avatar-img.hbs diff --git a/webapp/app/pods/components/acc-badge/template.hbs b/webapp/app/templates/components/acc-badge.hbs similarity index 100% rename from webapp/app/pods/components/acc-badge/template.hbs rename to webapp/app/templates/components/acc-badge.hbs diff --git a/webapp/app/templates/components/acc-emoji-picker.hbs b/webapp/app/templates/components/acc-emoji-picker.hbs new file mode 100644 index 000000000..1833a0035 --- /dev/null +++ b/webapp/app/templates/components/acc-emoji-picker.hbs @@ -0,0 +1,16 @@ + + +{{#if this.picker}} + +
    +
    +
    + {{this.picker}} +
    +
    +
    +{{/if}} \ No newline at end of file diff --git a/webapp/app/pods/components/acc-flash-message/template.hbs b/webapp/app/templates/components/acc-flash-message.hbs similarity index 100% rename from webapp/app/pods/components/acc-flash-message/template.hbs rename to webapp/app/templates/components/acc-flash-message.hbs diff --git a/webapp/app/pods/components/acc-modal/template.hbs b/webapp/app/templates/components/acc-modal.hbs similarity index 100% rename from webapp/app/pods/components/acc-modal/template.hbs rename to webapp/app/templates/components/acc-modal.hbs diff --git a/webapp/app/pods/components/acc-select/template.hbs b/webapp/app/templates/components/acc-select.hbs similarity index 80% rename from webapp/app/pods/components/acc-select/template.hbs rename to webapp/app/templates/components/acc-select.hbs index 4ccd83171..88d9851fd 100644 --- a/webapp/app/pods/components/acc-select/template.hbs +++ b/webapp/app/templates/components/acc-select.hbs @@ -17,6 +17,10 @@ {{option.label}} +{{else if @multi}} + + {{option.label}} + {{else}}
    + + {{#if @onChangeAdvancedFilterBoolean}} + + {{/if}} +
    + + {{#if this.showSomeFilters}} +
    +
    + {{#if this.showDocumentsSelect}} +
    +
    + +
    +
    + {{/if}} + + {{#if this.showVersionsSelect}} +
    +
    + +
    +
    + {{/if}} +
    +
    + {{/if}} + + {{#if this.displayAdvancedFilters}} + + {{/if}} +
    + + + \ No newline at end of file diff --git a/webapp/app/templates/components/conflicts-list.hbs b/webapp/app/templates/components/conflicts-list.hbs new file mode 100644 index 000000000..b8503f572 --- /dev/null +++ b/webapp/app/templates/components/conflicts-list.hbs @@ -0,0 +1,47 @@ +{{#if this.currentVersion}} +
    + + {{t 'components.conflicts_list.translations_version_notice'}} + {{this.currentVersion.tag}} +
    +{{/if}} + + + + \ No newline at end of file diff --git a/webapp/app/templates/components/conflicts-list/advanced-filters.hbs b/webapp/app/templates/components/conflicts-list/advanced-filters.hbs new file mode 100644 index 000000000..30947477d --- /dev/null +++ b/webapp/app/templates/components/conflicts-list/advanced-filters.hbs @@ -0,0 +1,42 @@ +
    + + {{t 'components.conflicts_filters.advanced_filters_title'}} + + +
    + + + + + + + + + +
    +
    \ No newline at end of file diff --git a/webapp/app/templates/components/conflicts-list/group.hbs b/webapp/app/templates/components/conflicts-list/group.hbs new file mode 100644 index 000000000..e2d1e4e76 --- /dev/null +++ b/webapp/app/templates/components/conflicts-list/group.hbs @@ -0,0 +1,37 @@ +
  • + + {{this.translationKey.value}} + + + {{#if this.translationKey.prefix}} + {{this.translationKey.prefix}} + {{else}} + {{@groupedTranslation.document.path}} + {{/if}} + + + + +
  • \ No newline at end of file diff --git a/webapp/app/templates/components/conflicts-list/item.hbs b/webapp/app/templates/components/conflicts-list/item.hbs new file mode 100644 index 000000000..8d4da5a35 --- /dev/null +++ b/webapp/app/templates/components/conflicts-list/item.hbs @@ -0,0 +1,77 @@ +
  • +
    +
    + {{#if this.error}} +
    + {{t 'components.translation_item.correct_error_text'}} +
    + {{/if}} +
    +
    +
    + + {{#component form.submit}} +
    + {{#if this.showOriginalButton}} + + {{inline-svg '/assets/revert.svg' class='button-icon'}} + + {{/if}} + +
    + +
    + + {{#if @translation.isConflicted}} + {{#if (get @permissions 'correct_translation')}} + + {{inline-svg '/assets/check.svg' class='button-icon'}} + + {{else if (get @permissions 'update_translation')}} + + {{inline-svg '/assets/pencil.svg' class='button-icon'}} + + {{/if}} + {{else}} + {{#if (get @permissions 'uncorrect_translation')}} + + {{inline-svg '/assets/revert.svg' class='button-icon'}} + + {{else if (get @permissions 'update_translation')}} + + {{inline-svg '/assets/pencil.svg' class='button-icon'}} + + {{/if}} + {{/if}} +
    + {{/component}} +
    +
    +
    +
    +
  • \ No newline at end of file diff --git a/webapp/app/pods/components/dashboard-revisions/template.hbs b/webapp/app/templates/components/dashboard-revisions.hbs similarity index 88% rename from webapp/app/pods/components/dashboard-revisions/template.hbs rename to webapp/app/templates/components/dashboard-revisions.hbs index 97566eb37..ea1a58c8f 100644 --- a/webapp/app/pods/components/dashboard-revisions/template.hbs +++ b/webapp/app/templates/components/dashboard-revisions.hbs @@ -30,7 +30,7 @@

    {{#if (get @permissions 'sync')}} - + {{inline-svg '/assets/sync.svg' class='button-icon'}} {{t 'components.documents_list.sync'}} @@ -59,17 +59,6 @@
    {{#if this.slaveRevisions}} -

    -
    - {{#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|}} - {{#if (get @permissions 'index_translations')}} - - {{this.languageName}} - {{#if this.rtl}} - - {{t 'components.dashboard_revisions.item.rtl_badge'}} - - {{/if}} - - {{this.correctedKeysPercentage}} - % - - - {{else}} - - {{this.languageName}} - - {{this.correctedKeysPercentage}} - % - - - {{/if}} + + {{this.languageName}} + {{#if this.rtl}} + + {{t 'components.dashboard_revisions.item.rtl_badge'}} + + {{/if}} + - - {{this.reviewsCount}} - - / - - {{@revision.translationsCount}} + + {{this.correctedKeysPercentage}}% + +
    + + {{this.toReviewCount}} + {{t 'components.dashboard_revisions.item.stats_to_review'}} + + + {{#unless @revision.isMaster}} + + {{@revision.translatedCount}} + {{t 'components.dashboard_revisions.item.stats_translated'}} + + {{/unless}} +
    diff --git a/webapp/app/templates/components/date-tag.hbs b/webapp/app/templates/components/date-tag.hbs new file mode 100644 index 000000000..00744688c --- /dev/null +++ b/webapp/app/templates/components/date-tag.hbs @@ -0,0 +1,5 @@ + + + \ No newline at end of file diff --git a/webapp/app/pods/components/documents-add-button/template.hbs b/webapp/app/templates/components/documents-add-button.hbs similarity index 100% rename from webapp/app/pods/components/documents-add-button/template.hbs rename to webapp/app/templates/components/documents-add-button.hbs diff --git a/webapp/app/pods/components/documents-list/template.hbs b/webapp/app/templates/components/documents-list.hbs similarity index 100% rename from webapp/app/pods/components/documents-list/template.hbs rename to webapp/app/templates/components/documents-list.hbs diff --git a/webapp/app/pods/components/documents-list/item/template.hbs b/webapp/app/templates/components/documents-list/item.hbs similarity index 78% rename from webapp/app/pods/components/documents-list/item/template.hbs rename to webapp/app/templates/components/documents-list/item.hbs index 2c9ec0ed2..b8a8bc98f 100644 --- a/webapp/app/pods/components/documents-list/item/template.hbs +++ b/webapp/app/templates/components/documents-list/item.hbs @@ -81,45 +81,28 @@ {{#unless this.empty}}
    {{#if (get @permissions 'sync')}} - + {{inline-svg '/assets/sync.svg' class='button-icon'}} + {{t 'components.documents_list.sync'}} {{/if}} {{#if this.multipleRevisions}} {{#if (get @permissions 'merge')}} - + {{inline-svg '/assets/merge.svg' class='button-icon'}} + {{t 'components.documents_list.merge'}} {{/if}} {{/if}} {{#if (get @permissions 'machine_translations_translate')}} - + {{inline-svg '/assets/language.svg' class='button-icon'}} + {{t 'components.documents_list.machine_translations'}} {{/if}} - + {{inline-svg '/assets/export.svg' class='button-icon'}} + {{t 'components.documents_list.export'}}
    diff --git a/webapp/app/pods/components/documents-machine-translations-button/template.hbs b/webapp/app/templates/components/documents-machine-translations-button.hbs similarity index 100% rename from webapp/app/pods/components/documents-machine-translations-button/template.hbs rename to webapp/app/templates/components/documents-machine-translations-button.hbs diff --git a/webapp/app/pods/components/dummy-login-form/template.hbs b/webapp/app/templates/components/dummy-login-form.hbs similarity index 100% rename from webapp/app/pods/components/dummy-login-form/template.hbs rename to webapp/app/templates/components/dummy-login-form.hbs diff --git a/webapp/app/pods/components/empty-content/template.hbs b/webapp/app/templates/components/empty-content.hbs similarity index 100% rename from webapp/app/pods/components/empty-content/template.hbs rename to webapp/app/templates/components/empty-content.hbs diff --git a/webapp/app/pods/components/error-section/template.hbs b/webapp/app/templates/components/error-section.hbs similarity index 100% rename from webapp/app/pods/components/error-section/template.hbs rename to webapp/app/templates/components/error-section.hbs diff --git a/webapp/app/pods/components/file-export-all/template.hbs b/webapp/app/templates/components/file-export-all.hbs similarity index 100% rename from webapp/app/pods/components/file-export-all/template.hbs rename to webapp/app/templates/components/file-export-all.hbs diff --git a/webapp/app/pods/components/file-export/template.hbs b/webapp/app/templates/components/file-export.hbs similarity index 100% rename from webapp/app/pods/components/file-export/template.hbs rename to webapp/app/templates/components/file-export.hbs diff --git a/webapp/app/pods/components/file-input/template.hbs b/webapp/app/templates/components/file-input.hbs similarity index 100% rename from webapp/app/pods/components/file-input/template.hbs rename to webapp/app/templates/components/file-input.hbs diff --git a/webapp/app/pods/components/flash-messages-list/template.hbs b/webapp/app/templates/components/flash-messages-list.hbs similarity index 100% rename from webapp/app/pods/components/flash-messages-list/template.hbs rename to webapp/app/templates/components/flash-messages-list.hbs diff --git a/webapp/app/pods/components/google-login-form/template.hbs b/webapp/app/templates/components/google-login-form.hbs similarity index 100% rename from webapp/app/pods/components/google-login-form/template.hbs rename to webapp/app/templates/components/google-login-form.hbs diff --git a/webapp/app/pods/components/highlight-render/template.hbs b/webapp/app/templates/components/highlight-render.hbs similarity index 100% rename from webapp/app/pods/components/highlight-render/template.hbs rename to webapp/app/templates/components/highlight-render.hbs diff --git a/webapp/app/pods/components/html-textarea/template.hbs b/webapp/app/templates/components/html-textarea.hbs similarity index 100% rename from webapp/app/pods/components/html-textarea/template.hbs rename to webapp/app/templates/components/html-textarea.hbs diff --git a/webapp/app/pods/components/improve-prompt/template.hbs b/webapp/app/templates/components/improve-prompt.hbs similarity index 100% rename from webapp/app/pods/components/improve-prompt/template.hbs rename to webapp/app/templates/components/improve-prompt.hbs diff --git a/webapp/app/templates/components/inline-machine-translate.hbs b/webapp/app/templates/components/inline-machine-translate.hbs new file mode 100644 index 000000000..bf5e9c1ae --- /dev/null +++ b/webapp/app/templates/components/inline-machine-translate.hbs @@ -0,0 +1,9 @@ + + {{inline-svg '/assets/language.svg' class='button-icon'}} + \ No newline at end of file diff --git a/webapp/app/pods/components/jipt-back-to-translations/template.hbs b/webapp/app/templates/components/jipt-back-to-translations.hbs similarity index 100% rename from webapp/app/pods/components/jipt-back-to-translations/template.hbs rename to webapp/app/templates/components/jipt-back-to-translations.hbs diff --git a/webapp/app/templates/components/jipt-example.hbs b/webapp/app/templates/components/jipt-example.hbs new file mode 100644 index 000000000..92723f816 --- /dev/null +++ b/webapp/app/templates/components/jipt-example.hbs @@ -0,0 +1,60 @@ +
    +
    + + ← Back to project + + +
    + {{#unless @loading}} +
    + <head> +
    + + + + +
    <script>
    +          {{{this.scriptContent}}}
    +          </script> <script async src="{{this.scriptSrc}}"></script>
    +        
    + +
    + <body> +
    + +

    {{@project.name}}’s Just-in-place translations

    + +

    Node inner HTML

    + +
    + <p>{^key@document_path}</p> + {{this.translationKey}} +
    + +
    + <strong>{^key@document_path}</strong> + {{this.translationKey}} +
    + +

    Node attributes

    + +
    + <input type="text" placeholder="{^key@document_path}" /> + +
    + +
    + <input type="submit" value="{^key@document_path}" /> + +
    + +
    + <img title="{^key@document_path}" src="…"/> + +
    + {{/unless}} +
    +
    +
    \ No newline at end of file diff --git a/webapp/app/pods/components/jipt-export/template.hbs b/webapp/app/templates/components/jipt-export.hbs similarity index 100% rename from webapp/app/pods/components/jipt-export/template.hbs rename to webapp/app/templates/components/jipt-export.hbs diff --git a/webapp/app/pods/components/jipt-header/template.hbs b/webapp/app/templates/components/jipt-header.hbs similarity index 100% rename from webapp/app/pods/components/jipt-header/template.hbs rename to webapp/app/templates/components/jipt-header.hbs diff --git a/webapp/app/pods/components/jipt-translation/template.hbs b/webapp/app/templates/components/jipt-translation.hbs similarity index 100% rename from webapp/app/pods/components/jipt-translation/template.hbs rename to webapp/app/templates/components/jipt-translation.hbs diff --git a/webapp/app/pods/components/jipt-translations-filtered-title/template.hbs b/webapp/app/templates/components/jipt-translations-filtered-title.hbs similarity index 100% rename from webapp/app/pods/components/jipt-translations-filtered-title/template.hbs rename to webapp/app/templates/components/jipt-translations-filtered-title.hbs diff --git a/webapp/app/pods/components/jipt-translations-list/template.hbs b/webapp/app/templates/components/jipt-translations-list.hbs similarity index 100% rename from webapp/app/pods/components/jipt-translations-list/template.hbs rename to webapp/app/templates/components/jipt-translations-list.hbs diff --git a/webapp/app/pods/components/jipt-translations-list/item/template.hbs b/webapp/app/templates/components/jipt-translations-list/item.hbs similarity index 51% rename from webapp/app/pods/components/jipt-translations-list/item/template.hbs rename to webapp/app/templates/components/jipt-translations-list/item.hbs index 35cb528ed..9f405cf0d 100644 --- a/webapp/app/pods/components/jipt-translations-list/item/template.hbs +++ b/webapp/app/templates/components/jipt-translations-list/item.hbs @@ -1,5 +1,8 @@ {{#if this.isTextEmpty}} {{t 'components.translations_list.empty_text'}} {{else}} - {{@translation.correctedText}} + + {{@translation.correctedText}} + {{@translation.key}} + {{/if}} \ No newline at end of file diff --git a/webapp/app/templates/components/lint-options.hbs b/webapp/app/templates/components/lint-options.hbs new file mode 100644 index 000000000..9da5d72a2 --- /dev/null +++ b/webapp/app/templates/components/lint-options.hbs @@ -0,0 +1,40 @@ +
    +
    +
    +
    +
    + {{inline-svg '/assets/search.svg' local-class='search-icon'}} + + +
    + + {{#if this.showSomeFilters}} +
    + {{#if this.showDocuments}} +
    +
    + +
    +
    + {{/if}} + + {{#if this.showVersions}} +
    +
    + +
    +
    + {{/if}} +
    + {{/if}} +
    +
    +
    +
    \ No newline at end of file diff --git a/webapp/app/pods/components/lint-translations-page/template.hbs b/webapp/app/templates/components/lint-translations-page.hbs similarity index 80% rename from webapp/app/pods/components/lint-translations-page/template.hbs rename to webapp/app/templates/components/lint-translations-page.hbs index e41722bbc..f1263429e 100644 --- a/webapp/app/pods/components/lint-translations-page/template.hbs +++ b/webapp/app/templates/components/lint-translations-page.hbs @@ -15,8 +15,8 @@
    {{#each @lintTranslations key='id' as |lintTranslation|}} -
    - +
    +
    {{/each}}
    diff --git a/webapp/app/templates/components/lint-translations-page/item.hbs b/webapp/app/templates/components/lint-translations-page/item.hbs new file mode 100644 index 000000000..dfcc94931 --- /dev/null +++ b/webapp/app/templates/components/lint-translations-page/item.hbs @@ -0,0 +1,62 @@ +{{#if @lintTranslation.messages}} +
    + + + {{#if @project}} +
    + + + {{this.translationKey.value}} + + {{#if this.translationKey.prefix}} + {{this.translationKey.prefix}} + {{else}} + {{@lintTranslation.translation.document.path}} + {{/if}} + + + +
    + {{/if}} + + {{#if this.allReplacable}} + + {{else}} +
    {{{this.annotatedText}}}
    + {{/if}} +
    +{{/if}} \ No newline at end of file diff --git a/webapp/app/pods/components/loading-content/template.hbs b/webapp/app/templates/components/loading-content.hbs similarity index 100% rename from webapp/app/pods/components/loading-content/template.hbs rename to webapp/app/templates/components/loading-content.hbs diff --git a/webapp/app/pods/components/login-forms/template.hbs b/webapp/app/templates/components/login-forms.hbs similarity index 92% rename from webapp/app/pods/components/login-forms/template.hbs rename to webapp/app/templates/components/login-forms.hbs index 5a2d0d9a0..72cc21402 100644 --- a/webapp/app/pods/components/login-forms/template.hbs +++ b/webapp/app/templates/components/login-forms.hbs @@ -92,6 +92,13 @@ {{t 'components.login_forms.auth0'}} {{/if}} + + {{#if this.oidcLoginEnabled}} + + + {{t 'components.login_forms.oidc'}} + + {{/if}} {{/if}} diff --git a/webapp/app/pods/components/machine-translations-document-translate/template.hbs b/webapp/app/templates/components/machine-translations-document-translate.hbs similarity index 100% rename from webapp/app/pods/components/machine-translations-document-translate/template.hbs rename to webapp/app/templates/components/machine-translations-document-translate.hbs diff --git a/webapp/app/pods/components/machine-translations-translate-upload-form/template.hbs b/webapp/app/templates/components/machine-translations-translate-upload-form.hbs similarity index 100% rename from webapp/app/pods/components/machine-translations-translate-upload-form/template.hbs rename to webapp/app/templates/components/machine-translations-translate-upload-form.hbs diff --git a/webapp/app/pods/components/operations-peek/template.hbs b/webapp/app/templates/components/operations-peek.hbs similarity index 100% rename from webapp/app/pods/components/operations-peek/template.hbs rename to webapp/app/templates/components/operations-peek.hbs diff --git a/webapp/app/pods/components/operations-peek/item/template.hbs b/webapp/app/templates/components/operations-peek/item.hbs similarity index 100% rename from webapp/app/pods/components/operations-peek/item/template.hbs rename to webapp/app/templates/components/operations-peek/item.hbs diff --git a/webapp/app/pods/components/page-title/end/template.hbs b/webapp/app/templates/components/page-title.hbs similarity index 100% rename from webapp/app/pods/components/page-title/end/template.hbs rename to webapp/app/templates/components/page-title.hbs diff --git a/webapp/app/pods/components/page-title/template.hbs b/webapp/app/templates/components/page-title/end.hbs similarity index 100% rename from webapp/app/pods/components/page-title/template.hbs rename to webapp/app/templates/components/page-title/end.hbs diff --git a/webapp/app/pods/components/phoenix-channel-listener/template.hbs b/webapp/app/templates/components/phoenix-channel-listener.hbs similarity index 100% rename from webapp/app/pods/components/phoenix-channel-listener/template.hbs rename to webapp/app/templates/components/phoenix-channel-listener.hbs diff --git a/webapp/app/pods/components/project-activities-filter/template.hbs b/webapp/app/templates/components/project-activities-filter.hbs similarity index 100% rename from webapp/app/pods/components/project-activities-filter/template.hbs rename to webapp/app/templates/components/project-activities-filter.hbs diff --git a/webapp/app/pods/components/project-activities-list/template.hbs b/webapp/app/templates/components/project-activities-list.hbs similarity index 100% rename from webapp/app/pods/components/project-activities-list/template.hbs rename to webapp/app/templates/components/project-activities-list.hbs diff --git a/webapp/app/pods/components/project-activity/template.hbs b/webapp/app/templates/components/project-activity.hbs similarity index 94% rename from webapp/app/pods/components/project-activity/template.hbs rename to webapp/app/templates/components/project-activity.hbs index 53f6fd1ab..b4bdf2bae 100644 --- a/webapp/app/pods/components/project-activity/template.hbs +++ b/webapp/app/templates/components/project-activity.hbs @@ -208,18 +208,16 @@ {{t 'components.project_activity.operations_label'}} -
    - {{#each this.operations.entries key='id' as |activity|}} - - {{/each}} -
    + {{#each this.operations.entries key='id' as |activity|}} + + {{/each}} {{#if this.operations.meta.nextPage}}
    diff --git a/webapp/app/pods/components/project-comments-list/template.hbs b/webapp/app/templates/components/project-comments-list.hbs similarity index 100% rename from webapp/app/pods/components/project-comments-list/template.hbs rename to webapp/app/templates/components/project-comments-list.hbs diff --git a/webapp/app/pods/components/project-comments-list/item/template.hbs b/webapp/app/templates/components/project-comments-list/item.hbs similarity index 100% rename from webapp/app/pods/components/project-comments-list/item/template.hbs rename to webapp/app/templates/components/project-comments-list/item.hbs diff --git a/webapp/app/pods/components/project-create-form/template.hbs b/webapp/app/templates/components/project-create-form.hbs similarity index 100% rename from webapp/app/pods/components/project-create-form/template.hbs rename to webapp/app/templates/components/project-create-form.hbs diff --git a/webapp/app/pods/components/project-file-operation/template.hbs b/webapp/app/templates/components/project-file-operation.hbs similarity index 100% rename from webapp/app/pods/components/project-file-operation/template.hbs rename to webapp/app/templates/components/project-file-operation.hbs diff --git a/webapp/app/pods/components/project-header/template.hbs b/webapp/app/templates/components/project-header.hbs similarity index 100% rename from webapp/app/pods/components/project-header/template.hbs rename to webapp/app/templates/components/project-header.hbs diff --git a/webapp/app/pods/components/project-logo/template.hbs b/webapp/app/templates/components/project-logo.hbs similarity index 100% rename from webapp/app/pods/components/project-logo/template.hbs rename to webapp/app/templates/components/project-logo.hbs diff --git a/webapp/app/pods/components/project-navigation/template.hbs b/webapp/app/templates/components/project-navigation.hbs similarity index 100% rename from webapp/app/pods/components/project-navigation/template.hbs rename to webapp/app/templates/components/project-navigation.hbs diff --git a/webapp/app/pods/components/project-navigation/list/template.hbs b/webapp/app/templates/components/project-navigation/list.hbs similarity index 90% rename from webapp/app/pods/components/project-navigation/list/template.hbs rename to webapp/app/templates/components/project-navigation/list.hbs index c7e588777..5e9de0412 100644 --- a/webapp/app/pods/components/project-navigation/list/template.hbs +++ b/webapp/app/templates/components/project-navigation/list.hbs @@ -26,13 +26,22 @@ {{#if (get @permissions 'correct_translation')}}
  • - + {{inline-svg '/assets/check.svg' local-class='list-item-link-icon'}} {{t 'components.project_navigation.conflicts_link_title'}}
  • + {{else if (get @permissions 'update_translation')}} +
  • + + {{inline-svg '/assets/pencil.svg' local-class='list-item-link-icon'}} + + {{t 'components.project_navigation.translate_link_title'}} + + +
  • {{/if}} {{#if (get @permissions 'lint')}} diff --git a/webapp/app/pods/components/project-settings/api-token/template.hbs b/webapp/app/templates/components/project-settings/api-token.hbs similarity index 100% rename from webapp/app/pods/components/project-settings/api-token/template.hbs rename to webapp/app/templates/components/project-settings/api-token.hbs diff --git a/webapp/app/pods/components/project-settings/api-token/item/template.hbs b/webapp/app/templates/components/project-settings/api-token/item.hbs similarity index 100% rename from webapp/app/pods/components/project-settings/api-token/item/template.hbs rename to webapp/app/templates/components/project-settings/api-token/item.hbs diff --git a/webapp/app/pods/components/project-settings/back-link/template.hbs b/webapp/app/templates/components/project-settings/back-link.hbs similarity index 100% rename from webapp/app/pods/components/project-settings/back-link/template.hbs rename to webapp/app/templates/components/project-settings/back-link.hbs diff --git a/webapp/app/pods/components/project-settings/badges/template.hbs b/webapp/app/templates/components/project-settings/badges.hbs similarity index 100% rename from webapp/app/pods/components/project-settings/badges/template.hbs rename to webapp/app/templates/components/project-settings/badges.hbs diff --git a/webapp/app/pods/components/project-settings/collaborators/template.hbs b/webapp/app/templates/components/project-settings/collaborators.hbs similarity index 72% rename from webapp/app/pods/components/project-settings/collaborators/template.hbs rename to webapp/app/templates/components/project-settings/collaborators.hbs index d0de5f7d1..547d72591 100644 --- a/webapp/app/pods/components/project-settings/collaborators/template.hbs +++ b/webapp/app/templates/components/project-settings/collaborators.hbs @@ -17,6 +17,7 @@
    + {{inline-svg 'assets/tool.svg' local-class='rolesList-icon'}} {{t 'general.roles.OWNER'}}

    @@ -24,6 +25,7 @@

    + {{inline-svg 'assets/users.svg' local-class='rolesList-icon'}} {{t 'general.roles.ADMIN'}}

    @@ -31,6 +33,7 @@

    + {{inline-svg 'assets/code.svg' local-class='rolesList-icon'}} {{t 'general.roles.DEVELOPER'}}

    @@ -38,11 +41,20 @@

    + {{inline-svg 'assets/check.svg' local-class='rolesList-icon'}} {{t 'general.roles.REVIEWER'}}

    {{t 'components.project_settings.collaborators.reviewer_text'}}

    + + + {{inline-svg 'assets/machine-translations.svg' local-class='rolesList-icon'}} + {{t 'general.roles.TRANSLATOR'}} + +

    + {{t 'components.project_settings.collaborators.translator_text'}} +

    \ No newline at end of file diff --git a/webapp/app/pods/components/project-settings/collaborators/create-form/template.hbs b/webapp/app/templates/components/project-settings/collaborators/create-form.hbs similarity index 100% rename from webapp/app/pods/components/project-settings/collaborators/create-form/template.hbs rename to webapp/app/templates/components/project-settings/collaborators/create-form.hbs diff --git a/webapp/app/pods/components/project-settings/collaborators/list/template.hbs b/webapp/app/templates/components/project-settings/collaborators/list.hbs similarity index 100% rename from webapp/app/pods/components/project-settings/collaborators/list/template.hbs rename to webapp/app/templates/components/project-settings/collaborators/list.hbs diff --git a/webapp/app/pods/components/project-settings/collaborators/list/item/template.hbs b/webapp/app/templates/components/project-settings/collaborators/list/item.hbs similarity index 100% rename from webapp/app/pods/components/project-settings/collaborators/list/item/template.hbs rename to webapp/app/templates/components/project-settings/collaborators/list/item.hbs diff --git a/webapp/app/pods/components/project-settings/delete-form/template.hbs b/webapp/app/templates/components/project-settings/delete-form.hbs similarity index 100% rename from webapp/app/pods/components/project-settings/delete-form/template.hbs rename to webapp/app/templates/components/project-settings/delete-form.hbs diff --git a/webapp/app/pods/components/project-settings/form/template.hbs b/webapp/app/templates/components/project-settings/form.hbs similarity index 100% rename from webapp/app/pods/components/project-settings/form/template.hbs rename to webapp/app/templates/components/project-settings/form.hbs diff --git a/webapp/app/pods/components/project-settings/integrations/template.hbs b/webapp/app/templates/components/project-settings/integrations.hbs similarity index 86% rename from webapp/app/pods/components/project-settings/integrations/template.hbs rename to webapp/app/templates/components/project-settings/integrations.hbs index a7ac62842..917847c8e 100644 --- a/webapp/app/pods/components/project-settings/integrations/template.hbs +++ b/webapp/app/templates/components/project-settings/integrations.hbs @@ -38,6 +38,12 @@

    {{t 'components.project_settings.integrations.empty_description.azure_storage_container.text'}}

    + +