diff --git a/app2/.babelrc b/app2/.babelrc
new file mode 100644
index 000000000..b56ad8dc6
--- /dev/null
+++ b/app2/.babelrc
@@ -0,0 +1,4 @@
+{
+ "presets": ["next/babel"],
+ "plugins": []
+}
\ No newline at end of file
diff --git a/app2/.eslintrc.json b/app2/.eslintrc.json
new file mode 100755
index 000000000..3af52d700
--- /dev/null
+++ b/app2/.eslintrc.json
@@ -0,0 +1,3 @@
+{
+ "extends": ["next/babel"]
+}
diff --git a/app2/.gitignore b/app2/.gitignore
new file mode 100755
index 000000000..737d87210
--- /dev/null
+++ b/app2/.gitignore
@@ -0,0 +1,35 @@
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+# dependencies
+/node_modules
+/.pnp
+.pnp.js
+
+# testing
+/coverage
+
+# next.js
+/.next/
+/out/
+
+# production
+/build
+
+# misc
+.DS_Store
+*.pem
+
+# debug
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+.pnpm-debug.log*
+
+# local env files
+.env*.local
+
+# vercel
+.vercel
+
+# typescript
+*.tsbuildinfo
diff --git a/app2/.nvmrc b/app2/.nvmrc
new file mode 100644
index 000000000..0ff38047b
--- /dev/null
+++ b/app2/.nvmrc
@@ -0,0 +1 @@
+16.16.0
\ No newline at end of file
diff --git a/app2/README.md b/app2/README.md
new file mode 100755
index 000000000..c87e0421d
--- /dev/null
+++ b/app2/README.md
@@ -0,0 +1,34 @@
+This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
+
+## Getting Started
+
+First, run the development server:
+
+```bash
+npm run dev
+# or
+yarn dev
+```
+
+Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
+
+You can start editing the page by modifying `pages/index.tsx`. The page auto-updates as you edit the file.
+
+[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.ts`.
+
+The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages.
+
+## Learn More
+
+To learn more about Next.js, take a look at the following resources:
+
+- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
+- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
+
+You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
+
+## Deploy on Vercel
+
+The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
+
+Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
diff --git a/app2/next-env.d.ts b/app2/next-env.d.ts
new file mode 100755
index 000000000..4f11a03dc
--- /dev/null
+++ b/app2/next-env.d.ts
@@ -0,0 +1,5 @@
+///
+///
+
+// NOTE: This file should not be edited
+// see https://nextjs.org/docs/basic-features/typescript for more information.
diff --git a/app2/next.config.js b/app2/next.config.js
new file mode 100755
index 000000000..ae887958d
--- /dev/null
+++ b/app2/next.config.js
@@ -0,0 +1,7 @@
+/** @type {import('next').NextConfig} */
+const nextConfig = {
+ reactStrictMode: true,
+ swcMinify: true,
+}
+
+module.exports = nextConfig
diff --git a/app2/package-lock.json b/app2/package-lock.json
new file mode 100644
index 000000000..4c0b1a706
--- /dev/null
+++ b/app2/package-lock.json
@@ -0,0 +1,9310 @@
+{
+ "name": "app2",
+ "version": "0.1.0",
+ "lockfileVersion": 2,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "app2",
+ "version": "0.1.0",
+ "dependencies": {
+ "@emotion/react": "^11.9.3",
+ "@reduxjs/toolkit": "^1.8.3",
+ "@types/react-redux": "^7.1.24",
+ "next": "12.2.2",
+ "react": "18.2.0",
+ "react-dom": "18.2.0",
+ "react-redux": "^8.0.2",
+ "redux": "^4.2.0",
+ "redux-flash": "^2.0.2"
+ },
+ "devDependencies": {
+ "@babel/core": "^7.18.9",
+ "@babel/preset-env": "^7.18.9",
+ "@types/node": "18.0.6",
+ "@types/react": "18.0.15",
+ "@types/react-dom": "18.0.6",
+ "eslint": "8.20.0",
+ "eslint-config-next": "12.2.2",
+ "typescript": "4.7.4"
+ }
+ },
+ "node_modules/@ampproject/remapping": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz",
+ "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==",
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.1.0",
+ "@jridgewell/trace-mapping": "^0.3.9"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@babel/code-frame": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz",
+ "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==",
+ "dependencies": {
+ "@babel/highlight": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/compat-data": {
+ "version": "7.18.8",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.18.8.tgz",
+ "integrity": "sha512-HSmX4WZPPK3FUxYp7g2T6EyO8j96HlZJlxmKPSh6KAcqwyDrfx7hKjXpAW/0FhFfTJsR0Yt4lAjLI2coMptIHQ==",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/core": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.9.tgz",
+ "integrity": "sha512-1LIb1eL8APMy91/IMW+31ckrfBM4yCoLaVzoDhZUKSM4cu1L1nIidyxkCgzPAgrC5WEz36IPEr/eSeSF9pIn+g==",
+ "dependencies": {
+ "@ampproject/remapping": "^2.1.0",
+ "@babel/code-frame": "^7.18.6",
+ "@babel/generator": "^7.18.9",
+ "@babel/helper-compilation-targets": "^7.18.9",
+ "@babel/helper-module-transforms": "^7.18.9",
+ "@babel/helpers": "^7.18.9",
+ "@babel/parser": "^7.18.9",
+ "@babel/template": "^7.18.6",
+ "@babel/traverse": "^7.18.9",
+ "@babel/types": "^7.18.9",
+ "convert-source-map": "^1.7.0",
+ "debug": "^4.1.0",
+ "gensync": "^1.0.0-beta.2",
+ "json5": "^2.2.1",
+ "semver": "^6.3.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/babel"
+ }
+ },
+ "node_modules/@babel/core/node_modules/json5": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz",
+ "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==",
+ "bin": {
+ "json5": "lib/cli.js"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@babel/core/node_modules/semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/@babel/generator": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.9.tgz",
+ "integrity": "sha512-wt5Naw6lJrL1/SGkipMiFxJjtyczUWTP38deiP1PO60HsBjDeKk08CGC3S8iVuvf0FmTdgKwU1KIXzSKL1G0Ug==",
+ "dependencies": {
+ "@babel/types": "^7.18.9",
+ "@jridgewell/gen-mapping": "^0.3.2",
+ "jsesc": "^2.5.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/generator/node_modules/@jridgewell/gen-mapping": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz",
+ "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==",
+ "dependencies": {
+ "@jridgewell/set-array": "^1.0.1",
+ "@jridgewell/sourcemap-codec": "^1.4.10",
+ "@jridgewell/trace-mapping": "^0.3.9"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@babel/helper-annotate-as-pure": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz",
+ "integrity": "sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.18.9.tgz",
+ "integrity": "sha512-yFQ0YCHoIqarl8BCRwBL8ulYUaZpz3bNsA7oFepAzee+8/+ImtADXNOmO5vJvsPff3qi+hvpkY/NYBTrBQgdNw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-explode-assignable-expression": "^7.18.6",
+ "@babel/types": "^7.18.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-compilation-targets": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.9.tgz",
+ "integrity": "sha512-tzLCyVmqUiFlcFoAPLA/gL9TeYrF61VLNtb+hvkuVaB5SUjW7jcfrglBIX1vUIoT7CLP3bBlIMeyEsIl2eFQNg==",
+ "dependencies": {
+ "@babel/compat-data": "^7.18.8",
+ "@babel/helper-validator-option": "^7.18.6",
+ "browserslist": "^4.20.2",
+ "semver": "^6.3.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-compilation-targets/node_modules/semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/@babel/helper-create-class-features-plugin": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.18.9.tgz",
+ "integrity": "sha512-WvypNAYaVh23QcjpMR24CwZY2Nz6hqdOcFdPbNpV56hL5H6KiFheO7Xm1aPdlLQ7d5emYZX7VZwPp9x3z+2opw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-annotate-as-pure": "^7.18.6",
+ "@babel/helper-environment-visitor": "^7.18.9",
+ "@babel/helper-function-name": "^7.18.9",
+ "@babel/helper-member-expression-to-functions": "^7.18.9",
+ "@babel/helper-optimise-call-expression": "^7.18.6",
+ "@babel/helper-replace-supers": "^7.18.9",
+ "@babel/helper-split-export-declaration": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-create-regexp-features-plugin": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.18.6.tgz",
+ "integrity": "sha512-7LcpH1wnQLGrI+4v+nPp+zUvIkF9x0ddv1Hkdue10tg3gmRnLy97DXh4STiOf1qeIInyD69Qv5kKSZzKD8B/7A==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-annotate-as-pure": "^7.18.6",
+ "regexpu-core": "^5.1.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-define-polyfill-provider": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.1.tgz",
+ "integrity": "sha512-J9hGMpJQmtWmj46B3kBHmL38UhJGhYX7eqkcq+2gsstyYt341HmPeWspihX43yVRA0mS+8GGk2Gckc7bY/HCmA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-compilation-targets": "^7.13.0",
+ "@babel/helper-module-imports": "^7.12.13",
+ "@babel/helper-plugin-utils": "^7.13.0",
+ "@babel/traverse": "^7.13.0",
+ "debug": "^4.1.1",
+ "lodash.debounce": "^4.0.8",
+ "resolve": "^1.14.2",
+ "semver": "^6.1.2"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.4.0-0"
+ }
+ },
+ "node_modules/@babel/helper-define-polyfill-provider/node_modules/semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/@babel/helper-environment-visitor": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz",
+ "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-explode-assignable-expression": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.18.6.tgz",
+ "integrity": "sha512-eyAYAsQmB80jNfg4baAtLeWAQHfHFiR483rzFK+BhETlGZaQC9bsfrugfXDCbRHLQbIA7U5NxhhOxN7p/dWIcg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-function-name": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.18.9.tgz",
+ "integrity": "sha512-fJgWlZt7nxGksJS9a0XdSaI4XvpExnNIgRP+rVefWh5U7BL8pPuir6SJUmFKRfjWQ51OtWSzwOxhaH/EBWWc0A==",
+ "dependencies": {
+ "@babel/template": "^7.18.6",
+ "@babel/types": "^7.18.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-hoist-variables": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz",
+ "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==",
+ "dependencies": {
+ "@babel/types": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-member-expression-to-functions": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.9.tgz",
+ "integrity": "sha512-RxifAh2ZoVU67PyKIO4AMi1wTenGfMR/O/ae0CCRqwgBAt5v7xjdtRw7UoSbsreKrQn5t7r89eruK/9JjYHuDg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.18.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-imports": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz",
+ "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==",
+ "dependencies": {
+ "@babel/types": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-transforms": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.18.9.tgz",
+ "integrity": "sha512-KYNqY0ICwfv19b31XzvmI/mfcylOzbLtowkw+mfvGPAQ3kfCnMLYbED3YecL5tPd8nAYFQFAd6JHp2LxZk/J1g==",
+ "dependencies": {
+ "@babel/helper-environment-visitor": "^7.18.9",
+ "@babel/helper-module-imports": "^7.18.6",
+ "@babel/helper-simple-access": "^7.18.6",
+ "@babel/helper-split-export-declaration": "^7.18.6",
+ "@babel/helper-validator-identifier": "^7.18.6",
+ "@babel/template": "^7.18.6",
+ "@babel/traverse": "^7.18.9",
+ "@babel/types": "^7.18.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-optimise-call-expression": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz",
+ "integrity": "sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-plugin-utils": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.18.9.tgz",
+ "integrity": "sha512-aBXPT3bmtLryXaoJLyYPXPlSD4p1ld9aYeR+sJNOZjJJGiOpb+fKfh3NkcCu7J54nUJwCERPBExCCpyCOHnu/w==",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-remap-async-to-generator": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.18.9.tgz",
+ "integrity": "sha512-dI7q50YKd8BAv3VEfgg7PS7yD3Rtbi2J1XMXaalXO0W0164hYLnh8zpjRS0mte9MfVp/tltvr/cfdXPvJr1opA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-annotate-as-pure": "^7.18.6",
+ "@babel/helper-environment-visitor": "^7.18.9",
+ "@babel/helper-wrap-function": "^7.18.9",
+ "@babel/types": "^7.18.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-replace-supers": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.18.9.tgz",
+ "integrity": "sha512-dNsWibVI4lNT6HiuOIBr1oyxo40HvIVmbwPUm3XZ7wMh4k2WxrxTqZwSqw/eEmXDS9np0ey5M2bz9tBmO9c+YQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-environment-visitor": "^7.18.9",
+ "@babel/helper-member-expression-to-functions": "^7.18.9",
+ "@babel/helper-optimise-call-expression": "^7.18.6",
+ "@babel/traverse": "^7.18.9",
+ "@babel/types": "^7.18.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-simple-access": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz",
+ "integrity": "sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g==",
+ "dependencies": {
+ "@babel/types": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-skip-transparent-expression-wrappers": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.18.9.tgz",
+ "integrity": "sha512-imytd2gHi3cJPsybLRbmFrF7u5BIEuI2cNheyKi3/iOBC63kNn3q8Crn2xVuESli0aM4KYsyEqKyS7lFL8YVtw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.18.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-split-export-declaration": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz",
+ "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==",
+ "dependencies": {
+ "@babel/types": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-identifier": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz",
+ "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-option": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz",
+ "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-wrap-function": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.18.9.tgz",
+ "integrity": "sha512-cG2ru3TRAL6a60tfQflpEfs4ldiPwF6YW3zfJiRgmoFVIaC1vGnBBgatfec+ZUziPHkHSaXAuEck3Cdkf3eRpQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-function-name": "^7.18.9",
+ "@babel/template": "^7.18.6",
+ "@babel/traverse": "^7.18.9",
+ "@babel/types": "^7.18.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helpers": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.18.9.tgz",
+ "integrity": "sha512-Jf5a+rbrLoR4eNdUmnFu8cN5eNJT6qdTdOg5IHIzq87WwyRw9PwguLFOWYgktN/60IP4fgDUawJvs7PjQIzELQ==",
+ "dependencies": {
+ "@babel/template": "^7.18.6",
+ "@babel/traverse": "^7.18.9",
+ "@babel/types": "^7.18.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/highlight": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz",
+ "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==",
+ "dependencies": {
+ "@babel/helper-validator-identifier": "^7.18.6",
+ "chalk": "^2.0.0",
+ "js-tokens": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/highlight/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==",
+ "dependencies": {
+ "color-convert": "^1.9.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@babel/highlight/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==",
+ "dependencies": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@babel/highlight/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==",
+ "dependencies": {
+ "color-name": "1.1.3"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="
+ },
+ "node_modules/@babel/highlight/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": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@babel/highlight/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==",
+ "dependencies": {
+ "has-flag": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@babel/parser": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.9.tgz",
+ "integrity": "sha512-9uJveS9eY9DJ0t64YbIBZICtJy8a5QrDEVdiLCG97fVLpDTpGX7t8mMSb6OWw6Lrnjqj4O8zwjELX3dhoMgiBg==",
+ "bin": {
+ "parser": "bin/babel-parser.js"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.18.6.tgz",
+ "integrity": "sha512-Dgxsyg54Fx1d4Nge8UnvTrED63vrwOdPmyvPzlNN/boaliRP54pm3pGzZD1SJUwrBA+Cs/xdG8kXX6Mn/RfISQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.18.9.tgz",
+ "integrity": "sha512-AHrP9jadvH7qlOj6PINbgSuphjQUAK7AOT7DPjBo9EHoLhQTnnK5u45e1Hd4DbSQEO9nqPWtQ89r+XEOWFScKg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.9",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.18.9",
+ "@babel/plugin-proposal-optional-chaining": "^7.18.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.13.0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-async-generator-functions": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.18.6.tgz",
+ "integrity": "sha512-WAz4R9bvozx4qwf74M+sfqPMKfSqwM0phxPTR6iJIi8robgzXwkEgmeJG1gEKhm6sDqT/U9aV3lfcqybIpev8w==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-environment-visitor": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6",
+ "@babel/helper-remap-async-to-generator": "^7.18.6",
+ "@babel/plugin-syntax-async-generators": "^7.8.4"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-class-properties": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz",
+ "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-create-class-features-plugin": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-class-static-block": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.18.6.tgz",
+ "integrity": "sha512-+I3oIiNxrCpup3Gi8n5IGMwj0gOCAjcJUSQEcotNnCCPMEnixawOQ+KeJPlgfjzx+FKQ1QSyZOWe7wmoJp7vhw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-create-class-features-plugin": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6",
+ "@babel/plugin-syntax-class-static-block": "^7.14.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.12.0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-dynamic-import": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.18.6.tgz",
+ "integrity": "sha512-1auuwmK+Rz13SJj36R+jqFPMJWyKEDd7lLSdOj4oJK0UTgGueSAtkrCvz9ewmgyU/P941Rv2fQwZJN8s6QruXw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.6",
+ "@babel/plugin-syntax-dynamic-import": "^7.8.3"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-export-namespace-from": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.18.9.tgz",
+ "integrity": "sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.9",
+ "@babel/plugin-syntax-export-namespace-from": "^7.8.3"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-json-strings": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.18.6.tgz",
+ "integrity": "sha512-lr1peyn9kOdbYc0xr0OdHTZ5FMqS6Di+H0Fz2I/JwMzGmzJETNeOFq2pBySw6X/KFL5EWDjlJuMsUGRFb8fQgQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.6",
+ "@babel/plugin-syntax-json-strings": "^7.8.3"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-logical-assignment-operators": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.18.9.tgz",
+ "integrity": "sha512-128YbMpjCrP35IOExw2Fq+x55LMP42DzhOhX2aNNIdI9avSWl2PI0yuBWarr3RYpZBSPtabfadkH2yeRiMD61Q==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.9",
+ "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-nullish-coalescing-operator": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz",
+ "integrity": "sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.6",
+ "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-numeric-separator": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz",
+ "integrity": "sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.6",
+ "@babel/plugin-syntax-numeric-separator": "^7.10.4"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-object-rest-spread": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.18.9.tgz",
+ "integrity": "sha512-kDDHQ5rflIeY5xl69CEqGEZ0KY369ehsCIEbTGb4siHG5BE9sga/T0r0OUwyZNLMmZE79E1kbsqAjwFCW4ds6Q==",
+ "dev": true,
+ "dependencies": {
+ "@babel/compat-data": "^7.18.8",
+ "@babel/helper-compilation-targets": "^7.18.9",
+ "@babel/helper-plugin-utils": "^7.18.9",
+ "@babel/plugin-syntax-object-rest-spread": "^7.8.3",
+ "@babel/plugin-transform-parameters": "^7.18.8"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-optional-catch-binding": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz",
+ "integrity": "sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.6",
+ "@babel/plugin-syntax-optional-catch-binding": "^7.8.3"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-optional-chaining": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.18.9.tgz",
+ "integrity": "sha512-v5nwt4IqBXihxGsW2QmCWMDS3B3bzGIk/EQVZz2ei7f3NJl8NzAJVvUmpDW5q1CRNY+Beb/k58UAH1Km1N411w==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.9",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.18.9",
+ "@babel/plugin-syntax-optional-chaining": "^7.8.3"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-private-methods": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz",
+ "integrity": "sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-create-class-features-plugin": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-private-property-in-object": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.18.6.tgz",
+ "integrity": "sha512-9Rysx7FOctvT5ouj5JODjAFAkgGoudQuLPamZb0v1TGLpapdNaftzifU8NTWQm0IRjqoYypdrSmyWgkocDQ8Dw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-annotate-as-pure": "^7.18.6",
+ "@babel/helper-create-class-features-plugin": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6",
+ "@babel/plugin-syntax-private-property-in-object": "^7.14.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-unicode-property-regex": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz",
+ "integrity": "sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-create-regexp-features-plugin": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "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,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-class-properties": {
+ "version": "7.12.13",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz",
+ "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.12.13"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-class-static-block": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz",
+ "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "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,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-export-namespace-from": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz",
+ "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.3"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-import-assertions": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.18.6.tgz",
+ "integrity": "sha512-/DU3RXad9+bZwrgWJQKbr39gYbJpLJHezqEzRzi/BHRlJ9zsQb4CK2CA/5apllXNomwA1qHwzvHl+AdEmC5krQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "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,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-jsx": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz",
+ "integrity": "sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-logical-assignment-operators": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz",
+ "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "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,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-numeric-separator": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz",
+ "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "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,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "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,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "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,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-private-property-in-object": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz",
+ "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-top-level-await": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz",
+ "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-arrow-functions": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.18.6.tgz",
+ "integrity": "sha512-9S9X9RUefzrsHZmKMbDXxweEH+YlE8JJEuat9FdvW9Qh1cw7W64jELCtWNkPBPX5En45uy28KGvA/AySqUh8CQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-async-to-generator": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.18.6.tgz",
+ "integrity": "sha512-ARE5wZLKnTgPW7/1ftQmSi1CmkqqHo2DNmtztFhvgtOWSDfq0Cq9/9L+KnZNYSNrydBekhW3rwShduf59RoXag==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-module-imports": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6",
+ "@babel/helper-remap-async-to-generator": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-block-scoped-functions": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.18.6.tgz",
+ "integrity": "sha512-ExUcOqpPWnliRcPqves5HJcJOvHvIIWfuS4sroBUenPuMdmW+SMHDakmtS7qOo13sVppmUijqeTv7qqGsvURpQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-block-scoping": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.18.9.tgz",
+ "integrity": "sha512-5sDIJRV1KtQVEbt/EIBwGy4T01uYIo4KRB3VUqzkhrAIOGx7AoctL9+Ux88btY0zXdDyPJ9mW+bg+v+XEkGmtw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-classes": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.18.9.tgz",
+ "integrity": "sha512-EkRQxsxoytpTlKJmSPYrsOMjCILacAjtSVkd4gChEe2kXjFCun3yohhW5I7plXJhCemM0gKsaGMcO8tinvCA5g==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-annotate-as-pure": "^7.18.6",
+ "@babel/helper-environment-visitor": "^7.18.9",
+ "@babel/helper-function-name": "^7.18.9",
+ "@babel/helper-optimise-call-expression": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.9",
+ "@babel/helper-replace-supers": "^7.18.9",
+ "@babel/helper-split-export-declaration": "^7.18.6",
+ "globals": "^11.1.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-classes/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,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@babel/plugin-transform-computed-properties": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.18.9.tgz",
+ "integrity": "sha512-+i0ZU1bCDymKakLxn5srGHrsAPRELC2WIbzwjLhHW9SIE1cPYkLCL0NlnXMZaM1vhfgA2+M7hySk42VBvrkBRw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-destructuring": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.18.9.tgz",
+ "integrity": "sha512-p5VCYNddPLkZTq4XymQIaIfZNJwT9YsjkPOhkVEqt6QIpQFZVM9IltqqYpOEkJoN1DPznmxUDyZ5CTZs/ZCuHA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-dotall-regex": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.18.6.tgz",
+ "integrity": "sha512-6S3jpun1eEbAxq7TdjLotAsl4WpQI9DxfkycRcKrjhQYzU87qpXdknpBg/e+TdcMehqGnLFi7tnFUBR02Vq6wg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-create-regexp-features-plugin": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-duplicate-keys": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.18.9.tgz",
+ "integrity": "sha512-d2bmXCtZXYc59/0SanQKbiWINadaJXqtvIQIzd4+hNwkWBgyCd5F/2t1kXoUdvPMrxzPvhK6EMQRROxsue+mfw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-exponentiation-operator": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.18.6.tgz",
+ "integrity": "sha512-wzEtc0+2c88FVR34aQmiz56dxEkxr2g8DQb/KfaFa1JYXOFVsbhvAonFN6PwVWj++fKmku8NP80plJ5Et4wqHw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-builder-binary-assignment-operator-visitor": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-for-of": {
+ "version": "7.18.8",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.18.8.tgz",
+ "integrity": "sha512-yEfTRnjuskWYo0k1mHUqrVWaZwrdq8AYbfrpqULOJOaucGSp4mNMVps+YtA8byoevxS/urwU75vyhQIxcCgiBQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-function-name": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.18.9.tgz",
+ "integrity": "sha512-WvIBoRPaJQ5yVHzcnJFor7oS5Ls0PYixlTYE63lCj2RtdQEl15M68FXQlxnG6wdraJIXRdR7KI+hQ7q/9QjrCQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-compilation-targets": "^7.18.9",
+ "@babel/helper-function-name": "^7.18.9",
+ "@babel/helper-plugin-utils": "^7.18.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-literals": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.18.9.tgz",
+ "integrity": "sha512-IFQDSRoTPnrAIrI5zoZv73IFeZu2dhu6irxQjY9rNjTT53VmKg9fenjvoiOWOkJ6mm4jKVPtdMzBY98Fp4Z4cg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-member-expression-literals": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.18.6.tgz",
+ "integrity": "sha512-qSF1ihLGO3q+/g48k85tUjD033C29TNTVB2paCwZPVmOsjn9pClvYYrM2VeJpBY2bcNkuny0YUyTNRyRxJ54KA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-modules-amd": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.18.6.tgz",
+ "integrity": "sha512-Pra5aXsmTsOnjM3IajS8rTaLCy++nGM4v3YR4esk5PCsyg9z8NA5oQLwxzMUtDBd8F+UmVza3VxoAaWCbzH1rg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-module-transforms": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6",
+ "babel-plugin-dynamic-import-node": "^2.3.3"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-modules-commonjs": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.18.6.tgz",
+ "integrity": "sha512-Qfv2ZOWikpvmedXQJDSbxNqy7Xr/j2Y8/KfijM0iJyKkBTmWuvCA1yeH1yDM7NJhBW/2aXxeucLj6i80/LAJ/Q==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-module-transforms": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6",
+ "@babel/helper-simple-access": "^7.18.6",
+ "babel-plugin-dynamic-import-node": "^2.3.3"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-modules-systemjs": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.18.9.tgz",
+ "integrity": "sha512-zY/VSIbbqtoRoJKo2cDTewL364jSlZGvn0LKOf9ntbfxOvjfmyrdtEEOAdswOswhZEb8UH3jDkCKHd1sPgsS0A==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-hoist-variables": "^7.18.6",
+ "@babel/helper-module-transforms": "^7.18.9",
+ "@babel/helper-plugin-utils": "^7.18.9",
+ "@babel/helper-validator-identifier": "^7.18.6",
+ "babel-plugin-dynamic-import-node": "^2.3.3"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-modules-umd": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.18.6.tgz",
+ "integrity": "sha512-dcegErExVeXcRqNtkRU/z8WlBLnvD4MRnHgNs3MytRO1Mn1sHRyhbcpYbVMGclAqOjdW+9cfkdZno9dFdfKLfQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-module-transforms": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-named-capturing-groups-regex": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.18.6.tgz",
+ "integrity": "sha512-UmEOGF8XgaIqD74bC8g7iV3RYj8lMf0Bw7NJzvnS9qQhM4mg+1WHKotUIdjxgD2RGrgFLZZPCFPFj3P/kVDYhg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-create-regexp-features-plugin": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-new-target": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.18.6.tgz",
+ "integrity": "sha512-DjwFA/9Iu3Z+vrAn+8pBUGcjhxKguSMlsFqeCKbhb9BAV756v0krzVK04CRDi/4aqmk8BsHb4a/gFcaA5joXRw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-object-super": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.18.6.tgz",
+ "integrity": "sha512-uvGz6zk+pZoS1aTZrOvrbj6Pp/kK2mp45t2B+bTDre2UgsZZ8EZLSJtUg7m/no0zOJUWgFONpB7Zv9W2tSaFlA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.6",
+ "@babel/helper-replace-supers": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-parameters": {
+ "version": "7.18.8",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.18.8.tgz",
+ "integrity": "sha512-ivfbE3X2Ss+Fj8nnXvKJS6sjRG4gzwPMsP+taZC+ZzEGjAYlvENixmt1sZ5Ca6tWls+BlKSGKPJ6OOXvXCbkFg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-property-literals": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.18.6.tgz",
+ "integrity": "sha512-cYcs6qlgafTud3PAzrrRNbQtfpQ8+y/+M5tKmksS9+M1ckbH6kzY8MrexEM9mcA6JDsukE19iIRvAyYl463sMg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-regenerator": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.18.6.tgz",
+ "integrity": "sha512-poqRI2+qiSdeldcz4wTSTXBRryoq3Gc70ye7m7UD5Ww0nE29IXqMl6r7Nd15WBgRd74vloEMlShtH6CKxVzfmQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.6",
+ "regenerator-transform": "^0.15.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-reserved-words": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.18.6.tgz",
+ "integrity": "sha512-oX/4MyMoypzHjFrT1CdivfKZ+XvIPMFXwwxHp/r0Ddy2Vuomt4HDFGmft1TAY2yiTKiNSsh3kjBAzcM8kSdsjA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-shorthand-properties": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.18.6.tgz",
+ "integrity": "sha512-eCLXXJqv8okzg86ywZJbRn19YJHU4XUa55oz2wbHhaQVn/MM+XhukiT7SYqp/7o00dg52Rj51Ny+Ecw4oyoygw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-spread": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.18.9.tgz",
+ "integrity": "sha512-39Q814wyoOPtIB/qGopNIL9xDChOE1pNU0ZY5dO0owhiVt/5kFm4li+/bBtwc7QotG0u5EPzqhZdjMtmqBqyQA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.9",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.18.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-sticky-regex": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.18.6.tgz",
+ "integrity": "sha512-kfiDrDQ+PBsQDO85yj1icueWMfGfJFKN1KCkndygtu/C9+XUfydLC8Iv5UYJqRwy4zk8EcplRxEOeLyjq1gm6Q==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-template-literals": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.18.9.tgz",
+ "integrity": "sha512-S8cOWfT82gTezpYOiVaGHrCbhlHgKhQt8XH5ES46P2XWmX92yisoZywf5km75wv5sYcXDUCLMmMxOLCtthDgMA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-typeof-symbol": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.18.9.tgz",
+ "integrity": "sha512-SRfwTtF11G2aemAZWivL7PD+C9z52v9EvMqH9BuYbabyPuKUvSWks3oCg6041pT925L4zVFqaVBeECwsmlguEw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-unicode-escapes": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.18.6.tgz",
+ "integrity": "sha512-XNRwQUXYMP7VLuy54cr/KS/WeL3AZeORhrmeZ7iewgu+X2eBqmpaLI/hzqr9ZxCeUoq0ASK4GUzSM0BDhZkLFw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-unicode-regex": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.18.6.tgz",
+ "integrity": "sha512-gE7A6Lt7YLnNOL3Pb9BNeZvi+d8l7tcRrG4+pwJjK9hD2xX4mEvjlQW60G9EEmfXVYRPv9VRQcyegIVHCql/AA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-create-regexp-features-plugin": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/preset-env": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.18.9.tgz",
+ "integrity": "sha512-75pt/q95cMIHWssYtyfjVlvI+QEZQThQbKvR9xH+F/Agtw/s4Wfc2V9Bwd/P39VtixB7oWxGdH4GteTTwYJWMg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/compat-data": "^7.18.8",
+ "@babel/helper-compilation-targets": "^7.18.9",
+ "@babel/helper-plugin-utils": "^7.18.9",
+ "@babel/helper-validator-option": "^7.18.6",
+ "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.18.6",
+ "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.18.9",
+ "@babel/plugin-proposal-async-generator-functions": "^7.18.6",
+ "@babel/plugin-proposal-class-properties": "^7.18.6",
+ "@babel/plugin-proposal-class-static-block": "^7.18.6",
+ "@babel/plugin-proposal-dynamic-import": "^7.18.6",
+ "@babel/plugin-proposal-export-namespace-from": "^7.18.9",
+ "@babel/plugin-proposal-json-strings": "^7.18.6",
+ "@babel/plugin-proposal-logical-assignment-operators": "^7.18.9",
+ "@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.6",
+ "@babel/plugin-proposal-numeric-separator": "^7.18.6",
+ "@babel/plugin-proposal-object-rest-spread": "^7.18.9",
+ "@babel/plugin-proposal-optional-catch-binding": "^7.18.6",
+ "@babel/plugin-proposal-optional-chaining": "^7.18.9",
+ "@babel/plugin-proposal-private-methods": "^7.18.6",
+ "@babel/plugin-proposal-private-property-in-object": "^7.18.6",
+ "@babel/plugin-proposal-unicode-property-regex": "^7.18.6",
+ "@babel/plugin-syntax-async-generators": "^7.8.4",
+ "@babel/plugin-syntax-class-properties": "^7.12.13",
+ "@babel/plugin-syntax-class-static-block": "^7.14.5",
+ "@babel/plugin-syntax-dynamic-import": "^7.8.3",
+ "@babel/plugin-syntax-export-namespace-from": "^7.8.3",
+ "@babel/plugin-syntax-import-assertions": "^7.18.6",
+ "@babel/plugin-syntax-json-strings": "^7.8.3",
+ "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4",
+ "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3",
+ "@babel/plugin-syntax-numeric-separator": "^7.10.4",
+ "@babel/plugin-syntax-object-rest-spread": "^7.8.3",
+ "@babel/plugin-syntax-optional-catch-binding": "^7.8.3",
+ "@babel/plugin-syntax-optional-chaining": "^7.8.3",
+ "@babel/plugin-syntax-private-property-in-object": "^7.14.5",
+ "@babel/plugin-syntax-top-level-await": "^7.14.5",
+ "@babel/plugin-transform-arrow-functions": "^7.18.6",
+ "@babel/plugin-transform-async-to-generator": "^7.18.6",
+ "@babel/plugin-transform-block-scoped-functions": "^7.18.6",
+ "@babel/plugin-transform-block-scoping": "^7.18.9",
+ "@babel/plugin-transform-classes": "^7.18.9",
+ "@babel/plugin-transform-computed-properties": "^7.18.9",
+ "@babel/plugin-transform-destructuring": "^7.18.9",
+ "@babel/plugin-transform-dotall-regex": "^7.18.6",
+ "@babel/plugin-transform-duplicate-keys": "^7.18.9",
+ "@babel/plugin-transform-exponentiation-operator": "^7.18.6",
+ "@babel/plugin-transform-for-of": "^7.18.8",
+ "@babel/plugin-transform-function-name": "^7.18.9",
+ "@babel/plugin-transform-literals": "^7.18.9",
+ "@babel/plugin-transform-member-expression-literals": "^7.18.6",
+ "@babel/plugin-transform-modules-amd": "^7.18.6",
+ "@babel/plugin-transform-modules-commonjs": "^7.18.6",
+ "@babel/plugin-transform-modules-systemjs": "^7.18.9",
+ "@babel/plugin-transform-modules-umd": "^7.18.6",
+ "@babel/plugin-transform-named-capturing-groups-regex": "^7.18.6",
+ "@babel/plugin-transform-new-target": "^7.18.6",
+ "@babel/plugin-transform-object-super": "^7.18.6",
+ "@babel/plugin-transform-parameters": "^7.18.8",
+ "@babel/plugin-transform-property-literals": "^7.18.6",
+ "@babel/plugin-transform-regenerator": "^7.18.6",
+ "@babel/plugin-transform-reserved-words": "^7.18.6",
+ "@babel/plugin-transform-shorthand-properties": "^7.18.6",
+ "@babel/plugin-transform-spread": "^7.18.9",
+ "@babel/plugin-transform-sticky-regex": "^7.18.6",
+ "@babel/plugin-transform-template-literals": "^7.18.9",
+ "@babel/plugin-transform-typeof-symbol": "^7.18.9",
+ "@babel/plugin-transform-unicode-escapes": "^7.18.6",
+ "@babel/plugin-transform-unicode-regex": "^7.18.6",
+ "@babel/preset-modules": "^0.1.5",
+ "@babel/types": "^7.18.9",
+ "babel-plugin-polyfill-corejs2": "^0.3.1",
+ "babel-plugin-polyfill-corejs3": "^0.5.2",
+ "babel-plugin-polyfill-regenerator": "^0.3.1",
+ "core-js-compat": "^3.22.1",
+ "semver": "^6.3.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/preset-env/node_modules/semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/@babel/preset-modules": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz",
+ "integrity": "sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==",
+ "dev": true,
+ "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"
+ }
+ },
+ "node_modules/@babel/runtime": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.18.6.tgz",
+ "integrity": "sha512-t9wi7/AW6XtKahAe20Yw0/mMljKq0B1r2fPdvaAdV/KPDZewFXdaaa6K7lxmZBZ8FBNpCiAT6iHPmd6QO9bKfQ==",
+ "dependencies": {
+ "regenerator-runtime": "^0.13.4"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/runtime-corejs3": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.18.6.tgz",
+ "integrity": "sha512-cOu5wH2JFBgMjje+a+fz2JNIWU4GzYpl05oSob3UDvBEh6EuIn+TXFHMmBbhSb+k/4HMzgKCQfEEDArAWNF9Cw==",
+ "dev": true,
+ "dependencies": {
+ "core-js-pure": "^3.20.2",
+ "regenerator-runtime": "^0.13.4"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/template": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.6.tgz",
+ "integrity": "sha512-JoDWzPe+wgBsTTgdnIma3iHNFC7YVJoPssVBDjiHfNlyt4YcunDtcDOUmfVDfCK5MfdsaIoX9PkijPhjH3nYUw==",
+ "dependencies": {
+ "@babel/code-frame": "^7.18.6",
+ "@babel/parser": "^7.18.6",
+ "@babel/types": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/traverse": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.9.tgz",
+ "integrity": "sha512-LcPAnujXGwBgv3/WHv01pHtb2tihcyW1XuL9wd7jqh1Z8AQkTd+QVjMrMijrln0T7ED3UXLIy36P9Ao7W75rYg==",
+ "dependencies": {
+ "@babel/code-frame": "^7.18.6",
+ "@babel/generator": "^7.18.9",
+ "@babel/helper-environment-visitor": "^7.18.9",
+ "@babel/helper-function-name": "^7.18.9",
+ "@babel/helper-hoist-variables": "^7.18.6",
+ "@babel/helper-split-export-declaration": "^7.18.6",
+ "@babel/parser": "^7.18.9",
+ "@babel/types": "^7.18.9",
+ "debug": "^4.1.0",
+ "globals": "^11.1.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/traverse/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==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@babel/types": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.9.tgz",
+ "integrity": "sha512-WwMLAg2MvJmt/rKEVQBBhIVffMmnilX4oe0sRe7iPOHIGsqpruFHHdrfj4O1CMMtgMtCU4oPafZjDPCRgO57Wg==",
+ "dependencies": {
+ "@babel/helper-validator-identifier": "^7.18.6",
+ "to-fast-properties": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@emotion/babel-plugin": {
+ "version": "11.9.2",
+ "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.9.2.tgz",
+ "integrity": "sha512-Pr/7HGH6H6yKgnVFNEj2MVlreu3ADqftqjqwUvDy/OJzKFgxKeTQ+eeUf20FOTuHVkDON2iNa25rAXVYtWJCjw==",
+ "dependencies": {
+ "@babel/helper-module-imports": "^7.12.13",
+ "@babel/plugin-syntax-jsx": "^7.12.13",
+ "@babel/runtime": "^7.13.10",
+ "@emotion/hash": "^0.8.0",
+ "@emotion/memoize": "^0.7.5",
+ "@emotion/serialize": "^1.0.2",
+ "babel-plugin-macros": "^2.6.1",
+ "convert-source-map": "^1.5.0",
+ "escape-string-regexp": "^4.0.0",
+ "find-root": "^1.1.0",
+ "source-map": "^0.5.7",
+ "stylis": "4.0.13"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@emotion/cache": {
+ "version": "11.9.3",
+ "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.9.3.tgz",
+ "integrity": "sha512-0dgkI/JKlCXa+lEXviaMtGBL0ynpx4osh7rjOXE71q9bIF8G+XhJgvi+wDu0B0IdCVx37BffiwXlN9I3UuzFvg==",
+ "dependencies": {
+ "@emotion/memoize": "^0.7.4",
+ "@emotion/sheet": "^1.1.1",
+ "@emotion/utils": "^1.0.0",
+ "@emotion/weak-memoize": "^0.2.5",
+ "stylis": "4.0.13"
+ }
+ },
+ "node_modules/@emotion/hash": {
+ "version": "0.8.0",
+ "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz",
+ "integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow=="
+ },
+ "node_modules/@emotion/memoize": {
+ "version": "0.7.5",
+ "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.5.tgz",
+ "integrity": "sha512-igX9a37DR2ZPGYtV6suZ6whr8pTFtyHL3K/oLUotxpSVO2ASaprmAe2Dkq7tBo7CRY7MMDrAa9nuQP9/YG8FxQ=="
+ },
+ "node_modules/@emotion/react": {
+ "version": "11.9.3",
+ "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.9.3.tgz",
+ "integrity": "sha512-g9Q1GcTOlzOEjqwuLF/Zd9LC+4FljjPjDfxSM7KmEakm+hsHXk+bYZ2q+/hTJzr0OUNkujo72pXLQvXj6H+GJQ==",
+ "dependencies": {
+ "@babel/runtime": "^7.13.10",
+ "@emotion/babel-plugin": "^11.7.1",
+ "@emotion/cache": "^11.9.3",
+ "@emotion/serialize": "^1.0.4",
+ "@emotion/utils": "^1.1.0",
+ "@emotion/weak-memoize": "^0.2.5",
+ "hoist-non-react-statics": "^3.3.1"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0",
+ "react": ">=16.8.0"
+ },
+ "peerDependenciesMeta": {
+ "@babel/core": {
+ "optional": true
+ },
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@emotion/serialize": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.0.4.tgz",
+ "integrity": "sha512-1JHamSpH8PIfFwAMryO2bNka+y8+KA5yga5Ocf2d7ZEiJjb7xlLW7aknBGZqJLajuLOvJ+72vN+IBSwPlXD1Pg==",
+ "dependencies": {
+ "@emotion/hash": "^0.8.0",
+ "@emotion/memoize": "^0.7.4",
+ "@emotion/unitless": "^0.7.5",
+ "@emotion/utils": "^1.0.0",
+ "csstype": "^3.0.2"
+ }
+ },
+ "node_modules/@emotion/sheet": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.1.1.tgz",
+ "integrity": "sha512-J3YPccVRMiTZxYAY0IOq3kd+hUP8idY8Kz6B/Cyo+JuXq52Ek+zbPbSQUrVQp95aJ+lsAW7DPL1P2Z+U1jGkKA=="
+ },
+ "node_modules/@emotion/unitless": {
+ "version": "0.7.5",
+ "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz",
+ "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg=="
+ },
+ "node_modules/@emotion/utils": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.1.0.tgz",
+ "integrity": "sha512-iRLa/Y4Rs5H/f2nimczYmS5kFJEbpiVvgN3XVfZ022IYhuNA1IRSHEizcof88LtCTXtl9S2Cxt32KgaXEu72JQ=="
+ },
+ "node_modules/@emotion/weak-memoize": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.2.5.tgz",
+ "integrity": "sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA=="
+ },
+ "node_modules/@eslint/eslintrc": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.0.tgz",
+ "integrity": "sha512-UWW0TMTmk2d7hLcWD1/e2g5HDM/HQ3csaLSqXCfqwh4uNDuNqlaKWXmEsL4Cs41Z0KnILNvwbHAah3C2yt06kw==",
+ "dev": true,
+ "dependencies": {
+ "ajv": "^6.12.4",
+ "debug": "^4.3.2",
+ "espree": "^9.3.2",
+ "globals": "^13.15.0",
+ "ignore": "^5.2.0",
+ "import-fresh": "^3.2.1",
+ "js-yaml": "^4.1.0",
+ "minimatch": "^3.1.2",
+ "strip-json-comments": "^3.1.1"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@humanwhocodes/config-array": {
+ "version": "0.9.5",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz",
+ "integrity": "sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==",
+ "dev": true,
+ "dependencies": {
+ "@humanwhocodes/object-schema": "^1.2.1",
+ "debug": "^4.1.1",
+ "minimatch": "^3.0.4"
+ },
+ "engines": {
+ "node": ">=10.10.0"
+ }
+ },
+ "node_modules/@humanwhocodes/object-schema": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz",
+ "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==",
+ "dev": true
+ },
+ "node_modules/@jridgewell/gen-mapping": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz",
+ "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==",
+ "dependencies": {
+ "@jridgewell/set-array": "^1.0.0",
+ "@jridgewell/sourcemap-codec": "^1.4.10"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/resolve-uri": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz",
+ "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/set-array": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz",
+ "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.4.14",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz",
+ "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw=="
+ },
+ "node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.14",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz",
+ "integrity": "sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ==",
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.0.3",
+ "@jridgewell/sourcemap-codec": "^1.4.10"
+ }
+ },
+ "node_modules/@next/env": {
+ "version": "12.2.2",
+ "resolved": "https://registry.npmjs.org/@next/env/-/env-12.2.2.tgz",
+ "integrity": "sha512-BqDwE4gDl1F608TpnNxZqrCn6g48MBjvmWFEmeX5wEXDXh3IkAOw6ASKUgjT8H4OUePYFqghDFUss5ZhnbOUjw=="
+ },
+ "node_modules/@next/eslint-plugin-next": {
+ "version": "12.2.2",
+ "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-12.2.2.tgz",
+ "integrity": "sha512-XOi0WzJhGH3Lk51SkSu9eZxF+IY1ZZhWcJTIGBycAbWU877IQa6+6KxMATWCOs7c+bmp6Sd8KywXJaDRxzu0JA==",
+ "dev": true,
+ "dependencies": {
+ "glob": "7.1.7"
+ }
+ },
+ "node_modules/@next/eslint-plugin-next/node_modules/glob": {
+ "version": "7.1.7",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz",
+ "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==",
+ "dev": 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/@next/swc-android-arm-eabi": {
+ "version": "12.2.2",
+ "resolved": "https://registry.npmjs.org/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-12.2.2.tgz",
+ "integrity": "sha512-VHjuCHeq9qCprUZbsRxxM/VqSW8MmsUtqB5nEpGEgUNnQi/BTm/2aK8tl7R4D0twGKRh6g1AAeFuWtXzk9Z/vQ==",
+ "cpu": [
+ "arm"
+ ],
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-android-arm64": {
+ "version": "12.2.2",
+ "resolved": "https://registry.npmjs.org/@next/swc-android-arm64/-/swc-android-arm64-12.2.2.tgz",
+ "integrity": "sha512-v5EYzXUOSv0r9mO/2PX6mOcF53k8ndlu9yeFHVAWW1Dhw2jaJcvTRcCAwYYN8Q3tDg0nH3NbEltJDLKmcJOuVA==",
+ "cpu": [
+ "arm64"
+ ],
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-darwin-arm64": {
+ "version": "12.2.2",
+ "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-12.2.2.tgz",
+ "integrity": "sha512-JCoGySHKGt+YBk7xRTFGx1QjrnCcwYxIo3yGepcOq64MoiocTM3yllQWeOAJU2/k9MH0+B5E9WUSme4rOCBbpA==",
+ "cpu": [
+ "arm64"
+ ],
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-darwin-x64": {
+ "version": "12.2.2",
+ "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-12.2.2.tgz",
+ "integrity": "sha512-dztDtvfkhUqiqpXvrWVccfGhLe44yQ5tQ7B4tBfnsOR6vxzI9DNPHTlEOgRN9qDqTAcFyPxvg86mn4l8bB9Jcw==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-freebsd-x64": {
+ "version": "12.2.2",
+ "resolved": "https://registry.npmjs.org/@next/swc-freebsd-x64/-/swc-freebsd-x64-12.2.2.tgz",
+ "integrity": "sha512-JUnXB+2xfxqsAvhFLPJpU1NeyDsvJrKoOjpV7g3Dxbno2Riu4tDKn3kKF886yleAuD/1qNTUCpqubTvbbT2VoA==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-linux-arm-gnueabihf": {
+ "version": "12.2.2",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-12.2.2.tgz",
+ "integrity": "sha512-XeYC/qqPLz58R4pjkb+x8sUUxuGLnx9QruC7/IGkK68yW4G17PHwKI/1njFYVfXTXUukpWjcfBuauWwxp9ke7Q==",
+ "cpu": [
+ "arm"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-linux-arm64-gnu": {
+ "version": "12.2.2",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-12.2.2.tgz",
+ "integrity": "sha512-d6jT8xgfKYFkzR7J0OHo2D+kFvY/6W8qEo6/hmdrTt6AKAqxs//rbbcdoyn3YQq1x6FVUUd39zzpezZntg9Naw==",
+ "cpu": [
+ "arm64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-linux-arm64-musl": {
+ "version": "12.2.2",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-12.2.2.tgz",
+ "integrity": "sha512-rIZRFxI9N/502auJT1i7coas0HTHUM+HaXMyJiCpnY8Rimbo0495ir24tzzHo3nQqJwcflcPTwEh/DV17sdv9A==",
+ "cpu": [
+ "arm64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-linux-x64-gnu": {
+ "version": "12.2.2",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-12.2.2.tgz",
+ "integrity": "sha512-ir1vNadlUDj7eQk15AvfhG5BjVizuCHks9uZwBfUgT5jyeDCeRvaDCo1+Q6+0CLOAnYDR/nqSCvBgzG2UdFh9A==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-linux-x64-musl": {
+ "version": "12.2.2",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-12.2.2.tgz",
+ "integrity": "sha512-bte5n2GzLN3O8JdSFYWZzMgEgDHZmRz5wiispiiDssj4ik3l8E7wq/czNi8RmIF+ioj2sYVokUNa/ekLzrESWw==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-win32-arm64-msvc": {
+ "version": "12.2.2",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-12.2.2.tgz",
+ "integrity": "sha512-ZUGCmcDmdPVSAlwJ/aD+1F9lYW8vttseiv4n2+VCDv5JloxiX9aY32kYZaJJO7hmTLNrprvXkb4OvNuHdN22Jg==",
+ "cpu": [
+ "arm64"
+ ],
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-win32-ia32-msvc": {
+ "version": "12.2.2",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-12.2.2.tgz",
+ "integrity": "sha512-v7ykeEDbr9eXiblGSZiEYYkWoig6sRhAbLKHUHQtk8vEWWVEqeXFcxmw6LRrKu5rCN1DY357UlYWToCGPQPCRA==",
+ "cpu": [
+ "ia32"
+ ],
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-win32-x64-msvc": {
+ "version": "12.2.2",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.2.2.tgz",
+ "integrity": "sha512-2D2iinWUL6xx8D9LYVZ5qi7FP6uLAoWymt8m8aaG2Ld/Ka8/k723fJfiklfuAcwOxfufPJI+nRbT5VcgHGzHAQ==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@nodelib/fs.scandir": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
+ "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
+ "dev": true,
+ "dependencies": {
+ "@nodelib/fs.stat": "2.0.5",
+ "run-parallel": "^1.1.9"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.stat": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+ "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
+ "dev": true,
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.walk": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
+ "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
+ "dev": true,
+ "dependencies": {
+ "@nodelib/fs.scandir": "2.1.5",
+ "fastq": "^1.6.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@reduxjs/toolkit": {
+ "version": "1.8.3",
+ "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-1.8.3.tgz",
+ "integrity": "sha512-lU/LDIfORmjBbyDLaqFN2JB9YmAT1BElET9y0ZszwhSBa5Ef3t6o5CrHupw5J1iOXwd+o92QfQZ8OJpwXvsssg==",
+ "dependencies": {
+ "immer": "^9.0.7",
+ "redux": "^4.1.2",
+ "redux-thunk": "^2.4.1",
+ "reselect": "^4.1.5"
+ },
+ "peerDependencies": {
+ "react": "^16.9.0 || ^17.0.0 || ^18",
+ "react-redux": "^7.2.1 || ^8.0.2"
+ },
+ "peerDependenciesMeta": {
+ "react": {
+ "optional": true
+ },
+ "react-redux": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@rushstack/eslint-patch": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.1.4.tgz",
+ "integrity": "sha512-LwzQKA4vzIct1zNZzBmRKI9QuNpLgTQMEjsQLf3BXuGYb3QPTP4Yjf6mkdX+X1mYttZ808QpOwAzZjv28kq7DA==",
+ "dev": true
+ },
+ "node_modules/@swc/helpers": {
+ "version": "0.4.2",
+ "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.4.2.tgz",
+ "integrity": "sha512-556Az0VX7WR6UdoTn4htt/l3zPQ7bsQWK+HqdG4swV7beUCxo/BqmvbOpUkTIm/9ih86LIf1qsUnywNL3obGHw==",
+ "dependencies": {
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@types/hoist-non-react-statics": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz",
+ "integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==",
+ "dependencies": {
+ "@types/react": "*",
+ "hoist-non-react-statics": "^3.3.0"
+ }
+ },
+ "node_modules/@types/json5": {
+ "version": "0.0.29",
+ "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
+ "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==",
+ "dev": true
+ },
+ "node_modules/@types/node": {
+ "version": "18.0.6",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-18.0.6.tgz",
+ "integrity": "sha512-/xUq6H2aQm261exT6iZTMifUySEt4GR5KX8eYyY+C4MSNPqSh9oNIP7tz2GLKTlFaiBbgZNxffoR3CVRG+cljw==",
+ "dev": true
+ },
+ "node_modules/@types/parse-json": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz",
+ "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA=="
+ },
+ "node_modules/@types/prop-types": {
+ "version": "15.7.5",
+ "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz",
+ "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w=="
+ },
+ "node_modules/@types/react": {
+ "version": "18.0.15",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.15.tgz",
+ "integrity": "sha512-iz3BtLuIYH1uWdsv6wXYdhozhqj20oD4/Hk2DNXIn1kFsmp9x8d9QB6FnPhfkbhd2PgEONt9Q1x/ebkwjfFLow==",
+ "dependencies": {
+ "@types/prop-types": "*",
+ "@types/scheduler": "*",
+ "csstype": "^3.0.2"
+ }
+ },
+ "node_modules/@types/react-dom": {
+ "version": "18.0.6",
+ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.0.6.tgz",
+ "integrity": "sha512-/5OFZgfIPSwy+YuIBP/FgJnQnsxhZhjjrnxudMddeblOouIodEQ75X14Rr4wGSG/bknL+Omy9iWlLo1u/9GzAA==",
+ "devOptional": true,
+ "dependencies": {
+ "@types/react": "*"
+ }
+ },
+ "node_modules/@types/react-redux": {
+ "version": "7.1.24",
+ "resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.24.tgz",
+ "integrity": "sha512-7FkurKcS1k0FHZEtdbbgN8Oc6b+stGSfZYjQGicofJ0j4U0qIn/jaSvnP2pLwZKiai3/17xqqxkkrxTgN8UNbQ==",
+ "dependencies": {
+ "@types/hoist-non-react-statics": "^3.3.0",
+ "@types/react": "*",
+ "hoist-non-react-statics": "^3.3.0",
+ "redux": "^4.0.0"
+ }
+ },
+ "node_modules/@types/scheduler": {
+ "version": "0.16.2",
+ "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz",
+ "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew=="
+ },
+ "node_modules/@types/use-sync-external-store": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz",
+ "integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA=="
+ },
+ "node_modules/@typescript-eslint/parser": {
+ "version": "5.30.6",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.30.6.tgz",
+ "integrity": "sha512-gfF9lZjT0p2ZSdxO70Xbw8w9sPPJGfAdjK7WikEjB3fcUI/yr9maUVEdqigBjKincUYNKOmf7QBMiTf719kbrA==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/scope-manager": "5.30.6",
+ "@typescript-eslint/types": "5.30.6",
+ "@typescript-eslint/typescript-estree": "5.30.6",
+ "debug": "^4.3.4"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/scope-manager": {
+ "version": "5.30.6",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.30.6.tgz",
+ "integrity": "sha512-Hkq5PhLgtVoW1obkqYH0i4iELctEKixkhWLPTYs55doGUKCASvkjOXOd/pisVeLdO24ZX9D6yymJ/twqpJiG3g==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "5.30.6",
+ "@typescript-eslint/visitor-keys": "5.30.6"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/types": {
+ "version": "5.30.6",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.30.6.tgz",
+ "integrity": "sha512-HdnP8HioL1F7CwVmT4RaaMX57RrfqsOMclZc08wGMiDYJBsLGBM7JwXM4cZJmbWLzIR/pXg1kkrBBVpxTOwfUg==",
+ "dev": true,
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree": {
+ "version": "5.30.6",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.30.6.tgz",
+ "integrity": "sha512-Z7TgPoeYUm06smfEfYF0RBkpF8csMyVnqQbLYiGgmUSTaSXTP57bt8f0UFXstbGxKIreTwQCujtaH0LY9w9B+A==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "5.30.6",
+ "@typescript-eslint/visitor-keys": "5.30.6",
+ "debug": "^4.3.4",
+ "globby": "^11.1.0",
+ "is-glob": "^4.0.3",
+ "semver": "^7.3.7",
+ "tsutils": "^3.21.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/visitor-keys": {
+ "version": "5.30.6",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.30.6.tgz",
+ "integrity": "sha512-41OiCjdL2mCaSDi2SvYbzFLlqqlm5v1ZW9Ym55wXKL/Rx6OOB1IbuFGo71Fj6Xy90gJDFTlgOS+vbmtGHPTQQA==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "5.30.6",
+ "eslint-visitor-keys": "^3.3.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/acorn": {
+ "version": "8.7.1",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz",
+ "integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==",
+ "dev": true,
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/acorn-jsx": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+ "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+ "dev": true,
+ "peerDependencies": {
+ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dev": true,
+ "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"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "dev": true
+ },
+ "node_modules/aria-query": {
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-4.2.2.tgz",
+ "integrity": "sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/runtime": "^7.10.2",
+ "@babel/runtime-corejs3": "^7.10.2"
+ },
+ "engines": {
+ "node": ">=6.0"
+ }
+ },
+ "node_modules/array-includes": {
+ "version": "3.1.5",
+ "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.5.tgz",
+ "integrity": "sha512-iSDYZMMyTPkiFasVqfuAQnWAYcvO/SeBSCGKePoEthjp4LEMTe4uLc7b025o4jAZpHhihh8xPo99TNWUWWkGDQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.19.5",
+ "get-intrinsic": "^1.1.1",
+ "is-string": "^1.0.7"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array-union": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
+ "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/array.prototype.flat": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.0.tgz",
+ "integrity": "sha512-12IUEkHsAhA4DY5s0FPgNXIdc8VRSqD9Zp78a5au9abH/SOBrsp082JOWFNTjkMozh8mqcdiKuaLGhPeYztxSw==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.19.2",
+ "es-shim-unscopables": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array.prototype.flatmap": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.0.tgz",
+ "integrity": "sha512-PZC9/8TKAIxcWKdyeb77EzULHPrIX/tIZebLJUQOMR1OwYosT8yggdfWScfTBCDj5utONvOuPQQumYsU2ULbkg==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.19.2",
+ "es-shim-unscopables": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/ast-types-flow": {
+ "version": "0.0.7",
+ "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz",
+ "integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==",
+ "dev": true
+ },
+ "node_modules/axe-core": {
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.4.3.tgz",
+ "integrity": "sha512-32+ub6kkdhhWick/UjvEwRchgoetXqTK14INLqbGm5U2TzBkBNF3nQtLYm8ovxSkQWArjEQvftCKryjZaATu3w==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/axobject-query": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz",
+ "integrity": "sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA==",
+ "dev": true
+ },
+ "node_modules/babel-plugin-dynamic-import-node": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz",
+ "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==",
+ "dev": true,
+ "dependencies": {
+ "object.assign": "^4.1.0"
+ }
+ },
+ "node_modules/babel-plugin-macros": {
+ "version": "2.8.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-2.8.0.tgz",
+ "integrity": "sha512-SEP5kJpfGYqYKpBrj5XU3ahw5p5GOHJ0U5ssOSQ/WBVdwkD2Dzlce95exQTs3jOVWPPKLBN2rlEWkCK7dSmLvg==",
+ "dependencies": {
+ "@babel/runtime": "^7.7.2",
+ "cosmiconfig": "^6.0.0",
+ "resolve": "^1.12.0"
+ }
+ },
+ "node_modules/babel-plugin-polyfill-corejs2": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.1.tgz",
+ "integrity": "sha512-v7/T6EQcNfVLfcN2X8Lulb7DjprieyLWJK/zOWH5DUYcAgex9sP3h25Q+DLsX9TloXe3y1O8l2q2Jv9q8UVB9w==",
+ "dev": true,
+ "dependencies": {
+ "@babel/compat-data": "^7.13.11",
+ "@babel/helper-define-polyfill-provider": "^0.3.1",
+ "semver": "^6.1.1"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/babel-plugin-polyfill-corejs3": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.2.tgz",
+ "integrity": "sha512-G3uJih0XWiID451fpeFaYGVuxHEjzKTHtc9uGFEjR6hHrvNzeS/PX+LLLcetJcytsB5m4j+K3o/EpXJNb/5IEQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-define-polyfill-provider": "^0.3.1",
+ "core-js-compat": "^3.21.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/babel-plugin-polyfill-regenerator": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.3.1.tgz",
+ "integrity": "sha512-Y2B06tvgHYt1x0yz17jGkGeeMr5FeKUu+ASJ+N6nB5lQ8Dapfg42i0OVrf8PNGJ3zKL4A23snMi1IRwrqqND7A==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-define-polyfill-provider": "^0.3.1"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "dev": true
+ },
+ "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,
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/braces": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+ "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+ "dev": true,
+ "dependencies": {
+ "fill-range": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/browserslist": {
+ "version": "4.21.2",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.2.tgz",
+ "integrity": "sha512-MonuOgAtUB46uP5CezYbRaYKBNt2LxP0yX+Pmj4LkcDFGkn9Cbpi83d9sCjwQDErXsIJSzY5oKGDbgOlF/LPAA==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ }
+ ],
+ "dependencies": {
+ "caniuse-lite": "^1.0.30001366",
+ "electron-to-chromium": "^1.4.188",
+ "node-releases": "^2.0.6",
+ "update-browserslist-db": "^1.0.4"
+ },
+ "bin": {
+ "browserslist": "cli.js"
+ },
+ "engines": {
+ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
+ }
+ },
+ "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==",
+ "dev": true,
+ "dependencies": {
+ "function-bind": "^1.1.1",
+ "get-intrinsic": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/caniuse-lite": {
+ "version": "1.0.30001367",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001367.tgz",
+ "integrity": "sha512-XDgbeOHfifWV3GEES2B8rtsrADx4Jf+juKX2SICJcaUhjYBO3bR96kvEIHa15VU6ohtOhBZuPGGYGbXMRn0NCw==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
+ }
+ ]
+ },
+ "node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+ "dev": true
+ },
+ "node_modules/convert-source-map": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz",
+ "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==",
+ "dependencies": {
+ "safe-buffer": "~5.1.1"
+ }
+ },
+ "node_modules/core-js-compat": {
+ "version": "3.23.5",
+ "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.23.5.tgz",
+ "integrity": "sha512-fHYozIFIxd+91IIbXJgWd/igXIc8Mf9is0fusswjnGIWVG96y2cwyUdlCkGOw6rMLHKAxg7xtCIVaHsyOUnJIg==",
+ "dev": true,
+ "dependencies": {
+ "browserslist": "^4.21.2",
+ "semver": "7.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/core-js"
+ }
+ },
+ "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-js-pure": {
+ "version": "3.23.5",
+ "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.23.5.tgz",
+ "integrity": "sha512-8t78LdpKSuCq4pJYCYk8hl7XEkAX+BP16yRIwL3AanTksxuEf7CM83vRyctmiEL8NDZ3jpUcv56fk9/zG3aIuw==",
+ "dev": true,
+ "hasInstallScript": true,
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/core-js"
+ }
+ },
+ "node_modules/cosmiconfig": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz",
+ "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==",
+ "dependencies": {
+ "@types/parse-json": "^4.0.0",
+ "import-fresh": "^3.1.0",
+ "parse-json": "^5.0.0",
+ "path-type": "^4.0.0",
+ "yaml": "^1.7.2"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/cross-spawn": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+ "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+ "dev": true,
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/csstype": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz",
+ "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA=="
+ },
+ "node_modules/damerau-levenshtein": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz",
+ "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==",
+ "dev": true
+ },
+ "node_modules/debug": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+ "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+ "dependencies": {
+ "ms": "2.1.2"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/deep-is": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
+ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
+ "dev": true
+ },
+ "node_modules/define-properties": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz",
+ "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==",
+ "dev": true,
+ "dependencies": {
+ "has-property-descriptors": "^1.0.0",
+ "object-keys": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/dir-glob": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
+ "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
+ "dev": true,
+ "dependencies": {
+ "path-type": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/doctrine": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
+ "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
+ "dev": true,
+ "dependencies": {
+ "esutils": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/electron-to-chromium": {
+ "version": "1.4.199",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.199.tgz",
+ "integrity": "sha512-WIGME0Cs7oob3mxsJwHbeWkH0tYkIE/sjkJ8ML2BYmuRcjhRl/q5kVDXG7W9LOOKwzPU5M0LBlXRq9rlSgnNlg=="
+ },
+ "node_modules/emoji-regex": {
+ "version": "9.2.2",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
+ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
+ "dev": true
+ },
+ "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==",
+ "dependencies": {
+ "is-arrayish": "^0.2.1"
+ }
+ },
+ "node_modules/es-abstract": {
+ "version": "1.20.1",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.1.tgz",
+ "integrity": "sha512-WEm2oBhfoI2sImeM4OF2zE2V3BYdSF+KnSi9Sidz51fQHd7+JuF8Xgcj9/0o+OWeIeIS/MiuNnlruQrJf16GQA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "es-to-primitive": "^1.2.1",
+ "function-bind": "^1.1.1",
+ "function.prototype.name": "^1.1.5",
+ "get-intrinsic": "^1.1.1",
+ "get-symbol-description": "^1.0.0",
+ "has": "^1.0.3",
+ "has-property-descriptors": "^1.0.0",
+ "has-symbols": "^1.0.3",
+ "internal-slot": "^1.0.3",
+ "is-callable": "^1.2.4",
+ "is-negative-zero": "^2.0.2",
+ "is-regex": "^1.1.4",
+ "is-shared-array-buffer": "^1.0.2",
+ "is-string": "^1.0.7",
+ "is-weakref": "^1.0.2",
+ "object-inspect": "^1.12.0",
+ "object-keys": "^1.1.1",
+ "object.assign": "^4.1.2",
+ "regexp.prototype.flags": "^1.4.3",
+ "string.prototype.trimend": "^1.0.5",
+ "string.prototype.trimstart": "^1.0.5",
+ "unbox-primitive": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/es-shim-unscopables": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz",
+ "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==",
+ "dev": true,
+ "dependencies": {
+ "has": "^1.0.3"
+ }
+ },
+ "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,
+ "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"
+ }
+ },
+ "node_modules/escalade": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
+ "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/eslint": {
+ "version": "8.20.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.20.0.tgz",
+ "integrity": "sha512-d4ixhz5SKCa1D6SCPrivP7yYVi7nyD6A4vs6HIAul9ujBzcEmZVM3/0NN/yu5nKhmO1wjp5xQ46iRfmDGlOviA==",
+ "dev": true,
+ "dependencies": {
+ "@eslint/eslintrc": "^1.3.0",
+ "@humanwhocodes/config-array": "^0.9.2",
+ "ajv": "^6.10.0",
+ "chalk": "^4.0.0",
+ "cross-spawn": "^7.0.2",
+ "debug": "^4.3.2",
+ "doctrine": "^3.0.0",
+ "escape-string-regexp": "^4.0.0",
+ "eslint-scope": "^7.1.1",
+ "eslint-utils": "^3.0.0",
+ "eslint-visitor-keys": "^3.3.0",
+ "espree": "^9.3.2",
+ "esquery": "^1.4.0",
+ "esutils": "^2.0.2",
+ "fast-deep-equal": "^3.1.3",
+ "file-entry-cache": "^6.0.1",
+ "functional-red-black-tree": "^1.0.1",
+ "glob-parent": "^6.0.1",
+ "globals": "^13.15.0",
+ "ignore": "^5.2.0",
+ "import-fresh": "^3.0.0",
+ "imurmurhash": "^0.1.4",
+ "is-glob": "^4.0.0",
+ "js-yaml": "^4.1.0",
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "levn": "^0.4.1",
+ "lodash.merge": "^4.6.2",
+ "minimatch": "^3.1.2",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.9.1",
+ "regexpp": "^3.2.0",
+ "strip-ansi": "^6.0.1",
+ "strip-json-comments": "^3.1.0",
+ "text-table": "^0.2.0",
+ "v8-compile-cache": "^2.0.3"
+ },
+ "bin": {
+ "eslint": "bin/eslint.js"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint-config-next": {
+ "version": "12.2.2",
+ "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-12.2.2.tgz",
+ "integrity": "sha512-oJhWBLC4wDYYUFv/5APbjHUFd0QRFCojMdj/QnMoOEktmeTvwnnoA8F8uaXs0fQgsaTK0tbUxBRv9/Y4/rpxOA==",
+ "dev": true,
+ "dependencies": {
+ "@next/eslint-plugin-next": "12.2.2",
+ "@rushstack/eslint-patch": "^1.1.3",
+ "@typescript-eslint/parser": "^5.21.0",
+ "eslint-import-resolver-node": "^0.3.6",
+ "eslint-import-resolver-typescript": "^2.7.1",
+ "eslint-plugin-import": "^2.26.0",
+ "eslint-plugin-jsx-a11y": "^6.5.1",
+ "eslint-plugin-react": "^7.29.4",
+ "eslint-plugin-react-hooks": "^4.5.0"
+ },
+ "peerDependencies": {
+ "eslint": "^7.23.0 || ^8.0.0",
+ "typescript": ">=3.3.1"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/eslint-import-resolver-node": {
+ "version": "0.3.6",
+ "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz",
+ "integrity": "sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw==",
+ "dev": true,
+ "dependencies": {
+ "debug": "^3.2.7",
+ "resolve": "^1.20.0"
+ }
+ },
+ "node_modules/eslint-import-resolver-node/node_modules/debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "dev": true,
+ "dependencies": {
+ "ms": "^2.1.1"
+ }
+ },
+ "node_modules/eslint-import-resolver-typescript": {
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-2.7.1.tgz",
+ "integrity": "sha512-00UbgGwV8bSgUv34igBDbTOtKhqoRMy9bFjNehT40bXg6585PNIct8HhXZ0SybqB9rWtXj9crcku8ndDn/gIqQ==",
+ "dev": true,
+ "dependencies": {
+ "debug": "^4.3.4",
+ "glob": "^7.2.0",
+ "is-glob": "^4.0.3",
+ "resolve": "^1.22.0",
+ "tsconfig-paths": "^3.14.1"
+ },
+ "engines": {
+ "node": ">=4"
+ },
+ "peerDependencies": {
+ "eslint": "*",
+ "eslint-plugin-import": "*"
+ }
+ },
+ "node_modules/eslint-module-utils": {
+ "version": "2.7.3",
+ "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.3.tgz",
+ "integrity": "sha512-088JEC7O3lDZM9xGe0RerkOMd0EjFl+Yvd1jPWIkMT5u3H9+HC34mWWPnqPrN13gieT9pBOO+Qt07Nb/6TresQ==",
+ "dev": true,
+ "dependencies": {
+ "debug": "^3.2.7",
+ "find-up": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/eslint-module-utils/node_modules/debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "dev": true,
+ "dependencies": {
+ "ms": "^2.1.1"
+ }
+ },
+ "node_modules/eslint-plugin-import": {
+ "version": "2.26.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.26.0.tgz",
+ "integrity": "sha512-hYfi3FXaM8WPLf4S1cikh/r4IxnO6zrhZbEGz2b660EJRbuxgpDS5gkCuYgGWg2xxh2rBuIr4Pvhve/7c31koA==",
+ "dev": true,
+ "dependencies": {
+ "array-includes": "^3.1.4",
+ "array.prototype.flat": "^1.2.5",
+ "debug": "^2.6.9",
+ "doctrine": "^2.1.0",
+ "eslint-import-resolver-node": "^0.3.6",
+ "eslint-module-utils": "^2.7.3",
+ "has": "^1.0.3",
+ "is-core-module": "^2.8.1",
+ "is-glob": "^4.0.3",
+ "minimatch": "^3.1.2",
+ "object.values": "^1.1.5",
+ "resolve": "^1.22.0",
+ "tsconfig-paths": "^3.14.1"
+ },
+ "engines": {
+ "node": ">=4"
+ },
+ "peerDependencies": {
+ "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8"
+ }
+ },
+ "node_modules/eslint-plugin-import/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/eslint-plugin-import/node_modules/doctrine": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
+ "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
+ "dev": true,
+ "dependencies": {
+ "esutils": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/eslint-plugin-import/node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "dev": true
+ },
+ "node_modules/eslint-plugin-jsx-a11y": {
+ "version": "6.6.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.6.0.tgz",
+ "integrity": "sha512-kTeLuIzpNhXL2CwLlc8AHI0aFRwWHcg483yepO9VQiHzM9bZwJdzTkzBszbuPrbgGmq2rlX/FaT2fJQsjUSHsw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/runtime": "^7.18.3",
+ "aria-query": "^4.2.2",
+ "array-includes": "^3.1.5",
+ "ast-types-flow": "^0.0.7",
+ "axe-core": "^4.4.2",
+ "axobject-query": "^2.2.0",
+ "damerau-levenshtein": "^1.0.8",
+ "emoji-regex": "^9.2.2",
+ "has": "^1.0.3",
+ "jsx-ast-utils": "^3.3.1",
+ "language-tags": "^1.0.5",
+ "minimatch": "^3.1.2",
+ "semver": "^6.3.0"
+ },
+ "engines": {
+ "node": ">=4.0"
+ },
+ "peerDependencies": {
+ "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8"
+ }
+ },
+ "node_modules/eslint-plugin-jsx-a11y/node_modules/semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/eslint-plugin-react": {
+ "version": "7.30.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.30.1.tgz",
+ "integrity": "sha512-NbEvI9jtqO46yJA3wcRF9Mo0lF9T/jhdHqhCHXiXtD+Zcb98812wvokjWpU7Q4QH5edo6dmqrukxVvWWXHlsUg==",
+ "dev": true,
+ "dependencies": {
+ "array-includes": "^3.1.5",
+ "array.prototype.flatmap": "^1.3.0",
+ "doctrine": "^2.1.0",
+ "estraverse": "^5.3.0",
+ "jsx-ast-utils": "^2.4.1 || ^3.0.0",
+ "minimatch": "^3.1.2",
+ "object.entries": "^1.1.5",
+ "object.fromentries": "^2.0.5",
+ "object.hasown": "^1.1.1",
+ "object.values": "^1.1.5",
+ "prop-types": "^15.8.1",
+ "resolve": "^2.0.0-next.3",
+ "semver": "^6.3.0",
+ "string.prototype.matchall": "^4.0.7"
+ },
+ "engines": {
+ "node": ">=4"
+ },
+ "peerDependencies": {
+ "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8"
+ }
+ },
+ "node_modules/eslint-plugin-react-hooks": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz",
+ "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0"
+ }
+ },
+ "node_modules/eslint-plugin-react/node_modules/doctrine": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
+ "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
+ "dev": true,
+ "dependencies": {
+ "esutils": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/eslint-plugin-react/node_modules/resolve": {
+ "version": "2.0.0-next.4",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.4.tgz",
+ "integrity": "sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ==",
+ "dev": true,
+ "dependencies": {
+ "is-core-module": "^2.9.0",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ },
+ "bin": {
+ "resolve": "bin/resolve"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/eslint-plugin-react/node_modules/semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/eslint-scope": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz",
+ "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==",
+ "dev": true,
+ "dependencies": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ }
+ },
+ "node_modules/eslint-utils": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz",
+ "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==",
+ "dev": true,
+ "dependencies": {
+ "eslint-visitor-keys": "^2.0.0"
+ },
+ "engines": {
+ "node": "^10.0.0 || ^12.0.0 || >= 14.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/mysticatea"
+ },
+ "peerDependencies": {
+ "eslint": ">=5"
+ }
+ },
+ "node_modules/eslint-utils/node_modules/eslint-visitor-keys": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz",
+ "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/eslint-visitor-keys": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz",
+ "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==",
+ "dev": true,
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ }
+ },
+ "node_modules/espree": {
+ "version": "9.3.2",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.2.tgz",
+ "integrity": "sha512-D211tC7ZwouTIuY5x9XnS0E9sWNChB7IYKX/Xp5eQj3nFXhqmiUDB9q27y76oFl8jTg3pXcQx/bpxMfs3CIZbA==",
+ "dev": true,
+ "dependencies": {
+ "acorn": "^8.7.1",
+ "acorn-jsx": "^5.3.2",
+ "eslint-visitor-keys": "^3.3.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ }
+ },
+ "node_modules/esquery": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz",
+ "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==",
+ "dev": true,
+ "dependencies": {
+ "estraverse": "^5.1.0"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/esrecurse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+ "dev": true,
+ "dependencies": {
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "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,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+ "dev": true
+ },
+ "node_modules/fast-glob": {
+ "version": "3.2.11",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz",
+ "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==",
+ "dev": true,
+ "dependencies": {
+ "@nodelib/fs.stat": "^2.0.2",
+ "@nodelib/fs.walk": "^1.2.3",
+ "glob-parent": "^5.1.2",
+ "merge2": "^1.3.0",
+ "micromatch": "^4.0.4"
+ },
+ "engines": {
+ "node": ">=8.6.0"
+ }
+ },
+ "node_modules/fast-glob/node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dev": true,
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "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
+ },
+ "node_modules/fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
+ "dev": true
+ },
+ "node_modules/fastq": {
+ "version": "1.13.0",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz",
+ "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==",
+ "dev": true,
+ "dependencies": {
+ "reusify": "^1.0.4"
+ }
+ },
+ "node_modules/file-entry-cache": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
+ "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
+ "dev": true,
+ "dependencies": {
+ "flat-cache": "^3.0.4"
+ },
+ "engines": {
+ "node": "^10.12.0 || >=12.0.0"
+ }
+ },
+ "node_modules/fill-range": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+ "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+ "dev": true,
+ "dependencies": {
+ "to-regex-range": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/find-root": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz",
+ "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng=="
+ },
+ "node_modules/find-up": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
+ "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==",
+ "dev": true,
+ "dependencies": {
+ "locate-path": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/flat-cache": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz",
+ "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==",
+ "dev": true,
+ "dependencies": {
+ "flatted": "^3.1.0",
+ "rimraf": "^3.0.2"
+ },
+ "engines": {
+ "node": "^10.12.0 || >=12.0.0"
+ }
+ },
+ "node_modules/flatted": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.6.tgz",
+ "integrity": "sha512-0sQoMh9s0BYsm+12Huy/rkKxVu4R1+r96YX5cG44rHV0pQ6iC3Q+mkoMFaGWObMFYQxCVT+ssG1ksneA2MI9KQ==",
+ "dev": true
+ },
+ "node_modules/fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
+ "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=="
+ },
+ "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==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.19.0",
+ "functions-have-names": "^1.2.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/functional-red-black-tree": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
+ "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==",
+ "dev": true
+ },
+ "node_modules/functions-have-names": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
+ "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/gensync": {
+ "version": "1.0.0-beta.2",
+ "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
+ "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/get-intrinsic": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.2.tgz",
+ "integrity": "sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==",
+ "dev": true,
+ "dependencies": {
+ "function-bind": "^1.1.1",
+ "has": "^1.0.3",
+ "has-symbols": "^1.0.3"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "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==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "get-intrinsic": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "dev": true,
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/glob-parent": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+ "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+ "dev": true,
+ "dependencies": {
+ "is-glob": "^4.0.3"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/globals": {
+ "version": "13.16.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-13.16.0.tgz",
+ "integrity": "sha512-A1lrQfpNF+McdPOnnFqY3kSN0AFTy485bTi1bkLk4mVPODIUEcSfhHgRqA+QdXPksrSTTztYXx37NFV+GpGk3Q==",
+ "dev": true,
+ "dependencies": {
+ "type-fest": "^0.20.2"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/globby": {
+ "version": "11.1.0",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
+ "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
+ "dev": true,
+ "dependencies": {
+ "array-union": "^2.1.0",
+ "dir-glob": "^3.0.1",
+ "fast-glob": "^3.2.9",
+ "ignore": "^5.2.0",
+ "merge2": "^1.4.1",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/has": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+ "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+ "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",
+ "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "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==",
+ "dev": true,
+ "dependencies": {
+ "get-intrinsic": "^1.1.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-symbols": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
+ "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "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==",
+ "dev": true,
+ "dependencies": {
+ "has-symbols": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/hoist-non-react-statics": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
+ "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
+ "dependencies": {
+ "react-is": "^16.7.0"
+ }
+ },
+ "node_modules/ignore": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz",
+ "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==",
+ "dev": true,
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/immer": {
+ "version": "9.0.15",
+ "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.15.tgz",
+ "integrity": "sha512-2eB/sswms9AEUSkOm4SbV5Y7Vmt/bKRwByd52jfLkW4OLYeaTP3EEiJ9agqU0O/tq6Dk62Zfj+TJSqfm1rLVGQ==",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/immer"
+ }
+ },
+ "node_modules/import-fresh": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
+ "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
+ "dependencies": {
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.8.19"
+ }
+ },
+ "node_modules/inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+ "dev": true,
+ "dependencies": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "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
+ },
+ "node_modules/internal-slot": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz",
+ "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==",
+ "dev": true,
+ "dependencies": {
+ "get-intrinsic": "^1.1.0",
+ "has": "^1.0.3",
+ "side-channel": "^1.0.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/invariant": {
+ "version": "2.2.4",
+ "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
+ "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
+ "dependencies": {
+ "loose-envify": "^1.0.0"
+ }
+ },
+ "node_modules/is-arrayish": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+ "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg=="
+ },
+ "node_modules/is-bigint": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz",
+ "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==",
+ "dev": true,
+ "dependencies": {
+ "has-bigints": "^1.0.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-boolean-object": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz",
+ "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-callable": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz",
+ "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-core-module": {
+ "version": "2.9.0",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz",
+ "integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==",
+ "dependencies": {
+ "has": "^1.0.3"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-date-object": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz",
+ "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==",
+ "dev": true,
+ "dependencies": {
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "dev": true,
+ "dependencies": {
+ "is-extglob": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "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==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/is-number-object": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz",
+ "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==",
+ "dev": true,
+ "dependencies": {
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-regex": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
+ "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "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==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-string": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz",
+ "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==",
+ "dev": true,
+ "dependencies": {
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-symbol": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz",
+ "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==",
+ "dev": true,
+ "dependencies": {
+ "has-symbols": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "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",
+ "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "dev": true
+ },
+ "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=="
+ },
+ "node_modules/js-yaml": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+ "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "dev": true,
+ "dependencies": {
+ "argparse": "^2.0.1"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/jsesc": {
+ "version": "2.5.2",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
+ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
+ "bin": {
+ "jsesc": "bin/jsesc"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/json-parse-even-better-errors": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
+ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w=="
+ },
+ "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
+ },
+ "node_modules/json-stable-stringify-without-jsonify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
+ "dev": true
+ },
+ "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,
+ "dependencies": {
+ "minimist": "^1.2.0"
+ },
+ "bin": {
+ "json5": "lib/cli.js"
+ }
+ },
+ "node_modules/jsx-ast-utils": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.2.tgz",
+ "integrity": "sha512-4ZCADZHRkno244xlNnn4AOG6sRQ7iBZ5BbgZ4vW4y5IZw7cVUD1PPeblm1xx/nfmMxPdt/LHsXZW8z/j58+l9Q==",
+ "dev": true,
+ "dependencies": {
+ "array-includes": "^3.1.5",
+ "object.assign": "^4.1.2"
+ },
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/just-curry-it": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/just-curry-it/-/just-curry-it-3.2.1.tgz",
+ "integrity": "sha512-Q8206k8pTY7krW32cdmPsP+DqqLgWx/hYPSj9/+7SYqSqz7UuwPbfSe07lQtvuuaVyiSJveXk0E5RydOuWwsEg=="
+ },
+ "node_modules/language-subtag-registry": {
+ "version": "0.3.22",
+ "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz",
+ "integrity": "sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==",
+ "dev": true
+ },
+ "node_modules/language-tags": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.5.tgz",
+ "integrity": "sha512-qJhlO9cGXi6hBGKoxEG/sKZDAHD5Hnu9Hs4WbOY3pCWXDhw0N8x1NenNzm2EnNLkLkk7J2SdxAkDSbb6ftT+UQ==",
+ "dev": true,
+ "dependencies": {
+ "language-subtag-registry": "~0.3.2"
+ }
+ },
+ "node_modules/levn": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+ "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+ "dev": true,
+ "dependencies": {
+ "prelude-ls": "^1.2.1",
+ "type-check": "~0.4.0"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/lines-and-columns": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
+ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="
+ },
+ "node_modules/locate-path": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
+ "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==",
+ "dev": true,
+ "dependencies": {
+ "p-locate": "^2.0.0",
+ "path-exists": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/lodash.debounce": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
+ "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==",
+ "dev": true
+ },
+ "node_modules/lodash.merge": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
+ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
+ "dev": true
+ },
+ "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==",
+ "dependencies": {
+ "js-tokens": "^3.0.0 || ^4.0.0"
+ },
+ "bin": {
+ "loose-envify": "cli.js"
+ }
+ },
+ "node_modules/lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "dev": true,
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/merge2": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/micromatch": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
+ "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
+ "dev": true,
+ "dependencies": {
+ "braces": "^3.0.2",
+ "picomatch": "^2.3.1"
+ },
+ "engines": {
+ "node": ">=8.6"
+ }
+ },
+ "node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/minimist": {
+ "version": "1.2.6",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
+ "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==",
+ "dev": true
+ },
+ "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=="
+ },
+ "node_modules/nanoid": {
+ "version": "3.3.4",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz",
+ "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==",
+ "bin": {
+ "nanoid": "bin/nanoid.cjs"
+ },
+ "engines": {
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ }
+ },
+ "node_modules/natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
+ "dev": true
+ },
+ "node_modules/next": {
+ "version": "12.2.2",
+ "resolved": "https://registry.npmjs.org/next/-/next-12.2.2.tgz",
+ "integrity": "sha512-zAYFY45aBry/PlKONqtlloRFqU/We3zWYdn2NoGvDZkoYUYQSJC8WMcalS5C19MxbCZLUVCX7D7a6gTGgl2yLg==",
+ "dependencies": {
+ "@next/env": "12.2.2",
+ "@swc/helpers": "0.4.2",
+ "caniuse-lite": "^1.0.30001332",
+ "postcss": "8.4.5",
+ "styled-jsx": "5.0.2",
+ "use-sync-external-store": "1.1.0"
+ },
+ "bin": {
+ "next": "dist/bin/next"
+ },
+ "engines": {
+ "node": ">=12.22.0"
+ },
+ "optionalDependencies": {
+ "@next/swc-android-arm-eabi": "12.2.2",
+ "@next/swc-android-arm64": "12.2.2",
+ "@next/swc-darwin-arm64": "12.2.2",
+ "@next/swc-darwin-x64": "12.2.2",
+ "@next/swc-freebsd-x64": "12.2.2",
+ "@next/swc-linux-arm-gnueabihf": "12.2.2",
+ "@next/swc-linux-arm64-gnu": "12.2.2",
+ "@next/swc-linux-arm64-musl": "12.2.2",
+ "@next/swc-linux-x64-gnu": "12.2.2",
+ "@next/swc-linux-x64-musl": "12.2.2",
+ "@next/swc-win32-arm64-msvc": "12.2.2",
+ "@next/swc-win32-ia32-msvc": "12.2.2",
+ "@next/swc-win32-x64-msvc": "12.2.2"
+ },
+ "peerDependencies": {
+ "fibers": ">= 3.1.0",
+ "node-sass": "^6.0.0 || ^7.0.0",
+ "react": "^17.0.2 || ^18.0.0-0",
+ "react-dom": "^17.0.2 || ^18.0.0-0",
+ "sass": "^1.3.0"
+ },
+ "peerDependenciesMeta": {
+ "fibers": {
+ "optional": true
+ },
+ "node-sass": {
+ "optional": true
+ },
+ "sass": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/node-releases": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz",
+ "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg=="
+ },
+ "node_modules/object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/object-inspect": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz",
+ "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "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,
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/object.assign": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz",
+ "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.0",
+ "define-properties": "^1.1.3",
+ "has-symbols": "^1.0.1",
+ "object-keys": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/object.entries": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.5.tgz",
+ "integrity": "sha512-TyxmjUoZggd4OrrU1W66FMDG6CuqJxsFvymeyXI51+vQLN67zYfZseptRge703kKQdo4uccgAKebXFcRCzk4+g==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.19.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/object.fromentries": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.5.tgz",
+ "integrity": "sha512-CAyG5mWQRRiBU57Re4FKoTBjXfDoNwdFVH2Y1tS9PqCsfUTymAohOkEMSG3aRNKmv4lV3O7p1et7c187q6bynw==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.19.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/object.hasown": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.1.tgz",
+ "integrity": "sha512-LYLe4tivNQzq4JdaWW6WO3HMZZJWzkkH8fnI6EebWl0VZth2wL2Lovm74ep2/gZzlaTdV62JZHEqHQ2yVn8Q/A==",
+ "dev": true,
+ "dependencies": {
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.19.5"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/object.values": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.5.tgz",
+ "integrity": "sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.19.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+ "dev": true,
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
+ "node_modules/optionator": {
+ "version": "0.9.1",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz",
+ "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==",
+ "dev": true,
+ "dependencies": {
+ "deep-is": "^0.1.3",
+ "fast-levenshtein": "^2.0.6",
+ "levn": "^0.4.1",
+ "prelude-ls": "^1.2.1",
+ "type-check": "^0.4.0",
+ "word-wrap": "^1.2.3"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "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,
+ "dependencies": {
+ "p-try": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/p-locate": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz",
+ "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==",
+ "dev": true,
+ "dependencies": {
+ "p-limit": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/p-try": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
+ "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/parent-module": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+ "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+ "dependencies": {
+ "callsites": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/parse-json": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
+ "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
+ "dependencies": {
+ "@babel/code-frame": "^7.0.0",
+ "error-ex": "^1.3.1",
+ "json-parse-even-better-errors": "^2.3.0",
+ "lines-and-columns": "^1.1.6"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/path-exists": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
+ "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "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": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-parse": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="
+ },
+ "node_modules/path-type": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
+ "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/picocolors": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
+ "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ=="
+ },
+ "node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "dev": true,
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/postcss": {
+ "version": "8.4.5",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.5.tgz",
+ "integrity": "sha512-jBDboWM8qpaqwkMwItqTQTiFikhs/67OYVvblFFTM7MrZjt6yMKd6r2kgXizEbTTljacm4NldIlZnhbjr84QYg==",
+ "dependencies": {
+ "nanoid": "^3.1.30",
+ "picocolors": "^1.0.0",
+ "source-map-js": "^1.0.1"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ }
+ },
+ "node_modules/prelude-ls": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/prop-types": {
+ "version": "15.8.1",
+ "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
+ "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
+ "dependencies": {
+ "loose-envify": "^1.4.0",
+ "object-assign": "^4.1.1",
+ "react-is": "^16.13.1"
+ }
+ },
+ "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,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/queue-microtask": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/react": {
+ "version": "18.2.0",
+ "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz",
+ "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==",
+ "dependencies": {
+ "loose-envify": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/react-dom": {
+ "version": "18.2.0",
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz",
+ "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==",
+ "dependencies": {
+ "loose-envify": "^1.1.0",
+ "scheduler": "^0.23.0"
+ },
+ "peerDependencies": {
+ "react": "^18.2.0"
+ }
+ },
+ "node_modules/react-is": {
+ "version": "16.13.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
+ },
+ "node_modules/react-redux": {
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-8.0.2.tgz",
+ "integrity": "sha512-nBwiscMw3NoP59NFCXFf02f8xdo+vSHT/uZ1ldDwF7XaTpzm+Phk97VT4urYBl5TYAPNVaFm12UHAEyzkpNzRA==",
+ "dependencies": {
+ "@babel/runtime": "^7.12.1",
+ "@types/hoist-non-react-statics": "^3.3.1",
+ "@types/use-sync-external-store": "^0.0.3",
+ "hoist-non-react-statics": "^3.3.2",
+ "react-is": "^18.0.0",
+ "use-sync-external-store": "^1.0.0"
+ },
+ "peerDependencies": {
+ "@types/react": "^16.8 || ^17.0 || ^18.0",
+ "@types/react-dom": "^16.8 || ^17.0 || ^18.0",
+ "react": "^16.8 || ^17.0 || ^18.0",
+ "react-dom": "^16.8 || ^17.0 || ^18.0",
+ "react-native": ">=0.59",
+ "redux": "^4"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ },
+ "react-dom": {
+ "optional": true
+ },
+ "react-native": {
+ "optional": true
+ },
+ "redux": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/react-redux/node_modules/react-is": {
+ "version": "18.2.0",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
+ "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w=="
+ },
+ "node_modules/reduce-reducers": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/reduce-reducers/-/reduce-reducers-0.4.3.tgz",
+ "integrity": "sha512-+CNMnI8QhgVMtAt54uQs3kUxC3Sybpa7Y63HR14uGLgI9/QR5ggHvpxwhGGe3wmx5V91YwqQIblN9k5lspAmGw=="
+ },
+ "node_modules/redux": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.0.tgz",
+ "integrity": "sha512-oSBmcKKIuIR4ME29/AeNUnl5L+hvBq7OaJWzaptTQJAntaPvxIJqfnjbaEiCzzaIz+XmVILfqAM3Ob0aXLPfjA==",
+ "dependencies": {
+ "@babel/runtime": "^7.9.2"
+ }
+ },
+ "node_modules/redux-actions": {
+ "version": "2.6.5",
+ "resolved": "https://registry.npmjs.org/redux-actions/-/redux-actions-2.6.5.tgz",
+ "integrity": "sha512-pFhEcWFTYNk7DhQgxMGnbsB1H2glqhQJRQrtPb96kD3hWiZRzXHwwmFPswg6V2MjraXRXWNmuP9P84tvdLAJmw==",
+ "dependencies": {
+ "invariant": "^2.2.4",
+ "just-curry-it": "^3.1.0",
+ "loose-envify": "^1.4.0",
+ "reduce-reducers": "^0.4.3",
+ "to-camel-case": "^1.0.0"
+ }
+ },
+ "node_modules/redux-flash": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/redux-flash/-/redux-flash-2.0.2.tgz",
+ "integrity": "sha512-tX8Yxf13uy2IVvQm5VpiGabirGySZhM9DZGzDsmU818px5bpmbUsxqCnUy/NtTmUEJnFuU+vL6IYejkbwHr/Dw==",
+ "dependencies": {
+ "prop-types": "^15.6.1",
+ "redux-actions": "^2.6.5",
+ "uuid": "^3.1.0"
+ },
+ "peerDependencies": {
+ "redux": "^4.0.0 || ^3.0.0"
+ }
+ },
+ "node_modules/redux-thunk": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.1.tgz",
+ "integrity": "sha512-OOYGNY5Jy2TWvTL1KgAlVy6dcx3siPJ1wTq741EPyUKfn6W6nChdICjZwCd0p8AZBs5kWpZlbkXW2nE/zjUa+Q==",
+ "peerDependencies": {
+ "redux": "^4"
+ }
+ },
+ "node_modules/regenerate": {
+ "version": "1.4.2",
+ "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz",
+ "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==",
+ "dev": true
+ },
+ "node_modules/regenerate-unicode-properties": {
+ "version": "10.0.1",
+ "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.0.1.tgz",
+ "integrity": "sha512-vn5DU6yg6h8hP/2OkQo3K7uVILvY4iu0oI4t3HFa81UPkhGJwkRwM10JEc3upjdhHjs/k8GJY1sRBhk5sr69Bw==",
+ "dev": true,
+ "dependencies": {
+ "regenerate": "^1.4.2"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/regenerator-runtime": {
+ "version": "0.13.9",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz",
+ "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA=="
+ },
+ "node_modules/regenerator-transform": {
+ "version": "0.15.0",
+ "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.0.tgz",
+ "integrity": "sha512-LsrGtPmbYg19bcPHwdtmXwbW+TqNvtY4riE3P83foeHRroMbH6/2ddFBfab3t7kbzc7v7p4wbkIecHImqt0QNg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/runtime": "^7.8.4"
+ }
+ },
+ "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==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.3",
+ "functions-have-names": "^1.2.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/regexpp": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz",
+ "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/mysticatea"
+ }
+ },
+ "node_modules/regexpu-core": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.1.0.tgz",
+ "integrity": "sha512-bb6hk+xWd2PEOkj5It46A16zFMs2mv86Iwpdu94la4S3sJ7C973h2dHpYKwIBGaWSO7cIRJ+UX0IeMaWcO4qwA==",
+ "dev": true,
+ "dependencies": {
+ "regenerate": "^1.4.2",
+ "regenerate-unicode-properties": "^10.0.1",
+ "regjsgen": "^0.6.0",
+ "regjsparser": "^0.8.2",
+ "unicode-match-property-ecmascript": "^2.0.0",
+ "unicode-match-property-value-ecmascript": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/regjsgen": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.6.0.tgz",
+ "integrity": "sha512-ozE883Uigtqj3bx7OhL1KNbCzGyW2NQZPl6Hs09WTvCuZD5sTI4JY58bkbQWa/Y9hxIsvJ3M8Nbf7j54IqeZbA==",
+ "dev": true
+ },
+ "node_modules/regjsparser": {
+ "version": "0.8.4",
+ "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.8.4.tgz",
+ "integrity": "sha512-J3LABycON/VNEu3abOviqGHuB/LOtOQj8SKmfP9anY5GfAVw/SPjwzSjxGjbZXIxbGfqTHtJw58C2Li/WkStmA==",
+ "dev": true,
+ "dependencies": {
+ "jsesc": "~0.5.0"
+ },
+ "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": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==",
+ "dev": true,
+ "bin": {
+ "jsesc": "bin/jsesc"
+ }
+ },
+ "node_modules/reselect": {
+ "version": "4.1.6",
+ "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.6.tgz",
+ "integrity": "sha512-ZovIuXqto7elwnxyXbBtCPo9YFEr3uJqj2rRbcOOog1bmu2Ag85M4hixSwFWyaBMKXNgvPaJ9OSu9SkBPIeJHQ=="
+ },
+ "node_modules/resolve": {
+ "version": "1.22.1",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
+ "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==",
+ "dependencies": {
+ "is-core-module": "^2.9.0",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ },
+ "bin": {
+ "resolve": "bin/resolve"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/resolve-from": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/reusify": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
+ "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
+ "dev": true,
+ "engines": {
+ "iojs": ">=1.0.0",
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/rimraf": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+ "dev": true,
+ "dependencies": {
+ "glob": "^7.1.3"
+ },
+ "bin": {
+ "rimraf": "bin.js"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/run-parallel": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+ "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "dependencies": {
+ "queue-microtask": "^1.2.2"
+ }
+ },
+ "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=="
+ },
+ "node_modules/scheduler": {
+ "version": "0.23.0",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz",
+ "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==",
+ "dependencies": {
+ "loose-envify": "^1.1.0"
+ }
+ },
+ "node_modules/semver": {
+ "version": "7.3.7",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
+ "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==",
+ "dev": true,
+ "dependencies": {
+ "lru-cache": "^6.0.0"
+ },
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dev": true,
+ "dependencies": {
+ "shebang-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "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==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.0",
+ "get-intrinsic": "^1.0.2",
+ "object-inspect": "^1.9.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/slash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/source-map": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/source-map-js": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
+ "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/string.prototype.matchall": {
+ "version": "4.0.7",
+ "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.7.tgz",
+ "integrity": "sha512-f48okCX7JiwVi1NXCVWcFnZgADDC/n2vePlQ/KUCNqCikLLilQvwjMO8+BHVKvgzH0JB0J9LEPgxOGT02RoETg==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.19.1",
+ "get-intrinsic": "^1.1.1",
+ "has-symbols": "^1.0.3",
+ "internal-slot": "^1.0.3",
+ "regexp.prototype.flags": "^1.4.1",
+ "side-channel": "^1.0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/string.prototype.trimend": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz",
+ "integrity": "sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.19.5"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/string.prototype.trimstart": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz",
+ "integrity": "sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.19.5"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-bom": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+ "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/strip-json-comments": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/styled-jsx": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.0.2.tgz",
+ "integrity": "sha512-LqPQrbBh3egD57NBcHET4qcgshPks+yblyhPlH2GY8oaDgKs8SK4C3dBh3oSJjgzJ3G5t1SYEZGHkP+QEpX9EQ==",
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "peerDependencies": {
+ "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0"
+ },
+ "peerDependenciesMeta": {
+ "@babel/core": {
+ "optional": true
+ },
+ "babel-plugin-macros": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/stylis": {
+ "version": "4.0.13",
+ "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.0.13.tgz",
+ "integrity": "sha512-xGPXiFVl4YED9Jh7Euv2V220mriG9u4B2TA6Ybjc1catrstKD2PpIdU3U0RKpkVBC2EhmL/F0sPCr9vrFTNRag=="
+ },
+ "node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/supports-preserve-symlinks-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/text-table": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
+ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
+ "dev": true
+ },
+ "node_modules/to-camel-case": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/to-camel-case/-/to-camel-case-1.0.0.tgz",
+ "integrity": "sha512-nD8pQi5H34kyu1QDMFjzEIYqk0xa9Alt6ZfrdEMuHCFOfTLhDG5pgTu/aAM9Wt9lXILwlXmWP43b8sav0GNE8Q==",
+ "dependencies": {
+ "to-space-case": "^1.0.0"
+ }
+ },
+ "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": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/to-no-case": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/to-no-case/-/to-no-case-1.0.2.tgz",
+ "integrity": "sha512-Z3g735FxuZY8rodxV4gH7LxClE4H0hTIyHNIHdk+vpQxjLm0cwnKXq/OFVZ76SOQmto7txVcwSCwkU5kqp+FKg=="
+ },
+ "node_modules/to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dev": true,
+ "dependencies": {
+ "is-number": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=8.0"
+ }
+ },
+ "node_modules/to-space-case": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/to-space-case/-/to-space-case-1.0.0.tgz",
+ "integrity": "sha512-rLdvwXZ39VOn1IxGL3V6ZstoTbwLRckQmn/U8ZDLuWwIXNpuZDhQ3AiRUlhTbOXFVE9C+dR51wM0CBDhk31VcA==",
+ "dependencies": {
+ "to-no-case": "^1.0.0"
+ }
+ },
+ "node_modules/tsconfig-paths": {
+ "version": "3.14.1",
+ "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz",
+ "integrity": "sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/json5": "^0.0.29",
+ "json5": "^1.0.1",
+ "minimist": "^1.2.6",
+ "strip-bom": "^3.0.0"
+ }
+ },
+ "node_modules/tslib": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz",
+ "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ=="
+ },
+ "node_modules/tsutils": {
+ "version": "3.21.0",
+ "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz",
+ "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==",
+ "dev": true,
+ "dependencies": {
+ "tslib": "^1.8.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ },
+ "peerDependencies": {
+ "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta"
+ }
+ },
+ "node_modules/tsutils/node_modules/tslib": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
+ "dev": true
+ },
+ "node_modules/type-check": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+ "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
+ "dev": true,
+ "dependencies": {
+ "prelude-ls": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/type-fest": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
+ "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/typescript": {
+ "version": "4.7.4",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz",
+ "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==",
+ "dev": true,
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=4.2.0"
+ }
+ },
+ "node_modules/unbox-primitive": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz",
+ "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "has-bigints": "^1.0.2",
+ "has-symbols": "^1.0.3",
+ "which-boxed-primitive": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/unicode-canonical-property-names-ecmascript": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz",
+ "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/unicode-match-property-ecmascript": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz",
+ "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==",
+ "dev": true,
+ "dependencies": {
+ "unicode-canonical-property-names-ecmascript": "^2.0.0",
+ "unicode-property-aliases-ecmascript": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/unicode-match-property-value-ecmascript": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz",
+ "integrity": "sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/unicode-property-aliases-ecmascript": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.0.0.tgz",
+ "integrity": "sha512-5Zfuy9q/DFr4tfO7ZPeVXb1aPoeQSdeFMLpYuFebehDAhbuevLs5yxSZmIFN1tP5F9Wl4IpJrYojg85/zgyZHQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/update-browserslist-db": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.5.tgz",
+ "integrity": "sha512-dteFFpCyvuDdr9S/ff1ISkKt/9YZxKjI9WlRR99c180GaztJtRa/fn18FdxGVKVsnPY7/a/FDN68mcvUmP4U7Q==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ }
+ ],
+ "dependencies": {
+ "escalade": "^3.1.1",
+ "picocolors": "^1.0.0"
+ },
+ "bin": {
+ "browserslist-lint": "cli.js"
+ },
+ "peerDependencies": {
+ "browserslist": ">= 4.21.0"
+ }
+ },
+ "node_modules/uri-js": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+ "dev": true,
+ "dependencies": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "node_modules/use-sync-external-store": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.1.0.tgz",
+ "integrity": "sha512-SEnieB2FPKEVne66NpXPd1Np4R1lTNKfjuy3XdIoPQKYBAFdzbzSZlSn1KJZUiihQLQC5Znot4SBz1EOTBwQAQ==",
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0"
+ }
+ },
+ "node_modules/uuid": {
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
+ "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
+ "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.",
+ "bin": {
+ "uuid": "bin/uuid"
+ }
+ },
+ "node_modules/v8-compile-cache": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz",
+ "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==",
+ "dev": true
+ },
+ "node_modules/which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dev": true,
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/which-boxed-primitive": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz",
+ "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==",
+ "dev": true,
+ "dependencies": {
+ "is-bigint": "^1.0.1",
+ "is-boolean-object": "^1.1.0",
+ "is-number-object": "^1.0.4",
+ "is-string": "^1.0.5",
+ "is-symbol": "^1.0.3"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "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,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
+ "dev": true
+ },
+ "node_modules/yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true
+ },
+ "node_modules/yaml": {
+ "version": "1.10.2",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz",
+ "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==",
+ "engines": {
+ "node": ">= 6"
+ }
+ }
+ },
+ "dependencies": {
+ "@ampproject/remapping": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz",
+ "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==",
+ "requires": {
+ "@jridgewell/gen-mapping": "^0.1.0",
+ "@jridgewell/trace-mapping": "^0.3.9"
+ }
+ },
+ "@babel/code-frame": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz",
+ "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==",
+ "requires": {
+ "@babel/highlight": "^7.18.6"
+ }
+ },
+ "@babel/compat-data": {
+ "version": "7.18.8",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.18.8.tgz",
+ "integrity": "sha512-HSmX4WZPPK3FUxYp7g2T6EyO8j96HlZJlxmKPSh6KAcqwyDrfx7hKjXpAW/0FhFfTJsR0Yt4lAjLI2coMptIHQ=="
+ },
+ "@babel/core": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.9.tgz",
+ "integrity": "sha512-1LIb1eL8APMy91/IMW+31ckrfBM4yCoLaVzoDhZUKSM4cu1L1nIidyxkCgzPAgrC5WEz36IPEr/eSeSF9pIn+g==",
+ "requires": {
+ "@ampproject/remapping": "^2.1.0",
+ "@babel/code-frame": "^7.18.6",
+ "@babel/generator": "^7.18.9",
+ "@babel/helper-compilation-targets": "^7.18.9",
+ "@babel/helper-module-transforms": "^7.18.9",
+ "@babel/helpers": "^7.18.9",
+ "@babel/parser": "^7.18.9",
+ "@babel/template": "^7.18.6",
+ "@babel/traverse": "^7.18.9",
+ "@babel/types": "^7.18.9",
+ "convert-source-map": "^1.7.0",
+ "debug": "^4.1.0",
+ "gensync": "^1.0.0-beta.2",
+ "json5": "^2.2.1",
+ "semver": "^6.3.0"
+ },
+ "dependencies": {
+ "json5": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz",
+ "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA=="
+ },
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
+ }
+ }
+ },
+ "@babel/generator": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.9.tgz",
+ "integrity": "sha512-wt5Naw6lJrL1/SGkipMiFxJjtyczUWTP38deiP1PO60HsBjDeKk08CGC3S8iVuvf0FmTdgKwU1KIXzSKL1G0Ug==",
+ "requires": {
+ "@babel/types": "^7.18.9",
+ "@jridgewell/gen-mapping": "^0.3.2",
+ "jsesc": "^2.5.1"
+ },
+ "dependencies": {
+ "@jridgewell/gen-mapping": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz",
+ "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==",
+ "requires": {
+ "@jridgewell/set-array": "^1.0.1",
+ "@jridgewell/sourcemap-codec": "^1.4.10",
+ "@jridgewell/trace-mapping": "^0.3.9"
+ }
+ }
+ }
+ },
+ "@babel/helper-annotate-as-pure": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz",
+ "integrity": "sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.18.6"
+ }
+ },
+ "@babel/helper-builder-binary-assignment-operator-visitor": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.18.9.tgz",
+ "integrity": "sha512-yFQ0YCHoIqarl8BCRwBL8ulYUaZpz3bNsA7oFepAzee+8/+ImtADXNOmO5vJvsPff3qi+hvpkY/NYBTrBQgdNw==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-explode-assignable-expression": "^7.18.6",
+ "@babel/types": "^7.18.9"
+ }
+ },
+ "@babel/helper-compilation-targets": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.9.tgz",
+ "integrity": "sha512-tzLCyVmqUiFlcFoAPLA/gL9TeYrF61VLNtb+hvkuVaB5SUjW7jcfrglBIX1vUIoT7CLP3bBlIMeyEsIl2eFQNg==",
+ "requires": {
+ "@babel/compat-data": "^7.18.8",
+ "@babel/helper-validator-option": "^7.18.6",
+ "browserslist": "^4.20.2",
+ "semver": "^6.3.0"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
+ }
+ }
+ },
+ "@babel/helper-create-class-features-plugin": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.18.9.tgz",
+ "integrity": "sha512-WvypNAYaVh23QcjpMR24CwZY2Nz6hqdOcFdPbNpV56hL5H6KiFheO7Xm1aPdlLQ7d5emYZX7VZwPp9x3z+2opw==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-annotate-as-pure": "^7.18.6",
+ "@babel/helper-environment-visitor": "^7.18.9",
+ "@babel/helper-function-name": "^7.18.9",
+ "@babel/helper-member-expression-to-functions": "^7.18.9",
+ "@babel/helper-optimise-call-expression": "^7.18.6",
+ "@babel/helper-replace-supers": "^7.18.9",
+ "@babel/helper-split-export-declaration": "^7.18.6"
+ }
+ },
+ "@babel/helper-create-regexp-features-plugin": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.18.6.tgz",
+ "integrity": "sha512-7LcpH1wnQLGrI+4v+nPp+zUvIkF9x0ddv1Hkdue10tg3gmRnLy97DXh4STiOf1qeIInyD69Qv5kKSZzKD8B/7A==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-annotate-as-pure": "^7.18.6",
+ "regexpu-core": "^5.1.0"
+ }
+ },
+ "@babel/helper-define-polyfill-provider": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.1.tgz",
+ "integrity": "sha512-J9hGMpJQmtWmj46B3kBHmL38UhJGhYX7eqkcq+2gsstyYt341HmPeWspihX43yVRA0mS+8GGk2Gckc7bY/HCmA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-compilation-targets": "^7.13.0",
+ "@babel/helper-module-imports": "^7.12.13",
+ "@babel/helper-plugin-utils": "^7.13.0",
+ "@babel/traverse": "^7.13.0",
+ "debug": "^4.1.1",
+ "lodash.debounce": "^4.0.8",
+ "resolve": "^1.14.2",
+ "semver": "^6.1.2"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true
+ }
+ }
+ },
+ "@babel/helper-environment-visitor": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz",
+ "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg=="
+ },
+ "@babel/helper-explode-assignable-expression": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.18.6.tgz",
+ "integrity": "sha512-eyAYAsQmB80jNfg4baAtLeWAQHfHFiR483rzFK+BhETlGZaQC9bsfrugfXDCbRHLQbIA7U5NxhhOxN7p/dWIcg==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.18.6"
+ }
+ },
+ "@babel/helper-function-name": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.18.9.tgz",
+ "integrity": "sha512-fJgWlZt7nxGksJS9a0XdSaI4XvpExnNIgRP+rVefWh5U7BL8pPuir6SJUmFKRfjWQ51OtWSzwOxhaH/EBWWc0A==",
+ "requires": {
+ "@babel/template": "^7.18.6",
+ "@babel/types": "^7.18.9"
+ }
+ },
+ "@babel/helper-hoist-variables": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz",
+ "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==",
+ "requires": {
+ "@babel/types": "^7.18.6"
+ }
+ },
+ "@babel/helper-member-expression-to-functions": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.9.tgz",
+ "integrity": "sha512-RxifAh2ZoVU67PyKIO4AMi1wTenGfMR/O/ae0CCRqwgBAt5v7xjdtRw7UoSbsreKrQn5t7r89eruK/9JjYHuDg==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.18.9"
+ }
+ },
+ "@babel/helper-module-imports": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz",
+ "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==",
+ "requires": {
+ "@babel/types": "^7.18.6"
+ }
+ },
+ "@babel/helper-module-transforms": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.18.9.tgz",
+ "integrity": "sha512-KYNqY0ICwfv19b31XzvmI/mfcylOzbLtowkw+mfvGPAQ3kfCnMLYbED3YecL5tPd8nAYFQFAd6JHp2LxZk/J1g==",
+ "requires": {
+ "@babel/helper-environment-visitor": "^7.18.9",
+ "@babel/helper-module-imports": "^7.18.6",
+ "@babel/helper-simple-access": "^7.18.6",
+ "@babel/helper-split-export-declaration": "^7.18.6",
+ "@babel/helper-validator-identifier": "^7.18.6",
+ "@babel/template": "^7.18.6",
+ "@babel/traverse": "^7.18.9",
+ "@babel/types": "^7.18.9"
+ }
+ },
+ "@babel/helper-optimise-call-expression": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz",
+ "integrity": "sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.18.6"
+ }
+ },
+ "@babel/helper-plugin-utils": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.18.9.tgz",
+ "integrity": "sha512-aBXPT3bmtLryXaoJLyYPXPlSD4p1ld9aYeR+sJNOZjJJGiOpb+fKfh3NkcCu7J54nUJwCERPBExCCpyCOHnu/w=="
+ },
+ "@babel/helper-remap-async-to-generator": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.18.9.tgz",
+ "integrity": "sha512-dI7q50YKd8BAv3VEfgg7PS7yD3Rtbi2J1XMXaalXO0W0164hYLnh8zpjRS0mte9MfVp/tltvr/cfdXPvJr1opA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-annotate-as-pure": "^7.18.6",
+ "@babel/helper-environment-visitor": "^7.18.9",
+ "@babel/helper-wrap-function": "^7.18.9",
+ "@babel/types": "^7.18.9"
+ }
+ },
+ "@babel/helper-replace-supers": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.18.9.tgz",
+ "integrity": "sha512-dNsWibVI4lNT6HiuOIBr1oyxo40HvIVmbwPUm3XZ7wMh4k2WxrxTqZwSqw/eEmXDS9np0ey5M2bz9tBmO9c+YQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-environment-visitor": "^7.18.9",
+ "@babel/helper-member-expression-to-functions": "^7.18.9",
+ "@babel/helper-optimise-call-expression": "^7.18.6",
+ "@babel/traverse": "^7.18.9",
+ "@babel/types": "^7.18.9"
+ }
+ },
+ "@babel/helper-simple-access": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz",
+ "integrity": "sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g==",
+ "requires": {
+ "@babel/types": "^7.18.6"
+ }
+ },
+ "@babel/helper-skip-transparent-expression-wrappers": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.18.9.tgz",
+ "integrity": "sha512-imytd2gHi3cJPsybLRbmFrF7u5BIEuI2cNheyKi3/iOBC63kNn3q8Crn2xVuESli0aM4KYsyEqKyS7lFL8YVtw==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.18.9"
+ }
+ },
+ "@babel/helper-split-export-declaration": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz",
+ "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==",
+ "requires": {
+ "@babel/types": "^7.18.6"
+ }
+ },
+ "@babel/helper-validator-identifier": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz",
+ "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g=="
+ },
+ "@babel/helper-validator-option": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz",
+ "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw=="
+ },
+ "@babel/helper-wrap-function": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.18.9.tgz",
+ "integrity": "sha512-cG2ru3TRAL6a60tfQflpEfs4ldiPwF6YW3zfJiRgmoFVIaC1vGnBBgatfec+ZUziPHkHSaXAuEck3Cdkf3eRpQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-function-name": "^7.18.9",
+ "@babel/template": "^7.18.6",
+ "@babel/traverse": "^7.18.9",
+ "@babel/types": "^7.18.9"
+ }
+ },
+ "@babel/helpers": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.18.9.tgz",
+ "integrity": "sha512-Jf5a+rbrLoR4eNdUmnFu8cN5eNJT6qdTdOg5IHIzq87WwyRw9PwguLFOWYgktN/60IP4fgDUawJvs7PjQIzELQ==",
+ "requires": {
+ "@babel/template": "^7.18.6",
+ "@babel/traverse": "^7.18.9",
+ "@babel/types": "^7.18.9"
+ }
+ },
+ "@babel/highlight": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz",
+ "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==",
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.18.6",
+ "chalk": "^2.0.0",
+ "js-tokens": "^4.0.0"
+ },
+ "dependencies": {
+ "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==",
+ "requires": {
+ "color-convert": "^1.9.0"
+ }
+ },
+ "chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "requires": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ }
+ },
+ "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==",
+ "requires": {
+ "color-name": "1.1.3"
+ }
+ },
+ "color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="
+ },
+ "escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="
+ },
+ "has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw=="
+ },
+ "supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ }
+ }
+ },
+ "@babel/parser": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.9.tgz",
+ "integrity": "sha512-9uJveS9eY9DJ0t64YbIBZICtJy8a5QrDEVdiLCG97fVLpDTpGX7t8mMSb6OWw6Lrnjqj4O8zwjELX3dhoMgiBg=="
+ },
+ "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.18.6.tgz",
+ "integrity": "sha512-Dgxsyg54Fx1d4Nge8UnvTrED63vrwOdPmyvPzlNN/boaliRP54pm3pGzZD1SJUwrBA+Cs/xdG8kXX6Mn/RfISQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.18.6"
+ }
+ },
+ "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.18.9.tgz",
+ "integrity": "sha512-AHrP9jadvH7qlOj6PINbgSuphjQUAK7AOT7DPjBo9EHoLhQTnnK5u45e1Hd4DbSQEO9nqPWtQ89r+XEOWFScKg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.18.9",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.18.9",
+ "@babel/plugin-proposal-optional-chaining": "^7.18.9"
+ }
+ },
+ "@babel/plugin-proposal-async-generator-functions": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.18.6.tgz",
+ "integrity": "sha512-WAz4R9bvozx4qwf74M+sfqPMKfSqwM0phxPTR6iJIi8robgzXwkEgmeJG1gEKhm6sDqT/U9aV3lfcqybIpev8w==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-environment-visitor": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6",
+ "@babel/helper-remap-async-to-generator": "^7.18.6",
+ "@babel/plugin-syntax-async-generators": "^7.8.4"
+ }
+ },
+ "@babel/plugin-proposal-class-properties": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz",
+ "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-create-class-features-plugin": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6"
+ }
+ },
+ "@babel/plugin-proposal-class-static-block": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.18.6.tgz",
+ "integrity": "sha512-+I3oIiNxrCpup3Gi8n5IGMwj0gOCAjcJUSQEcotNnCCPMEnixawOQ+KeJPlgfjzx+FKQ1QSyZOWe7wmoJp7vhw==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-create-class-features-plugin": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6",
+ "@babel/plugin-syntax-class-static-block": "^7.14.5"
+ }
+ },
+ "@babel/plugin-proposal-dynamic-import": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.18.6.tgz",
+ "integrity": "sha512-1auuwmK+Rz13SJj36R+jqFPMJWyKEDd7lLSdOj4oJK0UTgGueSAtkrCvz9ewmgyU/P941Rv2fQwZJN8s6QruXw==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.18.6",
+ "@babel/plugin-syntax-dynamic-import": "^7.8.3"
+ }
+ },
+ "@babel/plugin-proposal-export-namespace-from": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.18.9.tgz",
+ "integrity": "sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.18.9",
+ "@babel/plugin-syntax-export-namespace-from": "^7.8.3"
+ }
+ },
+ "@babel/plugin-proposal-json-strings": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.18.6.tgz",
+ "integrity": "sha512-lr1peyn9kOdbYc0xr0OdHTZ5FMqS6Di+H0Fz2I/JwMzGmzJETNeOFq2pBySw6X/KFL5EWDjlJuMsUGRFb8fQgQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.18.6",
+ "@babel/plugin-syntax-json-strings": "^7.8.3"
+ }
+ },
+ "@babel/plugin-proposal-logical-assignment-operators": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.18.9.tgz",
+ "integrity": "sha512-128YbMpjCrP35IOExw2Fq+x55LMP42DzhOhX2aNNIdI9avSWl2PI0yuBWarr3RYpZBSPtabfadkH2yeRiMD61Q==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.18.9",
+ "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4"
+ }
+ },
+ "@babel/plugin-proposal-nullish-coalescing-operator": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz",
+ "integrity": "sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.18.6",
+ "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3"
+ }
+ },
+ "@babel/plugin-proposal-numeric-separator": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz",
+ "integrity": "sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.18.6",
+ "@babel/plugin-syntax-numeric-separator": "^7.10.4"
+ }
+ },
+ "@babel/plugin-proposal-object-rest-spread": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.18.9.tgz",
+ "integrity": "sha512-kDDHQ5rflIeY5xl69CEqGEZ0KY369ehsCIEbTGb4siHG5BE9sga/T0r0OUwyZNLMmZE79E1kbsqAjwFCW4ds6Q==",
+ "dev": true,
+ "requires": {
+ "@babel/compat-data": "^7.18.8",
+ "@babel/helper-compilation-targets": "^7.18.9",
+ "@babel/helper-plugin-utils": "^7.18.9",
+ "@babel/plugin-syntax-object-rest-spread": "^7.8.3",
+ "@babel/plugin-transform-parameters": "^7.18.8"
+ }
+ },
+ "@babel/plugin-proposal-optional-catch-binding": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz",
+ "integrity": "sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.18.6",
+ "@babel/plugin-syntax-optional-catch-binding": "^7.8.3"
+ }
+ },
+ "@babel/plugin-proposal-optional-chaining": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.18.9.tgz",
+ "integrity": "sha512-v5nwt4IqBXihxGsW2QmCWMDS3B3bzGIk/EQVZz2ei7f3NJl8NzAJVvUmpDW5q1CRNY+Beb/k58UAH1Km1N411w==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.18.9",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.18.9",
+ "@babel/plugin-syntax-optional-chaining": "^7.8.3"
+ }
+ },
+ "@babel/plugin-proposal-private-methods": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz",
+ "integrity": "sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-create-class-features-plugin": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6"
+ }
+ },
+ "@babel/plugin-proposal-private-property-in-object": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.18.6.tgz",
+ "integrity": "sha512-9Rysx7FOctvT5ouj5JODjAFAkgGoudQuLPamZb0v1TGLpapdNaftzifU8NTWQm0IRjqoYypdrSmyWgkocDQ8Dw==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-annotate-as-pure": "^7.18.6",
+ "@babel/helper-create-class-features-plugin": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6",
+ "@babel/plugin-syntax-private-property-in-object": "^7.14.5"
+ }
+ },
+ "@babel/plugin-proposal-unicode-property-regex": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz",
+ "integrity": "sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-create-regexp-features-plugin": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6"
+ }
+ },
+ "@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": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ }
+ },
+ "@babel/plugin-syntax-class-properties": {
+ "version": "7.12.13",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz",
+ "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.12.13"
+ }
+ },
+ "@babel/plugin-syntax-class-static-block": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz",
+ "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ }
+ },
+ "@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": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ }
+ },
+ "@babel/plugin-syntax-export-namespace-from": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz",
+ "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.3"
+ }
+ },
+ "@babel/plugin-syntax-import-assertions": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.18.6.tgz",
+ "integrity": "sha512-/DU3RXad9+bZwrgWJQKbr39gYbJpLJHezqEzRzi/BHRlJ9zsQb4CK2CA/5apllXNomwA1qHwzvHl+AdEmC5krQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.18.6"
+ }
+ },
+ "@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": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ }
+ },
+ "@babel/plugin-syntax-jsx": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz",
+ "integrity": "sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.18.6"
+ }
+ },
+ "@babel/plugin-syntax-logical-assignment-operators": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz",
+ "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ }
+ },
+ "@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": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ }
+ },
+ "@babel/plugin-syntax-numeric-separator": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz",
+ "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ }
+ },
+ "@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": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ }
+ },
+ "@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": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ }
+ },
+ "@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": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ }
+ },
+ "@babel/plugin-syntax-private-property-in-object": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz",
+ "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ }
+ },
+ "@babel/plugin-syntax-top-level-await": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz",
+ "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ }
+ },
+ "@babel/plugin-transform-arrow-functions": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.18.6.tgz",
+ "integrity": "sha512-9S9X9RUefzrsHZmKMbDXxweEH+YlE8JJEuat9FdvW9Qh1cw7W64jELCtWNkPBPX5En45uy28KGvA/AySqUh8CQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.18.6"
+ }
+ },
+ "@babel/plugin-transform-async-to-generator": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.18.6.tgz",
+ "integrity": "sha512-ARE5wZLKnTgPW7/1ftQmSi1CmkqqHo2DNmtztFhvgtOWSDfq0Cq9/9L+KnZNYSNrydBekhW3rwShduf59RoXag==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-module-imports": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6",
+ "@babel/helper-remap-async-to-generator": "^7.18.6"
+ }
+ },
+ "@babel/plugin-transform-block-scoped-functions": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.18.6.tgz",
+ "integrity": "sha512-ExUcOqpPWnliRcPqves5HJcJOvHvIIWfuS4sroBUenPuMdmW+SMHDakmtS7qOo13sVppmUijqeTv7qqGsvURpQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.18.6"
+ }
+ },
+ "@babel/plugin-transform-block-scoping": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.18.9.tgz",
+ "integrity": "sha512-5sDIJRV1KtQVEbt/EIBwGy4T01uYIo4KRB3VUqzkhrAIOGx7AoctL9+Ux88btY0zXdDyPJ9mW+bg+v+XEkGmtw==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.18.9"
+ }
+ },
+ "@babel/plugin-transform-classes": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.18.9.tgz",
+ "integrity": "sha512-EkRQxsxoytpTlKJmSPYrsOMjCILacAjtSVkd4gChEe2kXjFCun3yohhW5I7plXJhCemM0gKsaGMcO8tinvCA5g==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-annotate-as-pure": "^7.18.6",
+ "@babel/helper-environment-visitor": "^7.18.9",
+ "@babel/helper-function-name": "^7.18.9",
+ "@babel/helper-optimise-call-expression": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.9",
+ "@babel/helper-replace-supers": "^7.18.9",
+ "@babel/helper-split-export-declaration": "^7.18.6",
+ "globals": "^11.1.0"
+ },
+ "dependencies": {
+ "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
+ }
+ }
+ },
+ "@babel/plugin-transform-computed-properties": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.18.9.tgz",
+ "integrity": "sha512-+i0ZU1bCDymKakLxn5srGHrsAPRELC2WIbzwjLhHW9SIE1cPYkLCL0NlnXMZaM1vhfgA2+M7hySk42VBvrkBRw==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.18.9"
+ }
+ },
+ "@babel/plugin-transform-destructuring": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.18.9.tgz",
+ "integrity": "sha512-p5VCYNddPLkZTq4XymQIaIfZNJwT9YsjkPOhkVEqt6QIpQFZVM9IltqqYpOEkJoN1DPznmxUDyZ5CTZs/ZCuHA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.18.9"
+ }
+ },
+ "@babel/plugin-transform-dotall-regex": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.18.6.tgz",
+ "integrity": "sha512-6S3jpun1eEbAxq7TdjLotAsl4WpQI9DxfkycRcKrjhQYzU87qpXdknpBg/e+TdcMehqGnLFi7tnFUBR02Vq6wg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-create-regexp-features-plugin": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6"
+ }
+ },
+ "@babel/plugin-transform-duplicate-keys": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.18.9.tgz",
+ "integrity": "sha512-d2bmXCtZXYc59/0SanQKbiWINadaJXqtvIQIzd4+hNwkWBgyCd5F/2t1kXoUdvPMrxzPvhK6EMQRROxsue+mfw==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.18.9"
+ }
+ },
+ "@babel/plugin-transform-exponentiation-operator": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.18.6.tgz",
+ "integrity": "sha512-wzEtc0+2c88FVR34aQmiz56dxEkxr2g8DQb/KfaFa1JYXOFVsbhvAonFN6PwVWj++fKmku8NP80plJ5Et4wqHw==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-builder-binary-assignment-operator-visitor": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6"
+ }
+ },
+ "@babel/plugin-transform-for-of": {
+ "version": "7.18.8",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.18.8.tgz",
+ "integrity": "sha512-yEfTRnjuskWYo0k1mHUqrVWaZwrdq8AYbfrpqULOJOaucGSp4mNMVps+YtA8byoevxS/urwU75vyhQIxcCgiBQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.18.6"
+ }
+ },
+ "@babel/plugin-transform-function-name": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.18.9.tgz",
+ "integrity": "sha512-WvIBoRPaJQ5yVHzcnJFor7oS5Ls0PYixlTYE63lCj2RtdQEl15M68FXQlxnG6wdraJIXRdR7KI+hQ7q/9QjrCQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-compilation-targets": "^7.18.9",
+ "@babel/helper-function-name": "^7.18.9",
+ "@babel/helper-plugin-utils": "^7.18.9"
+ }
+ },
+ "@babel/plugin-transform-literals": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.18.9.tgz",
+ "integrity": "sha512-IFQDSRoTPnrAIrI5zoZv73IFeZu2dhu6irxQjY9rNjTT53VmKg9fenjvoiOWOkJ6mm4jKVPtdMzBY98Fp4Z4cg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.18.9"
+ }
+ },
+ "@babel/plugin-transform-member-expression-literals": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.18.6.tgz",
+ "integrity": "sha512-qSF1ihLGO3q+/g48k85tUjD033C29TNTVB2paCwZPVmOsjn9pClvYYrM2VeJpBY2bcNkuny0YUyTNRyRxJ54KA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.18.6"
+ }
+ },
+ "@babel/plugin-transform-modules-amd": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.18.6.tgz",
+ "integrity": "sha512-Pra5aXsmTsOnjM3IajS8rTaLCy++nGM4v3YR4esk5PCsyg9z8NA5oQLwxzMUtDBd8F+UmVza3VxoAaWCbzH1rg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-module-transforms": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6",
+ "babel-plugin-dynamic-import-node": "^2.3.3"
+ }
+ },
+ "@babel/plugin-transform-modules-commonjs": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.18.6.tgz",
+ "integrity": "sha512-Qfv2ZOWikpvmedXQJDSbxNqy7Xr/j2Y8/KfijM0iJyKkBTmWuvCA1yeH1yDM7NJhBW/2aXxeucLj6i80/LAJ/Q==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-module-transforms": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6",
+ "@babel/helper-simple-access": "^7.18.6",
+ "babel-plugin-dynamic-import-node": "^2.3.3"
+ }
+ },
+ "@babel/plugin-transform-modules-systemjs": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.18.9.tgz",
+ "integrity": "sha512-zY/VSIbbqtoRoJKo2cDTewL364jSlZGvn0LKOf9ntbfxOvjfmyrdtEEOAdswOswhZEb8UH3jDkCKHd1sPgsS0A==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-hoist-variables": "^7.18.6",
+ "@babel/helper-module-transforms": "^7.18.9",
+ "@babel/helper-plugin-utils": "^7.18.9",
+ "@babel/helper-validator-identifier": "^7.18.6",
+ "babel-plugin-dynamic-import-node": "^2.3.3"
+ }
+ },
+ "@babel/plugin-transform-modules-umd": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.18.6.tgz",
+ "integrity": "sha512-dcegErExVeXcRqNtkRU/z8WlBLnvD4MRnHgNs3MytRO1Mn1sHRyhbcpYbVMGclAqOjdW+9cfkdZno9dFdfKLfQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-module-transforms": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6"
+ }
+ },
+ "@babel/plugin-transform-named-capturing-groups-regex": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.18.6.tgz",
+ "integrity": "sha512-UmEOGF8XgaIqD74bC8g7iV3RYj8lMf0Bw7NJzvnS9qQhM4mg+1WHKotUIdjxgD2RGrgFLZZPCFPFj3P/kVDYhg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-create-regexp-features-plugin": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6"
+ }
+ },
+ "@babel/plugin-transform-new-target": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.18.6.tgz",
+ "integrity": "sha512-DjwFA/9Iu3Z+vrAn+8pBUGcjhxKguSMlsFqeCKbhb9BAV756v0krzVK04CRDi/4aqmk8BsHb4a/gFcaA5joXRw==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.18.6"
+ }
+ },
+ "@babel/plugin-transform-object-super": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.18.6.tgz",
+ "integrity": "sha512-uvGz6zk+pZoS1aTZrOvrbj6Pp/kK2mp45t2B+bTDre2UgsZZ8EZLSJtUg7m/no0zOJUWgFONpB7Zv9W2tSaFlA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.18.6",
+ "@babel/helper-replace-supers": "^7.18.6"
+ }
+ },
+ "@babel/plugin-transform-parameters": {
+ "version": "7.18.8",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.18.8.tgz",
+ "integrity": "sha512-ivfbE3X2Ss+Fj8nnXvKJS6sjRG4gzwPMsP+taZC+ZzEGjAYlvENixmt1sZ5Ca6tWls+BlKSGKPJ6OOXvXCbkFg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.18.6"
+ }
+ },
+ "@babel/plugin-transform-property-literals": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.18.6.tgz",
+ "integrity": "sha512-cYcs6qlgafTud3PAzrrRNbQtfpQ8+y/+M5tKmksS9+M1ckbH6kzY8MrexEM9mcA6JDsukE19iIRvAyYl463sMg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.18.6"
+ }
+ },
+ "@babel/plugin-transform-regenerator": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.18.6.tgz",
+ "integrity": "sha512-poqRI2+qiSdeldcz4wTSTXBRryoq3Gc70ye7m7UD5Ww0nE29IXqMl6r7Nd15WBgRd74vloEMlShtH6CKxVzfmQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.18.6",
+ "regenerator-transform": "^0.15.0"
+ }
+ },
+ "@babel/plugin-transform-reserved-words": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.18.6.tgz",
+ "integrity": "sha512-oX/4MyMoypzHjFrT1CdivfKZ+XvIPMFXwwxHp/r0Ddy2Vuomt4HDFGmft1TAY2yiTKiNSsh3kjBAzcM8kSdsjA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.18.6"
+ }
+ },
+ "@babel/plugin-transform-shorthand-properties": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.18.6.tgz",
+ "integrity": "sha512-eCLXXJqv8okzg86ywZJbRn19YJHU4XUa55oz2wbHhaQVn/MM+XhukiT7SYqp/7o00dg52Rj51Ny+Ecw4oyoygw==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.18.6"
+ }
+ },
+ "@babel/plugin-transform-spread": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.18.9.tgz",
+ "integrity": "sha512-39Q814wyoOPtIB/qGopNIL9xDChOE1pNU0ZY5dO0owhiVt/5kFm4li+/bBtwc7QotG0u5EPzqhZdjMtmqBqyQA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.18.9",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.18.9"
+ }
+ },
+ "@babel/plugin-transform-sticky-regex": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.18.6.tgz",
+ "integrity": "sha512-kfiDrDQ+PBsQDO85yj1icueWMfGfJFKN1KCkndygtu/C9+XUfydLC8Iv5UYJqRwy4zk8EcplRxEOeLyjq1gm6Q==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.18.6"
+ }
+ },
+ "@babel/plugin-transform-template-literals": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.18.9.tgz",
+ "integrity": "sha512-S8cOWfT82gTezpYOiVaGHrCbhlHgKhQt8XH5ES46P2XWmX92yisoZywf5km75wv5sYcXDUCLMmMxOLCtthDgMA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.18.9"
+ }
+ },
+ "@babel/plugin-transform-typeof-symbol": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.18.9.tgz",
+ "integrity": "sha512-SRfwTtF11G2aemAZWivL7PD+C9z52v9EvMqH9BuYbabyPuKUvSWks3oCg6041pT925L4zVFqaVBeECwsmlguEw==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.18.9"
+ }
+ },
+ "@babel/plugin-transform-unicode-escapes": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.18.6.tgz",
+ "integrity": "sha512-XNRwQUXYMP7VLuy54cr/KS/WeL3AZeORhrmeZ7iewgu+X2eBqmpaLI/hzqr9ZxCeUoq0ASK4GUzSM0BDhZkLFw==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.18.6"
+ }
+ },
+ "@babel/plugin-transform-unicode-regex": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.18.6.tgz",
+ "integrity": "sha512-gE7A6Lt7YLnNOL3Pb9BNeZvi+d8l7tcRrG4+pwJjK9hD2xX4mEvjlQW60G9EEmfXVYRPv9VRQcyegIVHCql/AA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-create-regexp-features-plugin": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6"
+ }
+ },
+ "@babel/preset-env": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.18.9.tgz",
+ "integrity": "sha512-75pt/q95cMIHWssYtyfjVlvI+QEZQThQbKvR9xH+F/Agtw/s4Wfc2V9Bwd/P39VtixB7oWxGdH4GteTTwYJWMg==",
+ "dev": true,
+ "requires": {
+ "@babel/compat-data": "^7.18.8",
+ "@babel/helper-compilation-targets": "^7.18.9",
+ "@babel/helper-plugin-utils": "^7.18.9",
+ "@babel/helper-validator-option": "^7.18.6",
+ "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.18.6",
+ "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.18.9",
+ "@babel/plugin-proposal-async-generator-functions": "^7.18.6",
+ "@babel/plugin-proposal-class-properties": "^7.18.6",
+ "@babel/plugin-proposal-class-static-block": "^7.18.6",
+ "@babel/plugin-proposal-dynamic-import": "^7.18.6",
+ "@babel/plugin-proposal-export-namespace-from": "^7.18.9",
+ "@babel/plugin-proposal-json-strings": "^7.18.6",
+ "@babel/plugin-proposal-logical-assignment-operators": "^7.18.9",
+ "@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.6",
+ "@babel/plugin-proposal-numeric-separator": "^7.18.6",
+ "@babel/plugin-proposal-object-rest-spread": "^7.18.9",
+ "@babel/plugin-proposal-optional-catch-binding": "^7.18.6",
+ "@babel/plugin-proposal-optional-chaining": "^7.18.9",
+ "@babel/plugin-proposal-private-methods": "^7.18.6",
+ "@babel/plugin-proposal-private-property-in-object": "^7.18.6",
+ "@babel/plugin-proposal-unicode-property-regex": "^7.18.6",
+ "@babel/plugin-syntax-async-generators": "^7.8.4",
+ "@babel/plugin-syntax-class-properties": "^7.12.13",
+ "@babel/plugin-syntax-class-static-block": "^7.14.5",
+ "@babel/plugin-syntax-dynamic-import": "^7.8.3",
+ "@babel/plugin-syntax-export-namespace-from": "^7.8.3",
+ "@babel/plugin-syntax-import-assertions": "^7.18.6",
+ "@babel/plugin-syntax-json-strings": "^7.8.3",
+ "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4",
+ "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3",
+ "@babel/plugin-syntax-numeric-separator": "^7.10.4",
+ "@babel/plugin-syntax-object-rest-spread": "^7.8.3",
+ "@babel/plugin-syntax-optional-catch-binding": "^7.8.3",
+ "@babel/plugin-syntax-optional-chaining": "^7.8.3",
+ "@babel/plugin-syntax-private-property-in-object": "^7.14.5",
+ "@babel/plugin-syntax-top-level-await": "^7.14.5",
+ "@babel/plugin-transform-arrow-functions": "^7.18.6",
+ "@babel/plugin-transform-async-to-generator": "^7.18.6",
+ "@babel/plugin-transform-block-scoped-functions": "^7.18.6",
+ "@babel/plugin-transform-block-scoping": "^7.18.9",
+ "@babel/plugin-transform-classes": "^7.18.9",
+ "@babel/plugin-transform-computed-properties": "^7.18.9",
+ "@babel/plugin-transform-destructuring": "^7.18.9",
+ "@babel/plugin-transform-dotall-regex": "^7.18.6",
+ "@babel/plugin-transform-duplicate-keys": "^7.18.9",
+ "@babel/plugin-transform-exponentiation-operator": "^7.18.6",
+ "@babel/plugin-transform-for-of": "^7.18.8",
+ "@babel/plugin-transform-function-name": "^7.18.9",
+ "@babel/plugin-transform-literals": "^7.18.9",
+ "@babel/plugin-transform-member-expression-literals": "^7.18.6",
+ "@babel/plugin-transform-modules-amd": "^7.18.6",
+ "@babel/plugin-transform-modules-commonjs": "^7.18.6",
+ "@babel/plugin-transform-modules-systemjs": "^7.18.9",
+ "@babel/plugin-transform-modules-umd": "^7.18.6",
+ "@babel/plugin-transform-named-capturing-groups-regex": "^7.18.6",
+ "@babel/plugin-transform-new-target": "^7.18.6",
+ "@babel/plugin-transform-object-super": "^7.18.6",
+ "@babel/plugin-transform-parameters": "^7.18.8",
+ "@babel/plugin-transform-property-literals": "^7.18.6",
+ "@babel/plugin-transform-regenerator": "^7.18.6",
+ "@babel/plugin-transform-reserved-words": "^7.18.6",
+ "@babel/plugin-transform-shorthand-properties": "^7.18.6",
+ "@babel/plugin-transform-spread": "^7.18.9",
+ "@babel/plugin-transform-sticky-regex": "^7.18.6",
+ "@babel/plugin-transform-template-literals": "^7.18.9",
+ "@babel/plugin-transform-typeof-symbol": "^7.18.9",
+ "@babel/plugin-transform-unicode-escapes": "^7.18.6",
+ "@babel/plugin-transform-unicode-regex": "^7.18.6",
+ "@babel/preset-modules": "^0.1.5",
+ "@babel/types": "^7.18.9",
+ "babel-plugin-polyfill-corejs2": "^0.3.1",
+ "babel-plugin-polyfill-corejs3": "^0.5.2",
+ "babel-plugin-polyfill-regenerator": "^0.3.1",
+ "core-js-compat": "^3.22.1",
+ "semver": "^6.3.0"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true
+ }
+ }
+ },
+ "@babel/preset-modules": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz",
+ "integrity": "sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==",
+ "dev": true,
+ "requires": {
+ "@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"
+ }
+ },
+ "@babel/runtime": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.18.6.tgz",
+ "integrity": "sha512-t9wi7/AW6XtKahAe20Yw0/mMljKq0B1r2fPdvaAdV/KPDZewFXdaaa6K7lxmZBZ8FBNpCiAT6iHPmd6QO9bKfQ==",
+ "requires": {
+ "regenerator-runtime": "^0.13.4"
+ }
+ },
+ "@babel/runtime-corejs3": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.18.6.tgz",
+ "integrity": "sha512-cOu5wH2JFBgMjje+a+fz2JNIWU4GzYpl05oSob3UDvBEh6EuIn+TXFHMmBbhSb+k/4HMzgKCQfEEDArAWNF9Cw==",
+ "dev": true,
+ "requires": {
+ "core-js-pure": "^3.20.2",
+ "regenerator-runtime": "^0.13.4"
+ }
+ },
+ "@babel/template": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.6.tgz",
+ "integrity": "sha512-JoDWzPe+wgBsTTgdnIma3iHNFC7YVJoPssVBDjiHfNlyt4YcunDtcDOUmfVDfCK5MfdsaIoX9PkijPhjH3nYUw==",
+ "requires": {
+ "@babel/code-frame": "^7.18.6",
+ "@babel/parser": "^7.18.6",
+ "@babel/types": "^7.18.6"
+ }
+ },
+ "@babel/traverse": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.9.tgz",
+ "integrity": "sha512-LcPAnujXGwBgv3/WHv01pHtb2tihcyW1XuL9wd7jqh1Z8AQkTd+QVjMrMijrln0T7ED3UXLIy36P9Ao7W75rYg==",
+ "requires": {
+ "@babel/code-frame": "^7.18.6",
+ "@babel/generator": "^7.18.9",
+ "@babel/helper-environment-visitor": "^7.18.9",
+ "@babel/helper-function-name": "^7.18.9",
+ "@babel/helper-hoist-variables": "^7.18.6",
+ "@babel/helper-split-export-declaration": "^7.18.6",
+ "@babel/parser": "^7.18.9",
+ "@babel/types": "^7.18.9",
+ "debug": "^4.1.0",
+ "globals": "^11.1.0"
+ },
+ "dependencies": {
+ "globals": {
+ "version": "11.12.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
+ "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA=="
+ }
+ }
+ },
+ "@babel/types": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.9.tgz",
+ "integrity": "sha512-WwMLAg2MvJmt/rKEVQBBhIVffMmnilX4oe0sRe7iPOHIGsqpruFHHdrfj4O1CMMtgMtCU4oPafZjDPCRgO57Wg==",
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.18.6",
+ "to-fast-properties": "^2.0.0"
+ }
+ },
+ "@emotion/babel-plugin": {
+ "version": "11.9.2",
+ "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.9.2.tgz",
+ "integrity": "sha512-Pr/7HGH6H6yKgnVFNEj2MVlreu3ADqftqjqwUvDy/OJzKFgxKeTQ+eeUf20FOTuHVkDON2iNa25rAXVYtWJCjw==",
+ "requires": {
+ "@babel/helper-module-imports": "^7.12.13",
+ "@babel/plugin-syntax-jsx": "^7.12.13",
+ "@babel/runtime": "^7.13.10",
+ "@emotion/hash": "^0.8.0",
+ "@emotion/memoize": "^0.7.5",
+ "@emotion/serialize": "^1.0.2",
+ "babel-plugin-macros": "^2.6.1",
+ "convert-source-map": "^1.5.0",
+ "escape-string-regexp": "^4.0.0",
+ "find-root": "^1.1.0",
+ "source-map": "^0.5.7",
+ "stylis": "4.0.13"
+ }
+ },
+ "@emotion/cache": {
+ "version": "11.9.3",
+ "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.9.3.tgz",
+ "integrity": "sha512-0dgkI/JKlCXa+lEXviaMtGBL0ynpx4osh7rjOXE71q9bIF8G+XhJgvi+wDu0B0IdCVx37BffiwXlN9I3UuzFvg==",
+ "requires": {
+ "@emotion/memoize": "^0.7.4",
+ "@emotion/sheet": "^1.1.1",
+ "@emotion/utils": "^1.0.0",
+ "@emotion/weak-memoize": "^0.2.5",
+ "stylis": "4.0.13"
+ }
+ },
+ "@emotion/hash": {
+ "version": "0.8.0",
+ "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz",
+ "integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow=="
+ },
+ "@emotion/memoize": {
+ "version": "0.7.5",
+ "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.5.tgz",
+ "integrity": "sha512-igX9a37DR2ZPGYtV6suZ6whr8pTFtyHL3K/oLUotxpSVO2ASaprmAe2Dkq7tBo7CRY7MMDrAa9nuQP9/YG8FxQ=="
+ },
+ "@emotion/react": {
+ "version": "11.9.3",
+ "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.9.3.tgz",
+ "integrity": "sha512-g9Q1GcTOlzOEjqwuLF/Zd9LC+4FljjPjDfxSM7KmEakm+hsHXk+bYZ2q+/hTJzr0OUNkujo72pXLQvXj6H+GJQ==",
+ "requires": {
+ "@babel/runtime": "^7.13.10",
+ "@emotion/babel-plugin": "^11.7.1",
+ "@emotion/cache": "^11.9.3",
+ "@emotion/serialize": "^1.0.4",
+ "@emotion/utils": "^1.1.0",
+ "@emotion/weak-memoize": "^0.2.5",
+ "hoist-non-react-statics": "^3.3.1"
+ }
+ },
+ "@emotion/serialize": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.0.4.tgz",
+ "integrity": "sha512-1JHamSpH8PIfFwAMryO2bNka+y8+KA5yga5Ocf2d7ZEiJjb7xlLW7aknBGZqJLajuLOvJ+72vN+IBSwPlXD1Pg==",
+ "requires": {
+ "@emotion/hash": "^0.8.0",
+ "@emotion/memoize": "^0.7.4",
+ "@emotion/unitless": "^0.7.5",
+ "@emotion/utils": "^1.0.0",
+ "csstype": "^3.0.2"
+ }
+ },
+ "@emotion/sheet": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.1.1.tgz",
+ "integrity": "sha512-J3YPccVRMiTZxYAY0IOq3kd+hUP8idY8Kz6B/Cyo+JuXq52Ek+zbPbSQUrVQp95aJ+lsAW7DPL1P2Z+U1jGkKA=="
+ },
+ "@emotion/unitless": {
+ "version": "0.7.5",
+ "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz",
+ "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg=="
+ },
+ "@emotion/utils": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.1.0.tgz",
+ "integrity": "sha512-iRLa/Y4Rs5H/f2nimczYmS5kFJEbpiVvgN3XVfZ022IYhuNA1IRSHEizcof88LtCTXtl9S2Cxt32KgaXEu72JQ=="
+ },
+ "@emotion/weak-memoize": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.2.5.tgz",
+ "integrity": "sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA=="
+ },
+ "@eslint/eslintrc": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.0.tgz",
+ "integrity": "sha512-UWW0TMTmk2d7hLcWD1/e2g5HDM/HQ3csaLSqXCfqwh4uNDuNqlaKWXmEsL4Cs41Z0KnILNvwbHAah3C2yt06kw==",
+ "dev": true,
+ "requires": {
+ "ajv": "^6.12.4",
+ "debug": "^4.3.2",
+ "espree": "^9.3.2",
+ "globals": "^13.15.0",
+ "ignore": "^5.2.0",
+ "import-fresh": "^3.2.1",
+ "js-yaml": "^4.1.0",
+ "minimatch": "^3.1.2",
+ "strip-json-comments": "^3.1.1"
+ }
+ },
+ "@humanwhocodes/config-array": {
+ "version": "0.9.5",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz",
+ "integrity": "sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==",
+ "dev": true,
+ "requires": {
+ "@humanwhocodes/object-schema": "^1.2.1",
+ "debug": "^4.1.1",
+ "minimatch": "^3.0.4"
+ }
+ },
+ "@humanwhocodes/object-schema": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz",
+ "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==",
+ "dev": true
+ },
+ "@jridgewell/gen-mapping": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz",
+ "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==",
+ "requires": {
+ "@jridgewell/set-array": "^1.0.0",
+ "@jridgewell/sourcemap-codec": "^1.4.10"
+ }
+ },
+ "@jridgewell/resolve-uri": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz",
+ "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w=="
+ },
+ "@jridgewell/set-array": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz",
+ "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw=="
+ },
+ "@jridgewell/sourcemap-codec": {
+ "version": "1.4.14",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz",
+ "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw=="
+ },
+ "@jridgewell/trace-mapping": {
+ "version": "0.3.14",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz",
+ "integrity": "sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ==",
+ "requires": {
+ "@jridgewell/resolve-uri": "^3.0.3",
+ "@jridgewell/sourcemap-codec": "^1.4.10"
+ }
+ },
+ "@next/env": {
+ "version": "12.2.2",
+ "resolved": "https://registry.npmjs.org/@next/env/-/env-12.2.2.tgz",
+ "integrity": "sha512-BqDwE4gDl1F608TpnNxZqrCn6g48MBjvmWFEmeX5wEXDXh3IkAOw6ASKUgjT8H4OUePYFqghDFUss5ZhnbOUjw=="
+ },
+ "@next/eslint-plugin-next": {
+ "version": "12.2.2",
+ "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-12.2.2.tgz",
+ "integrity": "sha512-XOi0WzJhGH3Lk51SkSu9eZxF+IY1ZZhWcJTIGBycAbWU877IQa6+6KxMATWCOs7c+bmp6Sd8KywXJaDRxzu0JA==",
+ "dev": true,
+ "requires": {
+ "glob": "7.1.7"
+ },
+ "dependencies": {
+ "glob": {
+ "version": "7.1.7",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz",
+ "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ }
+ }
+ },
+ "@next/swc-android-arm-eabi": {
+ "version": "12.2.2",
+ "resolved": "https://registry.npmjs.org/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-12.2.2.tgz",
+ "integrity": "sha512-VHjuCHeq9qCprUZbsRxxM/VqSW8MmsUtqB5nEpGEgUNnQi/BTm/2aK8tl7R4D0twGKRh6g1AAeFuWtXzk9Z/vQ==",
+ "optional": true
+ },
+ "@next/swc-android-arm64": {
+ "version": "12.2.2",
+ "resolved": "https://registry.npmjs.org/@next/swc-android-arm64/-/swc-android-arm64-12.2.2.tgz",
+ "integrity": "sha512-v5EYzXUOSv0r9mO/2PX6mOcF53k8ndlu9yeFHVAWW1Dhw2jaJcvTRcCAwYYN8Q3tDg0nH3NbEltJDLKmcJOuVA==",
+ "optional": true
+ },
+ "@next/swc-darwin-arm64": {
+ "version": "12.2.2",
+ "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-12.2.2.tgz",
+ "integrity": "sha512-JCoGySHKGt+YBk7xRTFGx1QjrnCcwYxIo3yGepcOq64MoiocTM3yllQWeOAJU2/k9MH0+B5E9WUSme4rOCBbpA==",
+ "optional": true
+ },
+ "@next/swc-darwin-x64": {
+ "version": "12.2.2",
+ "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-12.2.2.tgz",
+ "integrity": "sha512-dztDtvfkhUqiqpXvrWVccfGhLe44yQ5tQ7B4tBfnsOR6vxzI9DNPHTlEOgRN9qDqTAcFyPxvg86mn4l8bB9Jcw==",
+ "optional": true
+ },
+ "@next/swc-freebsd-x64": {
+ "version": "12.2.2",
+ "resolved": "https://registry.npmjs.org/@next/swc-freebsd-x64/-/swc-freebsd-x64-12.2.2.tgz",
+ "integrity": "sha512-JUnXB+2xfxqsAvhFLPJpU1NeyDsvJrKoOjpV7g3Dxbno2Riu4tDKn3kKF886yleAuD/1qNTUCpqubTvbbT2VoA==",
+ "optional": true
+ },
+ "@next/swc-linux-arm-gnueabihf": {
+ "version": "12.2.2",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-12.2.2.tgz",
+ "integrity": "sha512-XeYC/qqPLz58R4pjkb+x8sUUxuGLnx9QruC7/IGkK68yW4G17PHwKI/1njFYVfXTXUukpWjcfBuauWwxp9ke7Q==",
+ "optional": true
+ },
+ "@next/swc-linux-arm64-gnu": {
+ "version": "12.2.2",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-12.2.2.tgz",
+ "integrity": "sha512-d6jT8xgfKYFkzR7J0OHo2D+kFvY/6W8qEo6/hmdrTt6AKAqxs//rbbcdoyn3YQq1x6FVUUd39zzpezZntg9Naw==",
+ "optional": true
+ },
+ "@next/swc-linux-arm64-musl": {
+ "version": "12.2.2",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-12.2.2.tgz",
+ "integrity": "sha512-rIZRFxI9N/502auJT1i7coas0HTHUM+HaXMyJiCpnY8Rimbo0495ir24tzzHo3nQqJwcflcPTwEh/DV17sdv9A==",
+ "optional": true
+ },
+ "@next/swc-linux-x64-gnu": {
+ "version": "12.2.2",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-12.2.2.tgz",
+ "integrity": "sha512-ir1vNadlUDj7eQk15AvfhG5BjVizuCHks9uZwBfUgT5jyeDCeRvaDCo1+Q6+0CLOAnYDR/nqSCvBgzG2UdFh9A==",
+ "optional": true
+ },
+ "@next/swc-linux-x64-musl": {
+ "version": "12.2.2",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-12.2.2.tgz",
+ "integrity": "sha512-bte5n2GzLN3O8JdSFYWZzMgEgDHZmRz5wiispiiDssj4ik3l8E7wq/czNi8RmIF+ioj2sYVokUNa/ekLzrESWw==",
+ "optional": true
+ },
+ "@next/swc-win32-arm64-msvc": {
+ "version": "12.2.2",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-12.2.2.tgz",
+ "integrity": "sha512-ZUGCmcDmdPVSAlwJ/aD+1F9lYW8vttseiv4n2+VCDv5JloxiX9aY32kYZaJJO7hmTLNrprvXkb4OvNuHdN22Jg==",
+ "optional": true
+ },
+ "@next/swc-win32-ia32-msvc": {
+ "version": "12.2.2",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-12.2.2.tgz",
+ "integrity": "sha512-v7ykeEDbr9eXiblGSZiEYYkWoig6sRhAbLKHUHQtk8vEWWVEqeXFcxmw6LRrKu5rCN1DY357UlYWToCGPQPCRA==",
+ "optional": true
+ },
+ "@next/swc-win32-x64-msvc": {
+ "version": "12.2.2",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.2.2.tgz",
+ "integrity": "sha512-2D2iinWUL6xx8D9LYVZ5qi7FP6uLAoWymt8m8aaG2Ld/Ka8/k723fJfiklfuAcwOxfufPJI+nRbT5VcgHGzHAQ==",
+ "optional": true
+ },
+ "@nodelib/fs.scandir": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
+ "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
+ "dev": true,
+ "requires": {
+ "@nodelib/fs.stat": "2.0.5",
+ "run-parallel": "^1.1.9"
+ }
+ },
+ "@nodelib/fs.stat": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+ "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
+ "dev": true
+ },
+ "@nodelib/fs.walk": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
+ "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
+ "dev": true,
+ "requires": {
+ "@nodelib/fs.scandir": "2.1.5",
+ "fastq": "^1.6.0"
+ }
+ },
+ "@reduxjs/toolkit": {
+ "version": "1.8.3",
+ "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-1.8.3.tgz",
+ "integrity": "sha512-lU/LDIfORmjBbyDLaqFN2JB9YmAT1BElET9y0ZszwhSBa5Ef3t6o5CrHupw5J1iOXwd+o92QfQZ8OJpwXvsssg==",
+ "requires": {
+ "immer": "^9.0.7",
+ "redux": "^4.1.2",
+ "redux-thunk": "^2.4.1",
+ "reselect": "^4.1.5"
+ }
+ },
+ "@rushstack/eslint-patch": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.1.4.tgz",
+ "integrity": "sha512-LwzQKA4vzIct1zNZzBmRKI9QuNpLgTQMEjsQLf3BXuGYb3QPTP4Yjf6mkdX+X1mYttZ808QpOwAzZjv28kq7DA==",
+ "dev": true
+ },
+ "@swc/helpers": {
+ "version": "0.4.2",
+ "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.4.2.tgz",
+ "integrity": "sha512-556Az0VX7WR6UdoTn4htt/l3zPQ7bsQWK+HqdG4swV7beUCxo/BqmvbOpUkTIm/9ih86LIf1qsUnywNL3obGHw==",
+ "requires": {
+ "tslib": "^2.4.0"
+ }
+ },
+ "@types/hoist-non-react-statics": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz",
+ "integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==",
+ "requires": {
+ "@types/react": "*",
+ "hoist-non-react-statics": "^3.3.0"
+ }
+ },
+ "@types/json5": {
+ "version": "0.0.29",
+ "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
+ "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==",
+ "dev": true
+ },
+ "@types/node": {
+ "version": "18.0.6",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-18.0.6.tgz",
+ "integrity": "sha512-/xUq6H2aQm261exT6iZTMifUySEt4GR5KX8eYyY+C4MSNPqSh9oNIP7tz2GLKTlFaiBbgZNxffoR3CVRG+cljw==",
+ "dev": true
+ },
+ "@types/parse-json": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz",
+ "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA=="
+ },
+ "@types/prop-types": {
+ "version": "15.7.5",
+ "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz",
+ "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w=="
+ },
+ "@types/react": {
+ "version": "18.0.15",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.15.tgz",
+ "integrity": "sha512-iz3BtLuIYH1uWdsv6wXYdhozhqj20oD4/Hk2DNXIn1kFsmp9x8d9QB6FnPhfkbhd2PgEONt9Q1x/ebkwjfFLow==",
+ "requires": {
+ "@types/prop-types": "*",
+ "@types/scheduler": "*",
+ "csstype": "^3.0.2"
+ }
+ },
+ "@types/react-dom": {
+ "version": "18.0.6",
+ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.0.6.tgz",
+ "integrity": "sha512-/5OFZgfIPSwy+YuIBP/FgJnQnsxhZhjjrnxudMddeblOouIodEQ75X14Rr4wGSG/bknL+Omy9iWlLo1u/9GzAA==",
+ "devOptional": true,
+ "requires": {
+ "@types/react": "*"
+ }
+ },
+ "@types/react-redux": {
+ "version": "7.1.24",
+ "resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.24.tgz",
+ "integrity": "sha512-7FkurKcS1k0FHZEtdbbgN8Oc6b+stGSfZYjQGicofJ0j4U0qIn/jaSvnP2pLwZKiai3/17xqqxkkrxTgN8UNbQ==",
+ "requires": {
+ "@types/hoist-non-react-statics": "^3.3.0",
+ "@types/react": "*",
+ "hoist-non-react-statics": "^3.3.0",
+ "redux": "^4.0.0"
+ }
+ },
+ "@types/scheduler": {
+ "version": "0.16.2",
+ "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz",
+ "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew=="
+ },
+ "@types/use-sync-external-store": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz",
+ "integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA=="
+ },
+ "@typescript-eslint/parser": {
+ "version": "5.30.6",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.30.6.tgz",
+ "integrity": "sha512-gfF9lZjT0p2ZSdxO70Xbw8w9sPPJGfAdjK7WikEjB3fcUI/yr9maUVEdqigBjKincUYNKOmf7QBMiTf719kbrA==",
+ "dev": true,
+ "requires": {
+ "@typescript-eslint/scope-manager": "5.30.6",
+ "@typescript-eslint/types": "5.30.6",
+ "@typescript-eslint/typescript-estree": "5.30.6",
+ "debug": "^4.3.4"
+ }
+ },
+ "@typescript-eslint/scope-manager": {
+ "version": "5.30.6",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.30.6.tgz",
+ "integrity": "sha512-Hkq5PhLgtVoW1obkqYH0i4iELctEKixkhWLPTYs55doGUKCASvkjOXOd/pisVeLdO24ZX9D6yymJ/twqpJiG3g==",
+ "dev": true,
+ "requires": {
+ "@typescript-eslint/types": "5.30.6",
+ "@typescript-eslint/visitor-keys": "5.30.6"
+ }
+ },
+ "@typescript-eslint/types": {
+ "version": "5.30.6",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.30.6.tgz",
+ "integrity": "sha512-HdnP8HioL1F7CwVmT4RaaMX57RrfqsOMclZc08wGMiDYJBsLGBM7JwXM4cZJmbWLzIR/pXg1kkrBBVpxTOwfUg==",
+ "dev": true
+ },
+ "@typescript-eslint/typescript-estree": {
+ "version": "5.30.6",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.30.6.tgz",
+ "integrity": "sha512-Z7TgPoeYUm06smfEfYF0RBkpF8csMyVnqQbLYiGgmUSTaSXTP57bt8f0UFXstbGxKIreTwQCujtaH0LY9w9B+A==",
+ "dev": true,
+ "requires": {
+ "@typescript-eslint/types": "5.30.6",
+ "@typescript-eslint/visitor-keys": "5.30.6",
+ "debug": "^4.3.4",
+ "globby": "^11.1.0",
+ "is-glob": "^4.0.3",
+ "semver": "^7.3.7",
+ "tsutils": "^3.21.0"
+ }
+ },
+ "@typescript-eslint/visitor-keys": {
+ "version": "5.30.6",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.30.6.tgz",
+ "integrity": "sha512-41OiCjdL2mCaSDi2SvYbzFLlqqlm5v1ZW9Ym55wXKL/Rx6OOB1IbuFGo71Fj6Xy90gJDFTlgOS+vbmtGHPTQQA==",
+ "dev": true,
+ "requires": {
+ "@typescript-eslint/types": "5.30.6",
+ "eslint-visitor-keys": "^3.3.0"
+ }
+ },
+ "acorn": {
+ "version": "8.7.1",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz",
+ "integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==",
+ "dev": true
+ },
+ "acorn-jsx": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+ "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+ "dev": true,
+ "requires": {}
+ },
+ "ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dev": true,
+ "requires": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ }
+ },
+ "ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true
+ },
+ "ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "requires": {
+ "color-convert": "^2.0.1"
+ }
+ },
+ "argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "dev": true
+ },
+ "aria-query": {
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-4.2.2.tgz",
+ "integrity": "sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA==",
+ "dev": true,
+ "requires": {
+ "@babel/runtime": "^7.10.2",
+ "@babel/runtime-corejs3": "^7.10.2"
+ }
+ },
+ "array-includes": {
+ "version": "3.1.5",
+ "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.5.tgz",
+ "integrity": "sha512-iSDYZMMyTPkiFasVqfuAQnWAYcvO/SeBSCGKePoEthjp4LEMTe4uLc7b025o4jAZpHhihh8xPo99TNWUWWkGDQ==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.19.5",
+ "get-intrinsic": "^1.1.1",
+ "is-string": "^1.0.7"
+ }
+ },
+ "array-union": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
+ "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
+ "dev": true
+ },
+ "array.prototype.flat": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.0.tgz",
+ "integrity": "sha512-12IUEkHsAhA4DY5s0FPgNXIdc8VRSqD9Zp78a5au9abH/SOBrsp082JOWFNTjkMozh8mqcdiKuaLGhPeYztxSw==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.19.2",
+ "es-shim-unscopables": "^1.0.0"
+ }
+ },
+ "array.prototype.flatmap": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.0.tgz",
+ "integrity": "sha512-PZC9/8TKAIxcWKdyeb77EzULHPrIX/tIZebLJUQOMR1OwYosT8yggdfWScfTBCDj5utONvOuPQQumYsU2ULbkg==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.19.2",
+ "es-shim-unscopables": "^1.0.0"
+ }
+ },
+ "ast-types-flow": {
+ "version": "0.0.7",
+ "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz",
+ "integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==",
+ "dev": true
+ },
+ "axe-core": {
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.4.3.tgz",
+ "integrity": "sha512-32+ub6kkdhhWick/UjvEwRchgoetXqTK14INLqbGm5U2TzBkBNF3nQtLYm8ovxSkQWArjEQvftCKryjZaATu3w==",
+ "dev": true
+ },
+ "axobject-query": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz",
+ "integrity": "sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA==",
+ "dev": true
+ },
+ "babel-plugin-dynamic-import-node": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz",
+ "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==",
+ "dev": true,
+ "requires": {
+ "object.assign": "^4.1.0"
+ }
+ },
+ "babel-plugin-macros": {
+ "version": "2.8.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-2.8.0.tgz",
+ "integrity": "sha512-SEP5kJpfGYqYKpBrj5XU3ahw5p5GOHJ0U5ssOSQ/WBVdwkD2Dzlce95exQTs3jOVWPPKLBN2rlEWkCK7dSmLvg==",
+ "requires": {
+ "@babel/runtime": "^7.7.2",
+ "cosmiconfig": "^6.0.0",
+ "resolve": "^1.12.0"
+ }
+ },
+ "babel-plugin-polyfill-corejs2": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.1.tgz",
+ "integrity": "sha512-v7/T6EQcNfVLfcN2X8Lulb7DjprieyLWJK/zOWH5DUYcAgex9sP3h25Q+DLsX9TloXe3y1O8l2q2Jv9q8UVB9w==",
+ "dev": true,
+ "requires": {
+ "@babel/compat-data": "^7.13.11",
+ "@babel/helper-define-polyfill-provider": "^0.3.1",
+ "semver": "^6.1.1"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true
+ }
+ }
+ },
+ "babel-plugin-polyfill-corejs3": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.2.tgz",
+ "integrity": "sha512-G3uJih0XWiID451fpeFaYGVuxHEjzKTHtc9uGFEjR6hHrvNzeS/PX+LLLcetJcytsB5m4j+K3o/EpXJNb/5IEQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-define-polyfill-provider": "^0.3.1",
+ "core-js-compat": "^3.21.0"
+ }
+ },
+ "babel-plugin-polyfill-regenerator": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.3.1.tgz",
+ "integrity": "sha512-Y2B06tvgHYt1x0yz17jGkGeeMr5FeKUu+ASJ+N6nB5lQ8Dapfg42i0OVrf8PNGJ3zKL4A23snMi1IRwrqqND7A==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-define-polyfill-provider": "^0.3.1"
+ }
+ },
+ "balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "dev": true
+ },
+ "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": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "braces": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+ "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+ "dev": true,
+ "requires": {
+ "fill-range": "^7.0.1"
+ }
+ },
+ "browserslist": {
+ "version": "4.21.2",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.2.tgz",
+ "integrity": "sha512-MonuOgAtUB46uP5CezYbRaYKBNt2LxP0yX+Pmj4LkcDFGkn9Cbpi83d9sCjwQDErXsIJSzY5oKGDbgOlF/LPAA==",
+ "requires": {
+ "caniuse-lite": "^1.0.30001366",
+ "electron-to-chromium": "^1.4.188",
+ "node-releases": "^2.0.6",
+ "update-browserslist-db": "^1.0.4"
+ }
+ },
+ "call-bind": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
+ "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
+ "dev": true,
+ "requires": {
+ "function-bind": "^1.1.1",
+ "get-intrinsic": "^1.0.2"
+ }
+ },
+ "callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="
+ },
+ "caniuse-lite": {
+ "version": "1.0.30001367",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001367.tgz",
+ "integrity": "sha512-XDgbeOHfifWV3GEES2B8rtsrADx4Jf+juKX2SICJcaUhjYBO3bR96kvEIHa15VU6ohtOhBZuPGGYGbXMRn0NCw=="
+ },
+ "chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ }
+ },
+ "color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "requires": {
+ "color-name": "~1.1.4"
+ }
+ },
+ "color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+ "dev": true
+ },
+ "convert-source-map": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz",
+ "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==",
+ "requires": {
+ "safe-buffer": "~5.1.1"
+ }
+ },
+ "core-js-compat": {
+ "version": "3.23.5",
+ "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.23.5.tgz",
+ "integrity": "sha512-fHYozIFIxd+91IIbXJgWd/igXIc8Mf9is0fusswjnGIWVG96y2cwyUdlCkGOw6rMLHKAxg7xtCIVaHsyOUnJIg==",
+ "dev": true,
+ "requires": {
+ "browserslist": "^4.21.2",
+ "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
+ }
+ }
+ },
+ "core-js-pure": {
+ "version": "3.23.5",
+ "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.23.5.tgz",
+ "integrity": "sha512-8t78LdpKSuCq4pJYCYk8hl7XEkAX+BP16yRIwL3AanTksxuEf7CM83vRyctmiEL8NDZ3jpUcv56fk9/zG3aIuw==",
+ "dev": true
+ },
+ "cosmiconfig": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz",
+ "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==",
+ "requires": {
+ "@types/parse-json": "^4.0.0",
+ "import-fresh": "^3.1.0",
+ "parse-json": "^5.0.0",
+ "path-type": "^4.0.0",
+ "yaml": "^1.7.2"
+ }
+ },
+ "cross-spawn": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+ "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+ "dev": true,
+ "requires": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ }
+ },
+ "csstype": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz",
+ "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA=="
+ },
+ "damerau-levenshtein": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz",
+ "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==",
+ "dev": true
+ },
+ "debug": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+ "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+ "requires": {
+ "ms": "2.1.2"
+ }
+ },
+ "deep-is": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
+ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
+ "dev": true
+ },
+ "define-properties": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz",
+ "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==",
+ "dev": true,
+ "requires": {
+ "has-property-descriptors": "^1.0.0",
+ "object-keys": "^1.1.1"
+ }
+ },
+ "dir-glob": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
+ "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
+ "dev": true,
+ "requires": {
+ "path-type": "^4.0.0"
+ }
+ },
+ "doctrine": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
+ "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
+ "dev": true,
+ "requires": {
+ "esutils": "^2.0.2"
+ }
+ },
+ "electron-to-chromium": {
+ "version": "1.4.199",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.199.tgz",
+ "integrity": "sha512-WIGME0Cs7oob3mxsJwHbeWkH0tYkIE/sjkJ8ML2BYmuRcjhRl/q5kVDXG7W9LOOKwzPU5M0LBlXRq9rlSgnNlg=="
+ },
+ "emoji-regex": {
+ "version": "9.2.2",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
+ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
+ "dev": true
+ },
+ "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==",
+ "requires": {
+ "is-arrayish": "^0.2.1"
+ }
+ },
+ "es-abstract": {
+ "version": "1.20.1",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.1.tgz",
+ "integrity": "sha512-WEm2oBhfoI2sImeM4OF2zE2V3BYdSF+KnSi9Sidz51fQHd7+JuF8Xgcj9/0o+OWeIeIS/MiuNnlruQrJf16GQA==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "es-to-primitive": "^1.2.1",
+ "function-bind": "^1.1.1",
+ "function.prototype.name": "^1.1.5",
+ "get-intrinsic": "^1.1.1",
+ "get-symbol-description": "^1.0.0",
+ "has": "^1.0.3",
+ "has-property-descriptors": "^1.0.0",
+ "has-symbols": "^1.0.3",
+ "internal-slot": "^1.0.3",
+ "is-callable": "^1.2.4",
+ "is-negative-zero": "^2.0.2",
+ "is-regex": "^1.1.4",
+ "is-shared-array-buffer": "^1.0.2",
+ "is-string": "^1.0.7",
+ "is-weakref": "^1.0.2",
+ "object-inspect": "^1.12.0",
+ "object-keys": "^1.1.1",
+ "object.assign": "^4.1.2",
+ "regexp.prototype.flags": "^1.4.3",
+ "string.prototype.trimend": "^1.0.5",
+ "string.prototype.trimstart": "^1.0.5",
+ "unbox-primitive": "^1.0.2"
+ }
+ },
+ "es-shim-unscopables": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz",
+ "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==",
+ "dev": true,
+ "requires": {
+ "has": "^1.0.3"
+ }
+ },
+ "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": {
+ "is-callable": "^1.1.4",
+ "is-date-object": "^1.0.1",
+ "is-symbol": "^1.0.2"
+ }
+ },
+ "escalade": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
+ "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw=="
+ },
+ "escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="
+ },
+ "eslint": {
+ "version": "8.20.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.20.0.tgz",
+ "integrity": "sha512-d4ixhz5SKCa1D6SCPrivP7yYVi7nyD6A4vs6HIAul9ujBzcEmZVM3/0NN/yu5nKhmO1wjp5xQ46iRfmDGlOviA==",
+ "dev": true,
+ "requires": {
+ "@eslint/eslintrc": "^1.3.0",
+ "@humanwhocodes/config-array": "^0.9.2",
+ "ajv": "^6.10.0",
+ "chalk": "^4.0.0",
+ "cross-spawn": "^7.0.2",
+ "debug": "^4.3.2",
+ "doctrine": "^3.0.0",
+ "escape-string-regexp": "^4.0.0",
+ "eslint-scope": "^7.1.1",
+ "eslint-utils": "^3.0.0",
+ "eslint-visitor-keys": "^3.3.0",
+ "espree": "^9.3.2",
+ "esquery": "^1.4.0",
+ "esutils": "^2.0.2",
+ "fast-deep-equal": "^3.1.3",
+ "file-entry-cache": "^6.0.1",
+ "functional-red-black-tree": "^1.0.1",
+ "glob-parent": "^6.0.1",
+ "globals": "^13.15.0",
+ "ignore": "^5.2.0",
+ "import-fresh": "^3.0.0",
+ "imurmurhash": "^0.1.4",
+ "is-glob": "^4.0.0",
+ "js-yaml": "^4.1.0",
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "levn": "^0.4.1",
+ "lodash.merge": "^4.6.2",
+ "minimatch": "^3.1.2",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.9.1",
+ "regexpp": "^3.2.0",
+ "strip-ansi": "^6.0.1",
+ "strip-json-comments": "^3.1.0",
+ "text-table": "^0.2.0",
+ "v8-compile-cache": "^2.0.3"
+ }
+ },
+ "eslint-config-next": {
+ "version": "12.2.2",
+ "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-12.2.2.tgz",
+ "integrity": "sha512-oJhWBLC4wDYYUFv/5APbjHUFd0QRFCojMdj/QnMoOEktmeTvwnnoA8F8uaXs0fQgsaTK0tbUxBRv9/Y4/rpxOA==",
+ "dev": true,
+ "requires": {
+ "@next/eslint-plugin-next": "12.2.2",
+ "@rushstack/eslint-patch": "^1.1.3",
+ "@typescript-eslint/parser": "^5.21.0",
+ "eslint-import-resolver-node": "^0.3.6",
+ "eslint-import-resolver-typescript": "^2.7.1",
+ "eslint-plugin-import": "^2.26.0",
+ "eslint-plugin-jsx-a11y": "^6.5.1",
+ "eslint-plugin-react": "^7.29.4",
+ "eslint-plugin-react-hooks": "^4.5.0"
+ }
+ },
+ "eslint-import-resolver-node": {
+ "version": "0.3.6",
+ "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz",
+ "integrity": "sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw==",
+ "dev": true,
+ "requires": {
+ "debug": "^3.2.7",
+ "resolve": "^1.20.0"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ }
+ }
+ },
+ "eslint-import-resolver-typescript": {
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-2.7.1.tgz",
+ "integrity": "sha512-00UbgGwV8bSgUv34igBDbTOtKhqoRMy9bFjNehT40bXg6585PNIct8HhXZ0SybqB9rWtXj9crcku8ndDn/gIqQ==",
+ "dev": true,
+ "requires": {
+ "debug": "^4.3.4",
+ "glob": "^7.2.0",
+ "is-glob": "^4.0.3",
+ "resolve": "^1.22.0",
+ "tsconfig-paths": "^3.14.1"
+ }
+ },
+ "eslint-module-utils": {
+ "version": "2.7.3",
+ "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.3.tgz",
+ "integrity": "sha512-088JEC7O3lDZM9xGe0RerkOMd0EjFl+Yvd1jPWIkMT5u3H9+HC34mWWPnqPrN13gieT9pBOO+Qt07Nb/6TresQ==",
+ "dev": true,
+ "requires": {
+ "debug": "^3.2.7",
+ "find-up": "^2.1.0"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ }
+ }
+ },
+ "eslint-plugin-import": {
+ "version": "2.26.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.26.0.tgz",
+ "integrity": "sha512-hYfi3FXaM8WPLf4S1cikh/r4IxnO6zrhZbEGz2b660EJRbuxgpDS5gkCuYgGWg2xxh2rBuIr4Pvhve/7c31koA==",
+ "dev": true,
+ "requires": {
+ "array-includes": "^3.1.4",
+ "array.prototype.flat": "^1.2.5",
+ "debug": "^2.6.9",
+ "doctrine": "^2.1.0",
+ "eslint-import-resolver-node": "^0.3.6",
+ "eslint-module-utils": "^2.7.3",
+ "has": "^1.0.3",
+ "is-core-module": "^2.8.1",
+ "is-glob": "^4.0.3",
+ "minimatch": "^3.1.2",
+ "object.values": "^1.1.5",
+ "resolve": "^1.22.0",
+ "tsconfig-paths": "^3.14.1"
+ },
+ "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"
+ }
+ },
+ "doctrine": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
+ "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
+ "dev": true,
+ "requires": {
+ "esutils": "^2.0.2"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "dev": true
+ }
+ }
+ },
+ "eslint-plugin-jsx-a11y": {
+ "version": "6.6.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.6.0.tgz",
+ "integrity": "sha512-kTeLuIzpNhXL2CwLlc8AHI0aFRwWHcg483yepO9VQiHzM9bZwJdzTkzBszbuPrbgGmq2rlX/FaT2fJQsjUSHsw==",
+ "dev": true,
+ "requires": {
+ "@babel/runtime": "^7.18.3",
+ "aria-query": "^4.2.2",
+ "array-includes": "^3.1.5",
+ "ast-types-flow": "^0.0.7",
+ "axe-core": "^4.4.2",
+ "axobject-query": "^2.2.0",
+ "damerau-levenshtein": "^1.0.8",
+ "emoji-regex": "^9.2.2",
+ "has": "^1.0.3",
+ "jsx-ast-utils": "^3.3.1",
+ "language-tags": "^1.0.5",
+ "minimatch": "^3.1.2",
+ "semver": "^6.3.0"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true
+ }
+ }
+ },
+ "eslint-plugin-react": {
+ "version": "7.30.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.30.1.tgz",
+ "integrity": "sha512-NbEvI9jtqO46yJA3wcRF9Mo0lF9T/jhdHqhCHXiXtD+Zcb98812wvokjWpU7Q4QH5edo6dmqrukxVvWWXHlsUg==",
+ "dev": true,
+ "requires": {
+ "array-includes": "^3.1.5",
+ "array.prototype.flatmap": "^1.3.0",
+ "doctrine": "^2.1.0",
+ "estraverse": "^5.3.0",
+ "jsx-ast-utils": "^2.4.1 || ^3.0.0",
+ "minimatch": "^3.1.2",
+ "object.entries": "^1.1.5",
+ "object.fromentries": "^2.0.5",
+ "object.hasown": "^1.1.1",
+ "object.values": "^1.1.5",
+ "prop-types": "^15.8.1",
+ "resolve": "^2.0.0-next.3",
+ "semver": "^6.3.0",
+ "string.prototype.matchall": "^4.0.7"
+ },
+ "dependencies": {
+ "doctrine": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
+ "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
+ "dev": true,
+ "requires": {
+ "esutils": "^2.0.2"
+ }
+ },
+ "resolve": {
+ "version": "2.0.0-next.4",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.4.tgz",
+ "integrity": "sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ==",
+ "dev": true,
+ "requires": {
+ "is-core-module": "^2.9.0",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ }
+ },
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true
+ }
+ }
+ },
+ "eslint-plugin-react-hooks": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz",
+ "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==",
+ "dev": true,
+ "requires": {}
+ },
+ "eslint-scope": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz",
+ "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==",
+ "dev": true,
+ "requires": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^5.2.0"
+ }
+ },
+ "eslint-utils": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz",
+ "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==",
+ "dev": true,
+ "requires": {
+ "eslint-visitor-keys": "^2.0.0"
+ },
+ "dependencies": {
+ "eslint-visitor-keys": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz",
+ "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==",
+ "dev": true
+ }
+ }
+ },
+ "eslint-visitor-keys": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz",
+ "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==",
+ "dev": true
+ },
+ "espree": {
+ "version": "9.3.2",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.2.tgz",
+ "integrity": "sha512-D211tC7ZwouTIuY5x9XnS0E9sWNChB7IYKX/Xp5eQj3nFXhqmiUDB9q27y76oFl8jTg3pXcQx/bpxMfs3CIZbA==",
+ "dev": true,
+ "requires": {
+ "acorn": "^8.7.1",
+ "acorn-jsx": "^5.3.2",
+ "eslint-visitor-keys": "^3.3.0"
+ }
+ },
+ "esquery": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz",
+ "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==",
+ "dev": true,
+ "requires": {
+ "estraverse": "^5.1.0"
+ }
+ },
+ "esrecurse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+ "dev": true,
+ "requires": {
+ "estraverse": "^5.2.0"
+ }
+ },
+ "estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true
+ },
+ "esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "dev": true
+ },
+ "fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+ "dev": true
+ },
+ "fast-glob": {
+ "version": "3.2.11",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz",
+ "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==",
+ "dev": true,
+ "requires": {
+ "@nodelib/fs.stat": "^2.0.2",
+ "@nodelib/fs.walk": "^1.2.3",
+ "glob-parent": "^5.1.2",
+ "merge2": "^1.3.0",
+ "micromatch": "^4.0.4"
+ },
+ "dependencies": {
+ "glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dev": true,
+ "requires": {
+ "is-glob": "^4.0.1"
+ }
+ }
+ }
+ },
+ "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": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
+ "dev": true
+ },
+ "fastq": {
+ "version": "1.13.0",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz",
+ "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==",
+ "dev": true,
+ "requires": {
+ "reusify": "^1.0.4"
+ }
+ },
+ "file-entry-cache": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
+ "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
+ "dev": true,
+ "requires": {
+ "flat-cache": "^3.0.4"
+ }
+ },
+ "fill-range": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+ "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+ "dev": true,
+ "requires": {
+ "to-regex-range": "^5.0.1"
+ }
+ },
+ "find-root": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz",
+ "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng=="
+ },
+ "find-up": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
+ "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==",
+ "dev": true,
+ "requires": {
+ "locate-path": "^2.0.0"
+ }
+ },
+ "flat-cache": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz",
+ "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==",
+ "dev": true,
+ "requires": {
+ "flatted": "^3.1.0",
+ "rimraf": "^3.0.2"
+ }
+ },
+ "flatted": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.6.tgz",
+ "integrity": "sha512-0sQoMh9s0BYsm+12Huy/rkKxVu4R1+r96YX5cG44rHV0pQ6iC3Q+mkoMFaGWObMFYQxCVT+ssG1ksneA2MI9KQ==",
+ "dev": true
+ },
+ "fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
+ "dev": true
+ },
+ "function-bind": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
+ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
+ },
+ "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==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.19.0",
+ "functions-have-names": "^1.2.2"
+ }
+ },
+ "functional-red-black-tree": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
+ "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==",
+ "dev": true
+ },
+ "functions-have-names": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
+ "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
+ "dev": true
+ },
+ "gensync": {
+ "version": "1.0.0-beta.2",
+ "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
+ "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg=="
+ },
+ "get-intrinsic": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.2.tgz",
+ "integrity": "sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==",
+ "dev": true,
+ "requires": {
+ "function-bind": "^1.1.1",
+ "has": "^1.0.3",
+ "has-symbols": "^1.0.3"
+ }
+ },
+ "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==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "get-intrinsic": "^1.1.1"
+ }
+ },
+ "glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "glob-parent": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+ "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+ "dev": true,
+ "requires": {
+ "is-glob": "^4.0.3"
+ }
+ },
+ "globals": {
+ "version": "13.16.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-13.16.0.tgz",
+ "integrity": "sha512-A1lrQfpNF+McdPOnnFqY3kSN0AFTy485bTi1bkLk4mVPODIUEcSfhHgRqA+QdXPksrSTTztYXx37NFV+GpGk3Q==",
+ "dev": true,
+ "requires": {
+ "type-fest": "^0.20.2"
+ }
+ },
+ "globby": {
+ "version": "11.1.0",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
+ "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
+ "dev": true,
+ "requires": {
+ "array-union": "^2.1.0",
+ "dir-glob": "^3.0.1",
+ "fast-glob": "^3.2.9",
+ "ignore": "^5.2.0",
+ "merge2": "^1.4.1",
+ "slash": "^3.0.0"
+ }
+ },
+ "has": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+ "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+ "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",
+ "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==",
+ "dev": true
+ },
+ "has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "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==",
+ "dev": true,
+ "requires": {
+ "get-intrinsic": "^1.1.1"
+ }
+ },
+ "has-symbols": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
+ "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
+ "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==",
+ "dev": true,
+ "requires": {
+ "has-symbols": "^1.0.2"
+ }
+ },
+ "hoist-non-react-statics": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
+ "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
+ "requires": {
+ "react-is": "^16.7.0"
+ }
+ },
+ "ignore": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz",
+ "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==",
+ "dev": true
+ },
+ "immer": {
+ "version": "9.0.15",
+ "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.15.tgz",
+ "integrity": "sha512-2eB/sswms9AEUSkOm4SbV5Y7Vmt/bKRwByd52jfLkW4OLYeaTP3EEiJ9agqU0O/tq6Dk62Zfj+TJSqfm1rLVGQ=="
+ },
+ "import-fresh": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
+ "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
+ "requires": {
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ }
+ },
+ "imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+ "dev": true
+ },
+ "inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+ "dev": true,
+ "requires": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+ "dev": true
+ },
+ "internal-slot": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz",
+ "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==",
+ "dev": true,
+ "requires": {
+ "get-intrinsic": "^1.1.0",
+ "has": "^1.0.3",
+ "side-channel": "^1.0.4"
+ }
+ },
+ "invariant": {
+ "version": "2.2.4",
+ "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
+ "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
+ "requires": {
+ "loose-envify": "^1.0.0"
+ }
+ },
+ "is-arrayish": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+ "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg=="
+ },
+ "is-bigint": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz",
+ "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==",
+ "dev": true,
+ "requires": {
+ "has-bigints": "^1.0.1"
+ }
+ },
+ "is-boolean-object": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz",
+ "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "has-tostringtag": "^1.0.0"
+ }
+ },
+ "is-callable": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz",
+ "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==",
+ "dev": true
+ },
+ "is-core-module": {
+ "version": "2.9.0",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz",
+ "integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==",
+ "requires": {
+ "has": "^1.0.3"
+ }
+ },
+ "is-date-object": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz",
+ "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==",
+ "dev": true,
+ "requires": {
+ "has-tostringtag": "^1.0.0"
+ }
+ },
+ "is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "dev": true
+ },
+ "is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "dev": true,
+ "requires": {
+ "is-extglob": "^2.1.1"
+ }
+ },
+ "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==",
+ "dev": true
+ },
+ "is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "dev": true
+ },
+ "is-number-object": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz",
+ "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==",
+ "dev": true,
+ "requires": {
+ "has-tostringtag": "^1.0.0"
+ }
+ },
+ "is-regex": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
+ "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "has-tostringtag": "^1.0.0"
+ }
+ },
+ "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==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2"
+ }
+ },
+ "is-string": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz",
+ "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==",
+ "dev": true,
+ "requires": {
+ "has-tostringtag": "^1.0.0"
+ }
+ },
+ "is-symbol": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz",
+ "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==",
+ "dev": true,
+ "requires": {
+ "has-symbols": "^1.0.2"
+ }
+ },
+ "is-weakref": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz",
+ "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2"
+ }
+ },
+ "isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "dev": true
+ },
+ "js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
+ },
+ "js-yaml": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+ "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "dev": true,
+ "requires": {
+ "argparse": "^2.0.1"
+ }
+ },
+ "jsesc": {
+ "version": "2.5.2",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
+ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA=="
+ },
+ "json-parse-even-better-errors": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
+ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w=="
+ },
+ "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-stable-stringify-without-jsonify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
+ "dev": true
+ },
+ "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": {
+ "minimist": "^1.2.0"
+ }
+ },
+ "jsx-ast-utils": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.2.tgz",
+ "integrity": "sha512-4ZCADZHRkno244xlNnn4AOG6sRQ7iBZ5BbgZ4vW4y5IZw7cVUD1PPeblm1xx/nfmMxPdt/LHsXZW8z/j58+l9Q==",
+ "dev": true,
+ "requires": {
+ "array-includes": "^3.1.5",
+ "object.assign": "^4.1.2"
+ }
+ },
+ "just-curry-it": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/just-curry-it/-/just-curry-it-3.2.1.tgz",
+ "integrity": "sha512-Q8206k8pTY7krW32cdmPsP+DqqLgWx/hYPSj9/+7SYqSqz7UuwPbfSe07lQtvuuaVyiSJveXk0E5RydOuWwsEg=="
+ },
+ "language-subtag-registry": {
+ "version": "0.3.22",
+ "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz",
+ "integrity": "sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==",
+ "dev": true
+ },
+ "language-tags": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.5.tgz",
+ "integrity": "sha512-qJhlO9cGXi6hBGKoxEG/sKZDAHD5Hnu9Hs4WbOY3pCWXDhw0N8x1NenNzm2EnNLkLkk7J2SdxAkDSbb6ftT+UQ==",
+ "dev": true,
+ "requires": {
+ "language-subtag-registry": "~0.3.2"
+ }
+ },
+ "levn": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+ "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+ "dev": true,
+ "requires": {
+ "prelude-ls": "^1.2.1",
+ "type-check": "~0.4.0"
+ }
+ },
+ "lines-and-columns": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
+ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="
+ },
+ "locate-path": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
+ "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==",
+ "dev": true,
+ "requires": {
+ "p-locate": "^2.0.0",
+ "path-exists": "^3.0.0"
+ }
+ },
+ "lodash.debounce": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
+ "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==",
+ "dev": true
+ },
+ "lodash.merge": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
+ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
+ "dev": true
+ },
+ "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==",
+ "requires": {
+ "js-tokens": "^3.0.0 || ^4.0.0"
+ }
+ },
+ "lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "dev": true,
+ "requires": {
+ "yallist": "^4.0.0"
+ }
+ },
+ "merge2": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+ "dev": true
+ },
+ "micromatch": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
+ "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
+ "dev": true,
+ "requires": {
+ "braces": "^3.0.2",
+ "picomatch": "^2.3.1"
+ }
+ },
+ "minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
+ },
+ "minimist": {
+ "version": "1.2.6",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
+ "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==",
+ "dev": true
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
+ },
+ "nanoid": {
+ "version": "3.3.4",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz",
+ "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw=="
+ },
+ "natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
+ "dev": true
+ },
+ "next": {
+ "version": "12.2.2",
+ "resolved": "https://registry.npmjs.org/next/-/next-12.2.2.tgz",
+ "integrity": "sha512-zAYFY45aBry/PlKONqtlloRFqU/We3zWYdn2NoGvDZkoYUYQSJC8WMcalS5C19MxbCZLUVCX7D7a6gTGgl2yLg==",
+ "requires": {
+ "@next/env": "12.2.2",
+ "@next/swc-android-arm-eabi": "12.2.2",
+ "@next/swc-android-arm64": "12.2.2",
+ "@next/swc-darwin-arm64": "12.2.2",
+ "@next/swc-darwin-x64": "12.2.2",
+ "@next/swc-freebsd-x64": "12.2.2",
+ "@next/swc-linux-arm-gnueabihf": "12.2.2",
+ "@next/swc-linux-arm64-gnu": "12.2.2",
+ "@next/swc-linux-arm64-musl": "12.2.2",
+ "@next/swc-linux-x64-gnu": "12.2.2",
+ "@next/swc-linux-x64-musl": "12.2.2",
+ "@next/swc-win32-arm64-msvc": "12.2.2",
+ "@next/swc-win32-ia32-msvc": "12.2.2",
+ "@next/swc-win32-x64-msvc": "12.2.2",
+ "@swc/helpers": "0.4.2",
+ "caniuse-lite": "^1.0.30001332",
+ "postcss": "8.4.5",
+ "styled-jsx": "5.0.2",
+ "use-sync-external-store": "1.1.0"
+ }
+ },
+ "node-releases": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz",
+ "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg=="
+ },
+ "object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="
+ },
+ "object-inspect": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz",
+ "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==",
+ "dev": true
+ },
+ "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
+ },
+ "object.assign": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz",
+ "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.0",
+ "define-properties": "^1.1.3",
+ "has-symbols": "^1.0.1",
+ "object-keys": "^1.1.1"
+ }
+ },
+ "object.entries": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.5.tgz",
+ "integrity": "sha512-TyxmjUoZggd4OrrU1W66FMDG6CuqJxsFvymeyXI51+vQLN67zYfZseptRge703kKQdo4uccgAKebXFcRCzk4+g==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.19.1"
+ }
+ },
+ "object.fromentries": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.5.tgz",
+ "integrity": "sha512-CAyG5mWQRRiBU57Re4FKoTBjXfDoNwdFVH2Y1tS9PqCsfUTymAohOkEMSG3aRNKmv4lV3O7p1et7c187q6bynw==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.19.1"
+ }
+ },
+ "object.hasown": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.1.tgz",
+ "integrity": "sha512-LYLe4tivNQzq4JdaWW6WO3HMZZJWzkkH8fnI6EebWl0VZth2wL2Lovm74ep2/gZzlaTdV62JZHEqHQ2yVn8Q/A==",
+ "dev": true,
+ "requires": {
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.19.5"
+ }
+ },
+ "object.values": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.5.tgz",
+ "integrity": "sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.19.1"
+ }
+ },
+ "once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+ "dev": true,
+ "requires": {
+ "wrappy": "1"
+ }
+ },
+ "optionator": {
+ "version": "0.9.1",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz",
+ "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==",
+ "dev": true,
+ "requires": {
+ "deep-is": "^0.1.3",
+ "fast-levenshtein": "^2.0.6",
+ "levn": "^0.4.1",
+ "prelude-ls": "^1.2.1",
+ "type-check": "^0.4.0",
+ "word-wrap": "^1.2.3"
+ }
+ },
+ "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": {
+ "p-try": "^1.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz",
+ "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==",
+ "dev": true,
+ "requires": {
+ "p-limit": "^1.1.0"
+ }
+ },
+ "p-try": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
+ "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==",
+ "dev": true
+ },
+ "parent-module": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+ "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+ "requires": {
+ "callsites": "^3.0.0"
+ }
+ },
+ "parse-json": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
+ "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
+ "requires": {
+ "@babel/code-frame": "^7.0.0",
+ "error-ex": "^1.3.1",
+ "json-parse-even-better-errors": "^2.3.0",
+ "lines-and-columns": "^1.1.6"
+ }
+ },
+ "path-exists": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
+ "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==",
+ "dev": true
+ },
+ "path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
+ "dev": true
+ },
+ "path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "dev": true
+ },
+ "path-parse": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="
+ },
+ "path-type": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
+ "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw=="
+ },
+ "picocolors": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
+ "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ=="
+ },
+ "picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "dev": true
+ },
+ "postcss": {
+ "version": "8.4.5",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.5.tgz",
+ "integrity": "sha512-jBDboWM8qpaqwkMwItqTQTiFikhs/67OYVvblFFTM7MrZjt6yMKd6r2kgXizEbTTljacm4NldIlZnhbjr84QYg==",
+ "requires": {
+ "nanoid": "^3.1.30",
+ "picocolors": "^1.0.0",
+ "source-map-js": "^1.0.1"
+ }
+ },
+ "prelude-ls": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
+ "dev": true
+ },
+ "prop-types": {
+ "version": "15.8.1",
+ "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
+ "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
+ "requires": {
+ "loose-envify": "^1.4.0",
+ "object-assign": "^4.1.1",
+ "react-is": "^16.13.1"
+ }
+ },
+ "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
+ },
+ "queue-microtask": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
+ "dev": true
+ },
+ "react": {
+ "version": "18.2.0",
+ "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz",
+ "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==",
+ "requires": {
+ "loose-envify": "^1.1.0"
+ }
+ },
+ "react-dom": {
+ "version": "18.2.0",
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz",
+ "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==",
+ "requires": {
+ "loose-envify": "^1.1.0",
+ "scheduler": "^0.23.0"
+ }
+ },
+ "react-is": {
+ "version": "16.13.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
+ },
+ "react-redux": {
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-8.0.2.tgz",
+ "integrity": "sha512-nBwiscMw3NoP59NFCXFf02f8xdo+vSHT/uZ1ldDwF7XaTpzm+Phk97VT4urYBl5TYAPNVaFm12UHAEyzkpNzRA==",
+ "requires": {
+ "@babel/runtime": "^7.12.1",
+ "@types/hoist-non-react-statics": "^3.3.1",
+ "@types/use-sync-external-store": "^0.0.3",
+ "hoist-non-react-statics": "^3.3.2",
+ "react-is": "^18.0.0",
+ "use-sync-external-store": "^1.0.0"
+ },
+ "dependencies": {
+ "react-is": {
+ "version": "18.2.0",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
+ "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w=="
+ }
+ }
+ },
+ "reduce-reducers": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/reduce-reducers/-/reduce-reducers-0.4.3.tgz",
+ "integrity": "sha512-+CNMnI8QhgVMtAt54uQs3kUxC3Sybpa7Y63HR14uGLgI9/QR5ggHvpxwhGGe3wmx5V91YwqQIblN9k5lspAmGw=="
+ },
+ "redux": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.0.tgz",
+ "integrity": "sha512-oSBmcKKIuIR4ME29/AeNUnl5L+hvBq7OaJWzaptTQJAntaPvxIJqfnjbaEiCzzaIz+XmVILfqAM3Ob0aXLPfjA==",
+ "requires": {
+ "@babel/runtime": "^7.9.2"
+ }
+ },
+ "redux-actions": {
+ "version": "2.6.5",
+ "resolved": "https://registry.npmjs.org/redux-actions/-/redux-actions-2.6.5.tgz",
+ "integrity": "sha512-pFhEcWFTYNk7DhQgxMGnbsB1H2glqhQJRQrtPb96kD3hWiZRzXHwwmFPswg6V2MjraXRXWNmuP9P84tvdLAJmw==",
+ "requires": {
+ "invariant": "^2.2.4",
+ "just-curry-it": "^3.1.0",
+ "loose-envify": "^1.4.0",
+ "reduce-reducers": "^0.4.3",
+ "to-camel-case": "^1.0.0"
+ }
+ },
+ "redux-flash": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/redux-flash/-/redux-flash-2.0.2.tgz",
+ "integrity": "sha512-tX8Yxf13uy2IVvQm5VpiGabirGySZhM9DZGzDsmU818px5bpmbUsxqCnUy/NtTmUEJnFuU+vL6IYejkbwHr/Dw==",
+ "requires": {
+ "prop-types": "^15.6.1",
+ "redux-actions": "^2.6.5",
+ "uuid": "^3.1.0"
+ }
+ },
+ "redux-thunk": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.1.tgz",
+ "integrity": "sha512-OOYGNY5Jy2TWvTL1KgAlVy6dcx3siPJ1wTq741EPyUKfn6W6nChdICjZwCd0p8AZBs5kWpZlbkXW2nE/zjUa+Q==",
+ "requires": {}
+ },
+ "regenerate": {
+ "version": "1.4.2",
+ "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz",
+ "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==",
+ "dev": true
+ },
+ "regenerate-unicode-properties": {
+ "version": "10.0.1",
+ "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.0.1.tgz",
+ "integrity": "sha512-vn5DU6yg6h8hP/2OkQo3K7uVILvY4iu0oI4t3HFa81UPkhGJwkRwM10JEc3upjdhHjs/k8GJY1sRBhk5sr69Bw==",
+ "dev": true,
+ "requires": {
+ "regenerate": "^1.4.2"
+ }
+ },
+ "regenerator-runtime": {
+ "version": "0.13.9",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz",
+ "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA=="
+ },
+ "regenerator-transform": {
+ "version": "0.15.0",
+ "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.0.tgz",
+ "integrity": "sha512-LsrGtPmbYg19bcPHwdtmXwbW+TqNvtY4riE3P83foeHRroMbH6/2ddFBfab3t7kbzc7v7p4wbkIecHImqt0QNg==",
+ "dev": true,
+ "requires": {
+ "@babel/runtime": "^7.8.4"
+ }
+ },
+ "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==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.3",
+ "functions-have-names": "^1.2.2"
+ }
+ },
+ "regexpp": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz",
+ "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==",
+ "dev": true
+ },
+ "regexpu-core": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.1.0.tgz",
+ "integrity": "sha512-bb6hk+xWd2PEOkj5It46A16zFMs2mv86Iwpdu94la4S3sJ7C973h2dHpYKwIBGaWSO7cIRJ+UX0IeMaWcO4qwA==",
+ "dev": true,
+ "requires": {
+ "regenerate": "^1.4.2",
+ "regenerate-unicode-properties": "^10.0.1",
+ "regjsgen": "^0.6.0",
+ "regjsparser": "^0.8.2",
+ "unicode-match-property-ecmascript": "^2.0.0",
+ "unicode-match-property-value-ecmascript": "^2.0.0"
+ }
+ },
+ "regjsgen": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.6.0.tgz",
+ "integrity": "sha512-ozE883Uigtqj3bx7OhL1KNbCzGyW2NQZPl6Hs09WTvCuZD5sTI4JY58bkbQWa/Y9hxIsvJ3M8Nbf7j54IqeZbA==",
+ "dev": true
+ },
+ "regjsparser": {
+ "version": "0.8.4",
+ "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.8.4.tgz",
+ "integrity": "sha512-J3LABycON/VNEu3abOviqGHuB/LOtOQj8SKmfP9anY5GfAVw/SPjwzSjxGjbZXIxbGfqTHtJw58C2Li/WkStmA==",
+ "dev": true,
+ "requires": {
+ "jsesc": "~0.5.0"
+ },
+ "dependencies": {
+ "jsesc": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz",
+ "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==",
+ "dev": true
+ }
+ }
+ },
+ "reselect": {
+ "version": "4.1.6",
+ "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.6.tgz",
+ "integrity": "sha512-ZovIuXqto7elwnxyXbBtCPo9YFEr3uJqj2rRbcOOog1bmu2Ag85M4hixSwFWyaBMKXNgvPaJ9OSu9SkBPIeJHQ=="
+ },
+ "resolve": {
+ "version": "1.22.1",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
+ "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==",
+ "requires": {
+ "is-core-module": "^2.9.0",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ }
+ },
+ "resolve-from": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="
+ },
+ "reusify": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
+ "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
+ "dev": true
+ },
+ "rimraf": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+ "dev": true,
+ "requires": {
+ "glob": "^7.1.3"
+ }
+ },
+ "run-parallel": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+ "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+ "dev": true,
+ "requires": {
+ "queue-microtask": "^1.2.2"
+ }
+ },
+ "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=="
+ },
+ "scheduler": {
+ "version": "0.23.0",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz",
+ "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==",
+ "requires": {
+ "loose-envify": "^1.1.0"
+ }
+ },
+ "semver": {
+ "version": "7.3.7",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
+ "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==",
+ "dev": true,
+ "requires": {
+ "lru-cache": "^6.0.0"
+ }
+ },
+ "shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dev": true,
+ "requires": {
+ "shebang-regex": "^3.0.0"
+ }
+ },
+ "shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "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==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.0",
+ "get-intrinsic": "^1.0.2",
+ "object-inspect": "^1.9.0"
+ }
+ },
+ "slash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+ "dev": true
+ },
+ "source-map": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ=="
+ },
+ "source-map-js": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
+ "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw=="
+ },
+ "string.prototype.matchall": {
+ "version": "4.0.7",
+ "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.7.tgz",
+ "integrity": "sha512-f48okCX7JiwVi1NXCVWcFnZgADDC/n2vePlQ/KUCNqCikLLilQvwjMO8+BHVKvgzH0JB0J9LEPgxOGT02RoETg==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.19.1",
+ "get-intrinsic": "^1.1.1",
+ "has-symbols": "^1.0.3",
+ "internal-slot": "^1.0.3",
+ "regexp.prototype.flags": "^1.4.1",
+ "side-channel": "^1.0.4"
+ }
+ },
+ "string.prototype.trimend": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz",
+ "integrity": "sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.19.5"
+ }
+ },
+ "string.prototype.trimstart": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz",
+ "integrity": "sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.19.5"
+ }
+ },
+ "strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^5.0.1"
+ }
+ },
+ "strip-bom": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+ "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==",
+ "dev": true
+ },
+ "strip-json-comments": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+ "dev": true
+ },
+ "styled-jsx": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.0.2.tgz",
+ "integrity": "sha512-LqPQrbBh3egD57NBcHET4qcgshPks+yblyhPlH2GY8oaDgKs8SK4C3dBh3oSJjgzJ3G5t1SYEZGHkP+QEpX9EQ==",
+ "requires": {}
+ },
+ "stylis": {
+ "version": "4.0.13",
+ "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.0.13.tgz",
+ "integrity": "sha512-xGPXiFVl4YED9Jh7Euv2V220mriG9u4B2TA6Ybjc1catrstKD2PpIdU3U0RKpkVBC2EhmL/F0sPCr9vrFTNRag=="
+ },
+ "supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^4.0.0"
+ }
+ },
+ "supports-preserve-symlinks-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="
+ },
+ "text-table": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
+ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
+ "dev": true
+ },
+ "to-camel-case": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/to-camel-case/-/to-camel-case-1.0.0.tgz",
+ "integrity": "sha512-nD8pQi5H34kyu1QDMFjzEIYqk0xa9Alt6ZfrdEMuHCFOfTLhDG5pgTu/aAM9Wt9lXILwlXmWP43b8sav0GNE8Q==",
+ "requires": {
+ "to-space-case": "^1.0.0"
+ }
+ },
+ "to-fast-properties": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
+ "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog=="
+ },
+ "to-no-case": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/to-no-case/-/to-no-case-1.0.2.tgz",
+ "integrity": "sha512-Z3g735FxuZY8rodxV4gH7LxClE4H0hTIyHNIHdk+vpQxjLm0cwnKXq/OFVZ76SOQmto7txVcwSCwkU5kqp+FKg=="
+ },
+ "to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dev": true,
+ "requires": {
+ "is-number": "^7.0.0"
+ }
+ },
+ "to-space-case": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/to-space-case/-/to-space-case-1.0.0.tgz",
+ "integrity": "sha512-rLdvwXZ39VOn1IxGL3V6ZstoTbwLRckQmn/U8ZDLuWwIXNpuZDhQ3AiRUlhTbOXFVE9C+dR51wM0CBDhk31VcA==",
+ "requires": {
+ "to-no-case": "^1.0.0"
+ }
+ },
+ "tsconfig-paths": {
+ "version": "3.14.1",
+ "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz",
+ "integrity": "sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==",
+ "dev": true,
+ "requires": {
+ "@types/json5": "^0.0.29",
+ "json5": "^1.0.1",
+ "minimist": "^1.2.6",
+ "strip-bom": "^3.0.0"
+ }
+ },
+ "tslib": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz",
+ "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ=="
+ },
+ "tsutils": {
+ "version": "3.21.0",
+ "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz",
+ "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==",
+ "dev": true,
+ "requires": {
+ "tslib": "^1.8.1"
+ },
+ "dependencies": {
+ "tslib": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
+ "dev": true
+ }
+ }
+ },
+ "type-check": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+ "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
+ "dev": true,
+ "requires": {
+ "prelude-ls": "^1.2.1"
+ }
+ },
+ "type-fest": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
+ "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
+ "dev": true
+ },
+ "typescript": {
+ "version": "4.7.4",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz",
+ "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==",
+ "dev": true
+ },
+ "unbox-primitive": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz",
+ "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "has-bigints": "^1.0.2",
+ "has-symbols": "^1.0.3",
+ "which-boxed-primitive": "^1.0.2"
+ }
+ },
+ "unicode-canonical-property-names-ecmascript": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz",
+ "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==",
+ "dev": true
+ },
+ "unicode-match-property-ecmascript": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz",
+ "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==",
+ "dev": true,
+ "requires": {
+ "unicode-canonical-property-names-ecmascript": "^2.0.0",
+ "unicode-property-aliases-ecmascript": "^2.0.0"
+ }
+ },
+ "unicode-match-property-value-ecmascript": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz",
+ "integrity": "sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw==",
+ "dev": true
+ },
+ "unicode-property-aliases-ecmascript": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.0.0.tgz",
+ "integrity": "sha512-5Zfuy9q/DFr4tfO7ZPeVXb1aPoeQSdeFMLpYuFebehDAhbuevLs5yxSZmIFN1tP5F9Wl4IpJrYojg85/zgyZHQ==",
+ "dev": true
+ },
+ "update-browserslist-db": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.5.tgz",
+ "integrity": "sha512-dteFFpCyvuDdr9S/ff1ISkKt/9YZxKjI9WlRR99c180GaztJtRa/fn18FdxGVKVsnPY7/a/FDN68mcvUmP4U7Q==",
+ "requires": {
+ "escalade": "^3.1.1",
+ "picocolors": "^1.0.0"
+ }
+ },
+ "uri-js": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+ "dev": true,
+ "requires": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "use-sync-external-store": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.1.0.tgz",
+ "integrity": "sha512-SEnieB2FPKEVne66NpXPd1Np4R1lTNKfjuy3XdIoPQKYBAFdzbzSZlSn1KJZUiihQLQC5Znot4SBz1EOTBwQAQ==",
+ "requires": {}
+ },
+ "uuid": {
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
+ "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
+ },
+ "v8-compile-cache": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz",
+ "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==",
+ "dev": true
+ },
+ "which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dev": true,
+ "requires": {
+ "isexe": "^2.0.0"
+ }
+ },
+ "which-boxed-primitive": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz",
+ "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==",
+ "dev": true,
+ "requires": {
+ "is-bigint": "^1.0.1",
+ "is-boolean-object": "^1.1.0",
+ "is-number-object": "^1.0.4",
+ "is-string": "^1.0.5",
+ "is-symbol": "^1.0.3"
+ }
+ },
+ "word-wrap": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
+ "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
+ "dev": true
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
+ "dev": true
+ },
+ "yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true
+ },
+ "yaml": {
+ "version": "1.10.2",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz",
+ "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg=="
+ }
+ }
+}
diff --git a/app2/package.json b/app2/package.json
new file mode 100644
index 000000000..4cb4fa0d9
--- /dev/null
+++ b/app2/package.json
@@ -0,0 +1,33 @@
+{
+ "name": "app2",
+ "version": "0.1.0",
+ "private": true,
+ "scripts": {
+ "dev": "PORT=4000 next dev",
+ "build": "next build",
+ "start": "next start",
+ "lint": "next lint"
+ },
+ "dependencies": {
+ "@emotion/react": "^11.9.3",
+ "@reduxjs/toolkit": "^1.8.3",
+ "@types/react-redux": "^7.1.24",
+ "next": "12.2.2",
+ "react": "18.2.0",
+ "react-dom": "18.2.0",
+ "react-redux": "^8.0.2",
+ "redux": "^4.2.0",
+ "redux-flash": "^2.0.2"
+ },
+ "devDependencies": {
+ "@babel/core": "^7.18.9",
+ "@babel/preset-env": "^7.18.9",
+ "@types/node": "18.0.6",
+ "@types/react": "18.0.15",
+ "@types/react-dom": "18.0.6",
+ "eslint": "8.20.0",
+ "eslint-config-next": "12.2.2",
+ "typescript": "4.7.4"
+ },
+ "types": "./types/*"
+}
diff --git a/app2/public/favicon.ico b/app2/public/favicon.ico
new file mode 100755
index 000000000..718d6fea4
Binary files /dev/null and b/app2/public/favicon.ico differ
diff --git a/app2/public/vercel.svg b/app2/public/vercel.svg
new file mode 100755
index 000000000..fbf0e25a6
--- /dev/null
+++ b/app2/public/vercel.svg
@@ -0,0 +1,4 @@
+
\ No newline at end of file
diff --git a/app2/src/api/api.js b/app2/src/api/api.js
new file mode 100644
index 000000000..a464fc186
--- /dev/null
+++ b/app2/src/api/api.js
@@ -0,0 +1,723 @@
+import jwtDecode from 'jwt-decode';
+import { parseFromTimeZone, convertToTimeZone } from 'date-fns-timezone';
+import { format } from 'date-fns';
+
+export const UserRoleEnum = Object.freeze({
+ GOVERNMENT_ADMIN: 'government_admin',
+ CAMPAIGN_ADMIN: 'campaign_admin',
+ CAMPAIGN_STAFF: 'campaign_staff',
+});
+
+export const ContributionTypeEnum = Object.freeze({
+ CONTRIBUTION: 'contribution',
+ OTHER: 'other',
+});
+
+export const ContributionTypeFieldEnum = Object.freeze({
+ CONTRIBUTION: 'Contribution',
+ OTHER: 'Other Receipt',
+});
+
+export const DataToContributionTypeFieldMap = new Map([
+ [ContributionTypeEnum.CONTRIBUTION, ContributionTypeFieldEnum.CONTRIBUTION],
+ [ContributionTypeEnum.OTHER, ContributionTypeFieldEnum.OTHER],
+]);
+
+export const ContributionTypeFieldToDataMap = new Map([
+ [ContributionTypeFieldEnum.CONTRIBUTION, ContributionTypeEnum.CONTRIBUTION],
+ [ContributionTypeFieldEnum.OTHER, ContributionTypeEnum.OTHER],
+]);
+
+export const ContributionSubTypeEnum = Object.freeze({
+ CASH: 'cash',
+ INKIND_CONTRIBUTION: 'inkind_contribution',
+ INKIND_PAID_SUPERVISION: 'inkind_paid_supervision',
+ INKIND_FORGIVEN_ACCOUNT: 'inkind_forgiven_account',
+ INKIND_FORGIVEN_PERSONAL: 'inkind_forgiven_personal',
+ ITEM_SOLD_FAIR_MARKET: 'item_sold_fair_market',
+ ITEM_RETURNED_CHECK: 'item_returned_check',
+ ITEM_MISC: 'item_misc',
+ ITEM_REFUND: 'item_refund',
+});
+
+export const ContributionSubTypeFieldEnum = Object.freeze({
+ ITEM_SOLD_FAIR_MARKET: 'Items Sold at Fair Market Value',
+ LOST_RETURNED_CHECK: 'Lost or Returned Check',
+ MISC_OTHER_RECEIPT: 'Miscellaneous Other Receipt',
+ REFUND_REBATES: 'Refunds and Rebates',
+ INKIND_CONTRIBUTION: 'In-Kind Contribution',
+ INKIND_FORGIVEN_ACCOUNT: 'In-Kind Forgiven Accounts Payable',
+ INKIND_FORGIVEN_PERSONAL: 'In-Kind /Forgiven Personal Expenditure',
+ CASH_CONTRIBUTION: 'Cash Contribution',
+});
+
+export const InKindDescriptionTypeEnum = Object.freeze({
+ WAGES: 'wages',
+ BROADCAST: 'broadcast_advertising',
+ FUNDRAISING: 'fundraising_event_expenses',
+ GENERAL_OPERATING: 'general_operating_expenses',
+ PRINTING: 'printing',
+ MANAGEMENT: 'management',
+ NEWSPAPER: 'print_advertising',
+ OTHER_AD: 'other_advertising',
+ PETITION: 'petition_circulators',
+ POSTAGE: 'postage',
+ PREP_AD: 'preparation_of_advertising',
+ POLLING: 'surveys_and_polls',
+ TRAVEL: 'travel_expenses',
+ UTILITIES: 'utilities',
+});
+
+export const DataToContributionSubTypeFieldMap = new Map([
+ [
+ ContributionSubTypeEnum.CASH,
+ ContributionSubTypeFieldEnum.CASH_CONTRIBUTION,
+ ],
+ [
+ ContributionSubTypeEnum.INKIND_CONTRIBUTION,
+ ContributionSubTypeFieldEnum.INKIND_CONTRIBUTION,
+ ],
+ [
+ ContributionSubTypeEnum.INKIND_FORGIVEN_ACCOUNT,
+ ContributionSubTypeFieldEnum.INKIND_FORGIVEN_ACCOUNT,
+ ],
+ [
+ ContributionSubTypeEnum.INKIND_FORGIVEN_PERSONAL,
+ ContributionSubTypeFieldEnum.INKIND_FORGIVEN_PERSONAL,
+ ],
+ [
+ ContributionSubTypeEnum.ITEM_SOLD_FAIR_MARKET,
+ ContributionSubTypeFieldEnum.ITEM_SOLD_FAIR_MARKET,
+ ],
+ [
+ ContributionSubTypeEnum.ITEM_RETURNED_CHECK,
+ ContributionSubTypeFieldEnum.LOST_RETURNED_CHECK,
+ ],
+ [
+ ContributionSubTypeEnum.ITEM_MISC,
+ ContributionSubTypeFieldEnum.MISC_OTHER_RECEIPT,
+ ],
+ [
+ ContributionSubTypeEnum.ITEM_REFUND,
+ ContributionSubTypeFieldEnum.REFUND_REBATES,
+ ],
+]);
+
+export const ContributionSubTypeFieldToDataMap = new Map([
+ [
+ ContributionSubTypeFieldEnum.CASH_CONTRIBUTION,
+ ContributionSubTypeEnum.CASH,
+ ],
+ [
+ ContributionSubTypeFieldEnum.INKIND_CONTRIBUTION,
+ ContributionSubTypeEnum.INKIND_CONTRIBUTION,
+ ],
+ [
+ ContributionSubTypeFieldEnum.INKIND_FORGIVEN_ACCOUNT,
+ ContributionSubTypeEnum.INKIND_FORGIVEN_ACCOUNT,
+ ],
+ [
+ ContributionSubTypeFieldEnum.INKIND_FORGIVEN_PERSONAL,
+ ContributionSubTypeEnum.INKIND_FORGIVEN_PERSONAL,
+ ],
+ [
+ ContributionSubTypeFieldEnum.ITEM_SOLD_FAIR_MARKET,
+ ContributionSubTypeEnum.ITEM_SOLD_FAIR_MARKET,
+ ],
+ [
+ ContributionSubTypeFieldEnum.LOST_RETURNED_CHECK,
+ ContributionSubTypeEnum.ITEM_RETURNED_CHECK,
+ ],
+ [
+ ContributionSubTypeFieldEnum.MISC_OTHER_RECEIPT,
+ ContributionSubTypeEnum.ITEM_MISC,
+ ],
+ [
+ ContributionSubTypeFieldEnum.REFUND_REBATES,
+ ContributionSubTypeEnum.ITEM_REFUND,
+ ],
+]);
+
+export const ContributorTypeEnum = Object.freeze({
+ INDIVIDUAL: 'individual',
+ BUSINESS: 'business',
+ FAMILY: 'family',
+ LABOR: 'labor',
+ POLITICAL_COMMITTEE: 'political_committee',
+ POLITICAL_PARTY: 'political_party',
+ UNREGISTERED: 'unregistered',
+ OTHER: 'other',
+});
+
+export const ContributorTypeFieldEnum = Object.freeze({
+ BUSINESS_ENTITY: 'Business Entity',
+ LABOR_ORGANIZATION: 'Labor Organization',
+ POLITICAL_COMMITTEE: 'Political Committee',
+ POLITICAL_PARTY_COMMITEE: 'Political Party Committee',
+ UNREGISTERED_COMMITTEE: 'Unregistered Committee',
+ INDIVIDUAL: 'Individual',
+ CANDIDATE_IMMEDIATE_FAMILY: 'Candidate’s Immediate Family',
+ OTHER: 'Other',
+});
+
+export const DataToContributorTypeFieldMap = new Map([
+ [ContributorTypeEnum.INDIVIDUAL, ContributorTypeFieldEnum.INDIVIDUAL],
+ [ContributorTypeEnum.BUSINESS, ContributorTypeFieldEnum.BUSINESS_ENTITY],
+ [
+ ContributorTypeEnum.FAMILY,
+ ContributorTypeFieldEnum.CANDIDATE_IMMEDIATE_FAMILY,
+ ],
+ [ContributorTypeEnum.LABOR, ContributorTypeFieldEnum.LABOR_ORGANIZATION],
+ [
+ ContributorTypeEnum.POLITICAL_COMMITTEE,
+ ContributorTypeFieldEnum.POLITICAL_COMMITTEE,
+ ],
+ [
+ ContributorTypeEnum.POLITICAL_PARTY,
+ ContributorTypeFieldEnum.POLITICAL_PARTY_COMMITEE,
+ ],
+ [
+ ContributorTypeEnum.UNREGISTERED,
+ ContributorTypeFieldEnum.UNREGISTERED_COMMITTEE,
+ ],
+ [ContributorTypeEnum.OTHER, ContributorTypeFieldEnum.OTHER],
+]);
+
+export const ContributorTypeFieldToDataMap = new Map([
+ [ContributorTypeFieldEnum.INDIVIDUAL, ContributorTypeEnum.INDIVIDUAL],
+ [ContributorTypeFieldEnum.BUSINESS_ENTITY, ContributorTypeEnum.BUSINESS],
+ [
+ ContributorTypeFieldEnum.CANDIDATE_IMMEDIATE_FAMILY,
+ ContributorTypeEnum.FAMILY,
+ ],
+ [ContributorTypeFieldEnum.LABOR_ORGANIZATION, ContributorTypeEnum.LABOR],
+ [
+ ContributorTypeFieldEnum.POLITICAL_COMMITTEE,
+ ContributorTypeEnum.POLITICAL_COMMITTEE,
+ ],
+ [
+ ContributorTypeFieldEnum.POLITICAL_PARTY_COMMITEE,
+ ContributorTypeEnum.POLITICAL_PARTY,
+ ],
+ [
+ ContributorTypeFieldEnum.UNREGISTERED_COMMITTEE,
+ ContributorTypeEnum.UNREGISTERED,
+ ],
+ [ContributorTypeFieldEnum.OTHER, ContributorTypeEnum.OTHER],
+]);
+
+export const OaeTypeEnum = Object.freeze({
+ SEED_MONEY: 'seed',
+ MATCHABLE: 'matchable',
+ PUBLIC_MATCHING_CONTRIBUTION: 'public_matching_contribution',
+ QUALIFYING: 'qualifying',
+ ALLOWABLE: 'allowable',
+ INKIND: 'inkind',
+ OTHER: 'other',
+});
+
+export const OaeTypeFieldEnum = Object.freeze({
+ SEED_MONEY: 'Seed Money',
+ MATCHABLE: 'Matchable',
+ PUBLIC_MATCHING_CONTRIBUTION: 'Public Matching Contribution',
+ QUALIFYING: 'Qualifying',
+ ALLOWABLE: 'Allowable',
+ INKIND: 'In-Kind',
+ OTHER: 'Other',
+});
+
+export const DataToOaeTypeTypeFieldMap = new Map([
+ [OaeTypeEnum.SEED_MONEY, OaeTypeFieldEnum.SEED_MONEY],
+ [OaeTypeEnum.MATCHABLE, OaeTypeFieldEnum.MATCHABLE],
+ [
+ OaeTypeEnum.PUBLIC_MATCHING_CONTRIBUTION,
+ OaeTypeFieldEnum.PUBLIC_MATCHING_CONTRIBUTION,
+ ],
+ [OaeTypeEnum.QUALIFYING, OaeTypeFieldEnum.QUALIFYING],
+ [OaeTypeEnum.ALLOWABLE, OaeTypeFieldEnum.ALLOWABLE],
+ [OaeTypeEnum.INKIND, OaeTypeFieldEnum.INKIND],
+ [OaeTypeEnum.OTHER, OaeTypeFieldEnum.OTHER],
+]);
+
+export const OaeTypeFieldToDataMap = new Map([
+ [OaeTypeFieldEnum.SEED_MONEY, OaeTypeEnum.SEED_MONEY],
+ [OaeTypeFieldEnum.MATCHABLE, OaeTypeEnum.MATCHABLE],
+ [
+ OaeTypeFieldEnum.PUBLIC_MATCHING_CONTRIBUTION,
+ OaeTypeEnum.PUBLIC_MATCHING_CONTRIBUTION,
+ ],
+ [OaeTypeFieldEnum.QUALIFYING, OaeTypeEnum.QUALIFYING],
+ [OaeTypeFieldEnum.ALLOWABLE, OaeTypeEnum.ALLOWABLE],
+ [OaeTypeFieldEnum.INKIND, OaeTypeEnum.INKIND],
+]);
+
+export const PhoneTypeEnum = Object.freeze({
+ MOBILE: 'Mobile',
+ WORK: 'Work',
+ HOME: 'Home',
+});
+
+export const PhoneTypeFieldEnum = Object.freeze({
+ MOBILE_PHONE: 'Mobile Phone',
+ WORK_PHONE: 'Work Phone',
+ HOME_PHONE: 'Home Phone',
+});
+
+export const PaymentMethodEnum = Object.freeze({
+ CASH: 'cash',
+ CHECK: 'check',
+ MONEY_ORDER: 'money_order',
+ CREDIT_CARD_ONLINE: 'credit_card_online',
+ CREDIT_CARD_PAPER: 'credit_card_paper',
+ ETF: 'electronic_funds_transfer',
+ DEBIT: 'debit',
+});
+
+export const DataToPhoneTypeFieldMap = new Map([
+ [PhoneTypeEnum.MOBILE, PhoneTypeFieldEnum.MOBILE_PHONE],
+ [PhoneTypeEnum.WORK, PhoneTypeFieldEnum.WORK_PHONE],
+ [PhoneTypeEnum.HOME, PhoneTypeFieldEnum.HOME_PHONE],
+]);
+
+export const PhoneTypeFieldToDataMap = new Map([
+ [PhoneTypeFieldEnum.MOBILE_PHONE, PhoneTypeEnum.MOBILE],
+ [PhoneTypeFieldEnum.HOME_PHONE, PhoneTypeEnum.HOME_PHONE],
+ [PhoneTypeFieldEnum.WORK_PHONE, PhoneTypeEnum.WORK],
+]);
+
+export const ContributionStatusEnum = Object.freeze({
+ ARCHIVED: 'Archived',
+ DRAFT: 'Draft',
+ SUBMITTED: 'Submitted',
+ PROCESSED: 'Processed',
+ AWAITING: 'Awaiting',
+});
+
+export const ExpenditureTypeEnum = Object.freeze({
+ EXPENDITURE: 'expenditure',
+ OTHER: 'other',
+ OTHER_DISBURSEMENT: 'other_disbursement',
+});
+
+export const ExpenditureSubTypeEnum = Object.freeze({
+ ACCOUNTS_PAYABLE: 'accounts_payable',
+ CASH_EXPENDITURE: 'cash_expenditure',
+ PERSONAL_EXPENDITURE: 'personal_expenditure',
+ ACCOUNTS_PAYABLE_RESCINDED: 'accounts_payable_rescinded',
+ CASH_BALANCE_ADJUSTMENT: 'cash_balance_adjustment',
+ MISCELLANEOUS_OTHER_DISBURSEMENT: 'miscellaneous_other_disbursement',
+ REFUND_OF_CONTRIBUTION: 'refund_of_expenditure',
+});
+
+export const PayeeTypeEnum = Object.freeze({
+ INDIVIDUAL: 'individual',
+ BUSINESS: 'business',
+ FAMILY: 'family',
+ LABOR: 'labor',
+ POLITICAL_COMMITTEE: 'political_committee',
+ POLITICAL_PARTY: 'political_party',
+ UNREGISTERED: 'unregistered',
+ OTHER: 'other',
+});
+
+export const ExpenditureStatusEnum = Object.freeze({
+ ARCHIVED: 'archived',
+ DRAFT: 'draft',
+ SUBMITTED: 'submitted',
+ OUT_OF_COMPLIANCE: 'out_of_compliance',
+ IN_COMPLIANCE: 'in_compliance',
+});
+
+export const PurposeTypeEnum = Object.freeze({
+ WAGES: 'wages',
+ CASH: 'cash_contribution',
+ REIMBURSEMENT: 'personal_reimbursement',
+ BROADCAST: 'broadcast_advertising',
+ FUNDRAISING: 'fundraising_event_expenses',
+ GENERAL_OPERATING: 'general_operating_expenses',
+ PRIMTING: 'printing',
+ MANAGEMENT: 'management',
+ NEWSPAPER: 'print_advertising',
+ OTHER_AD: 'other_advertising',
+ PETITION: 'petition_circulators',
+ POSTAGE: 'postage',
+ PREP_AD: 'preparation_of_advertising',
+ POLLING: 'surveys_and_polls',
+ TRAVEL: 'travel_expenses',
+ UTILITIES: 'utilities',
+});
+
+export function post(url, data) {
+ const headers = {
+ 'Content-Type': 'application/json',
+ Accept: 'application/json',
+ };
+
+ if (data.format === 'csv') {
+ headers.Accept = 'text/csv';
+ }
+
+ if (process.env.NODE_ENV === 'test' && !!process.env.TOKEN) {
+ headers.Cookie = `token=${process.env.TOKEN}`;
+ }
+ return fetch(url, {
+ method: 'POST',
+ headers,
+ body: JSON.stringify(data),
+ credentials: 'include',
+ });
+}
+
+export function deleteRequest(url) {
+ const headers = {
+ 'Content-Type': 'application/json',
+ Accept: 'application/json',
+ };
+ if (process.env.NODE_ENV === 'test' && !!process.env.TOKEN) {
+ headers.Cookie = `token=${process.env.TOKEN}`;
+ }
+ return fetch(url, {
+ method: 'DELETE',
+ headers,
+ credentials: 'include',
+ });
+}
+
+export function get(url) {
+ const headers = {
+ 'Content-Type': 'application/json',
+ Accept: 'application/json',
+ };
+ if (process.env.NODE_ENV === 'test' && !!process.env.TOKEN) {
+ headers.Cookie = `token=${process.env.TOKEN}`;
+ }
+ return fetch(url, {
+ method: 'GET',
+ headers,
+ credentials: 'include',
+ });
+}
+
+export function put(url, data) {
+ const headers = {
+ 'Content-Type': 'application/json',
+ Accept: 'application/json',
+ };
+ if (process.env.NODE_ENV === 'test' && !!process.env.TOKEN) {
+ headers.Cookie = `token=${process.env.TOKEN}`;
+ }
+ return fetch(url, {
+ method: 'PUT',
+ headers,
+ body: JSON.stringify(data),
+ credentials: 'include',
+ });
+}
+
+export function decodeToken(token) {
+ return jwtDecode(token);
+}
+
+export function baseUrl(isDataVisualizationRequest = false) {
+ if (process.env.NODE_ENV === 'test') {
+ return 'http://localhost:3000';
+ }
+
+ if (window && window.location.hostname.includes('qa')) {
+ return 'https://api-qa.openelectionsportland.org';
+ }
+
+ if (process.env.NODE_ENV === 'development' && !isDataVisualizationRequest) {
+ return 'http://localhost:3000';
+ }
+
+ return 'https://api.openelectionsportland.org';
+}
+
+// returns the jwt session token
+export function login(email, password) {
+ return post(`${baseUrl()}/users/login`, { email, password });
+}
+
+// returns the jwt session token
+export function me() {
+ return get(`${baseUrl()}/me`).then(response => response.json());
+}
+
+export function dateToPickerFormat(date) {
+ return date !== null && date !== ''
+ ? format(
+ parseFromTimeZone(date, {
+ timeZone: 'America/Los_Angeles',
+ }),
+ 'yyyy-MM-dd'
+ )
+ : '';
+}
+
+export function dateToMicroTime(formatedDate) {
+ return new Date(
+ convertToTimeZone(formatedDate, {
+ timeZone: 'America/Los_Angeles',
+ })
+ ).getTime();
+}
+
+export function inviteUsertoGovernment(
+ email,
+ firstName,
+ lastName,
+ governmentId
+) {
+ return post(`${baseUrl()}/users/invite`, {
+ email,
+ firstName,
+ lastName,
+ governmentId,
+ role: UserRoleEnum.GOVERNMENT_ADMIN,
+ });
+}
+
+export function inviteUsertoCampaign(
+ email,
+ firstName,
+ lastName,
+ campaignId,
+ role
+) {
+ return post(`${baseUrl()}/users/invite`, {
+ email,
+ firstName,
+ lastName,
+ campaignId,
+ role,
+ });
+}
+
+export function resendInvite(userId) {
+ return post(`${baseUrl()}/users/resend-invite`, { userId });
+}
+
+export function removePermission(permissionId) {
+ return deleteRequest(`${baseUrl()}/permissions/${permissionId}`);
+}
+
+export function redeemInvite(invitationCode, password, firstName, lastName) {
+ const data = {
+ invitationCode,
+ password,
+ firstName,
+ lastName,
+ };
+
+ return post(`${baseUrl()}/users/redeem-invite`, data);
+}
+
+export function getCampaignUsers(campaignId) {
+ return post(`${baseUrl()}/users`, { campaignId }).then(response =>
+ response.json()
+ );
+}
+
+export function getGovernmentUsers(governmentId) {
+ return post(`${baseUrl()}/users`, { governmentId }).then(response =>
+ response.json()
+ );
+}
+
+// path: '/users/send-password-reset-email',
+// method: 'post',
+export function sendPasswordResetEmail(email) {
+ return post(`${baseUrl()}/users/send-password-reset-email`, { email });
+}
+
+// path: '/users/reset-password',
+// method: 'post',
+export function resetPassword(invitationCode, password) {
+ return post(`${baseUrl()}/users/reset-password`, {
+ invitationCode,
+ password,
+ });
+}
+
+// path: '/users/password',
+// method: 'put',
+export function updatePassword(currentPassword, newPassword) {
+ return put(`${baseUrl()}/users/password`, { currentPassword, newPassword });
+}
+
+// path: '/activities',
+// method: 'post',
+export function getCampaignActivities(activitiesAttrs) {
+ return post(`${baseUrl()}/activities`, activitiesAttrs).then(response =>
+ response.json()
+ );
+}
+
+export function getGovernmentActivities(activitiesAttrs) {
+ return post(`${baseUrl()}/activities`, activitiesAttrs).then(response =>
+ response.json()
+ );
+}
+
+export function getContributionActivities(activitiesAttrs) {
+ return post(`${baseUrl()}/activities`, activitiesAttrs).then(response =>
+ response.json()
+ );
+}
+
+export function getExpenditureActivities(activitiesAttrs) {
+ return post(`${baseUrl()}/activities`, activitiesAttrs).then(response =>
+ response.json()
+ );
+}
+
+// path: '/campaigns',
+// method: 'post',
+export function getCampaignsForGovernment(governmentId) {
+ return post(`${baseUrl()}/campaigns`, { governmentId }).then(response =>
+ response.json()
+ );
+}
+
+// path: '/campaigns/new',
+// method: 'post',
+export function createCampaignForGovernment(campaignAttrs) {
+ return post(`${baseUrl()}/campaigns/new`, campaignAttrs);
+}
+
+// path: '/campaigns/update',
+// method: 'post',
+export function updateCampaignNameForGovernment(campaignAttrs) {
+ return post(`${baseUrl()}/campaigns/update`, campaignAttrs).then(response =>
+ response.json()
+ );
+}
+
+// path: '/contributions/:id'
+// method: 'put',
+export function updateContribution(contributionAttrs) {
+ return put(
+ `${baseUrl()}/contributions/${contributionAttrs.id}`,
+ contributionAttrs
+ );
+}
+
+// path: '/contributions/new',
+// method: 'post',
+export function createContribution(contributionAttrs) {
+ return post(`${baseUrl()}/contributions/new`, contributionAttrs);
+}
+
+// path: '/contributions',
+// method: 'post',
+export function getContributions(contributionSearchAttrs) {
+ return post(`${baseUrl()}/contributions`, contributionSearchAttrs);
+}
+
+// path: '/contributions/:id/comments',
+// method: 'post',
+export function postContributionComment(contributionId, comment, attachment) {
+ const formData = new FormData();
+ if (attachment) {
+ formData.append('attachment', attachment);
+ }
+ formData.append('comment', comment);
+ return fetch(`${baseUrl()}/contributions/${contributionId}/comments`, {
+ method: 'POST',
+ body: formData,
+ credentials: 'include',
+ });
+}
+
+// path: '/contributions/{id}',
+// method: 'post',
+export function getContributionById(id) {
+ return get(`${baseUrl()}/contributions/${id}`);
+}
+
+// path: '/contributions/{id}',
+// method: 'delete',
+export function archiveContribution(id) {
+ return deleteRequest(`${baseUrl()}/contributions/${id}`);
+}
+
+// path: '/expenditures/new',
+// method: 'post',
+export function createExpenditure(expenditureAttrs) {
+ return post(`${baseUrl()}/expenditures/new`, expenditureAttrs);
+}
+
+// path: '/expenditures/:id/comments',
+// method: 'post',
+export function postExpenditureComment(expenditureId, comment, attachment) {
+ const formData = new FormData();
+ if (attachment) {
+ formData.append('attachment', attachment);
+ }
+ formData.append('comment', comment);
+ return fetch(`${baseUrl()}/expenditures/${expenditureId}/comments`, {
+ method: 'POST',
+ body: formData,
+ credentials: 'include',
+ });
+}
+
+// path: '/expenditures',
+// method: 'post',
+export function getExpenditures(expenditureSearchAttrs) {
+ return post(`${baseUrl()}/expenditures`, expenditureSearchAttrs);
+}
+
+// path: '/expenditures/:id',
+// method: 'get',
+export function getExpenditureById(id) {
+ return get(`${baseUrl()}/expenditures/${id}`);
+}
+
+// path: '/expenditures/:id'
+// method: 'put',
+export function updateExpenditure(expenditureAttrs) {
+ return put(
+ `${baseUrl()}/expenditures/${expenditureAttrs.id}`,
+ expenditureAttrs
+ );
+}
+
+// path: '/summary'
+// method: 'post',
+// summaryArttrs = {governmentId: integer OR campaignId: integer}
+export function getStatusSummary(summaryAttrs) {
+ return post(`${baseUrl()}/summary`, summaryAttrs);
+}
+
+// path '/matches/:id'
+// method: 'get'
+export function getMatchesByContributionId(id) {
+ return get(`${baseUrl()}/matches/${id}`);
+}
+
+/*
+path '/matches'
+method: 'post'
+@attrs {
+contributionId: number,
+matchId: string,
+matchStrength: enum[exact, strong, weak, none]
+ }
+ */
+export function updateMatchForContribution(attrs) {
+ return post(`${baseUrl()}/matches`, attrs);
+}
+
+export function getContributionGeoData() {
+ return get(`${baseUrl(true)}/contributionsgeo`).then(response =>
+ response.json()
+ );
+}
+
+export function getExternalContributionGeoData() {
+ return get(`${baseUrl()}/external-contributionsgeo`).then(response =>
+ response.json()
+ );
+}
diff --git a/app2/src/api/api.test.js b/app2/src/api/api.test.js
new file mode 100644
index 000000000..c53b32ee5
--- /dev/null
+++ b/app2/src/api/api.test.js
@@ -0,0 +1,562 @@
+import * as api from './api';
+
+let govAdminToken;
+let campaignAdminToken;
+let campaignStaffToken;
+let governmentId;
+let campaignId;
+let campaignStaffId;
+let campaignAdminId;
+
+describe('API', () => {
+ beforeAll(async () => {
+ let tokenResponse = await api.login(
+ 'govadmin@openelectionsportland.org',
+ 'password'
+ );
+ govAdminToken = tokenResponse.headers
+ .get('set-cookie')
+ .match(/=([a-zA-Z0-9].+); Path/)[1];
+ let decodedToken = api.decodeToken(govAdminToken);
+ governmentId = decodedToken.permissions[0].governmentId;
+
+ tokenResponse = await api.login(
+ 'campaignadmin@openelectionsportland.org',
+ 'password'
+ );
+
+ campaignAdminToken = tokenResponse.headers
+ .get('set-cookie')
+ .match(/=([a-zA-Z0-9].+); Path/)[1];
+ decodedToken = api.decodeToken(campaignAdminToken);
+ campaignId = decodedToken.permissions[0].campaignId;
+ campaignAdminId = decodedToken.id;
+
+ tokenResponse = await api.login(
+ 'campaignstaff@openelectionsportland.org',
+ 'password'
+ );
+ campaignStaffToken = tokenResponse.headers
+ .get('set-cookie')
+ .match(/=([a-zA-Z0-9].+); Path/)[1];
+ decodedToken = api.decodeToken(campaignStaffToken);
+ campaignStaffId = decodedToken.id;
+ });
+
+ beforeEach(() => {
+ delete process.env.TOKEN;
+ });
+
+ it('decodeToken', () => {
+ const decoded = api.decodeToken(
+ 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MzEwOSwiZXhwIjoxNTU4NTQ2OTE5OTk5LCJmaXJzdE5hbWUiOiJHb3Zlcm5tZW50IiwibGFzdE5hbWUiOiJBZG1pbiIsImVtYWlsIjoiZ292YWRtaW5Ab3BlbmVsZWN0aW9uc3BvcnRsYW5kLm9yZyIsInBlcm1pc3Npb25zIjpbeyJyb2xlIjoiZ292ZXJubWVudF9hZG1pbiIsInR5cGUiOiJnb3Zlcm5tZW50IiwiaWQiOjI0MTF9XSwiaWF0IjoxNTU4Mjg3NzE5fQ.qdSVIWO8yJ0ZR73MUGfyW1TQDOrhfcaOBEOTvEK_dUs'
+ );
+ expect(decoded.email).toEqual('govadmin@openelectionsportland.org');
+ expect(decoded.firstName).toEqual('Government');
+ expect(decoded.lastName).toEqual('Admin');
+ expect(decoded.permissions.length).toEqual(1);
+ expect(decoded.permissions[0].role).toEqual('government_admin');
+ expect(decoded.permissions[0].type).toEqual('government');
+ });
+
+ it('login govadmin success', async () => {
+ const response = await api.login(
+ 'govadmin@openelectionsportland.org',
+ 'password'
+ );
+ govAdminToken = response.headers
+ .get('set-cookie')
+ .match(/=([a-zA-Z0-9].+); Path/)[1];
+ expect(govAdminToken).toBeDefined();
+ });
+
+ it('login campaignadmin success', async () => {
+ const response = await api.login(
+ 'campaignadmin@openelectionsportland.org',
+ 'password'
+ );
+ campaignAdminToken = response.headers
+ .get('set-cookie')
+ .match(/=([a-zA-Z0-9].+); Path/)[1];
+ expect(campaignAdminToken).toBeDefined();
+ });
+
+ it('login campaignstaff success1', async () => {
+ const response = await api.login(
+ 'campaignstaff@openelectionsportland.org',
+ 'password'
+ );
+ campaignStaffToken = response.headers
+ .get('set-cookie')
+ .match(/=([a-zA-Z0-9].+); Path/)[1];
+ expect(campaignStaffToken).toBeDefined();
+ });
+
+ it('login fail', async () => {
+ const response = await api.login(
+ 'govadmin@openelectionsportland.org',
+ 'password1'
+ );
+ expect(response.status).toEqual(401);
+ });
+
+ it('me', async () => {
+ process.env.TOKEN = govAdminToken;
+ const response = await api.me();
+ expect(response.email).toEqual('govadmin@openelectionsportland.org');
+ expect(response.firstName).toEqual('Government');
+ expect(response.lastName).toEqual('Admin');
+ expect(response.permissions.length).toEqual(1);
+ expect(response.permissions[0].role).toEqual('government_admin');
+ expect(response.permissions[0].type).toEqual('government');
+ governmentId = response.permissions[0].id;
+ process.env.TOKEN = null;
+ });
+
+ it('inviteUsertoGovernment', async () => {
+ process.env.TOKEN = govAdminToken;
+ const response = await api.inviteUsertoGovernment(
+ 'govadmin1@openelectionsportland.org',
+ 'Government2',
+ 'Admin2',
+ governmentId
+ );
+ expect(response.status).toEqual(201);
+ process.env.TOKEN = null;
+ });
+
+ it('inviteUsertoCampaign as govAdmin', async () => {
+ process.env.TOKEN = govAdminToken;
+ const response = await api.inviteUsertoCampaign(
+ 'campaignadmin1@openelectionsportland.org',
+ 'Government2',
+ 'Admin2',
+ campaignId,
+ api.UserRoleEnum.CAMPAIGN_STAFF
+ );
+ expect(response.status).toEqual(201);
+ process.env.TOKEN = null;
+ });
+
+ it('inviteUsertoCampaign as campaignAdmin', async () => {
+ process.env.TOKEN = campaignAdminToken;
+ const response = await api.inviteUsertoCampaign(
+ 'campaignadmin2@openelectionsportland.org',
+ 'Government2',
+ 'Admin2',
+ campaignId,
+ api.UserRoleEnum.CAMPAIGN_ADMIN
+ );
+ expect(response.status).toEqual(201);
+ process.env.TOKEN = null;
+ });
+
+ it('redeemInvite', async () => {
+ const response = await api.redeemInvite('inviteme', 'password');
+ expect(response.status).toEqual(204);
+ });
+
+ it('getCampaignUsers', async () => {
+ process.env.TOKEN = campaignAdminToken;
+ const response = await api.getCampaignUsers(campaignId);
+ expect(response.length > 1).toBeTruthy();
+ process.env.TOKEN = null;
+ });
+
+ it('getGovernmentUsers', async () => {
+ process.env.TOKEN = govAdminToken;
+ const response = await api.getGovernmentUsers(governmentId);
+ expect(response.length > 1).toBeTruthy();
+ });
+
+ it('sendPasswordResetEmail', async () => {
+ const response = await api.sendPasswordResetEmail(
+ 'campaignstaff@openelectionsportland.org'
+ );
+ expect(response.status).toEqual(204);
+ });
+
+ it('resetPassword', async () => {
+ const response = await api.resetPassword('resetme', 'newpassword');
+
+ expect(response.status).toEqual(204);
+ });
+
+ it('updatePassword', async () => {
+ process.env.TOKEN = govAdminToken;
+ const response = await api.updatePassword('password', 'newpassword');
+ expect(response.status).toEqual(204);
+ });
+
+ it('createCampaignForGovernment', async () => {
+ process.env.TOKEN = govAdminToken;
+ const response = await api.createCampaignForGovernment({
+ governmentId,
+ name: 'Test for Mayor',
+ officeSought: 'Mayor',
+ });
+ expect(response.status).toEqual(201);
+ });
+
+ it('getCampaignsForGovernment', async () => {
+ process.env.TOKEN = govAdminToken;
+ const response = await api.getCampaignsForGovernment(governmentId);
+ expect(response.length > 1).toBeTruthy();
+ });
+
+ it('getGovernmentActivities', async () => {
+ process.env.TOKEN = govAdminToken;
+ const response = await api.getGovernmentActivities({ governmentId });
+ expect(response.data.length > 1).toBeTruthy();
+ });
+
+ it('getCampaignActivities', async () => {
+ process.env.TOKEN = campaignAdminToken;
+ const response = await api.getCampaignActivities({ campaignId });
+ expect(response.data.length > 1).toBeTruthy();
+ });
+
+ it('createContribution', async () => {
+ process.env.TOKEN = campaignStaffToken;
+ const response = await api.createContribution({
+ address1: '123 ABC ST',
+ amount: 250,
+ campaignId,
+ city: 'Portland',
+ currentUserId: campaignStaffId,
+ date: 1562436237619,
+ firstName: 'John',
+ middleInitial: '',
+ lastName: 'Doe',
+ governmentId,
+ type: api.ContributionTypeEnum.CONTRIBUTION,
+ subType: api.ContributionSubTypeEnum.CASH,
+ paymentMethod: api.PaymentMethodEnum.CASH,
+ state: 'OR',
+ status: api.ContributionStatusEnum.DRAFT,
+ zip: '97214',
+ contributorType: api.ContributorTypeEnum.INDIVIDUAL,
+ });
+ expect(response.status).toEqual(201);
+ });
+
+ it('getContributionActivities', async () => {
+ process.env.TOKEN = campaignAdminToken;
+ let contribution = await api.createContribution({
+ address1: '123 ABC ST',
+ amount: 250,
+ campaignId,
+ city: 'Portland',
+ currentUserId: campaignStaffId,
+ date: 1562436237700,
+ firstName: 'John',
+ middleInitial: '',
+ lastName: 'Doe',
+ governmentId,
+ type: api.ContributionTypeEnum.CONTRIBUTION,
+ subType: api.ContributionSubTypeEnum.CASH,
+ paymentMethod: api.PaymentMethodEnum.CASH,
+ state: 'OR',
+ status: api.ContributionStatusEnum.DRAFT,
+ zip: '97214',
+ contributorType: api.ContributorTypeEnum.INDIVIDUAL,
+ });
+ contribution = await contribution.json();
+
+ const response = await api.getContributionActivities({
+ contributionId: contribution.id,
+ });
+ expect(response.data.length >= 1).toBeTruthy();
+ });
+
+ it('updateContribution', async () => {
+ process.env.TOKEN = campaignStaffToken;
+
+ let response = await api.createContribution({
+ address1: '123 ABC ST',
+ amount: 250,
+ campaignId,
+ city: 'Portland',
+ currentUserId: campaignAdminId,
+ date: 1562436237619,
+ firstName: 'John',
+ middleInitial: '',
+ lastName: 'Doe',
+ governmentId,
+ type: api.ContributionTypeEnum.CONTRIBUTION,
+ subType: api.ContributionSubTypeEnum.CASH,
+ paymentMethod: api.PaymentMethodEnum.CASH,
+ state: 'OR',
+ status: api.ContributionStatusEnum.DRAFT,
+ zip: '97214',
+ contributorType: api.ContributorTypeEnum.INDIVIDUAL,
+ });
+ const contribution = await response.json();
+
+ response = await api.updateContribution({
+ id: contribution.id,
+ firstName: 'Ian',
+ currentUserId: campaignStaffId,
+ });
+ expect(response.status).toEqual(204);
+ });
+
+ it('getContributions', async () => {
+ process.env.TOKEN = campaignStaffToken;
+ const response = await api.getContributions({
+ governmentId,
+ campaignId,
+ currentUserId: campaignAdminId,
+ });
+ expect(response.status).toEqual(200);
+ });
+
+ it('getContributionById', async () => {
+ process.env.TOKEN = campaignStaffToken;
+ const contribution = await api.createContribution({
+ address1: '123 ABC ST',
+ amount: 250,
+ campaignId,
+ city: 'Portland',
+ currentUserId: campaignStaffId,
+ date: 1562436237619,
+ firstName: 'John',
+ middleInitial: '',
+ lastName: 'Doe',
+ governmentId,
+ type: api.ContributionTypeEnum.CONTRIBUTION,
+ subType: api.ContributionSubTypeEnum.CASH,
+ paymentMethod: api.PaymentMethodEnum.CASH,
+ state: 'OR',
+ status: api.ContributionStatusEnum.DRAFT,
+ zip: '97214',
+ contributorType: api.ContributorTypeEnum.INDIVIDUAL,
+ });
+ const { id } = await contribution.json();
+ const response = await api.getContributionById(id);
+ expect(response.status).toEqual(200);
+ });
+
+ it('removePermission', async () => {
+ process.env.TOKEN = campaignAdminToken;
+ const tokenResponse = await api.login(
+ 'campaignstaff+removeme@openelectionsportland.org',
+ 'password'
+ );
+
+ const token = tokenResponse.headers
+ .get('set-cookie')
+ .match(/=([a-zA-Z0-9].+); Path/)[1];
+
+ const user = api.decodeToken(token);
+
+ const permissionId = user.permissions[0].id;
+ const response = await api.removePermission(permissionId);
+ expect(response.status).toEqual(200);
+ });
+
+ it('archiveContribution', async () => {
+ process.env.TOKEN = campaignStaffToken;
+ let contribution = await api.createContribution({
+ address1: '123 ABC ST',
+ amount: 250,
+ campaignId,
+ city: 'Portland',
+ currentUserId: campaignStaffId,
+ date: 1562436237700,
+ firstName: 'John',
+ middleInitial: '',
+ lastName: 'Doe',
+ governmentId,
+ type: api.ContributionTypeEnum.CONTRIBUTION,
+ subType: api.ContributionSubTypeEnum.CASH,
+ paymentMethod: api.PaymentMethodEnum.CASH,
+ state: 'OR',
+ status: api.ContributionStatusEnum.DRAFT,
+ zip: '97214',
+ contributorType: api.ContributorTypeEnum.INDIVIDUAL,
+ });
+ contribution = await contribution.json();
+
+ let response = await api.archiveContribution(contribution.id);
+ expect(response.status).toEqual(200);
+ response = await api.getContributionById(contribution.id);
+ contribution = await response.json();
+ expect(contribution.status).toEqual(api.ContributionStatusEnum.ARCHIVED);
+ });
+
+ it('createExpenditure', async () => {
+ process.env.TOKEN = campaignStaffToken;
+ const response = await api.createExpenditure({
+ address1: '123 ABC ST',
+ amount: 250,
+ campaignId,
+ city: 'Portland',
+ currentUserId: campaignStaffId,
+ date: 1562436237700,
+ governmentId,
+ type: api.ExpenditureTypeEnum.EXPENDITURE,
+ subType: api.ExpenditureSubTypeEnum.CASH_EXPENDITURE,
+ state: 'OR',
+ status: api.ExpenditureStatusEnum.DRAFT,
+ zip: '97214',
+ payeeType: api.PayeeTypeEnum.INDIVIDUAL,
+ name: 'Test Expenditure',
+ description: 'This is a test',
+ });
+ expect(response.status).toEqual(201);
+ });
+
+ it('getExpenditures', async () => {
+ process.env.TOKEN = campaignStaffToken;
+ const response = await api.getExpenditures({
+ governmentId,
+ campaignId,
+ currentUserId: campaignStaffId,
+ });
+ expect(response.status).toEqual(200);
+ });
+
+ it('updateExpenditure', async () => {
+ process.env.TOKEN = campaignStaffToken;
+
+ let response = await api.createExpenditure({
+ address1: '123 ABC ST',
+ amount: 250,
+ campaignId,
+ city: 'Portland',
+ currentUserId: campaignStaffId,
+ date: 1562436237700,
+ governmentId,
+ type: api.ExpenditureTypeEnum.EXPENDITURE,
+ subType: api.ExpenditureSubTypeEnum.CASH_EXPENDITURE,
+ state: 'OR',
+ status: api.ExpenditureStatusEnum.DRAFT,
+ zip: '97214',
+ payeeType: api.PayeeTypeEnum.INDIVIDUAL,
+ name: 'Test Expenditure',
+ description: 'This is an update test',
+ });
+ const expenditure = await response.json();
+
+ response = await api.updateExpenditure({
+ id: expenditure.id,
+ amount: 500,
+ currentUserId: campaignStaffId,
+ });
+ expect(response.status).toEqual(204);
+ });
+
+ it('getExpenditureActivities', async () => {
+ process.env.TOKEN = campaignStaffToken;
+
+ let response = await api.createExpenditure({
+ address1: '123 ABC ST',
+ amount: 250,
+ campaignId,
+ city: 'Portland',
+ currentUserId: campaignStaffId,
+ date: 1562436237700,
+ governmentId,
+ type: api.ExpenditureTypeEnum.EXPENDITURE,
+ subType: api.ExpenditureSubTypeEnum.CASH_EXPENDITURE,
+ state: 'OR',
+ status: api.ExpenditureStatusEnum.DRAFT,
+ zip: '97214',
+ payeeType: api.PayeeTypeEnum.INDIVIDUAL,
+ name: 'Test Expenditure',
+ description: 'This is an update test',
+ });
+ const expenditure = await response.json();
+
+ response = await api.getExpenditureActivities({
+ expenditureId: expenditure.id,
+ });
+ expect(response.data.length >= 1).toBeTruthy();
+ });
+
+ xit('postExpenditureComment', async () => {
+ process.env.TOKEN = campaignStaffToken;
+
+ let response = await api.createExpenditure({
+ address1: '123 ABC ST',
+ amount: 250,
+ campaignId,
+ city: 'Portland',
+ currentUserId: campaignStaffId,
+ date: 1562436237700,
+ governmentId,
+ type: api.ExpenditureTypeEnum.EXPENDITURE,
+ subType: api.ExpenditureSubTypeEnum.CASH_EXPENDITURE,
+ state: 'OR',
+ status: api.ExpenditureStatusEnum.DRAFT,
+ zip: '97214',
+ payeeType: api.PayeeTypeEnum.INDIVIDUAL,
+ name: 'Test Expenditure',
+ description: 'This is an update test',
+ });
+ const expenditure = await response.json();
+
+ response = await api.postExpenditureComment(
+ expenditure.id,
+ 'This is a comment'
+ );
+ expect(response.status).toEqual(204);
+ });
+
+ it('getExpenditure', async () => {
+ process.env.TOKEN = campaignStaffToken;
+
+ let response = await api.createExpenditure({
+ address1: '123 ABC ST',
+ amount: 250,
+ campaignId,
+ city: 'Portland',
+ currentUserId: campaignStaffId,
+ date: 1562436237700,
+ governmentId,
+ type: api.ExpenditureTypeEnum.EXPENDITURE,
+ subType: api.ExpenditureSubTypeEnum.CASH_EXPENDITURE,
+ state: 'OR',
+ status: api.ExpenditureStatusEnum.DRAFT,
+ zip: '97214',
+ payeeType: api.PayeeTypeEnum.INDIVIDUAL,
+ name: 'Test Expenditure',
+ description: 'This is an update test',
+ });
+ const expenditure = await response.json();
+
+ response = await api.getExpenditureById(expenditure.id);
+ expect(response.status).toEqual(200);
+ });
+
+ xit('postContributionComment', async () => {
+ process.env.TOKEN = campaignStaffToken;
+ let contribution = await api.createContribution({
+ address1: '123 ABC ST',
+ amount: 250,
+ campaignId,
+ city: 'Portland',
+ currentUserId: campaignStaffId,
+ date: 1562436237700,
+ firstName: 'John',
+ middleInitial: '',
+ lastName: 'Doe',
+ governmentId,
+ type: api.ContributionTypeEnum.CONTRIBUTION,
+ subType: api.ContributionSubTypeEnum.CASH,
+ paymentMethod: api.PaymentMethodEnum.CASH,
+ state: 'OR',
+ status: api.ContributionStatusEnum.DRAFT,
+ zip: '97214',
+ contributorType: api.ContributorTypeEnum.INDIVIDUAL,
+ });
+ contribution = await contribution.json();
+
+ const response = await api.postContributionComment(
+ contribution.id,
+ 'This is a comment'
+ );
+ expect(response.status).toEqual(204);
+ });
+});
diff --git a/app2/src/api/index.js b/app2/src/api/index.js
new file mode 100644
index 000000000..b1c13e734
--- /dev/null
+++ b/app2/src/api/index.js
@@ -0,0 +1 @@
+export * from './api';
diff --git a/app2/src/api/schema.js b/app2/src/api/schema.js
new file mode 100644
index 000000000..b919820ed
--- /dev/null
+++ b/app2/src/api/schema.js
@@ -0,0 +1,21 @@
+import { schema } from 'normalizr';
+
+export const user = new schema.Entity('users');
+
+export const government = new schema.Entity('governments');
+
+export const campaign = new schema.Entity('campaigns');
+
+export const permission = new schema.Entity('permissions', {
+ user,
+ government,
+ campaign,
+});
+
+export const activity = new schema.Entity('activities');
+
+export const contribution = new schema.Entity('contributions');
+
+export const expenditure = new schema.Entity('expenditures');
+
+export const match = new schema.Entity('matches');
diff --git a/app2/src/pages/_app.tsx b/app2/src/pages/_app.tsx
new file mode 100755
index 000000000..c4f722d60
--- /dev/null
+++ b/app2/src/pages/_app.tsx
@@ -0,0 +1,21 @@
+import { Provider, useStore } from 'react-redux'
+import type { AppProps } from 'next/app'
+import {useState, useEffect} from 'react'
+
+function MyApp({ Component, pageProps }: AppProps) {
+ const [isLoading, setLoading] = useState(true)
+ const store = useStore(pageProps.initialReduxState)
+
+ useEffect(() => {
+ loadAuth().then(() => {
+ setLoading(false)
+ });
+ }, [])
+ return (
+
+
+
+ )
+}
+
+export default MyApp
diff --git a/app2/src/pages/index.tsx b/app2/src/pages/index.tsx
new file mode 100755
index 000000000..86b5b3b5b
--- /dev/null
+++ b/app2/src/pages/index.tsx
@@ -0,0 +1,72 @@
+import type { NextPage } from 'next'
+import Head from 'next/head'
+import Image from 'next/image'
+import styles from '../styles/Home.module.css'
+
+const Home: NextPage = () => {
+ return (
+
+
+
Create Next App
+
+
+
+
+
+
+
+
+ Get started by editing{' '}
+ pages/index.tsx
+
+
+
+
+
+
+
+ )
+}
+
+export default Home
diff --git a/app2/src/pages/sign-in.tsx b/app2/src/pages/sign-in.tsx
new file mode 100644
index 000000000..3388de234
--- /dev/null
+++ b/app2/src/pages/sign-in.tsx
@@ -0,0 +1,7 @@
+export default function SignIn() {
+ return (
+
+
sign in
+
+ )
+}
\ No newline at end of file
diff --git a/app2/src/state/ducks/activities.js b/app2/src/state/ducks/activities.js
new file mode 100644
index 000000000..188c538f8
--- /dev/null
+++ b/app2/src/state/ducks/activities.js
@@ -0,0 +1,226 @@
+/* eslint-disable no-unused-vars */
+import { normalize } from 'normalizr';
+import { isEmpty } from 'lodash';
+import createReducer from '../utils/createReducer';
+import createActionTypes from '../utils/createActionTypes';
+import action from '../utils/action';
+import { RESET_STATE, resetState } from './common';
+
+export const STATE_KEY = 'activities';
+export const ADD_ACTIVITY_ENTITIES = 'ADD_ACTIVITY_ENTITIES';
+export const addActivityEntities = entities => {
+ return {
+ type: ADD_ACTIVITY_ENTITIES,
+ payload: entities,
+ };
+};
+
+// Action Types
+export const actionTypes = {
+ GET_CAMPAIGN_ACTIVITIES: createActionTypes(
+ STATE_KEY,
+ 'GET_CAMPAIGN_ACTIVITIES'
+ ),
+ GET_GOVERNMENT_ACTIVITIES: createActionTypes(
+ STATE_KEY,
+ 'GET_GOVERNMENT_ACTIVITIES'
+ ),
+ GET_CONTRIBUTION_ACTIVITIES: createActionTypes(
+ STATE_KEY,
+ 'GET_CONTRIBUTION_ACTIVITIES'
+ ),
+ GET_EXPENDITURE_ACTIVITIES: createActionTypes(
+ STATE_KEY,
+ 'GET_EXPENDITURE_ACTIVITIES'
+ ),
+};
+
+// Initial State
+export const initialState = {
+ list: null,
+ listOrder: [],
+ listOptions: {
+ page: 0,
+ perPage: 25,
+ total: 0,
+ },
+ isLoading: false,
+ error: null,
+};
+
+export const resetActvityState = resetState;
+// Reducer
+export default createReducer(initialState, {
+ [RESET_STATE]: () => {
+ return { ...initialState };
+ },
+ [ADD_ACTIVITY_ENTITIES]: (state, action) => {
+ return {
+ ...state,
+ list: { ...action.payload.entities.activities },
+ listOrder: action.payload.result,
+ listOptions: {
+ page: action.payload.page || initialState.listOptions.page,
+ perPage: action.payload.perPage || initialState.listOptions.perPage,
+ total: action.payload.total,
+ },
+ };
+ },
+ [actionTypes.GET_CAMPAIGN_ACTIVITIES.REQUEST]: state => {
+ return { ...state, isLoading: true };
+ },
+ [actionTypes.GET_CAMPAIGN_ACTIVITIES.SUCCESS]: state => {
+ return { ...state, isLoading: false };
+ },
+ [actionTypes.GET_CAMPAIGN_ACTIVITIES.FAILURE]: (state, action) => {
+ return { ...state, isLoading: false, error: action.error };
+ },
+ [actionTypes.GET_GOVERNMENT_ACTIVITIES.REQUEST]: state => {
+ return { ...state, isLoading: true };
+ },
+ [actionTypes.GET_GOVERNMENT_ACTIVITIES.SUCCESS]: state => {
+ return { ...state, isLoading: false };
+ },
+ [actionTypes.GET_GOVERNMENT_ACTIVITIES.FAILURE]: (state, action) => {
+ return { ...state, isLoading: false, error: action.error };
+ },
+ [actionTypes.GET_CONTRIBUTION_ACTIVITIES.REQUEST]: state => {
+ return { ...state, isLoading: true };
+ },
+ [actionTypes.GET_CONTRIBUTION_ACTIVITIES.SUCCESS]: state => {
+ return { ...state, isLoading: false };
+ },
+ [actionTypes.GET_CONTRIBUTION_ACTIVITIES.FAILURE]: (state, action) => {
+ return { ...state, isLoading: false, error: action.error };
+ },
+ [actionTypes.GET_EXPENDITURE_ACTIVITIES.REQUEST]: state => {
+ return { ...state, isLoading: true };
+ },
+ [actionTypes.GET_EXPENDITURE_ACTIVITIES.SUCCESS]: state => {
+ return { ...state, isLoading: false };
+ },
+ [actionTypes.GET_EXPENDITURE_ACTIVITIES.FAILURE]: (state, action) => {
+ return { ...state, isLoading: false, error: action.error };
+ },
+});
+
+// Action Creators
+export const actionCreators = {
+ getCampaignActivities: {
+ request: () => action(actionTypes.GET_CAMPAIGN_ACTIVITIES.REQUEST),
+ success: () => action(actionTypes.GET_CAMPAIGN_ACTIVITIES.SUCCESS),
+ failure: error =>
+ action(actionTypes.GET_CAMPAIGN_ACTIVITIES.FAILURE, { error }),
+ },
+ getGovernmentActivities: {
+ request: () => action(actionTypes.GET_GOVERNMENT_ACTIVITIES.REQUEST),
+ success: () => action(actionTypes.GET_GOVERNMENT_ACTIVITIES.SUCCESS),
+ failure: error =>
+ action(actionTypes.GET_GOVERNMENT_ACTIVITIES.FAILURE, { error }),
+ },
+ getContributionActivities: {
+ request: () => action(actionTypes.GET_CONTRIBUTION_ACTIVITIES.REQUEST),
+ success: () => action(actionTypes.GET_CONTRIBUTION_ACTIVITIES.SUCCESS),
+ failure: error =>
+ action(actionTypes.GET_CONTRIBUTION_ACTIVITIES.FAILURE, { error }),
+ },
+ getExpenditureActivities: {
+ request: () => action(actionTypes.GET_EXPENDITURE_ACTIVITIES.REQUEST),
+ success: () => action(actionTypes.GET_EXPENDITURE_ACTIVITIES.SUCCESS),
+ failure: error =>
+ action(actionTypes.GET_EXPENDITURE_ACTIVITIES.FAILURE, { error }),
+ },
+};
+
+// Side Effects, e.g. thunks
+export function getCampaignActivities(campaignId) {
+ return async (dispatch, getState, { api, schema }) => {
+ dispatch(actionCreators.getCampaignActivities.request());
+ try {
+ const response = await api.getCampaignActivities(campaignId);
+ const data = normalize(response.data, [schema.activity]);
+ const { page, perPage, total } = response;
+ dispatch(addActivityEntities({ ...data, page, perPage, total }));
+ dispatch(actionCreators.getCampaignActivities.success());
+ } catch (error) {
+ dispatch(actionCreators.getCampaignActivities.failure(error));
+ }
+ };
+}
+
+export function getGovernmentActivities(governmentId) {
+ return async (dispatch, getState, { api, schema }) => {
+ dispatch(actionCreators.getGovernmentActivities.request());
+ try {
+ const response = await api.getGovernmentActivities(governmentId);
+ const data = normalize(response.data, [schema.activity]);
+ const { page, perPage, total } = response;
+ dispatch(addActivityEntities({ ...data, page, perPage, total }));
+ dispatch(actionCreators.getGovernmentActivities.success());
+ } catch (error) {
+ dispatch(actionCreators.getGovernmentActivities.failure(error));
+ }
+ };
+}
+
+export function getContributionActivities(contributionAttrs) {
+ return async (dispatch, getState, { api, schema }) => {
+ dispatch(actionCreators.getContributionActivities.request());
+ try {
+ const response = await api.getContributionActivities(contributionAttrs);
+ const data = normalize(response.data, [schema.activity]);
+ const { page, perPage, total } = response;
+ dispatch(addActivityEntities({ ...data, page, perPage, total }));
+ dispatch(actionCreators.getContributionActivities.success());
+ } catch (error) {
+ dispatch(actionCreators.getContributionActivities.failure(error));
+ }
+ };
+}
+
+export function getExpenditureActivities(activitiesAttrs) {
+ return async (dispatch, getState, { api, schema }) => {
+ dispatch(actionCreators.getExpenditureActivities.request());
+ try {
+ const response = await api.getExpenditureActivities(activitiesAttrs);
+ const data = normalize(response.data, [schema.activity]);
+ const { page, perPage, total } = response;
+ dispatch(addActivityEntities({ ...data, page, perPage, total }));
+ dispatch(actionCreators.getExpenditureActivities.success());
+ } catch (error) {
+ dispatch(actionCreators.getExpenditureActivities.failure(error));
+ }
+ };
+}
+
+export function getActivitiesByIdType(activitiesAttrs) {
+ const {
+ expenditureId,
+ contributionId,
+ governmentId,
+ campaignId,
+ } = activitiesAttrs;
+ return async (dispatch, getState, { api, schema }) => {
+ if (expenditureId) dispatch(getExpenditureActivities(activitiesAttrs));
+ if (contributionId) dispatch(getContributionActivities(activitiesAttrs));
+ if (governmentId) dispatch(getGovernmentActivities(activitiesAttrs));
+ if (campaignId) dispatch(getCampaignActivities(activitiesAttrs));
+ };
+}
+
+export const getActivities = state => {
+ if (isEmpty(state.activities.list) || isEmpty(state.activities.listOrder)) {
+ return [];
+ }
+ return state.activities.listOrder.map(id => state.activities.list[id]);
+};
+
+export const getActivtiesCount = state => {
+ return isEmpty(state.activities.list)
+ ? 0
+ : Object.keys(state.activities.list).length;
+};
+
+export const getTotalCount = state => {
+ return state.activities.listOptions.total;
+};
diff --git a/app2/src/state/ducks/activities.test.js b/app2/src/state/ducks/activities.test.js
new file mode 100644
index 000000000..2fef4a1d5
--- /dev/null
+++ b/app2/src/state/ducks/activities.test.js
@@ -0,0 +1,204 @@
+/* eslint-disable no-unused-vars */
+import configureMockStore from 'redux-mock-store';
+import thunk from 'redux-thunk';
+import * as activities from './activities';
+import * as api from '../../api';
+import * as schema from '../../api/schema';
+
+const { actionTypes, actionCreators } = activities;
+
+const middlewares = [thunk.withExtraArgument({ api, schema })];
+const mockStore = configureMockStore(middlewares);
+
+const govAdmin = {
+ email: 'govadmin@openelectionsportland.org',
+ password: 'password',
+};
+
+const invite = {
+ code: 'inviteme',
+ email: 'campaignStaff+1@openelectionsportland.org',
+ password: 'password',
+};
+
+const reset = {
+ code: 'resetme',
+ password: 'newpassword',
+};
+
+describe('Reducer', () => {
+ const reducer = activities.default;
+ it('initial state', () => {
+ expect(reducer(undefined, {})).toEqual({
+ list: null,
+ listOrder: [],
+ isLoading: false,
+ error: null,
+ listOptions: {
+ page: 0,
+ perPage: 25,
+ total: 0,
+ },
+ });
+ });
+
+ it('adds activity entities', () => {
+ expect(
+ reducer(undefined, {
+ type: activities.ADD_ACTIVITY_ENTITIES,
+ payload: {
+ result: [],
+ page: 0,
+ perPage: 25,
+ total: 1,
+ entities: {
+ activities: {
+ '1': {},
+ },
+ },
+ },
+ })
+ ).toEqual({
+ list: {
+ '1': {},
+ },
+ listOptions: {
+ page: 0,
+ perPage: 25,
+ total: 1,
+ },
+ listOrder: [],
+ isLoading: false,
+ error: null,
+ });
+ });
+});
+
+describe('Action Creators', () => {
+ it('get campaign activities request', () => {
+ const expectedAction = {
+ type: actionTypes.GET_CAMPAIGN_ACTIVITIES.REQUEST,
+ };
+ expect(actionCreators.getCampaignActivities.request()).toEqual(
+ expectedAction
+ );
+ });
+ it('get campaign activities success', () => {
+ const expectedAction = {
+ type: actionTypes.GET_CAMPAIGN_ACTIVITIES.SUCCESS,
+ };
+ expect(actionCreators.getCampaignActivities.success()).toEqual(
+ expectedAction
+ );
+ });
+ it('get campaign activities failure', () => {
+ const expectedAction = {
+ type: actionTypes.GET_CAMPAIGN_ACTIVITIES.FAILURE,
+ };
+ expect(actionCreators.getCampaignActivities.failure()).toEqual(
+ expectedAction
+ );
+ });
+});
+
+let govAdminToken;
+let campaignAdminToken;
+let campaignStaffToken;
+let governmentId;
+let campaignId;
+describe('Side Effects', () => {
+ beforeAll(async () => {
+ let tokenResponse = await api.login(
+ 'govadmin@openelectionsportland.org',
+ 'password'
+ );
+ govAdminToken = tokenResponse.headers
+ .get('set-cookie')
+ .match(/=([a-zA-Z0-9].+); Path/)[1];
+ let decodedToken = api.decodeToken(govAdminToken);
+ governmentId = decodedToken.permissions[0].governmentId;
+
+ tokenResponse = await api.login(
+ 'campaignadmin@openelectionsportland.org',
+ 'password'
+ );
+ campaignAdminToken = tokenResponse.headers
+ .get('set-cookie')
+ .match(/=([a-zA-Z0-9].+); Path/)[1];
+ decodedToken = api.decodeToken(campaignAdminToken);
+ campaignId = decodedToken.permissions[0].campaignId;
+
+ tokenResponse = await api.login(
+ 'campaignstaff@openelectionsportland.org',
+ 'password'
+ );
+ campaignStaffToken = tokenResponse.headers
+ .get('set-cookie')
+ .match(/=([a-zA-Z0-9].+); Path/)[1];
+ });
+
+ beforeEach(() => {
+ delete process.env.TOKEN;
+ });
+
+ it('gets campaign activities', async () => {
+ const expectedActions = [
+ { type: actionTypes.GET_CAMPAIGN_ACTIVITIES.REQUEST },
+ { type: activities.ADD_ACTIVITY_ENTITIES },
+ { type: actionTypes.GET_CAMPAIGN_ACTIVITIES.SUCCESS },
+ ];
+ const store = mockStore({});
+
+ process.env.TOKEN = campaignAdminToken;
+ return store
+ .dispatch(
+ activities.getCampaignActivities({ campaignId, page: 0, perPage: 25 })
+ )
+ .then(() => {
+ const actions = store.getActions();
+ expect(actions[0].type).toEqual(expectedActions[0].type);
+ expect(actions[1].type).toEqual(expectedActions[1].type);
+ expect(actions[2].type).toEqual(expectedActions[2].type);
+ });
+ });
+
+ it('gets CONTRIBUTION activities', async () => {
+ const expectedActions = [
+ { type: actionTypes.GET_CONTRIBUTION_ACTIVITIES.REQUEST },
+ { type: activities.ADD_ACTIVITY_ENTITIES },
+ { type: actionTypes.GET_CONTRIBUTION_ACTIVITIES.SUCCESS },
+ ];
+ const store = mockStore({});
+
+ process.env.TOKEN = campaignAdminToken;
+
+ return store
+ .dispatch(activities.getContributionActivities({ contributionId: 1 }))
+ .then(() => {
+ const actions = store.getActions();
+ expect(actions[0].type).toEqual(expectedActions[0].type);
+ expect(actions[1].type).toEqual(expectedActions[1].type);
+ expect(actions[2].type).toEqual(expectedActions[2].type);
+ });
+ });
+
+ it('gets EXPENDITURE activities', async () => {
+ const expectedActions = [
+ { type: actionTypes.GET_EXPENDITURE_ACTIVITIES.REQUEST },
+ { type: activities.ADD_ACTIVITY_ENTITIES },
+ { type: actionTypes.GET_EXPENDITURE_ACTIVITIES.SUCCESS },
+ ];
+ const store = mockStore({});
+
+ process.env.TOKEN = campaignAdminToken;
+
+ return store
+ .dispatch(activities.getExpenditureActivities({ expenditureid: 1 }))
+ .then(() => {
+ const actions = store.getActions();
+ expect(actions[0].type).toEqual(expectedActions[0].type);
+ expect(actions[1].type).toEqual(expectedActions[1].type);
+ expect(actions[2].type).toEqual(expectedActions[2].type);
+ });
+ });
+});
diff --git a/app2/src/state/ducks/auth.js b/app2/src/state/ducks/auth.js
new file mode 100644
index 000000000..0cffe5693
--- /dev/null
+++ b/app2/src/state/ducks/auth.js
@@ -0,0 +1,458 @@
+/* eslint-disable no-unused-vars */
+import { push } from 'connected-react-router';
+import { flashMessage } from 'redux-flash';
+import createReducer from '../utils/createReducer';
+import createActionTypes, {
+ createCustomActionTypes,
+} from '../utils/createActionTypes';
+import action from '../utils/action';
+import * as governments from './governments';
+import { getStatusSummaryAction } from './summary';
+import { resetContributionState } from './contributions';
+import { resetExpenditureState } from './expenditures';
+import { resetUserState } from './users';
+import { resetPermissionState } from './permissions';
+import { resetActvityState } from './activities';
+import {
+ resetCampaignState,
+ actionCreators as campaignsActionCreators,
+} from './campaigns';
+
+// Export State Key
+export const STATE_KEY = 'auth';
+
+// Action Types
+export const actionTypes = {
+ ME: createActionTypes(STATE_KEY, 'ME'),
+ LOGIN: createActionTypes(STATE_KEY, 'LOGIN'),
+ REDEEM_INVITE: createActionTypes(STATE_KEY, 'REDEEM_INVITE'),
+ RESET_PASSWORD: createActionTypes(STATE_KEY, 'RESET_PASSWORD'),
+ SEND_PASSWORD_RESET_EMAIL: createActionTypes(
+ STATE_KEY,
+ 'SEND_PASSWORD_RESET_EMAIL'
+ ),
+ UPDATE_PASSWORD: createActionTypes(STATE_KEY, 'UPDATE_PASSWORD'),
+ SET_ASSUME: createCustomActionTypes(STATE_KEY, 'SET_ASSUME', ['UPDATE']),
+};
+
+// Initial State
+export const initialState = {
+ me: null,
+ assume: false,
+ isLoading: false,
+ error: null,
+};
+
+// Reducer
+export default createReducer(initialState, {
+ [actionTypes.ME.REQUEST]: (state, action) => {
+ return { ...state, isLoading: true };
+ },
+ [actionTypes.ME.SUCCESS]: (state, action) => {
+ return { ...state, isLoading: false, me: action.me };
+ },
+ [actionTypes.ME.FAILURE]: (state, action) => {
+ return { ...state, isLoading: false, error: action.error };
+ },
+ [actionTypes.LOGIN.REQUEST]: (state, action) => {
+ return { ...state, isLoading: true, error: null };
+ },
+ [actionTypes.LOGIN.SUCCESS]: (state, action) => {
+ return { ...state, isLoading: false, error: null, me: action.me };
+ },
+ [actionTypes.LOGIN.FAILURE]: (state, action) => {
+ return { ...state, isLoading: false, error: action.error };
+ },
+ [actionTypes.REDEEM_INVITE.REQUEST]: (state, action) => {
+ return { ...state, isLoading: true };
+ },
+ [actionTypes.REDEEM_INVITE.SUCCESS]: (state, action) => {
+ return { ...state, isLoading: false };
+ },
+ [actionTypes.REDEEM_INVITE.FAILURE]: (state, action) => {
+ return { ...state, isLoading: false, error: action.error };
+ },
+ [actionTypes.RESET_PASSWORD.REQUEST]: (state, action) => {
+ return { ...state, isLoading: true };
+ },
+ [actionTypes.RESET_PASSWORD.SUCCESS]: (state, action) => {
+ return { ...state, isLoading: false };
+ },
+ [actionTypes.RESET_PASSWORD.FAILURE]: (state, action) => {
+ return { ...state, isLoading: false, error: action.error };
+ },
+ [actionTypes.SEND_PASSWORD_RESET_EMAIL.REQUEST]: (state, action) => {
+ return { ...state, isLoading: true };
+ },
+ [actionTypes.SEND_PASSWORD_RESET_EMAIL.SUCCESS]: (state, action) => {
+ return { ...state, isLoading: false };
+ },
+ [actionTypes.SEND_PASSWORD_RESET_EMAIL.FAILURE]: (state, action) => {
+ return { ...state, isLoading: false, error: action.error };
+ },
+ [actionTypes.UPDATE_PASSWORD.REQUEST]: (state, action) => {
+ return { ...state, isLoading: true };
+ },
+ [actionTypes.UPDATE_PASSWORD.SUCCESS]: (state, action) => {
+ return { ...state, isLoading: false, error: null };
+ },
+ [actionTypes.UPDATE_PASSWORD.FAILURE]: (state, action) => {
+ return { ...state, isLoading: false, error: action.error };
+ },
+ [actionTypes.SET_ASSUME.UPDATE]: (state, action) => {
+ return { ...state, assume: action.assume };
+ },
+});
+
+// Action Creators
+export const actionCreators = {
+ me: {
+ request: () => action(actionTypes.ME.REQUEST),
+ success: me => action(actionTypes.ME.SUCCESS, { me }),
+ failure: error => action(actionTypes.ME.FAILURE, { error }),
+ },
+ login: {
+ request: () => action(actionTypes.LOGIN.REQUEST),
+ success: me => action(actionTypes.LOGIN.SUCCESS, { me }),
+ failure: error => action(actionTypes.LOGIN.FAILURE, { error }),
+ },
+ redeemInvite: {
+ request: () => action(actionTypes.REDEEM_INVITE.REQUEST),
+ success: () => action(actionTypes.REDEEM_INVITE.SUCCESS),
+ failure: error => action(actionTypes.REDEEM_INVITE.FAILURE, { error }),
+ },
+ resetPassword: {
+ request: () => action(actionTypes.RESET_PASSWORD.REQUEST),
+ success: () => action(actionTypes.RESET_PASSWORD.SUCCESS),
+ failure: error => action(actionTypes.RESET_PASSWORD.FAILURE, { error }),
+ },
+ sendPasswordResetEmail: {
+ request: () => action(actionTypes.SEND_PASSWORD_RESET_EMAIL.REQUEST),
+ success: () => action(actionTypes.SEND_PASSWORD_RESET_EMAIL.SUCCESS),
+ failure: error =>
+ action(actionTypes.SEND_PASSWORD_RESET_EMAIL.FAILURE, { error }),
+ },
+ updatePassword: {
+ request: () => action(actionTypes.UPDATE_PASSWORD.REQUEST),
+ success: () => action(actionTypes.UPDATE_PASSWORD.SUCCESS),
+ failure: error => action(actionTypes.UPDATE_PASSWORD.FAILURE, { error }),
+ },
+ setAssume: assume => action(actionTypes.SET_ASSUME.UPDATE, { assume }),
+};
+
+export const getMeRole = (state, role = 'campaign_admin') => {
+ if (state.auth.me && state.auth.me.permissions) {
+ return !!state.auth.me.permissions.find(permission => {
+ return permission.role === role;
+ });
+ }
+ return false;
+};
+
+export function setAssume() {
+ return (dispatch, getState) => {
+ if (getMeRole(getState(), 'government_admin')) {
+ dispatch(actionCreators.setAssume(true));
+ }
+ };
+}
+export function unSetAssume() {
+ return dispatch => {
+ dispatch(actionCreators.setAssume(false));
+ };
+}
+
+// Side Effects, e.g. thunks
+export function redeemInvite(invitationCode, password, firstName, lastName) {
+ return async (dispatch, getState, { api }) => {
+ dispatch(actionCreators.redeemInvite.request());
+ try {
+ const { status } = await api.redeemInvite(
+ invitationCode,
+ password,
+ firstName,
+ lastName
+ );
+ if (status === 204) {
+ dispatch(actionCreators.redeemInvite.success());
+ dispatch(
+ flashMessage('Signup Success', { props: { variant: 'success' } })
+ );
+ dispatch(push('/sign-in'));
+ } else {
+ dispatch(actionCreators.redeemInvite.failure());
+ dispatch(flashMessage('Signup Error', { props: { variant: 'error' } }));
+ }
+ } catch (error) {
+ dispatch(actionCreators.redeemInvite.failure(error));
+ dispatch(
+ flashMessage(`Signup Error - ${error}`, { props: { variant: 'error' } })
+ );
+ }
+ };
+}
+
+export function resetPassword(invitationCode, password) {
+ return async (dispatch, getState, { api }) => {
+ dispatch(actionCreators.resetPassword.request());
+ try {
+ const { status } = await api.resetPassword(invitationCode, password);
+ if (status === 204) {
+ dispatch(actionCreators.resetPassword.success());
+ return true;
+ }
+ dispatch(actionCreators.resetPassword.failure());
+ return false;
+ } catch (error) {
+ dispatch(actionCreators.resetPassword.failure(error));
+ return false;
+ }
+ };
+}
+
+export function sendPasswordResetEmail(email) {
+ return async (dispatch, getState, { api }) => {
+ dispatch(actionCreators.sendPasswordResetEmail.request());
+ try {
+ const { status } = await api.sendPasswordResetEmail(email);
+ if (status === 204) {
+ dispatch(actionCreators.sendPasswordResetEmail.success());
+ return true;
+ }
+ dispatch(actionCreators.sendPasswordResetEmail.failure());
+ return false;
+ } catch (error) {
+ dispatch(actionCreators.sendPasswordResetEmail.failure(error));
+ return false;
+ }
+ };
+}
+
+export function logout() {
+ return dispatch => {
+ dispatch(actionCreators.me.success(null));
+ dispatch(unSetAssume());
+ dispatch(resetContributionState());
+ dispatch(resetExpenditureState());
+ dispatch(resetUserState());
+ dispatch(resetCampaignState());
+ dispatch(resetPermissionState());
+ dispatch(resetActvityState());
+ if (!window.location.hostname.includes('localhost')) {
+ document.cookie =
+ 'token=; domain=.openelectionsportland.org; expires=Thu, 01 Jan 1970 00:00:00 GMT';
+ } else {
+ document.cookie = 'token=; expires=Thu, 01 Jan 1970 00:00:00 GMT';
+ }
+
+ dispatch(push('/sign-in'));
+ };
+}
+
+export function me() {
+ return async (dispatch, getState, { api }) => {
+ if (
+ process.env.NODE_ENV !== 'development' &&
+ !document.cookie.includes('token') &&
+ !process.env.TOKEN
+ ) {
+ return;
+ }
+ dispatch(actionCreators.me.request());
+ try {
+ const me = await api.me();
+ if (me.message && me.message === 'Token expired or incorrect') {
+ dispatch(logout);
+ }
+ if (me && me.permissions) {
+ const campaignPermission = me.permissions.filter(permission => {
+ return (permission.type = 'campaign');
+ });
+ if (campaignPermission.length) {
+ dispatch(
+ campaignsActionCreators.setCampaign.success(
+ me.permissions[0].campaignId
+ )
+ );
+ if (me.permissions[0].campaignId) {
+ dispatch(
+ getStatusSummaryAction({
+ campaignId: me.permissions[0].campaignId,
+ })
+ );
+ }
+ }
+
+ const govPermission = me.permissions.filter(permission => {
+ return (permission.type = 'government');
+ });
+ if (govPermission.length) {
+ dispatch(
+ governments.actionCreators.setGovernment.success(
+ me.permissions[0].governmentId
+ )
+ );
+ if (me.permissions[0].governmentId) {
+ dispatch(
+ getStatusSummaryAction({
+ governmentId: me.permissions[0].governmentId,
+ })
+ );
+ }
+ }
+ }
+ dispatch(actionCreators.me.success(me));
+ } catch (error) {
+ dispatch(actionCreators.me.failure(error));
+ }
+ };
+}
+export function login(email, password) {
+ return async (dispatch, getState, { api }) => {
+ // dispatch(actionCreators.login.failure(true));
+ dispatch(actionCreators.login.request());
+ try {
+ await api.login(email, password).then(response => {
+ if (response.status === 204) {
+ dispatch(actionCreators.login.success());
+ dispatch(me());
+ dispatch(
+ flashMessage('Signin Success', { props: { variant: 'success' } })
+ );
+ dispatch(push('/dashboard'));
+ } else {
+ dispatch(actionCreators.login.failure(true));
+ dispatch(
+ flashMessage('Signin Error', { props: { variant: 'error' } })
+ );
+ }
+ });
+ } catch (error) {
+ dispatch(actionCreators.login.failure(error));
+ dispatch(
+ flashMessage(`Signin Error - ${error}`, { props: { variant: 'error' } })
+ );
+ }
+ };
+}
+
+export function updatePassword(password, newPassword) {
+ return async (dispatch, getState, { api }) => {
+ dispatch(actionCreators.updatePassword.request());
+ try {
+ const { status } = await api.updatePassword(password, newPassword);
+ if (status === 204) {
+ dispatch(actionCreators.updatePassword.success());
+ dispatch(
+ flashMessage('Password updated', { props: { variant: 'success' } })
+ );
+ dispatch(logout());
+ } else {
+ dispatch(
+ actionCreators.updatePassword.failure(
+ 'Update password request failed'
+ )
+ );
+ dispatch(
+ flashMessage('Password update failed', {
+ props: { variant: 'error' },
+ })
+ );
+ }
+ } catch (error) {
+ dispatch(actionCreators.updatePassword.failure(error));
+ dispatch(
+ flashMessage(`Password update failed - ${error}`, {
+ props: { variant: 'error' },
+ })
+ );
+ }
+ };
+}
+
+export function redirectToLogin() {
+ return async (dispatch, getState, { api }) => {
+ dispatch(push('/sign-in'));
+ };
+}
+
+// TODO Dispatch this function from thunks to redirect on stale auth cookies
+export function checkForUnauthorizedResponse(response) {
+ return dispatch => {
+ if (response.status === 401 || response.status === 422) {
+ dispatch(logout());
+ }
+ };
+}
+
+// Selectors
+export const rootState = state => state || {};
+
+export const isLoggedIn = state => {
+ return state.auth.me !== null;
+};
+
+export const isAdmin = state => {
+ return state.auth.me !== null
+ ? state.auth.me.permissions[0].role === 'government_admin' ||
+ state.auth.me.permissions[0].role === 'campaign_admin'
+ : false;
+};
+
+export const isGovAdminAuthenticated = state => {
+ return getMeRole(state, 'government_admin');
+};
+export const isAssumed = state => {
+ return !!state.auth.assume;
+};
+export const isGovAdmin = state => {
+ return state.auth.assume &&
+ (state.router.location.pathname.includes('/contributions/') ||
+ state.router.location.pathname.includes('/expenses/'))
+ ? false
+ : getMeRole(state, 'government_admin');
+};
+export const isCampAdmin = state => {
+ return state.auth.assume &&
+ (state.router.location.pathname.includes('/contributions/') ||
+ state.router.location.pathname.includes('/expenses/'))
+ ? true
+ : getMeRole(state, 'campaign_admin');
+};
+export const isCampStaff = state => {
+ return getMeRole(state, 'campaign_staff');
+};
+
+export const getGovOrCampIdAttributes = state => {
+ if (state.auth.me && state.auth.me.permissions) {
+ const { governmentId = 1, campaignId } = state.auth.me.permissions[0];
+ return { governmentId, campaignId };
+ }
+};
+
+export const getCurrentUserId = state => {
+ if (state.auth.me) {
+ return state.auth.me.id;
+ }
+ return null;
+};
+
+// Assumes only one campaign. Add setter and adjust default to [0] permission
+export const getCurrentCampaignId = state => {
+ if (state.auth.me && state.auth.me.permissions) {
+ if (state.auth.me.permissions[0] && state.auth.me.permissions[0].campaignId)
+ return state.auth.me.permissions[0].campaignId;
+ }
+ return null;
+};
+
+export const getCurrentCampaignName = state => {
+ if (state.auth.me && state.auth.me.permissions) {
+ if (
+ state.auth.me.permissions[0] &&
+ state.auth.me.permissions[0].campaignName
+ )
+ return state.auth.me.permissions[0].campaignName;
+ }
+ return 'Campaign';
+};
diff --git a/app2/src/state/ducks/auth.test.js b/app2/src/state/ducks/auth.test.js
new file mode 100644
index 000000000..bf97b564e
--- /dev/null
+++ b/app2/src/state/ducks/auth.test.js
@@ -0,0 +1,646 @@
+/* eslint-disable no-unused-vars */
+import configureMockStore from 'redux-mock-store';
+import thunk from 'redux-thunk';
+import * as auth from './auth';
+import * as campaigns from './campaigns';
+import * as summary from './summary';
+import * as governments from './governments';
+import * as api from '../../api';
+import * as schema from '../../api/schema';
+
+const { actionTypes, actionCreators } = auth;
+
+const middlewares = [thunk.withExtraArgument({ api, schema })];
+const mockStore = configureMockStore(middlewares);
+
+const govAdmin = {
+ email: 'govadmin@openelectionsportland.org',
+ password: 'password',
+};
+
+const invite = {
+ code: 'inviteme',
+ email: 'campaignStaff+1@openelectionsportland.org',
+ password: 'password',
+};
+
+const reset = {
+ code: 'resetme',
+ password: 'newpassword',
+};
+
+describe('Reducer', () => {
+ const reducer = auth.default;
+ it('initial state', () => {
+ expect(reducer(undefined, {})).toEqual({
+ assume: false,
+ me: null,
+ isLoading: false,
+ error: null,
+ });
+ });
+
+ it('login', () => {
+ expect(
+ reducer(undefined, {
+ type: actionTypes.LOGIN.REQUEST,
+ })
+ ).toEqual({
+ assume: false,
+ me: null,
+ isLoading: true,
+ error: null,
+ });
+
+ expect(
+ reducer(undefined, {
+ type: actionTypes.LOGIN.SUCCESS,
+ me: {},
+ })
+ ).toEqual({
+ assume: false,
+ me: {},
+ isLoading: false,
+ error: null,
+ });
+
+ expect(
+ reducer(undefined, {
+ type: actionTypes.LOGIN.FAILURE,
+ error: '',
+ })
+ ).toEqual({
+ assume: false,
+ me: null,
+ isLoading: false,
+ error: '',
+ });
+ });
+
+ // it("logout", () => {
+ // expect(
+ // reducer(undefined, {
+ // type: actionTypes.LOGIN.SUCCESS,
+ // me: null
+ // })
+ // ).toEqual({
+ // me: null,
+ // isLoading: false,
+ // error: null
+ // });
+ // });
+
+ it('me', () => {
+ expect(
+ reducer(undefined, {
+ type: actionTypes.ME.REQUEST,
+ })
+ ).toEqual({
+ assume: false,
+ me: null,
+ isLoading: true,
+ error: null,
+ });
+
+ expect(
+ reducer(undefined, {
+ type: actionTypes.ME.SUCCESS,
+ me: {},
+ })
+ ).toEqual({
+ assume: false,
+ me: {},
+ isLoading: false,
+ error: null,
+ });
+
+ expect(
+ reducer(undefined, {
+ type: actionTypes.ME.FAILURE,
+ error: '',
+ })
+ ).toEqual({
+ assume: false,
+ me: null,
+ isLoading: false,
+ error: '',
+ });
+ });
+
+ it('redeem invite', () => {
+ expect(
+ reducer(undefined, {
+ type: actionTypes.REDEEM_INVITE.REQUEST,
+ })
+ ).toEqual({
+ assume: false,
+ me: null,
+ isLoading: true,
+ error: null,
+ });
+
+ expect(
+ reducer(undefined, {
+ type: actionTypes.REDEEM_INVITE.SUCCESS,
+ })
+ ).toEqual({
+ assume: false,
+ me: null,
+ isLoading: false,
+ error: null,
+ });
+
+ expect(
+ reducer(undefined, {
+ type: actionTypes.REDEEM_INVITE.FAILURE,
+ error: '',
+ })
+ ).toEqual({
+ assume: false,
+ me: null,
+ isLoading: false,
+ error: '',
+ });
+ });
+
+ it('reset password', () => {
+ expect(
+ reducer(undefined, {
+ type: actionTypes.RESET_PASSWORD.REQUEST,
+ })
+ ).toEqual({
+ assume: false,
+ me: null,
+ isLoading: true,
+ error: null,
+ });
+
+ expect(
+ reducer(undefined, {
+ type: actionTypes.RESET_PASSWORD.SUCCESS,
+ })
+ ).toEqual({
+ assume: false,
+ me: null,
+ isLoading: false,
+ error: null,
+ });
+
+ expect(
+ reducer(undefined, {
+ type: actionTypes.RESET_PASSWORD.FAILURE,
+ error: '',
+ })
+ ).toEqual({
+ assume: false,
+ me: null,
+ isLoading: false,
+ error: '',
+ });
+ });
+
+ it('send password reset email', () => {
+ expect(
+ reducer(undefined, {
+ type: actionTypes.SEND_PASSWORD_RESET_EMAIL.REQUEST,
+ })
+ ).toEqual({
+ assume: false,
+ me: null,
+ isLoading: true,
+ error: null,
+ });
+
+ expect(
+ reducer(undefined, {
+ type: actionTypes.SEND_PASSWORD_RESET_EMAIL.SUCCESS,
+ })
+ ).toEqual({
+ assume: false,
+ me: null,
+ isLoading: false,
+ error: null,
+ });
+
+ expect(
+ reducer(undefined, {
+ type: actionTypes.SEND_PASSWORD_RESET_EMAIL.FAILURE,
+ error: '',
+ })
+ ).toEqual({
+ assume: false,
+ me: null,
+ isLoading: false,
+ error: '',
+ });
+ });
+
+ it('update password', () => {
+ expect(
+ reducer(undefined, {
+ type: actionTypes.UPDATE_PASSWORD.REQUEST,
+ })
+ ).toEqual({
+ assume: false,
+ me: null,
+ isLoading: true,
+ error: null,
+ });
+
+ expect(
+ reducer(undefined, {
+ type: actionTypes.UPDATE_PASSWORD.SUCCESS,
+ })
+ ).toEqual({
+ assume: false,
+ me: null,
+ isLoading: false,
+ error: null,
+ });
+
+ expect(
+ reducer(undefined, {
+ type: actionTypes.UPDATE_PASSWORD.FAILURE,
+ error: '',
+ })
+ ).toEqual({
+ assume: false,
+ me: null,
+ isLoading: false,
+ error: '',
+ });
+ });
+});
+
+describe('Action Creators', () => {
+ it('me request', () => {
+ const expectedAction = {
+ type: actionTypes.ME.REQUEST,
+ };
+ expect(actionCreators.me.request()).toEqual(expectedAction);
+ });
+
+ it('me success', () => {
+ const me = {};
+ const expectedAction = {
+ type: actionTypes.ME.SUCCESS,
+ me: {},
+ };
+ expect(actionCreators.me.success(me)).toEqual(expectedAction);
+ });
+
+ it('me failure', () => {
+ const error = '';
+ const expectedAction = {
+ type: actionTypes.ME.FAILURE,
+ error: '',
+ };
+ expect(actionCreators.me.failure(error)).toEqual(expectedAction);
+ });
+
+ it('login request', () => {
+ const expectedAction = {
+ type: actionTypes.LOGIN.REQUEST,
+ };
+ expect(actionCreators.login.request()).toEqual(expectedAction);
+ });
+
+ it('login success', () => {
+ const me = {};
+ const expectedAction = {
+ type: actionTypes.LOGIN.SUCCESS,
+ me: {},
+ };
+ expect(actionCreators.login.success(me)).toEqual(expectedAction);
+ });
+
+ it('login failure', () => {
+ const error = '';
+ const expectedAction = {
+ type: actionTypes.LOGIN.FAILURE,
+ error: '',
+ };
+ expect(actionCreators.login.failure(error)).toEqual(expectedAction);
+ });
+
+ it('redeem invite request', () => {
+ const expectedAction = {
+ type: actionTypes.REDEEM_INVITE.REQUEST,
+ };
+ expect(actionCreators.redeemInvite.request()).toEqual(expectedAction);
+ });
+
+ it('redeem invite success', () => {
+ const expectedAction = {
+ type: actionTypes.REDEEM_INVITE.SUCCESS,
+ };
+ expect(actionCreators.redeemInvite.success()).toEqual(expectedAction);
+ });
+
+ it('redeem invite failure', () => {
+ const error = '';
+ const expectedAction = {
+ type: actionTypes.REDEEM_INVITE.FAILURE,
+ error: '',
+ };
+ expect(actionCreators.redeemInvite.failure(error)).toEqual(expectedAction);
+ });
+
+ it('reset password request', () => {
+ const expectedAction = {
+ type: actionTypes.RESET_PASSWORD.REQUEST,
+ };
+ expect(actionCreators.resetPassword.request()).toEqual(expectedAction);
+ });
+
+ it('reset password success', () => {
+ const expectedAction = {
+ type: actionTypes.RESET_PASSWORD.SUCCESS,
+ };
+ expect(actionCreators.resetPassword.success()).toEqual(expectedAction);
+ });
+
+ it('reset password failure', () => {
+ const error = '';
+ const expectedAction = {
+ type: actionTypes.RESET_PASSWORD.FAILURE,
+ error: '',
+ };
+ expect(actionCreators.resetPassword.failure(error)).toEqual(expectedAction);
+ });
+
+ it('send password reset email request', () => {
+ const expectedAction = {
+ type: actionTypes.SEND_PASSWORD_RESET_EMAIL.REQUEST,
+ };
+ expect(actionCreators.sendPasswordResetEmail.request()).toEqual(
+ expectedAction
+ );
+ });
+
+ it('send password reset email success', () => {
+ const expectedAction = {
+ type: actionTypes.SEND_PASSWORD_RESET_EMAIL.SUCCESS,
+ };
+ expect(actionCreators.sendPasswordResetEmail.success()).toEqual(
+ expectedAction
+ );
+ });
+
+ it('send password reset email failure', () => {
+ const error = '';
+ const expectedAction = {
+ type: actionTypes.SEND_PASSWORD_RESET_EMAIL.FAILURE,
+ error: '',
+ };
+ expect(actionCreators.sendPasswordResetEmail.failure(error)).toEqual(
+ expectedAction
+ );
+ });
+
+ it('update password request', () => {
+ const expectedAction = {
+ type: actionTypes.UPDATE_PASSWORD.REQUEST,
+ };
+ expect(actionCreators.updatePassword.request()).toEqual(expectedAction);
+ });
+
+ it('update password success', () => {
+ const expectedAction = {
+ type: actionTypes.UPDATE_PASSWORD.SUCCESS,
+ };
+ expect(actionCreators.updatePassword.success()).toEqual(expectedAction);
+ });
+
+ it('update password failure', () => {
+ const error = '';
+ const expectedAction = {
+ type: actionTypes.UPDATE_PASSWORD.FAILURE,
+ error: '',
+ };
+ expect(actionCreators.updatePassword.failure(error)).toEqual(
+ expectedAction
+ );
+ });
+});
+
+describe('Side Effects', () => {
+ beforeEach(() => {
+ delete process.env.TOKEN;
+ });
+
+ it('me', async () => {
+ const expectedActions = [
+ { type: actionTypes.ME.REQUEST },
+ { type: campaigns.actionTypes.SET_CAMPAIGN.SUCCESS, campaignId: 1 },
+ { type: governments.actionTypes.SET_GOVERNMENT.SUCCESS, governmentId: 1 },
+ { type: summary.actionTypes.GET_SUMMARY.REQUEST },
+ { type: actionTypes.ME.SUCCESS },
+ ];
+ const store = mockStore({});
+
+ const tokenResponse = await api.login(
+ 'govadmin@openelectionsportland.org',
+ 'password'
+ );
+ process.env.TOKEN = tokenResponse.headers
+ .get('set-cookie')
+ .match(/=([a-zA-Z0-9].+); Path/)[1];
+
+ return store.dispatch(auth.me()).then(() => {
+ const actions = store.getActions();
+ expect(actions[0]).toEqual(expectedActions[0]);
+ expect(actions[1].type).toEqual(expectedActions[1].type);
+ expect(actions[2].type).toEqual(expectedActions[2].type);
+ expect(actions[3].type).toEqual(expectedActions[3].type);
+ expect(actions[4].me).toMatchObject({
+ id: expect.any(Number),
+ email: expect.any(String),
+ });
+ });
+ });
+
+ it('me no token', () => {
+ const expectedActions = [];
+ const store = mockStore({});
+
+ return store.dispatch(auth.me()).then(() => {
+ const actions = store.getActions();
+ expect(actions).toHaveLength(0);
+ });
+ });
+
+ it('login', () => {
+ const expectedActions = [
+ { type: actionTypes.LOGIN.REQUEST },
+ { type: actionTypes.LOGIN.SUCCESS },
+ ];
+ const store = mockStore({});
+
+ return store
+ .dispatch(auth.login(govAdmin.email, govAdmin.password))
+ .then(() => {
+ const actions = store.getActions();
+ expect(actions[0]).toEqual(expectedActions[0]);
+ expect(actions[1].type).toEqual(expectedActions[1].type);
+ });
+ });
+
+ it('logout', () => {
+ const expectedActions = [{ type: actionTypes.ME.SUCCESS, me: null }];
+ const store = mockStore({});
+ store.dispatch(auth.logout());
+ const actions = store.getActions();
+ expect(actions[0]).toEqual(expectedActions[0]);
+ });
+
+ it('login failure', () => {
+ const expectedActions = [
+ { type: actionTypes.LOGIN.REQUEST },
+ { type: actionTypes.LOGIN.FAILURE },
+ ];
+ const store = mockStore({});
+
+ return store
+ .dispatch(auth.login(govAdmin.email, 'wrongpassword'))
+ .then(() => {
+ const actions = store.getActions();
+ expect(actions[0]).toEqual(expectedActions[0]);
+ expect(actions[1].type).toEqual(expectedActions[1].type);
+ });
+ });
+
+ it('redeem invite', () => {
+ const expectedActions = [
+ { type: actionTypes.REDEEM_INVITE.REQUEST },
+ { type: actionTypes.REDEEM_INVITE.SUCCESS },
+ ];
+ const store = mockStore({});
+
+ return store
+ .dispatch(auth.redeemInvite(invite.code, invite.password))
+ .then(() => {
+ const actions = store.getActions();
+ expect(actions[0]).toEqual(expectedActions[0]);
+ expect(actions[1]).toEqual(expectedActions[1]);
+ });
+ });
+
+ it('redeem invite failure', () => {
+ const expectedActions = [
+ { type: actionTypes.REDEEM_INVITE.REQUEST },
+ { type: actionTypes.REDEEM_INVITE.FAILURE },
+ ];
+ const store = mockStore({});
+
+ return store
+ .dispatch(auth.redeemInvite('wrongcode', invite.password))
+ .then(() => {
+ const actions = store.getActions();
+ expect(actions[0]).toEqual(expectedActions[0]);
+ expect(actions[1]).toEqual(expectedActions[1]);
+ });
+ });
+
+ it('reset password', () => {
+ const expectedActions = [
+ { type: actionTypes.RESET_PASSWORD.REQUEST },
+ { type: actionTypes.RESET_PASSWORD.SUCCESS },
+ ];
+ const store = mockStore({});
+
+ return store
+ .dispatch(auth.resetPassword(reset.code, reset.password))
+ .then(() => {
+ expect(store.getActions()).toEqual(expectedActions);
+ });
+ });
+
+ it('reset password failure', () => {
+ const expectedActions = [
+ { type: actionTypes.RESET_PASSWORD.REQUEST },
+ { type: actionTypes.RESET_PASSWORD.FAILURE },
+ ];
+ const store = mockStore({});
+
+ return store
+ .dispatch(auth.resetPassword('wrongcode', reset.password))
+ .then(() => {
+ expect(store.getActions()).toEqual(expectedActions);
+ });
+ });
+
+ it('send password reset email', () => {
+ const expectedActions = [
+ { type: actionTypes.SEND_PASSWORD_RESET_EMAIL.REQUEST },
+ { type: actionTypes.SEND_PASSWORD_RESET_EMAIL.SUCCESS },
+ ];
+ const store = mockStore({});
+
+ return store
+ .dispatch(
+ auth.sendPasswordResetEmail('campaignstaff@openelectionsportland.org')
+ )
+ .then(() => {
+ expect(store.getActions()).toEqual(expectedActions);
+ });
+ });
+
+ it('send password reset email failure', () => {
+ const expectedActions = [
+ { type: actionTypes.SEND_PASSWORD_RESET_EMAIL.REQUEST },
+ { type: actionTypes.SEND_PASSWORD_RESET_EMAIL.FAILURE },
+ ];
+ const store = mockStore({});
+
+ return store
+ .dispatch(
+ auth.sendPasswordResetEmail(
+ 'wrong_campaignstaff@@openelectionsportland.org'
+ )
+ )
+ .then(() => {
+ expect(store.getActions()).toEqual(expectedActions);
+ });
+ });
+
+ it('update password', async () => {
+ const expectedActions = [
+ { type: actionTypes.UPDATE_PASSWORD.REQUEST },
+ { type: actionTypes.UPDATE_PASSWORD.SUCCESS },
+ ];
+ const store = mockStore({});
+
+ const tokenResponse = await api.login(
+ 'govadmin@openelectionsportland.org',
+ 'password'
+ );
+ process.env.TOKEN = tokenResponse.headers
+ .get('set-cookie')
+ .match(/=([a-zA-Z0-9].+); Path/)[1];
+
+ return store
+ .dispatch(auth.updatePassword('password', 'newpassword'))
+ .then(() => {
+ const actions = store.getActions();
+ expect(actions[0]).toEqual(expectedActions[0]);
+ expect(actions[1]).toEqual(expectedActions[1]);
+ });
+ });
+
+ it('update password failure', () => {
+ const expectedActions = [
+ { type: actionTypes.UPDATE_PASSWORD.REQUEST },
+ { type: actionTypes.UPDATE_PASSWORD.FAILURE },
+ ];
+ const store = mockStore({});
+
+ return store
+ .dispatch(auth.updatePassword('password', 'newpassword'))
+ .then(() => {
+ const actions = store.getActions();
+ expect(actions[0]).toEqual(expectedActions[0]);
+ expect(actions[1].type).toEqual(expectedActions[1].type);
+ });
+ });
+});
diff --git a/app2/src/state/ducks/campaigns.js b/app2/src/state/ducks/campaigns.js
new file mode 100644
index 000000000..2dbdcc5ef
--- /dev/null
+++ b/app2/src/state/ducks/campaigns.js
@@ -0,0 +1,216 @@
+/* eslint-disable no-unused-vars */
+import { createSelector } from 'reselect';
+import { normalize } from 'normalizr';
+import { flashMessage } from 'redux-flash';
+import createReducer from '../utils/createReducer';
+import createActionTypes from '../utils/createActionTypes';
+import action from '../utils/action';
+import { addEntities, ADD_ENTITIES, resetState, RESET_STATE } from './common';
+import { inviteUser } from './users';
+import { getCurrentCampaignId } from './auth';
+
+export const STATE_KEY = 'campaigns';
+
+// Action Types
+export const actionTypes = {
+ CREATE_CAMPAIGN: createActionTypes(STATE_KEY, 'CREATE_CAMPAIGN'),
+ SET_CAMPAIGN: createActionTypes(STATE_KEY, 'SET_CAMPAIGN'),
+ GET_CAMPAIGNS: createActionTypes(STATE_KEY, 'GET_CAMPAIGNS'),
+ UPDATE_CAMPAIGN_NAME: createActionTypes(STATE_KEY, 'UPDATE_CAMPAIGN_NAME'),
+};
+
+// Initial State
+export const initialState = {
+ isLoading: false,
+ error: null,
+ currentCampaignId: null,
+ list: {},
+};
+
+export const resetCampaignState = resetState;
+// Reducer
+export default createReducer(initialState, {
+ [RESET_STATE]: () => {
+ return { ...initialState };
+ },
+ [ADD_ENTITIES]: (state, action) => {
+ return { ...state, list: action.payload.campaigns };
+ },
+ [actionTypes.CREATE_CAMPAIGN.REQUEST]: (state, action) => {
+ return { ...state, isLoading: true };
+ },
+ [actionTypes.CREATE_CAMPAIGN.SUCCESS]: (state, action) => {
+ return { ...state, isLoading: false };
+ },
+ [actionTypes.CREATE_CAMPAIGN.FAILURE]: (state, action) => {
+ return { ...state, isLoading: false, error: action.error };
+ },
+ [actionTypes.SET_CAMPAIGN.SUCCESS]: (state, action) => {
+ return { ...state, currentCampaignId: action.campaignId };
+ },
+ [actionTypes.GET_CAMPAIGNS.REQUEST]: (state, action) => {
+ return { ...state, isLoading: true };
+ },
+ [actionTypes.GET_CAMPAIGNS.SUCCESS]: (state, action) => {
+ return { ...state, isLoading: false };
+ },
+ [actionTypes.GET_CAMPAIGNS.FAILURE]: (state, action) => {
+ return { ...state, isLoading: false, error: action.error };
+ },
+});
+
+// Action Creators
+export const actionCreators = {
+ createCampaign: {
+ request: () => action(actionTypes.CREATE_CAMPAIGN.REQUEST),
+ success: () => action(actionTypes.CREATE_CAMPAIGN.SUCCESS),
+ failure: error => action(actionTypes.CREATE_CAMPAIGN.FAILURE, { error }),
+ },
+ setCampaign: {
+ success: campaignId =>
+ action(actionTypes.SET_CAMPAIGN.SUCCESS, { campaignId }),
+ },
+ getCampaigns: {
+ request: () => action(actionTypes.GET_CAMPAIGNS.REQUEST),
+ success: () => action(actionTypes.GET_CAMPAIGNS.SUCCESS),
+ failure: error => action(actionTypes.GET_CAMPAIGNS.FAILURE, { error }),
+ },
+ updateCampaignName: {
+ request: () => action(actionTypes.UPDATE_CAMPAIGN_NAME.REQUEST),
+ success: () => action(actionTypes.UPDATE_CAMPAIGN_NAME.SUCCESS),
+ failure: error =>
+ action(actionTypes.UPDATE_CAMPAIGN_NAME.FAILURE, { error }),
+ },
+};
+
+// Side Effects, e.g. thunks
+export function createCampaignForGovernment(
+ governmentId,
+ campaignName,
+ officeSought,
+ email,
+ firstName,
+ lastName
+) {
+ return async (dispatch, getState, { api, schema }) => {
+ dispatch(actionCreators.createCampaign.request());
+ const campaignAttrs = {
+ governmentId,
+ name: campaignName,
+ officeSought,
+ };
+ try {
+ const response = await api.createCampaignForGovernment(campaignAttrs);
+ if (response.status === 201) {
+ const data = normalize(await response.json(), schema.campaign);
+ dispatch(addEntities(data.entities));
+ dispatch(actionCreators.createCampaign.success());
+ dispatch(
+ inviteUser(
+ email,
+ firstName,
+ lastName,
+ data.result,
+ api.UserRoleEnum.CAMPAIGN_ADMIN
+ )
+ );
+ dispatch(
+ flashMessage('Campaign created', { props: { variant: 'success' } })
+ );
+ } else {
+ dispatch(actionCreators.createCampaign.failure());
+ dispatch(
+ flashMessage('Unable to create Campaign', {
+ props: { variant: 'error' },
+ })
+ );
+ }
+ } catch (error) {
+ dispatch(actionCreators.createCampaign.failure(error));
+ dispatch(
+ flashMessage(`Unable to create Campaign - ${error}`, {
+ props: { variant: 'error' },
+ })
+ );
+ }
+ };
+}
+
+export function updateCampaignName(governmentId, campaignId, campaignName) {
+ return async (dispatch, getState, { api, schema }) => {
+ dispatch(actionCreators.updateCampaignName.request());
+ const campaignAttrs = {
+ governmentId,
+ campaignId,
+ newName: campaignName,
+ };
+ try {
+ const response = await api.updateCampaignNameForGovernment(campaignAttrs);
+ if (response.status === 201) {
+ dispatch(actionCreators.updateCampaignName.success());
+ dispatch(
+ flashMessage('Campaign name updated', {
+ props: {
+ variant: 'success',
+ },
+ })
+ );
+ }
+ } catch (error) {
+ dispatch(actionCreators.updateCampaignName.failure(error));
+ dispatch(
+ flashMessage(`Unable to update campaign name - ${error}`, {
+ props: { variant: 'error' },
+ })
+ );
+ }
+ };
+}
+
+export function getCampaigns(governmentId) {
+ return async (dispatch, getState, { api, schema }) => {
+ dispatch(actionCreators.getCampaigns.request());
+
+ try {
+ const response = await api.getCampaignsForGovernment(governmentId);
+ if (Array.isArray(response)) {
+ const data = normalize(response, [schema.campaign]);
+ dispatch(addEntities(data.entities));
+ dispatch(actionCreators.getCampaigns.success());
+ } else {
+ dispatch(actionCreators.getCampaigns.failure());
+ }
+ } catch (error) {
+ dispatch(actionCreators.getCampaigns.failure(error));
+ }
+ };
+}
+
+// Selectors
+export const rootState = state => state || {};
+
+export const getCampaignInfo = createSelector(
+ rootState,
+ state => state.campaigns
+);
+
+// Assumes one campaign
+export const getCampaignName = state => {
+ const id = getCurrentCampaignId(state);
+
+ return id &&
+ state.campaigns.list &&
+ state.campaigns.list[id] &&
+ state.campaigns.list[id].name
+ ? state.campaigns.list[id].name
+ : 'Campaign';
+};
+
+export const getCampaignList = createSelector(rootState, state => {
+ return state.campaigns.list ? Object.values(state.campaigns.list) : [{}];
+});
+
+export const isCampaignsLoading = createSelector(
+ rootState,
+ state => state.campaigns.isLoading
+);
diff --git a/app2/src/state/ducks/campaigns.test.js b/app2/src/state/ducks/campaigns.test.js
new file mode 100644
index 000000000..e02d12903
--- /dev/null
+++ b/app2/src/state/ducks/campaigns.test.js
@@ -0,0 +1,233 @@
+/* eslint-disable no-unused-vars */
+import configureMockStore from 'redux-mock-store';
+import thunk from 'redux-thunk';
+import * as campaigns from './campaigns';
+import * as api from '../../api';
+import * as schema from '../../api/schema';
+import { ADD_ENTITIES } from './common';
+
+const { actionTypes, actionCreators } = campaigns;
+
+const middlewares = [thunk.withExtraArgument({ api, schema })];
+const mockStore = configureMockStore(middlewares);
+
+const govAdmin = {
+ email: 'govadmin@openelectionsportland.org',
+ password: 'password',
+};
+
+const invite = {
+ code: 'inviteme',
+ email: 'campaignStaff+1@openelectionsportland.org',
+ password: 'password',
+};
+
+const reset = {
+ code: 'resetme',
+ password: 'newpassword',
+};
+
+describe('Reducer', () => {
+ const reducer = campaigns.default;
+ it('initial state', () => {
+ expect(reducer(undefined, {})).toEqual({
+ currentCampaignId: null,
+ isLoading: false,
+ error: null,
+ list: {},
+ });
+ });
+
+ it('adds campaign entities', () => {
+ expect(
+ reducer(undefined, {
+ type: ADD_ENTITIES,
+ payload: {
+ campaigns: {
+ '1': {},
+ },
+ },
+ })
+ ).toEqual({
+ list: {
+ '1': {},
+ },
+ currentCampaignId: null,
+ isLoading: false,
+ error: null,
+ });
+ });
+
+ it('sets current campaign', () => {
+ expect(
+ reducer(
+ {
+ currentCampaignId: null,
+ isLoading: false,
+ error: null,
+ },
+ {
+ type: actionTypes.SET_CAMPAIGN.SUCCESS,
+ campaignId: 1,
+ }
+ )
+ ).toEqual({
+ currentCampaignId: 1,
+ isLoading: false,
+ error: null,
+ });
+ });
+});
+
+describe('Action Creators', () => {
+ it('create campaign request', () => {
+ const expectedAction = {
+ type: actionTypes.CREATE_CAMPAIGN.REQUEST,
+ };
+ expect(actionCreators.createCampaign.request()).toEqual(expectedAction);
+ });
+ it('create campaign success', () => {
+ const expectedAction = {
+ type: actionTypes.CREATE_CAMPAIGN.SUCCESS,
+ };
+ expect(actionCreators.createCampaign.success()).toEqual(expectedAction);
+ });
+ it('create campaign failure', () => {
+ const expectedAction = {
+ type: actionTypes.CREATE_CAMPAIGN.FAILURE,
+ };
+ expect(actionCreators.createCampaign.failure()).toEqual(expectedAction);
+ });
+ it('set campaign success', () => {
+ const expectedAction = {
+ type: actionTypes.SET_CAMPAIGN.SUCCESS,
+ campaignId: 1,
+ };
+ expect(actionCreators.setCampaign.success(1)).toEqual(expectedAction);
+ });
+ it('update campaign name request', () => {
+ const expectedAction = {
+ type: actionTypes.UPDATE_CAMPAIGN_NAME.REQUEST,
+ };
+ expect(actionCreators.updateCampaignName.request()).toEqual(expectedAction);
+ });
+ it('update campaign name success', () => {
+ const expectedAction = {
+ type: actionTypes.UPDATE_CAMPAIGN_NAME.SUCCESS,
+ };
+ expect(actionCreators.updateCampaignName.success()).toEqual(expectedAction);
+ });
+ it('update campaign name failure', () => {
+ const expectedAction = {
+ type: actionTypes.UPDATE_CAMPAIGN_NAME.FAILURE,
+ };
+ expect(actionCreators.updateCampaignName.failure()).toEqual(expectedAction);
+ });
+});
+
+let govAdminToken;
+let campaignAdminToken;
+let campaignStaffToken;
+let governmentId;
+let campaignId;
+describe.only('Side Effects', () => {
+ beforeAll(async () => {
+ let tokenResponse = await api.login(
+ 'govadmin@openelectionsportland.org',
+ 'password'
+ );
+ govAdminToken = tokenResponse.headers
+ .get('set-cookie')
+ .match(/=([a-zA-Z0-9].+); Path/)[1];
+ let decodedToken = api.decodeToken(govAdminToken);
+ governmentId = decodedToken.permissions[0].governmentId;
+
+ tokenResponse = await api.login(
+ 'campaignadmin@openelectionsportland.org',
+ 'password'
+ );
+ campaignAdminToken = tokenResponse.headers
+ .get('set-cookie')
+ .match(/=([a-zA-Z0-9].+); Path/)[1];
+ decodedToken = api.decodeToken(campaignAdminToken);
+ campaignId = decodedToken.permissions[0].campaignId;
+
+ tokenResponse = await api.login(
+ 'campaignstaff@openelectionsportland.org',
+ 'password'
+ );
+ campaignStaffToken = tokenResponse.headers
+ .get('set-cookie')
+ .match(/=([a-zA-Z0-9].+); Path/)[1];
+ });
+
+ beforeEach(() => {
+ delete process.env.TOKEN;
+ });
+
+ it('creates campaign for government testme', async () => {
+ const expectedActions = [
+ { type: actionTypes.CREATE_CAMPAIGN.REQUEST },
+ { type: ADD_ENTITIES },
+ { type: actionTypes.CREATE_CAMPAIGN.SUCCESS },
+ ];
+ const store = mockStore({});
+
+ process.env.TOKEN = govAdminToken;
+
+ return store
+ .dispatch(
+ campaigns.createCampaignForGovernment(
+ governmentId,
+ 'Test New Gov Campaign',
+ 'Mayor',
+ 'campaignadminbygov@openelectionsportland.org',
+ 'CampaignAdmin',
+ 'InvitedByGov'
+ )
+ )
+ .then(() => {
+ const actions = store.getActions();
+ expect(actions[0].type).toEqual(expectedActions[0].type);
+ expect(actions[1].type).toEqual(expectedActions[1].type);
+ expect(actions[2].type).toEqual(expectedActions[2].type);
+ });
+ });
+
+ it('updates campaign name', async () => {
+ const expectedActions = [
+ { type: actionTypes.UPDATE_CAMPAIGN_NAME.REQUEST },
+ { type: actionTypes.UPDATE_CAMPAIGN_NAME.SUCCESS },
+ ];
+ const store = mockStore({});
+
+ process.env.TOKEN = govAdminToken;
+
+ return store
+ .dispatch(
+ campaigns.updateCampaignName(governmentId, campaignId, 'campaignName')
+ )
+ .then(() => {
+ const actions = store.getActions();
+ expect(actions[0].type).toEqual(expectedActions[0].type);
+ });
+ });
+
+ it('gets campaigns', async () => {
+ const expectedActions = [
+ { type: actionTypes.GET_CAMPAIGNS.REQUEST },
+ { type: ADD_ENTITIES },
+ { type: actionTypes.GET_CAMPAIGNS.SUCCESS },
+ ];
+ const store = mockStore({});
+
+ process.env.TOKEN = govAdminToken;
+
+ return store.dispatch(campaigns.getCampaigns(governmentId)).then(() => {
+ const actions = store.getActions();
+ expect(actions[0].type).toEqual(expectedActions[0].type);
+ expect(actions[1].type).toEqual(expectedActions[1].type);
+ expect(actions[2].type).toEqual(expectedActions[2].type);
+ });
+ });
+});
diff --git a/app2/src/state/ducks/common.js b/app2/src/state/ducks/common.js
new file mode 100644
index 000000000..b690c379f
--- /dev/null
+++ b/app2/src/state/ducks/common.js
@@ -0,0 +1,30 @@
+export const ADD_ENTITIES = 'ADD_ENTITIES';
+export const addEntities = entities => {
+ return {
+ type: ADD_ENTITIES,
+ payload: entities,
+ };
+};
+
+export const ADD_CONTRIBUTION_ENTITIES = 'ADD_CONTRIBUTION_ENTITIES';
+export const addContributionEntities = entities => {
+ return {
+ type: ADD_CONTRIBUTION_ENTITIES,
+ payload: entities,
+ };
+};
+
+export const ADD_EXPENDITURE_ENTITIES = 'ADD_EXPENDITURE_ENTITIES';
+export const addExpenditureEntities = entities => {
+ return {
+ type: ADD_EXPENDITURE_ENTITIES,
+ payload: entities,
+ };
+};
+
+export const RESET_STATE = 'RESET_STATE';
+export const resetState = () => {
+ return {
+ type: RESET_STATE,
+ };
+};
diff --git a/app2/src/state/ducks/contributions.js b/app2/src/state/ducks/contributions.js
new file mode 100644
index 000000000..89be3bd85
--- /dev/null
+++ b/app2/src/state/ducks/contributions.js
@@ -0,0 +1,441 @@
+/* eslint-disable no-unused-vars */
+import { normalize } from 'normalizr';
+import { createSelector } from 'reselect';
+import { isEmpty } from 'lodash';
+import { flashMessage } from 'redux-flash';
+import { push } from 'connected-react-router';
+import createReducer from '../utils/createReducer';
+import createActionTypes, {
+ createCustomActionTypes,
+} from '../utils/createActionTypes';
+import action from '../utils/action';
+import {
+ addContributionEntities,
+ ADD_CONTRIBUTION_ENTITIES,
+ resetState,
+ RESET_STATE,
+} from './common';
+import { getActivitiesByIdType } from './activities';
+import { downloadFile } from '../utils/helpers';
+import { isGovAdmin } from './auth';
+import { getMatchesByContributionId } from './matches';
+import { getContributionsByMatchId } from './pastContributions';
+
+export const STATE_KEY = 'contributions';
+
+// Action Types
+export const actionTypes = {
+ CREATE_CONTRIBUTION: createActionTypes(STATE_KEY, 'CREATE_CONTRIBUTION'),
+ UPDATE_CONTRIBUTION: createActionTypes(STATE_KEY, 'UPDATE_CONTRIBUTION'),
+ GET_CONTRIBUTIONS: createActionTypes(STATE_KEY, 'GET_CONTRIBUTIONS'),
+ GET_CONTRIBUTION_BY_ID: createActionTypes(
+ STATE_KEY,
+ 'GET_CONTRIBUTION_BY_ID'
+ ),
+ ARCHIVE_CONTRIBUTION: createActionTypes(STATE_KEY, 'ARCHIVE_CONTRIBUTION'),
+ POST_CONTRIBUTION_COMMENT: createActionTypes(
+ STATE_KEY,
+ 'POST_CONTRIBUTION_COMMENT'
+ ),
+ GET_MATCHES_BY_CONTRIBUTION_ID: createActionTypes(
+ STATE_KEY,
+ 'GET_MATCHES_BY_CONTRIBUTION_ID'
+ ),
+ FILTER: createCustomActionTypes(STATE_KEY, 'FILTER', ['UPDATE']),
+};
+
+// Initial State
+export const initialState = {
+ list: null,
+ listOrder: [],
+ listFilterOptions: {
+ from: '',
+ to: '',
+ status: 'all',
+ page: 0,
+ perPage: 50,
+ sort: {},
+ },
+ isLoading: false,
+ error: null,
+ currentId: 0,
+ total: 0,
+};
+
+export const resetContributionState = resetState;
+// Reducer
+export default createReducer(initialState, {
+ [RESET_STATE]: () => {
+ return { ...initialState };
+ },
+ [ADD_CONTRIBUTION_ENTITIES]: (state, action) => {
+ return {
+ ...state,
+ list: { ...action.payload.entities.contributions },
+ listOrder: action.payload.result,
+ };
+ },
+ [actionTypes.CREATE_CONTRIBUTION.REQUEST]: (state, action) => {
+ return { ...state, isLoading: true };
+ },
+ [actionTypes.CREATE_CONTRIBUTION.SUCCESS]: (state, action) => {
+ return { ...state, isLoading: false };
+ },
+ [actionTypes.CREATE_CONTRIBUTION.FAILURE]: (state, action) => {
+ return { ...state, isLoading: false, error: action.error };
+ },
+ [actionTypes.UPDATE_CONTRIBUTION.REQUEST]: (state, action) => {
+ return { ...state, isLoading: true };
+ },
+ [actionTypes.UPDATE_CONTRIBUTION.SUCCESS]: (state, action) => {
+ return { ...state, isLoading: false };
+ },
+ [actionTypes.UPDATE_CONTRIBUTION.FAILURE]: (state, action) => {
+ return { ...state, isLoading: false, error: action.error };
+ },
+ [actionTypes.GET_CONTRIBUTIONS.REQUEST]: (state, action) => {
+ return { ...state, isLoading: true };
+ },
+ [actionTypes.GET_CONTRIBUTIONS.SUCCESS]: (state, action) => {
+ return {
+ ...state,
+ isLoading: false,
+ total: action.total,
+ };
+ },
+ [actionTypes.GET_CONTRIBUTIONS.FAILURE]: (state, action) => {
+ return { ...state, isLoading: false, error: action.error };
+ },
+ [actionTypes.GET_CONTRIBUTION_BY_ID.REQUEST]: (state, action) => {
+ return { ...state, isLoading: true };
+ },
+ [actionTypes.GET_CONTRIBUTION_BY_ID.SUCCESS]: (state, action) => {
+ return {
+ ...state,
+ isLoading: false,
+ currentId: action.id,
+ };
+ },
+ [actionTypes.GET_CONTRIBUTION_BY_ID.FAILURE]: (state, action) => {
+ return { ...state, isLoading: false, error: action.error };
+ },
+ [actionTypes.ARCHIVE_CONTRIBUTION.REQUEST]: (state, action) => {
+ return { ...state, isLoading: true };
+ },
+ [actionTypes.ARCHIVE_CONTRIBUTION.SUCCESS]: state => {
+ return { ...state, isLoading: false };
+ },
+ [actionTypes.ARCHIVE_CONTRIBUTION.FAILURE]: state => {
+ return { ...state, isLoading: false, error: action.error };
+ },
+ [actionTypes.POST_CONTRIBUTION_COMMENT.REQUEST]: (state, action) => {
+ return { ...state, isLoading: true };
+ },
+ [actionTypes.POST_CONTRIBUTION_COMMENT.SUCCESS]: state => {
+ return { ...state, isLoading: false };
+ },
+ [actionTypes.POST_CONTRIBUTION_COMMENT.FAILURE]: (state, action) => {
+ return { ...state, isLoading: false, error: action.error };
+ },
+ [actionTypes.FILTER.UPDATE]: (state, action) => {
+ return { ...state, listFilterOptions: action.listFilterOptions };
+ },
+});
+
+// Action Creators
+export const actionCreators = {
+ createContribution: {
+ request: () => action(actionTypes.CREATE_CONTRIBUTION.REQUEST),
+ success: () => action(actionTypes.CREATE_CONTRIBUTION.SUCCESS),
+ failure: error =>
+ action(actionTypes.CREATE_CONTRIBUTION.FAILURE, { error }),
+ },
+ updateContribution: {
+ request: () => action(actionTypes.UPDATE_CONTRIBUTION.REQUEST),
+ success: () => action(actionTypes.UPDATE_CONTRIBUTION.SUCCESS),
+ failure: error =>
+ action(actionTypes.UPDATE_CONTRIBUTION.FAILURE, { error }),
+ },
+ getContributions: {
+ request: () => action(actionTypes.GET_CONTRIBUTIONS.REQUEST),
+ success: total => action(actionTypes.GET_CONTRIBUTIONS.SUCCESS, { total }),
+ failure: error => action(actionTypes.GET_CONTRIBUTIONS.FAILURE, { error }),
+ },
+ getContributionById: {
+ request: () => action(actionTypes.GET_CONTRIBUTION_BY_ID.REQUEST),
+ success: id => action(actionTypes.GET_CONTRIBUTION_BY_ID.SUCCESS, { id }),
+ failure: error =>
+ action(actionTypes.GET_CONTRIBUTION_BY_ID.FAILURE, { error }),
+ },
+ archiveContribution: {
+ request: () => action(actionTypes.ARCHIVE_CONTRIBUTION.REQUEST),
+ success: () => action(actionTypes.ARCHIVE_CONTRIBUTION.SUCCESS),
+ failure: error =>
+ action(actionTypes.ARCHIVE_CONTRIBUTION.FAILURE, { error }),
+ },
+ postContributionComment: {
+ request: () => action(actionTypes.POST_CONTRIBUTION_COMMENT.REQUEST),
+ success: () => action(actionTypes.POST_CONTRIBUTION_COMMENT.SUCCESS),
+ failure: error =>
+ action(actionTypes.POST_CONTRIBUTION_COMMENT.FAILURE, { error }),
+ },
+ filter: {
+ update: listFilterOptions => {
+ return action(actionTypes.FILTER.UPDATE, { listFilterOptions });
+ },
+ },
+};
+
+// Side Effects, e.g. thunks
+export function updateFilter(newFilterOptions) {
+ return (dispatch, getState) => {
+ // eslint-disable-next-line prefer-const
+ let filterOptions = getState().contributions.listFilterOptions;
+ if (newFilterOptions.perPage) {
+ filterOptions.page = Math.floor(
+ (filterOptions.page * filterOptions.perPage) / newFilterOptions.perPage
+ );
+ }
+ Object.entries(filterOptions).forEach(([key, value]) => {
+ if (Object.prototype.hasOwnProperty.call(newFilterOptions, key))
+ filterOptions[key] = newFilterOptions[key];
+ });
+ dispatch(actionCreators.filter.update(filterOptions));
+ };
+}
+
+export const getFilterOptionsForRequest = state => {
+ const filter = state.contributions.listFilterOptions;
+ const sort = state.contributions.listFilterOptions.sort || {};
+ const returnObj = {};
+
+ Object.entries(filter).forEach(([key, value]) => {
+ // Look for any filters such as status
+ if (value) {
+ returnObj[key] = value;
+ }
+ });
+ if (sort.field) {
+ // If the sort field is set make sure there is also a direction
+ returnObj.sort = {
+ field: sort.field,
+ direction: sort.direction || 'DESC',
+ };
+ } else {
+ // Remove sort if there isn't any, defauts to last modified DESC
+ delete returnObj.sort;
+ }
+
+ // API defaults to all statuses but all is not a status
+ if (returnObj.status === 'all') delete returnObj.status;
+
+ // Always pass in the pagination to maintain sync with table
+ returnObj.perPage = filter.perPage;
+ returnObj.page = filter.page * filter.perPage;
+ return returnObj;
+};
+
+export function createContribution(contributionAttrs) {
+ return async (dispatch, getState, { api, schema }) => {
+ dispatch(actionCreators.createContribution.request());
+ try {
+ const response = await api.createContribution(contributionAttrs);
+ if (response.status === 201) {
+ const data = normalize(await response.json(), schema.contribution);
+ dispatch(addContributionEntities(data));
+ dispatch(actionCreators.createContribution.success());
+ dispatch(
+ flashMessage(`Contribution Added`, {
+ props: { variant: 'success' },
+ })
+ );
+ dispatch(push(`/contributions/${data.result}`));
+ return data.result;
+ }
+ dispatch(actionCreators.createContribution.failure());
+ dispatch(
+ flashMessage(`Error - ${response.status} status returned`, {
+ props: { variant: 'error' },
+ })
+ );
+ } catch (error) {
+ dispatch(actionCreators.createContribution.failure(error));
+ dispatch(
+ flashMessage(`Error - ${error}`, { props: { variant: 'error' } })
+ );
+ }
+ };
+}
+
+export function updateContribution(contributionAttrs) {
+ return async (dispatch, getState, { api, schema }) => {
+ dispatch(actionCreators.updateContribution.request());
+ try {
+ const response = await api.updateContribution(contributionAttrs);
+ if (response.status === 204) {
+ let status = '';
+ if (contributionAttrs.status) {
+ status = contributionAttrs.status;
+ }
+ dispatch(actionCreators.updateContribution.success());
+ dispatch(
+ flashMessage(`Contribution Updated ${status}`, {
+ props: { variant: 'success' },
+ })
+ );
+ dispatch(push('/contributions'));
+ } else {
+ dispatch(actionCreators.updateContribution.failure());
+ const error = await response.json();
+ dispatch(
+ flashMessage(`Error - ${error}`, { props: { variant: 'error' } })
+ );
+ return error;
+ }
+ } catch (error) {
+ dispatch(actionCreators.updateContribution.failure(error));
+ dispatch(
+ flashMessage(`Error - ${error}`, { props: { variant: 'error' } })
+ );
+ return error;
+ }
+ };
+}
+
+export function getContributions(contributionSearchAttrs, applyFilter = false) {
+ return async (dispatch, getState, { api, schema }) => {
+ dispatch(actionCreators.getContributions.request());
+ try {
+ const filter = applyFilter ? getFilterOptionsForRequest(getState()) : {};
+ const response = await api.getContributions({
+ ...contributionSearchAttrs,
+ ...filter,
+ });
+ if (contributionSearchAttrs.format === 'csv' && response.status === 200) {
+ const contributions = await response.text();
+ downloadFile(contributions, `contributions-download-${Date.now()}.csv`);
+ } else if (
+ contributionSearchAttrs.format === 'xml' &&
+ response.status === 200
+ ) {
+ const contributions = await response.json();
+ contributions.map((contribution, index) => {
+ return downloadFile(
+ contribution,
+ `contributions-download-${index + 1}-${Date.now()}.xml`
+ );
+ });
+ } else if (response.status === 200) {
+ const contributions = await response.json();
+ const data = normalize(contributions.data, [schema.contribution]);
+ dispatch(addContributionEntities(data));
+ dispatch(actionCreators.getContributions.success(contributions.total));
+ } else {
+ dispatch(actionCreators.getContributions.failure());
+ }
+ } catch (error) {
+ dispatch(actionCreators.getContributions.failure(error));
+ }
+ };
+}
+
+export function getContributionById(id) {
+ return async (dispatch, getState, { api, schema }) => {
+ dispatch(actionCreators.getContributionById.request());
+ try {
+ const response = await api.getContributionById(id);
+ if (response.status === 200) {
+ const json = await response.json();
+ const data = normalize(json, schema.contribution);
+ dispatch(addContributionEntities(data));
+ dispatch(actionCreators.getContributionById.success(id));
+ if (isGovAdmin(getState())) {
+ dispatch(getMatchesByContributionId(id));
+ if (json.matchId) {
+ dispatch(getContributionsByMatchId(json.matchId));
+ }
+ }
+ // dispatch(getContributionActivities(id));
+ } else {
+ dispatch(actionCreators.getContributionById.failure());
+ }
+ } catch (error) {
+ dispatch(actionCreators.getContributionById.failure(error));
+ }
+ };
+}
+
+export function archiveContribution(id) {
+ return async (dispatch, getState, { api, schema }) => {
+ dispatch(actionCreators.archiveContribution.request());
+ try {
+ const response = await api.archiveContribution(id);
+ if (response.status === 200) {
+ const data = normalize(await response.json(), schema.contribution);
+ dispatch(addContributionEntities(data));
+ dispatch(actionCreators.archiveContribution.success());
+ } else {
+ dispatch(actionCreators.archiveContribution.failure());
+ }
+ } catch (error) {
+ dispatch(actionCreators.archiveContribution.failure(error));
+ }
+ };
+}
+
+export function postContributionComment(id, comment, attachment) {
+ return async (dispatch, getState, { api, schema }) => {
+ dispatch(actionCreators.postContributionComment.request());
+ try {
+ const response = await api.postContributionComment(
+ id,
+ comment,
+ attachment
+ );
+ if (response.status === 204) {
+ dispatch(getActivitiesByIdType({ contributionId: id }));
+ dispatch(actionCreators.postContributionComment.success());
+ } else {
+ dispatch(actionCreators.postContributionComment.failure());
+ }
+ } catch (error) {
+ dispatch(actionCreators.postContributionComment.failure(error));
+ }
+ };
+}
+
+// Selectors
+export const rootState = state => state || {};
+
+export const getContributionsList = createSelector(rootState, state => {
+ if (
+ isEmpty(state.contributions.list) ||
+ isEmpty(state.contributions.listOrder)
+ ) {
+ return [];
+ }
+ return state.contributions.listOrder.map(id => state.contributions.list[id]);
+});
+
+export const getContributionsTotal = createSelector(rootState, state => {
+ return state.contributions.total;
+});
+
+export const getCurrentContribution = state => {
+ return state.contributions &&
+ state.contributions.list &&
+ state.contributions.currentId
+ ? state.contributions.list[state.contributions.currentId]
+ : false;
+};
+
+export const getContributionCampaignName = state => {
+ const contribution = getCurrentContribution(state);
+ return contribution ? contribution.campaign.name : null;
+};
+
+export const getFilterOptions = state => {
+ const filter = state.contributions.listFilterOptions;
+ const sort = state.contributions.listFilterOptions.sort || {};
+ return { ...filter, sort };
+};
diff --git a/app2/src/state/ducks/contributions.test.js b/app2/src/state/ducks/contributions.test.js
new file mode 100644
index 000000000..3bf9d165a
--- /dev/null
+++ b/app2/src/state/ducks/contributions.test.js
@@ -0,0 +1,363 @@
+import configureMockStore from 'redux-mock-store';
+import thunk from 'redux-thunk';
+import * as contributions from './contributions';
+import * as activities from './activities';
+import * as api from '../../api';
+import * as schema from '../../api/schema';
+import { ADD_CONTRIBUTION_ENTITIES } from './common';
+
+const { actionTypes, actionCreators } = contributions;
+
+const middlewares = [thunk.withExtraArgument({ api, schema })];
+const mockStore = configureMockStore(middlewares);
+
+describe('Reducer', () => {
+ const reducer = contributions.default;
+ it('initial state', () => {
+ expect(reducer(undefined, {})).toEqual({
+ list: null,
+ isLoading: false,
+ error: null,
+ currentId: 0,
+ listOrder: [],
+ listFilterOptions: {
+ from: '',
+ to: '',
+ status: 'all',
+ page: 0,
+ perPage: 50,
+ sort: {},
+ },
+ total: 0,
+ });
+ });
+
+ it('adds contribution entities', () => {
+ expect(
+ reducer(undefined, {
+ type: ADD_CONTRIBUTION_ENTITIES,
+ payload: {
+ entities: {
+ contributions: {
+ '1': {},
+ },
+ },
+ },
+ })
+ ).toEqual({
+ list: {
+ '1': {},
+ },
+ isLoading: false,
+ listFilterOptions: {
+ from: '',
+ to: '',
+ status: 'all',
+ page: 0,
+ perPage: 50,
+ sort: {},
+ },
+ error: null,
+ currentId: 0,
+ total: 0,
+ });
+ });
+});
+
+describe('Action Creators', () => {
+ it('create contribution request', () => {
+ const expectedAction = {
+ type: actionTypes.CREATE_CONTRIBUTION.REQUEST,
+ };
+ expect(actionCreators.createContribution.request()).toEqual(expectedAction);
+ });
+ it('create contribution success', () => {
+ const expectedAction = {
+ type: actionTypes.CREATE_CONTRIBUTION.SUCCESS,
+ };
+ expect(actionCreators.createContribution.success()).toEqual(expectedAction);
+ });
+ it('create contribution failure', () => {
+ const expectedAction = {
+ type: actionTypes.CREATE_CONTRIBUTION.FAILURE,
+ };
+ expect(actionCreators.createContribution.failure()).toEqual(expectedAction);
+ });
+});
+
+let govAdminToken;
+let campaignAdminToken;
+let campaignStaffToken;
+let governmentId;
+let campaignId;
+let campaignStaffId;
+let campaignAdminId;
+describe('Side Effects', () => {
+ beforeAll(async () => {
+ let tokenResponse = await api.login(
+ 'govadmin@openelectionsportland.org',
+ 'password'
+ );
+ govAdminToken = tokenResponse.headers
+ .get('set-cookie')
+ .match(/=([a-zA-Z0-9].+); Path/)[1];
+ let decodedToken = api.decodeToken(govAdminToken);
+ governmentId = decodedToken.permissions[0].governmentId;
+
+ tokenResponse = await api.login(
+ 'campaignadmin@openelectionsportland.org',
+ 'password'
+ );
+ campaignAdminToken = tokenResponse.headers
+ .get('set-cookie')
+ .match(/=([a-zA-Z0-9].+); Path/)[1];
+ decodedToken = api.decodeToken(campaignAdminToken);
+ campaignId = decodedToken.permissions[0].campaignId;
+
+ campaignAdminId = decodedToken.id;
+
+ tokenResponse = await api.login(
+ 'campaignstaff@openelectionsportland.org',
+ 'password'
+ );
+ campaignStaffToken = tokenResponse.headers
+ .get('set-cookie')
+ .match(/=([a-zA-Z0-9].+); Path/)[1];
+ decodedToken = api.decodeToken(campaignStaffToken);
+ campaignStaffId = decodedToken.id;
+ });
+
+ beforeEach(() => {
+ delete process.env.TOKEN;
+ });
+
+ it('creates contribution', async () => {
+ const expectedActions = [
+ { type: actionTypes.CREATE_CONTRIBUTION.REQUEST },
+ { type: ADD_CONTRIBUTION_ENTITIES },
+ { type: actionTypes.CREATE_CONTRIBUTION.SUCCESS },
+ ];
+ const store = mockStore({});
+
+ process.env.TOKEN = campaignStaffToken;
+ return store
+ .dispatch(
+ contributions.createContribution({
+ address1: '123 ABC ST',
+ amount: 250,
+ campaignId,
+ city: 'Portland',
+ currentUserId: campaignStaffId,
+ date: 1562436237619,
+ firstName: 'John',
+ middleInitial: '',
+ lastName: 'Doe',
+ governmentId,
+ type: api.ContributionTypeEnum.CONTRIBUTION,
+ subType: api.ContributionSubTypeEnum.CASH,
+ paymentMethod: api.PaymentMethodEnum.CASH,
+ state: 'OR',
+ status: api.ContributionStatusEnum.DRAFT,
+ zip: '97214',
+ contributorType: api.ContributorTypeEnum.INDIVIDUAL,
+ })
+ )
+ .then(() => {
+ const actions = store.getActions();
+ expect(actions[0].type).toEqual(expectedActions[0].type);
+ expect(actions[1].type).toEqual(expectedActions[1].type);
+ expect(actions[2].type).toEqual(expectedActions[2].type);
+ });
+ });
+
+ it('updates contribution', async () => {
+ const expectedActions = [
+ { type: actionTypes.UPDATE_CONTRIBUTION.REQUEST },
+ { type: actionTypes.UPDATE_CONTRIBUTION.SUCCESS },
+ ];
+ const store = mockStore({});
+
+ process.env.TOKEN = campaignAdminToken;
+
+ const contribution = await api.createContribution({
+ address1: '123 ABC ST',
+ amount: 250,
+ campaignId,
+ city: 'Portland',
+ currentUserId: campaignAdminId,
+ date: 1562436237619,
+ firstName: 'John',
+ middleInitial: '',
+ lastName: 'Doe',
+ governmentId,
+ type: api.ContributionTypeEnum.CONTRIBUTION,
+ subType: api.ContributionSubTypeEnum.CASH,
+ paymentMethod: api.PaymentMethodEnum.CASH,
+ state: 'OR',
+ status: api.ContributionStatusEnum.DRAFT,
+ zip: '97214',
+ contributorType: api.ContributorTypeEnum.INDIVIDUAL,
+ });
+ const { id } = await contribution.json();
+
+ return store
+ .dispatch(
+ contributions.updateContribution({
+ id,
+ firstName: 'Ian',
+ currentUserId: campaignAdminId,
+ })
+ )
+ .then(() => {
+ const actions = store.getActions();
+ expect(actions[0].type).toEqual(expectedActions[0].type);
+ expect(actions[1].type).toEqual(expectedActions[1].type);
+ });
+ });
+
+ it('gets contributions', async () => {
+ const expectedActions = [
+ { type: actionTypes.GET_CONTRIBUTIONS.REQUEST },
+ { type: ADD_CONTRIBUTION_ENTITIES },
+ { type: actionTypes.GET_CONTRIBUTIONS.SUCCESS },
+ ];
+ const store = mockStore({});
+
+ process.env.TOKEN = campaignAdminToken;
+
+ return store
+ .dispatch(
+ contributions.getContributions({
+ governmentId,
+ campaignId,
+ currentUserId: campaignAdminId,
+ })
+ )
+ .then(() => {
+ const actions = store.getActions();
+ expect(actions[0].type).toEqual(expectedActions[0].type);
+ expect(actions[1].type).toEqual(expectedActions[1].type);
+ expect(actions[2].type).toEqual(expectedActions[2].type);
+ });
+ });
+
+ it('gets contribution by id', async () => {
+ const expectedActions = [
+ { type: actionTypes.GET_CONTRIBUTION_BY_ID.REQUEST },
+ { type: ADD_CONTRIBUTION_ENTITIES },
+ { type: actionTypes.GET_CONTRIBUTION_BY_ID.SUCCESS },
+ ];
+ const store = mockStore({});
+
+ process.env.TOKEN = campaignAdminToken;
+
+ const contribution = await api.createContribution({
+ address1: '123 ABC ST',
+ amount: 250,
+ campaignId,
+ city: 'Portland',
+ currentUserId: campaignAdminId,
+ date: 1562436237619,
+ firstName: 'John',
+ middleInitial: '',
+ lastName: 'Doe',
+ governmentId,
+ type: api.ContributionTypeEnum.CONTRIBUTION,
+ subType: api.ContributionSubTypeEnum.CASH,
+ paymentMethod: api.PaymentMethodEnum.CASH,
+ state: 'OR',
+ status: api.ContributionStatusEnum.DRAFT,
+ zip: '97214',
+ contributorType: api.ContributorTypeEnum.INDIVIDUAL,
+ });
+ const { id } = await contribution.json();
+
+ return store.dispatch(contributions.getContributionById(id)).then(() => {
+ const actions = store.getActions();
+ expect(actions[0].type).toEqual(expectedActions[0].type);
+ expect(actions[1].type).toEqual(expectedActions[1].type);
+ expect(actions[2].type).toEqual(expectedActions[2].type);
+ });
+ });
+
+ it('archives contribution by id', async () => {
+ const expectedActions = [
+ { type: actionTypes.ARCHIVE_CONTRIBUTION.REQUEST },
+ { type: ADD_CONTRIBUTION_ENTITIES },
+ { type: actionTypes.ARCHIVE_CONTRIBUTION.SUCCESS },
+ ];
+ const store = mockStore({});
+
+ process.env.TOKEN = campaignAdminToken;
+
+ const contribution = await api.createContribution({
+ address1: '123 ABC ST',
+ amount: 250,
+ campaignId,
+ city: 'Portland',
+ currentUserId: campaignAdminId,
+ date: 1562436237619,
+ firstName: 'John',
+ middleInitial: '',
+ lastName: 'Doe',
+ governmentId,
+ type: api.ContributionTypeEnum.CONTRIBUTION,
+ subType: api.ContributionSubTypeEnum.CASH,
+ paymentMethod: api.PaymentMethodEnum.CASH,
+ state: 'OR',
+ status: api.ContributionStatusEnum.DRAFT,
+ zip: '97214',
+ contributorType: api.ContributorTypeEnum.INDIVIDUAL,
+ });
+ const { id } = await contribution.json();
+
+ return store.dispatch(contributions.archiveContribution(id)).then(() => {
+ const actions = store.getActions();
+ expect(actions[0].type).toEqual(expectedActions[0].type);
+ expect(actions[1].type).toEqual(expectedActions[1].type);
+ expect(actions[2].type).toEqual(expectedActions[2].type);
+ });
+ });
+
+ xit('post comments', async () => {
+ const expectedActions = [
+ { type: actionTypes.POST_CONTRIBUTION_COMMENT.REQUEST },
+ { type: activities.actionTypes.GET_CONTRIBUTION_ACTIVITIES.REQUEST },
+ { type: actionTypes.POST_CONTRIBUTION_COMMENT.SUCCESS },
+ ];
+ const store = mockStore({});
+
+ process.env.TOKEN = campaignAdminToken;
+
+ const contribution = await api.createContribution({
+ address1: '123 ABC ST',
+ amount: 250,
+ campaignId,
+ city: 'Portland',
+ currentUserId: campaignAdminId,
+ date: 1562436237619,
+ firstName: 'John',
+ middleInitial: '',
+ lastName: 'Doe',
+ governmentId,
+ type: api.ContributionTypeEnum.CONTRIBUTION,
+ subType: api.ContributionSubTypeEnum.CASH,
+ paymentMethod: api.PaymentMethodEnum.CASH,
+ state: 'OR',
+ status: api.ContributionStatusEnum.DRAFT,
+ zip: '97214',
+ contributorType: api.ContributorTypeEnum.INDIVIDUAL,
+ });
+ const { id } = await contribution.json();
+
+ return store
+ .dispatch(contributions.postContributionComment(id, 'This is a comment'))
+ .then(() => {
+ const actions = store.getActions();
+ expect(actions.length).toEqual(3);
+ expect(actions[0].type).toEqual(expectedActions[0].type);
+ expect(actions[1].type).toEqual(expectedActions[1].type);
+ expect(actions[2].type).toEqual(expectedActions[2].type);
+ });
+ });
+});
diff --git a/app2/src/state/ducks/expenditures.js b/app2/src/state/ducks/expenditures.js
new file mode 100644
index 000000000..bcec51bdf
--- /dev/null
+++ b/app2/src/state/ducks/expenditures.js
@@ -0,0 +1,389 @@
+/* eslint-disable no-unused-vars */
+// campaigns.js
+import { normalize } from 'normalizr';
+import { createSelector } from 'reselect';
+import { isEmpty } from 'lodash';
+import { flashMessage } from 'redux-flash';
+import { push } from 'connected-react-router';
+import createReducer from '../utils/createReducer';
+import createActionTypes, {
+ createCustomActionTypes,
+} from '../utils/createActionTypes';
+import action from '../utils/action';
+import {
+ addExpenditureEntities,
+ ADD_EXPENDITURE_ENTITIES,
+ resetState,
+ RESET_STATE,
+} from './common';
+import { downloadFile } from '../utils/helpers';
+import { getActivitiesByIdType } from './activities';
+
+export const STATE_KEY = 'expenditures';
+
+// Action Types
+export const actionTypes = {
+ CREATE_EXPENDITURE: createActionTypes(STATE_KEY, 'CREATE_EXPENDITURE'),
+ UPDATE_EXPENDITURE: createActionTypes(STATE_KEY, 'UPDATE_EXPENDITURE'),
+ GET_EXPENDITURES: createActionTypes(STATE_KEY, 'GET_EXPENDITURES'),
+ GET_EXPENDITURE_BY_ID: createActionTypes(STATE_KEY, 'GET_EXPENDITURE_BY_ID'),
+ POST_EXPENDITURE_COMMENT: createActionTypes(
+ STATE_KEY,
+ 'POST_EXPENDITURE_COMMENT'
+ ),
+ FILTER: createCustomActionTypes(STATE_KEY, 'FILTER', ['UPDATE']),
+};
+
+// Initial State
+export const initialState = {
+ isLoading: false,
+ error: null,
+ list: null,
+ listFilterOptions: {
+ from: '',
+ to: '',
+ status: 'all',
+ page: 0,
+ perPage: 50,
+ sort: {},
+ },
+ listOrder: [],
+ currentId: null,
+ total: 0,
+};
+
+export const resetExpenditureState = resetState;
+// Reducer
+export default createReducer(initialState, {
+ [RESET_STATE]: () => {
+ return { ...initialState };
+ },
+ [ADD_EXPENDITURE_ENTITIES]: (state, action) => {
+ return {
+ ...state,
+ list: { ...action.payload.entities.expenditures },
+ listOrder: action.payload.result,
+ };
+ },
+ [actionTypes.CREATE_EXPENDITURE.REQUEST]: (state, action) => {
+ return { ...state, isLoading: true };
+ },
+ [actionTypes.CREATE_EXPENDITURE.SUCCESS]: (state, action) => {
+ return { ...state, isLoading: false };
+ },
+ [actionTypes.CREATE_EXPENDITURE.FAILURE]: (state, action) => {
+ return { ...state, isLoading: false, error: action.error };
+ },
+ [actionTypes.UPDATE_EXPENDITURE.REQUEST]: (state, action) => {
+ return { ...state, isLoading: true };
+ },
+ [actionTypes.UPDATE_EXPENDITURE.SUCCESS]: (state, action) => {
+ return { ...state, isLoading: false };
+ },
+ [actionTypes.UPDATE_EXPENDITURE.FAILURE]: (state, action) => {
+ return { ...state, isLoading: false, error: action.error };
+ },
+ [actionTypes.GET_EXPENDITURES.REQUEST]: (state, action) => {
+ return { ...state, isLoading: true };
+ },
+ [actionTypes.GET_EXPENDITURES.SUCCESS]: (state, action) => {
+ return { ...state, isLoading: false, total: action.total };
+ },
+ [actionTypes.GET_EXPENDITURES.FAILURE]: (state, action) => {
+ return { ...state, isLoading: false, error: action.error };
+ },
+ [actionTypes.GET_EXPENDITURE_BY_ID.REQUEST]: (state, action) => {
+ return { ...state, isLoading: true };
+ },
+ [actionTypes.GET_EXPENDITURE_BY_ID.SUCCESS]: (state, action) => {
+ return {
+ ...state,
+ isLoading: false,
+ currentId: action.id,
+ };
+ },
+ [actionTypes.GET_EXPENDITURE_BY_ID.FAILURE]: (state, action) => {
+ return { ...state, isLoading: false, error: action.error };
+ },
+ [actionTypes.POST_EXPENDITURE_COMMENT.REQUEST]: state => {
+ return { ...state, isLoading: true };
+ },
+ [actionTypes.POST_EXPENDITURE_COMMENT.SUCCESS]: state => {
+ return { ...state, isLoading: false };
+ },
+ [actionTypes.POST_EXPENDITURE_COMMENT.FAILURE]: (state, action) => {
+ return { ...state, isLoading: false, error: action.error };
+ },
+ [actionTypes.FILTER.UPDATE]: (state, action) => {
+ return { ...state, listFilterOptions: action.listFilterOptions };
+ },
+});
+
+// Action Creators
+export const actionCreators = {
+ createExpenditure: {
+ request: () => action(actionTypes.CREATE_EXPENDITURE.REQUEST),
+ success: () => action(actionTypes.CREATE_EXPENDITURE.SUCCESS),
+ failure: error => action(actionTypes.CREATE_EXPENDITURE.FAILURE, { error }),
+ },
+ updateExpenditure: {
+ request: () => action(actionTypes.UPDATE_EXPENDITURE.REQUEST),
+ success: () => action(actionTypes.UPDATE_EXPENDITURE.SUCCESS),
+ failure: error => action(actionTypes.UPDATE_EXPENDITURE.FAILURE, { error }),
+ },
+ getExpenditures: {
+ request: () => action(actionTypes.GET_EXPENDITURES.REQUEST),
+ success: total => action(actionTypes.GET_EXPENDITURES.SUCCESS, { total }),
+ failure: error => action(actionTypes.GET_EXPENDITURES.FAILURE, { error }),
+ },
+ getExpenditureById: {
+ request: () => action(actionTypes.GET_EXPENDITURE_BY_ID.REQUEST),
+ success: id => action(actionTypes.GET_EXPENDITURE_BY_ID.SUCCESS, { id }),
+ failure: error =>
+ action(actionTypes.GET_EXPENDITURE_BY_ID.FAILURE, { error }),
+ },
+ postExpenditureComment: {
+ request: () => action(actionTypes.POST_EXPENDITURE_COMMENT.REQUEST),
+ success: () => action(actionTypes.POST_EXPENDITURE_COMMENT.SUCCESS),
+ failure: error =>
+ action(actionTypes.POST_EXPENDITURE_COMMENT.FAILURE, { error }),
+ },
+ filter: {
+ update: listFilterOptions => {
+ return action(actionTypes.FILTER.UPDATE, { listFilterOptions });
+ },
+ },
+};
+
+export function updateFilter(newFilterOptions) {
+ return (dispatch, getState) => {
+ // eslint-disable-next-line prefer-const
+ let filterOptions = getState().expenditures.listFilterOptions;
+ if (newFilterOptions.perPage) {
+ filterOptions.page = Math.floor(
+ (filterOptions.page * filterOptions.perPage) / newFilterOptions.perPage
+ );
+ }
+ Object.entries(filterOptions).forEach(([key, value]) => {
+ if (Object.prototype.hasOwnProperty.call(newFilterOptions, key))
+ filterOptions[key] = newFilterOptions[key];
+ });
+ dispatch(actionCreators.filter.update(filterOptions));
+ };
+}
+
+export const getFilterOptionsForRequest = state => {
+ const filter = state.expenditures.listFilterOptions;
+ const sort = state.expenditures.listFilterOptions.sort || {};
+ const returnObj = {};
+
+ Object.entries(filter).forEach(([key, value]) => {
+ // Look for any filters such as status
+ if (value) {
+ returnObj[key] = value;
+ }
+ });
+ if (sort.field) {
+ // If the sort field is set make sure there is also a direction
+ returnObj.sort = {
+ field: sort.field,
+ direction: sort.direction || 'DESC',
+ };
+ } else {
+ // Remove sort if there isn't any, defauts to last modified DESC
+ delete returnObj.sort;
+ }
+
+ // API defaults to all statuses but all is not a status
+ if (returnObj.status === 'all') delete returnObj.status;
+
+ // Always pass in the pagination to maintain sync with table
+ returnObj.perPage = filter.perPage;
+ returnObj.page = filter.page * filter.perPage;
+ return returnObj;
+};
+
+// Side Effects, e.g. thunks
+export function createExpenditure(expenditureAttrs) {
+ return async (dispatch, getState, { api, schema }) => {
+ dispatch(actionCreators.createExpenditure.request());
+ try {
+ const response = await api.createExpenditure(expenditureAttrs);
+ if (response.status === 201) {
+ const data = normalize(await response.json(), schema.expenditure);
+ dispatch(addExpenditureEntities(data));
+ dispatch(actionCreators.createExpenditure.success());
+ dispatch(
+ flashMessage(`Expenditure Added`, {
+ props: { variant: 'success' },
+ })
+ );
+ return data.result;
+ }
+ dispatch(actionCreators.createExpenditure.failure());
+ dispatch(
+ flashMessage(`Error - ${response.status} status returned`, {
+ props: { variant: 'error' },
+ })
+ );
+ } catch (error) {
+ dispatch(actionCreators.createExpenditure.failure(error));
+ dispatch(
+ flashMessage(`Error - ${error}`, { props: { variant: 'error' } })
+ );
+ }
+ };
+}
+
+export function updateExpenditure(expenditureAttrs) {
+ return async (dispatch, getState, { api, schema }) => {
+ dispatch(actionCreators.updateExpenditure.request());
+ try {
+ const response = await api.updateExpenditure(expenditureAttrs);
+ if (response.status === 204) {
+ let status = '';
+ if (expenditureAttrs.status) {
+ status = expenditureAttrs.status;
+ }
+ dispatch(actionCreators.updateExpenditure.success());
+ dispatch(
+ flashMessage(`Expenditure Updated ${status}`, {
+ props: { variant: 'success' },
+ })
+ );
+ dispatch(push('/expenses'));
+ } else {
+ dispatch(actionCreators.updateExpenditure.failure());
+ const error = await response.json();
+ dispatch(
+ flashMessage(`Error - ${error}`, { props: { variant: 'error' } })
+ );
+ return error;
+ }
+ } catch (error) {
+ dispatch(actionCreators.updateExpenditure.failure(error));
+ dispatch(
+ flashMessage(`Error - ${error}`, { props: { variant: 'error' } })
+ );
+ return error;
+ }
+ };
+}
+
+export function getExpenditures(expenditureSearchAttrs, applyFilter = false) {
+ return async (dispatch, getState, { api, schema }) => {
+ dispatch(actionCreators.getExpenditures.request());
+ try {
+ const filter = applyFilter ? getFilterOptionsForRequest(getState()) : {};
+ const response = await api.getExpenditures({
+ ...expenditureSearchAttrs,
+ ...filter,
+ });
+ if (expenditureSearchAttrs.format === 'csv' && response.status === 200) {
+ const expenditures = await response.text();
+ downloadFile(expenditures, `expenditures-download-${Date.now()}.csv`);
+ } else if (
+ expenditureSearchAttrs.format === 'xml' &&
+ response.status === 200
+ ) {
+ const expenditures = await response.json();
+ expenditures.map((expenditure, index) => {
+ return downloadFile(
+ expenditure,
+ `expenditures-download-${index + 1}-${Date.now()}.xml`
+ );
+ });
+ } else if (response.status === 200) {
+ const expenses = await response.json();
+ const data = normalize(expenses.data, [schema.expenditure]);
+ dispatch(addExpenditureEntities(data));
+ dispatch(actionCreators.getExpenditures.success(expenses.total));
+ } else {
+ dispatch(actionCreators.getExpenditures.failure());
+ }
+ } catch (error) {
+ dispatch(actionCreators.getExpenditures.failure(error));
+ }
+ };
+}
+
+export function getExpenditureById(id) {
+ return async (dispatch, getState, { api, schema }) => {
+ dispatch(actionCreators.getExpenditureById.request());
+ try {
+ const response = await api.getExpenditureById(id);
+ if (response.status === 200) {
+ const data = normalize(await response.json(), schema.expenditure);
+ dispatch(addExpenditureEntities(data));
+ dispatch(actionCreators.getExpenditureById.success(id));
+ } else {
+ dispatch(actionCreators.getExpenditureById.failure());
+ }
+ } catch (error) {
+ dispatch(actionCreators.getExpenditureById.failure(error));
+ }
+ };
+}
+
+export function postExpenditureComment(id, comment, attachment) {
+ return async (dispatch, getState, { api, schema }) => {
+ dispatch(actionCreators.postExpenditureComment.request());
+ try {
+ const response = await api.postExpenditureComment(
+ id,
+ comment,
+ attachment
+ );
+ if (response.status === 204) {
+ dispatch(actionCreators.postExpenditureComment.success());
+ dispatch(getActivitiesByIdType({ expenditureId: id }));
+ } else {
+ dispatch(actionCreators.postExpenditureComment.failure());
+ }
+ } catch (error) {
+ dispatch(actionCreators.postExpenditureComment.failure(error));
+ }
+ };
+}
+
+// Selectors
+export const rootState = state => state || {};
+
+export const getExpendituresList = createSelector(rootState, state => {
+ if (
+ isEmpty(state.expenditures.list) ||
+ isEmpty(state.expenditures.listOrder)
+ ) {
+ return [];
+ }
+ return state.expenditures.listOrder.map(id => state.expenditures.list[id]);
+});
+
+export const getExpendituresTotal = createSelector(rootState, state => {
+ return state.expenditures.total;
+});
+
+export const getCurrentExpenditureId = state => {
+ return state.expenditures &&
+ state.expenditures.list &&
+ state.expenditures.currentId
+ ? state.expenditures.currentId
+ : false;
+};
+
+export const getCurrentExpenditure = state => {
+ return getCurrentExpenditureId(state)
+ ? state.expenditures.list[getCurrentExpenditureId(state)]
+ : false;
+};
+
+export const getExpenditureCampaignName = state => {
+ const expenditure = getCurrentExpenditure(state);
+ return expenditure ? expenditure.campaign.name : null;
+};
+
+export const getFilterOptions = state => {
+ const filter = state.expenditures.listFilterOptions;
+ const sort = state.expenditures.listFilterOptions.sort || {};
+ return { ...filter, sort };
+};
diff --git a/app2/src/state/ducks/expenditures.test.js b/app2/src/state/ducks/expenditures.test.js
new file mode 100644
index 000000000..0e14b8fbd
--- /dev/null
+++ b/app2/src/state/ducks/expenditures.test.js
@@ -0,0 +1,275 @@
+import configureMockStore from 'redux-mock-store';
+import thunk from 'redux-thunk';
+import * as expenditures from './expenditures';
+import * as api from '../../api';
+import * as schema from '../../api/schema';
+import { ADD_EXPENDITURE_ENTITIES } from './common';
+
+const { actionTypes, actionCreators } = expenditures;
+
+const middlewares = [thunk.withExtraArgument({ api, schema })];
+const mockStore = configureMockStore(middlewares);
+
+describe('Reducer', () => {
+ const reducer = expenditures.default;
+ it('initial state', () => {
+ expect(reducer(undefined, {})).toEqual({
+ isLoading: false,
+ error: null,
+ list: null,
+ currentId: null,
+ listOrder: [],
+ total: 0,
+ listFilterOptions: {
+ from: '',
+ to: '',
+ status: 'all',
+ page: 0,
+ perPage: 50,
+ sort: {},
+ },
+ });
+ });
+
+ it('adds expenditure entities', () => {
+ expect(
+ reducer(undefined, {
+ type: ADD_EXPENDITURE_ENTITIES,
+ payload: {
+ entities: {
+ expenditures: {
+ '1': {},
+ },
+ },
+ },
+ })
+ ).toEqual({
+ list: {
+ '1': {},
+ },
+ currentId: null,
+ isLoading: false,
+ error: null,
+ total: 0,
+ listFilterOptions: {
+ from: '',
+ to: '',
+ status: 'all',
+ page: 0,
+ perPage: 50,
+ sort: {},
+ },
+ });
+ });
+});
+
+describe('Action Creators', () => {
+ it('create expenditure request', () => {
+ const expectedAction = {
+ type: actionTypes.CREATE_EXPENDITURE.REQUEST,
+ };
+ expect(actionCreators.createExpenditure.request()).toEqual(expectedAction);
+ });
+ it('create expenditure success', () => {
+ const expectedAction = {
+ type: actionTypes.CREATE_EXPENDITURE.SUCCESS,
+ };
+ expect(actionCreators.createExpenditure.success()).toEqual(expectedAction);
+ });
+ it('create expenditure failure', () => {
+ const expectedAction = {
+ type: actionTypes.CREATE_EXPENDITURE.FAILURE,
+ };
+ expect(actionCreators.createExpenditure.failure()).toEqual(expectedAction);
+ });
+});
+
+let govAdminToken;
+let campaignAdminToken;
+let campaignStaffToken;
+let governmentId;
+let campaignId;
+let campaignStaffId;
+let campaignAdminId;
+describe('Side Effects', () => {
+ beforeAll(async () => {
+ let tokenResponse = await api.login(
+ 'govadmin@openelectionsportland.org',
+ 'password'
+ );
+ govAdminToken = tokenResponse.headers
+ .get('set-cookie')
+ .match(/=([a-zA-Z0-9].+); Path/)[1];
+ let decodedToken = api.decodeToken(govAdminToken);
+ governmentId = decodedToken.permissions[0].governmentId;
+
+ tokenResponse = await api.login(
+ 'campaignadmin@openelectionsportland.org',
+ 'password'
+ );
+ campaignAdminToken = tokenResponse.headers
+ .get('set-cookie')
+ .match(/=([a-zA-Z0-9].+); Path/)[1];
+ decodedToken = api.decodeToken(campaignAdminToken);
+ campaignId = decodedToken.permissions[0].campaignId;
+
+ campaignAdminId = decodedToken.id;
+
+ tokenResponse = await api.login(
+ 'campaignstaff@openelectionsportland.org',
+ 'password'
+ );
+ campaignStaffToken = tokenResponse.headers
+ .get('set-cookie')
+ .match(/=([a-zA-Z0-9].+); Path/)[1];
+ decodedToken = api.decodeToken(campaignStaffToken);
+ campaignStaffId = decodedToken.id;
+ });
+
+ beforeEach(() => {
+ delete process.env.TOKEN;
+ });
+
+ it('creates expenditure testme', async () => {
+ const expectedActions = [
+ { type: actionTypes.CREATE_EXPENDITURE.REQUEST },
+ { type: ADD_EXPENDITURE_ENTITIES },
+ { type: actionTypes.CREATE_EXPENDITURE.SUCCESS },
+ ];
+ const store = mockStore({});
+
+ process.env.TOKEN = campaignStaffToken;
+ return store
+ .dispatch(
+ expenditures.createExpenditure({
+ address1: '123 ABC ST',
+ amount: 250,
+ campaignId,
+ city: 'Portland',
+ currentUserId: campaignStaffId,
+ date: 1565060230243,
+ governmentId,
+ type: api.ExpenditureTypeEnum.EXPENDITURE,
+ subType: api.ExpenditureSubTypeEnum.CASH_EXPENDITURE,
+ state: 'OR',
+ status: api.ExpenditureStatusEnum.DRAFT,
+ zip: '97214',
+ payeeType: api.PayeeTypeEnum.INDIVIDUAL,
+ name: 'Test Expenditure',
+ description: 'This is a test',
+ })
+ )
+ .then(() => {
+ const actions = store.getActions();
+ expect(actions[0].type).toEqual(expectedActions[0].type);
+ expect(actions[1].type).toEqual(expectedActions[1].type);
+ expect(actions[2].type).toEqual(expectedActions[2].type);
+ });
+ });
+
+ it('gets expenditures', async () => {
+ const expectedActions = [
+ { type: actionTypes.GET_EXPENDITURES.REQUEST },
+ { type: ADD_EXPENDITURE_ENTITIES },
+ { type: actionTypes.GET_EXPENDITURES.SUCCESS },
+ ];
+ const store = mockStore({});
+
+ process.env.TOKEN = campaignAdminToken;
+
+ return store
+ .dispatch(
+ expenditures.getExpenditures({
+ governmentId,
+ campaignId,
+ currentUserId: campaignAdminId,
+ })
+ )
+ .then(() => {
+ const actions = store.getActions();
+ expect(actions[0].type).toEqual(expectedActions[0].type);
+ expect(actions[1].type).toEqual(expectedActions[1].type);
+ expect(actions[2].type).toEqual(expectedActions[2].type);
+ });
+ });
+
+ it('updates expenditure', async () => {
+ const expectedActions = [
+ { type: actionTypes.UPDATE_EXPENDITURE.REQUEST },
+ { type: actionTypes.UPDATE_EXPENDITURE.SUCCESS },
+ ];
+ const store = mockStore({});
+
+ process.env.TOKEN = campaignAdminToken;
+
+ const expenditure = await api.createExpenditure({
+ address1: '123 ABC ST',
+ amount: 250,
+ campaignId,
+ city: 'Portland',
+ currentUserId: campaignStaffId,
+ date: 1564881802534,
+ governmentId,
+ type: api.ExpenditureTypeEnum.EXPENDITURE,
+ subType: api.ExpenditureSubTypeEnum.CASH_EXPENDITURE,
+ state: 'OR',
+ status: api.ExpenditureStatusEnum.DRAFT,
+ zip: '97214',
+ payeeType: api.PayeeTypeEnum.INDIVIDUAL,
+ name: 'Test Expenditure',
+ description: 'This is a test',
+ });
+ const { id } = await expenditure.json();
+
+ return store
+ .dispatch(
+ expenditures.updateExpenditure({
+ id,
+ amount: 500,
+ currentUserId: campaignAdminId,
+ })
+ )
+ .then(() => {
+ const actions = store.getActions();
+ expect(actions[0].type).toEqual(expectedActions[0].type);
+ expect(actions[1].type).toEqual(expectedActions[1].type);
+ });
+ });
+
+ it('gets expenditure', async () => {
+ const expectedActions = [
+ { type: actionTypes.GET_EXPENDITURE_BY_ID.REQUEST },
+ { type: ADD_EXPENDITURE_ENTITIES },
+ { type: actionTypes.GET_EXPENDITURE_BY_ID.SUCCESS },
+ ];
+ const store = mockStore({});
+
+ process.env.TOKEN = campaignAdminToken;
+
+ const expenditure = await api.createExpenditure({
+ address1: '123 ABC ST',
+ amount: 250,
+ campaignId,
+ city: 'Portland',
+ currentUserId: campaignStaffId,
+ date: 1564881802534,
+ governmentId,
+ type: api.ExpenditureTypeEnum.EXPENDITURE,
+ subType: api.ExpenditureSubTypeEnum.CASH_EXPENDITURE,
+ state: 'OR',
+ status: api.ExpenditureStatusEnum.DRAFT,
+ zip: '97214',
+ payeeType: api.PayeeTypeEnum.INDIVIDUAL,
+ name: 'Test Expenditure',
+ description: 'This is a test',
+ });
+ const { id } = await expenditure.json();
+
+ return store.dispatch(expenditures.getExpenditureById(id)).then(() => {
+ const actions = store.getActions();
+ expect(actions[0].type).toEqual(expectedActions[0].type);
+ expect(actions[1].type).toEqual(expectedActions[1].type);
+ expect(actions[2].type).toEqual(expectedActions[2].type);
+ });
+ });
+});
diff --git a/app2/src/state/ducks/externalData.js b/app2/src/state/ducks/externalData.js
new file mode 100644
index 000000000..fdc22675c
--- /dev/null
+++ b/app2/src/state/ducks/externalData.js
@@ -0,0 +1,64 @@
+import createActionTypes from '../utils/createActionTypes';
+import createReducer from '../utils/createReducer';
+import action from '../utils/action';
+import { RESET_STATE } from './common';
+
+export const STATE_KEY = 'externalData';
+// Action Types
+export const actionTypes = {
+ GET_EXTERNAL_DATA: createActionTypes(STATE_KEY, 'GET_EXTERNAL_DATA'),
+};
+
+// Initial State
+export const initialState = {
+ data: {
+ type: 'FeatureCollection',
+ features: [],
+ },
+ isLoading: false,
+ error: null,
+};
+
+// Reducer
+export default createReducer(initialState, {
+ [RESET_STATE]: () => {
+ return { ...initialState };
+ },
+ [actionTypes.GET_EXTERNAL_DATA.REQUEST]: state => {
+ return { ...state, isLoading: true };
+ },
+ [actionTypes.GET_EXTERNAL_DATA.SUCCESS]: (state, action) => {
+ return {
+ ...state,
+ isLoading: false,
+ data: action.payload,
+ timeLoaded: new Date(),
+ };
+ },
+ [actionTypes.GET_EXTERNAL_DATA.FAILURE]: (state, action) => {
+ return { ...state, isLoading: false, error: action.error };
+ },
+});
+
+// Action Creators
+export const actionCreators = {
+ getExternalData: {
+ request: () => action(actionTypes.GET_EXTERNAL_DATA.REQUEST),
+ success: payload =>
+ action(actionTypes.GET_EXTERNAL_DATA.SUCCESS, { payload }),
+ failure: error => action(actionTypes.GET_EXTERNAL_DATA.FAILURE, { error }),
+ },
+};
+
+// Side Effects, e.g. thunks
+export function getExternalData() {
+ return async (dispatch, _getState, { api }) => {
+ dispatch(actionCreators.getExternalData.request());
+ try {
+ const response = await api.getExternalContributionGeoData();
+ dispatch(actionCreators.getExternalData.success(response));
+ } catch (error) {
+ dispatch(actionCreators.getExternalData.failure(error));
+ }
+ };
+}
diff --git a/app2/src/state/ducks/governments.js b/app2/src/state/ducks/governments.js
new file mode 100644
index 000000000..f181d2af6
--- /dev/null
+++ b/app2/src/state/ducks/governments.js
@@ -0,0 +1,58 @@
+// governments.js
+import createReducer from '../utils/createReducer';
+import { ADD_ENTITIES, resetState, RESET_STATE } from './common';
+import createActionTypes from '../utils/createActionTypes';
+import action from '../utils/action';
+
+export const STATE_KEY = 'governments';
+
+export const actionTypes = {
+ SET_GOVERNMENT: createActionTypes(STATE_KEY, 'SET_GOVERNMENT'),
+};
+
+// Action Types
+
+// Initial State
+export const initialState = {
+ isLoading: false,
+ error: null,
+ currentGovernmentId: null,
+};
+
+export const resetGovernmentState = resetState;
+// Reducer
+export default createReducer(initialState, {
+ [RESET_STATE]: () => {
+ return { ...initialState };
+ },
+ [ADD_ENTITIES]: (state, action) => {
+ return { ...state, ...action.payload.governments };
+ },
+ [actionTypes.SET_GOVERNMENT.SUCCESS]: (state, action) => {
+ return { ...state, currentGovernmentId: action.governmentId };
+ },
+});
+
+// Action Creators
+
+export const actionCreators = {
+ setGovernment: {
+ success: governmentId =>
+ action(actionTypes.SET_GOVERNMENT.SUCCESS, { governmentId }),
+ },
+};
+
+// Side Effects, e.g. thunks
+
+// Selectors
+export const rootState = state => state || {};
+
+// TODO: Remove default gov id to 1
+export const getCurrentGovernmentId = state => {
+ if (state.governments && state.governments.currentGovernmentId) {
+ return state.governments.currentGovernmentId !== null
+ ? state.governments.currentGovernmentId
+ : 1;
+ }
+ return 1;
+};
diff --git a/app2/src/state/ducks/governments.test.js b/app2/src/state/ducks/governments.test.js
new file mode 100644
index 000000000..e5a442926
--- /dev/null
+++ b/app2/src/state/ducks/governments.test.js
@@ -0,0 +1,37 @@
+import * as governments from './governments';
+
+const { actionTypes, actionCreators } = governments;
+
+describe('Reducer', () => {
+ const reducer = governments.default;
+
+ it('sets current government', () => {
+ expect(
+ reducer(
+ {
+ currentGovernmentId: null,
+ isLoading: false,
+ error: null,
+ },
+ {
+ type: actionTypes.SET_GOVERNMENT.SUCCESS,
+ governmentId: 1,
+ }
+ )
+ ).toEqual({
+ currentGovernmentId: 1,
+ isLoading: false,
+ error: null,
+ });
+ });
+});
+
+describe('Action Creators', () => {
+ it('set government success', () => {
+ const expectedAction = {
+ type: actionTypes.SET_GOVERNMENT.SUCCESS,
+ governmentId: 1,
+ };
+ expect(actionCreators.setGovernment.success(1)).toEqual(expectedAction);
+ });
+});
diff --git a/app2/src/state/ducks/matches.js b/app2/src/state/ducks/matches.js
new file mode 100644
index 000000000..30a135e8d
--- /dev/null
+++ b/app2/src/state/ducks/matches.js
@@ -0,0 +1,191 @@
+/* eslint-disable no-unused-vars */
+import { cloneDeep } from 'lodash';
+import { flashMessage } from 'redux-flash';
+import createReducer from '../utils/createReducer';
+import { RESET_STATE } from './common';
+import createActionTypes from '../utils/createActionTypes';
+import action from '../utils/action';
+import { getContributionById, getCurrentContribution } from './contributions';
+
+export const STATE_KEY = 'matches';
+
+// Action Types
+export const actionTypes = {
+ GET_MATCHES_BY_CONTRIBUTION_ID: createActionTypes(
+ STATE_KEY,
+ 'GET_MATCHES_BY_CONTRIBUTION_ID'
+ ),
+ UPDATE_MATCH_ID: createActionTypes(STATE_KEY, 'UPDATE_MATCH_ID'),
+};
+
+// Initial State
+export const initialState = {
+ isLoading: false,
+ error: null,
+ list: {},
+};
+
+// Reducer
+export default createReducer(initialState, {
+ [RESET_STATE]: () => {
+ return { ...initialState };
+ },
+ [actionTypes.GET_MATCHES_BY_CONTRIBUTION_ID.REQUEST]: (state, action) => {
+ return { ...state, isLoading: true };
+ },
+ [actionTypes.GET_MATCHES_BY_CONTRIBUTION_ID.SUCCESS]: (state, action) => {
+ const newState = cloneDeep(state);
+ const match = action.match;
+ newState.list[match.id] = match;
+ return { ...state, isLoading: false, list: newState.list };
+ },
+ [actionTypes.GET_MATCHES_BY_CONTRIBUTION_ID.FAILURE]: (state, action) => {
+ return { ...state, isLoading: false, error: action.error };
+ },
+ [actionTypes.UPDATE_MATCH_ID.REQUEST]: (state, action) => {
+ return { ...state, isLoading: true };
+ },
+ [actionTypes.UPDATE_MATCH_ID.SUCCESS]: (state, action) => {
+ return { ...state, isLoading: false };
+ },
+ [actionTypes.UPDATE_MATCH_ID.FAILURE]: (state, action) => {
+ return { ...state, isLoading: false, error: action.error };
+ },
+});
+
+// Action Creators
+
+export const actionCreators = {
+ getMatchesByContributionId: {
+ request: () => action(actionTypes.GET_MATCHES_BY_CONTRIBUTION_ID.REQUEST),
+ success: match =>
+ action(actionTypes.GET_MATCHES_BY_CONTRIBUTION_ID.SUCCESS, { match }),
+ failure: error =>
+ action(actionTypes.GET_MATCHES_BY_CONTRIBUTION_ID.FAILURE, { error }),
+ },
+ updateMatchForContribution: {
+ request: () => action(actionTypes.UPDATE_MATCH_ID.REQUEST),
+ success: match => action(actionTypes.UPDATE_MATCH_ID.SUCCESS, { match }),
+ failure: error => action(actionTypes.UPDATE_MATCH_ID.FAILURE, { error }),
+ },
+};
+
+// Side Effects, e.g. thunks
+export function getMatchesByContributionId(contributionId) {
+ return async (dispatch, getState, { api, schema }) => {
+ dispatch(actionCreators.getMatchesByContributionId.request());
+ try {
+ const response = await api.getMatchesByContributionId(contributionId);
+ if (response.status === 200) {
+ const match = await response.json();
+ match.id = contributionId;
+ dispatch(actionCreators.getMatchesByContributionId.success(match));
+ } else {
+ dispatch(actionCreators.getMatchesByContributionId.failure());
+ }
+ } catch (error) {
+ dispatch(actionCreators.getMatchesByContributionId.failure(error));
+ }
+ };
+}
+/*
+@attrs {
+contributionId: number,
+matchId: string,
+matchStrength: enum[exact, strong, weak, none]
+ }
+ */
+export function updateMatchForContribution(attrs) {
+ return async (dispatch, getState, { api, schema }) => {
+ dispatch(actionCreators.updateMatchForContribution.request());
+ try {
+ const response = await api.updateMatchForContribution(attrs);
+ if (response.status === 204 || response.status === 200) {
+ dispatch(getMatchesByContributionId(attrs.contributionId));
+ dispatch(getContributionById(attrs.contributionId));
+ dispatch(
+ flashMessage(`Match Updated`, {
+ props: { variant: 'success' },
+ })
+ );
+ } else {
+ dispatch(actionCreators.updateMatchForContribution.failure());
+ dispatch(
+ flashMessage(`Error - ${response.status} status returned`, {
+ props: { variant: 'error' },
+ })
+ );
+ }
+ } catch (error) {
+ dispatch(actionCreators.updateMatchForContribution.failure(error));
+ flashMessage(`Error - ${error}`, { props: { variant: 'error' } });
+ }
+ };
+}
+
+export const matchStrengthEnum = ['exact', 'strong', 'weak', 'none'];
+export const getCurrentContributionMatch = state => {
+ return state.matches && state.matches.list && state.contributions.currentId
+ ? state.matches.list[state.contributions.currentId]
+ : false;
+};
+
+export const getCurrentMatchResults = state => {
+ const currentMatches = getCurrentContributionMatch(state);
+ const matches = [];
+ const results = currentMatches.results;
+ const currentContribution = getCurrentContribution(state);
+ let match = {};
+ let selectedMatchId = '';
+ if (results) {
+ selectedMatchId = currentContribution ? currentContribution.matchId : '';
+ const matchId = currentMatches.matchId;
+ // Create a easy to traverse structure
+ for (const matchStrength of matchStrengthEnum) {
+ if (
+ results[matchStrength] &&
+ Array.isArray(results[matchStrength]) &&
+ results[matchStrength].length > 0
+ ) {
+ // Pass back camelcase to be pretty happy
+ for (const result of results[matchStrength]) {
+ match = {
+ id: result.id,
+ bestMatch: !!(matchId === result.id),
+ matchStrength,
+ selected: !!(selectedMatchId === result.id),
+ firstName: result.first_name,
+ lastName: result.last_name,
+ address1: result.address_1,
+ address2: result.address_2,
+ city: result.city,
+ state: result.state,
+ zip: result.zip,
+ };
+ // Ensure the selected or best matched result is first
+ if (match.selected || (match.bestMatch && !selectedMatchId)) {
+ matches.unshift(match);
+ } else {
+ matches.push(match);
+ }
+ }
+ }
+ }
+ }
+ if (currentMatches.matchStrength !== 'exact') {
+ if (currentContribution.matchStrength === 'none') {
+ matches.unshift({
+ id: results.none,
+ selected: true,
+ matchStrength: 'none',
+ });
+ } else {
+ matches.push({
+ id: results.none,
+ selected: false,
+ matchStrength: 'none',
+ });
+ }
+ }
+ return matches;
+};
diff --git a/app2/src/state/ducks/modal.js b/app2/src/state/ducks/modal.js
new file mode 100644
index 000000000..e6891aaf1
--- /dev/null
+++ b/app2/src/state/ducks/modal.js
@@ -0,0 +1,67 @@
+/* eslint-disable no-unused-vars */
+import { createSelector } from 'reselect';
+import createReducer from '../utils/createReducer';
+import createAction from '../utils/createAction';
+import action from '../utils/action';
+
+export const STATE_KEY = 'modal';
+
+// Action Types
+export const actionTypes = {
+ SHOW_MODAL: createAction(STATE_KEY, 'SHOW_MODAL'),
+ DISMISS_MODAL: createAction(STATE_KEY, 'DISMISS_MODAL'),
+};
+
+// Initial State
+export const initialState = {
+ currentModal: null,
+ isActive: false,
+ isLoading: false,
+ state: null,
+ error: null,
+};
+
+// Reducer
+export default createReducer(initialState, {
+ [actionTypes.SHOW_MODAL]: (state, action) => {
+ return {
+ ...state,
+ isActive: true,
+ currentModal: action.payload.component,
+ _props: action.payload.props,
+ state: action.payload.state,
+ };
+ },
+ [actionTypes.DISMISS_MODAL]: (state, action) => {
+ return { ...state, isActive: false, currentModal: null, state: null };
+ },
+});
+
+// Action Creators
+export const actionCreators = {
+ showmodal: payload => {
+ return action(actionTypes.SHOW_MODAL, { payload });
+ },
+ dismissmodal: () => action(actionTypes.DISMISS_MODAL),
+};
+
+export function showModal(payload) {
+ return (dispatch, getState) => {
+ dispatch(actionCreators.showmodal(payload));
+ };
+}
+
+export function clearModal() {
+ return (dispatch, getState) => {
+ dispatch(actionCreators.dismissmodal());
+ };
+}
+
+// Selectors
+export const rootState = state => state || {};
+export const getModalState = createSelector(rootState, state => state.modal);
+
+export const modalIsActive = createSelector(
+ rootState,
+ state => state.modal.isActive
+);
diff --git a/app2/src/state/ducks/pastContributions.js b/app2/src/state/ducks/pastContributions.js
new file mode 100644
index 000000000..27b7ae778
--- /dev/null
+++ b/app2/src/state/ducks/pastContributions.js
@@ -0,0 +1,82 @@
+/* eslint-disable no-unused-vars */
+import { cloneDeep } from 'lodash';
+import createReducer from '../utils/createReducer';
+import { RESET_STATE } from './common';
+import createActionTypes from '../utils/createActionTypes';
+import action from '../utils/action';
+
+export const STATE_KEY = 'pastContributions';
+
+// Action Types
+export const actionTypes = {
+ GET_PAST_CONTRIBUTIONS_BY_MATCH_ID: createActionTypes(
+ STATE_KEY,
+ 'GET_PAST_CONTRIBUTIONS_BY_MATCH_ID'
+ ),
+};
+
+// Initial State
+export const initialState = {
+ isLoading: false,
+ error: null,
+ list: {},
+};
+
+// Reducer
+export default createReducer(initialState, {
+ [RESET_STATE]: () => {
+ return { ...initialState };
+ },
+ [actionTypes.GET_PAST_CONTRIBUTIONS_BY_MATCH_ID.REQUEST]: (state, action) => {
+ return { ...state, isLoading: true };
+ },
+ [actionTypes.GET_PAST_CONTRIBUTIONS_BY_MATCH_ID.SUCCESS]: (state, action) => {
+ const newState = cloneDeep(state);
+ const pastContributions = action.pastContributions;
+ newState.list[action.matchId] = pastContributions;
+ return { ...state, isLoading: false, list: newState.list };
+ },
+ [actionTypes.GET_PAST_CONTRIBUTIONS_BY_MATCH_ID.FAILURE]: (state, action) => {
+ return { ...state, isLoading: false, error: action.error };
+ },
+});
+
+// Action Creators
+
+export const actionCreators = {
+ getContributionsByMatchId: {
+ request: () =>
+ action(actionTypes.GET_PAST_CONTRIBUTIONS_BY_MATCH_ID.REQUEST),
+ success: (matchId, pastContributions) =>
+ action(actionTypes.GET_PAST_CONTRIBUTIONS_BY_MATCH_ID.SUCCESS, {
+ matchId,
+ pastContributions,
+ }),
+ failure: error =>
+ action(actionTypes.GET_PAST_CONTRIBUTIONS_BY_MATCH_ID.FAILURE, { error }),
+ },
+};
+
+// Side Effects, e.g. thunks
+export function getContributionsByMatchId(matchId) {
+ return async (dispatch, getState, { api, schema }) => {
+ dispatch(actionCreators.getContributionsByMatchId.request());
+ try {
+ const response = await api.getContributions({ matchId, governmentId: 1 });
+
+ if (response.status === 200) {
+ const contributions = await response.json();
+ dispatch(
+ actionCreators.getContributionsByMatchId.success(
+ matchId,
+ contributions.data
+ )
+ );
+ } else {
+ dispatch(actionCreators.getContributionsByMatchId.failure());
+ }
+ } catch (error) {
+ dispatch(actionCreators.getContributionsByMatchId.failure(error));
+ }
+ };
+}
diff --git a/app2/src/state/ducks/permissions.js b/app2/src/state/ducks/permissions.js
new file mode 100644
index 000000000..c889f4da9
--- /dev/null
+++ b/app2/src/state/ducks/permissions.js
@@ -0,0 +1,49 @@
+/* eslint-disable no-unused-vars */
+import createReducer from '../utils/createReducer';
+import { ADD_ENTITIES, resetState, RESET_STATE } from './common';
+import createActionTypes from '../utils/createActionTypes';
+import action from '../utils/action';
+
+export const STATE_KEY = 'permissions';
+
+// Action Types
+export const actionTypes = {
+ REMOVE_PERMISSION: createActionTypes(STATE_KEY, 'REMOVE_PERMISSION'),
+};
+
+// Initial State
+export const initialState = {
+ isLoading: false,
+ error: null,
+};
+
+export const resetPermissionState = resetState;
+// Reducer
+export default createReducer(initialState, {
+ [RESET_STATE]: () => {
+ return { ...initialState };
+ },
+ [ADD_ENTITIES]: (state, action) => {
+ return { ...state, ...action.payload.permissions };
+ },
+ [actionTypes.REMOVE_PERMISSION.SUCCESS]: (state, action) => {
+ const newState = { ...state, isLoading: false };
+ delete newState[action.permissionId];
+ return newState;
+ },
+});
+
+// Action Creators
+
+export const actionCreators = {
+ removePermission: {
+ success: permissionId =>
+ action(actionTypes.REMOVE_PERMISSION.SUCCESS, { permissionId }),
+ },
+};
+
+// Side Effects, e.g. thunks
+
+export function removePermission(permissionId) {
+ return actionCreators.removePermission.success(permissionId);
+}
diff --git a/app2/src/state/ducks/permissions.test.js b/app2/src/state/ducks/permissions.test.js
new file mode 100644
index 000000000..124981b7e
--- /dev/null
+++ b/app2/src/state/ducks/permissions.test.js
@@ -0,0 +1,84 @@
+/* eslint-disable no-unused-vars */
+import configureMockStore from 'redux-mock-store';
+import thunk from 'redux-thunk';
+import * as permissions from './permissions';
+import * as api from '../../api';
+import * as schema from '../../api/schema';
+import { ADD_ENTITIES } from './common';
+
+const { actionTypes, actionCreators } = permissions;
+
+const middlewares = [thunk.withExtraArgument({ api, schema })];
+const mockStore = configureMockStore(middlewares);
+
+describe('Reducer', () => {
+ const reducer = permissions.default;
+ it('initial state', () => {
+ expect(reducer(undefined, {})).toEqual({
+ isLoading: false,
+ error: null,
+ });
+ });
+
+ it('adds permissions entities', () => {
+ expect(
+ reducer(undefined, {
+ type: ADD_ENTITIES,
+ payload: {
+ permissions: {
+ '1': {
+ userId: 1,
+ campaignId: 1,
+ governmentId: 1,
+ role: 'CAMPAIGN_STAFF',
+ },
+ },
+ },
+ })
+ ).toEqual({
+ '1': {
+ userId: 1,
+ campaignId: 1,
+ governmentId: 1,
+ role: 'CAMPAIGN_STAFF',
+ },
+ isLoading: false,
+ error: null,
+ });
+ });
+
+ it('removes permission entity', () => {
+ expect(
+ reducer(
+ {
+ '1': {
+ userId: 1,
+ campaignId: 1,
+ governmentId: 1,
+ role: 'CAMPAIGN_STAFF',
+ },
+ isLoading: false,
+ error: null,
+ },
+ {
+ type: actionTypes.REMOVE_PERMISSION.SUCCESS,
+ permissionId: 1,
+ error: null,
+ }
+ )
+ ).toEqual({
+ isLoading: false,
+ error: null,
+ });
+ });
+});
+
+describe('Action Creators', () => {
+ it('remove permissions success', () => {
+ const expectedAction = {
+ permissionId: 1,
+ type: actionTypes.REMOVE_PERMISSION.SUCCESS,
+ };
+ expect(actionCreators.removePermission.success(1)).toEqual(expectedAction);
+ });
+});
diff --git a/app2/src/state/ducks/publicData.js b/app2/src/state/ducks/publicData.js
new file mode 100644
index 000000000..3218f5bbd
--- /dev/null
+++ b/app2/src/state/ducks/publicData.js
@@ -0,0 +1,1017 @@
+/* eslint-disable no-unused-vars */
+import { createSelector } from 'reselect';
+import { isAfter, isBefore, isEqual } from 'date-fns';
+import { civicFormat } from '@hackoregon/component-library/dist/utils';
+import { fromPairs } from 'lodash';
+import createReducer from '../utils/createReducer';
+import createActionTypes, {
+ createCustomActionTypes,
+} from '../utils/createActionTypes';
+import action from '../utils/action';
+import { RESET_STATE, resetState } from './common';
+import campaigns from './campaigns';
+
+const { titleCase } = civicFormat;
+export const STATE_KEY = 'publicData';
+
+const isInclusiveAfter = (date, compare) =>
+ isEqual(date, compare) || isAfter(date, compare);
+
+const isInclusiveBefore = (date, compare) =>
+ isEqual(date, compare) || isBefore(date, compare);
+
+const numericSort = (a, b) => a - b;
+
+const median = arr => {
+ if (!arr || !arr.length) return null;
+
+ arr.sort(numericSort);
+
+ if (arr.length % 2 === 0) {
+ const a = arr[arr.length / 2 - 1];
+ const b = arr[arr.length / 2];
+ return (a + b) / 2;
+ }
+
+ return arr[Math.floor(arr.length / 2)];
+};
+
+const groupBy = (field, list) => {
+ const groups = {};
+ list.forEach(d => {
+ // Skip datapoints that do not have the field in question
+ if (!d[field]) return;
+
+ if (!groups[d[field]]) {
+ groups[d[field]] = [d];
+ } else {
+ groups[d[field]].push(d);
+ }
+ });
+
+ return groups;
+};
+
+const makeArray = input => {
+ if (input instanceof Array) return input;
+ if (input == null) return [];
+ return [input];
+};
+
+// Action Types
+export const actionTypes = {
+ GET_PUBLIC_DATA: createActionTypes(STATE_KEY, 'GET_PUBLIC_DATA'),
+ GET_EXTERNAL_PUBLIC_DATA: createActionTypes(
+ STATE_KEY,
+ 'GET_EXTERNAL_PUBLIC_DATA'
+ ),
+ SET_FILTER: createCustomActionTypes(STATE_KEY, 'SET_FILTER', [
+ 'OFFICES',
+ 'FINANCING',
+ 'CAMPAIGNS',
+ 'START_DATE',
+ 'END_DATE',
+ 'COUNT',
+ 'COMPARE',
+ 'RESET_ALL',
+ 'CUSTOM',
+ ]),
+};
+
+// Initial State
+export const initialState = {
+ data: {
+ type: 'FeatureCollection',
+ features: [],
+ },
+ externalData: {
+ type: 'FeatureCollection',
+ features: [],
+ },
+ filters: {
+ financing: 'public',
+ campaigns: [],
+ offices: [],
+ startDate: null,
+ endDate: null,
+ count: false,
+ compare: false,
+ },
+ isLoading: false,
+ isExternalLoading: false,
+ error: null,
+ externalError: null,
+};
+
+// Reducer
+export default createReducer(initialState, {
+ [RESET_STATE]: () => {
+ return { ...initialState };
+ },
+ [actionTypes.GET_PUBLIC_DATA.REQUEST]: state => {
+ return { ...state, isLoading: true };
+ },
+ [actionTypes.GET_PUBLIC_DATA.SUCCESS]: (state, action) => {
+ return {
+ ...state,
+ isLoading: false,
+ data: action.payload,
+ timeLoaded: new Date(),
+ };
+ },
+ [actionTypes.GET_PUBLIC_DATA.FAILURE]: (state, action) => {
+ return { ...state, isLoading: false, error: action.error };
+ },
+ [actionTypes.GET_EXTERNAL_PUBLIC_DATA.REQUEST]: state => {
+ return { ...state, isExternalLoading: true };
+ },
+ [actionTypes.GET_EXTERNAL_PUBLIC_DATA.SUCCESS]: (state, action) => {
+ return {
+ ...state,
+ isExternalLoading: false,
+ externalData: action.payload,
+ };
+ },
+ [actionTypes.GET_EXTERNAL_PUBLIC_DATA.FAILURE]: (state, action) => {
+ return { ...state, isExternalLoading: false, externalError: action.error };
+ },
+ [actionTypes.SET_FILTER.OFFICES]: (state, action) => {
+ return {
+ ...state,
+ filters: { ...state.filters, offices: makeArray(action.offices) },
+ };
+ },
+ [actionTypes.SET_FILTER.FINANCING]: (state, action) => {
+ return {
+ ...state,
+ filters: {
+ ...state.filters,
+ financing: action.financing,
+ compare: false,
+ },
+ };
+ },
+ [actionTypes.SET_FILTER.CAMPAIGNS]: (state, action) => {
+ return {
+ ...state,
+ filters: {
+ ...state.filters,
+ campaigns: makeArray(action.campaigns),
+ compare: makeArray(action.campaigns).length > 1,
+ },
+ };
+ },
+ [actionTypes.SET_FILTER.START_DATE]: (state, action) => {
+ return {
+ ...state,
+ filters: { ...state.filters, startDate: action.startDate },
+ };
+ },
+ [actionTypes.SET_FILTER.END_DATE]: (state, action) => {
+ return { ...state, filters: { ...state.filters, endDate: action.endDate } };
+ },
+ [actionTypes.SET_FILTER.COUNT]: (state, action) => {
+ return { ...state, filters: { ...state.filters, count: action.count } };
+ },
+ [actionTypes.SET_FILTER.COMPARE]: (state, action) => {
+ return { ...state, filters: { ...state.filters, compare: action.compare } };
+ },
+ [actionTypes.SET_FILTER.RESET_ALL]: state => {
+ return {
+ ...state,
+ filters: {
+ financing: 'public',
+ campaigns: [],
+ offices: [],
+ startDate: null,
+ endDate: null,
+ count: false,
+ compare: false,
+ },
+ };
+ },
+ [actionTypes.SET_FILTER.CUSTOM]: (state, action) => {
+ return {
+ ...state,
+ filters: {
+ financing: 'public',
+ campaigns: [],
+ offices: [],
+ startDate: null,
+ endDate: null,
+ count: false,
+ compare: false,
+ ...action.filters,
+ },
+ };
+ },
+});
+
+// Action Creators
+export const actionCreators = {
+ getPublicData: {
+ request: () => action(actionTypes.GET_PUBLIC_DATA.REQUEST),
+ success: payload =>
+ action(actionTypes.GET_PUBLIC_DATA.SUCCESS, { payload }),
+ failure: error => action(actionTypes.GET_PUBLIC_DATA.FAILURE, { error }),
+ },
+ getExternalPublicData: {
+ request: () => action(actionTypes.GET_EXTERNAL_PUBLIC_DATA.REQUEST),
+ success: payload =>
+ action(actionTypes.GET_EXTERNAL_PUBLIC_DATA.SUCCESS, { payload }),
+ failure: error =>
+ action(actionTypes.GET_EXTERNAL_PUBLIC_DATA.FAILURE, { error }),
+ },
+ setFilter: {
+ offices: offices => action(actionTypes.SET_FILTER.OFFICES, { offices }),
+ financing: financing =>
+ action(actionTypes.SET_FILTER.FINANCING, { financing }),
+ campaigns: campaigns =>
+ action(actionTypes.SET_FILTER.CAMPAIGNS, { campaigns }),
+ startDate: startDate =>
+ action(actionTypes.SET_FILTER.START_DATE, { startDate }),
+ endDate: endDate => action(actionTypes.SET_FILTER.END_DATE, { endDate }),
+ count: count => action(actionTypes.SET_FILTER.COUNT, { count }),
+ compare: compare => action(actionTypes.SET_FILTER.COMPARE, { compare }),
+ resetAll: () => action(actionTypes.SET_FILTER.RESET_ALL),
+ custom: filters => action(actionTypes.SET_FILTER.CUSTOM, { filters }),
+ },
+};
+
+export const setSelectedOffices = actionCreators.setFilter.offices;
+export const setSelectedFinancing = actionCreators.setFilter.financing;
+export const setSelectedCampaigns = actionCreators.setFilter.campaigns;
+export const setSelectedStartDate = actionCreators.setFilter.startDate;
+export const setSelectedEndDate = actionCreators.setFilter.endDate;
+export const setSelectedCount = actionCreators.setFilter.count;
+export const setSelectedCompare = actionCreators.setFilter.compare;
+export const resetAll = actionCreators.setFilter.resetAll;
+export const setCustomFilters = actionCreators.setFilter.custom;
+
+// Side Effects, e.g. thunks
+export function getPublicData() {
+ return async (dispatch, getState, { api, schema }) => {
+ dispatch(actionCreators.getPublicData.request());
+ try {
+ const response = await api.getContributionGeoData();
+ dispatch(actionCreators.getPublicData.success(response));
+ } catch (error) {
+ dispatch(actionCreators.getPublicData.failure(error));
+ }
+ };
+}
+
+export function getExternalPublicData() {
+ return async (dispatch, getState, { api, schema }) => {
+ dispatch(actionCreators.getExternalPublicData.request());
+ try {
+ const response = await api.getExternalContributionGeoData();
+ dispatch(actionCreators.getExternalPublicData.success(response));
+ } catch (error) {
+ dispatch(actionCreators.getExternalPublicData.failure(error));
+ }
+ };
+}
+
+export const rootState = state => state || {};
+export const allPublicData = createSelector(
+ rootState,
+ state => state[STATE_KEY] || {}
+);
+
+export const publicDataRequest = createSelector(allPublicData, state => {
+ const { data, isLoading, error, timeLoaded } = state;
+ return { data, isLoading, error, timeLoaded };
+});
+
+export const externalPublicDataRequest = createSelector(
+ allPublicData,
+ state => {
+ const { externalData, isExternalLoading, externalError } = state;
+ return { externalData, isExternalLoading, externalError };
+ }
+);
+
+export const publicDataRequestIsLoading = createSelector(
+ allPublicData,
+ state => {
+ const { isLoading, isExternalLoading } = state;
+ return !(!isLoading && !isExternalLoading);
+ }
+);
+
+export const publicDataFilters = createSelector(
+ allPublicData,
+ state => state.filters
+);
+
+export const mostRecentExternalContributionDate = createSelector(
+ externalPublicDataRequest,
+ extReq => {
+ const externalData = extReq.externalData;
+ // Return undefined if no external contributions
+ if (!externalData.features) return undefined;
+ if (externalData.features.length < 1) return undefined;
+
+ // Convert date strings to Date objects
+ externalData.features.forEach(f => {
+ if (f.properties.date) {
+ f.properties.date = new Date(f.properties.date);
+ // force date to be PDT timezone
+ f.properties.date.setUTCHours(7);
+ }
+ });
+
+ // Create a shallow copy of the combined Geojson and sort latest date
+ const dataCopy = { ...externalData };
+ dataCopy.features = externalData.features.slice();
+
+ const donations = dataCopy.features.map(f => f.properties);
+ donations.sort((a, b) => b.date - a.date);
+ const mostRecentDonationDate = donations[0].date;
+
+ return mostRecentDonationDate;
+ }
+);
+
+export const publicDataGeojson = createSelector(
+ publicDataRequest,
+ externalPublicDataRequest,
+ (req, extReq) => {
+ const data = req.data;
+ if (!data.features) return data;
+ const externalData = extReq.externalData;
+ if (!externalData.features) return externalData;
+
+ // Convert date strings to Date objects
+ data.features.forEach(f => {
+ if (f.properties.date) {
+ f.properties.date = new Date(f.properties.date);
+ }
+ });
+
+ // Convert date strings to Date objects and set match to 0
+ externalData.features.forEach(f => {
+ if (f.properties.date) {
+ f.properties.date = new Date(f.properties.date);
+ }
+ f.properties.oaeType = 'not participating';
+ f.properties.matchAmount = null;
+ });
+
+ // Create a shallow copy of the combined Geojson
+ const dataCopy = { ...data };
+ dataCopy.features = data.features
+ .slice()
+ .concat(externalData.features.slice());
+
+ return dataCopy;
+ }
+);
+
+// Filter Options (based off of the complete public dataset)
+
+export const allOffices = createSelector(publicDataGeojson, json => {
+ if (!json || !json.features) return [];
+
+ const offices = new Set();
+ json.features.forEach(f => {
+ offices.add(f.properties.officeSought);
+ });
+ return Array.from(offices);
+});
+
+export const allCampaigns = createSelector(publicDataGeojson, json => {
+ if (!json || !json.features) return [];
+
+ const campaignHash = json.features.reduce((campaigns, f) => {
+ const { campaignName, officeSought } = f.properties;
+ campaigns[f.properties.campaignId] = { campaignName, officeSought };
+ return campaigns;
+ }, {});
+
+ return Object.keys(campaignHash).map(id => ({
+ id,
+ name: campaignHash[id].campaignName,
+ officeSought: campaignHash[id].officeSought,
+ }));
+});
+
+// Filter selections
+
+export const selectedOffices = createSelector(
+ publicDataFilters,
+ filters => filters.offices || []
+);
+
+export const selectedFinancing = createSelector(
+ publicDataFilters,
+ filters => filters.financing
+);
+
+export const selectedCampaigns = createSelector(
+ publicDataFilters,
+ filters => filters.campaigns || []
+);
+
+export const selectedCampaignNames = createSelector(
+ selectedCampaigns,
+ campaigns => campaigns.map(campaign => campaign.name)
+);
+
+export const selectedStartDate = createSelector(publicDataFilters, filters =>
+ typeof filters.startDate === 'string'
+ ? new Date(filters.startDate)
+ : filters.startDate
+);
+
+export const selectedEndDate = createSelector(publicDataFilters, filters =>
+ typeof filters.endDate === 'string'
+ ? new Date(filters.endDate)
+ : filters.endDate
+);
+
+export const selectedCount = createSelector(
+ publicDataFilters,
+ filters => filters.count
+);
+
+export const selectedCompare = createSelector(
+ publicDataFilters,
+ filters => filters.compare
+);
+
+// Filtered filter options
+
+export const availableCampaigns = createSelector(
+ allCampaigns,
+ selectedOffices,
+ (campaigns, offices) => {
+ if (!offices || !offices.length) return campaigns;
+
+ return campaigns.filter(campaign =>
+ offices.includes(campaign.officeSought)
+ );
+ }
+);
+
+export const availableCampaignNames = createSelector(
+ availableCampaigns,
+ campaigns => campaigns.map(campaign => campaign.name)
+);
+
+// The only non-participating candidate this election cycle is Ted Wheeler
+const participatingCandidate = f => f.properties.campaignName !== 'Ted Wheeler';
+
+const nonParticipatingCandidate = f =>
+ f.properties.campaignName === 'Ted Wheeler';
+// Filtered public dataset (based on above filters)
+
+export const filteredPublicData = createSelector(
+ publicDataGeojson,
+ selectedOffices,
+ selectedFinancing,
+ selectedCampaigns,
+ selectedStartDate,
+ selectedEndDate,
+ (data, offices, financing, campaigns, start, end) => {
+ const campaignIds = campaigns.map(c => +c.id);
+ // Create a shallow copy of the underlying Geojson
+ const dataCopy = { ...data };
+ dataCopy.features = dataCopy.features.slice();
+
+ // Filter data starting with the fastest, broadest filters first
+ if (campaigns.length) {
+ dataCopy.features = dataCopy.features.filter(f =>
+ campaignIds.includes(+f.properties.campaignId)
+ );
+ }
+
+ if (offices.length) {
+ dataCopy.features = dataCopy.features.filter(f =>
+ offices.includes(f.properties.officeSought)
+ );
+ }
+
+ if (financing !== 'all') {
+ if (financing === 'public') {
+ dataCopy.features = dataCopy.features.filter(participatingCandidate);
+ }
+ if (financing === 'private') {
+ dataCopy.features = dataCopy.features.filter(nonParticipatingCandidate);
+ }
+ }
+
+ if (start && end) {
+ dataCopy.features = dataCopy.features.filter(
+ f =>
+ isInclusiveAfter(f.properties.date, start) &&
+ isInclusiveBefore(f.properties.date, end)
+ );
+ } else if (start) {
+ dataCopy.features = dataCopy.features.filter(f =>
+ isInclusiveAfter(f.properties.date, start)
+ );
+ } else if (end) {
+ dataCopy.features = dataCopy.features.filter(f =>
+ isInclusiveBefore(f.properties.date, end)
+ );
+ }
+
+ // filter out public_matching_contributions
+ dataCopy.features = dataCopy.features.filter(
+ f => f.properties.oaeType !== 'public_matching_contribution'
+ );
+
+ return dataCopy;
+ }
+);
+
+// Aggregated data per chart
+
+// Done: map takes Geojson of the filtered donations
+export const mapData = createSelector(filteredPublicData, data => data);
+
+const addParticipatingStatus = (data, status) => {
+ return { ...data, participatingStatus: status };
+};
+
+export const filteredPublicDataParticipatingOnly = createSelector(
+ filteredPublicData,
+ data => {
+ // Create a shallow copy of the underlying Geojson
+ const dataCopy = { ...data };
+ dataCopy.features = dataCopy.features.slice();
+ // Filter out non-participating candidates
+ dataCopy.features = dataCopy.features.filter(participatingCandidate);
+ return dataCopy;
+ }
+);
+
+export const filteredPublicDataNonParticipatingOnly = createSelector(
+ filteredPublicData,
+ data => {
+ // Create a shallow copy of the underlying Geojson
+ const dataCopy = { ...data };
+ dataCopy.features = dataCopy.features.slice();
+ // Filter for non-participating candidates
+ dataCopy.features = dataCopy.features.filter(nonParticipatingCandidate);
+ return dataCopy;
+ }
+);
+
+const sortedDonations = createSelector(filteredPublicData, data => {
+ const donations = data.features.map(f => f.properties);
+ donations.sort((a, b) => a.amount - b.amount);
+ return donations;
+});
+
+const sortedDonationsNonParticipatingOnly = createSelector(
+ filteredPublicDataNonParticipatingOnly,
+ data => {
+ const donations = data.features.map(f => f.properties);
+ donations.sort((a, b) => a.amount - b.amount);
+ return donations;
+ }
+);
+
+const sortedDonationsParticipatingOnly = createSelector(
+ filteredPublicDataParticipatingOnly,
+ data => {
+ const donations = data.features.map(f => f.properties);
+ donations.sort((a, b) => a.amount - b.amount);
+ return donations;
+ }
+);
+
+export const sortedDonationsByCandidate = createSelector(
+ filteredPublicData,
+ selectedCampaignNames,
+ (data, campaigns) => {
+ const campaignDonations = {};
+ campaigns.map(campaign => {
+ const donations = data.features
+ .filter(f => f.properties.campaignName === campaign)
+ .map(f => f.properties);
+ donations.sort((a, b) => a.amount - b.amount);
+ campaignDonations[campaign] = donations;
+ return {};
+ });
+ return campaignDonations;
+ }
+ // returns an array of donation for each candidate
+
+ // want to return a keyed object based on candidate name
+ // { ted: donations, sarah: donations }
+);
+
+const summarize = donations => {
+ const donationsCount = donations.length;
+
+ const nonOAEContributions = [];
+ const markedDonors = {};
+ const markedCampaigns = {};
+ let donorsCount = 0;
+ let totalAmountContributed = 0;
+ let totalAmountMatched = 0;
+ let campaignsCount = 0;
+
+ // Only iterate over the array once for better performance
+ donations.forEach(d => {
+ // NOTE: contributor name is not a strong idenfitier, could result in miscounting
+ // NOTE: Count each "Miscellaneous Cash Contributions $100 and under " as one donor
+
+ if (
+ !markedDonors[d.contributorName] ||
+ d.contributorName === 'Miscellaneous Cash Contributions $100 and under '
+ ) {
+ donorsCount += 1;
+ markedDonors[d.contributorName] = true;
+ }
+
+ if (!markedCampaigns[d.campaignName]) {
+ campaignsCount += 1;
+ markedCampaigns[d.campaignName] = true;
+ }
+
+ // Guard against bad data
+ if (+d.amount === d.amount && d.amount >= 0) {
+ totalAmountContributed += d.amount;
+ if (d.oaeType !== 'public_matching_contribution') {
+ nonOAEContributions.push(d.amount);
+ }
+ }
+
+ if (+d.matchAmount === d.matchAmount && d.matchAmount >= 0) {
+ totalAmountMatched += d.matchAmount;
+ }
+ });
+
+ return {
+ campaignsCount,
+ donationsCount,
+ donorsCount,
+ totalAmountContributed,
+ totalAmountMatched,
+ medianContributionSize: median(nonOAEContributions),
+ };
+};
+
+// Done: summary data includes aggregations and averages
+// - number of campaigns
+// - number of donors
+// - number of donations
+// - median contribution size (exclude OAE type public match)
+// - total amount contributed (by campaign?)
+// - total amount matched (requires explanatory text since it won't be exactly 6x)
+
+export const summaryData = createSelector(sortedDonations, donations =>
+ summarize(donations)
+);
+
+export const summaryDataByParticipation = createSelector(
+ sortedDonationsParticipatingOnly,
+ sortedDonationsNonParticipatingOnly,
+ (participatingDonations, nonParticipatingDonations) => {
+ const summaryData = [];
+ participatingDonations.length > 0 &&
+ summaryData.push(
+ addParticipatingStatus(summarize(participatingDonations), true)
+ );
+ nonParticipatingDonations.length > 0 &&
+ summaryData.push(
+ addParticipatingStatus(summarize(nonParticipatingDonations), false)
+ );
+ return summaryData;
+ }
+);
+
+const bracketize = donations => {
+ const aggregates = {
+ micro: {
+ total: 0,
+ contributions: [],
+ },
+ small: {
+ total: 0,
+ contributions: [],
+ },
+ medium: {
+ total: 0,
+ contributions: [],
+ },
+ large: {
+ total: 0,
+ contributions: [],
+ },
+ mega: {
+ total: 0,
+ contributions: [],
+ },
+ };
+
+ const markers = ['micro', 'small', 'medium', 'large', 'mega'];
+ const breakpoints = [25, 100, 250, 1000];
+
+ let index = 0;
+ let marker = markers[index];
+ let breakpoint = breakpoints[index];
+
+ donations.forEach(d => {
+ // Skip non-numeric values
+ if (+d.amount !== d.amount) return;
+
+ if (d.amount > breakpoint) {
+ while (d.amount > breakpoint) {
+ index += 1;
+ marker = markers[index];
+ if (index >= breakpoints.length) {
+ breakpoint = Number.MAX_VALUE;
+ break;
+ }
+ breakpoint = breakpoints[index];
+ }
+ }
+
+ // Categorize "Miscellaneous Cash Contributions $100 and under" in the 25-100 category
+ if (
+ d.contributorName === 'Miscellaneous Cash Contributions $100 and under '
+ ) {
+ aggregates.small.total += d.amount;
+ aggregates.small.contributions.push(d.amount);
+ return;
+ }
+
+ aggregates[marker].total += d.amount;
+ aggregates[marker].contributions.push(d.amount);
+ });
+
+ return aggregates;
+};
+
+// Done: aggregate donation amounts by binned donations ranges
+// - micro ($0-25)
+// - small ($25-100)
+// - medium ($100-250)
+// - large ($250-1000)
+// - mega ($1000+)
+// For each bucket include three properties ({ name: 'micro', count: number of donations, total: sum of donations})
+export const donationSizeByDonationRange = createSelector(
+ sortedDonations,
+ donations => bracketize(donations)
+);
+
+export const donationSizeByDonationRangeByCandidate = createSelector(
+ sortedDonationsByCandidate,
+ candidateDonations =>
+ fromPairs(
+ Object.entries(candidateDonations).map(entry => [
+ entry[0],
+ bracketize(entry[1]),
+ ])
+ )
+);
+
+const aggregateDonationsBySize = aggregates => {
+ const markers = ['micro', 'small', 'medium', 'large', 'mega'];
+ const labels = ['<$25', '$25-$100', '$100-$250', '$250-$1000', '>$1000'];
+ const summarizedAggregates = markers.map((category, index) => {
+ return {
+ type: category,
+ formattedType: labels[index],
+ total: aggregates[category].total,
+ contributions: aggregates[category].contributions,
+ count: aggregates[category].contributions.length,
+ };
+ });
+ return summarizedAggregates;
+};
+
+export const aggregatedDonationSize = createSelector(
+ donationSizeByDonationRange,
+ aggregateDonationsBySize
+);
+
+export const aggregatedDonationSizeByCandidate = createSelector(
+ donationSizeByDonationRangeByCandidate,
+ candidateDonations => {
+ if (Object.keys(candidateDonations).length < 1) {
+ return [];
+ }
+ return fromPairs(
+ Object.entries(candidateDonations).map(entry => [
+ entry[0],
+ aggregateDonationsBySize(entry[1]),
+ ])
+ );
+ }
+);
+
+// Done: count of and sum of donations for each contributor type
+// (individual, business, family, labor, political_committee, political_party, unregistered, other)
+// For each type include three properties ({ type: 'individual', count: number of donations, total: sum of donations })
+// Note: pad out the rest of the map with zeroes for each type that isn't represented in the data
+const aggregateDonationsByContributorType = donations => {
+ const categories = [
+ 'individual',
+ 'business',
+ 'family',
+ 'labor',
+ 'political_committee',
+ 'political_party',
+ 'unregistered',
+ 'other',
+ ];
+ const aggregates = categories.reduce((agg, type) => {
+ agg[type] = {
+ total: 0,
+ contributions: [],
+ };
+ return agg;
+ }, {});
+
+ donations.forEach(d => {
+ const bucket = aggregates[d.contributorType || 'other'];
+ bucket.total += d.amount;
+ bucket.contributions.push(d.amount);
+ });
+
+ const summarizedAggregates = categories.map(category => {
+ return {
+ type: category,
+ label: titleCase(category),
+ total: aggregates[category].total,
+ contributions: aggregates[category].contributions,
+ count: aggregates[category].contributions.length,
+ };
+ });
+
+ return summarizedAggregates;
+};
+
+export const aggregatedContributorTypes = createSelector(
+ sortedDonations,
+ aggregateDonationsByContributorType
+);
+
+export const aggregatedContributorTypesByCandidate = createSelector(
+ sortedDonationsByCandidate,
+ candidateDonations => {
+ if (Object.keys(candidateDonations).length < 1) {
+ return [];
+ }
+ return fromPairs(
+ Object.entries(candidateDonations).map(entry => [
+ entry[0],
+ aggregateDonationsByContributorType(entry[1]),
+ ])
+ );
+ }
+);
+
+// Done: count of and sum of donations for each contribution type
+// (cash, inkind, other)
+// Same as above data shape
+const aggregateDonationsByContributionType = donations => {
+ const categories = ['cash', 'inkind', 'other'];
+ const aggregates = categories.reduce((agg, type) => {
+ agg[type] = {
+ total: 0,
+ contributions: [],
+ };
+ return agg;
+ }, {});
+
+ donations.forEach(d => {
+ let type = 'other';
+ if (d.contributionSubType === 'cash') type = 'cash';
+ if ((d.contributionSubType || '').startsWith('inkind_')) type = 'inkind';
+
+ const bucket = aggregates[type];
+ bucket.total += d.amount;
+ bucket.contributions.push(d.amount);
+ });
+
+ const summarizedAggregates = categories.map(category => {
+ return {
+ type: category,
+ formattedType: titleCase(category),
+ total: aggregates[category].total,
+ contributions: aggregates[category].contributions,
+ count: aggregates[category].contributions.length,
+ };
+ });
+
+ return summarizedAggregates;
+};
+
+export const aggregatedContributionTypes = createSelector(
+ sortedDonations,
+ aggregateDonationsByContributionType
+);
+
+export const aggregatedContributionTypesByCandidate = createSelector(
+ sortedDonationsByCandidate,
+ candidateDonations => {
+ if (Object.keys(candidateDonations).length < 1) {
+ return [];
+ }
+ return fromPairs(
+ Object.entries(candidateDonations).map(entry => [
+ entry[0],
+ aggregateDonationsByContributionType(entry[1]),
+ ])
+ );
+ }
+);
+
+// Done: count and sum of donations for each region
+// (portland, oregon, outside)
+// Note: filter out OAE subtype public_matching
+// Note: do not include portland in oregon
+const aggregateDonationsByRegion = donations => {
+ const categories = ['portland', 'oregon', 'out_of_state'];
+ const aggregates = categories.reduce((agg, type) => {
+ agg[type] = {
+ total: 0,
+ contributions: [],
+ };
+ return agg;
+ }, {});
+
+ donations.forEach(d => {
+ let type = 'out_of_state';
+ if ((d.state || '').toUpperCase() === 'OR') {
+ type = 'oregon';
+ // NOTE: this is a strict address match. If we want to include the entire metro area,
+ // it would probably be better to check against a set of zipcodes or something.
+ if ((d.city || '').toUpperCase() === 'PORTLAND') type = 'portland';
+ }
+
+ const bucket = aggregates[type];
+ bucket.total += d.amount;
+ bucket.contributions.push(d.amount);
+ });
+
+ const summarizedAggregates = categories.map(category => {
+ return {
+ type: category,
+ label: titleCase(category),
+ total: aggregates[category].total,
+ contributions: aggregates[category].contributions,
+ count: aggregates[category].contributions.length,
+ };
+ });
+
+ return summarizedAggregates;
+};
+
+export const aggregatedContributionsByRegion = createSelector(
+ sortedDonations,
+ aggregateDonationsByRegion
+);
+
+export const aggregatedContributionsByRegionByCandidate = createSelector(
+ sortedDonationsByCandidate,
+ candidateDonations => {
+ if (Object.keys(candidateDonations).length < 1) {
+ return [];
+ }
+ return fromPairs(
+ Object.entries(candidateDonations).map(entry => [
+ entry[0],
+ aggregateDonationsByRegion(entry[1]),
+ ])
+ );
+ }
+);
+
+// Done: create a table that matches this format
+// | Campaign Name | Total Amount | Total Donations | Total Match Amount | Micro | Small | Medium | Large | Mega |
+// | ------------- | ------------ | --------------- | ------------------ | ----- | ----- | ------ | ----- | ---- |
+// | One | $1,234 | 29 | $20,444 | 15 | 12 | 1 | 1 | 0 |
+// | Two | $1,234 | 29 | $20,444 | 15 | 12 | 1 | 1 | 0 |
+export const campaignsTable = createSelector(sortedDonations, donations => {
+ const donationsByCampaign = groupBy('campaignId', donations);
+ const campaigns = Object.keys(donationsByCampaign).map(k => ({
+ campaignId: k,
+ contributions: donationsByCampaign[k],
+ }));
+
+ campaigns.forEach(campaign => {
+ Object.assign(
+ campaign,
+ summarize(campaign.contributions),
+ bracketize(campaign.contributions)
+ );
+
+ // Pull common properties of a contribution up
+ // to the campaign for convenience
+ const contribution = campaign.contributions[0];
+ campaign.campaignName = contribution.campaignName;
+ campaign.officeSought = contribution.officeSought;
+ campaign.participatingStatus = contribution.campaignName !== 'Ted Wheeler';
+ });
+
+ return campaigns;
+});
diff --git a/app2/src/state/ducks/publicData.test.js b/app2/src/state/ducks/publicData.test.js
new file mode 100644
index 000000000..544770dc3
--- /dev/null
+++ b/app2/src/state/ducks/publicData.test.js
@@ -0,0 +1,1767 @@
+import * as publicData from './publicData';
+
+const { actionTypes } = publicData;
+
+const makeData = (features = [], overrides = {}) => {
+ const state = {
+ [publicData.STATE_KEY]: {
+ ...publicData.initialState,
+ data: {
+ type: 'FeatureCollection',
+ features,
+ },
+ ...overrides,
+ },
+ };
+ return [state, JSON.parse(JSON.stringify(state[publicData.STATE_KEY]))];
+};
+
+const point = (properties = {}, geometry = {}) => ({
+ type: 'Feature',
+ properties,
+ geometry: {
+ type: 'Point',
+ coordinates: [-122.654, 45.516],
+ ...geometry,
+ },
+});
+
+describe('Reducer', () => {
+ const reducer = publicData.default;
+
+ describe('set campaigns', () => {
+ it('sets the campaigns filter', () => {
+ expect(
+ reducer(publicData.initialState, {
+ type: actionTypes.SET_FILTER.CAMPAIGNS,
+ campaigns: ['1', '2', '3'],
+ }).filters
+ ).toEqual({
+ campaigns: ['1', '2', '3'],
+ financing: 'public',
+ offices: [],
+ startDate: null,
+ endDate: null,
+ count: false,
+ compare: true,
+ });
+ });
+
+ it('is liberal with what it accepts', () => {
+ expect(
+ reducer(publicData.initialState, {
+ type: actionTypes.SET_FILTER.CAMPAIGNS,
+ campaigns: null,
+ }).filters
+ ).toEqual({
+ campaigns: [],
+ financing: 'public',
+ offices: [],
+ startDate: null,
+ endDate: null,
+ count: false,
+ compare: false,
+ });
+
+ expect(
+ reducer(publicData.initialState, {
+ type: actionTypes.SET_FILTER.CAMPAIGNS,
+ campaigns: 'just-the-one',
+ }).filters
+ ).toEqual({
+ campaigns: ['just-the-one'],
+ financing: 'public',
+ offices: [],
+ startDate: null,
+ endDate: null,
+ count: false,
+ compare: false,
+ });
+ });
+ });
+
+ describe('set offices', () => {
+ it('sets the offices filter', () => {
+ expect(
+ reducer(publicData.initialState, {
+ type: actionTypes.SET_FILTER.OFFICES,
+ offices: ['1', '2', '3'],
+ }).filters
+ ).toEqual({
+ campaigns: [],
+ financing: 'public',
+ offices: ['1', '2', '3'],
+ startDate: null,
+ endDate: null,
+ count: false,
+ compare: false,
+ });
+ });
+
+ it('is liberal with what it accepts', () => {
+ expect(
+ reducer(publicData.initialState, {
+ type: actionTypes.SET_FILTER.OFFICES,
+ offices: null,
+ }).filters
+ ).toEqual({
+ campaigns: [],
+ financing: 'public',
+ offices: [],
+ startDate: null,
+ endDate: null,
+ count: false,
+ compare: false,
+ });
+
+ expect(
+ reducer(publicData.initialState, {
+ type: actionTypes.SET_FILTER.OFFICES,
+ offices: 'just-the-one',
+ }).filters
+ ).toEqual({
+ campaigns: [],
+ financing: 'public',
+ offices: ['just-the-one'],
+ startDate: null,
+ endDate: null,
+ count: false,
+ compare: false,
+ });
+ });
+ });
+
+ describe('set financing', () => {
+ it('sets the financing filter', () => {
+ expect(
+ reducer(publicData.initialState, {
+ type: actionTypes.SET_FILTER.FINANCING,
+ financing: 'all',
+ }).filters
+ ).toEqual({
+ campaigns: [],
+ financing: 'all',
+ offices: [],
+ startDate: null,
+ endDate: null,
+ count: false,
+ compare: false,
+ });
+ });
+ });
+
+ describe('set start date', () => {
+ it('sets the start date filter', () => {
+ const date = new Date();
+ expect(
+ reducer(publicData.initialState, {
+ type: actionTypes.SET_FILTER.START_DATE,
+ startDate: date,
+ }).filters
+ ).toEqual({
+ campaigns: [],
+ financing: 'public',
+ offices: [],
+ startDate: date,
+ endDate: null,
+ count: false,
+ compare: false,
+ });
+ });
+ });
+
+ describe('set end date', () => {
+ it('sets the end date filter', () => {
+ const date = new Date();
+ expect(
+ reducer(publicData.initialState, {
+ type: actionTypes.SET_FILTER.END_DATE,
+ endDate: date,
+ }).filters
+ ).toEqual({
+ campaigns: [],
+ financing: 'public',
+ offices: [],
+ startDate: null,
+ endDate: date,
+ count: false,
+ compare: false,
+ });
+ });
+ });
+
+ describe('set compare', () => {
+ it('sets the compare filter', () => {
+ expect(
+ reducer(publicData.initialState, {
+ type: actionTypes.SET_FILTER.COMPARE,
+ compare: true,
+ }).filters
+ ).toEqual({
+ campaigns: [],
+ financing: 'public',
+ offices: [],
+ startDate: null,
+ endDate: null,
+ count: false,
+ compare: true,
+ });
+ });
+ });
+
+ describe('set custom', () => {
+ it('sets a custom filter', () => {
+ expect(
+ reducer(publicData.initialState, {
+ type: actionTypes.SET_FILTER.CUSTOM,
+ filters: {
+ financing: 'all',
+ count: true,
+ offices: ['1', '2', '3'],
+ campaigns: ['hazel'],
+ compare: true,
+ },
+ }).filters
+ ).toEqual({
+ campaigns: ['hazel'],
+ financing: 'all',
+ offices: ['1', '2', '3'],
+ startDate: null,
+ endDate: null,
+ count: true,
+ compare: true,
+ });
+ });
+ });
+});
+
+describe('Selectors', () => {
+ describe('allPublicData', () => {
+ const [state, data] = makeData();
+
+ it('returns the object at the module STATE_KEY', () => {
+ expect(publicData.allPublicData(state)).toEqual(data);
+ });
+ });
+
+ describe('publicDataFilters', () => {
+ const [emptyState] = makeData();
+
+ const filters = {
+ campaigns: [1, 2, 3],
+ offices: ['Mayor'],
+ startDate: new Date().toISOString(),
+ endDate: null,
+ count: false,
+ };
+ const [stateWithSelections] = makeData([], { filters });
+
+ it('returns the current filter selections', () => {
+ expect(publicData.publicDataFilters(emptyState)).toEqual(
+ publicData.initialState.filters
+ );
+ expect(publicData.publicDataFilters(stateWithSelections)).toEqual(
+ filters
+ );
+ });
+ });
+
+ describe('publicDataRequest', () => {
+ const [emptyState, emptyData] = makeData();
+ const [stateWithData, dataWithData] = makeData(
+ [
+ point({ type: 'contribution', campaignId: 1 }),
+ point({ type: 'contribution', campaignId: 2 }),
+ ],
+ {
+ isLoading: false,
+ error: null,
+ }
+ );
+
+ it('returns the data, isLoading, and error states', () => {
+ expect(publicData.publicDataRequest(emptyState)).toEqual({
+ data: emptyData.data,
+ isLoading: emptyData.isLoading,
+ error: emptyData.error,
+ });
+
+ expect(publicData.publicDataRequest(stateWithData)).toEqual({
+ data: dataWithData.data,
+ isLoading: dataWithData.isLoading,
+ error: dataWithData.error,
+ });
+ });
+ });
+
+ describe('publicDataGeojson', () => {
+ it('returns just the data from the state tree', () => {
+ const [state, data] = makeData();
+ expect(publicData.publicDataGeojson(state)).toEqual(data.data);
+ });
+
+ it('converts date strings into Date objects where applicable', () => {
+ const [state, data] = makeData([
+ point({ date: '2019-12-14T04:02:09.416Z' }),
+ point({ date: '2019-12-13T04:02:09.416Z' }),
+ point({ date: '2019-12-12T04:02:09.416Z' }),
+ ]);
+
+ expect(publicData.publicDataGeojson(state)).not.toEqual(data.data);
+ expect(
+ publicData.publicDataGeojson(state).features.map(f => f.properties.date)
+ ).toEqual(data.data.features.map(f => new Date(f.properties.date)));
+ });
+ });
+
+ describe('allOffices', () => {
+ it('returns an array of offices based on the data prop', () => {
+ const [state] = makeData([
+ point({ officeSought: 'Mayor' }),
+ point({ officeSought: 'Commissioner 1' }),
+ point({ officeSought: 'Commissioner 2' }),
+ ]);
+
+ expect(publicData.allOffices(state)).toEqual([
+ 'Mayor',
+ 'Commissioner 1',
+ 'Commissioner 2',
+ ]);
+ });
+
+ it('does not return duplicate values', () => {
+ const [state] = makeData([
+ point({ officeSought: 'Mayor' }),
+ point({ officeSought: 'Mayor' }),
+ point({ officeSought: 'Mayor' }),
+ ]);
+
+ expect(publicData.allOffices(state)).toEqual(['Mayor']);
+ });
+
+ it('returns an empty array when there is no data', () => {
+ const [state] = makeData();
+
+ expect(publicData.allOffices(state)).toEqual([]);
+ });
+ });
+
+ describe('allCampaigns', () => {
+ it('returns an array of campaign objects, including ID and Name', () => {
+ const campaigns = [
+ { campaignId: '1', campaignName: 'Foo', officeSought: 'Mayor' },
+ { campaignId: '2', campaignName: 'Bar', officeSought: 'Mayor' },
+ { campaignId: '3', campaignName: 'Baz', officeSought: 'Commissioner' },
+ ];
+ const [state] = makeData(campaigns.map(point));
+
+ expect(publicData.allCampaigns(state)).toEqual(
+ campaigns.map(c => ({
+ id: c.campaignId,
+ name: c.campaignName,
+ officeSought: c.officeSought,
+ }))
+ );
+ });
+
+ it('does not return duplicate values (based on ID, last name wins)', () => {
+ const campaigns = [
+ { campaignId: '1', campaignName: 'Foo 1', officeSought: 'Mayor' },
+ { campaignId: '1', campaignName: 'Foo 2', officeSought: 'Mayor' },
+ { campaignId: '2', campaignName: 'Bar 1', officeSought: 'Mayor' },
+ { campaignId: '2', campaignName: 'Bar 2', officeSought: 'Mayor' },
+ { campaignId: '3', campaignName: 'Foo 1', officeSought: 'Mayor' },
+ { campaignId: '3', campaignName: 'Foo 2', officeSought: 'Mayor' },
+ ];
+ const [state] = makeData(campaigns.map(point));
+
+ expect(publicData.allCampaigns(state)).toEqual([
+ { id: '1', name: 'Foo 2', officeSought: 'Mayor' },
+ { id: '2', name: 'Bar 2', officeSought: 'Mayor' },
+ { id: '3', name: 'Foo 2', officeSought: 'Mayor' },
+ ]);
+ });
+
+ it('returns an empty array when there is no data', () => {
+ const [state] = makeData();
+
+ expect(publicData.allCampaigns(state)).toEqual([]);
+ });
+ });
+
+ describe('availableCampaigns', () => {
+ const campaigns = [
+ { campaignId: '1', campaignName: 'Foo', officeSought: 'First' },
+ { campaignId: '2', campaignName: 'Bar', officeSought: 'Second' },
+ { campaignId: '3', campaignName: 'Baz', officeSought: 'Third' },
+ ];
+
+ it('returns an array of all campaigns when there is no office filter selection', () => {
+ const [state] = makeData(campaigns.map(point));
+ expect(publicData.availableCampaigns(state)).toEqual([
+ { id: '1', name: 'Foo', officeSought: 'First' },
+ { id: '2', name: 'Bar', officeSought: 'Second' },
+ { id: '3', name: 'Baz', officeSought: 'Third' },
+ ]);
+ });
+
+ it('returns an array of only matching campaigns when there is an office filter selection', () => {
+ const [state] = makeData(campaigns.map(point), {
+ filters: {
+ offices: ['First', 'Third'],
+ },
+ });
+ expect(publicData.availableCampaigns(state)).toEqual([
+ { id: '1', name: 'Foo', officeSought: 'First' },
+ { id: '3', name: 'Baz', officeSought: 'Third' },
+ ]);
+ });
+ });
+
+ describe('filter selections', () => {
+ const startDate = new Date();
+ const endDate = new Date();
+
+ const [state] = makeData([], {
+ filters: {
+ offices: ['Mayor', 'Test', 'Case'],
+ campaigns: [
+ { id: '1', name: 'One' },
+ { id: '2', name: 'Four' },
+ { id: '3', name: 'Three' },
+ ],
+ startDate,
+ endDate,
+ },
+ });
+
+ const [emptyState] = makeData([], {
+ filters: {},
+ });
+
+ it('returns a list of offices for selectedOffices', () => {
+ expect(publicData.selectedOffices(state)).toEqual([
+ 'Mayor',
+ 'Test',
+ 'Case',
+ ]);
+ });
+
+ it('defaults to an empty array for selectedOffices', () => {
+ expect(publicData.selectedOffices(emptyState)).toEqual([]);
+ });
+
+ it('returns a list of campaign IDs for selectedCampaigns', () => {
+ expect(publicData.selectedCampaigns(state)).toEqual([
+ { id: '1', name: 'One' },
+ { id: '2', name: 'Four' },
+ { id: '3', name: 'Three' },
+ ]);
+ });
+
+ it('defaults to an empty array for selectedCampaigns', () => {
+ expect(publicData.selectedCampaigns(emptyState)).toEqual([]);
+ });
+
+ it('returns a date for selectedStartDate', () => {
+ expect(publicData.selectedStartDate(state)).toEqual(startDate);
+ });
+
+ it('returns a date for selectedEndDate', () => {
+ expect(publicData.selectedEndDate(state)).toEqual(endDate);
+ });
+ });
+
+ describe('filtered selectors', () => {
+ const ids = d => d.properties.id;
+
+ let incr = 0;
+ const factory = staticProps => date => {
+ incr += 1;
+ return point({
+ id: incr,
+ date,
+ ...staticProps,
+ });
+ };
+
+ const campaign1 = factory({
+ officeSought: 'Mayor',
+ campaignId: '1',
+ campaignName: 'One',
+ });
+ const campaign2 = factory({
+ officeSought: 'Mayor',
+ campaignId: '2',
+ campaignName: 'Two',
+ });
+ const campaign3 = factory({
+ officeSought: 'Commissioner 1',
+ campaignId: '3',
+ campaignName: 'Three',
+ });
+ const campaign4 = factory({
+ officeSought: 'Commissioner 2',
+ campaignId: '4',
+ campaignName: 'Four',
+ });
+
+ const points = [
+ campaign1('2019-12-01T04:02:09.416Z'),
+ campaign1('2019-12-07T04:02:09.416Z'),
+ campaign1('2019-12-14T04:02:09.416Z'),
+
+ campaign2('2019-12-02T04:02:09.416Z'),
+ campaign2('2019-12-08T04:02:09.416Z'),
+ campaign2('2019-12-15T04:02:09.416Z'),
+
+ campaign3('2019-12-03T04:02:09.416Z'),
+ campaign3('2019-12-09T04:02:09.416Z'),
+ campaign3('2019-12-16T04:02:09.416Z'),
+
+ campaign4('2019-12-04T04:02:09.416Z'),
+ campaign4('2019-12-10T04:02:09.416Z'),
+ campaign4('2019-12-17T04:02:09.416Z'),
+ ];
+
+ describe('filteredPublicData', () => {
+ it('returns all data when there is no active filter', () => {
+ const [state] = makeData(points, {
+ filters: {},
+ });
+
+ const { features } = publicData.filteredPublicData(state);
+ expect(features).toHaveLength(points.length);
+ expect(features.map(ids)).toEqual(points.map(ids));
+ });
+
+ it('returns all data matching any selected office', () => {
+ const [singleState] = makeData(points, {
+ filters: {
+ offices: ['Mayor'],
+ },
+ });
+
+ const [multiState] = makeData(points, {
+ filters: {
+ offices: ['Mayor', 'Commissioner 2'],
+ },
+ });
+
+ const { features: singleFeatures } = publicData.filteredPublicData(
+ singleState
+ );
+ const { features: multiFeatures } = publicData.filteredPublicData(
+ multiState
+ );
+
+ expect(singleFeatures.map(ids)).toEqual([1, 2, 3, 4, 5, 6]);
+ expect(multiFeatures.map(ids)).toEqual([1, 2, 3, 4, 5, 6, 10, 11, 12]);
+ });
+
+ it('returns all data matching any selected campaign', () => {
+ const [singleState] = makeData(points, {
+ filters: {
+ campaigns: [{ id: '1', name: 'One' }],
+ },
+ });
+
+ const [multiState] = makeData(points, {
+ filters: {
+ campaigns: [
+ { id: '1', name: 'One' },
+ { id: '3', name: 'Three' },
+ { id: '4', name: 'Four' },
+ ],
+ },
+ });
+
+ const { features: singleFeatures } = publicData.filteredPublicData(
+ singleState
+ );
+ const { features: multiFeatures } = publicData.filteredPublicData(
+ multiState
+ );
+
+ expect(singleFeatures.map(ids)).toEqual([1, 2, 3]);
+ expect(multiFeatures.map(ids)).toEqual([1, 2, 3, 7, 8, 9, 10, 11, 12]);
+ });
+
+ it('returns only data matching both selected campaigns AND selected offices', () => {
+ const [state] = makeData(points, {
+ filters: {
+ campaigns: [
+ { id: '2', name: 'Two' },
+ { id: '4', name: 'Four' },
+ ],
+ offices: ['Mayor', 'Commissioner 1'],
+ },
+ });
+
+ const { features } = publicData.filteredPublicData(state);
+
+ expect(features.map(ids)).toEqual([4, 5, 6]);
+ });
+
+ it('returns all data after or including the start date', () => {
+ const [state] = makeData(points, {
+ filters: {
+ startDate: new Date('2019-12-10T04:02:09.416Z'),
+ },
+ });
+
+ const { features } = publicData.filteredPublicData(state);
+ expect(features.map(ids)).toEqual([3, 6, 9, 11, 12]);
+ });
+
+ it('returns all data before or including the end date', () => {
+ const [state] = makeData(points, {
+ filters: {
+ endDate: new Date('2019-12-06T04:02:09.416Z'),
+ },
+ });
+
+ const { features } = publicData.filteredPublicData(state);
+ expect(features.map(ids)).toEqual([1, 4, 7, 10]);
+ });
+
+ it('returns only data within (inclusive) the start and end date', () => {
+ const [state] = makeData(points, {
+ filters: {
+ startDate: new Date('2019-12-06T04:02:09.416Z'),
+ endDate: new Date('2019-12-10T04:02:09.416Z'),
+ },
+ });
+
+ const { features } = publicData.filteredPublicData(state);
+ expect(features.map(ids)).toEqual([2, 5, 8, 11]);
+ });
+
+ it('returns only data within the start and end date matching both selected campaigns AND selected offices', () => {
+ const [state] = makeData(points, {
+ filters: {
+ campaigns: [
+ { id: '2', name: 'Two' },
+ { id: '4', name: 'Four' },
+ ],
+ offices: ['Mayor'],
+ startDate: new Date('2019-12-03T04:02:09.416Z'),
+ endDate: new Date('2019-12-14T04:02:09.416Z'),
+ },
+ });
+
+ const { features } = publicData.filteredPublicData(state);
+ expect(features.map(ids)).toEqual([5]);
+ });
+ });
+
+ describe('mapData', () => {
+ it('returns filteredPublicData, since it is already GeoJSON', () => {
+ const [state] = makeData(points, {
+ filters: {
+ offices: ['Mayor'],
+ },
+ });
+
+ expect(publicData.mapData(state)).toEqual({
+ type: 'FeatureCollection',
+ features: points.slice(0, 6),
+ });
+ });
+ });
+ });
+
+ describe('summaryData', () => {
+ const summaryPoint = (
+ campaignName,
+ contributorName,
+ amount,
+ matchAmount,
+ oaeType
+ ) => point({ campaignName, contributorName, amount, matchAmount, oaeType });
+
+ const points = [
+ summaryPoint('Zyx', 'Abc', 10, null, 'allowable'),
+ summaryPoint('Zyx', 'Abc', 20, 120, 'matchable'),
+ summaryPoint('Yxw', 'Def', 30, 150, 'matchable'),
+ summaryPoint('Xwv', 'Ghi', 100, null, 'public_matching_contribution'),
+ summaryPoint('Wvu', 'Jkl', 5, 30, 'matchable'),
+ summaryPoint(
+ 'Wvu',
+ 'Miscellaneous Cash Contributions $100 and under ',
+ 150,
+ null,
+ 'allowable'
+ ),
+ summaryPoint(
+ 'Wvu',
+ 'Miscellaneous Cash Contributions $100 and under ',
+ 150,
+ null,
+ 'allowable'
+ ),
+ ];
+
+ const [state] = makeData(points);
+
+ it('returns the total number of donations (excluding public_matching_contribution', () => {
+ expect(publicData.summaryData(state).donationsCount).toEqual(
+ points.length - 1
+ );
+ });
+
+ it('returns the total number of campaigns (uniqued by campaign name, excluding public matching contribution)', () => {
+ expect(publicData.summaryData(state).campaignsCount).toEqual(3);
+ });
+
+ it('returns the total number of donors (uniqued by contributor name, excluding public matching contribution, counting each bundled contribution as 1 donor)', () => {
+ expect(publicData.summaryData(state).donorsCount).toEqual(5);
+ });
+
+ it('returns the total amount contributed (excluding public matching contributions) and the total amount matched', () => {
+ const total = 10 + 20 + 30 + 5 + 150 + 150;
+ const matchTotal = 120 + 150 + 30;
+ expect(publicData.summaryData(state).totalAmountContributed).toEqual(
+ total
+ );
+ expect(publicData.summaryData(state).totalAmountMatched).toEqual(
+ matchTotal
+ );
+ });
+
+ it('returns the median contribution size, excluding public_matching_contribution types', () => {
+ // Contributions
+ // [ 10, 20, 30, 100, 5, 150, 150 ]
+ // Exclude public_matching_contribution types
+ // [ 10, 20, 30, 5, 150, 150 ]
+ // Sort
+ // [ 5.23, 10, 20, 30, 150, 150 ]
+ // Median (avg middle data points)
+ // (20 + 30) / 2 = 25
+ expect(publicData.summaryData(state).medianContributionSize).toEqual(25);
+ });
+ });
+
+ describe('donationSizeByDonationRange', () => {
+ it('buckets and summates donations appropriately', () => {
+ const points = [
+ point({ amount: 0 }),
+ point({ amount: 5 }),
+ point({ amount: 10 }),
+ point({ amount: 20 }),
+ point({ amount: 30 }),
+ point({ amount: 50 }),
+ point({ amount: 100 }),
+ point({ amount: 150 }),
+ point({ amount: 200 }),
+ point({ amount: 500 }),
+ point({ amount: 750 }),
+ point({ amount: 1000 }),
+ point({ amount: 2500 }),
+ ];
+
+ const [state] = makeData(points);
+
+ expect(publicData.donationSizeByDonationRange(state)).toEqual({
+ micro: {
+ total: 0 + 5 + 10 + 20,
+ contributions: [0, 5, 10, 20],
+ },
+ small: {
+ total: 30 + 50 + 100,
+ contributions: [30, 50, 100],
+ },
+ medium: {
+ total: 150 + 200,
+ contributions: [150, 200],
+ },
+ large: {
+ total: 500 + 750 + 1000,
+ contributions: [500, 750, 1000],
+ },
+ mega: {
+ total: 2500,
+ contributions: [2500],
+ },
+ });
+ });
+
+ it('buckets and summates donations appropriately including ', () => {
+ const points = [
+ point({ amount: 0 }),
+ point({ amount: 5 }),
+ point({ amount: 10 }),
+ point({ amount: 20 }),
+ point({ amount: 30 }),
+ point({ amount: 50 }),
+ point({ amount: 100 }),
+ point({ amount: 150 }),
+ point({ amount: 200 }),
+ point({ amount: 500 }),
+ point({ amount: 750 }),
+ point({ amount: 1000 }),
+ point({
+ amount: 2500,
+ contributorName: 'Miscellaneous Cash Contributions $100 and under ',
+ }),
+ point({ amount: 2500 }),
+ ];
+
+ const [state] = makeData(points);
+
+ expect(publicData.donationSizeByDonationRange(state)).toEqual({
+ micro: {
+ total: 0 + 5 + 10 + 20,
+ contributions: [0, 5, 10, 20],
+ },
+ small: {
+ total: 30 + 50 + 100 + 2500,
+ contributions: [30, 50, 100, 2500],
+ },
+ medium: {
+ total: 150 + 200,
+ contributions: [150, 200],
+ },
+ large: {
+ total: 500 + 750 + 1000,
+ contributions: [500, 750, 1000],
+ },
+ mega: {
+ total: 2500,
+ contributions: [2500],
+ },
+ });
+ });
+
+ it('reports 0 for any empty buckets', () => {
+ const points = [
+ point({ amount: 30 }),
+ point({ amount: 50 }),
+ point({ amount: 1000 }),
+ point({ amount: 2500 }),
+ ];
+
+ const [state] = makeData(points);
+
+ expect(publicData.donationSizeByDonationRange(state)).toEqual({
+ micro: {
+ total: 0,
+ contributions: [],
+ },
+ small: {
+ total: 30 + 50,
+ contributions: [30, 50],
+ },
+ medium: {
+ total: 0,
+ contributions: [],
+ },
+ large: {
+ total: 1000,
+ contributions: [1000],
+ },
+ mega: {
+ total: 2500,
+ contributions: [2500],
+ },
+ });
+ });
+ });
+
+ describe('donationSizeByDonationRangeByCandidate', () => {
+ const summaryPoint = (campaignId, campaignName, amount) =>
+ point({
+ campaignId,
+ campaignName,
+ amount,
+ officeSought: 'Mayor',
+ });
+
+ const points = [
+ summaryPoint('1', 'One', 5),
+ summaryPoint('1', 'One', 1000),
+
+ summaryPoint('2', 'Two', 5),
+ summaryPoint('2', 'Two', 20),
+ ];
+
+ const filters = {
+ campaigns: [
+ { id: '1', name: 'One' },
+ { id: '2', name: 'Two' },
+ ],
+ };
+
+ const [stateWithSelections] = makeData(points, { filters });
+
+ it('buckets and summates appropriately in an object by candidate', () => {
+ expect(
+ publicData.donationSizeByDonationRangeByCandidate(stateWithSelections)
+ ).toEqual({
+ One: {
+ micro: {
+ total: 5,
+ contributions: [5],
+ },
+ small: {
+ total: 0,
+ contributions: [],
+ },
+ medium: {
+ total: 0,
+ contributions: [],
+ },
+ large: {
+ total: 1000,
+ contributions: [1000],
+ },
+ mega: {
+ total: 0,
+ contributions: [],
+ },
+ },
+ Two: {
+ micro: {
+ total: 5 + 20,
+ contributions: [5, 20],
+ },
+ small: {
+ total: 0,
+ contributions: [],
+ },
+ medium: {
+ total: 0,
+ contributions: [],
+ },
+ large: {
+ total: 0,
+ contributions: [],
+ },
+ mega: {
+ total: 0,
+ contributions: [],
+ },
+ },
+ });
+ });
+ });
+
+ describe('aggregatedContributorTypes', () => {
+ const summaryPoint = (contributorType, amount) =>
+ point({ contributorType, amount });
+
+ it('buckets and summates donations appropriately', () => {
+ const points = [
+ summaryPoint('individual', 10),
+ summaryPoint('individual', 15),
+ summaryPoint('business', 100),
+ summaryPoint('business', 1450),
+ summaryPoint('business', 890),
+ summaryPoint('family', 50),
+ summaryPoint('labor', 500),
+ summaryPoint('political_committee', 30),
+ summaryPoint('political_party', 100),
+ summaryPoint('unregistered', 150),
+ summaryPoint('other', 10),
+ summaryPoint(null, 9),
+ ];
+
+ const [state] = makeData(points);
+
+ expect(publicData.aggregatedContributorTypes(state)).toEqual([
+ {
+ type: 'individual',
+ label: 'Individual',
+ total: 10 + 15,
+ contributions: [10, 15],
+ count: 2,
+ },
+ {
+ type: 'business',
+ label: 'Business',
+ total: 100 + 1450 + 890,
+ contributions: [100, 890, 1450],
+ count: 3,
+ },
+ {
+ type: 'family',
+ label: 'Family',
+ total: 50,
+ contributions: [50],
+ count: 1,
+ },
+ {
+ type: 'labor',
+ label: 'Labor',
+ total: 500,
+ contributions: [500],
+ count: 1,
+ },
+ {
+ type: 'political_committee',
+ label: 'Political Committee',
+ total: 30,
+ contributions: [30],
+ count: 1,
+ },
+ {
+ type: 'political_party',
+ label: 'Political Party',
+ total: 100,
+ contributions: [100],
+ count: 1,
+ },
+ {
+ type: 'unregistered',
+ label: 'Unregistered',
+ total: 150,
+ contributions: [150],
+ count: 1,
+ },
+ {
+ type: 'other',
+ label: 'Other',
+ total: 9 + 10,
+ contributions: [9, 10],
+ count: 2,
+ },
+ ]);
+ });
+
+ it('reports 0 for any empty buckets', () => {
+ const points = [
+ summaryPoint('individual', 10),
+ summaryPoint('individual', 15),
+ summaryPoint('business', 100),
+ summaryPoint('business', 1450),
+ summaryPoint('business', 890),
+ summaryPoint('unregistered', 150),
+ ];
+
+ const [state] = makeData(points);
+
+ expect(publicData.aggregatedContributorTypes(state)).toEqual([
+ {
+ type: 'individual',
+ label: 'Individual',
+ total: 10 + 15,
+ contributions: [10, 15],
+ count: 2,
+ },
+ {
+ type: 'business',
+ label: 'Business',
+ total: 100 + 1450 + 890,
+ contributions: [100, 890, 1450],
+ count: 3,
+ },
+ {
+ type: 'family',
+ label: 'Family',
+ total: 0,
+ contributions: [],
+ count: 0,
+ },
+ {
+ type: 'labor',
+ label: 'Labor',
+ total: 0,
+ contributions: [],
+ count: 0,
+ },
+ {
+ type: 'political_committee',
+ label: 'Political Committee',
+ total: 0,
+ contributions: [],
+ count: 0,
+ },
+ {
+ type: 'political_party',
+ label: 'Political Party',
+ total: 0,
+ contributions: [],
+ count: 0,
+ },
+ {
+ type: 'unregistered',
+ label: 'Unregistered',
+ total: 150,
+ contributions: [150],
+ count: 1,
+ },
+ {
+ type: 'other',
+ label: 'Other',
+ total: 0,
+ contributions: [],
+ count: 0,
+ },
+ ]);
+ });
+ });
+
+ describe('aggregatedContributorTypesByCandidate', () => {
+ const summaryPoint = (campaignId, campaignName, amount, contributorType) =>
+ point({
+ campaignId,
+ campaignName,
+ amount,
+ contributorType,
+ });
+
+ const points = [
+ summaryPoint('1', 'One', 5, 'individual'),
+ summaryPoint('1', 'One', 5, 'individual'),
+ summaryPoint('1', 'One', 20, 'unregistered'),
+ summaryPoint('2', 'Two', 1000, 'business'),
+ ];
+
+ const filters = {
+ campaigns: [
+ { id: '1', name: 'One' },
+ { id: '2', name: 'Two' },
+ ],
+ };
+
+ const [stateWithSelections] = makeData(points, { filters });
+
+ it('buckets and summates appropriately in an object by candidate', () => {
+ expect(
+ publicData.aggregatedContributorTypesByCandidate(stateWithSelections)
+ ).toEqual({
+ One: [
+ {
+ type: 'individual',
+ label: 'Individual',
+ total: 5 + 5,
+ contributions: [5, 5],
+ count: 2,
+ },
+ {
+ type: 'business',
+ label: 'Business',
+ total: 0,
+ contributions: [],
+ count: 0,
+ },
+ {
+ type: 'family',
+ label: 'Family',
+ total: 0,
+ contributions: [],
+ count: 0,
+ },
+ {
+ type: 'labor',
+ label: 'Labor',
+ total: 0,
+ contributions: [],
+ count: 0,
+ },
+ {
+ type: 'political_committee',
+ label: 'Political Committee',
+ total: 0,
+ contributions: [],
+ count: 0,
+ },
+ {
+ type: 'political_party',
+ label: 'Political Party',
+ total: 0,
+ contributions: [],
+ count: 0,
+ },
+ {
+ type: 'unregistered',
+ label: 'Unregistered',
+ total: 20,
+ contributions: [20],
+ count: 1,
+ },
+ {
+ type: 'other',
+ label: 'Other',
+ total: 0,
+ contributions: [],
+ count: 0,
+ },
+ ],
+ Two: [
+ {
+ type: 'individual',
+ label: 'Individual',
+ total: 0,
+ contributions: [],
+ count: 0,
+ },
+ {
+ type: 'business',
+ label: 'Business',
+ total: 1000,
+ contributions: [1000],
+ count: 1,
+ },
+ {
+ type: 'family',
+ label: 'Family',
+ total: 0,
+ contributions: [],
+ count: 0,
+ },
+ {
+ type: 'labor',
+ label: 'Labor',
+ total: 0,
+ contributions: [],
+ count: 0,
+ },
+ {
+ type: 'political_committee',
+ label: 'Political Committee',
+ total: 0,
+ contributions: [],
+ count: 0,
+ },
+ {
+ type: 'political_party',
+ label: 'Political Party',
+ total: 0,
+ contributions: [],
+ count: 0,
+ },
+ {
+ type: 'unregistered',
+ label: 'Unregistered',
+ total: 0,
+ contributions: [],
+ count: 0,
+ },
+ {
+ type: 'other',
+ label: 'Other',
+ total: 0,
+ contributions: [],
+ count: 0,
+ },
+ ],
+ });
+ });
+ });
+
+ describe('aggregatedContributionTypes', () => {
+ const summaryPoint = (contributionSubType, amount) =>
+ point({ contributionSubType, amount });
+
+ it('buckets and summates donations appropriately', () => {
+ const points = [
+ summaryPoint('cash', 10),
+ summaryPoint('cash', 14),
+ summaryPoint('inkind_onefish', 40),
+ summaryPoint('inkind_2_fish', 95),
+ summaryPoint('inkind_redfish', 100),
+ summaryPoint('inkind_bluefish', 139),
+ summaryPoint('other', 10),
+ summaryPoint('nothing', 25),
+ summaryPoint(null, 5),
+ ];
+
+ const [state] = makeData(points);
+
+ expect(publicData.aggregatedContributionTypes(state)).toEqual([
+ {
+ type: 'cash',
+ formattedType: 'Cash',
+ total: 10 + 14,
+ contributions: [10, 14],
+ count: 2,
+ },
+ {
+ type: 'inkind',
+ formattedType: 'Inkind',
+ total: 40 + 95 + 100 + 139,
+ contributions: [40, 95, 100, 139],
+ count: 4,
+ },
+ {
+ type: 'other',
+ formattedType: 'Other',
+ total: 10 + 25 + 5,
+ contributions: [5, 10, 25],
+ count: 3,
+ },
+ ]);
+ });
+
+ it('reports 0 for any empty buckets', () => {
+ const points = [
+ summaryPoint('inkind_onefish', 40),
+ summaryPoint('inkind_2_fish', 95),
+ summaryPoint('inkind_redfish', 100),
+ summaryPoint('inkind_bluefish', 139),
+ ];
+
+ const [state] = makeData(points);
+
+ expect(publicData.aggregatedContributionTypes(state)).toEqual([
+ {
+ type: 'cash',
+ formattedType: 'Cash',
+ total: 0,
+ contributions: [],
+ count: 0,
+ },
+ {
+ type: 'inkind',
+ formattedType: 'Inkind',
+ total: 40 + 95 + 100 + 139,
+ contributions: [40, 95, 100, 139],
+ count: 4,
+ },
+ {
+ type: 'other',
+ formattedType: 'Other',
+ total: 0,
+ contributions: [],
+ count: 0,
+ },
+ ]);
+ });
+ });
+
+ describe('aggregatedContributionTypesByCandidate', () => {
+ const summaryPoint = (
+ campaignId,
+ campaignName,
+ amount,
+ contributionSubType
+ ) =>
+ point({
+ campaignId,
+ campaignName,
+ amount,
+ contributionSubType,
+ });
+
+ const points = [
+ summaryPoint('1', 'One', 5, 'cash'),
+ summaryPoint('1', 'One', 7, 'cash'),
+ summaryPoint('1', 'One', 20, 'inkind_onefish'),
+ summaryPoint('2', 'Two', 1000, 'other'),
+ ];
+
+ const filters = {
+ campaigns: [
+ { id: '1', name: 'One' },
+ { id: '2', name: 'Two' },
+ ],
+ };
+
+ const [stateWithSelections] = makeData(points, { filters });
+
+ it('buckets and summates donations appropriately in an object by candidate', () => {
+ expect(
+ publicData.aggregatedContributionTypesByCandidate(stateWithSelections)
+ ).toEqual({
+ One: [
+ {
+ type: 'cash',
+ formattedType: 'Cash',
+ total: 5 + 7,
+ contributions: [5, 7],
+ count: 2,
+ },
+ {
+ type: 'inkind',
+ formattedType: 'Inkind',
+ total: 20,
+ contributions: [20],
+ count: 1,
+ },
+ {
+ type: 'other',
+ formattedType: 'Other',
+ total: 0,
+ contributions: [],
+ count: 0,
+ },
+ ],
+ Two: [
+ {
+ type: 'cash',
+ formattedType: 'Cash',
+ total: 0,
+ contributions: [],
+ count: 0,
+ },
+ {
+ type: 'inkind',
+ formattedType: 'Inkind',
+ total: 0,
+ contributions: [],
+ count: 0,
+ },
+ {
+ type: 'other',
+ formattedType: 'Other',
+ total: 1000,
+ contributions: [1000],
+ count: 1,
+ },
+ ],
+ });
+ });
+ });
+
+ describe('aggregatedContributionsByRegion', () => {
+ const summaryPoint = (city, state, amount) =>
+ point({ city, state, amount });
+
+ it('buckets and summates donations appropriately', () => {
+ const points = [
+ summaryPoint('portland', 'or', 10),
+ summaryPoint('portland', 'or', 25),
+ summaryPoint('portland', 'me', 200),
+ summaryPoint('eugene', 'or', 100),
+ summaryPoint('gresham', 'or', 25),
+ summaryPoint('wamic', 'or', 100),
+ summaryPoint('culver', 'or', 50),
+ summaryPoint('new york city', 'ny', 1000),
+ ];
+
+ const [state] = makeData(points);
+
+ expect(publicData.aggregatedContributionsByRegion(state)).toEqual([
+ {
+ type: 'portland',
+ label: 'Portland',
+ total: 10 + 25,
+ contributions: [10, 25],
+ count: 2,
+ },
+ {
+ type: 'oregon',
+ label: 'Oregon',
+ total: 100 + 25 + 100 + 50,
+ contributions: [25, 50, 100, 100],
+ count: 4,
+ },
+ {
+ type: 'out_of_state',
+ label: 'Out Of State',
+ total: 200 + 1000,
+ contributions: [200, 1000],
+ count: 2,
+ },
+ ]);
+ });
+
+ it('reports 0 for any empty buckets', () => {
+ const points = [
+ summaryPoint('eugene', 'or', 100),
+ summaryPoint('gresham', 'or', 25),
+ summaryPoint('wamic', 'or', 100),
+ summaryPoint('culver', 'or', 50),
+ ];
+
+ const [state] = makeData(points);
+
+ expect(publicData.aggregatedContributionsByRegion(state)).toEqual([
+ {
+ type: 'portland',
+ label: 'Portland',
+ total: 0,
+ contributions: [],
+ count: 0,
+ },
+ {
+ type: 'oregon',
+ label: 'Oregon',
+ total: 100 + 25 + 100 + 50,
+ contributions: [25, 50, 100, 100],
+ count: 4,
+ },
+ {
+ type: 'out_of_state',
+ label: 'Out Of State',
+ total: 0,
+ contributions: [],
+ count: 0,
+ },
+ ]);
+ });
+ });
+
+ describe('aggregatedContributionsByRegionByCandidate', () => {
+ const summaryPoint = (campaignId, campaignName, amount, city, state) =>
+ point({
+ campaignId,
+ campaignName,
+ amount,
+ city,
+ state,
+ });
+
+ const points = [
+ summaryPoint('1', 'One', 5, 'portland', 'or'),
+ summaryPoint('1', 'One', 7, 'gresham', 'or'),
+ summaryPoint('1', 'One', 20, 'washington', 'dc'),
+ summaryPoint('2', 'Two', 1000, 'washington', 'dc'),
+ ];
+
+ const filters = {
+ campaigns: [
+ { id: '1', name: 'One' },
+ { id: '2', name: 'Two' },
+ ],
+ };
+
+ const [stateWithSelections] = makeData(points, { filters });
+
+ it('aggregates and summates appropriately in an object by candidate', () => {
+ expect(
+ publicData.aggregatedContributionsByRegionByCandidate(
+ stateWithSelections
+ )
+ ).toEqual({
+ One: [
+ {
+ type: 'portland',
+ label: 'Portland',
+ total: 5,
+ contributions: [5],
+ count: 1,
+ },
+ {
+ type: 'oregon',
+ label: 'Oregon',
+ total: 7,
+ contributions: [7],
+ count: 1,
+ },
+ {
+ type: 'out_of_state',
+ label: 'Out Of State',
+ total: 20,
+ contributions: [20],
+ count: 1,
+ },
+ ],
+ Two: [
+ {
+ type: 'portland',
+ label: 'Portland',
+ total: 0,
+ contributions: [],
+ count: 0,
+ },
+ {
+ type: 'oregon',
+ label: 'Oregon',
+ total: 0,
+ contributions: [],
+ count: 0,
+ },
+ {
+ type: 'out_of_state',
+ label: 'Out Of State',
+ total: 1000,
+ contributions: [1000],
+ count: 1,
+ },
+ ],
+ });
+ });
+ });
+
+ describe('campaignsTable', () => {
+ const summaryPoint = (
+ campaignId,
+ campaignName,
+ contributorName,
+ amount,
+ matchAmount,
+ oaeType
+ ) =>
+ point({
+ campaignId,
+ campaignName,
+ contributorName,
+ amount,
+ matchAmount,
+ oaeType,
+ officeSought: 'Mayor',
+ });
+
+ // public_matching_contribution
+
+ const points = [
+ summaryPoint('1', 'One', 'Abc', 5, 30, 'matchable'),
+ summaryPoint('1', 'One', 'Def', 20, 120, 'matchable'),
+ summaryPoint('1', 'One', 'Def', 100, 0, 'allowable'),
+ summaryPoint('1', 'One', 'Ghi', 1000, null, 'allowable'),
+
+ summaryPoint('2', 'Two', 'Def', 5, 30, 'matchable'),
+ summaryPoint('2', 'Two', 'Ghi', 5, 30, 'matchable'),
+ summaryPoint('2', 'Two', 'Ghi', 20, 120, 'matchable'),
+ summaryPoint('2', 'Two', 'Jkl', 25, 150, 'matchable'),
+ summaryPoint('2', 'Two', 'Jkl', 35, 210, 'matchable'),
+ summaryPoint('2', 'Two', 'Mno', 100, 0, 'allowable'),
+ summaryPoint(
+ '2',
+ 'Two',
+ 'Mno',
+ 500,
+ null,
+ 'public_matching_contribution'
+ ),
+
+ summaryPoint('3', 'Three', 'Abc', 50, 300, 'matchable'),
+ summaryPoint('3', 'Three', 'Abc', 50, 300, 'matchable'),
+ summaryPoint('3', 'Three', 'Abc', 78, 0, 'allowable'),
+ summaryPoint('3', 'Three', 'Abc', 501, 30, 'allowable'),
+
+ summaryPoint('4', 'Four', 'Def', 5, 30, 'matchable'),
+ summaryPoint('4', 'Four', 'Ghi', 6, 36, 'matchable'),
+ summaryPoint('4', 'Four', 'Jkl', 7, 42, 'matchable'),
+ ];
+
+ const [state] = makeData(points);
+
+ expect(publicData.campaignsTable(state)).toEqual([
+ {
+ campaignId: '1',
+ campaignName: 'One',
+ campaignsCount: 1,
+ officeSought: 'Mayor',
+ participatingStatus: true,
+ donationsCount: 4,
+ donorsCount: 3,
+ totalAmountContributed: 5 + 20 + 100 + 1000,
+ totalAmountMatched: 30 + 120,
+ medianContributionSize: 60,
+ micro: {
+ total: 5 + 20,
+ contributions: [5, 20],
+ },
+ small: {
+ total: 100,
+ contributions: [100],
+ },
+ medium: {
+ total: 0,
+ contributions: [],
+ },
+ large: {
+ total: 1000,
+ contributions: [1000],
+ },
+ mega: {
+ total: 0,
+ contributions: [],
+ },
+ contributions: points.slice(0, 4).map(p => p.properties),
+ },
+ {
+ campaignId: '2',
+ campaignName: 'Two',
+ campaignsCount: 1,
+ officeSought: 'Mayor',
+ participatingStatus: true,
+ donationsCount: 6,
+ donorsCount: 4,
+ totalAmountContributed: 5 + 5 + 20 + 25 + 35 + 100,
+ totalAmountMatched: 30 + 30 + 120 + 150 + 210,
+ medianContributionSize: 22.5,
+ micro: {
+ total: 5 + 5 + 20 + 25,
+ contributions: [5, 5, 20, 25],
+ },
+ small: {
+ total: 35 + 100,
+ contributions: [35, 100],
+ },
+ medium: {
+ total: 0,
+ contributions: [],
+ },
+ large: {
+ total: 0,
+ contributions: [],
+ },
+ mega: {
+ total: 0,
+ contributions: [],
+ },
+ contributions: points.slice(4, 10).map(p => p.properties),
+ },
+ {
+ campaignId: '3',
+ campaignName: 'Three',
+ campaignsCount: 1,
+ officeSought: 'Mayor',
+ participatingStatus: true,
+ donationsCount: 4,
+ donorsCount: 1,
+ totalAmountContributed: 50 + 50 + 78 + 501,
+ totalAmountMatched: 300 + 300 + 30,
+ medianContributionSize: 64,
+ micro: {
+ total: 0,
+ contributions: [],
+ },
+ small: {
+ total: 50 + 50 + 78,
+ contributions: [50, 50, 78],
+ },
+ medium: {
+ total: 0,
+ contributions: [],
+ },
+ large: {
+ total: 501,
+ contributions: [501],
+ },
+ mega: {
+ total: 0,
+ contributions: [],
+ },
+ contributions: points.slice(11, 15).map(p => p.properties),
+ },
+ {
+ campaignId: '4',
+ campaignName: 'Four',
+ campaignsCount: 1,
+ officeSought: 'Mayor',
+ participatingStatus: true,
+ donationsCount: 3,
+ donorsCount: 3,
+ totalAmountContributed: 5 + 6 + 7,
+ totalAmountMatched: 30 + 36 + 42,
+ medianContributionSize: 6,
+ micro: {
+ total: 5 + 6 + 7,
+ contributions: [5, 6, 7],
+ },
+ small: {
+ total: 0,
+ contributions: [],
+ },
+ medium: {
+ total: 0,
+ contributions: [],
+ },
+ large: {
+ total: 0,
+ contributions: [],
+ },
+ mega: {
+ total: 0,
+ contributions: [],
+ },
+ contributions: points.slice(15).map(p => p.properties),
+ },
+ ]);
+ });
+});
diff --git a/app2/src/state/ducks/summary.js b/app2/src/state/ducks/summary.js
new file mode 100644
index 000000000..2b304c3b7
--- /dev/null
+++ b/app2/src/state/ducks/summary.js
@@ -0,0 +1,69 @@
+/* eslint-disable no-unused-vars */
+import createReducer from '../utils/createReducer';
+import createActionTypes from '../utils/createActionTypes';
+import action from '../utils/action';
+
+export const STATE_KEY = 'summary';
+
+// Action Types
+export const actionTypes = {
+ GET_SUMMARY: createActionTypes(STATE_KEY, 'GET_SUMMARY'),
+};
+
+// Initial State
+export const initialState = {
+ isLoading: false,
+ error: null,
+ contributions: [],
+ expenditures: [],
+};
+// Reducer
+
+export default createReducer(initialState, {
+ [actionTypes.GET_SUMMARY.REQUEST]: state => {
+ return { ...state, isLoading: true };
+ },
+ [actionTypes.GET_SUMMARY.SUCCESS]: (state, action) => {
+ return {
+ isLoading: false,
+ contributions: action.contributions,
+ expenditures: action.expenditures,
+ };
+ },
+ [actionTypes.GET_SUMMARY.FAILURE]: (state, action) => {
+ return { ...state, isLoading: false, error: action.error };
+ },
+});
+
+// Action Creators
+export const actionCreators = {
+ getStatusSummary: {
+ request: () => action(actionTypes.GET_SUMMARY.REQUEST),
+ success: (contributions, expenditures) =>
+ action(actionTypes.GET_SUMMARY.SUCCESS, {
+ contributions,
+ expenditures,
+ }),
+ failure: error => action(actionTypes.GET_SUMMARY.FAILURE, { error }),
+ },
+};
+
+// Side Effects, e.g. thunks
+// attrs of campaignId or governmentId
+export function getStatusSummaryAction(attrs) {
+ return async (dispatch, getState, { api, schema }) => {
+ dispatch(actionCreators.getStatusSummary.request());
+ try {
+ const response = await api.getStatusSummary(attrs);
+ const body = await response.json();
+ dispatch(
+ actionCreators.getStatusSummary.success(
+ body.contributions,
+ body.expenditures
+ )
+ );
+ } catch (error) {
+ dispatch(actionCreators.getStatusSummary.failure(error));
+ }
+ };
+}
diff --git a/app2/src/state/ducks/users.js b/app2/src/state/ducks/users.js
new file mode 100644
index 000000000..2c3615f09
--- /dev/null
+++ b/app2/src/state/ducks/users.js
@@ -0,0 +1,252 @@
+/* eslint-disable no-unused-vars */
+import { normalize } from 'normalizr';
+import { createSelector } from 'reselect';
+import { get, startCase } from 'lodash';
+import { flashMessage } from 'redux-flash';
+import { push } from 'connected-react-router';
+import createReducer from '../utils/createReducer';
+import createActionTypes from '../utils/createActionTypes';
+import action from '../utils/action';
+import { addEntities, ADD_ENTITIES, resetState, RESET_STATE } from './common';
+import { removePermission } from './permissions';
+import { clearModal } from './modal';
+
+export const STATE_KEY = 'users';
+
+// Action Types
+export const actionTypes = {
+ INVITE_USER: createActionTypes(STATE_KEY, 'INVITE_USER'),
+ RESEND_USER_INVITE: createActionTypes(STATE_KEY, 'RESEND_USER_INVITE'),
+ GET_GOVERNMENT_USERS: createActionTypes(STATE_KEY, 'GET_GOVERNMENT_USERS'),
+ GET_CAMPAIGN_USERS: createActionTypes(STATE_KEY, 'GET_CAMPAIGN_USERS'),
+ REMOVE_USER: createActionTypes(STATE_KEY, 'REMOVE_USER'),
+};
+
+// Initial State
+export const initialState = {
+ isLoading: false,
+ error: null,
+};
+
+export const resetUserState = resetState;
+// Reducer
+export default createReducer(initialState, {
+ [RESET_STATE]: () => {
+ return { ...initialState };
+ },
+ [ADD_ENTITIES]: (state, action) => {
+ return { ...state, ...action.payload.users };
+ },
+ [actionTypes.INVITE_USER.REQUEST]: state => {
+ return { ...state, isLoading: true };
+ },
+ [actionTypes.INVITE_USER.SUCCESS]: state => {
+ return { ...state, isLoading: false };
+ },
+ [actionTypes.INVITE_USER.FAILURE]: (state, action) => {
+ return { ...state, isLoading: false, error: action.error };
+ },
+ [actionTypes.RESEND_USER_INVITE.REQUEST]: state => {
+ return { ...state, isLoading: true };
+ },
+ [actionTypes.RESEND_USER_INVITE.SUCCESS]: state => {
+ return { ...state, isLoading: false };
+ },
+ [actionTypes.RESEND_USER_INVITE.FAILURE]: (state, action) => {
+ return { ...state, isLoading: false, error: action.error };
+ },
+ [actionTypes.GET_GOVERNMENT_USERS.REQUEST]: state => {
+ return { ...state, isLoading: true };
+ },
+ [actionTypes.GET_GOVERNMENT_USERS.SUCCESS]: state => {
+ return { ...state, isLoading: false };
+ },
+ [actionTypes.GET_GOVERNMENT_USERS.FAILURE]: (state, action) => {
+ return { ...state, isLoading: false, error: action.error };
+ },
+ [actionTypes.GET_CAMPAIGN_USERS.REQUEST]: state => {
+ return { ...state, isLoading: true };
+ },
+ [actionTypes.GET_CAMPAIGN_USERS.SUCCESS]: state => {
+ return { ...state, isLoading: false };
+ },
+ [actionTypes.GET_CAMPAIGN_USERS.FAILURE]: (state, action) => {
+ return { ...state, isLoading: false, error: action.error };
+ },
+ [actionTypes.REMOVE_USER.REQUEST]: (state, action) => {
+ return { ...state, isLoading: true, error: action.error || null };
+ },
+ [actionTypes.REMOVE_USER.SUCCESS]: (state, action) => {
+ const newState = { ...state, isLoading: false };
+ delete newState[action.userId];
+ return newState;
+ },
+ [actionTypes.REMOVE_USER.FAILURE]: (state, action) => {
+ return { ...state, isLoading: false, error: action.error };
+ },
+});
+
+// Action Creators
+export const actionCreators = {
+ inviteUser: {
+ request: () => action(actionTypes.INVITE_USER.REQUEST),
+ success: () => action(actionTypes.INVITE_USER.SUCCESS),
+ failure: error => action(actionTypes.INVITE_USER.FAILURE, { error }),
+ },
+ resendUserInvite: {
+ request: () => action(actionTypes.RESEND_USER_INVITE.REQUEST),
+ success: () => action(actionTypes.RESEND_USER_INVITE.SUCCESS),
+ failure: error => action(actionTypes.RESEND_USER_INVITE.FAILURE, { error }),
+ },
+ getGovernmentUsers: {
+ request: () => action(actionTypes.GET_GOVERNMENT_USERS.REQUEST),
+ success: () => action(actionTypes.GET_GOVERNMENT_USERS.SUCCESS),
+ failure: error =>
+ action(actionTypes.GET_GOVERNMENT_USERS.FAILURE, { error }),
+ },
+ getCampaignUsers: {
+ request: () => action(actionTypes.GET_CAMPAIGN_USERS.REQUEST),
+ success: () => action(actionTypes.GET_CAMPAIGN_USERS.SUCCESS),
+ failure: error => action(actionTypes.GET_CAMPAIGN_USERS.FAILURE, { error }),
+ },
+ removeUser: {
+ request: () => action(actionTypes.REMOVE_USER.REQUEST),
+ success: userId => action(actionTypes.REMOVE_USER.SUCCESS, { userId }),
+ failure: error => action(actionTypes.REMOVE_USER.FAILURE, { error }),
+ },
+};
+
+export function getGovernmentUsers(governmentId) {
+ return async (dispatch, getState, { api, schema }) => {
+ dispatch(actionCreators.getGovernmentUsers.request());
+ try {
+ const response = await api.getGovernmentUsers(governmentId);
+ const data = normalize(response, [schema.permission]);
+ dispatch(addEntities(data.entities));
+ dispatch(actionCreators.getGovernmentUsers.success());
+ } catch (error) {
+ dispatch(actionCreators.getGovernmentUsers.failure(error));
+ }
+ };
+}
+
+export function getCampaignUsers(campaignId) {
+ return async (dispatch, getState, { api, schema }) => {
+ dispatch(actionCreators.getCampaignUsers.request());
+ try {
+ const response = await api.getCampaignUsers(campaignId);
+ const data = normalize(response, [schema.permission]);
+ dispatch(addEntities(data.entities));
+ dispatch(actionCreators.getCampaignUsers.success());
+ } catch (error) {
+ dispatch(actionCreators.getCampaignUsers.failure(error));
+ }
+ };
+}
+
+// Side Effects, e.g. thunks
+export function inviteUser(
+ email,
+ firstName,
+ lastName,
+ campaignOrGovernmentId,
+ role = null
+) {
+ return async (dispatch, getState, { api }) => {
+ dispatch(actionCreators.inviteUser.request());
+ try {
+ const { status } = role
+ ? await api.inviteUsertoCampaign(
+ email,
+ firstName,
+ lastName,
+ campaignOrGovernmentId,
+ role
+ )
+ : await api.inviteUsertoGovernment(
+ email,
+ firstName,
+ lastName,
+ campaignOrGovernmentId
+ );
+ if (status === 201) {
+ dispatch(actionCreators.inviteUser.success());
+ role
+ ? dispatch(getCampaignUsers(campaignOrGovernmentId))
+ : dispatch(getGovernmentUsers(campaignOrGovernmentId));
+ dispatch(
+ flashMessage('User Invited', { props: { variant: 'success' } })
+ );
+ } else {
+ dispatch(actionCreators.inviteUser.failure());
+ }
+ } catch (error) {
+ dispatch(actionCreators.inviteUser.failure(error));
+ }
+ };
+}
+
+export function removeUser(userId, permissionId) {
+ return async (dispatch, getState, { api }) => {
+ dispatch(actionCreators.removeUser.request());
+ try {
+ const response = await api.removePermission(permissionId);
+ if (response.status === 200) {
+ dispatch(actionCreators.removeUser.success(userId));
+ dispatch(removePermission(permissionId));
+ dispatch(
+ flashMessage('User Removed', { props: { variant: 'success' } })
+ );
+ dispatch(push('/settings'));
+ dispatch(clearModal());
+ } else {
+ dispatch(actionCreators.removeUser.failure());
+ dispatch(
+ flashMessage('Unable to remove user', { props: { variant: 'error' } })
+ );
+ dispatch(clearModal());
+ }
+ } catch (error) {
+ dispatch(actionCreators.removeUser.failure(error));
+ dispatch(
+ flashMessage(`Unable to remove user - ${error}`, {
+ props: { variant: 'error' },
+ })
+ );
+ dispatch(clearModal());
+ }
+ };
+}
+
+export function resendUserInvite(userId) {
+ return async (dispatch, getState, { api }) => {
+ dispatch(actionCreators.resendUserInvite.request());
+ try {
+ const { status } = await api.resendInvite(userId);
+ status === 204
+ ? dispatch(actionCreators.resendUserInvite.success())
+ : dispatch(actionCreators.resendUserInvite.failure());
+ } catch (error) {
+ dispatch(actionCreators.resendUserInvite.failure(error));
+ }
+ };
+}
+
+// Selectors
+export const rootState = state => state || {};
+
+export const getUsers = createSelector(rootState, state =>
+ Object.values(state.permissions)
+ .filter(perm => !!get(perm, 'id'))
+ .map(perm => {
+ const userAndRole = { ...state.users[perm.user] };
+ userAndRole.role = startCase(perm.role);
+ userAndRole.roleId = perm.id;
+ return userAndRole;
+ })
+);
+
+export const isUsersLoading = createSelector(
+ rootState,
+ state => state.users.isLoading
+);
diff --git a/app2/src/state/ducks/users.test.js b/app2/src/state/ducks/users.test.js
new file mode 100644
index 000000000..5708d322e
--- /dev/null
+++ b/app2/src/state/ducks/users.test.js
@@ -0,0 +1,534 @@
+/* eslint-disable no-unused-vars */
+import configureMockStore from 'redux-mock-store';
+import thunk from 'redux-thunk';
+import * as users from './users';
+import * as permissions from './permissions';
+import * as api from '../../api';
+import * as schema from '../../api/schema';
+import { ADD_ENTITIES } from './common';
+
+const { actionTypes, actionCreators } = users;
+
+const middlewares = [thunk.withExtraArgument({ api, schema })];
+const mockStore = configureMockStore(middlewares);
+
+const govAdmin = {
+ email: 'govadmin@openelectionsportland.org',
+ password: 'password',
+};
+
+const invite = {
+ code: 'inviteme',
+ email: 'campaignStaff+1@openelectionsportland.org',
+ password: 'password',
+};
+
+const reset = {
+ code: 'resetme',
+ password: 'newpassword',
+};
+
+describe('Reducer', () => {
+ const reducer = users.default;
+ it('initial state', () => {
+ expect(reducer(undefined, {})).toEqual({
+ isLoading: false,
+ error: null,
+ });
+ });
+
+ it('invite', () => {
+ expect(
+ reducer(undefined, {
+ type: actionTypes.INVITE_USER.REQUEST,
+ })
+ ).toEqual({
+ isLoading: true,
+ error: null,
+ });
+
+ expect(
+ reducer(undefined, {
+ type: actionTypes.INVITE_USER.SUCCESS,
+ })
+ ).toEqual({
+ isLoading: false,
+ error: null,
+ });
+
+ expect(
+ reducer(undefined, {
+ type: actionTypes.INVITE_USER.FAILURE,
+ error: '',
+ })
+ ).toEqual({
+ isLoading: false,
+ error: '',
+ });
+ });
+
+ it('resend invite', () => {
+ expect(
+ reducer(undefined, {
+ type: actionTypes.RESEND_USER_INVITE.REQUEST,
+ })
+ ).toEqual({
+ isLoading: true,
+ error: null,
+ });
+
+ expect(
+ reducer(undefined, {
+ type: actionTypes.RESEND_USER_INVITE.SUCCESS,
+ })
+ ).toEqual({
+ isLoading: false,
+ error: null,
+ });
+
+ expect(
+ reducer(undefined, {
+ type: actionTypes.RESEND_USER_INVITE.FAILURE,
+ error: '',
+ })
+ ).toEqual({
+ isLoading: false,
+ error: '',
+ });
+ });
+
+ it('adds user entities', () => {
+ expect(
+ reducer(undefined, {
+ type: ADD_ENTITIES,
+ payload: {
+ users: {
+ '1': {},
+ },
+ },
+ })
+ ).toEqual({
+ '1': {},
+ isLoading: false,
+ error: null,
+ });
+ });
+
+ it('removeUser success', () => {
+ expect(
+ reducer(
+ {
+ 1: {
+ firstName: 'Dan',
+ lastName: 'Melton',
+ email: 'dan@civicsoftwarefoundation.org',
+ },
+ },
+ {
+ type: actionTypes.REMOVE_USER.SUCCESS,
+ userId: 1,
+ }
+ )
+ ).toEqual({
+ isLoading: false,
+ });
+ });
+
+ it('removeUser fail', () => {
+ expect(
+ reducer(
+ {
+ 1: {
+ firstName: 'Dan',
+ lastName: 'Melton',
+ email: 'dan@civicsoftwarefoundation.org',
+ },
+ isLoading: true,
+ error: null,
+ },
+ {
+ type: actionTypes.REMOVE_USER.FAILURE,
+ error: 'an error',
+ }
+ )
+ ).toEqual({
+ 1: {
+ firstName: 'Dan',
+ lastName: 'Melton',
+ email: 'dan@civicsoftwarefoundation.org',
+ },
+ isLoading: false,
+ error: 'an error',
+ });
+ });
+
+ it('removeUser request', () => {
+ expect(
+ reducer(
+ {
+ 1: {
+ firstName: 'Dan',
+ lastName: 'Melton',
+ email: 'dan@civicsoftwarefoundation.org',
+ },
+ isLoading: false,
+ error: null,
+ },
+ {
+ type: actionTypes.REMOVE_USER.REQUEST,
+ }
+ )
+ ).toEqual({
+ 1: {
+ firstName: 'Dan',
+ lastName: 'Melton',
+ email: 'dan@civicsoftwarefoundation.org',
+ },
+ isLoading: true,
+ error: null,
+ });
+ });
+});
+
+describe('Action Creators', () => {
+ it('invite request', () => {
+ const expectedAction = {
+ type: actionTypes.INVITE_USER.REQUEST,
+ };
+ expect(actionCreators.inviteUser.request()).toEqual(expectedAction);
+ });
+ it('invite success', () => {
+ const expectedAction = {
+ type: actionTypes.INVITE_USER.SUCCESS,
+ };
+ expect(actionCreators.inviteUser.success()).toEqual(expectedAction);
+ });
+ it('invite failure', () => {
+ const expectedAction = {
+ type: actionTypes.INVITE_USER.FAILURE,
+ };
+ expect(actionCreators.inviteUser.failure()).toEqual(expectedAction);
+ });
+
+ it('resend invite request', () => {
+ const expectedAction = {
+ type: actionTypes.RESEND_USER_INVITE.REQUEST,
+ };
+ expect(actionCreators.resendUserInvite.request()).toEqual(expectedAction);
+ });
+ it('resend invite success', () => {
+ const expectedAction = {
+ type: actionTypes.RESEND_USER_INVITE.SUCCESS,
+ };
+ expect(actionCreators.resendUserInvite.success()).toEqual(expectedAction);
+ });
+ it('resend invite failure', () => {
+ const expectedAction = {
+ type: actionTypes.RESEND_USER_INVITE.FAILURE,
+ };
+ expect(actionCreators.resendUserInvite.failure()).toEqual(expectedAction);
+ });
+
+ it('get government users request', () => {
+ const expectedAction = {
+ type: actionTypes.GET_GOVERNMENT_USERS.REQUEST,
+ };
+ expect(actionCreators.getGovernmentUsers.request()).toEqual(expectedAction);
+ });
+ it('get government users success', () => {
+ const expectedAction = {
+ type: actionTypes.GET_GOVERNMENT_USERS.SUCCESS,
+ };
+ expect(actionCreators.getGovernmentUsers.success()).toEqual(expectedAction);
+ });
+ it('get government users failure', () => {
+ const expectedAction = {
+ type: actionTypes.GET_GOVERNMENT_USERS.FAILURE,
+ };
+ expect(actionCreators.getGovernmentUsers.failure()).toEqual(expectedAction);
+ });
+
+ it('get campaign users request', () => {
+ const expectedAction = {
+ type: actionTypes.GET_CAMPAIGN_USERS.REQUEST,
+ };
+ expect(actionCreators.getCampaignUsers.request()).toEqual(expectedAction);
+ });
+ it('get campaign users success', () => {
+ const expectedAction = {
+ type: actionTypes.GET_CAMPAIGN_USERS.SUCCESS,
+ };
+ expect(actionCreators.getCampaignUsers.success()).toEqual(expectedAction);
+ });
+ it('get campaign users failure', () => {
+ const expectedAction = {
+ type: actionTypes.GET_CAMPAIGN_USERS.FAILURE,
+ };
+ expect(actionCreators.getCampaignUsers.failure()).toEqual(expectedAction);
+ });
+
+ it('removeUser Request', () => {
+ const expectedAction = {
+ type: actionTypes.REMOVE_USER.REQUEST,
+ };
+ expect(actionCreators.removeUser.request()).toEqual(expectedAction);
+ });
+
+ it('removeUser Success', () => {
+ const expectedAction = {
+ type: actionTypes.REMOVE_USER.SUCCESS,
+ userId: 1,
+ };
+ expect(actionCreators.removeUser.success(1)).toEqual(expectedAction);
+ });
+
+ it('removeUser Failure', () => {
+ const expectedAction = {
+ type: actionTypes.REMOVE_USER.FAILURE,
+ error: 'an error message',
+ };
+ expect(actionCreators.removeUser.failure('an error message')).toEqual(
+ expectedAction
+ );
+ });
+});
+
+let govAdminToken;
+let campaignAdminToken;
+let campaignStaffToken;
+let governmentId;
+let campaignId;
+
+describe('Side Effects', () => {
+ beforeAll(async () => {
+ let tokenResponse = await api.login(
+ 'govadmin@openelectionsportland.org',
+ 'password'
+ );
+ govAdminToken = tokenResponse.headers
+ .get('set-cookie')
+ .match(/=([a-zA-Z0-9].+); Path/)[1];
+ let decodedToken = api.decodeToken(govAdminToken);
+ governmentId = decodedToken.permissions[0].governmentId;
+
+ tokenResponse = await api.login(
+ 'campaignadmin@openelectionsportland.org',
+ 'password'
+ );
+ campaignAdminToken = tokenResponse.headers
+ .get('set-cookie')
+ .match(/=([a-zA-Z0-9].+); Path/)[1];
+ decodedToken = api.decodeToken(campaignAdminToken);
+ campaignId = decodedToken.permissions[0].campaignId;
+
+ tokenResponse = await api.login(
+ 'campaignstaff@openelectionsportland.org',
+ 'password'
+ );
+ campaignStaffToken = tokenResponse.headers
+ .get('set-cookie')
+ .match(/=([a-zA-Z0-9].+); Path/)[1];
+ });
+
+ beforeEach(() => {
+ delete process.env.TOKEN;
+ });
+
+ it('invite user to gov', async () => {
+ const expectedActions = [
+ { type: actionTypes.INVITE_USER.REQUEST },
+ { type: actionTypes.INVITE_USER.SUCCESS },
+ { type: actionTypes.GET_GOVERNMENT_USERS.REQUEST },
+ ];
+ const store = mockStore({});
+
+ process.env.TOKEN = govAdminToken;
+
+ return store
+ .dispatch(
+ users.inviteUser(
+ 'govadmin1@openelectionsportland.org',
+ 'Government2',
+ 'Admin2',
+ governmentId
+ )
+ )
+ .then(() => {
+ const actions = store.getActions();
+ expect(actions[0]).toEqual(expectedActions[0]);
+ expect(actions[1]).toEqual(expectedActions[1]);
+ expect(actions[2]).toEqual(expectedActions[2]);
+ });
+ });
+
+ it('invite user to gov failure', async () => {
+ const expectedActions = [
+ { type: actionTypes.INVITE_USER.REQUEST },
+ { type: actionTypes.INVITE_USER.FAILURE },
+ ];
+ const store = mockStore({});
+
+ process.env.TOKEN = campaignAdminToken;
+
+ return store
+ .dispatch(
+ users.inviteUser(
+ 'govadmin1@openelectionsportland.org',
+ 'Government2',
+ 'Admin2',
+ governmentId
+ )
+ )
+ .then(() => {
+ expect(store.getActions()).toEqual(expectedActions);
+ });
+ });
+
+ it('invite user to campaign', async () => {
+ const expectedActions = [
+ { type: actionTypes.INVITE_USER.REQUEST },
+ { type: actionTypes.INVITE_USER.SUCCESS },
+ { type: actionTypes.GET_CAMPAIGN_USERS.REQUEST },
+ ];
+ const store = mockStore({});
+
+ process.env.TOKEN = campaignAdminToken;
+
+ return store
+ .dispatch(
+ users.inviteUser(
+ 'campaignadmin1@openelectionsportland.org',
+ 'Government2',
+ 'Admin2',
+ campaignId,
+ api.UserRoleEnum.CAMPAIGN_STAFF
+ )
+ )
+ .then(() => {
+ const actions = store.getActions();
+ expect(actions[0]).toEqual(expectedActions[0]);
+ expect(actions[1]).toEqual(expectedActions[1]);
+ expect(actions[2]).toEqual(expectedActions[2]);
+ });
+ });
+
+ it('invite user to campaign failure', async () => {
+ const expectedActions = [
+ { type: actionTypes.INVITE_USER.REQUEST },
+ { type: actionTypes.INVITE_USER.FAILURE },
+ ];
+ const store = mockStore({});
+
+ return store
+ .dispatch(
+ users.inviteUser(
+ 'campaignadmin1@openelectionsportland.org',
+ 'Government2',
+ 'Admin2',
+ campaignId,
+ api.UserRoleEnum.CAMPAIGN_STAFF
+ )
+ )
+ .then(() => {
+ expect(store.getActions()).toEqual(expectedActions);
+ });
+ });
+
+ it('remove user failure', async () => {
+ const expectedActions = [
+ { type: actionTypes.REMOVE_USER.REQUEST },
+ { type: actionTypes.REMOVE_USER.FAILURE },
+ ];
+ const store = mockStore({});
+
+ process.env.TOKEN = campaignStaffToken;
+ const token = api.decodeToken(campaignStaffToken);
+ return store
+ .dispatch(users.removeUser(token.id, token.permissions[0].id))
+ .then(() => {
+ const actions = store.getActions();
+ expect(actions[0]).toEqual(expectedActions[0]);
+ expect(actions[1]).toEqual(expectedActions[1]);
+ });
+ });
+
+ it('remove user success', async () => {
+ process.env.TOKEN = govAdminToken;
+ const tokenResponse = await api.login(
+ 'campaignstaff+removeme2@openelectionsportland.org',
+ 'password'
+ );
+
+ const token = tokenResponse.headers
+ .get('set-cookie')
+ .match(/=([a-zA-Z0-9].+); Path/)[1];
+
+ const user = api.decodeToken(token);
+
+ const permissionId = user.permissions[0].id;
+
+ const expectedActions = [
+ { type: actionTypes.REMOVE_USER.REQUEST },
+ { type: actionTypes.REMOVE_USER.SUCCESS, userId: user.id },
+ { type: permissions.actionTypes.REMOVE_PERMISSION.SUCCESS, permissionId },
+ ];
+ const store = mockStore({});
+
+ return store.dispatch(users.removeUser(user.id, permissionId)).then(() => {
+ const actions = store.getActions();
+ expect(actions[0]).toEqual(expectedActions[0]);
+ expect(actions[1]).toEqual(expectedActions[1]);
+ expect(actions[2]).toEqual(expectedActions[2]);
+ });
+ });
+
+ it('fails to resend user invite as campaign admin', async () => {
+ const expectedActions = [
+ { type: actionTypes.RESEND_USER_INVITE.REQUEST },
+ { type: actionTypes.RESEND_USER_INVITE.FAILURE },
+ ];
+ const store = mockStore({});
+
+ process.env.TOKEN = campaignAdminToken;
+
+ return store.dispatch(users.resendUserInvite(null)).then(() => {
+ expect(store.getActions()).toEqual(expectedActions);
+ });
+ });
+
+ it('gets government users', async () => {
+ const expectedActions = [
+ { type: actionTypes.GET_GOVERNMENT_USERS.REQUEST },
+ { type: ADD_ENTITIES },
+ { type: actionTypes.GET_GOVERNMENT_USERS.SUCCESS },
+ ];
+ const store = mockStore({});
+
+ process.env.TOKEN = govAdminToken;
+
+ return store.dispatch(users.getGovernmentUsers(governmentId)).then(() => {
+ const actions = store.getActions();
+ expect(actions[0].type).toEqual(expectedActions[0].type);
+ expect(actions[1].type).toEqual(expectedActions[1].type);
+ expect(actions[2].type).toEqual(expectedActions[2].type);
+ });
+ });
+
+ it('gets campaign users', async () => {
+ const expectedActions = [
+ { type: actionTypes.GET_CAMPAIGN_USERS.REQUEST },
+ { type: ADD_ENTITIES },
+ { type: actionTypes.GET_CAMPAIGN_USERS.SUCCESS },
+ ];
+ const store = mockStore({});
+
+ process.env.TOKEN = campaignAdminToken;
+
+ return store.dispatch(users.getCampaignUsers(campaignId)).then(() => {
+ const actions = store.getActions();
+ expect(actions[0].type).toEqual(expectedActions[0].type);
+ expect(actions[1].type).toEqual(expectedActions[1].type);
+ expect(actions[2].type).toEqual(expectedActions[2].type);
+ });
+ });
+});
diff --git a/app2/src/state/index.ts b/app2/src/state/index.ts
new file mode 100644
index 000000000..b6d031d39
--- /dev/null
+++ b/app2/src/state/index.ts
@@ -0,0 +1,12 @@
+import { combineReducers } from "redux";
+import { reducer as flashReducer } from "redux-flash";
+
+// Whenever an action is dispatched, Redux will update each top-level application state property
+// using the reducer with the matching name. It's important that the names match exactly, and that
+// the reducer acts on the corresponding ApplicationState property type.
+export const createReducer = (asyncReducers: any) => {
+ return combineReducers({
+ flash: flashReducer,
+ ...asyncReducers,
+ });
+};
diff --git a/app2/src/state/slices/auth.ts b/app2/src/state/slices/auth.ts
new file mode 100644
index 000000000..11f1454da
--- /dev/null
+++ b/app2/src/state/slices/auth.ts
@@ -0,0 +1,55 @@
+import { createSlice, Draft, PayloadAction } from "@reduxjs/toolkit";
+
+// Export State Key
+export const STATE_KEY = "auth";
+
+export interface AuthState {
+ me: string;
+ assume: boolean;
+ isLoading: boolean;
+ error: null;
+}
+
+/**
+ * Default state object with initial values.
+ */
+// Initial State
+export const initialState = {
+ me: null,
+ assume: false,
+ isLoading: false,
+ error: null,
+} as const;
+
+/**
+ * Create a slice as a reducer containing actions.
+ *
+ * In this example actions are included in the slice. It is fine and can be
+ * changed based on your needs.
+ */
+export const userSlice = createSlice({
+ name: STATE_KEY,
+ initialState,
+ reducers: {
+ setName: (
+ state: Draft,
+ action: PayloadAction
+ ) => {
+ state.name = action.payload;
+ },
+ setEmail: (
+ state: Draft,
+ action: PayloadAction
+ ) => {
+ state.email = action.payload;
+ },
+ },
+});
+
+// A small helper of user state for `useSelector` function.
+export const getUserState = (state: { user: UserState }) => state.user;
+
+// Exports all actions
+export const { setName, setEmail } = userSlice.actions;
+
+export default userSlice.reducer;
diff --git a/app2/src/state/store.ts b/app2/src/state/store.ts
new file mode 100644
index 000000000..680091669
--- /dev/null
+++ b/app2/src/state/store.ts
@@ -0,0 +1,42 @@
+import { Action, configureStore, ThunkAction } from "@reduxjs/toolkit";
+import * as api from "../api";
+import * as schema from "../api/schema";
+
+export const store = configureStore({
+ reducer: {
+ // router: connectRouter(history),
+ // [ACTIVITIES_STATE_KEY]: activities,
+ [AUTH_STATE_KEY]: auth,
+ // [CAMPAIGNS_STATE_KEY]: campaigns,
+ // [CONTRIBUTIONS_STATE_KEY]: contributions,
+ // [MATCHES_STATE_KEY]: matches,
+ // [GOVERNMENTS_STATE_KEY]: governments,
+ // [PERMISSIONS_STATE_KEY]: permissions,
+ // [USERS_STATE_KEY]: users,
+ // [MODAL_STATE_KEY]: modal,
+ // [EXPENDITURES_STATE_KEY]: expenditures,
+ // [SUMMARY_STATE_KEY]: summary,
+ // [PAST_CONTRIBUTIONS_STATE_KEY]: pastContributions,
+ // [PUBLIC_DATA_STATE_KEY]: publicData,
+ // [EXTERNAL_DATA_STATE_KEY]: externalData,
+ },
+ middleware: (getDefaultMiddleware) =>
+ getDefaultMiddleware({
+ thunk: {
+ extraArgument: {
+ api,
+ schema,
+ },
+ },
+ // flashMiddleware()
+ }),
+});
+
+export type AppDispatch = typeof store.dispatch;
+export type RootState = ReturnType;
+export type AppThunk = ThunkAction<
+ ReturnType,
+ RootState,
+ unknown,
+ Action
+>;
diff --git a/app2/src/state/utils/action.js b/app2/src/state/utils/action.js
new file mode 100644
index 000000000..5bf12f630
--- /dev/null
+++ b/app2/src/state/utils/action.js
@@ -0,0 +1,3 @@
+export default function action(type, payload = {}) {
+ return { type, ...payload };
+}
diff --git a/app2/src/state/utils/common-action-emitter.js b/app2/src/state/utils/common-action-emitter.js
new file mode 100644
index 000000000..3848eeabb
--- /dev/null
+++ b/app2/src/state/utils/common-action-emitter.js
@@ -0,0 +1,9 @@
+const actionEmitter = type => payload => {
+ const ret = { type };
+ if (payload !== null) {
+ ret.payload = payload;
+ }
+ return ret;
+};
+
+export default actionEmitter;
diff --git a/app2/src/state/utils/createAction.js b/app2/src/state/utils/createAction.js
new file mode 100644
index 000000000..d20a13f96
--- /dev/null
+++ b/app2/src/state/utils/createAction.js
@@ -0,0 +1,3 @@
+export default function createAction(stateKey, base) {
+ return `openelections/${stateKey}/${base}`;
+}
diff --git a/app2/src/state/utils/createActionTypes.js b/app2/src/state/utils/createActionTypes.js
new file mode 100644
index 000000000..95b94ba12
--- /dev/null
+++ b/app2/src/state/utils/createActionTypes.js
@@ -0,0 +1,17 @@
+const REQUEST = 'REQUEST';
+const SUCCESS = 'SUCCESS';
+const FAILURE = 'FAILURE';
+
+export default function createActionTypes(stateKey, base) {
+ return [REQUEST, SUCCESS, FAILURE].reduce((acc, type) => {
+ acc[type] = `openelections/${stateKey}/${base}_${type}`;
+ return acc;
+ }, {});
+}
+
+export function createCustomActionTypes(stateKey, base, actions) {
+ return [...actions].reduce((acc, type) => {
+ acc[type] = `openelections/${stateKey}/${base}_${type}`;
+ return acc;
+ }, {});
+}
diff --git a/app2/src/state/utils/createReducer.js b/app2/src/state/utils/createReducer.js
new file mode 100644
index 000000000..59e456ca9
--- /dev/null
+++ b/app2/src/state/utils/createReducer.js
@@ -0,0 +1,8 @@
+export default function createReducer(initialState, handlers) {
+ return function reducer(state = initialState, action) {
+ if (Object.prototype.hasOwnProperty.call(handlers, action.type)) {
+ return handlers[action.type](state, action);
+ }
+ return state;
+ };
+}
diff --git a/app2/src/state/utils/helpers.js b/app2/src/state/utils/helpers.js
new file mode 100644
index 000000000..e6a6d19fa
--- /dev/null
+++ b/app2/src/state/utils/helpers.js
@@ -0,0 +1,20 @@
+export function downloadFile(data, fileName) {
+ const blob = new Blob([data], {
+ type: 'application/csv;charset=utf-8;',
+ });
+
+ if (window.navigator.msSaveBlob) {
+ // FOR IE BROWSER
+ navigator.msSaveBlob(blob, fileName);
+ } else {
+ // FOR OTHER BROWSERS
+ const link = document.createElement('a');
+ const csvUrl = URL.createObjectURL(blob);
+ link.href = csvUrl;
+ link.style = 'visibility:hidden';
+ link.download = fileName;
+ document.body.appendChild(link);
+ link.click();
+ document.body.removeChild(link);
+ }
+}
diff --git a/app2/styles/Home.module.css b/app2/styles/Home.module.css
new file mode 100755
index 000000000..32a57d52f
--- /dev/null
+++ b/app2/styles/Home.module.css
@@ -0,0 +1,116 @@
+.container {
+ padding: 0 2rem;
+}
+
+.main {
+ min-height: 100vh;
+ padding: 4rem 0;
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+}
+
+.footer {
+ display: flex;
+ flex: 1;
+ padding: 2rem 0;
+ border-top: 1px solid #eaeaea;
+ justify-content: center;
+ align-items: center;
+}
+
+.footer a {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ flex-grow: 1;
+}
+
+.title a {
+ color: #0070f3;
+ text-decoration: none;
+}
+
+.title a:hover,
+.title a:focus,
+.title a:active {
+ text-decoration: underline;
+}
+
+.title {
+ margin: 0;
+ line-height: 1.15;
+ font-size: 4rem;
+}
+
+.title,
+.description {
+ text-align: center;
+}
+
+.description {
+ margin: 4rem 0;
+ line-height: 1.5;
+ font-size: 1.5rem;
+}
+
+.code {
+ background: #fafafa;
+ border-radius: 5px;
+ padding: 0.75rem;
+ font-size: 1.1rem;
+ font-family: Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono,
+ Bitstream Vera Sans Mono, Courier New, monospace;
+}
+
+.grid {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ flex-wrap: wrap;
+ max-width: 800px;
+}
+
+.card {
+ margin: 1rem;
+ padding: 1.5rem;
+ text-align: left;
+ color: inherit;
+ text-decoration: none;
+ border: 1px solid #eaeaea;
+ border-radius: 10px;
+ transition: color 0.15s ease, border-color 0.15s ease;
+ max-width: 300px;
+}
+
+.card:hover,
+.card:focus,
+.card:active {
+ color: #0070f3;
+ border-color: #0070f3;
+}
+
+.card h2 {
+ margin: 0 0 1rem 0;
+ font-size: 1.5rem;
+}
+
+.card p {
+ margin: 0;
+ font-size: 1.25rem;
+ line-height: 1.5;
+}
+
+.logo {
+ height: 1em;
+ margin-left: 0.5rem;
+}
+
+@media (max-width: 600px) {
+ .grid {
+ width: 100%;
+ flex-direction: column;
+ }
+}
diff --git a/app2/styles/globals.css b/app2/styles/globals.css
new file mode 100755
index 000000000..e5e2dcc23
--- /dev/null
+++ b/app2/styles/globals.css
@@ -0,0 +1,16 @@
+html,
+body {
+ padding: 0;
+ margin: 0;
+ font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
+ Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
+}
+
+a {
+ color: inherit;
+ text-decoration: none;
+}
+
+* {
+ box-sizing: border-box;
+}
diff --git a/app2/tsconfig.json b/app2/tsconfig.json
new file mode 100755
index 000000000..b8e4cc588
--- /dev/null
+++ b/app2/tsconfig.json
@@ -0,0 +1,48 @@
+{
+ "compilerOptions": {
+ "target": "es5",
+ "lib": [
+ "dom",
+ "dom.iterable",
+ "esnext"
+ ],
+ "allowJs": true,
+ "skipLibCheck": true,
+ "strict": true,
+ "forceConsistentCasingInFileNames": true,
+ "esModuleInterop": true,
+ "module": "esnext",
+ "moduleResolution": "node",
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "jsx": "preserve",
+ "incremental": true,
+ // Generate d.ts files
+ "declaration": true,
+ // Types should go into this directory.
+ // Removing this would place the .d.ts files
+ // next to the .js files
+ "outDir": "types",
+ // go to js file when using IDE functions like
+ // "Go to Definition" in VSCode
+ "declarationMap": true,
+ // "typeRoots": [
+ // "node_modules/@types",
+ // "./types"
+ // ],
+ "paths": {
+ "*": [
+ "./types/*"
+ ]
+ },
+ "noEmit": true
+ },
+ "include": [
+ "next-env.d.ts",
+ "**/*.ts",
+ "**/*.tsx"
+ ],
+ "exclude": [
+ "node_modules"
+ ]
+}
diff --git a/app2/types/redux-flash.d.ts b/app2/types/redux-flash.d.ts
new file mode 100644
index 000000000..86b0afb5a
--- /dev/null
+++ b/app2/types/redux-flash.d.ts
@@ -0,0 +1,41 @@
+/** Declaration file generated by dts-gen */
+
+export function clearMessages(...args: any[]): void;
+
+export function flashErrorMessage(message: any, options: any): any;
+
+export function flashMessage(message: any, ...args: any[]): any;
+
+export function flashMessageType(p0: any, p1: any, p2: any, p3: any, p4: any, p5: any): any;
+
+export function flashSuccessMessage(message: any, ...args: any[]): any;
+
+export function getErrorMessages(state: any): any;
+
+export function getFlashMessages(state: any): any;
+
+export function getLatestMessage(state: any): any;
+
+export function getSuccessMessages(state: any): any;
+
+export function middleware(...args: any[]): any;
+
+export function reducer(state: any, action: any): any;
+
+export function removeMessage(...args: any[]): void;
+
+export namespace clearMessages {
+ function toString(): any;
+
+}
+
+export namespace flashMessageType {
+ function isRequired(p0: any, p1: any, p2: any, p3: any, p4: any, p5: any): any;
+
+}
+
+export namespace removeMessage {
+ function toString(): any;
+
+}
+