diff --git a/.eslintrc.js b/.eslintrc.js
index ca398a9ca6e487d159886d30c50ad8ab7f534bf3..79e71088ab5d4c45f77b0285b67edde80f2c399a 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -1,17 +1,62 @@
 module.exports = {
   root: true,
   env: {
-    node: true
+    node: true,
+    commonjs: true,
+    browser: true
   },
-  'extends': [
-    'plugin:vue/essential',
-    'eslint:recommended'
+  parserOptions: {
+    ecmaVersion: 2017,
+    parser: '@babel/eslint-parser'
+  },
+  extends: [
+    'eslint:recommended',
+    'plugin:vue/recommended'
   ],
   rules: {
-   // 'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
-    //'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off'
-  },
-  parserOptions: {
-    parser: 'babel-eslint'
+    'quote-props': [
+      'error',
+      'as-needed'
+    ],
+    'object-curly-spacing': [
+      'error',
+      'always',
+      {
+        arraysInObjects: true,
+        objectsInObjects: true
+      }
+    ],
+    indent: [
+      'error',
+      2
+    ],
+    'linebreak-style': [
+      'error',
+      'unix'
+    ],
+    semi: [
+      'error',
+      'always'
+    ],
+    quotes: [
+      'error',
+      'single',
+      {
+        avoidEscape: true
+      }
+    ],
+    'max-len': [
+      'error',
+      {
+        code: 120,
+        tabWidth: 2,
+        ignoreComments: true,
+        ignoreTrailingComments: true,
+        ignoreUrls: true,
+        ignoreStrings: true,
+        ignoreTemplateLiterals: true,
+        ignoreRegExpLiterals: true
+      }
+    ]
   }
-}
\ No newline at end of file
+};
\ No newline at end of file
diff --git a/Dockerfile b/Dockerfile
index cc27e038c58e349e28dccf75daccde01322bb594..dae111fb247296b894175734796701f3976fb2eb 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,4 +1,4 @@
-FROM node:12.13-slim AS builder
+FROM node:14-slim AS builder
 
 WORKDIR /app
 RUN npm install -g npm@latest
diff --git a/README.md b/README.md
index 82e11afb6415028270f58d9e3b6128412d316ace..4d0fd2340ccda019c910a4ecfc2950847435a5e0 100644
--- a/README.md
+++ b/README.md
@@ -28,6 +28,11 @@ NODE_ENV=development
     "VUE_APP_LOGO_PATH":"/geocontrib/img/logo-neogeo-circle.png",
     "VUE_APP_DJANGO_BASE":"",
     "VUE_APP_DJANGO_API_BASE":"/geocontrib/api/",
+    "VUE_APP_CATALOG_NAME": "Datasud", => renseigne le nom du catalogue dans le bouton importer depuis le catalogue
+    "VUE_APP_IDGO": true, => si le bouton importer depuis le catalogue doit être affiché ou pas
+    "VUE_APP_RELOAD_INTERVAL": 15000,
+    "VUE_APP_DISABLE_LOGIN_BUTTON":false,
+    "VUE_APP_LOGIN_URL":"",
     "DEFAULT_BASE_MAP":{
         "SERVICE": "https://{s}.tile.openstreetmap.fr/osmfr/{z}/{x}/{y}.png",
         "OPTIONS": {
diff --git a/babel.config.js b/babel.config.js
index e9558405fdcc02f12d757acb308e02937a7444f1..3f453d445802728801d7a55ba414c26655784ef7 100644
--- a/babel.config.js
+++ b/babel.config.js
@@ -2,4 +2,4 @@ module.exports = {
   presets: [
     '@vue/cli-plugin-babel/preset'
   ]
-}
+};
diff --git a/package-lock.json b/package-lock.json
index 4cb9a58425382f7f7a869ed25024ebe0352b9b60..4de64269566c5368f1d5e59a0cc5db8b7635f8c2 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,39 +1,39 @@
 {
   "name": "geocontrib-frontend",
-  "version": "2.3.2",
+  "version": "3.0.0-rc1",
   "lockfileVersion": 1,
   "requires": true,
   "dependencies": {
     "@babel/code-frame": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.14.5.tgz",
-      "integrity": "sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz",
+      "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==",
       "dev": true,
       "requires": {
-        "@babel/highlight": "^7.14.5"
+        "@babel/highlight": "^7.16.7"
       }
     },
     "@babel/compat-data": {
-      "version": "7.14.7",
-      "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.14.7.tgz",
-      "integrity": "sha512-nS6dZaISCXJ3+518CWiBfEr//gHyMO02uDxBkXTKZDN5POruCnOZ1N4YBRZDCabwF8nZMWBpRxIicmXtBs+fvw==",
+      "version": "7.16.4",
+      "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.16.4.tgz",
+      "integrity": "sha512-1o/jo7D+kC9ZjHX5v+EHrdjl3PhxMrLSOTGsOdHJ+KL8HCaEK6ehrVL2RS6oHDZp+L7xLirLrPmQtEng769J/Q==",
       "dev": true
     },
     "@babel/core": {
-      "version": "7.14.6",
-      "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.14.6.tgz",
-      "integrity": "sha512-gJnOEWSqTk96qG5BoIrl5bVtc23DCycmIePPYnamY9RboYdI4nFy5vAQMSl81O5K/W0sLDWfGysnOECC+KUUCA==",
-      "dev": true,
-      "requires": {
-        "@babel/code-frame": "^7.14.5",
-        "@babel/generator": "^7.14.5",
-        "@babel/helper-compilation-targets": "^7.14.5",
-        "@babel/helper-module-transforms": "^7.14.5",
-        "@babel/helpers": "^7.14.6",
-        "@babel/parser": "^7.14.6",
-        "@babel/template": "^7.14.5",
-        "@babel/traverse": "^7.14.5",
-        "@babel/types": "^7.14.5",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.16.7.tgz",
+      "integrity": "sha512-aeLaqcqThRNZYmbMqtulsetOQZ/5gbR/dWruUCJcpas4Qoyy+QeagfDsPdMrqwsPRDNxJvBlRiZxxX7THO7qtA==",
+      "dev": true,
+      "requires": {
+        "@babel/code-frame": "^7.16.7",
+        "@babel/generator": "^7.16.7",
+        "@babel/helper-compilation-targets": "^7.16.7",
+        "@babel/helper-module-transforms": "^7.16.7",
+        "@babel/helpers": "^7.16.7",
+        "@babel/parser": "^7.16.7",
+        "@babel/template": "^7.16.7",
+        "@babel/traverse": "^7.16.7",
+        "@babel/types": "^7.16.7",
         "convert-source-map": "^1.7.0",
         "debug": "^4.1.0",
         "gensync": "^1.0.0-beta.2",
@@ -42,76 +42,100 @@
         "source-map": "^0.5.0"
       }
     },
+    "@babel/eslint-parser": {
+      "version": "7.16.5",
+      "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.16.5.tgz",
+      "integrity": "sha512-mUqYa46lgWqHKQ33Q6LNCGp/wPR3eqOYTUixHFsfrSQqRxH0+WOzca75iEjFr5RDGH1dDz622LaHhLOzOuQRUA==",
+      "dev": true,
+      "requires": {
+        "eslint-scope": "^5.1.1",
+        "eslint-visitor-keys": "^2.1.0",
+        "semver": "^6.3.0"
+      },
+      "dependencies": {
+        "eslint-scope": {
+          "version": "5.1.1",
+          "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
+          "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
+          "dev": true,
+          "requires": {
+            "esrecurse": "^4.3.0",
+            "estraverse": "^4.1.1"
+          }
+        }
+      }
+    },
     "@babel/generator": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.14.5.tgz",
-      "integrity": "sha512-y3rlP+/G25OIX3mYKKIOlQRcqj7YgrvHxOLbVmyLJ9bPmi5ttvUmpydVjcFjZphOktWuA7ovbx91ECloWTfjIA==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.16.7.tgz",
+      "integrity": "sha512-/ST3Sg8MLGY5HVYmrjOgL60ENux/HfO/CsUh7y4MalThufhE/Ff/6EibFDHi4jiDCaWfJKoqbE6oTh21c5hrRg==",
       "dev": true,
       "requires": {
-        "@babel/types": "^7.14.5",
+        "@babel/types": "^7.16.7",
         "jsesc": "^2.5.1",
         "source-map": "^0.5.0"
       }
     },
     "@babel/helper-annotate-as-pure": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.14.5.tgz",
-      "integrity": "sha512-EivH9EgBIb+G8ij1B2jAwSH36WnGvkQSEC6CkX/6v6ZFlw5fVOHvsgGF4uiEHO2GzMvunZb6tDLQEQSdrdocrA==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz",
+      "integrity": "sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw==",
       "dev": true,
       "requires": {
-        "@babel/types": "^7.14.5"
+        "@babel/types": "^7.16.7"
       }
     },
     "@babel/helper-builder-binary-assignment-operator-visitor": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.14.5.tgz",
-      "integrity": "sha512-YTA/Twn0vBXDVGJuAX6PwW7x5zQei1luDDo2Pl6q1qZ7hVNl0RZrhHCQG/ArGpR29Vl7ETiB8eJyrvpuRp300w==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.16.7.tgz",
+      "integrity": "sha512-C6FdbRaxYjwVu/geKW4ZeQ0Q31AftgRcdSnZ5/jsH6BzCJbtvXvhpfkbkThYSuutZA7nCXpPR6AD9zd1dprMkA==",
       "dev": true,
       "requires": {
-        "@babel/helper-explode-assignable-expression": "^7.14.5",
-        "@babel/types": "^7.14.5"
+        "@babel/helper-explode-assignable-expression": "^7.16.7",
+        "@babel/types": "^7.16.7"
       }
     },
     "@babel/helper-compilation-targets": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.14.5.tgz",
-      "integrity": "sha512-v+QtZqXEiOnpO6EYvlImB6zCD2Lel06RzOPzmkz/D/XgQiUu3C/Jb1LOqSt/AIA34TYi/Q+KlT8vTQrgdxkbLw==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.16.7.tgz",
+      "integrity": "sha512-mGojBwIWcwGD6rfqgRXVlVYmPAv7eOpIemUG3dGnDdCY4Pae70ROij3XmfrH6Fa1h1aiDylpglbZyktfzyo/hA==",
       "dev": true,
       "requires": {
-        "@babel/compat-data": "^7.14.5",
-        "@babel/helper-validator-option": "^7.14.5",
-        "browserslist": "^4.16.6",
+        "@babel/compat-data": "^7.16.4",
+        "@babel/helper-validator-option": "^7.16.7",
+        "browserslist": "^4.17.5",
         "semver": "^6.3.0"
       }
     },
     "@babel/helper-create-class-features-plugin": {
-      "version": "7.14.6",
-      "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.14.6.tgz",
-      "integrity": "sha512-Z6gsfGofTxH/+LQXqYEK45kxmcensbzmk/oi8DmaQytlQCgqNZt9XQF8iqlI/SeXWVjaMNxvYvzaYw+kh42mDg==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.16.7.tgz",
+      "integrity": "sha512-kIFozAvVfK05DM4EVQYKK+zteWvY85BFdGBRQBytRyY3y+6PX0DkDOn/CZ3lEuczCfrCxEzwt0YtP/87YPTWSw==",
       "dev": true,
       "requires": {
-        "@babel/helper-annotate-as-pure": "^7.14.5",
-        "@babel/helper-function-name": "^7.14.5",
-        "@babel/helper-member-expression-to-functions": "^7.14.5",
-        "@babel/helper-optimise-call-expression": "^7.14.5",
-        "@babel/helper-replace-supers": "^7.14.5",
-        "@babel/helper-split-export-declaration": "^7.14.5"
+        "@babel/helper-annotate-as-pure": "^7.16.7",
+        "@babel/helper-environment-visitor": "^7.16.7",
+        "@babel/helper-function-name": "^7.16.7",
+        "@babel/helper-member-expression-to-functions": "^7.16.7",
+        "@babel/helper-optimise-call-expression": "^7.16.7",
+        "@babel/helper-replace-supers": "^7.16.7",
+        "@babel/helper-split-export-declaration": "^7.16.7"
       }
     },
     "@babel/helper-create-regexp-features-plugin": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.14.5.tgz",
-      "integrity": "sha512-TLawwqpOErY2HhWbGJ2nZT5wSkR192QpN+nBg1THfBfftrlvOh+WbhrxXCH4q4xJ9Gl16BGPR/48JA+Ryiho/A==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.16.7.tgz",
+      "integrity": "sha512-fk5A6ymfp+O5+p2yCkXAu5Kyj6v0xh0RBeNcAkYUMDvvAAoxvSKXn+Jb37t/yWFiQVDFK1ELpUTD8/aLhCPu+g==",
       "dev": true,
       "requires": {
-        "@babel/helper-annotate-as-pure": "^7.14.5",
+        "@babel/helper-annotate-as-pure": "^7.16.7",
         "regexpu-core": "^4.7.1"
       }
     },
     "@babel/helper-define-polyfill-provider": {
-      "version": "0.2.3",
-      "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.2.3.tgz",
-      "integrity": "sha512-RH3QDAfRMzj7+0Nqu5oqgO5q9mFtQEVvCRsi8qCEfzLR9p2BHfn5FzhSB2oj1fF7I2+DcTORkYaQ6aTR9Cofew==",
+      "version": "0.3.0",
+      "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.0.tgz",
+      "integrity": "sha512-7hfT8lUljl/tM3h+izTX/pO3W3frz2ok6Pk+gzys8iJqDfZrZy2pXjRTZAvG2YmfHun1X4q8/UZRLatMfqc5Tg==",
       "dev": true,
       "requires": {
         "@babel/helper-compilation-targets": "^7.13.0",
@@ -124,373 +148,392 @@
         "semver": "^6.1.2"
       }
     },
+    "@babel/helper-environment-visitor": {
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz",
+      "integrity": "sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag==",
+      "dev": true,
+      "requires": {
+        "@babel/types": "^7.16.7"
+      }
+    },
     "@babel/helper-explode-assignable-expression": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.14.5.tgz",
-      "integrity": "sha512-Htb24gnGJdIGT4vnRKMdoXiOIlqOLmdiUYpAQ0mYfgVT/GDm8GOYhgi4GL+hMKrkiPRohO4ts34ELFsGAPQLDQ==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.16.7.tgz",
+      "integrity": "sha512-KyUenhWMC8VrxzkGP0Jizjo4/Zx+1nNZhgocs+gLzyZyB8SHidhoq9KK/8Ato4anhwsivfkBLftky7gvzbZMtQ==",
       "dev": true,
       "requires": {
-        "@babel/types": "^7.14.5"
+        "@babel/types": "^7.16.7"
       }
     },
     "@babel/helper-function-name": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.14.5.tgz",
-      "integrity": "sha512-Gjna0AsXWfFvrAuX+VKcN/aNNWonizBj39yGwUzVDVTlMYJMK2Wp6xdpy72mfArFq5uK+NOuexfzZlzI1z9+AQ==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.16.7.tgz",
+      "integrity": "sha512-QfDfEnIUyyBSR3HtrtGECuZ6DAyCkYFp7GHl75vFtTnn6pjKeK0T1DB5lLkFvBea8MdaiUABx3osbgLyInoejA==",
       "dev": true,
       "requires": {
-        "@babel/helper-get-function-arity": "^7.14.5",
-        "@babel/template": "^7.14.5",
-        "@babel/types": "^7.14.5"
+        "@babel/helper-get-function-arity": "^7.16.7",
+        "@babel/template": "^7.16.7",
+        "@babel/types": "^7.16.7"
       }
     },
     "@babel/helper-get-function-arity": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.14.5.tgz",
-      "integrity": "sha512-I1Db4Shst5lewOM4V+ZKJzQ0JGGaZ6VY1jYvMghRjqs6DWgxLCIyFt30GlnKkfUeFLpJt2vzbMVEXVSXlIFYUg==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.7.tgz",
+      "integrity": "sha512-flc+RLSOBXzNzVhcLu6ujeHUrD6tANAOU5ojrRx/as+tbzf8+stUCj7+IfRRoAbEZqj/ahXEMsjhOhgeZsrnTw==",
       "dev": true,
       "requires": {
-        "@babel/types": "^7.14.5"
+        "@babel/types": "^7.16.7"
       }
     },
     "@babel/helper-hoist-variables": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.14.5.tgz",
-      "integrity": "sha512-R1PXiz31Uc0Vxy4OEOm07x0oSjKAdPPCh3tPivn/Eo8cvz6gveAeuyUUPB21Hoiif0uoPQSSdhIPS3352nvdyQ==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz",
+      "integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==",
       "dev": true,
       "requires": {
-        "@babel/types": "^7.14.5"
+        "@babel/types": "^7.16.7"
       }
     },
     "@babel/helper-member-expression-to-functions": {
-      "version": "7.14.7",
-      "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.14.7.tgz",
-      "integrity": "sha512-TMUt4xKxJn6ccjcOW7c4hlwyJArizskAhoSTOCkA0uZ+KghIaci0Qg9R043kUMWI9mtQfgny+NQ5QATnZ+paaA==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.16.7.tgz",
+      "integrity": "sha512-VtJ/65tYiU/6AbMTDwyoXGPKHgTsfRarivm+YbB5uAzKUyuPjgZSgAFeG87FCigc7KNHu2Pegh1XIT3lXjvz3Q==",
       "dev": true,
       "requires": {
-        "@babel/types": "^7.14.5"
+        "@babel/types": "^7.16.7"
       }
     },
     "@babel/helper-module-imports": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.14.5.tgz",
-      "integrity": "sha512-SwrNHu5QWS84XlHwGYPDtCxcA0hrSlL2yhWYLgeOc0w7ccOl2qv4s/nARI0aYZW+bSwAL5CukeXA47B/1NKcnQ==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz",
+      "integrity": "sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==",
       "dev": true,
       "requires": {
-        "@babel/types": "^7.14.5"
+        "@babel/types": "^7.16.7"
       }
     },
     "@babel/helper-module-transforms": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.14.5.tgz",
-      "integrity": "sha512-iXpX4KW8LVODuAieD7MzhNjmM6dzYY5tfRqT+R9HDXWl0jPn/djKmA+G9s/2C2T9zggw5tK1QNqZ70USfedOwA==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.16.7.tgz",
+      "integrity": "sha512-gaqtLDxJEFCeQbYp9aLAefjhkKdjKcdh6DB7jniIGU3Pz52WAmP268zK0VgPz9hUNkMSYeH976K2/Y6yPadpng==",
       "dev": true,
       "requires": {
-        "@babel/helper-module-imports": "^7.14.5",
-        "@babel/helper-replace-supers": "^7.14.5",
-        "@babel/helper-simple-access": "^7.14.5",
-        "@babel/helper-split-export-declaration": "^7.14.5",
-        "@babel/helper-validator-identifier": "^7.14.5",
-        "@babel/template": "^7.14.5",
-        "@babel/traverse": "^7.14.5",
-        "@babel/types": "^7.14.5"
+        "@babel/helper-environment-visitor": "^7.16.7",
+        "@babel/helper-module-imports": "^7.16.7",
+        "@babel/helper-simple-access": "^7.16.7",
+        "@babel/helper-split-export-declaration": "^7.16.7",
+        "@babel/helper-validator-identifier": "^7.16.7",
+        "@babel/template": "^7.16.7",
+        "@babel/traverse": "^7.16.7",
+        "@babel/types": "^7.16.7"
       }
     },
     "@babel/helper-optimise-call-expression": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.14.5.tgz",
-      "integrity": "sha512-IqiLIrODUOdnPU9/F8ib1Fx2ohlgDhxnIDU7OEVi+kAbEZcyiF7BLU8W6PfvPi9LzztjS7kcbzbmL7oG8kD6VA==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.16.7.tgz",
+      "integrity": "sha512-EtgBhg7rd/JcnpZFXpBy0ze1YRfdm7BnBX4uKMBd3ixa3RGAE002JZB66FJyNH7g0F38U05pXmA5P8cBh7z+1w==",
       "dev": true,
       "requires": {
-        "@babel/types": "^7.14.5"
+        "@babel/types": "^7.16.7"
       }
     },
     "@babel/helper-plugin-utils": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.14.5.tgz",
-      "integrity": "sha512-/37qQCE3K0vvZKwoK4XU/irIJQdIfCJuhU5eKnNxpFDsOkgFaUAwbv+RYw6eYgsC0E4hS7r5KqGULUogqui0fQ==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.7.tgz",
+      "integrity": "sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA==",
       "dev": true
     },
     "@babel/helper-remap-async-to-generator": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.14.5.tgz",
-      "integrity": "sha512-rLQKdQU+HYlxBwQIj8dk4/0ENOUEhA/Z0l4hN8BexpvmSMN9oA9EagjnhnDpNsRdWCfjwa4mn/HyBXO9yhQP6A==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.16.7.tgz",
+      "integrity": "sha512-C3o117GnP/j/N2OWo+oepeWbFEKRfNaay+F1Eo5Mj3A1SRjyx+qaFhm23nlipub7Cjv2azdUUiDH+VlpdwUFRg==",
       "dev": true,
       "requires": {
-        "@babel/helper-annotate-as-pure": "^7.14.5",
-        "@babel/helper-wrap-function": "^7.14.5",
-        "@babel/types": "^7.14.5"
+        "@babel/helper-annotate-as-pure": "^7.16.7",
+        "@babel/helper-wrap-function": "^7.16.7",
+        "@babel/types": "^7.16.7"
       }
     },
     "@babel/helper-replace-supers": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.14.5.tgz",
-      "integrity": "sha512-3i1Qe9/8x/hCHINujn+iuHy+mMRLoc77b2nI9TB0zjH1hvn9qGlXjWlggdwUcju36PkPCy/lpM7LLUdcTyH4Ow==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.16.7.tgz",
+      "integrity": "sha512-y9vsWilTNaVnVh6xiJfABzsNpgDPKev9HnAgz6Gb1p6UUwf9NepdlsV7VXGCftJM+jqD5f7JIEubcpLjZj5dBw==",
       "dev": true,
       "requires": {
-        "@babel/helper-member-expression-to-functions": "^7.14.5",
-        "@babel/helper-optimise-call-expression": "^7.14.5",
-        "@babel/traverse": "^7.14.5",
-        "@babel/types": "^7.14.5"
+        "@babel/helper-environment-visitor": "^7.16.7",
+        "@babel/helper-member-expression-to-functions": "^7.16.7",
+        "@babel/helper-optimise-call-expression": "^7.16.7",
+        "@babel/traverse": "^7.16.7",
+        "@babel/types": "^7.16.7"
       }
     },
     "@babel/helper-simple-access": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.14.5.tgz",
-      "integrity": "sha512-nfBN9xvmCt6nrMZjfhkl7i0oTV3yxR4/FztsbOASyTvVcoYd0TRHh7eMLdlEcCqobydC0LAF3LtC92Iwxo0wyw==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.16.7.tgz",
+      "integrity": "sha512-ZIzHVyoeLMvXMN/vok/a4LWRy8G2v205mNP0XOuf9XRLyX5/u9CnVulUtDgUTama3lT+bf/UqucuZjqiGuTS1g==",
       "dev": true,
       "requires": {
-        "@babel/types": "^7.14.5"
+        "@babel/types": "^7.16.7"
       }
     },
     "@babel/helper-skip-transparent-expression-wrappers": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.14.5.tgz",
-      "integrity": "sha512-dmqZB7mrb94PZSAOYtr+ZN5qt5owZIAgqtoTuqiFbHFtxgEcmQlRJVI+bO++fciBunXtB6MK7HrzrfcAzIz2NQ==",
+      "version": "7.16.0",
+      "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.16.0.tgz",
+      "integrity": "sha512-+il1gTy0oHwUsBQZyJvukbB4vPMdcYBrFHa0Uc4AizLxbq6BOYC51Rv4tWocX9BLBDLZ4kc6qUFpQ6HRgL+3zw==",
       "dev": true,
       "requires": {
-        "@babel/types": "^7.14.5"
+        "@babel/types": "^7.16.0"
       }
     },
     "@babel/helper-split-export-declaration": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.14.5.tgz",
-      "integrity": "sha512-hprxVPu6e5Kdp2puZUmvOGjaLv9TCe58E/Fl6hRq4YiVQxIcNvuq6uTM2r1mT/oPskuS9CgR+I94sqAYv0NGKA==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz",
+      "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==",
       "dev": true,
       "requires": {
-        "@babel/types": "^7.14.5"
+        "@babel/types": "^7.16.7"
       }
     },
     "@babel/helper-validator-identifier": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.5.tgz",
-      "integrity": "sha512-5lsetuxCLilmVGyiLEfoHBRX8UCFD+1m2x3Rj97WrW3V7H3u4RWRXA4evMjImCsin2J2YT0QaVDGf+z8ondbAg==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz",
+      "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==",
       "dev": true
     },
     "@babel/helper-validator-option": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.14.5.tgz",
-      "integrity": "sha512-OX8D5eeX4XwcroVW45NMvoYaIuFI+GQpA2a8Gi+X/U/cDUIRsV37qQfF905F0htTRCREQIB4KqPeaveRJUl3Ow==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz",
+      "integrity": "sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==",
       "dev": true
     },
     "@babel/helper-wrap-function": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.14.5.tgz",
-      "integrity": "sha512-YEdjTCq+LNuNS1WfxsDCNpgXkJaIyqco6DAelTUjT4f2KIWC1nBcaCaSdHTBqQVLnTBexBcVcFhLSU1KnYuePQ==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.16.7.tgz",
+      "integrity": "sha512-7a9sABeVwcunnztZZ7WTgSw6jVYLzM1wua0Z4HIXm9S3/HC96WKQTkFgGEaj5W06SHHihPJ6Le6HzS5cGOQMNw==",
       "dev": true,
       "requires": {
-        "@babel/helper-function-name": "^7.14.5",
-        "@babel/template": "^7.14.5",
-        "@babel/traverse": "^7.14.5",
-        "@babel/types": "^7.14.5"
+        "@babel/helper-function-name": "^7.16.7",
+        "@babel/template": "^7.16.7",
+        "@babel/traverse": "^7.16.7",
+        "@babel/types": "^7.16.7"
       }
     },
     "@babel/helpers": {
-      "version": "7.14.6",
-      "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.14.6.tgz",
-      "integrity": "sha512-yesp1ENQBiLI+iYHSJdoZKUtRpfTlL1grDIX9NRlAVppljLw/4tTyYupIB7uIYmC3stW/imAv8EqaKaS/ibmeA==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.16.7.tgz",
+      "integrity": "sha512-9ZDoqtfY7AuEOt3cxchfii6C7GDyyMBffktR5B2jvWv8u2+efwvpnVKXMWzNehqy68tKgAfSwfdw/lWpthS2bw==",
       "dev": true,
       "requires": {
-        "@babel/template": "^7.14.5",
-        "@babel/traverse": "^7.14.5",
-        "@babel/types": "^7.14.5"
+        "@babel/template": "^7.16.7",
+        "@babel/traverse": "^7.16.7",
+        "@babel/types": "^7.16.7"
       }
     },
     "@babel/highlight": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz",
-      "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.7.tgz",
+      "integrity": "sha512-aKpPMfLvGO3Q97V0qhw/V2SWNWlwfJknuwAunU7wZLSfrM4xTBvg7E5opUVi1kJTBKihE38CPg4nBiqX83PWYw==",
       "dev": true,
       "requires": {
-        "@babel/helper-validator-identifier": "^7.14.5",
+        "@babel/helper-validator-identifier": "^7.16.7",
         "chalk": "^2.0.0",
         "js-tokens": "^4.0.0"
       }
     },
     "@babel/parser": {
-      "version": "7.14.7",
-      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.7.tgz",
-      "integrity": "sha512-X67Z5y+VBJuHB/RjwECp8kSl5uYi0BvRbNeWqkaJCVh+LiTPl19WBUfG627psSgp9rSf6ojuXghQM3ha6qHHdA==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.16.7.tgz",
+      "integrity": "sha512-sR4eaSrnM7BV7QPzGfEX5paG/6wrZM3I0HDzfIAK06ESvo9oy3xBuVBxE3MbQaKNhvg8g/ixjMWo2CGpzpHsDA==",
       "dev": true
     },
+    "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": {
+      "version": "7.16.7",
+      "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.16.7.tgz",
+      "integrity": "sha512-anv/DObl7waiGEnC24O9zqL0pSuI9hljihqiDuFHC8d7/bjr/4RLGPWuc8rYOff/QPzbEPSkzG8wGG9aDuhHRg==",
+      "dev": true,
+      "requires": {
+        "@babel/helper-plugin-utils": "^7.16.7"
+      }
+    },
     "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.14.5.tgz",
-      "integrity": "sha512-ZoJS2XCKPBfTmL122iP6NM9dOg+d4lc9fFk3zxc8iDjvt8Pk4+TlsHSKhIPf6X+L5ORCdBzqMZDjL/WHj7WknQ==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.16.7.tgz",
+      "integrity": "sha512-di8vUHRdf+4aJ7ltXhaDbPoszdkh59AQtJM5soLsuHpQJdFQZOA4uGj0V2u/CZ8bJ/u8ULDL5yq6FO/bCXnKHw==",
       "dev": true,
       "requires": {
-        "@babel/helper-plugin-utils": "^7.14.5",
-        "@babel/helper-skip-transparent-expression-wrappers": "^7.14.5",
-        "@babel/plugin-proposal-optional-chaining": "^7.14.5"
+        "@babel/helper-plugin-utils": "^7.16.7",
+        "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0",
+        "@babel/plugin-proposal-optional-chaining": "^7.16.7"
       }
     },
     "@babel/plugin-proposal-async-generator-functions": {
-      "version": "7.14.7",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.14.7.tgz",
-      "integrity": "sha512-RK8Wj7lXLY3bqei69/cc25gwS5puEc3dknoFPFbqfy3XxYQBQFvu4ioWpafMBAB+L9NyptQK4nMOa5Xz16og8Q==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.16.7.tgz",
+      "integrity": "sha512-TTXBT3A5c11eqRzaC6beO6rlFT3Mo9C2e8eB44tTr52ESXSK2CIc2fOp1ynpAwQA8HhBMho+WXhMHWlAe3xkpw==",
       "dev": true,
       "requires": {
-        "@babel/helper-plugin-utils": "^7.14.5",
-        "@babel/helper-remap-async-to-generator": "^7.14.5",
+        "@babel/helper-plugin-utils": "^7.16.7",
+        "@babel/helper-remap-async-to-generator": "^7.16.7",
         "@babel/plugin-syntax-async-generators": "^7.8.4"
       }
     },
     "@babel/plugin-proposal-class-properties": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.14.5.tgz",
-      "integrity": "sha512-q/PLpv5Ko4dVc1LYMpCY7RVAAO4uk55qPwrIuJ5QJ8c6cVuAmhu7I/49JOppXL6gXf7ZHzpRVEUZdYoPLM04Gg==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.16.7.tgz",
+      "integrity": "sha512-IobU0Xme31ewjYOShSIqd/ZGM/r/cuOz2z0MDbNrhF5FW+ZVgi0f2lyeoj9KFPDOAqsYxmLWZte1WOwlvY9aww==",
       "dev": true,
       "requires": {
-        "@babel/helper-create-class-features-plugin": "^7.14.5",
-        "@babel/helper-plugin-utils": "^7.14.5"
+        "@babel/helper-create-class-features-plugin": "^7.16.7",
+        "@babel/helper-plugin-utils": "^7.16.7"
       }
     },
     "@babel/plugin-proposal-class-static-block": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.14.5.tgz",
-      "integrity": "sha512-KBAH5ksEnYHCegqseI5N9skTdxgJdmDoAOc0uXa+4QMYKeZD0w5IARh4FMlTNtaHhbB8v+KzMdTgxMMzsIy6Yg==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.16.7.tgz",
+      "integrity": "sha512-dgqJJrcZoG/4CkMopzhPJjGxsIe9A8RlkQLnL/Vhhx8AA9ZuaRwGSlscSh42hazc7WSrya/IK7mTeoF0DP9tEw==",
       "dev": true,
       "requires": {
-        "@babel/helper-create-class-features-plugin": "^7.14.5",
-        "@babel/helper-plugin-utils": "^7.14.5",
+        "@babel/helper-create-class-features-plugin": "^7.16.7",
+        "@babel/helper-plugin-utils": "^7.16.7",
         "@babel/plugin-syntax-class-static-block": "^7.14.5"
       }
     },
     "@babel/plugin-proposal-decorators": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.14.5.tgz",
-      "integrity": "sha512-LYz5nvQcvYeRVjui1Ykn28i+3aUiXwQ/3MGoEy0InTaz1pJo/lAzmIDXX+BQny/oufgHzJ6vnEEiXQ8KZjEVFg==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.16.7.tgz",
+      "integrity": "sha512-DoEpnuXK14XV9btI1k8tzNGCutMclpj4yru8aXKoHlVmbO1s+2A+g2+h4JhcjrxkFJqzbymnLG6j/niOf3iFXQ==",
       "dev": true,
       "requires": {
-        "@babel/helper-create-class-features-plugin": "^7.14.5",
-        "@babel/helper-plugin-utils": "^7.14.5",
-        "@babel/plugin-syntax-decorators": "^7.14.5"
+        "@babel/helper-create-class-features-plugin": "^7.16.7",
+        "@babel/helper-plugin-utils": "^7.16.7",
+        "@babel/plugin-syntax-decorators": "^7.16.7"
       }
     },
     "@babel/plugin-proposal-dynamic-import": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.14.5.tgz",
-      "integrity": "sha512-ExjiNYc3HDN5PXJx+bwC50GIx/KKanX2HiggnIUAYedbARdImiCU4RhhHfdf0Kd7JNXGpsBBBCOm+bBVy3Gb0g==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.16.7.tgz",
+      "integrity": "sha512-I8SW9Ho3/8DRSdmDdH3gORdyUuYnk1m4cMxUAdu5oy4n3OfN8flDEH+d60iG7dUfi0KkYwSvoalHzzdRzpWHTg==",
       "dev": true,
       "requires": {
-        "@babel/helper-plugin-utils": "^7.14.5",
+        "@babel/helper-plugin-utils": "^7.16.7",
         "@babel/plugin-syntax-dynamic-import": "^7.8.3"
       }
     },
     "@babel/plugin-proposal-export-namespace-from": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.14.5.tgz",
-      "integrity": "sha512-g5POA32bXPMmSBu5Dx/iZGLGnKmKPc5AiY7qfZgurzrCYgIztDlHFbznSNCoQuv57YQLnQfaDi7dxCtLDIdXdA==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.16.7.tgz",
+      "integrity": "sha512-ZxdtqDXLRGBL64ocZcs7ovt71L3jhC1RGSyR996svrCi3PYqHNkb3SwPJCs8RIzD86s+WPpt2S73+EHCGO+NUA==",
       "dev": true,
       "requires": {
-        "@babel/helper-plugin-utils": "^7.14.5",
+        "@babel/helper-plugin-utils": "^7.16.7",
         "@babel/plugin-syntax-export-namespace-from": "^7.8.3"
       }
     },
     "@babel/plugin-proposal-json-strings": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.14.5.tgz",
-      "integrity": "sha512-NSq2fczJYKVRIsUJyNxrVUMhB27zb7N7pOFGQOhBKJrChbGcgEAqyZrmZswkPk18VMurEeJAaICbfm57vUeTbQ==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.16.7.tgz",
+      "integrity": "sha512-lNZ3EEggsGY78JavgbHsK9u5P3pQaW7k4axlgFLYkMd7UBsiNahCITShLjNQschPyjtO6dADrL24757IdhBrsQ==",
       "dev": true,
       "requires": {
-        "@babel/helper-plugin-utils": "^7.14.5",
+        "@babel/helper-plugin-utils": "^7.16.7",
         "@babel/plugin-syntax-json-strings": "^7.8.3"
       }
     },
     "@babel/plugin-proposal-logical-assignment-operators": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.14.5.tgz",
-      "integrity": "sha512-YGn2AvZAo9TwyhlLvCCWxD90Xq8xJ4aSgaX3G5D/8DW94L8aaT+dS5cSP+Z06+rCJERGSr9GxMBZ601xoc2taw==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.16.7.tgz",
+      "integrity": "sha512-K3XzyZJGQCr00+EtYtrDjmwX7o7PLK6U9bi1nCwkQioRFVUv6dJoxbQjtWVtP+bCPy82bONBKG8NPyQ4+i6yjg==",
       "dev": true,
       "requires": {
-        "@babel/helper-plugin-utils": "^7.14.5",
+        "@babel/helper-plugin-utils": "^7.16.7",
         "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4"
       }
     },
     "@babel/plugin-proposal-nullish-coalescing-operator": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.14.5.tgz",
-      "integrity": "sha512-gun/SOnMqjSb98Nkaq2rTKMwervfdAoz6NphdY0vTfuzMfryj+tDGb2n6UkDKwez+Y8PZDhE3D143v6Gepp4Hg==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.16.7.tgz",
+      "integrity": "sha512-aUOrYU3EVtjf62jQrCj63pYZ7k6vns2h/DQvHPWGmsJRYzWXZ6/AsfgpiRy6XiuIDADhJzP2Q9MwSMKauBQ+UQ==",
       "dev": true,
       "requires": {
-        "@babel/helper-plugin-utils": "^7.14.5",
+        "@babel/helper-plugin-utils": "^7.16.7",
         "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3"
       }
     },
     "@babel/plugin-proposal-numeric-separator": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.14.5.tgz",
-      "integrity": "sha512-yiclALKe0vyZRZE0pS6RXgjUOt87GWv6FYa5zqj15PvhOGFO69R5DusPlgK/1K5dVnCtegTiWu9UaBSrLLJJBg==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.16.7.tgz",
+      "integrity": "sha512-vQgPMknOIgiuVqbokToyXbkY/OmmjAzr/0lhSIbG/KmnzXPGwW/AdhdKpi+O4X/VkWiWjnkKOBiqJrTaC98VKw==",
       "dev": true,
       "requires": {
-        "@babel/helper-plugin-utils": "^7.14.5",
+        "@babel/helper-plugin-utils": "^7.16.7",
         "@babel/plugin-syntax-numeric-separator": "^7.10.4"
       }
     },
     "@babel/plugin-proposal-object-rest-spread": {
-      "version": "7.14.7",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.14.7.tgz",
-      "integrity": "sha512-082hsZz+sVabfmDWo1Oct1u1AgbKbUAyVgmX4otIc7bdsRgHBXwTwb3DpDmD4Eyyx6DNiuz5UAATT655k+kL5g==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.16.7.tgz",
+      "integrity": "sha512-3O0Y4+dw94HA86qSg9IHfyPktgR7q3gpNVAeiKQd+8jBKFaU5NQS1Yatgo4wY+UFNuLjvxcSmzcsHqrhgTyBUA==",
       "dev": true,
       "requires": {
-        "@babel/compat-data": "^7.14.7",
-        "@babel/helper-compilation-targets": "^7.14.5",
-        "@babel/helper-plugin-utils": "^7.14.5",
+        "@babel/compat-data": "^7.16.4",
+        "@babel/helper-compilation-targets": "^7.16.7",
+        "@babel/helper-plugin-utils": "^7.16.7",
         "@babel/plugin-syntax-object-rest-spread": "^7.8.3",
-        "@babel/plugin-transform-parameters": "^7.14.5"
+        "@babel/plugin-transform-parameters": "^7.16.7"
       }
     },
     "@babel/plugin-proposal-optional-catch-binding": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.14.5.tgz",
-      "integrity": "sha512-3Oyiixm0ur7bzO5ybNcZFlmVsygSIQgdOa7cTfOYCMY+wEPAYhZAJxi3mixKFCTCKUhQXuCTtQ1MzrpL3WT8ZQ==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.16.7.tgz",
+      "integrity": "sha512-eMOH/L4OvWSZAE1VkHbr1vckLG1WUcHGJSLqqQwl2GaUqG6QjddvrOaTUMNYiv77H5IKPMZ9U9P7EaHwvAShfA==",
       "dev": true,
       "requires": {
-        "@babel/helper-plugin-utils": "^7.14.5",
+        "@babel/helper-plugin-utils": "^7.16.7",
         "@babel/plugin-syntax-optional-catch-binding": "^7.8.3"
       }
     },
     "@babel/plugin-proposal-optional-chaining": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.14.5.tgz",
-      "integrity": "sha512-ycz+VOzo2UbWNI1rQXxIuMOzrDdHGrI23fRiz/Si2R4kv2XZQ1BK8ccdHwehMKBlcH/joGW/tzrUmo67gbJHlQ==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.16.7.tgz",
+      "integrity": "sha512-eC3xy+ZrUcBtP7x+sq62Q/HYd674pPTb/77XZMb5wbDPGWIdUbSr4Agr052+zaUPSb+gGRnjxXfKFvx5iMJ+DA==",
       "dev": true,
       "requires": {
-        "@babel/helper-plugin-utils": "^7.14.5",
-        "@babel/helper-skip-transparent-expression-wrappers": "^7.14.5",
+        "@babel/helper-plugin-utils": "^7.16.7",
+        "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0",
         "@babel/plugin-syntax-optional-chaining": "^7.8.3"
       }
     },
     "@babel/plugin-proposal-private-methods": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.14.5.tgz",
-      "integrity": "sha512-838DkdUA1u+QTCplatfq4B7+1lnDa/+QMI89x5WZHBcnNv+47N8QEj2k9I2MUU9xIv8XJ4XvPCviM/Dj7Uwt9g==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.16.7.tgz",
+      "integrity": "sha512-7twV3pzhrRxSwHeIvFE6coPgvo+exNDOiGUMg39o2LiLo1Y+4aKpfkcLGcg1UHonzorCt7SNXnoMyCnnIOA8Sw==",
       "dev": true,
       "requires": {
-        "@babel/helper-create-class-features-plugin": "^7.14.5",
-        "@babel/helper-plugin-utils": "^7.14.5"
+        "@babel/helper-create-class-features-plugin": "^7.16.7",
+        "@babel/helper-plugin-utils": "^7.16.7"
       }
     },
     "@babel/plugin-proposal-private-property-in-object": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.14.5.tgz",
-      "integrity": "sha512-62EyfyA3WA0mZiF2e2IV9mc9Ghwxcg8YTu8BS4Wss4Y3PY725OmS9M0qLORbJwLqFtGh+jiE4wAmocK2CTUK2Q==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.16.7.tgz",
+      "integrity": "sha512-rMQkjcOFbm+ufe3bTZLyOfsOUOxyvLXZJCTARhJr+8UMSoZmqTe1K1BgkFcrW37rAchWg57yI69ORxiWvUINuQ==",
       "dev": true,
       "requires": {
-        "@babel/helper-annotate-as-pure": "^7.14.5",
-        "@babel/helper-create-class-features-plugin": "^7.14.5",
-        "@babel/helper-plugin-utils": "^7.14.5",
+        "@babel/helper-annotate-as-pure": "^7.16.7",
+        "@babel/helper-create-class-features-plugin": "^7.16.7",
+        "@babel/helper-plugin-utils": "^7.16.7",
         "@babel/plugin-syntax-private-property-in-object": "^7.14.5"
       }
     },
     "@babel/plugin-proposal-unicode-property-regex": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.14.5.tgz",
-      "integrity": "sha512-6axIeOU5LnY471KenAB9vI8I5j7NQ2d652hIYwVyRfgaZT5UpiqFKCuVXCDMSrU+3VFafnu2c5m3lrWIlr6A5Q==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.16.7.tgz",
+      "integrity": "sha512-QRK0YI/40VLhNVGIjRNAAQkEHws0cswSdFFjpFyt943YmJIU1da9uW63Iu6NFV6CxTZW5eTDCrwZUstBWgp/Rg==",
       "dev": true,
       "requires": {
-        "@babel/helper-create-regexp-features-plugin": "^7.14.5",
-        "@babel/helper-plugin-utils": "^7.14.5"
+        "@babel/helper-create-regexp-features-plugin": "^7.16.7",
+        "@babel/helper-plugin-utils": "^7.16.7"
       }
     },
     "@babel/plugin-syntax-async-generators": {
@@ -521,12 +564,12 @@
       }
     },
     "@babel/plugin-syntax-decorators": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.14.5.tgz",
-      "integrity": "sha512-c4sZMRWL4GSvP1EXy0woIP7m4jkVcEuG8R1TOZxPBPtp4FSM/kiPZub9UIs/Jrb5ZAOzvTUSGYrWsrSu1JvoPw==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.16.7.tgz",
+      "integrity": "sha512-vQ+PxL+srA7g6Rx6I1e15m55gftknl2X8GCUW1JTlkTaXZLJOS0UcaY0eK9jYT7IYf4awn6qwyghVHLDz1WyMw==",
       "dev": true,
       "requires": {
-        "@babel/helper-plugin-utils": "^7.14.5"
+        "@babel/helper-plugin-utils": "^7.16.7"
       }
     },
     "@babel/plugin-syntax-dynamic-import": {
@@ -557,12 +600,12 @@
       }
     },
     "@babel/plugin-syntax-jsx": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.14.5.tgz",
-      "integrity": "sha512-ohuFIsOMXJnbOMRfX7/w7LocdR6R7whhuRD4ax8IipLcLPlZGJKkBxgHp++U4N/vKyU16/YDQr2f5seajD3jIw==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.16.7.tgz",
+      "integrity": "sha512-Esxmk7YjA8QysKeT3VhTXvF6y77f/a91SIs4pWb4H2eWGQkCKFgQaG6hdoEVZtGsrAcb2K5BW66XsOErD4WU3Q==",
       "dev": true,
       "requires": {
-        "@babel/helper-plugin-utils": "^7.14.5"
+        "@babel/helper-plugin-utils": "^7.16.7"
       }
     },
     "@babel/plugin-syntax-logical-assignment-operators": {
@@ -638,357 +681,360 @@
       }
     },
     "@babel/plugin-transform-arrow-functions": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.14.5.tgz",
-      "integrity": "sha512-KOnO0l4+tD5IfOdi4x8C1XmEIRWUjNRV8wc6K2vz/3e8yAOoZZvsRXRRIF/yo/MAOFb4QjtAw9xSxMXbSMRy8A==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.16.7.tgz",
+      "integrity": "sha512-9ffkFFMbvzTvv+7dTp/66xvZAWASuPD5Tl9LK3Z9vhOmANo6j94rik+5YMBt4CwHVMWLWpMsriIc2zsa3WW3xQ==",
       "dev": true,
       "requires": {
-        "@babel/helper-plugin-utils": "^7.14.5"
+        "@babel/helper-plugin-utils": "^7.16.7"
       }
     },
     "@babel/plugin-transform-async-to-generator": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.14.5.tgz",
-      "integrity": "sha512-szkbzQ0mNk0rpu76fzDdqSyPu0MuvpXgC+6rz5rpMb5OIRxdmHfQxrktL8CYolL2d8luMCZTR0DpIMIdL27IjA==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.16.7.tgz",
+      "integrity": "sha512-pFEfjnK4DfXCfAlA5I98BYdDJD8NltMzx19gt6DAmfE+2lXRfPUoa0/5SUjT4+TDE1W/rcxU/1lgN55vpAjjdg==",
       "dev": true,
       "requires": {
-        "@babel/helper-module-imports": "^7.14.5",
-        "@babel/helper-plugin-utils": "^7.14.5",
-        "@babel/helper-remap-async-to-generator": "^7.14.5"
+        "@babel/helper-module-imports": "^7.16.7",
+        "@babel/helper-plugin-utils": "^7.16.7",
+        "@babel/helper-remap-async-to-generator": "^7.16.7"
       }
     },
     "@babel/plugin-transform-block-scoped-functions": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.14.5.tgz",
-      "integrity": "sha512-dtqWqdWZ5NqBX3KzsVCWfQI3A53Ft5pWFCT2eCVUftWZgjc5DpDponbIF1+c+7cSGk2wN0YK7HGL/ezfRbpKBQ==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.16.7.tgz",
+      "integrity": "sha512-JUuzlzmF40Z9cXyytcbZEZKckgrQzChbQJw/5PuEHYeqzCsvebDx0K0jWnIIVcmmDOAVctCgnYs0pMcrYj2zJg==",
       "dev": true,
       "requires": {
-        "@babel/helper-plugin-utils": "^7.14.5"
+        "@babel/helper-plugin-utils": "^7.16.7"
       }
     },
     "@babel/plugin-transform-block-scoping": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.14.5.tgz",
-      "integrity": "sha512-LBYm4ZocNgoCqyxMLoOnwpsmQ18HWTQvql64t3GvMUzLQrNoV1BDG0lNftC8QKYERkZgCCT/7J5xWGObGAyHDw==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.16.7.tgz",
+      "integrity": "sha512-ObZev2nxVAYA4bhyusELdo9hb3H+A56bxH3FZMbEImZFiEDYVHXQSJ1hQKFlDnlt8G9bBrCZ5ZpURZUrV4G5qQ==",
       "dev": true,
       "requires": {
-        "@babel/helper-plugin-utils": "^7.14.5"
+        "@babel/helper-plugin-utils": "^7.16.7"
       }
     },
     "@babel/plugin-transform-classes": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.14.5.tgz",
-      "integrity": "sha512-J4VxKAMykM06K/64z9rwiL6xnBHgB1+FVspqvlgCdwD1KUbQNfszeKVVOMh59w3sztHYIZDgnhOC4WbdEfHFDA==",
-      "dev": true,
-      "requires": {
-        "@babel/helper-annotate-as-pure": "^7.14.5",
-        "@babel/helper-function-name": "^7.14.5",
-        "@babel/helper-optimise-call-expression": "^7.14.5",
-        "@babel/helper-plugin-utils": "^7.14.5",
-        "@babel/helper-replace-supers": "^7.14.5",
-        "@babel/helper-split-export-declaration": "^7.14.5",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.16.7.tgz",
+      "integrity": "sha512-WY7og38SFAGYRe64BrjKf8OrE6ulEHtr5jEYaZMwox9KebgqPi67Zqz8K53EKk1fFEJgm96r32rkKZ3qA2nCWQ==",
+      "dev": true,
+      "requires": {
+        "@babel/helper-annotate-as-pure": "^7.16.7",
+        "@babel/helper-environment-visitor": "^7.16.7",
+        "@babel/helper-function-name": "^7.16.7",
+        "@babel/helper-optimise-call-expression": "^7.16.7",
+        "@babel/helper-plugin-utils": "^7.16.7",
+        "@babel/helper-replace-supers": "^7.16.7",
+        "@babel/helper-split-export-declaration": "^7.16.7",
         "globals": "^11.1.0"
       }
     },
     "@babel/plugin-transform-computed-properties": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.14.5.tgz",
-      "integrity": "sha512-pWM+E4283UxaVzLb8UBXv4EIxMovU4zxT1OPnpHJcmnvyY9QbPPTKZfEj31EUvG3/EQRbYAGaYEUZ4yWOBC2xg==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.16.7.tgz",
+      "integrity": "sha512-gN72G9bcmenVILj//sv1zLNaPyYcOzUho2lIJBMh/iakJ9ygCo/hEF9cpGb61SCMEDxbbyBoVQxrt+bWKu5KGw==",
       "dev": true,
       "requires": {
-        "@babel/helper-plugin-utils": "^7.14.5"
+        "@babel/helper-plugin-utils": "^7.16.7"
       }
     },
     "@babel/plugin-transform-destructuring": {
-      "version": "7.14.7",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.14.7.tgz",
-      "integrity": "sha512-0mDE99nK+kVh3xlc5vKwB6wnP9ecuSj+zQCa/n0voENtP/zymdT4HH6QEb65wjjcbqr1Jb/7z9Qp7TF5FtwYGw==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.16.7.tgz",
+      "integrity": "sha512-VqAwhTHBnu5xBVDCvrvqJbtLUa++qZaWC0Fgr2mqokBlulZARGyIvZDoqbPlPaKImQ9dKAcCzbv+ul//uqu70A==",
       "dev": true,
       "requires": {
-        "@babel/helper-plugin-utils": "^7.14.5"
+        "@babel/helper-plugin-utils": "^7.16.7"
       }
     },
     "@babel/plugin-transform-dotall-regex": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.14.5.tgz",
-      "integrity": "sha512-loGlnBdj02MDsFaHhAIJzh7euK89lBrGIdM9EAtHFo6xKygCUGuuWe07o1oZVk287amtW1n0808sQM99aZt3gw==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.16.7.tgz",
+      "integrity": "sha512-Lyttaao2SjZF6Pf4vk1dVKv8YypMpomAbygW+mU5cYP3S5cWTfCJjG8xV6CFdzGFlfWK81IjL9viiTvpb6G7gQ==",
       "dev": true,
       "requires": {
-        "@babel/helper-create-regexp-features-plugin": "^7.14.5",
-        "@babel/helper-plugin-utils": "^7.14.5"
+        "@babel/helper-create-regexp-features-plugin": "^7.16.7",
+        "@babel/helper-plugin-utils": "^7.16.7"
       }
     },
     "@babel/plugin-transform-duplicate-keys": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.14.5.tgz",
-      "integrity": "sha512-iJjbI53huKbPDAsJ8EmVmvCKeeq21bAze4fu9GBQtSLqfvzj2oRuHVx4ZkDwEhg1htQ+5OBZh/Ab0XDf5iBZ7A==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.16.7.tgz",
+      "integrity": "sha512-03DvpbRfvWIXyK0/6QiR1KMTWeT6OcQ7tbhjrXyFS02kjuX/mu5Bvnh5SDSWHxyawit2g5aWhKwI86EE7GUnTw==",
       "dev": true,
       "requires": {
-        "@babel/helper-plugin-utils": "^7.14.5"
+        "@babel/helper-plugin-utils": "^7.16.7"
       }
     },
     "@babel/plugin-transform-exponentiation-operator": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.14.5.tgz",
-      "integrity": "sha512-jFazJhMBc9D27o9jDnIE5ZErI0R0m7PbKXVq77FFvqFbzvTMuv8jaAwLZ5PviOLSFttqKIW0/wxNSDbjLk0tYA==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.16.7.tgz",
+      "integrity": "sha512-8UYLSlyLgRixQvlYH3J2ekXFHDFLQutdy7FfFAMm3CPZ6q9wHCwnUyiXpQCe3gVVnQlHc5nsuiEVziteRNTXEA==",
       "dev": true,
       "requires": {
-        "@babel/helper-builder-binary-assignment-operator-visitor": "^7.14.5",
-        "@babel/helper-plugin-utils": "^7.14.5"
+        "@babel/helper-builder-binary-assignment-operator-visitor": "^7.16.7",
+        "@babel/helper-plugin-utils": "^7.16.7"
       }
     },
     "@babel/plugin-transform-for-of": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.14.5.tgz",
-      "integrity": "sha512-CfmqxSUZzBl0rSjpoQSFoR9UEj3HzbGuGNL21/iFTmjb5gFggJp3ph0xR1YBhexmLoKRHzgxuFvty2xdSt6gTA==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.16.7.tgz",
+      "integrity": "sha512-/QZm9W92Ptpw7sjI9Nx1mbcsWz33+l8kuMIQnDwgQBG5s3fAfQvkRjQ7NqXhtNcKOnPkdICmUHyCaWW06HCsqg==",
       "dev": true,
       "requires": {
-        "@babel/helper-plugin-utils": "^7.14.5"
+        "@babel/helper-plugin-utils": "^7.16.7"
       }
     },
     "@babel/plugin-transform-function-name": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.14.5.tgz",
-      "integrity": "sha512-vbO6kv0fIzZ1GpmGQuvbwwm+O4Cbm2NrPzwlup9+/3fdkuzo1YqOZcXw26+YUJB84Ja7j9yURWposEHLYwxUfQ==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.16.7.tgz",
+      "integrity": "sha512-SU/C68YVwTRxqWj5kgsbKINakGag0KTgq9f2iZEXdStoAbOzLHEBRYzImmA6yFo8YZhJVflvXmIHUO7GWHmxxA==",
       "dev": true,
       "requires": {
-        "@babel/helper-function-name": "^7.14.5",
-        "@babel/helper-plugin-utils": "^7.14.5"
+        "@babel/helper-compilation-targets": "^7.16.7",
+        "@babel/helper-function-name": "^7.16.7",
+        "@babel/helper-plugin-utils": "^7.16.7"
       }
     },
     "@babel/plugin-transform-literals": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.14.5.tgz",
-      "integrity": "sha512-ql33+epql2F49bi8aHXxvLURHkxJbSmMKl9J5yHqg4PLtdE6Uc48CH1GS6TQvZ86eoB/ApZXwm7jlA+B3kra7A==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.16.7.tgz",
+      "integrity": "sha512-6tH8RTpTWI0s2sV6uq3e/C9wPo4PTqqZps4uF0kzQ9/xPLFQtipynvmT1g/dOfEJ+0EQsHhkQ/zyRId8J2b8zQ==",
       "dev": true,
       "requires": {
-        "@babel/helper-plugin-utils": "^7.14.5"
+        "@babel/helper-plugin-utils": "^7.16.7"
       }
     },
     "@babel/plugin-transform-member-expression-literals": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.14.5.tgz",
-      "integrity": "sha512-WkNXxH1VXVTKarWFqmso83xl+2V3Eo28YY5utIkbsmXoItO8Q3aZxN4BTS2k0hz9dGUloHK26mJMyQEYfkn/+Q==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.16.7.tgz",
+      "integrity": "sha512-mBruRMbktKQwbxaJof32LT9KLy2f3gH+27a5XSuXo6h7R3vqltl0PgZ80C8ZMKw98Bf8bqt6BEVi3svOh2PzMw==",
       "dev": true,
       "requires": {
-        "@babel/helper-plugin-utils": "^7.14.5"
+        "@babel/helper-plugin-utils": "^7.16.7"
       }
     },
     "@babel/plugin-transform-modules-amd": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.14.5.tgz",
-      "integrity": "sha512-3lpOU8Vxmp3roC4vzFpSdEpGUWSMsHFreTWOMMLzel2gNGfHE5UWIh/LN6ghHs2xurUp4jRFYMUIZhuFbody1g==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.16.7.tgz",
+      "integrity": "sha512-KaaEtgBL7FKYwjJ/teH63oAmE3lP34N3kshz8mm4VMAw7U3PxjVwwUmxEFksbgsNUaO3wId9R2AVQYSEGRa2+g==",
       "dev": true,
       "requires": {
-        "@babel/helper-module-transforms": "^7.14.5",
-        "@babel/helper-plugin-utils": "^7.14.5",
+        "@babel/helper-module-transforms": "^7.16.7",
+        "@babel/helper-plugin-utils": "^7.16.7",
         "babel-plugin-dynamic-import-node": "^2.3.3"
       }
     },
     "@babel/plugin-transform-modules-commonjs": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.14.5.tgz",
-      "integrity": "sha512-en8GfBtgnydoao2PS+87mKyw62k02k7kJ9ltbKe0fXTHrQmG6QZZflYuGI1VVG7sVpx4E1n7KBpNlPb8m78J+A==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.16.7.tgz",
+      "integrity": "sha512-h2RP2kE7He1ZWKyAlanMZrAbdv+Acw1pA8dQZhE025WJZE2z0xzFADAinXA9fxd5bn7JnM+SdOGcndGx1ARs9w==",
       "dev": true,
       "requires": {
-        "@babel/helper-module-transforms": "^7.14.5",
-        "@babel/helper-plugin-utils": "^7.14.5",
-        "@babel/helper-simple-access": "^7.14.5",
+        "@babel/helper-module-transforms": "^7.16.7",
+        "@babel/helper-plugin-utils": "^7.16.7",
+        "@babel/helper-simple-access": "^7.16.7",
         "babel-plugin-dynamic-import-node": "^2.3.3"
       }
     },
     "@babel/plugin-transform-modules-systemjs": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.14.5.tgz",
-      "integrity": "sha512-mNMQdvBEE5DcMQaL5LbzXFMANrQjd2W7FPzg34Y4yEz7dBgdaC+9B84dSO+/1Wba98zoDbInctCDo4JGxz1VYA==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.16.7.tgz",
+      "integrity": "sha512-DuK5E3k+QQmnOqBR9UkusByy5WZWGRxfzV529s9nPra1GE7olmxfqO2FHobEOYSPIjPBTr4p66YDcjQnt8cBmw==",
       "dev": true,
       "requires": {
-        "@babel/helper-hoist-variables": "^7.14.5",
-        "@babel/helper-module-transforms": "^7.14.5",
-        "@babel/helper-plugin-utils": "^7.14.5",
-        "@babel/helper-validator-identifier": "^7.14.5",
+        "@babel/helper-hoist-variables": "^7.16.7",
+        "@babel/helper-module-transforms": "^7.16.7",
+        "@babel/helper-plugin-utils": "^7.16.7",
+        "@babel/helper-validator-identifier": "^7.16.7",
         "babel-plugin-dynamic-import-node": "^2.3.3"
       }
     },
     "@babel/plugin-transform-modules-umd": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.14.5.tgz",
-      "integrity": "sha512-RfPGoagSngC06LsGUYyM9QWSXZ8MysEjDJTAea1lqRjNECE3y0qIJF/qbvJxc4oA4s99HumIMdXOrd+TdKaAAA==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.16.7.tgz",
+      "integrity": "sha512-EMh7uolsC8O4xhudF2F6wedbSHm1HHZ0C6aJ7K67zcDNidMzVcxWdGr+htW9n21klm+bOn+Rx4CBsAntZd3rEQ==",
       "dev": true,
       "requires": {
-        "@babel/helper-module-transforms": "^7.14.5",
-        "@babel/helper-plugin-utils": "^7.14.5"
+        "@babel/helper-module-transforms": "^7.16.7",
+        "@babel/helper-plugin-utils": "^7.16.7"
       }
     },
     "@babel/plugin-transform-named-capturing-groups-regex": {
-      "version": "7.14.7",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.14.7.tgz",
-      "integrity": "sha512-DTNOTaS7TkW97xsDMrp7nycUVh6sn/eq22VaxWfEdzuEbRsiaOU0pqU7DlyUGHVsbQbSghvjKRpEl+nUCKGQSg==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.16.7.tgz",
+      "integrity": "sha512-kFy35VwmwIQwCjwrAQhl3+c/kr292i4KdLPKp5lPH03Ltc51qnFlIADoyPxc/6Naz3ok3WdYKg+KK6AH+D4utg==",
       "dev": true,
       "requires": {
-        "@babel/helper-create-regexp-features-plugin": "^7.14.5"
+        "@babel/helper-create-regexp-features-plugin": "^7.16.7"
       }
     },
     "@babel/plugin-transform-new-target": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.14.5.tgz",
-      "integrity": "sha512-Nx054zovz6IIRWEB49RDRuXGI4Gy0GMgqG0cII9L3MxqgXz/+rgII+RU58qpo4g7tNEx1jG7rRVH4ihZoP4esQ==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.16.7.tgz",
+      "integrity": "sha512-xiLDzWNMfKoGOpc6t3U+etCE2yRnn3SM09BXqWPIZOBpL2gvVrBWUKnsJx0K/ADi5F5YC5f8APFfWrz25TdlGg==",
       "dev": true,
       "requires": {
-        "@babel/helper-plugin-utils": "^7.14.5"
+        "@babel/helper-plugin-utils": "^7.16.7"
       }
     },
     "@babel/plugin-transform-object-super": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.14.5.tgz",
-      "integrity": "sha512-MKfOBWzK0pZIrav9z/hkRqIk/2bTv9qvxHzPQc12RcVkMOzpIKnFCNYJip00ssKWYkd8Sf5g0Wr7pqJ+cmtuFg==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.16.7.tgz",
+      "integrity": "sha512-14J1feiQVWaGvRxj2WjyMuXS2jsBkgB3MdSN5HuC2G5nRspa5RK9COcs82Pwy5BuGcjb+fYaUj94mYcOj7rCvw==",
       "dev": true,
       "requires": {
-        "@babel/helper-plugin-utils": "^7.14.5",
-        "@babel/helper-replace-supers": "^7.14.5"
+        "@babel/helper-plugin-utils": "^7.16.7",
+        "@babel/helper-replace-supers": "^7.16.7"
       }
     },
     "@babel/plugin-transform-parameters": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.14.5.tgz",
-      "integrity": "sha512-Tl7LWdr6HUxTmzQtzuU14SqbgrSKmaR77M0OKyq4njZLQTPfOvzblNKyNkGwOfEFCEx7KeYHQHDI0P3F02IVkA==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.16.7.tgz",
+      "integrity": "sha512-AT3MufQ7zZEhU2hwOA11axBnExW0Lszu4RL/tAlUJBuNoRak+wehQW8h6KcXOcgjY42fHtDxswuMhMjFEuv/aw==",
       "dev": true,
       "requires": {
-        "@babel/helper-plugin-utils": "^7.14.5"
+        "@babel/helper-plugin-utils": "^7.16.7"
       }
     },
     "@babel/plugin-transform-property-literals": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.14.5.tgz",
-      "integrity": "sha512-r1uilDthkgXW8Z1vJz2dKYLV1tuw2xsbrp3MrZmD99Wh9vsfKoob+JTgri5VUb/JqyKRXotlOtwgu4stIYCmnw==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.16.7.tgz",
+      "integrity": "sha512-z4FGr9NMGdoIl1RqavCqGG+ZuYjfZ/hkCIeuH6Do7tXmSm0ls11nYVSJqFEUOSJbDab5wC6lRE/w6YjVcr6Hqw==",
       "dev": true,
       "requires": {
-        "@babel/helper-plugin-utils": "^7.14.5"
+        "@babel/helper-plugin-utils": "^7.16.7"
       }
     },
     "@babel/plugin-transform-regenerator": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.14.5.tgz",
-      "integrity": "sha512-NVIY1W3ITDP5xQl50NgTKlZ0GrotKtLna08/uGY6ErQt6VEQZXla86x/CTddm5gZdcr+5GSsvMeTmWA5Ii6pkg==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.16.7.tgz",
+      "integrity": "sha512-mF7jOgGYCkSJagJ6XCujSQg+6xC1M77/03K2oBmVJWoFGNUtnVJO4WHKJk3dnPC8HCcj4xBQP1Egm8DWh3Pb3Q==",
       "dev": true,
       "requires": {
         "regenerator-transform": "^0.14.2"
       }
     },
     "@babel/plugin-transform-reserved-words": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.14.5.tgz",
-      "integrity": "sha512-cv4F2rv1nD4qdexOGsRQXJrOcyb5CrgjUH9PKrrtyhSDBNWGxd0UIitjyJiWagS+EbUGjG++22mGH1Pub8D6Vg==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.16.7.tgz",
+      "integrity": "sha512-KQzzDnZ9hWQBjwi5lpY5v9shmm6IVG0U9pB18zvMu2i4H90xpT4gmqwPYsn8rObiadYe2M0gmgsiOIF5A/2rtg==",
       "dev": true,
       "requires": {
-        "@babel/helper-plugin-utils": "^7.14.5"
+        "@babel/helper-plugin-utils": "^7.16.7"
       }
     },
     "@babel/plugin-transform-runtime": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.14.5.tgz",
-      "integrity": "sha512-fPMBhh1AV8ZyneiCIA+wYYUH1arzlXR1UMcApjvchDhfKxhy2r2lReJv8uHEyihi4IFIGlr1Pdx7S5fkESDQsg==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.16.7.tgz",
+      "integrity": "sha512-2FoHiSAWkdq4L06uaDN3rS43i6x28desUVxq+zAFuE6kbWYQeiLPJI5IC7Sg9xKYVcrBKSQkVUfH6aeQYbl9QA==",
       "dev": true,
       "requires": {
-        "@babel/helper-module-imports": "^7.14.5",
-        "@babel/helper-plugin-utils": "^7.14.5",
-        "babel-plugin-polyfill-corejs2": "^0.2.2",
-        "babel-plugin-polyfill-corejs3": "^0.2.2",
-        "babel-plugin-polyfill-regenerator": "^0.2.2",
+        "@babel/helper-module-imports": "^7.16.7",
+        "@babel/helper-plugin-utils": "^7.16.7",
+        "babel-plugin-polyfill-corejs2": "^0.3.0",
+        "babel-plugin-polyfill-corejs3": "^0.4.0",
+        "babel-plugin-polyfill-regenerator": "^0.3.0",
         "semver": "^6.3.0"
       }
     },
     "@babel/plugin-transform-shorthand-properties": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.14.5.tgz",
-      "integrity": "sha512-xLucks6T1VmGsTB+GWK5Pl9Jl5+nRXD1uoFdA5TSO6xtiNjtXTjKkmPdFXVLGlK5A2/or/wQMKfmQ2Y0XJfn5g==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.16.7.tgz",
+      "integrity": "sha512-hah2+FEnoRoATdIb05IOXf+4GzXYTq75TVhIn1PewihbpyrNWUt2JbudKQOETWw6QpLe+AIUpJ5MVLYTQbeeUg==",
       "dev": true,
       "requires": {
-        "@babel/helper-plugin-utils": "^7.14.5"
+        "@babel/helper-plugin-utils": "^7.16.7"
       }
     },
     "@babel/plugin-transform-spread": {
-      "version": "7.14.6",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.14.6.tgz",
-      "integrity": "sha512-Zr0x0YroFJku7n7+/HH3A2eIrGMjbmAIbJSVv0IZ+t3U2WUQUA64S/oeied2e+MaGSjmt4alzBCsK9E8gh+fag==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.16.7.tgz",
+      "integrity": "sha512-+pjJpgAngb53L0iaA5gU/1MLXJIfXcYepLgXB3esVRf4fqmj8f2cxM3/FKaHsZms08hFQJkFccEWuIpm429TXg==",
       "dev": true,
       "requires": {
-        "@babel/helper-plugin-utils": "^7.14.5",
-        "@babel/helper-skip-transparent-expression-wrappers": "^7.14.5"
+        "@babel/helper-plugin-utils": "^7.16.7",
+        "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0"
       }
     },
     "@babel/plugin-transform-sticky-regex": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.14.5.tgz",
-      "integrity": "sha512-Z7F7GyvEMzIIbwnziAZmnSNpdijdr4dWt+FJNBnBLz5mwDFkqIXU9wmBcWWad3QeJF5hMTkRe4dAq2sUZiG+8A==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.16.7.tgz",
+      "integrity": "sha512-NJa0Bd/87QV5NZZzTuZG5BPJjLYadeSZ9fO6oOUoL4iQx+9EEuw/eEM92SrsT19Yc2jgB1u1hsjqDtH02c3Drw==",
       "dev": true,
       "requires": {
-        "@babel/helper-plugin-utils": "^7.14.5"
+        "@babel/helper-plugin-utils": "^7.16.7"
       }
     },
     "@babel/plugin-transform-template-literals": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.14.5.tgz",
-      "integrity": "sha512-22btZeURqiepOfuy/VkFr+zStqlujWaarpMErvay7goJS6BWwdd6BY9zQyDLDa4x2S3VugxFb162IZ4m/S/+Gg==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.16.7.tgz",
+      "integrity": "sha512-VwbkDDUeenlIjmfNeDX/V0aWrQH2QiVyJtwymVQSzItFDTpxfyJh3EVaQiS0rIN/CqbLGr0VcGmuwyTdZtdIsA==",
       "dev": true,
       "requires": {
-        "@babel/helper-plugin-utils": "^7.14.5"
+        "@babel/helper-plugin-utils": "^7.16.7"
       }
     },
     "@babel/plugin-transform-typeof-symbol": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.14.5.tgz",
-      "integrity": "sha512-lXzLD30ffCWseTbMQzrvDWqljvZlHkXU+CnseMhkMNqU1sASnCsz3tSzAaH3vCUXb9PHeUb90ZT1BdFTm1xxJw==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.16.7.tgz",
+      "integrity": "sha512-p2rOixCKRJzpg9JB4gjnG4gjWkWa89ZoYUnl9snJ1cWIcTH/hvxZqfO+WjG6T8DRBpctEol5jw1O5rA8gkCokQ==",
       "dev": true,
       "requires": {
-        "@babel/helper-plugin-utils": "^7.14.5"
+        "@babel/helper-plugin-utils": "^7.16.7"
       }
     },
     "@babel/plugin-transform-unicode-escapes": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.14.5.tgz",
-      "integrity": "sha512-crTo4jATEOjxj7bt9lbYXcBAM3LZaUrbP2uUdxb6WIorLmjNKSpHfIybgY4B8SRpbf8tEVIWH3Vtm7ayCrKocA==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.16.7.tgz",
+      "integrity": "sha512-TAV5IGahIz3yZ9/Hfv35TV2xEm+kaBDaZQCn2S/hG9/CZ0DktxJv9eKfPc7yYCvOYR4JGx1h8C+jcSOvgaaI/Q==",
       "dev": true,
       "requires": {
-        "@babel/helper-plugin-utils": "^7.14.5"
+        "@babel/helper-plugin-utils": "^7.16.7"
       }
     },
     "@babel/plugin-transform-unicode-regex": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.14.5.tgz",
-      "integrity": "sha512-UygduJpC5kHeCiRw/xDVzC+wj8VaYSoKl5JNVmbP7MadpNinAm3SvZCxZ42H37KZBKztz46YC73i9yV34d0Tzw==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.16.7.tgz",
+      "integrity": "sha512-oC5tYYKw56HO75KZVLQ+R/Nl3Hro9kf8iG0hXoaHP7tjAyCpvqBiSNe6vGrZni1Z6MggmUOC6A7VP7AVmw225Q==",
       "dev": true,
       "requires": {
-        "@babel/helper-create-regexp-features-plugin": "^7.14.5",
-        "@babel/helper-plugin-utils": "^7.14.5"
+        "@babel/helper-create-regexp-features-plugin": "^7.16.7",
+        "@babel/helper-plugin-utils": "^7.16.7"
       }
     },
     "@babel/preset-env": {
-      "version": "7.14.7",
-      "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.14.7.tgz",
-      "integrity": "sha512-itOGqCKLsSUl0Y+1nSfhbuuOlTs0MJk2Iv7iSH+XT/mR8U1zRLO7NjWlYXB47yhK4J/7j+HYty/EhFZDYKa/VA==",
-      "dev": true,
-      "requires": {
-        "@babel/compat-data": "^7.14.7",
-        "@babel/helper-compilation-targets": "^7.14.5",
-        "@babel/helper-plugin-utils": "^7.14.5",
-        "@babel/helper-validator-option": "^7.14.5",
-        "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.14.5",
-        "@babel/plugin-proposal-async-generator-functions": "^7.14.7",
-        "@babel/plugin-proposal-class-properties": "^7.14.5",
-        "@babel/plugin-proposal-class-static-block": "^7.14.5",
-        "@babel/plugin-proposal-dynamic-import": "^7.14.5",
-        "@babel/plugin-proposal-export-namespace-from": "^7.14.5",
-        "@babel/plugin-proposal-json-strings": "^7.14.5",
-        "@babel/plugin-proposal-logical-assignment-operators": "^7.14.5",
-        "@babel/plugin-proposal-nullish-coalescing-operator": "^7.14.5",
-        "@babel/plugin-proposal-numeric-separator": "^7.14.5",
-        "@babel/plugin-proposal-object-rest-spread": "^7.14.7",
-        "@babel/plugin-proposal-optional-catch-binding": "^7.14.5",
-        "@babel/plugin-proposal-optional-chaining": "^7.14.5",
-        "@babel/plugin-proposal-private-methods": "^7.14.5",
-        "@babel/plugin-proposal-private-property-in-object": "^7.14.5",
-        "@babel/plugin-proposal-unicode-property-regex": "^7.14.5",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.16.7.tgz",
+      "integrity": "sha512-urX3Cee4aOZbRWOSa3mKPk0aqDikfILuo+C7qq7HY0InylGNZ1fekq9jmlr3pLWwZHF4yD7heQooc2Pow2KMyQ==",
+      "dev": true,
+      "requires": {
+        "@babel/compat-data": "^7.16.4",
+        "@babel/helper-compilation-targets": "^7.16.7",
+        "@babel/helper-plugin-utils": "^7.16.7",
+        "@babel/helper-validator-option": "^7.16.7",
+        "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.16.7",
+        "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.16.7",
+        "@babel/plugin-proposal-async-generator-functions": "^7.16.7",
+        "@babel/plugin-proposal-class-properties": "^7.16.7",
+        "@babel/plugin-proposal-class-static-block": "^7.16.7",
+        "@babel/plugin-proposal-dynamic-import": "^7.16.7",
+        "@babel/plugin-proposal-export-namespace-from": "^7.16.7",
+        "@babel/plugin-proposal-json-strings": "^7.16.7",
+        "@babel/plugin-proposal-logical-assignment-operators": "^7.16.7",
+        "@babel/plugin-proposal-nullish-coalescing-operator": "^7.16.7",
+        "@babel/plugin-proposal-numeric-separator": "^7.16.7",
+        "@babel/plugin-proposal-object-rest-spread": "^7.16.7",
+        "@babel/plugin-proposal-optional-catch-binding": "^7.16.7",
+        "@babel/plugin-proposal-optional-chaining": "^7.16.7",
+        "@babel/plugin-proposal-private-methods": "^7.16.7",
+        "@babel/plugin-proposal-private-property-in-object": "^7.16.7",
+        "@babel/plugin-proposal-unicode-property-regex": "^7.16.7",
         "@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",
@@ -1003,51 +1049,51 @@
         "@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.14.5",
-        "@babel/plugin-transform-async-to-generator": "^7.14.5",
-        "@babel/plugin-transform-block-scoped-functions": "^7.14.5",
-        "@babel/plugin-transform-block-scoping": "^7.14.5",
-        "@babel/plugin-transform-classes": "^7.14.5",
-        "@babel/plugin-transform-computed-properties": "^7.14.5",
-        "@babel/plugin-transform-destructuring": "^7.14.7",
-        "@babel/plugin-transform-dotall-regex": "^7.14.5",
-        "@babel/plugin-transform-duplicate-keys": "^7.14.5",
-        "@babel/plugin-transform-exponentiation-operator": "^7.14.5",
-        "@babel/plugin-transform-for-of": "^7.14.5",
-        "@babel/plugin-transform-function-name": "^7.14.5",
-        "@babel/plugin-transform-literals": "^7.14.5",
-        "@babel/plugin-transform-member-expression-literals": "^7.14.5",
-        "@babel/plugin-transform-modules-amd": "^7.14.5",
-        "@babel/plugin-transform-modules-commonjs": "^7.14.5",
-        "@babel/plugin-transform-modules-systemjs": "^7.14.5",
-        "@babel/plugin-transform-modules-umd": "^7.14.5",
-        "@babel/plugin-transform-named-capturing-groups-regex": "^7.14.7",
-        "@babel/plugin-transform-new-target": "^7.14.5",
-        "@babel/plugin-transform-object-super": "^7.14.5",
-        "@babel/plugin-transform-parameters": "^7.14.5",
-        "@babel/plugin-transform-property-literals": "^7.14.5",
-        "@babel/plugin-transform-regenerator": "^7.14.5",
-        "@babel/plugin-transform-reserved-words": "^7.14.5",
-        "@babel/plugin-transform-shorthand-properties": "^7.14.5",
-        "@babel/plugin-transform-spread": "^7.14.6",
-        "@babel/plugin-transform-sticky-regex": "^7.14.5",
-        "@babel/plugin-transform-template-literals": "^7.14.5",
-        "@babel/plugin-transform-typeof-symbol": "^7.14.5",
-        "@babel/plugin-transform-unicode-escapes": "^7.14.5",
-        "@babel/plugin-transform-unicode-regex": "^7.14.5",
-        "@babel/preset-modules": "^0.1.4",
-        "@babel/types": "^7.14.5",
-        "babel-plugin-polyfill-corejs2": "^0.2.2",
-        "babel-plugin-polyfill-corejs3": "^0.2.2",
-        "babel-plugin-polyfill-regenerator": "^0.2.2",
-        "core-js-compat": "^3.15.0",
+        "@babel/plugin-transform-arrow-functions": "^7.16.7",
+        "@babel/plugin-transform-async-to-generator": "^7.16.7",
+        "@babel/plugin-transform-block-scoped-functions": "^7.16.7",
+        "@babel/plugin-transform-block-scoping": "^7.16.7",
+        "@babel/plugin-transform-classes": "^7.16.7",
+        "@babel/plugin-transform-computed-properties": "^7.16.7",
+        "@babel/plugin-transform-destructuring": "^7.16.7",
+        "@babel/plugin-transform-dotall-regex": "^7.16.7",
+        "@babel/plugin-transform-duplicate-keys": "^7.16.7",
+        "@babel/plugin-transform-exponentiation-operator": "^7.16.7",
+        "@babel/plugin-transform-for-of": "^7.16.7",
+        "@babel/plugin-transform-function-name": "^7.16.7",
+        "@babel/plugin-transform-literals": "^7.16.7",
+        "@babel/plugin-transform-member-expression-literals": "^7.16.7",
+        "@babel/plugin-transform-modules-amd": "^7.16.7",
+        "@babel/plugin-transform-modules-commonjs": "^7.16.7",
+        "@babel/plugin-transform-modules-systemjs": "^7.16.7",
+        "@babel/plugin-transform-modules-umd": "^7.16.7",
+        "@babel/plugin-transform-named-capturing-groups-regex": "^7.16.7",
+        "@babel/plugin-transform-new-target": "^7.16.7",
+        "@babel/plugin-transform-object-super": "^7.16.7",
+        "@babel/plugin-transform-parameters": "^7.16.7",
+        "@babel/plugin-transform-property-literals": "^7.16.7",
+        "@babel/plugin-transform-regenerator": "^7.16.7",
+        "@babel/plugin-transform-reserved-words": "^7.16.7",
+        "@babel/plugin-transform-shorthand-properties": "^7.16.7",
+        "@babel/plugin-transform-spread": "^7.16.7",
+        "@babel/plugin-transform-sticky-regex": "^7.16.7",
+        "@babel/plugin-transform-template-literals": "^7.16.7",
+        "@babel/plugin-transform-typeof-symbol": "^7.16.7",
+        "@babel/plugin-transform-unicode-escapes": "^7.16.7",
+        "@babel/plugin-transform-unicode-regex": "^7.16.7",
+        "@babel/preset-modules": "^0.1.5",
+        "@babel/types": "^7.16.7",
+        "babel-plugin-polyfill-corejs2": "^0.3.0",
+        "babel-plugin-polyfill-corejs3": "^0.4.0",
+        "babel-plugin-polyfill-regenerator": "^0.3.0",
+        "core-js-compat": "^3.19.1",
         "semver": "^6.3.0"
       }
     },
     "@babel/preset-modules": {
-      "version": "0.1.4",
-      "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.4.tgz",
-      "integrity": "sha512-J36NhwnfdzpmH41M1DrnkkgAqhZaqr/NBdPfQ677mLzlaXo+oDiv1deyCDtgAhz8p328otdob0Du7+xgHGZbKg==",
+      "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",
@@ -1058,52 +1104,103 @@
       }
     },
     "@babel/runtime": {
-      "version": "7.14.6",
-      "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.6.tgz",
-      "integrity": "sha512-/PCB2uJ7oM44tz8YhC4Z/6PeOKXp4K588f+5M3clr1M4zbqztlo0XEfJ2LEzj/FgwfgGcIdl8n7YYjTCI0BYwg==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.16.7.tgz",
+      "integrity": "sha512-9E9FJowqAsytyOY6LG+1KuueckRL+aQW+mKvXRXnuFGyRAyepJPmEo9vgMfXUA6O9u3IeEdv9MAkppFcaQwogQ==",
       "dev": true,
       "requires": {
         "regenerator-runtime": "^0.13.4"
       }
     },
     "@babel/template": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.14.5.tgz",
-      "integrity": "sha512-6Z3Po85sfxRGachLULUhOmvAaOo7xCvqGQtxINai2mEGPFm6pQ4z5QInFnUrRpfoSV60BnjyF5F3c+15fxFV1g==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz",
+      "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==",
       "dev": true,
       "requires": {
-        "@babel/code-frame": "^7.14.5",
-        "@babel/parser": "^7.14.5",
-        "@babel/types": "^7.14.5"
+        "@babel/code-frame": "^7.16.7",
+        "@babel/parser": "^7.16.7",
+        "@babel/types": "^7.16.7"
       }
     },
     "@babel/traverse": {
-      "version": "7.14.7",
-      "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.14.7.tgz",
-      "integrity": "sha512-9vDr5NzHu27wgwejuKL7kIOm4bwEtaPQ4Z6cpCmjSuaRqpH/7xc4qcGEscwMqlkwgcXl6MvqoAjZkQ24uSdIZQ==",
-      "dev": true,
-      "requires": {
-        "@babel/code-frame": "^7.14.5",
-        "@babel/generator": "^7.14.5",
-        "@babel/helper-function-name": "^7.14.5",
-        "@babel/helper-hoist-variables": "^7.14.5",
-        "@babel/helper-split-export-declaration": "^7.14.5",
-        "@babel/parser": "^7.14.7",
-        "@babel/types": "^7.14.5",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.16.7.tgz",
+      "integrity": "sha512-8KWJPIb8c2VvY8AJrydh6+fVRo2ODx1wYBU2398xJVq0JomuLBZmVQzLPBblJgHIGYG4znCpUZUZ0Pt2vdmVYQ==",
+      "dev": true,
+      "requires": {
+        "@babel/code-frame": "^7.16.7",
+        "@babel/generator": "^7.16.7",
+        "@babel/helper-environment-visitor": "^7.16.7",
+        "@babel/helper-function-name": "^7.16.7",
+        "@babel/helper-hoist-variables": "^7.16.7",
+        "@babel/helper-split-export-declaration": "^7.16.7",
+        "@babel/parser": "^7.16.7",
+        "@babel/types": "^7.16.7",
         "debug": "^4.1.0",
         "globals": "^11.1.0"
       }
     },
     "@babel/types": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.5.tgz",
-      "integrity": "sha512-M/NzBpEL95I5Hh4dwhin5JlE7EzO5PHMAuzjxss3tiOBD46KfQvVedN/3jEPZvdRvtsK2222XfdHogNIttFgcg==",
+      "version": "7.16.7",
+      "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.16.7.tgz",
+      "integrity": "sha512-E8HuV7FO9qLpx6OtoGfUQ2cjIYnbFwvZWYBS+87EwtdMvmUPJSwykpovFB+8insbpF0uJcpr8KMUi64XZntZcg==",
       "dev": true,
       "requires": {
-        "@babel/helper-validator-identifier": "^7.14.5",
+        "@babel/helper-validator-identifier": "^7.16.7",
         "to-fast-properties": "^2.0.0"
       }
     },
+    "@eslint/eslintrc": {
+      "version": "0.4.3",
+      "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz",
+      "integrity": "sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==",
+      "dev": true,
+      "requires": {
+        "ajv": "^6.12.4",
+        "debug": "^4.1.1",
+        "espree": "^7.3.0",
+        "globals": "^13.9.0",
+        "ignore": "^4.0.6",
+        "import-fresh": "^3.2.1",
+        "js-yaml": "^3.13.1",
+        "minimatch": "^3.0.4",
+        "strip-json-comments": "^3.1.1"
+      },
+      "dependencies": {
+        "globals": {
+          "version": "13.12.0",
+          "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.0.tgz",
+          "integrity": "sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg==",
+          "dev": true,
+          "requires": {
+            "type-fest": "^0.20.2"
+          }
+        },
+        "import-fresh": {
+          "version": "3.3.0",
+          "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
+          "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
+          "dev": true,
+          "requires": {
+            "parent-module": "^1.0.0",
+            "resolve-from": "^4.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==",
+          "dev": true
+        },
+        "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
+        }
+      }
+    },
     "@fortawesome/fontawesome-common-types": {
       "version": "0.2.36",
       "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.36.tgz",
@@ -1191,6 +1288,23 @@
         "@hapi/hoek": "^8.3.0"
       }
     },
+    "@humanwhocodes/config-array": {
+      "version": "0.5.0",
+      "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz",
+      "integrity": "sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==",
+      "dev": true,
+      "requires": {
+        "@humanwhocodes/object-schema": "^1.2.0",
+        "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
+    },
     "@intervolga/optimize-cssnano-plugin": {
       "version": "1.0.6",
       "resolved": "https://registry.npmjs.org/@intervolga/optimize-cssnano-plugin/-/optimize-cssnano-plugin-1.0.6.tgz",
@@ -1225,22 +1339,130 @@
         "glob-to-regexp": "^0.3.0"
       }
     },
+    "@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"
+      },
+      "dependencies": {
+        "@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.stat": {
       "version": "1.1.3",
       "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz",
       "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==",
       "dev": true
     },
+    "@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"
+      }
+    },
+    "@sideway/address": {
+      "version": "4.1.3",
+      "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.3.tgz",
+      "integrity": "sha512-8ncEUtmnTsMmL7z1YPB47kPUq7LpKWJNFPsRzHiIajGC5uXlWGn+AmkYPcHNl8S4tcEGx+cnORnNYaw2wvL+LQ==",
+      "dev": true,
+      "requires": {
+        "@hapi/hoek": "^9.0.0"
+      },
+      "dependencies": {
+        "@hapi/hoek": {
+          "version": "9.2.1",
+          "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.2.1.tgz",
+          "integrity": "sha512-gfta+H8aziZsm8pZa0vj04KO6biEiisppNgA1kbJvFrrWu9Vm7eaUEy76DIxsuTaWvti5fkJVhllWc6ZTE+Mdw==",
+          "dev": true
+        }
+      }
+    },
+    "@sideway/formula": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.0.tgz",
+      "integrity": "sha512-vHe7wZ4NOXVfkoRb8T5otiENVlT7a3IAiw7H5M2+GO+9CDgcVUUsX1zalAztCmwyOr2RUTGJdgB+ZvSVqmdHmg==",
+      "dev": true
+    },
+    "@sideway/pinpoint": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz",
+      "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==",
+      "dev": true
+    },
     "@soda/friendly-errors-webpack-plugin": {
-      "version": "1.8.0",
-      "resolved": "https://registry.npmjs.org/@soda/friendly-errors-webpack-plugin/-/friendly-errors-webpack-plugin-1.8.0.tgz",
-      "integrity": "sha512-RLotfx6k1+nfLacwNCenj7VnTMPxVwYKoGOcffMFoJDKM8tXzBiCN0hMHFJNnoAojduYAsxuiMm0EOMixgiRow==",
+      "version": "1.8.1",
+      "resolved": "https://registry.npmjs.org/@soda/friendly-errors-webpack-plugin/-/friendly-errors-webpack-plugin-1.8.1.tgz",
+      "integrity": "sha512-h2ooWqP8XuFqTXT+NyAFbrArzfQA7R6HTezADrvD9Re8fxMLTPPniLdqVTdDaO0eIoLaAwKT+d6w+5GeTk7Vbg==",
       "dev": true,
       "requires": {
-        "chalk": "^2.4.2",
-        "error-stack-parser": "^2.0.2",
-        "string-width": "^2.0.0",
-        "strip-ansi": "^5"
+        "chalk": "^3.0.0",
+        "error-stack-parser": "^2.0.6",
+        "string-width": "^4.2.3",
+        "strip-ansi": "^6.0.1"
+      },
+      "dependencies": {
+        "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"
+          }
+        },
+        "chalk": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
+          "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==",
+          "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
+        },
+        "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
+        },
+        "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"
+          }
+        }
       }
     },
     "@soda/get-current-script": {
@@ -1281,9 +1503,9 @@
       }
     },
     "@types/body-parser": {
-      "version": "1.19.1",
-      "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.1.tgz",
-      "integrity": "sha512-a6bTJ21vFOGIkwM0kzh9Yr89ziVxq4vYH2fQ6N8AeipEzai/cFK6aGMArIkUeIdRIgpwQa+2bXiLuUJCpSf2Cg==",
+      "version": "1.19.2",
+      "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz",
+      "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==",
       "dev": true,
       "requires": {
         "@types/connect": "*",
@@ -1309,8 +1531,34 @@
         "@types/node": "*"
       }
     },
-    "@types/express": {
-      "version": "4.17.13",
+    "@types/eslint": {
+      "version": "7.29.0",
+      "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-7.29.0.tgz",
+      "integrity": "sha512-VNcvioYDH8/FxaeTKkM4/TiTwt6pBV9E3OfGmvaw8tPl0rrHCJ4Ll15HRT+pMiFAf/MLQvAzC+6RzUMEL9Ceng==",
+      "dev": true,
+      "requires": {
+        "@types/estree": "*",
+        "@types/json-schema": "*"
+      }
+    },
+    "@types/eslint-scope": {
+      "version": "3.7.2",
+      "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.2.tgz",
+      "integrity": "sha512-TzgYCWoPiTeRg6RQYgtuW7iODtVoKu3RVL72k3WohqhjfaOLK5Mg2T4Tg1o2bSfu0vPkoI48wdQFv5b/Xe04wQ==",
+      "dev": true,
+      "requires": {
+        "@types/eslint": "*",
+        "@types/estree": "*"
+      }
+    },
+    "@types/estree": {
+      "version": "0.0.50",
+      "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.50.tgz",
+      "integrity": "sha512-C6N5s2ZFtuZRj54k2/zyRhNDjJwwcViAM3Nbm8zjBpbqAdZ00mr0CFxvSKeO8Y/e03WVFLpQMdHYVfUd6SB+Hw==",
+      "dev": true
+    },
+    "@types/express": {
+      "version": "4.17.13",
       "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz",
       "integrity": "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==",
       "dev": true,
@@ -1322,9 +1570,9 @@
       }
     },
     "@types/express-serve-static-core": {
-      "version": "4.17.23",
-      "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.23.tgz",
-      "integrity": "sha512-WYqTtTPTJn9kXMdnAH5HPPb7ctXvBpP4PfuOb8MV4OHPQWHhDZixGlhgR159lJPpKm23WOdoCkt2//cCEaOJkw==",
+      "version": "4.17.27",
+      "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.27.tgz",
+      "integrity": "sha512-e/sVallzUTPdyOTiqi8O8pMdBBphscvI6E4JYaKlja4Lm+zh7UFSSdW5VMkRbhDtmrONqOUHOXRguPsDckzxNA==",
       "dev": true,
       "requires": {
         "@types/node": "*",
@@ -1333,9 +1581,9 @@
       }
     },
     "@types/glob": {
-      "version": "7.1.4",
-      "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.4.tgz",
-      "integrity": "sha512-w+LsMxKyYQm347Otw+IfBXOv9UWVjpHpCDdbBMt8Kz/xbvCYNjP+0qPh91Km3iKfSRLBB0P7fAMf0KHrPu+MyA==",
+      "version": "7.2.0",
+      "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz",
+      "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==",
       "dev": true,
       "requires": {
         "@types/minimatch": "*",
@@ -1343,18 +1591,18 @@
       }
     },
     "@types/http-proxy": {
-      "version": "1.17.7",
-      "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.7.tgz",
-      "integrity": "sha512-9hdj6iXH64tHSLTY+Vt2eYOGzSogC+JQ2H7bdPWkuh7KXP5qLllWx++t+K9Wk556c3dkDdPws/SpMRi0sdCT1w==",
+      "version": "1.17.8",
+      "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.8.tgz",
+      "integrity": "sha512-5kPLG5BKpWYkw/LVOGWpiq3nEVqxiN32rTgI53Sk12/xHFQ2rG3ehI9IO+O3W2QoKeyB92dJkoka8SUm6BX1pA==",
       "dev": true,
       "requires": {
         "@types/node": "*"
       }
     },
     "@types/json-schema": {
-      "version": "7.0.8",
-      "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.8.tgz",
-      "integrity": "sha512-YSBPTLTVm2e2OoQIDYx8HaeWJ5tTToLH67kXR7zYNGupXMEHa2++G8k+DczX2cFVgalypqtyZIcU19AFcmOpmg==",
+      "version": "7.0.9",
+      "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz",
+      "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==",
       "dev": true
     },
     "@types/mime": {
@@ -1376,9 +1624,9 @@
       "dev": true
     },
     "@types/node": {
-      "version": "16.0.1",
-      "resolved": "https://registry.npmjs.org/@types/node/-/node-16.0.1.tgz",
-      "integrity": "sha512-hBOx4SUlEPKwRi6PrXuTGw1z6lz0fjsibcWCM378YxsSu/6+C30L6CR49zIBKHiwNWCYIcOLjg4OHKZaFeLAug==",
+      "version": "17.0.8",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.8.tgz",
+      "integrity": "sha512-YofkM6fGv4gDJq78g4j0mMuGMkZVxZDgtU0JRdx6FgiJDG+0fY0GKVolOV8WqVmEhLCXkQRjwDdKyPxJp/uucg==",
       "dev": true
     },
     "@types/normalize-package-data": {
@@ -1445,9 +1693,9 @@
       }
     },
     "@types/webpack": {
-      "version": "4.41.30",
-      "resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.30.tgz",
-      "integrity": "sha512-GUHyY+pfuQ6haAfzu4S14F+R5iGRwN6b2FRNJY7U0NilmFAqbsOfK6j1HwuLBAqwRIT+pVdNDJGJ6e8rpp0KHA==",
+      "version": "4.41.32",
+      "resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.32.tgz",
+      "integrity": "sha512-cb+0ioil/7oz5//7tZUSwbrSAN/NWHrQylz5cW8G0dWTcF/g+/dSdMlKVZspBYuMAN1+WnwHrkxiRrLcwd0Heg==",
       "dev": true,
       "requires": {
         "@types/node": "*",
@@ -1467,9 +1715,9 @@
       }
     },
     "@types/webpack-dev-server": {
-      "version": "3.11.5",
-      "resolved": "https://registry.npmjs.org/@types/webpack-dev-server/-/webpack-dev-server-3.11.5.tgz",
-      "integrity": "sha512-vjsbQBW3fE5FDICkF3w3ZWFRXNwQdKt7JRPLmRy5W0KXlcuew4wgpKWXhgHS71iLNv7Z2PlY9dSSIaYg+bk+9w==",
+      "version": "3.11.6",
+      "resolved": "https://registry.npmjs.org/@types/webpack-dev-server/-/webpack-dev-server-3.11.6.tgz",
+      "integrity": "sha512-XCph0RiiqFGetukCTC3KVnY1jwLcZ84illFRMbyFzCcWl90B/76ew0tSqF46oBhnLC4obNDG7dMO0JfTN0MgMQ==",
       "dev": true,
       "requires": {
         "@types/connect-history-api-fallback": "*",
@@ -1480,9 +1728,9 @@
       }
     },
     "@types/webpack-sources": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-2.1.1.tgz",
-      "integrity": "sha512-MjM1R6iuw8XaVbtkCBz0N349cyqBjJHCbQiOeppe3VBeFvxqs74RKHAVt9LkxTnUWc7YLZOEsUfPUnmK6SBPKQ==",
+      "version": "3.2.0",
+      "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-3.2.0.tgz",
+      "integrity": "sha512-Ft7YH3lEVRQ6ls8k4Ff1oB4jN6oy/XmU6tQISKdhfh+1mR+viZFphS6WL0IrtDOzvefmJg5a0s7ZQoRXwqTEFg==",
       "dev": true,
       "requires": {
         "@types/node": "*",
@@ -1511,9 +1759,9 @@
       "dev": true
     },
     "@vue/babel-plugin-jsx": {
-      "version": "1.0.6",
-      "resolved": "https://registry.npmjs.org/@vue/babel-plugin-jsx/-/babel-plugin-jsx-1.0.6.tgz",
-      "integrity": "sha512-RzYsvBhzKUmY2YG6LoV+W5PnlnkInq0thh1AzCmewwctAgGN6e9UFon6ZrQQV1CO5G5PeME7MqpB+/vvGg0h4g==",
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/@vue/babel-plugin-jsx/-/babel-plugin-jsx-1.1.1.tgz",
+      "integrity": "sha512-j2uVfZjnB5+zkcbc/zsOc0fSNGCMMjaEXP52wdwdIfn0qjFfEYpYZBFKFg+HHnQeJCVrjOeO0YxgaL7DMrym9w==",
       "dev": true,
       "requires": {
         "@babel/helper-module-imports": "^7.0.0",
@@ -1550,9 +1798,9 @@
       }
     },
     "@vue/babel-preset-app": {
-      "version": "4.5.13",
-      "resolved": "https://registry.npmjs.org/@vue/babel-preset-app/-/babel-preset-app-4.5.13.tgz",
-      "integrity": "sha512-pM7CR3yXB6L8Gfn6EmX7FLNE3+V/15I3o33GkSNsWvgsMp6HVGXKkXgojrcfUUauyL1LZOdvTmu4enU2RePGHw==",
+      "version": "4.5.15",
+      "resolved": "https://registry.npmjs.org/@vue/babel-preset-app/-/babel-preset-app-4.5.15.tgz",
+      "integrity": "sha512-J+YttzvwRfV1BPczf8r3qCevznYk+jh531agVF+5EYlHF4Sgh/cGXTz9qkkiux3LQgvhEGXgmCteg1n38WuuKg==",
       "dev": true,
       "requires": {
         "@babel/core": "^7.11.0",
@@ -1673,20 +1921,20 @@
       }
     },
     "@vue/cli-overlay": {
-      "version": "4.5.13",
-      "resolved": "https://registry.npmjs.org/@vue/cli-overlay/-/cli-overlay-4.5.13.tgz",
-      "integrity": "sha512-jhUIg3klgi5Cxhs8dnat5hi/W2tQJvsqCxR0u6hgfSob0ORODgUBlN+F/uwq7cKIe/pzedVUk1y07F13GQvPqg==",
+      "version": "4.5.15",
+      "resolved": "https://registry.npmjs.org/@vue/cli-overlay/-/cli-overlay-4.5.15.tgz",
+      "integrity": "sha512-0zI0kANAVmjFO2LWGUIzdGPMeE3+9k+KeRDXsUqB30YfRF7abjfiiRPq5BU9pOzlJbVdpRkisschBrvdJqDuDg==",
       "dev": true
     },
     "@vue/cli-plugin-babel": {
-      "version": "4.5.13",
-      "resolved": "https://registry.npmjs.org/@vue/cli-plugin-babel/-/cli-plugin-babel-4.5.13.tgz",
-      "integrity": "sha512-ykvEAfD8PgGs+dGMGqr7l/nRmIS39NRzWLhMluPLTvDV1L+IxcoB73HNLGA/aENDpl8CuWrTE+1VgydcOhp+wg==",
+      "version": "4.5.15",
+      "resolved": "https://registry.npmjs.org/@vue/cli-plugin-babel/-/cli-plugin-babel-4.5.15.tgz",
+      "integrity": "sha512-hBLrwYfFkHldEe34op/YNgPhpOWI5n5DB2Qt9I/1Epeif4M4iFaayrgjvOR9AVM6WbD3Yx7WCFszYpWrQZpBzQ==",
       "dev": true,
       "requires": {
         "@babel/core": "^7.11.0",
-        "@vue/babel-preset-app": "^4.5.13",
-        "@vue/cli-shared-utils": "^4.5.13",
+        "@vue/babel-preset-app": "^4.5.15",
+        "@vue/cli-shared-utils": "^4.5.15",
         "babel-loader": "^8.1.0",
         "cache-loader": "^4.1.0",
         "thread-loader": "^2.1.3",
@@ -1694,259 +1942,858 @@
       }
     },
     "@vue/cli-plugin-eslint": {
-      "version": "4.5.13",
-      "resolved": "https://registry.npmjs.org/@vue/cli-plugin-eslint/-/cli-plugin-eslint-4.5.13.tgz",
-      "integrity": "sha512-yc2uXX6aBiy3vEf5TwaueaDqQbdIXIhk0x0KzEtpPo23jBdLkpOSoU5NCgE06g/ZiGAcettpmBSv73Hfp4wHEw==",
+      "version": "5.0.0-rc.1",
+      "resolved": "https://registry.npmjs.org/@vue/cli-plugin-eslint/-/cli-plugin-eslint-5.0.0-rc.1.tgz",
+      "integrity": "sha512-CK/T00XeibQCMHzSenBWDROB11HbCL69bEc1nwT8gjXq5MMw9AB8qlaZzSuoHbbUE0PDyD272V/RDePO1ExT7w==",
       "dev": true,
       "requires": {
-        "@vue/cli-shared-utils": "^4.5.13",
-        "eslint-loader": "^2.2.1",
-        "globby": "^9.2.0",
-        "inquirer": "^7.1.0",
-        "webpack": "^4.0.0",
+        "@vue/cli-shared-utils": "^5.0.0-rc.1",
+        "eslint-webpack-plugin": "^3.1.0",
+        "globby": "^11.0.2",
+        "webpack": "^5.54.0",
         "yorkie": "^2.0.0"
-      }
-    },
-    "@vue/cli-plugin-pwa": {
-      "version": "4.5.13",
-      "resolved": "https://registry.npmjs.org/@vue/cli-plugin-pwa/-/cli-plugin-pwa-4.5.13.tgz",
-      "integrity": "sha512-uU5pp94VU0YscfKq/mNRsKOdxG+CTqVlZWaYkRc+HCcwkJ/m/CnxgaEqQFr0QpHC8zmlX4gILO1RVYygJoR9tw==",
-      "dev": true,
-      "requires": {
-        "@vue/cli-shared-utils": "^4.5.13",
-        "webpack": "^4.0.0",
-        "workbox-webpack-plugin": "^4.3.1"
-      }
-    },
-    "@vue/cli-plugin-router": {
-      "version": "4.5.13",
-      "resolved": "https://registry.npmjs.org/@vue/cli-plugin-router/-/cli-plugin-router-4.5.13.tgz",
-      "integrity": "sha512-tgtMDjchB/M1z8BcfV4jSOY9fZSMDTPgF9lsJIiqBWMxvBIsk9uIZHxp62DibYME4CCKb/nNK61XHaikFp+83w==",
-      "dev": true,
-      "requires": {
-        "@vue/cli-shared-utils": "^4.5.13"
-      }
-    },
-    "@vue/cli-plugin-vuex": {
-      "version": "4.5.13",
-      "resolved": "https://registry.npmjs.org/@vue/cli-plugin-vuex/-/cli-plugin-vuex-4.5.13.tgz",
-      "integrity": "sha512-I1S9wZC7iI0Wn8kw8Zh+A2Qkf6s1M6vTGBkx8boXjuzfwEEyEHRxadsVCecZc8Mkpydo0nykj+MyYF96TKFuVA==",
-      "dev": true
-    },
-    "@vue/cli-service": {
-      "version": "4.5.13",
-      "resolved": "https://registry.npmjs.org/@vue/cli-service/-/cli-service-4.5.13.tgz",
-      "integrity": "sha512-CKAZN4iokMMsaUyJRU22oUAz3oS/X9sVBSKAF2/shFBV5xh3jqAlKl8OXZYz4cXGFLA6djNuYrniuLAo7Ku97A==",
-      "dev": true,
-      "requires": {
-        "@intervolga/optimize-cssnano-plugin": "^1.0.5",
-        "@soda/friendly-errors-webpack-plugin": "^1.7.1",
-        "@soda/get-current-script": "^1.0.0",
-        "@types/minimist": "^1.2.0",
-        "@types/webpack": "^4.0.0",
-        "@types/webpack-dev-server": "^3.11.0",
-        "@vue/cli-overlay": "^4.5.13",
-        "@vue/cli-plugin-router": "^4.5.13",
-        "@vue/cli-plugin-vuex": "^4.5.13",
-        "@vue/cli-shared-utils": "^4.5.13",
-        "@vue/component-compiler-utils": "^3.1.2",
-        "@vue/preload-webpack-plugin": "^1.1.0",
-        "@vue/web-component-wrapper": "^1.2.0",
-        "acorn": "^7.4.0",
-        "acorn-walk": "^7.1.1",
-        "address": "^1.1.2",
-        "autoprefixer": "^9.8.6",
-        "browserslist": "^4.12.0",
-        "cache-loader": "^4.1.0",
-        "case-sensitive-paths-webpack-plugin": "^2.3.0",
-        "cli-highlight": "^2.1.4",
-        "clipboardy": "^2.3.0",
-        "cliui": "^6.0.0",
-        "copy-webpack-plugin": "^5.1.1",
-        "css-loader": "^3.5.3",
-        "cssnano": "^4.1.10",
-        "debug": "^4.1.1",
-        "default-gateway": "^5.0.5",
-        "dotenv": "^8.2.0",
-        "dotenv-expand": "^5.1.0",
-        "file-loader": "^4.2.0",
-        "fs-extra": "^7.0.1",
-        "globby": "^9.2.0",
-        "hash-sum": "^2.0.0",
-        "html-webpack-plugin": "^3.2.0",
-        "launch-editor-middleware": "^2.2.1",
-        "lodash.defaultsdeep": "^4.6.1",
-        "lodash.mapvalues": "^4.6.0",
-        "lodash.transform": "^4.6.0",
-        "mini-css-extract-plugin": "^0.9.0",
-        "minimist": "^1.2.5",
-        "pnp-webpack-plugin": "^1.6.4",
-        "portfinder": "^1.0.26",
-        "postcss-loader": "^3.0.0",
-        "ssri": "^8.0.1",
-        "terser-webpack-plugin": "^1.4.4",
-        "thread-loader": "^2.1.3",
-        "url-loader": "^2.2.0",
-        "vue-loader": "^15.9.2",
-        "vue-loader-v16": "npm:vue-loader@^16.1.0",
-        "vue-style-loader": "^4.1.2",
-        "webpack": "^4.0.0",
-        "webpack-bundle-analyzer": "^3.8.0",
-        "webpack-chain": "^6.4.0",
-        "webpack-dev-server": "^3.11.0",
-        "webpack-merge": "^4.2.2"
-      }
-    },
-    "@vue/cli-shared-utils": {
-      "version": "4.5.13",
-      "resolved": "https://registry.npmjs.org/@vue/cli-shared-utils/-/cli-shared-utils-4.5.13.tgz",
-      "integrity": "sha512-HpnOrkLg42RFUsQGMJv26oTG3J3FmKtO2WSRhKIIL+1ok3w9OjGCtA3nMMXN27f9eX14TqO64M36DaiSZ1fSiw==",
-      "dev": true,
-      "requires": {
-        "@hapi/joi": "^15.0.1",
-        "chalk": "^2.4.2",
-        "execa": "^1.0.0",
-        "launch-editor": "^2.2.1",
-        "lru-cache": "^5.1.1",
-        "node-ipc": "^9.1.1",
-        "open": "^6.3.0",
-        "ora": "^3.4.0",
-        "read-pkg": "^5.1.1",
-        "request": "^2.88.2",
-        "semver": "^6.1.0",
-        "strip-ansi": "^6.0.0"
       },
       "dependencies": {
-        "ansi-regex": {
-          "version": "5.0.0",
-          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
-          "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
+        "@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
         },
-        "strip-ansi": {
-          "version": "6.0.0",
-          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
-          "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
+        "@vue/cli-shared-utils": {
+          "version": "5.0.0-rc.1",
+          "resolved": "https://registry.npmjs.org/@vue/cli-shared-utils/-/cli-shared-utils-5.0.0-rc.1.tgz",
+          "integrity": "sha512-rZVTGfSQ0Sqw76BD/Z6iARfnO2r5ICSxt0iIpzjM8w9ohpRtI2B45NrngF0rILwy9d8we4A/n7gQQ0rqwkAX7g==",
           "dev": true,
           "requires": {
-            "ansi-regex": "^5.0.0"
+            "chalk": "^4.1.2",
+            "execa": "^1.0.0",
+            "joi": "^17.4.0",
+            "launch-editor": "^2.2.1",
+            "lru-cache": "^6.0.0",
+            "node-fetch": "^2.6.1",
+            "node-ipc": "^9.1.1",
+            "open": "^8.0.2",
+            "ora": "^5.3.0",
+            "read-pkg": "^5.1.1",
+            "semver": "^7.3.4",
+            "strip-ansi": "^6.0.0"
           }
-        }
-      }
-    },
-    "@vue/component-compiler-utils": {
-      "version": "3.2.2",
-      "resolved": "https://registry.npmjs.org/@vue/component-compiler-utils/-/component-compiler-utils-3.2.2.tgz",
-      "integrity": "sha512-rAYMLmgMuqJFWAOb3Awjqqv5X3Q3hVr4jH/kgrFJpiU0j3a90tnNBplqbj+snzrgZhC9W128z+dtgMifOiMfJg==",
-      "dev": true,
-      "requires": {
-        "consolidate": "^0.15.1",
-        "hash-sum": "^1.0.2",
-        "lru-cache": "^4.1.2",
-        "merge-source-map": "^1.1.0",
-        "postcss": "^7.0.36",
-        "postcss-selector-parser": "^6.0.2",
-        "prettier": "^1.18.2",
-        "source-map": "~0.6.1",
-        "vue-template-es2015-compiler": "^1.9.0"
-      },
-      "dependencies": {
-        "hash-sum": {
-          "version": "1.0.2",
-          "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-1.0.2.tgz",
-          "integrity": "sha1-M7QHd3VMZDJXPBIMw4CLvRDUfwQ=",
+        },
+        "@webassemblyjs/ast": {
+          "version": "1.11.1",
+          "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz",
+          "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==",
+          "dev": true,
+          "requires": {
+            "@webassemblyjs/helper-numbers": "1.11.1",
+            "@webassemblyjs/helper-wasm-bytecode": "1.11.1"
+          }
+        },
+        "@webassemblyjs/helper-api-error": {
+          "version": "1.11.1",
+          "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz",
+          "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==",
           "dev": true
         },
-        "lru-cache": {
-          "version": "4.1.5",
-          "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
-          "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
+        "@webassemblyjs/helper-buffer": {
+          "version": "1.11.1",
+          "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz",
+          "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==",
+          "dev": true
+        },
+        "@webassemblyjs/helper-wasm-bytecode": {
+          "version": "1.11.1",
+          "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz",
+          "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==",
+          "dev": true
+        },
+        "@webassemblyjs/helper-wasm-section": {
+          "version": "1.11.1",
+          "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz",
+          "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==",
           "dev": true,
           "requires": {
-            "pseudomap": "^1.0.2",
-            "yallist": "^2.1.2"
+            "@webassemblyjs/ast": "1.11.1",
+            "@webassemblyjs/helper-buffer": "1.11.1",
+            "@webassemblyjs/helper-wasm-bytecode": "1.11.1",
+            "@webassemblyjs/wasm-gen": "1.11.1"
           }
         },
-        "source-map": {
-          "version": "0.6.1",
-          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
-          "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+        "@webassemblyjs/ieee754": {
+          "version": "1.11.1",
+          "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz",
+          "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==",
+          "dev": true,
+          "requires": {
+            "@xtuc/ieee754": "^1.2.0"
+          }
+        },
+        "@webassemblyjs/leb128": {
+          "version": "1.11.1",
+          "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz",
+          "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==",
+          "dev": true,
+          "requires": {
+            "@xtuc/long": "4.2.2"
+          }
+        },
+        "@webassemblyjs/utf8": {
+          "version": "1.11.1",
+          "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz",
+          "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==",
           "dev": true
         },
-        "yallist": {
-          "version": "2.1.2",
-          "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
-          "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=",
+        "@webassemblyjs/wasm-edit": {
+          "version": "1.11.1",
+          "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz",
+          "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==",
+          "dev": true,
+          "requires": {
+            "@webassemblyjs/ast": "1.11.1",
+            "@webassemblyjs/helper-buffer": "1.11.1",
+            "@webassemblyjs/helper-wasm-bytecode": "1.11.1",
+            "@webassemblyjs/helper-wasm-section": "1.11.1",
+            "@webassemblyjs/wasm-gen": "1.11.1",
+            "@webassemblyjs/wasm-opt": "1.11.1",
+            "@webassemblyjs/wasm-parser": "1.11.1",
+            "@webassemblyjs/wast-printer": "1.11.1"
+          }
+        },
+        "@webassemblyjs/wasm-gen": {
+          "version": "1.11.1",
+          "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz",
+          "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==",
+          "dev": true,
+          "requires": {
+            "@webassemblyjs/ast": "1.11.1",
+            "@webassemblyjs/helper-wasm-bytecode": "1.11.1",
+            "@webassemblyjs/ieee754": "1.11.1",
+            "@webassemblyjs/leb128": "1.11.1",
+            "@webassemblyjs/utf8": "1.11.1"
+          }
+        },
+        "@webassemblyjs/wasm-opt": {
+          "version": "1.11.1",
+          "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz",
+          "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==",
+          "dev": true,
+          "requires": {
+            "@webassemblyjs/ast": "1.11.1",
+            "@webassemblyjs/helper-buffer": "1.11.1",
+            "@webassemblyjs/wasm-gen": "1.11.1",
+            "@webassemblyjs/wasm-parser": "1.11.1"
+          }
+        },
+        "@webassemblyjs/wasm-parser": {
+          "version": "1.11.1",
+          "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz",
+          "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==",
+          "dev": true,
+          "requires": {
+            "@webassemblyjs/ast": "1.11.1",
+            "@webassemblyjs/helper-api-error": "1.11.1",
+            "@webassemblyjs/helper-wasm-bytecode": "1.11.1",
+            "@webassemblyjs/ieee754": "1.11.1",
+            "@webassemblyjs/leb128": "1.11.1",
+            "@webassemblyjs/utf8": "1.11.1"
+          }
+        },
+        "@webassemblyjs/wast-printer": {
+          "version": "1.11.1",
+          "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz",
+          "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==",
+          "dev": true,
+          "requires": {
+            "@webassemblyjs/ast": "1.11.1",
+            "@xtuc/long": "4.2.2"
+          }
+        },
+        "acorn": {
+          "version": "8.7.0",
+          "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz",
+          "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==",
           "dev": true
-        }
-      }
-    },
-    "@vue/preload-webpack-plugin": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/@vue/preload-webpack-plugin/-/preload-webpack-plugin-1.1.2.tgz",
-      "integrity": "sha512-LIZMuJk38pk9U9Ur4YzHjlIyMuxPlACdBIHH9/nGYVTsaGKOSnSuELiE8vS9wa+dJpIYspYUOqk+L1Q4pgHQHQ==",
-      "dev": true
-    },
-    "@vue/web-component-wrapper": {
-      "version": "1.3.0",
-      "resolved": "https://registry.npmjs.org/@vue/web-component-wrapper/-/web-component-wrapper-1.3.0.tgz",
-      "integrity": "sha512-Iu8Tbg3f+emIIMmI2ycSI8QcEuAUgPTgHwesDU1eKMLE4YC/c/sFbGc70QgMq31ijRftV0R7vCm9co6rldCeOA==",
-      "dev": true
-    },
-    "@webassemblyjs/ast": {
-      "version": "1.9.0",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz",
-      "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==",
-      "dev": true,
-      "requires": {
-        "@webassemblyjs/helper-module-context": "1.9.0",
-        "@webassemblyjs/helper-wasm-bytecode": "1.9.0",
-        "@webassemblyjs/wast-parser": "1.9.0"
-      }
-    },
-    "@webassemblyjs/floating-point-hex-parser": {
-      "version": "1.9.0",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz",
-      "integrity": "sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA==",
-      "dev": true
-    },
-    "@webassemblyjs/helper-api-error": {
-      "version": "1.9.0",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz",
-      "integrity": "sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw==",
-      "dev": true
-    },
-    "@webassemblyjs/helper-buffer": {
-      "version": "1.9.0",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz",
-      "integrity": "sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA==",
-      "dev": true
-    },
-    "@webassemblyjs/helper-code-frame": {
-      "version": "1.9.0",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz",
-      "integrity": "sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA==",
-      "dev": true,
-      "requires": {
-        "@webassemblyjs/wast-printer": "1.9.0"
-      }
-    },
-    "@webassemblyjs/helper-fsm": {
-      "version": "1.9.0",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz",
-      "integrity": "sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw==",
-      "dev": true
-    },
-    "@webassemblyjs/helper-module-context": {
-      "version": "1.9.0",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz",
-      "integrity": "sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g==",
-      "dev": true,
-      "requires": {
-        "@webassemblyjs/ast": "1.9.0"
-      }
-    },
-    "@webassemblyjs/helper-wasm-bytecode": {
+        },
+        "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"
+          }
+        },
+        "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
+        },
+        "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"
+          }
+        },
+        "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"
+          }
+        },
+        "cli-cursor": {
+          "version": "3.1.0",
+          "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
+          "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==",
+          "dev": true,
+          "requires": {
+            "restore-cursor": "^3.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
+        },
+        "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"
+          }
+        },
+        "enhanced-resolve": {
+          "version": "5.8.3",
+          "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.8.3.tgz",
+          "integrity": "sha512-EGAbGvH7j7Xt2nc0E7D99La1OiEs8LnyimkRgwExpUMScN6O+3x9tIWs7PLQZVNx4YD+00skHXPXi1yQHpAmZA==",
+          "dev": true,
+          "requires": {
+            "graceful-fs": "^4.2.4",
+            "tapable": "^2.2.0"
+          }
+        },
+        "eslint-scope": {
+          "version": "5.1.1",
+          "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
+          "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
+          "dev": true,
+          "requires": {
+            "esrecurse": "^4.3.0",
+            "estraverse": "^4.1.1"
+          }
+        },
+        "fast-glob": {
+          "version": "3.2.7",
+          "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz",
+          "integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==",
+          "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"
+          }
+        },
+        "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"
+          }
+        },
+        "glob-to-regexp": {
+          "version": "0.4.1",
+          "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz",
+          "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==",
+          "dev": true
+        },
+        "globby": {
+          "version": "11.0.4",
+          "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz",
+          "integrity": "sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==",
+          "dev": true,
+          "requires": {
+            "array-union": "^2.1.0",
+            "dir-glob": "^3.0.1",
+            "fast-glob": "^3.1.1",
+            "ignore": "^5.1.4",
+            "merge2": "^1.3.0",
+            "slash": "^3.0.0"
+          }
+        },
+        "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
+        },
+        "ignore": {
+          "version": "5.2.0",
+          "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz",
+          "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==",
+          "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-wsl": {
+          "version": "2.2.0",
+          "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
+          "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==",
+          "dev": true,
+          "requires": {
+            "is-docker": "^2.0.0"
+          }
+        },
+        "loader-runner": {
+          "version": "4.2.0",
+          "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.2.0.tgz",
+          "integrity": "sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw==",
+          "dev": true
+        },
+        "log-symbols": {
+          "version": "4.1.0",
+          "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
+          "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==",
+          "dev": true,
+          "requires": {
+            "chalk": "^4.1.0",
+            "is-unicode-supported": "^0.1.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"
+          }
+        },
+        "micromatch": {
+          "version": "4.0.4",
+          "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz",
+          "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==",
+          "dev": true,
+          "requires": {
+            "braces": "^3.0.1",
+            "picomatch": "^2.2.3"
+          }
+        },
+        "mimic-fn": {
+          "version": "2.1.0",
+          "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
+          "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
+          "dev": true
+        },
+        "onetime": {
+          "version": "5.1.2",
+          "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
+          "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
+          "dev": true,
+          "requires": {
+            "mimic-fn": "^2.1.0"
+          }
+        },
+        "open": {
+          "version": "8.4.0",
+          "resolved": "https://registry.npmjs.org/open/-/open-8.4.0.tgz",
+          "integrity": "sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q==",
+          "dev": true,
+          "requires": {
+            "define-lazy-prop": "^2.0.0",
+            "is-docker": "^2.1.1",
+            "is-wsl": "^2.2.0"
+          }
+        },
+        "ora": {
+          "version": "5.4.1",
+          "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz",
+          "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==",
+          "dev": true,
+          "requires": {
+            "bl": "^4.1.0",
+            "chalk": "^4.1.0",
+            "cli-cursor": "^3.1.0",
+            "cli-spinners": "^2.5.0",
+            "is-interactive": "^1.0.0",
+            "is-unicode-supported": "^0.1.0",
+            "log-symbols": "^4.1.0",
+            "strip-ansi": "^6.0.0",
+            "wcwidth": "^1.0.1"
+          }
+        },
+        "path-type": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
+          "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
+          "dev": true
+        },
+        "restore-cursor": {
+          "version": "3.1.0",
+          "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz",
+          "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==",
+          "dev": true,
+          "requires": {
+            "onetime": "^5.1.0",
+            "signal-exit": "^3.0.2"
+          }
+        },
+        "schema-utils": {
+          "version": "3.1.1",
+          "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz",
+          "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==",
+          "dev": true,
+          "requires": {
+            "@types/json-schema": "^7.0.8",
+            "ajv": "^6.12.5",
+            "ajv-keywords": "^3.5.2"
+          }
+        },
+        "semver": {
+          "version": "7.3.5",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
+          "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
+          "dev": true,
+          "requires": {
+            "lru-cache": "^6.0.0"
+          }
+        },
+        "serialize-javascript": {
+          "version": "6.0.0",
+          "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz",
+          "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==",
+          "dev": true,
+          "requires": {
+            "randombytes": "^2.1.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.6.1",
+          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+          "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+          "dev": true
+        },
+        "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"
+          }
+        },
+        "tapable": {
+          "version": "2.2.1",
+          "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz",
+          "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==",
+          "dev": true
+        },
+        "terser": {
+          "version": "5.10.0",
+          "resolved": "https://registry.npmjs.org/terser/-/terser-5.10.0.tgz",
+          "integrity": "sha512-AMmF99DMfEDiRJfxfY5jj5wNH/bYO09cniSqhfoyxc8sFoYIgkJy86G04UoZU5VjlpnplVu0K6Tx6E9b5+DlHA==",
+          "dev": true,
+          "requires": {
+            "commander": "^2.20.0",
+            "source-map": "~0.7.2",
+            "source-map-support": "~0.5.20"
+          },
+          "dependencies": {
+            "source-map": {
+              "version": "0.7.3",
+              "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz",
+              "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==",
+              "dev": true
+            }
+          }
+        },
+        "terser-webpack-plugin": {
+          "version": "5.3.0",
+          "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.0.tgz",
+          "integrity": "sha512-LPIisi3Ol4chwAaPP8toUJ3L4qCM1G0wao7L3qNv57Drezxj6+VEyySpPw4B1HSO2Eg/hDY/MNF5XihCAoqnsQ==",
+          "dev": true,
+          "requires": {
+            "jest-worker": "^27.4.1",
+            "schema-utils": "^3.1.1",
+            "serialize-javascript": "^6.0.0",
+            "source-map": "^0.6.1",
+            "terser": "^5.7.2"
+          }
+        },
+        "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"
+          }
+        },
+        "watchpack": {
+          "version": "2.3.1",
+          "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.3.1.tgz",
+          "integrity": "sha512-x0t0JuydIo8qCNctdDrn1OzH/qDzk2+rdCOC3YzumZ42fiMqmQ7T3xQurykYMhYfHaPHTp4ZxAx2NfUo1K6QaA==",
+          "dev": true,
+          "requires": {
+            "glob-to-regexp": "^0.4.1",
+            "graceful-fs": "^4.1.2"
+          }
+        },
+        "webpack": {
+          "version": "5.65.0",
+          "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.65.0.tgz",
+          "integrity": "sha512-Q5or2o6EKs7+oKmJo7LaqZaMOlDWQse9Tm5l1WAfU/ujLGN5Pb0SqGeVkN/4bpPmEqEP5RnVhiqsOtWtUVwGRw==",
+          "dev": true,
+          "requires": {
+            "@types/eslint-scope": "^3.7.0",
+            "@types/estree": "^0.0.50",
+            "@webassemblyjs/ast": "1.11.1",
+            "@webassemblyjs/wasm-edit": "1.11.1",
+            "@webassemblyjs/wasm-parser": "1.11.1",
+            "acorn": "^8.4.1",
+            "acorn-import-assertions": "^1.7.6",
+            "browserslist": "^4.14.5",
+            "chrome-trace-event": "^1.0.2",
+            "enhanced-resolve": "^5.8.3",
+            "es-module-lexer": "^0.9.0",
+            "eslint-scope": "5.1.1",
+            "events": "^3.2.0",
+            "glob-to-regexp": "^0.4.1",
+            "graceful-fs": "^4.2.4",
+            "json-parse-better-errors": "^1.0.2",
+            "loader-runner": "^4.2.0",
+            "mime-types": "^2.1.27",
+            "neo-async": "^2.6.2",
+            "schema-utils": "^3.1.0",
+            "tapable": "^2.1.1",
+            "terser-webpack-plugin": "^5.1.3",
+            "watchpack": "^2.3.1",
+            "webpack-sources": "^3.2.2"
+          }
+        },
+        "webpack-sources": {
+          "version": "3.2.2",
+          "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.2.tgz",
+          "integrity": "sha512-cp5qdmHnu5T8wRg2G3vZZHoJPN14aqQ89SyQ11NpGH5zEMDCclt49rzo+MaRazk7/UeILhAI+/sEtcM+7Fr0nw==",
+          "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
+        }
+      }
+    },
+    "@vue/cli-plugin-pwa": {
+      "version": "4.5.15",
+      "resolved": "https://registry.npmjs.org/@vue/cli-plugin-pwa/-/cli-plugin-pwa-4.5.15.tgz",
+      "integrity": "sha512-yQzsspaIkjeQyN6btF8ATgbJFU023q1HC8uUpmiBa4QE9EyBlR8fSrKFhcJ0EmT6KnU7PMwlnOJ/OqjguFnufA==",
+      "dev": true,
+      "requires": {
+        "@vue/cli-shared-utils": "^4.5.15",
+        "webpack": "^4.0.0",
+        "workbox-webpack-plugin": "^4.3.1"
+      }
+    },
+    "@vue/cli-plugin-router": {
+      "version": "4.5.15",
+      "resolved": "https://registry.npmjs.org/@vue/cli-plugin-router/-/cli-plugin-router-4.5.15.tgz",
+      "integrity": "sha512-q7Y6kP9b3k55Ca2j59xJ7XPA6x+iSRB+N4ac0ZbcL1TbInVQ4j5wCzyE+uqid40hLy4fUdlpl4X9fHJEwuVxPA==",
+      "dev": true,
+      "requires": {
+        "@vue/cli-shared-utils": "^4.5.15"
+      }
+    },
+    "@vue/cli-plugin-vuex": {
+      "version": "4.5.15",
+      "resolved": "https://registry.npmjs.org/@vue/cli-plugin-vuex/-/cli-plugin-vuex-4.5.15.tgz",
+      "integrity": "sha512-fqap+4HN+w+InDxlA3hZTOGE0tzBTgXhKLoDydhywqgmhQ1D9JA6Feh94ze6tG8DsWX58/ujYUqA8jAz17FJtg==",
+      "dev": true
+    },
+    "@vue/cli-service": {
+      "version": "4.5.15",
+      "resolved": "https://registry.npmjs.org/@vue/cli-service/-/cli-service-4.5.15.tgz",
+      "integrity": "sha512-sFWnLYVCn4zRfu45IcsIE9eXM0YpDV3S11vlM2/DVbIPAGoYo5ySpSof6aHcIvkeGsIsrHFpPHzNvDZ/efs7jA==",
+      "dev": true,
+      "requires": {
+        "@intervolga/optimize-cssnano-plugin": "^1.0.5",
+        "@soda/friendly-errors-webpack-plugin": "^1.7.1",
+        "@soda/get-current-script": "^1.0.0",
+        "@types/minimist": "^1.2.0",
+        "@types/webpack": "^4.0.0",
+        "@types/webpack-dev-server": "^3.11.0",
+        "@vue/cli-overlay": "^4.5.15",
+        "@vue/cli-plugin-router": "^4.5.15",
+        "@vue/cli-plugin-vuex": "^4.5.15",
+        "@vue/cli-shared-utils": "^4.5.15",
+        "@vue/component-compiler-utils": "^3.1.2",
+        "@vue/preload-webpack-plugin": "^1.1.0",
+        "@vue/web-component-wrapper": "^1.2.0",
+        "acorn": "^7.4.0",
+        "acorn-walk": "^7.1.1",
+        "address": "^1.1.2",
+        "autoprefixer": "^9.8.6",
+        "browserslist": "^4.12.0",
+        "cache-loader": "^4.1.0",
+        "case-sensitive-paths-webpack-plugin": "^2.3.0",
+        "cli-highlight": "^2.1.4",
+        "clipboardy": "^2.3.0",
+        "cliui": "^6.0.0",
+        "copy-webpack-plugin": "^5.1.1",
+        "css-loader": "^3.5.3",
+        "cssnano": "^4.1.10",
+        "debug": "^4.1.1",
+        "default-gateway": "^5.0.5",
+        "dotenv": "^8.2.0",
+        "dotenv-expand": "^5.1.0",
+        "file-loader": "^4.2.0",
+        "fs-extra": "^7.0.1",
+        "globby": "^9.2.0",
+        "hash-sum": "^2.0.0",
+        "html-webpack-plugin": "^3.2.0",
+        "launch-editor-middleware": "^2.2.1",
+        "lodash.defaultsdeep": "^4.6.1",
+        "lodash.mapvalues": "^4.6.0",
+        "lodash.transform": "^4.6.0",
+        "mini-css-extract-plugin": "^0.9.0",
+        "minimist": "^1.2.5",
+        "pnp-webpack-plugin": "^1.6.4",
+        "portfinder": "^1.0.26",
+        "postcss-loader": "^3.0.0",
+        "ssri": "^8.0.1",
+        "terser-webpack-plugin": "^1.4.4",
+        "thread-loader": "^2.1.3",
+        "url-loader": "^2.2.0",
+        "vue-loader": "^15.9.2",
+        "vue-loader-v16": "npm:vue-loader@^16.1.0",
+        "vue-style-loader": "^4.1.2",
+        "webpack": "^4.0.0",
+        "webpack-bundle-analyzer": "^3.8.0",
+        "webpack-chain": "^6.4.0",
+        "webpack-dev-server": "^3.11.0",
+        "webpack-merge": "^4.2.2"
+      },
+      "dependencies": {
+        "acorn": {
+          "version": "7.4.1",
+          "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz",
+          "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==",
+          "dev": true
+        },
+        "fs-extra": {
+          "version": "7.0.1",
+          "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz",
+          "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==",
+          "dev": true,
+          "requires": {
+            "graceful-fs": "^4.1.2",
+            "jsonfile": "^4.0.0",
+            "universalify": "^0.1.0"
+          }
+        },
+        "ssri": {
+          "version": "8.0.1",
+          "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz",
+          "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==",
+          "dev": true,
+          "requires": {
+            "minipass": "^3.1.1"
+          }
+        }
+      }
+    },
+    "@vue/cli-shared-utils": {
+      "version": "4.5.15",
+      "resolved": "https://registry.npmjs.org/@vue/cli-shared-utils/-/cli-shared-utils-4.5.15.tgz",
+      "integrity": "sha512-SKaej9hHzzjKSOw1NlFmc6BSE0vcqUQMQiv1cxQ2DhVyy4QxZXBmzmiLBUBe+hYZZs1neXW7n//udeN9bCAY+Q==",
+      "dev": true,
+      "requires": {
+        "@hapi/joi": "^15.0.1",
+        "chalk": "^2.4.2",
+        "execa": "^1.0.0",
+        "launch-editor": "^2.2.1",
+        "lru-cache": "^5.1.1",
+        "node-ipc": "^9.1.1",
+        "open": "^6.3.0",
+        "ora": "^3.4.0",
+        "read-pkg": "^5.1.1",
+        "request": "^2.88.2",
+        "semver": "^6.1.0",
+        "strip-ansi": "^6.0.0"
+      }
+    },
+    "@vue/component-compiler-utils": {
+      "version": "3.3.0",
+      "resolved": "https://registry.npmjs.org/@vue/component-compiler-utils/-/component-compiler-utils-3.3.0.tgz",
+      "integrity": "sha512-97sfH2mYNU+2PzGrmK2haqffDpVASuib9/w2/noxiFi31Z54hW+q3izKQXXQZSNhtiUpAI36uSuYepeBe4wpHQ==",
+      "dev": true,
+      "requires": {
+        "consolidate": "^0.15.1",
+        "hash-sum": "^1.0.2",
+        "lru-cache": "^4.1.2",
+        "merge-source-map": "^1.1.0",
+        "postcss": "^7.0.36",
+        "postcss-selector-parser": "^6.0.2",
+        "prettier": "^1.18.2 || ^2.0.0",
+        "source-map": "~0.6.1",
+        "vue-template-es2015-compiler": "^1.9.0"
+      },
+      "dependencies": {
+        "hash-sum": {
+          "version": "1.0.2",
+          "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-1.0.2.tgz",
+          "integrity": "sha1-M7QHd3VMZDJXPBIMw4CLvRDUfwQ=",
+          "dev": true
+        },
+        "lru-cache": {
+          "version": "4.1.5",
+          "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
+          "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
+          "dev": true,
+          "requires": {
+            "pseudomap": "^1.0.2",
+            "yallist": "^2.1.2"
+          }
+        },
+        "source-map": {
+          "version": "0.6.1",
+          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+          "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+          "dev": true
+        },
+        "yallist": {
+          "version": "2.1.2",
+          "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
+          "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=",
+          "dev": true
+        }
+      }
+    },
+    "@vue/preload-webpack-plugin": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/@vue/preload-webpack-plugin/-/preload-webpack-plugin-1.1.2.tgz",
+      "integrity": "sha512-LIZMuJk38pk9U9Ur4YzHjlIyMuxPlACdBIHH9/nGYVTsaGKOSnSuELiE8vS9wa+dJpIYspYUOqk+L1Q4pgHQHQ==",
+      "dev": true
+    },
+    "@vue/web-component-wrapper": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/@vue/web-component-wrapper/-/web-component-wrapper-1.3.0.tgz",
+      "integrity": "sha512-Iu8Tbg3f+emIIMmI2ycSI8QcEuAUgPTgHwesDU1eKMLE4YC/c/sFbGc70QgMq31ijRftV0R7vCm9co6rldCeOA==",
+      "dev": true
+    },
+    "@webassemblyjs/ast": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz",
+      "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==",
+      "dev": true,
+      "requires": {
+        "@webassemblyjs/helper-module-context": "1.9.0",
+        "@webassemblyjs/helper-wasm-bytecode": "1.9.0",
+        "@webassemblyjs/wast-parser": "1.9.0"
+      }
+    },
+    "@webassemblyjs/floating-point-hex-parser": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz",
+      "integrity": "sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA==",
+      "dev": true
+    },
+    "@webassemblyjs/helper-api-error": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz",
+      "integrity": "sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw==",
+      "dev": true
+    },
+    "@webassemblyjs/helper-buffer": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz",
+      "integrity": "sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA==",
+      "dev": true
+    },
+    "@webassemblyjs/helper-code-frame": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz",
+      "integrity": "sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA==",
+      "dev": true,
+      "requires": {
+        "@webassemblyjs/wast-printer": "1.9.0"
+      }
+    },
+    "@webassemblyjs/helper-fsm": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz",
+      "integrity": "sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw==",
+      "dev": true
+    },
+    "@webassemblyjs/helper-module-context": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz",
+      "integrity": "sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g==",
+      "dev": true,
+      "requires": {
+        "@webassemblyjs/ast": "1.9.0"
+      }
+    },
+    "@webassemblyjs/helper-numbers": {
+      "version": "1.11.1",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz",
+      "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==",
+      "dev": true,
+      "requires": {
+        "@webassemblyjs/floating-point-hex-parser": "1.11.1",
+        "@webassemblyjs/helper-api-error": "1.11.1",
+        "@xtuc/long": "4.2.2"
+      },
+      "dependencies": {
+        "@webassemblyjs/floating-point-hex-parser": {
+          "version": "1.11.1",
+          "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz",
+          "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==",
+          "dev": true
+        },
+        "@webassemblyjs/helper-api-error": {
+          "version": "1.11.1",
+          "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz",
+          "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==",
+          "dev": true
+        }
+      }
+    },
+    "@webassemblyjs/helper-wasm-bytecode": {
       "version": "1.9.0",
       "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz",
       "integrity": "sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==",
@@ -2091,15 +2938,21 @@
       }
     },
     "acorn": {
-      "version": "7.4.1",
-      "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz",
-      "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==",
+      "version": "6.4.2",
+      "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz",
+      "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==",
+      "dev": true
+    },
+    "acorn-import-assertions": {
+      "version": "1.8.0",
+      "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz",
+      "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==",
       "dev": true
     },
     "acorn-jsx": {
-      "version": "5.3.1",
-      "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz",
-      "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==",
+      "version": "5.3.2",
+      "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+      "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
       "dev": true
     },
     "acorn-walk": {
@@ -2150,19 +3003,10 @@
       "integrity": "sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==",
       "dev": true
     },
-    "ansi-escapes": {
-      "version": "4.3.2",
-      "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
-      "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==",
-      "dev": true,
-      "requires": {
-        "type-fest": "^0.21.3"
-      }
-    },
-    "ansi-html": {
-      "version": "0.0.7",
-      "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz",
-      "integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4=",
+    "ansi-html-community": {
+      "version": "0.0.8",
+      "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz",
+      "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==",
       "dev": true
     },
     "ansi-regex": {
@@ -2269,9 +3113,9 @@
       "dev": true
     },
     "asn1": {
-      "version": "0.2.4",
-      "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
-      "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==",
+      "version": "0.2.6",
+      "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz",
+      "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==",
       "dev": true,
       "requires": {
         "safer-buffer": "~2.1.0"
@@ -2337,9 +3181,9 @@
       "dev": true
     },
     "astral-regex": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz",
-      "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==",
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz",
+      "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==",
       "dev": true
     },
     "async": {
@@ -2376,18 +3220,26 @@
       "dev": true
     },
     "autoprefixer": {
-      "version": "9.8.6",
-      "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.8.6.tgz",
-      "integrity": "sha512-XrvP4VVHdRBCdX1S3WXVD8+RyG9qeb1D5Sn1DeLiG2xfSpzellk5k54xbUERJ3M5DggQxes39UGOTP8CFrEGbg==",
+      "version": "9.8.8",
+      "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.8.8.tgz",
+      "integrity": "sha512-eM9d/swFopRt5gdJ7jrpCwgvEMIayITpojhkkSMRsFHYuH5bkSQ4p/9qTEHtmNudUZh22Tehu7I6CxAW0IXTKA==",
       "dev": true,
       "requires": {
         "browserslist": "^4.12.0",
         "caniuse-lite": "^1.0.30001109",
-        "colorette": "^1.2.1",
         "normalize-range": "^0.1.2",
         "num2fraction": "^1.2.2",
+        "picocolors": "^0.2.1",
         "postcss": "^7.0.32",
         "postcss-value-parser": "^4.1.0"
+      },
+      "dependencies": {
+        "picocolors": {
+          "version": "0.2.1",
+          "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz",
+          "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==",
+          "dev": true
+        }
       }
     },
     "aws-sign2": {
@@ -2403,25 +3255,11 @@
       "dev": true
     },
     "axios": {
-      "version": "0.21.1",
-      "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz",
-      "integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==",
-      "requires": {
-        "follow-redirects": "^1.10.0"
-      }
-    },
-    "babel-eslint": {
-      "version": "10.1.0",
-      "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.1.0.tgz",
-      "integrity": "sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg==",
-      "dev": true,
+      "version": "0.21.4",
+      "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz",
+      "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==",
       "requires": {
-        "@babel/code-frame": "^7.0.0",
-        "@babel/parser": "^7.7.0",
-        "@babel/traverse": "^7.7.0",
-        "@babel/types": "^7.7.0",
-        "eslint-visitor-keys": "^1.0.0",
-        "resolve": "^1.12.0"
+        "follow-redirects": "^1.14.0"
       }
     },
     "babel-extract-comments": {
@@ -2434,9 +3272,9 @@
       }
     },
     "babel-loader": {
-      "version": "8.2.2",
-      "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.2.2.tgz",
-      "integrity": "sha512-JvTd0/D889PQBtUXJ2PXaKU/pjZDMtHA9V2ecm+eNRmmBCMR09a+fmpGTNwnJtFmFl5Ei7Vy47LjBb+L0wQ99g==",
+      "version": "8.2.3",
+      "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.2.3.tgz",
+      "integrity": "sha512-n4Zeta8NC3QAsuyiizu0GkmRcQ6clkV9WFUnUf1iXP//IeSKbWjofW3UHyZVwlOB4y039YQKefawyTn64Zwbuw==",
       "dev": true,
       "requires": {
         "find-cache-dir": "^3.3.1",
@@ -2455,33 +3293,33 @@
       }
     },
     "babel-plugin-polyfill-corejs2": {
-      "version": "0.2.2",
-      "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.2.2.tgz",
-      "integrity": "sha512-kISrENsJ0z5dNPq5eRvcctITNHYXWOA4DUZRFYCz3jYCcvTb/A546LIddmoGNMVYg2U38OyFeNosQwI9ENTqIQ==",
+      "version": "0.3.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.0.tgz",
+      "integrity": "sha512-wMDoBJ6uG4u4PNFh72Ty6t3EgfA91puCuAwKIazbQlci+ENb/UU9A3xG5lutjUIiXCIn1CY5L15r9LimiJyrSA==",
       "dev": true,
       "requires": {
         "@babel/compat-data": "^7.13.11",
-        "@babel/helper-define-polyfill-provider": "^0.2.2",
+        "@babel/helper-define-polyfill-provider": "^0.3.0",
         "semver": "^6.1.1"
       }
     },
     "babel-plugin-polyfill-corejs3": {
-      "version": "0.2.3",
-      "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.2.3.tgz",
-      "integrity": "sha512-rCOFzEIJpJEAU14XCcV/erIf/wZQMmMT5l5vXOpL5uoznyOGfDIjPj6FVytMvtzaKSTSVKouOCTPJ5OMUZH30g==",
+      "version": "0.4.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.4.0.tgz",
+      "integrity": "sha512-YxFreYwUfglYKdLUGvIF2nJEsGwj+RhWSX/ije3D2vQPOXuyMLMtg/cCGMDpOA7Nd+MwlNdnGODbd2EwUZPlsw==",
       "dev": true,
       "requires": {
-        "@babel/helper-define-polyfill-provider": "^0.2.2",
-        "core-js-compat": "^3.14.0"
+        "@babel/helper-define-polyfill-provider": "^0.3.0",
+        "core-js-compat": "^3.18.0"
       }
     },
     "babel-plugin-polyfill-regenerator": {
-      "version": "0.2.2",
-      "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.2.2.tgz",
-      "integrity": "sha512-Goy5ghsc21HgPDFtzRkSirpZVW35meGoTmTOb2bxqdl60ghub4xOidgNTHaZfQ2FaxQsKmwvXtOAkcIS4SMBWg==",
+      "version": "0.3.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.3.0.tgz",
+      "integrity": "sha512-dhAPTDLGoMW5/84wkgwiLRwMnio2i1fUe53EuvtKMv0pn2p3S8OCoV1xAzfJPl0KOX7IB89s2ib85vbYiea3jg==",
       "dev": true,
       "requires": {
-        "@babel/helper-define-polyfill-provider": "^0.2.2"
+        "@babel/helper-define-polyfill-provider": "^0.3.0"
       }
     },
     "babel-plugin-syntax-object-rest-spread": {
@@ -2557,7 +3395,36 @@
           "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
           "dev": true,
           "requires": {
-            "is-descriptor": "^1.0.0"
+            "is-descriptor": "^1.0.0"
+          }
+        },
+        "is-accessor-descriptor": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+          "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+          "dev": true,
+          "requires": {
+            "kind-of": "^6.0.0"
+          }
+        },
+        "is-data-descriptor": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+          "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+          "dev": true,
+          "requires": {
+            "kind-of": "^6.0.0"
+          }
+        },
+        "is-descriptor": {
+          "version": "1.0.2",
+          "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+          "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+          "dev": true,
+          "requires": {
+            "is-accessor-descriptor": "^1.0.0",
+            "is-data-descriptor": "^1.0.0",
+            "kind-of": "^6.0.2"
           }
         }
       }
@@ -2618,6 +3485,40 @@
         "file-uri-to-path": "1.0.0"
       }
     },
+    "bl": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
+      "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
+      "dev": true,
+      "requires": {
+        "buffer": "^5.5.0",
+        "inherits": "^2.0.4",
+        "readable-stream": "^3.4.0"
+      },
+      "dependencies": {
+        "buffer": {
+          "version": "5.7.1",
+          "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
+          "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
+          "dev": true,
+          "requires": {
+            "base64-js": "^1.3.1",
+            "ieee754": "^1.1.13"
+          }
+        },
+        "readable-stream": {
+          "version": "3.6.0",
+          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+          "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+          "dev": true,
+          "requires": {
+            "inherits": "^2.0.3",
+            "string_decoder": "^1.1.1",
+            "util-deprecate": "^1.0.1"
+          }
+        }
+      }
+    },
     "bluebird": {
       "version": "3.7.2",
       "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
@@ -2631,21 +3532,21 @@
       "dev": true
     },
     "body-parser": {
-      "version": "1.19.0",
-      "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz",
-      "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==",
+      "version": "1.19.1",
+      "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.1.tgz",
+      "integrity": "sha512-8ljfQi5eBk8EJfECMrgqNGWPEY5jWP+1IzkzkGdFFEwFQZZyaZ21UqdaHktgiMlH0xLHqIFtE/u2OYE5dOtViA==",
       "dev": true,
       "requires": {
-        "bytes": "3.1.0",
+        "bytes": "3.1.1",
         "content-type": "~1.0.4",
         "debug": "2.6.9",
         "depd": "~1.1.2",
-        "http-errors": "1.7.2",
+        "http-errors": "1.8.1",
         "iconv-lite": "0.4.24",
         "on-finished": "~2.3.0",
-        "qs": "6.7.0",
-        "raw-body": "2.4.0",
-        "type-is": "~1.6.17"
+        "qs": "6.9.6",
+        "raw-body": "2.4.2",
+        "type-is": "~1.6.18"
       },
       "dependencies": {
         "debug": {
@@ -2664,9 +3565,9 @@
           "dev": true
         },
         "qs": {
-          "version": "6.7.0",
-          "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
-          "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==",
+          "version": "6.9.6",
+          "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.6.tgz",
+          "integrity": "sha512-TIRk4aqYLNoJUbd+g2lEdz5kLWIuTMRagAXxl78Q0RiVjAOugHmeKNGdd3cwo/ktpf9aL9epCfFqWDEKysUlLQ==",
           "dev": true
         }
       }
@@ -2735,12 +3636,6 @@
           "requires": {
             "is-extendable": "^0.1.0"
           }
-        },
-        "is-extendable": {
-          "version": "0.1.1",
-          "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
-          "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=",
-          "dev": true
         }
       }
     },
@@ -2843,16 +3738,16 @@
       }
     },
     "browserslist": {
-      "version": "4.16.6",
-      "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.6.tgz",
-      "integrity": "sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ==",
+      "version": "4.19.1",
+      "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.19.1.tgz",
+      "integrity": "sha512-u2tbbG5PdKRTUoctO3NBD8FQ5HdPh1ZXPHzp1rwaa5jTc+RV9/+RlWiAIKmjRPQF+xbGM9Kklj5bZQFa2s/38A==",
       "dev": true,
       "requires": {
-        "caniuse-lite": "^1.0.30001219",
-        "colorette": "^1.2.2",
-        "electron-to-chromium": "^1.3.723",
+        "caniuse-lite": "^1.0.30001286",
+        "electron-to-chromium": "^1.4.17",
         "escalade": "^3.1.1",
-        "node-releases": "^1.1.71"
+        "node-releases": "^2.0.1",
+        "picocolors": "^1.0.0"
       }
     },
     "buffer": {
@@ -2867,9 +3762,9 @@
       }
     },
     "buffer-from": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
-      "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==",
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
+      "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
       "dev": true
     },
     "buffer-indexof": {
@@ -2897,9 +3792,9 @@
       "dev": true
     },
     "bytes": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
-      "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==",
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.1.tgz",
+      "integrity": "sha512-dWe4nWO/ruEOY7HkUJ5gFt1DCFV9zPRoJr8pV0/ASQermOZjtq8jMjOprC0Kd10GLN+l7xaUPvxzJFWtxGu8Fg==",
       "dev": true
     },
     "cacache": {
@@ -2923,17 +3818,6 @@
         "ssri": "^6.0.1",
         "unique-filename": "^1.1.1",
         "y18n": "^4.0.0"
-      },
-      "dependencies": {
-        "ssri": {
-          "version": "6.0.2",
-          "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.2.tgz",
-          "integrity": "sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q==",
-          "dev": true,
-          "requires": {
-            "figgy-pudding": "^3.5.1"
-          }
-        }
       }
     },
     "cache-base": {
@@ -3018,9 +3902,9 @@
       }
     },
     "camelcase": {
-      "version": "6.2.0",
-      "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz",
-      "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==",
+      "version": "6.3.0",
+      "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
+      "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
       "dev": true
     },
     "caniuse-api": {
@@ -3036,9 +3920,9 @@
       }
     },
     "caniuse-lite": {
-      "version": "1.0.30001243",
-      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001243.tgz",
-      "integrity": "sha512-vNxw9mkTBtkmLFnJRv/2rhs1yufpDfCkBZexG3Y0xdOH2Z/eE/85E4Dl5j1YUN34nZVsSp6vVRFQRrez9wJMRA==",
+      "version": "1.0.30001296",
+      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001296.tgz",
+      "integrity": "sha512-WfrtPEoNSoeATDlf4y3QvkwiELl9GyPLISV5GejTbbQRtQx4LhsXmc9IQ6XCL2d7UxCyEzToEZNMeqR79OUw8Q==",
       "dev": true
     },
     "case-sensitive-paths-webpack-plugin": {
@@ -3064,12 +3948,6 @@
         "supports-color": "^5.3.0"
       }
     },
-    "chardet": {
-      "version": "0.7.0",
-      "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz",
-      "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==",
-      "dev": true
-    },
     "check-types": {
       "version": "8.0.3",
       "resolved": "https://registry.npmjs.org/check-types/-/check-types-8.0.3.tgz",
@@ -3113,16 +3991,6 @@
             "to-regex-range": "^5.0.1"
           }
         },
-        "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,
-          "optional": true,
-          "requires": {
-            "is-glob": "^4.0.1"
-          }
-        },
         "is-number": {
           "version": "7.0.0",
           "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
@@ -3190,70 +4058,13 @@
           "requires": {
             "is-descriptor": "^0.1.0"
           }
-        },
-        "is-accessor-descriptor": {
-          "version": "0.1.6",
-          "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
-          "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=",
-          "dev": true,
-          "requires": {
-            "kind-of": "^3.0.2"
-          },
-          "dependencies": {
-            "kind-of": {
-              "version": "3.2.2",
-              "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-              "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
-              "dev": true,
-              "requires": {
-                "is-buffer": "^1.1.5"
-              }
-            }
-          }
-        },
-        "is-data-descriptor": {
-          "version": "0.1.4",
-          "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
-          "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=",
-          "dev": true,
-          "requires": {
-            "kind-of": "^3.0.2"
-          },
-          "dependencies": {
-            "kind-of": {
-              "version": "3.2.2",
-              "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-              "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
-              "dev": true,
-              "requires": {
-                "is-buffer": "^1.1.5"
-              }
-            }
-          }
-        },
-        "is-descriptor": {
-          "version": "0.1.6",
-          "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
-          "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==",
-          "dev": true,
-          "requires": {
-            "is-accessor-descriptor": "^0.1.6",
-            "is-data-descriptor": "^0.1.4",
-            "kind-of": "^5.0.0"
-          }
-        },
-        "kind-of": {
-          "version": "5.1.0",
-          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
-          "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
-          "dev": true
         }
       }
     },
     "clean-css": {
-      "version": "4.2.3",
-      "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.3.tgz",
-      "integrity": "sha512-VcMWDN54ZN/DS+g58HYL5/n4Zrqe8vHJpGA8KdgUXFU4fuP/aHNw8eld9SyEIyabIMJX/0RaY/fplOo5hYLSFA==",
+      "version": "4.2.4",
+      "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.4.tgz",
+      "integrity": "sha512-EJUDT7nDVFDvaQgAo2G/PJvxmp1o/c6iXLbswsBbUFXi1Nr+AjA2cKmfbKDMjMvzEe75g3P6JkaDDAKk96A85A==",
       "dev": true,
       "requires": {
         "source-map": "~0.6.0"
@@ -3268,12 +4079,12 @@
       }
     },
     "cli-cursor": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
-      "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==",
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz",
+      "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=",
       "dev": true,
       "requires": {
-        "restore-cursor": "^3.1.0"
+        "restore-cursor": "^2.0.0"
       }
     },
     "cli-highlight": {
@@ -3300,9 +4111,9 @@
           }
         },
         "chalk": {
-          "version": "4.1.1",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz",
-          "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==",
+          "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",
@@ -3342,15 +4153,9 @@
       }
     },
     "cli-spinners": {
-      "version": "2.6.0",
-      "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.0.tgz",
-      "integrity": "sha512-t+4/y50K/+4xcCRosKkA7W4gTr1MySvLV0q+PxmG7FJ5g+66ChKurYjxBCjHggHH3HA5Hh9cy+lcUGWDqVH+4Q==",
-      "dev": true
-    },
-    "cli-width": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz",
-      "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==",
+      "version": "2.6.1",
+      "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz",
+      "integrity": "sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==",
       "dev": true
     },
     "clipboardy": {
@@ -3362,6 +4167,17 @@
         "arch": "^2.1.1",
         "execa": "^1.0.0",
         "is-wsl": "^2.1.1"
+      },
+      "dependencies": {
+        "is-wsl": {
+          "version": "2.2.0",
+          "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
+          "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==",
+          "dev": true,
+          "requires": {
+            "is-docker": "^2.0.0"
+          }
+        }
       }
     },
     "cliui": {
@@ -3375,36 +4191,39 @@
         "wrap-ansi": "^6.2.0"
       },
       "dependencies": {
-        "ansi-regex": {
-          "version": "5.0.0",
-          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
-          "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
-          "dev": true
-        },
-        "is-fullwidth-code-point": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
-          "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
-          "dev": true
+        "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"
+          }
         },
-        "string-width": {
-          "version": "4.2.2",
-          "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz",
-          "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==",
+        "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": {
-            "emoji-regex": "^8.0.0",
-            "is-fullwidth-code-point": "^3.0.0",
-            "strip-ansi": "^6.0.0"
+            "color-name": "~1.1.4"
           }
         },
-        "strip-ansi": {
-          "version": "6.0.0",
-          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
-          "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
+        "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
+        },
+        "wrap-ansi": {
+          "version": "6.2.0",
+          "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
+          "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
           "dev": true,
           "requires": {
-            "ansi-regex": "^5.0.0"
+            "ansi-styles": "^4.0.0",
+            "string-width": "^4.1.0",
+            "strip-ansi": "^6.0.0"
           }
         }
       }
@@ -3437,13 +4256,13 @@
       }
     },
     "color": {
-      "version": "3.1.3",
-      "resolved": "https://registry.npmjs.org/color/-/color-3.1.3.tgz",
-      "integrity": "sha512-xgXAcTHa2HeFCGLE9Xs/R82hujGtu9Jd9x4NW3T34+OMs7VoPsjwzRczKHvTAHeJwWFwX5j15+MgAppE8ztObQ==",
+      "version": "3.2.1",
+      "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz",
+      "integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==",
       "dev": true,
       "requires": {
-        "color-convert": "^1.9.1",
-        "color-string": "^1.5.4"
+        "color-convert": "^1.9.3",
+        "color-string": "^1.6.0"
       }
     },
     "color-convert": {
@@ -3462,21 +4281,15 @@
       "dev": true
     },
     "color-string": {
-      "version": "1.5.5",
-      "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.5.tgz",
-      "integrity": "sha512-jgIoum0OfQfq9Whcfc2z/VhCNcmQjWbey6qBX0vqt7YICflUmBCh9E9CiQD5GSJ+Uehixm3NUwHVhqUAWRivZg==",
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.0.tgz",
+      "integrity": "sha512-9Mrz2AQLefkH1UvASKj6v6hj/7eWgjnT/cVsR8CumieLoT+g900exWeNogqtweI8dxloXN9BDQTYro1oWu/5CQ==",
       "dev": true,
       "requires": {
         "color-name": "^1.0.0",
         "simple-swizzle": "^0.2.2"
       }
     },
-    "colorette": {
-      "version": "1.2.2",
-      "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz",
-      "integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==",
-      "dev": true
-    },
     "combined-stream": {
       "version": "1.0.8",
       "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
@@ -3499,14 +4312,14 @@
       }
     },
     "commander": {
-      "version": "2.17.1",
-      "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz",
-      "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg=="
+      "version": "2.20.3",
+      "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+      "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
     },
     "common-tags": {
-      "version": "1.8.0",
-      "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.0.tgz",
-      "integrity": "sha512-6P6g0uetGpW/sdyUy/iQQCbFF0kWVMSIVSyYz7Zgjcgh8mgw8PQzDNZeyZ5DQ2gM7LBoZPHmnjz8rUthkBG5tw==",
+      "version": "1.8.2",
+      "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz",
+      "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==",
       "dev": true
     },
     "commondir": {
@@ -3614,12 +4427,20 @@
       "dev": true
     },
     "content-disposition": {
-      "version": "0.5.3",
-      "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz",
-      "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==",
+      "version": "0.5.4",
+      "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
+      "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
       "dev": true,
       "requires": {
-        "safe-buffer": "5.1.2"
+        "safe-buffer": "5.2.1"
+      },
+      "dependencies": {
+        "safe-buffer": {
+          "version": "5.2.1",
+          "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+          "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+          "dev": true
+        }
       }
     },
     "content-type": {
@@ -3638,9 +4459,9 @@
       }
     },
     "cookie": {
-      "version": "0.4.0",
-      "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz",
-      "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==",
+      "version": "0.4.1",
+      "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz",
+      "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==",
       "dev": true
     },
     "cookie-signature": {
@@ -3718,6 +4539,27 @@
             "locate-path": "^3.0.0"
           }
         },
+        "glob-parent": {
+          "version": "3.1.0",
+          "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
+          "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=",
+          "dev": true,
+          "requires": {
+            "is-glob": "^3.1.0",
+            "path-dirname": "^1.0.0"
+          },
+          "dependencies": {
+            "is-glob": {
+              "version": "3.1.0",
+              "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
+              "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=",
+              "dev": true,
+              "requires": {
+                "is-extglob": "^2.1.0"
+              }
+            }
+          }
+        },
         "globby": {
           "version": "7.1.1",
           "resolved": "https://registry.npmjs.org/globby/-/globby-7.1.1.tgz",
@@ -3816,17 +4658,17 @@
       }
     },
     "core-js": {
-      "version": "3.15.2",
-      "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.15.2.tgz",
-      "integrity": "sha512-tKs41J7NJVuaya8DxIOCnl8QuPHx5/ZVbFo1oKgVl1qHFBBrDctzQGtuLjPpRdNTWmKPH6oEvgN/MUID+l485Q=="
+      "version": "3.20.2",
+      "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.20.2.tgz",
+      "integrity": "sha512-nuqhq11DcOAbFBV4zCbKeGbKQsUDRqTX0oqx7AttUBuqe3h20ixsE039QHelbL6P4h+9kytVqyEtyZ6gsiwEYw=="
     },
     "core-js-compat": {
-      "version": "3.15.2",
-      "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.15.2.tgz",
-      "integrity": "sha512-Wp+BJVvwopjI+A1EFqm2dwUmWYXrvucmtIB2LgXn/Rb+gWPKYxtmb4GKHGKG/KGF1eK9jfjzT38DITbTOCX/SQ==",
+      "version": "3.20.2",
+      "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.20.2.tgz",
+      "integrity": "sha512-qZEzVQ+5Qh6cROaTPFLNS4lkvQ6mBzE3R6A6EEpssj7Zr2egMHgsy4XapdifqJDGC9CBiNv7s+ejI96rLNQFdg==",
       "dev": true,
       "requires": {
-        "browserslist": "^4.16.6",
+        "browserslist": "^4.19.1",
         "semver": "7.0.0"
       },
       "dependencies": {
@@ -3864,6 +4706,18 @@
         "is-directory": "^0.3.1",
         "js-yaml": "^3.13.1",
         "parse-json": "^4.0.0"
+      },
+      "dependencies": {
+        "parse-json": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
+          "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=",
+          "dev": true,
+          "requires": {
+            "error-ex": "^1.3.1",
+            "json-parse-better-errors": "^1.0.1"
+          }
+        }
       }
     },
     "create-ecdh": {
@@ -3997,16 +4851,15 @@
       }
     },
     "css-select": {
-      "version": "4.1.3",
-      "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.1.3.tgz",
-      "integrity": "sha512-gT3wBNd9Nj49rAbmtFHj1cljIAOLYSX1nZ8CB7TBO3INYckygm5B7LISU/szY//YmdiSLbJvDLOx9VnMVpMBxA==",
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.1.0.tgz",
+      "integrity": "sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ==",
       "dev": true,
       "requires": {
         "boolbase": "^1.0.0",
-        "css-what": "^5.0.0",
-        "domhandler": "^4.2.0",
-        "domutils": "^2.6.0",
-        "nth-check": "^2.0.0"
+        "css-what": "^3.2.1",
+        "domutils": "^1.7.0",
+        "nth-check": "^1.0.2"
       }
     },
     "css-select-base-adapter": {
@@ -4034,9 +4887,9 @@
       }
     },
     "css-what": {
-      "version": "5.0.1",
-      "resolved": "https://registry.npmjs.org/css-what/-/css-what-5.0.1.tgz",
-      "integrity": "sha512-FYDTSHb/7KXsWICVsxdmiExPjCfRC4qRFBdVwv7Ax9hMnvMmEjP9RfxTEZ3qPZGmADDn2vAKSo9UcN1jKVYscg==",
+      "version": "3.4.2",
+      "resolved": "https://registry.npmjs.org/css-what/-/css-what-3.4.2.tgz",
+      "integrity": "sha512-ACUm3L0/jiZTqfzRM3Hi9Q8eZqd6IK37mMWPLz9PJxkLWllYeRf+EHUSHYEtFop2Eqytaq1FizFVh7XfBnXCDQ==",
       "dev": true
     },
     "cssesc": {
@@ -4177,9 +5030,9 @@
       "dev": true
     },
     "debug": {
-      "version": "4.3.2",
-      "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz",
-      "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==",
+      "version": "4.3.3",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz",
+      "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==",
       "dev": true,
       "requires": {
         "ms": "2.1.2"
@@ -4212,9 +5065,9 @@
       }
     },
     "deep-is": {
-      "version": "0.1.3",
-      "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
-      "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=",
+      "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
     },
     "deepmerge": {
@@ -4271,9 +5124,15 @@
           }
         },
         "is-stream": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz",
-          "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==",
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
+          "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
+          "dev": true
+        },
+        "mimic-fn": {
+          "version": "2.1.0",
+          "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
+          "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
           "dev": true
         },
         "npm-run-path": {
@@ -4285,6 +5144,15 @@
             "path-key": "^3.0.0"
           }
         },
+        "onetime": {
+          "version": "5.1.2",
+          "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
+          "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
+          "dev": true,
+          "requires": {
+            "mimic-fn": "^2.1.0"
+          }
+        },
         "p-finally": {
           "version": "2.0.1",
           "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-2.0.1.tgz",
@@ -4332,6 +5200,12 @@
         "clone": "^1.0.2"
       }
     },
+    "define-lazy-prop": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz",
+      "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==",
+      "dev": true
+    },
     "define-properties": {
       "version": "1.1.3",
       "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
@@ -4349,6 +5223,37 @@
       "requires": {
         "is-descriptor": "^1.0.2",
         "isobject": "^3.0.1"
+      },
+      "dependencies": {
+        "is-accessor-descriptor": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+          "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+          "dev": true,
+          "requires": {
+            "kind-of": "^6.0.0"
+          }
+        },
+        "is-data-descriptor": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+          "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+          "dev": true,
+          "requires": {
+            "kind-of": "^6.0.0"
+          }
+        },
+        "is-descriptor": {
+          "version": "1.0.2",
+          "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+          "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+          "dev": true,
+          "requires": {
+            "is-accessor-descriptor": "^1.0.0",
+            "is-data-descriptor": "^1.0.0",
+            "kind-of": "^6.0.2"
+          }
+        }
       }
     },
     "del": {
@@ -4495,14 +5400,21 @@
       }
     },
     "dom-serializer": {
-      "version": "1.3.2",
-      "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz",
-      "integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==",
+      "version": "0.2.2",
+      "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz",
+      "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==",
       "dev": true,
       "requires": {
         "domelementtype": "^2.0.1",
-        "domhandler": "^4.2.0",
         "entities": "^2.0.0"
+      },
+      "dependencies": {
+        "domelementtype": {
+          "version": "2.2.0",
+          "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz",
+          "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==",
+          "dev": true
+        }
       }
     },
     "domain-browser": {
@@ -4512,29 +5424,36 @@
       "dev": true
     },
     "domelementtype": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz",
-      "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==",
+      "version": "1.3.1",
+      "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz",
+      "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==",
       "dev": true
     },
     "domhandler": {
-      "version": "4.2.0",
-      "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.2.0.tgz",
-      "integrity": "sha512-zk7sgt970kzPks2Bf+dwT/PLzghLnsivb9CcxkvR8Mzr66Olr0Ofd8neSbglHJHaHa2MadfoSdNlKYAaafmWfA==",
+      "version": "4.3.0",
+      "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.0.tgz",
+      "integrity": "sha512-fC0aXNQXqKSFTr2wDNZDhsEYjCiYsDWl3D01kwt25hm1YIPyDGHvvi3rw+PLqHAl/m71MaiF7d5zvBr0p5UB2g==",
       "dev": true,
       "requires": {
         "domelementtype": "^2.2.0"
+      },
+      "dependencies": {
+        "domelementtype": {
+          "version": "2.2.0",
+          "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz",
+          "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==",
+          "dev": true
+        }
       }
     },
     "domutils": {
-      "version": "2.7.0",
-      "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.7.0.tgz",
-      "integrity": "sha512-8eaHa17IwJUPAiB+SoTYBo5mCdeMgdcAoXJ59m6DT1vw+5iLS3gNoqYaRowaBKtGVrOF1Jz4yDTgYKLK2kvfJg==",
+      "version": "1.7.0",
+      "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz",
+      "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==",
       "dev": true,
       "requires": {
-        "dom-serializer": "^1.0.1",
-        "domelementtype": "^2.2.0",
-        "domhandler": "^4.2.0"
+        "dom-serializer": "0",
+        "domelementtype": "1"
       }
     },
     "dot-prop": {
@@ -4613,9 +5532,9 @@
       "dev": true
     },
     "electron-to-chromium": {
-      "version": "1.3.770",
-      "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.770.tgz",
-      "integrity": "sha512-Kyh8DGK1KfEZuYKIHvuOmrKotsKZQ+qBkDIWHciE3QoFkxXB1KzPP+tfLilSHAfxTON0yYMnFCWkQtUOR7g6KQ==",
+      "version": "1.4.36",
+      "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.36.tgz",
+      "integrity": "sha512-MbLlbF39vKrXWlFEFpCgDHwdlz4O3LmHM5W4tiLRHjSmEUXjJjz8sZkMgWgvYxlZw3N1iDTmCEtOkkESb5TMCg==",
       "dev": true
     },
     "elliptic": {
@@ -4691,6 +5610,23 @@
         }
       }
     },
+    "enquirer": {
+      "version": "2.3.6",
+      "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz",
+      "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==",
+      "dev": true,
+      "requires": {
+        "ansi-colors": "^4.1.1"
+      },
+      "dependencies": {
+        "ansi-colors": {
+          "version": "4.1.1",
+          "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz",
+          "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==",
+          "dev": true
+        }
+      }
+    },
     "entities": {
       "version": "2.2.0",
       "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz",
@@ -4725,22 +5661,26 @@
       }
     },
     "es-abstract": {
-      "version": "1.18.3",
-      "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.3.tgz",
-      "integrity": "sha512-nQIr12dxV7SSxE6r6f1l3DtAeEYdsGpps13dR0TwJg1S8gyp4ZPgy3FZcHBgbiQqnoqSTb+oC+kO4UQ0C/J8vw==",
+      "version": "1.19.1",
+      "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.1.tgz",
+      "integrity": "sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w==",
       "dev": true,
       "requires": {
         "call-bind": "^1.0.2",
         "es-to-primitive": "^1.2.1",
         "function-bind": "^1.1.1",
         "get-intrinsic": "^1.1.1",
+        "get-symbol-description": "^1.0.0",
         "has": "^1.0.3",
         "has-symbols": "^1.0.2",
-        "is-callable": "^1.2.3",
+        "internal-slot": "^1.0.3",
+        "is-callable": "^1.2.4",
         "is-negative-zero": "^2.0.1",
-        "is-regex": "^1.1.3",
-        "is-string": "^1.0.6",
-        "object-inspect": "^1.10.3",
+        "is-regex": "^1.1.4",
+        "is-shared-array-buffer": "^1.0.1",
+        "is-string": "^1.0.7",
+        "is-weakref": "^1.0.1",
+        "object-inspect": "^1.11.0",
         "object-keys": "^1.1.1",
         "object.assign": "^4.1.2",
         "string.prototype.trimend": "^1.0.4",
@@ -4748,6 +5688,12 @@
         "unbox-primitive": "^1.0.1"
       }
     },
+    "es-module-lexer": {
+      "version": "0.9.3",
+      "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz",
+      "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==",
+      "dev": true
+    },
     "es-to-primitive": {
       "version": "1.2.1",
       "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
@@ -4778,50 +5724,113 @@
       "dev": true
     },
     "eslint": {
-      "version": "6.8.0",
-      "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.8.0.tgz",
-      "integrity": "sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig==",
+      "version": "7.32.0",
+      "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz",
+      "integrity": "sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==",
       "dev": true,
       "requires": {
-        "@babel/code-frame": "^7.0.0",
+        "@babel/code-frame": "7.12.11",
+        "@eslint/eslintrc": "^0.4.3",
+        "@humanwhocodes/config-array": "^0.5.0",
         "ajv": "^6.10.0",
-        "chalk": "^2.1.0",
-        "cross-spawn": "^6.0.5",
+        "chalk": "^4.0.0",
+        "cross-spawn": "^7.0.2",
         "debug": "^4.0.1",
         "doctrine": "^3.0.0",
-        "eslint-scope": "^5.0.0",
-        "eslint-utils": "^1.4.3",
-        "eslint-visitor-keys": "^1.1.0",
-        "espree": "^6.1.2",
-        "esquery": "^1.0.1",
+        "enquirer": "^2.3.5",
+        "escape-string-regexp": "^4.0.0",
+        "eslint-scope": "^5.1.1",
+        "eslint-utils": "^2.1.0",
+        "eslint-visitor-keys": "^2.0.0",
+        "espree": "^7.3.1",
+        "esquery": "^1.4.0",
         "esutils": "^2.0.2",
-        "file-entry-cache": "^5.0.1",
+        "fast-deep-equal": "^3.1.3",
+        "file-entry-cache": "^6.0.1",
         "functional-red-black-tree": "^1.0.1",
-        "glob-parent": "^5.0.0",
-        "globals": "^12.1.0",
+        "glob-parent": "^5.1.2",
+        "globals": "^13.6.0",
         "ignore": "^4.0.6",
         "import-fresh": "^3.0.0",
         "imurmurhash": "^0.1.4",
-        "inquirer": "^7.0.0",
         "is-glob": "^4.0.0",
         "js-yaml": "^3.13.1",
         "json-stable-stringify-without-jsonify": "^1.0.1",
-        "levn": "^0.3.0",
-        "lodash": "^4.17.14",
+        "levn": "^0.4.1",
+        "lodash.merge": "^4.6.2",
         "minimatch": "^3.0.4",
-        "mkdirp": "^0.5.1",
         "natural-compare": "^1.4.0",
-        "optionator": "^0.8.3",
+        "optionator": "^0.9.1",
         "progress": "^2.0.0",
-        "regexpp": "^2.0.1",
-        "semver": "^6.1.2",
-        "strip-ansi": "^5.2.0",
-        "strip-json-comments": "^3.0.1",
-        "table": "^5.2.3",
+        "regexpp": "^3.1.0",
+        "semver": "^7.2.1",
+        "strip-ansi": "^6.0.0",
+        "strip-json-comments": "^3.1.0",
+        "table": "^6.0.9",
         "text-table": "^0.2.0",
         "v8-compile-cache": "^2.0.3"
       },
       "dependencies": {
+        "@babel/code-frame": {
+          "version": "7.12.11",
+          "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz",
+          "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==",
+          "dev": true,
+          "requires": {
+            "@babel/highlight": "^7.10.4"
+          }
+        },
+        "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"
+          }
+        },
+        "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
+        },
+        "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"
+          }
+        },
+        "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==",
+          "dev": true
+        },
         "eslint-scope": {
           "version": "5.1.1",
           "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
@@ -4832,24 +5841,21 @@
             "estraverse": "^4.1.1"
           }
         },
-        "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"
-          }
-        },
         "globals": {
-          "version": "12.4.0",
-          "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz",
-          "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==",
+          "version": "13.12.0",
+          "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.0.tgz",
+          "integrity": "sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg==",
           "dev": true,
           "requires": {
-            "type-fest": "^0.8.1"
+            "type-fest": "^0.20.2"
           }
         },
+        "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
+        },
         "import-fresh": {
           "version": "3.3.0",
           "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
@@ -4860,50 +5866,93 @@
             "resolve-from": "^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"
+          }
+        },
+        "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
+        },
         "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==",
           "dev": true
         },
+        "semver": {
+          "version": "7.3.5",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
+          "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
+          "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
+        },
+        "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"
+          }
+        },
         "type-fest": {
-          "version": "0.8.1",
-          "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
-          "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
+          "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
+        },
+        "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"
+          }
+        },
+        "yallist": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+          "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
           "dev": true
         }
       }
     },
-    "eslint-loader": {
-      "version": "2.2.1",
-      "resolved": "https://registry.npmjs.org/eslint-loader/-/eslint-loader-2.2.1.tgz",
-      "integrity": "sha512-RLgV9hoCVsMLvOxCuNjdqOrUqIj9oJg8hF44vzJaYqsAHuY9G2YAeN3joQ9nxP0p5Th9iFSIpKo+SD8KISxXRg==",
-      "dev": true,
-      "requires": {
-        "loader-fs-cache": "^1.0.0",
-        "loader-utils": "^1.0.2",
-        "object-assign": "^4.0.1",
-        "object-hash": "^1.1.4",
-        "rimraf": "^2.6.1"
-      }
-    },
     "eslint-plugin-vue": {
-      "version": "6.2.2",
-      "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-6.2.2.tgz",
-      "integrity": "sha512-Nhc+oVAHm0uz/PkJAWscwIT4ijTrK5fqNqz9QB1D35SbbuMG1uB6Yr5AJpvPSWg+WOw7nYNswerYh0kOk64gqQ==",
+      "version": "7.20.0",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-7.20.0.tgz",
+      "integrity": "sha512-oVNDqzBC9h3GO+NTgWeLMhhGigy6/bQaQbHS+0z7C4YEu/qK/yxHvca/2PTZtGNPsCrHwOTgKMrwu02A9iPBmw==",
       "dev": true,
       "requires": {
+        "eslint-utils": "^2.1.0",
         "natural-compare": "^1.4.0",
-        "semver": "^5.6.0",
-        "vue-eslint-parser": "^7.0.0"
-      },
-      "dependencies": {
-        "semver": {
-          "version": "5.7.1",
-          "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
-          "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
-          "dev": true
-        }
+        "semver": "^6.3.0",
+        "vue-eslint-parser": "^7.10.0"
       }
     },
     "eslint-scope": {
@@ -4917,29 +5966,120 @@
       }
     },
     "eslint-utils": {
-      "version": "1.4.3",
-      "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz",
-      "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==",
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz",
+      "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==",
       "dev": true,
       "requires": {
         "eslint-visitor-keys": "^1.1.0"
+      },
+      "dependencies": {
+        "eslint-visitor-keys": {
+          "version": "1.3.0",
+          "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz",
+          "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==",
+          "dev": true
+        }
       }
     },
     "eslint-visitor-keys": {
-      "version": "1.3.0",
-      "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz",
-      "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==",
+      "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-webpack-plugin": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/eslint-webpack-plugin/-/eslint-webpack-plugin-3.1.1.tgz",
+      "integrity": "sha512-xSucskTN9tOkfW7so4EaiFIkulWLXwCB/15H917lR6pTv0Zot6/fetFucmENRb7J5whVSFKIvwnrnsa78SG2yg==",
+      "dev": true,
+      "requires": {
+        "@types/eslint": "^7.28.2",
+        "jest-worker": "^27.3.1",
+        "micromatch": "^4.0.4",
+        "normalize-path": "^3.0.0",
+        "schema-utils": "^3.1.1"
+      },
+      "dependencies": {
+        "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"
+          }
+        },
+        "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"
+          }
+        },
+        "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
+        },
+        "micromatch": {
+          "version": "4.0.4",
+          "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz",
+          "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==",
+          "dev": true,
+          "requires": {
+            "braces": "^3.0.1",
+            "picomatch": "^2.2.3"
+          }
+        },
+        "schema-utils": {
+          "version": "3.1.1",
+          "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz",
+          "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==",
+          "dev": true,
+          "requires": {
+            "@types/json-schema": "^7.0.8",
+            "ajv": "^6.12.5",
+            "ajv-keywords": "^3.5.2"
+          }
+        },
+        "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"
+          }
+        }
+      }
+    },
     "espree": {
-      "version": "6.2.1",
-      "resolved": "https://registry.npmjs.org/espree/-/espree-6.2.1.tgz",
-      "integrity": "sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw==",
+      "version": "7.3.1",
+      "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz",
+      "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==",
       "dev": true,
       "requires": {
-        "acorn": "^7.1.1",
-        "acorn-jsx": "^5.2.0",
-        "eslint-visitor-keys": "^1.1.0"
+        "acorn": "^7.4.0",
+        "acorn-jsx": "^5.3.1",
+        "eslint-visitor-keys": "^1.3.0"
+      },
+      "dependencies": {
+        "acorn": {
+          "version": "7.4.1",
+          "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz",
+          "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==",
+          "dev": true
+        },
+        "eslint-visitor-keys": {
+          "version": "1.3.0",
+          "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz",
+          "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==",
+          "dev": true
+        }
       }
     },
     "esprima": {
@@ -4958,9 +6098,9 @@
       },
       "dependencies": {
         "estraverse": {
-          "version": "5.2.0",
-          "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz",
-          "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==",
+          "version": "5.3.0",
+          "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+          "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
           "dev": true
         }
       }
@@ -4975,9 +6115,9 @@
       },
       "dependencies": {
         "estraverse": {
-          "version": "5.2.0",
-          "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz",
-          "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==",
+          "version": "5.3.0",
+          "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+          "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
           "dev": true
         }
       }
@@ -5094,69 +6234,6 @@
             "is-extendable": "^0.1.0"
           }
         },
-        "is-accessor-descriptor": {
-          "version": "0.1.6",
-          "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
-          "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=",
-          "dev": true,
-          "requires": {
-            "kind-of": "^3.0.2"
-          },
-          "dependencies": {
-            "kind-of": {
-              "version": "3.2.2",
-              "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-              "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
-              "dev": true,
-              "requires": {
-                "is-buffer": "^1.1.5"
-              }
-            }
-          }
-        },
-        "is-data-descriptor": {
-          "version": "0.1.4",
-          "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
-          "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=",
-          "dev": true,
-          "requires": {
-            "kind-of": "^3.0.2"
-          },
-          "dependencies": {
-            "kind-of": {
-              "version": "3.2.2",
-              "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-              "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
-              "dev": true,
-              "requires": {
-                "is-buffer": "^1.1.5"
-              }
-            }
-          }
-        },
-        "is-descriptor": {
-          "version": "0.1.6",
-          "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
-          "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==",
-          "dev": true,
-          "requires": {
-            "is-accessor-descriptor": "^0.1.6",
-            "is-data-descriptor": "^0.1.4",
-            "kind-of": "^5.0.0"
-          }
-        },
-        "is-extendable": {
-          "version": "0.1.1",
-          "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
-          "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=",
-          "dev": true
-        },
-        "kind-of": {
-          "version": "5.1.0",
-          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
-          "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
-          "dev": true
-        },
         "ms": {
           "version": "2.0.0",
           "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
@@ -5166,17 +6243,17 @@
       }
     },
     "express": {
-      "version": "4.17.1",
-      "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz",
-      "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==",
+      "version": "4.17.2",
+      "resolved": "https://registry.npmjs.org/express/-/express-4.17.2.tgz",
+      "integrity": "sha512-oxlxJxcQlYwqPWKVJJtvQiwHgosH/LrLSPA+H4UxpyvSS6jC5aH+5MoHFM+KABgTOt0APue4w66Ha8jCUo9QGg==",
       "dev": true,
       "requires": {
         "accepts": "~1.3.7",
         "array-flatten": "1.1.1",
-        "body-parser": "1.19.0",
-        "content-disposition": "0.5.3",
+        "body-parser": "1.19.1",
+        "content-disposition": "0.5.4",
         "content-type": "~1.0.4",
-        "cookie": "0.4.0",
+        "cookie": "0.4.1",
         "cookie-signature": "1.0.6",
         "debug": "2.6.9",
         "depd": "~1.1.2",
@@ -5190,13 +6267,13 @@
         "on-finished": "~2.3.0",
         "parseurl": "~1.3.3",
         "path-to-regexp": "0.1.7",
-        "proxy-addr": "~2.0.5",
-        "qs": "6.7.0",
+        "proxy-addr": "~2.0.7",
+        "qs": "6.9.6",
         "range-parser": "~1.2.1",
-        "safe-buffer": "5.1.2",
-        "send": "0.17.1",
-        "serve-static": "1.14.1",
-        "setprototypeof": "1.1.1",
+        "safe-buffer": "5.2.1",
+        "send": "0.17.2",
+        "serve-static": "1.14.2",
+        "setprototypeof": "1.2.0",
         "statuses": "~1.5.0",
         "type-is": "~1.6.18",
         "utils-merge": "1.0.1",
@@ -5219,9 +6296,15 @@
           "dev": true
         },
         "qs": {
-          "version": "6.7.0",
-          "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
-          "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==",
+          "version": "6.9.6",
+          "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.6.tgz",
+          "integrity": "sha512-TIRk4aqYLNoJUbd+g2lEdz5kLWIuTMRagAXxl78Q0RiVjAOugHmeKNGdd3cwo/ktpf9aL9epCfFqWDEKysUlLQ==",
+          "dev": true
+        },
+        "safe-buffer": {
+          "version": "5.2.1",
+          "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+          "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
           "dev": true
         }
       }
@@ -5240,17 +6323,17 @@
       "requires": {
         "assign-symbols": "^1.0.0",
         "is-extendable": "^1.0.1"
-      }
-    },
-    "external-editor": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz",
-      "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==",
-      "dev": true,
-      "requires": {
-        "chardet": "^0.7.0",
-        "iconv-lite": "^0.4.24",
-        "tmp": "^0.0.33"
+      },
+      "dependencies": {
+        "is-extendable": {
+          "version": "1.0.1",
+          "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
+          "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
+          "dev": true,
+          "requires": {
+            "is-plain-object": "^2.0.4"
+          }
+        }
       }
     },
     "extglob": {
@@ -5287,11 +6370,34 @@
             "is-extendable": "^0.1.0"
           }
         },
-        "is-extendable": {
-          "version": "0.1.1",
-          "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
-          "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=",
-          "dev": true
+        "is-accessor-descriptor": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+          "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+          "dev": true,
+          "requires": {
+            "kind-of": "^6.0.0"
+          }
+        },
+        "is-data-descriptor": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+          "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+          "dev": true,
+          "requires": {
+            "kind-of": "^6.0.0"
+          }
+        },
+        "is-descriptor": {
+          "version": "1.0.2",
+          "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+          "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+          "dev": true,
+          "requires": {
+            "is-accessor-descriptor": "^1.0.0",
+            "is-data-descriptor": "^1.0.0",
+            "kind-of": "^6.0.2"
+          }
         }
       }
     },
@@ -5319,6 +6425,29 @@
         "is-glob": "^4.0.0",
         "merge2": "^1.2.3",
         "micromatch": "^3.1.10"
+      },
+      "dependencies": {
+        "glob-parent": {
+          "version": "3.1.0",
+          "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
+          "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=",
+          "dev": true,
+          "requires": {
+            "is-glob": "^3.1.0",
+            "path-dirname": "^1.0.0"
+          },
+          "dependencies": {
+            "is-glob": {
+              "version": "3.1.0",
+              "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
+              "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=",
+              "dev": true,
+              "requires": {
+                "is-extglob": "^2.1.0"
+              }
+            }
+          }
+        }
       }
     },
     "fast-json-stable-stringify": {
@@ -5333,6 +6462,15 @@
       "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
       "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"
+      }
+    },
     "faye-websocket": {
       "version": "0.11.4",
       "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz",
@@ -5348,22 +6486,13 @@
       "integrity": "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==",
       "dev": true
     },
-    "figures": {
-      "version": "3.2.0",
-      "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz",
-      "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==",
-      "dev": true,
-      "requires": {
-        "escape-string-regexp": "^1.0.5"
-      }
-    },
     "file-entry-cache": {
-      "version": "5.0.1",
-      "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz",
-      "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==",
+      "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": "^2.0.1"
+        "flat-cache": "^3.0.4"
       }
     },
     "file-loader": {
@@ -5409,12 +6538,6 @@
           "requires": {
             "is-extendable": "^0.1.0"
           }
-        },
-        "is-extendable": {
-          "version": "0.1.1",
-          "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
-          "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=",
-          "dev": true
         }
       }
     },
@@ -5451,9 +6574,9 @@
       }
     },
     "find-cache-dir": {
-      "version": "3.3.1",
-      "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz",
-      "integrity": "sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==",
+      "version": "3.3.2",
+      "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz",
+      "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==",
       "dev": true,
       "requires": {
         "commondir": "^1.0.1",
@@ -5481,20 +6604,19 @@
       }
     },
     "flat-cache": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz",
-      "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==",
+      "version": "3.0.4",
+      "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz",
+      "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==",
       "dev": true,
       "requires": {
-        "flatted": "^2.0.0",
-        "rimraf": "2.6.3",
-        "write": "1.0.3"
+        "flatted": "^3.1.0",
+        "rimraf": "^3.0.2"
       },
       "dependencies": {
         "rimraf": {
-          "version": "2.6.3",
-          "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz",
-          "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==",
+          "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"
@@ -5503,9 +6625,9 @@
       }
     },
     "flatted": {
-      "version": "2.0.2",
-      "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz",
-      "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==",
+      "version": "3.2.4",
+      "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.4.tgz",
+      "integrity": "sha512-8/sOawo8tJ4QOBX8YlQBMxL8+RLZfxMQOif9o0KUKTNTjMYElWPE0r/m5VNFxTRd0NSw8qSy8dajrwX4RYI1Hw==",
       "dev": true
     },
     "flush-write-stream": {
@@ -5519,9 +6641,9 @@
       }
     },
     "follow-redirects": {
-      "version": "1.14.1",
-      "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.1.tgz",
-      "integrity": "sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg=="
+      "version": "1.14.6",
+      "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.6.tgz",
+      "integrity": "sha512-fhUl5EwSJbbl8AR+uYL2KQDxLkdSjZGR36xy46AO7cOMTrCMON6Sa28FmAnC2tRTDbd/Uuzz3aJBv7EBN7JH8A=="
     },
     "for-in": {
       "version": "1.0.2",
@@ -5578,9 +6700,9 @@
       }
     },
     "fs-extra": {
-      "version": "7.0.1",
-      "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz",
-      "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==",
+      "version": "4.0.3",
+      "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz",
+      "integrity": "sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg==",
       "dev": true,
       "requires": {
         "graceful-fs": "^4.1.2",
@@ -5663,6 +6785,16 @@
         "pump": "^3.0.0"
       }
     },
+    "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"
+      }
+    },
     "get-value": {
       "version": "2.0.6",
       "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz",
@@ -5679,9 +6811,9 @@
       }
     },
     "glob": {
-      "version": "7.1.7",
-      "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz",
-      "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==",
+      "version": "7.2.0",
+      "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
+      "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==",
       "dev": true,
       "requires": {
         "fs.realpath": "^1.0.0",
@@ -5693,24 +6825,12 @@
       }
     },
     "glob-parent": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
-      "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=",
+      "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": "^3.1.0",
-        "path-dirname": "^1.0.0"
-      },
-      "dependencies": {
-        "is-glob": {
-          "version": "3.1.0",
-          "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
-          "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=",
-          "dev": true,
-          "requires": {
-            "is-extglob": "^2.1.0"
-          }
-        }
+        "is-glob": "^4.0.1"
       }
     },
     "glob-to-regexp": {
@@ -5742,9 +6862,9 @@
       }
     },
     "graceful-fs": {
-      "version": "4.2.6",
-      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz",
-      "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==",
+      "version": "4.2.9",
+      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
+      "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
       "dev": true
     },
     "gzip-size": {
@@ -5806,6 +6926,15 @@
       "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==",
       "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"
+      }
+    },
     "has-value": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz",
@@ -5968,6 +7097,14 @@
         "param-case": "2.1.x",
         "relateurl": "0.2.x",
         "uglify-js": "3.4.x"
+      },
+      "dependencies": {
+        "commander": {
+          "version": "2.17.1",
+          "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz",
+          "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==",
+          "dev": true
+        }
       }
     },
     "html-tags": {
@@ -6020,6 +7157,16 @@
             "json5": "^0.5.0",
             "object-assign": "^4.0.1"
           }
+        },
+        "util.promisify": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz",
+          "integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==",
+          "dev": true,
+          "requires": {
+            "define-properties": "^1.1.2",
+            "object.getownpropertydescriptors": "^2.0.3"
+          }
         }
       }
     },
@@ -6033,6 +7180,36 @@
         "domhandler": "^4.0.0",
         "domutils": "^2.5.2",
         "entities": "^2.0.0"
+      },
+      "dependencies": {
+        "dom-serializer": {
+          "version": "1.3.2",
+          "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz",
+          "integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==",
+          "dev": true,
+          "requires": {
+            "domelementtype": "^2.0.1",
+            "domhandler": "^4.2.0",
+            "entities": "^2.0.0"
+          }
+        },
+        "domelementtype": {
+          "version": "2.2.0",
+          "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz",
+          "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==",
+          "dev": true
+        },
+        "domutils": {
+          "version": "2.8.0",
+          "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz",
+          "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==",
+          "dev": true,
+          "requires": {
+            "dom-serializer": "^1.0.1",
+            "domelementtype": "^2.2.0",
+            "domhandler": "^4.2.0"
+          }
+        }
       }
     },
     "http-deceiver": {
@@ -6042,30 +7219,22 @@
       "dev": true
     },
     "http-errors": {
-      "version": "1.7.2",
-      "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz",
-      "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==",
+      "version": "1.8.1",
+      "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz",
+      "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==",
       "dev": true,
       "requires": {
         "depd": "~1.1.2",
-        "inherits": "2.0.3",
-        "setprototypeof": "1.1.1",
+        "inherits": "2.0.4",
+        "setprototypeof": "1.2.0",
         "statuses": ">= 1.5.0 < 2",
-        "toidentifier": "1.0.0"
-      },
-      "dependencies": {
-        "inherits": {
-          "version": "2.0.3",
-          "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
-          "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
-          "dev": true
-        }
+        "toidentifier": "1.0.1"
       }
     },
     "http-parser-js": {
-      "version": "0.5.3",
-      "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.3.tgz",
-      "integrity": "sha512-t7hjvef/5HEK7RWTdUzVUhl8zkEu+LlaE0IYzdMuvbSDipxBRpOn4Uhw8ZyECEa808iVT8XCjzo6xmYt4CiLZg==",
+      "version": "0.5.5",
+      "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.5.tgz",
+      "integrity": "sha512-x+JVEkO2PoM8qqpbPbOL3cqHPwerep7OwzK7Ay+sMQjKzaKCqWvjoXm5tqMP9tXWWTnTzAjIhXg+J99XYuPhPA==",
       "dev": true
     },
     "http-proxy": {
@@ -6319,110 +7488,6 @@
       "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
       "dev": true
     },
-    "inquirer": {
-      "version": "7.3.3",
-      "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.3.3.tgz",
-      "integrity": "sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==",
-      "dev": true,
-      "requires": {
-        "ansi-escapes": "^4.2.1",
-        "chalk": "^4.1.0",
-        "cli-cursor": "^3.1.0",
-        "cli-width": "^3.0.0",
-        "external-editor": "^3.0.3",
-        "figures": "^3.0.0",
-        "lodash": "^4.17.19",
-        "mute-stream": "0.0.8",
-        "run-async": "^2.4.0",
-        "rxjs": "^6.6.0",
-        "string-width": "^4.1.0",
-        "strip-ansi": "^6.0.0",
-        "through": "^2.3.6"
-      },
-      "dependencies": {
-        "ansi-regex": {
-          "version": "5.0.0",
-          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
-          "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
-          "dev": true
-        },
-        "ansi-styles": {
-          "version": "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"
-          }
-        },
-        "chalk": {
-          "version": "4.1.1",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz",
-          "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==",
-          "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
-        },
-        "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
-        },
-        "is-fullwidth-code-point": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
-          "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
-          "dev": true
-        },
-        "string-width": {
-          "version": "4.2.2",
-          "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz",
-          "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==",
-          "dev": true,
-          "requires": {
-            "emoji-regex": "^8.0.0",
-            "is-fullwidth-code-point": "^3.0.0",
-            "strip-ansi": "^6.0.0"
-          }
-        },
-        "strip-ansi": {
-          "version": "6.0.0",
-          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
-          "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
-          "dev": true,
-          "requires": {
-            "ansi-regex": "^5.0.0"
-          }
-        },
-        "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"
-          }
-        }
-      }
-    },
     "internal-ip": {
       "version": "4.3.0",
       "resolved": "https://registry.npmjs.org/internal-ip/-/internal-ip-4.3.0.tgz",
@@ -6445,6 +7510,17 @@
         }
       }
     },
+    "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"
+      }
+    },
     "ip": {
       "version": "1.1.5",
       "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz",
@@ -6470,21 +7546,33 @@
       "dev": true
     },
     "is-accessor-descriptor": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
-      "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+      "version": "0.1.6",
+      "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
+      "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=",
       "dev": true,
       "requires": {
-        "kind-of": "^6.0.0"
+        "kind-of": "^3.0.2"
+      },
+      "dependencies": {
+        "kind-of": {
+          "version": "3.2.2",
+          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+          "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+          "dev": true,
+          "requires": {
+            "is-buffer": "^1.1.5"
+          }
+        }
       }
     },
     "is-arguments": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.0.tgz",
-      "integrity": "sha512-1Ij4lOMPl/xB5kBDn7I+b2ttPMKa8szhEIrXDuXQD/oe3HJLTLhqhgGspwgyGd6MOywBUqVvYicF72lkgDnIHg==",
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz",
+      "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==",
       "dev": true,
       "requires": {
-        "call-bind": "^1.0.0"
+        "call-bind": "^1.0.2",
+        "has-tostringtag": "^1.0.0"
       }
     },
     "is-arrayish": {
@@ -6494,10 +7582,13 @@
       "dev": true
     },
     "is-bigint": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.2.tgz",
-      "integrity": "sha512-0JV5+SOCQkIdzjBK9buARcV804Ddu7A0Qet6sHi3FimE9ne6m4BGQZfRn+NZiXbBk4F4XmHfDZIipLj9pX8dSA==",
-      "dev": true
+      "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-binary-path": {
       "version": "2.1.0",
@@ -6510,12 +7601,13 @@
       }
     },
     "is-boolean-object": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.1.tgz",
-      "integrity": "sha512-bXdQWkECBUIAcCkeH1unwJLIpZYaa5VvuygSyS/c2lf719mTKZDU5UdDRlpd01UjADgmW8RfqaP+mRaVPdr/Ng==",
+      "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"
+        "call-bind": "^1.0.2",
+        "has-tostringtag": "^1.0.0"
       }
     },
     "is-buffer": {
@@ -6525,9 +7617,9 @@
       "dev": true
     },
     "is-callable": {
-      "version": "1.2.3",
-      "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz",
-      "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==",
+      "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-ci": {
@@ -6554,38 +7646,60 @@
       }
     },
     "is-core-module": {
-      "version": "2.4.0",
-      "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.4.0.tgz",
-      "integrity": "sha512-6A2fkfq1rfeQZjxrZJGerpLCTHRNEBiSgnu0+obeJpEPZRUooHgsizvzv0ZjJwOz3iWIHdJtVWJ/tmPr3D21/A==",
+      "version": "2.8.1",
+      "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz",
+      "integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==",
       "dev": true,
       "requires": {
         "has": "^1.0.3"
       }
     },
-    "is-data-descriptor": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
-      "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+    "is-data-descriptor": {
+      "version": "0.1.4",
+      "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
+      "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=",
+      "dev": true,
+      "requires": {
+        "kind-of": "^3.0.2"
+      },
+      "dependencies": {
+        "kind-of": {
+          "version": "3.2.2",
+          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+          "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+          "dev": true,
+          "requires": {
+            "is-buffer": "^1.1.5"
+          }
+        }
+      }
+    },
+    "is-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": {
-        "kind-of": "^6.0.0"
+        "has-tostringtag": "^1.0.0"
       }
     },
-    "is-date-object": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.4.tgz",
-      "integrity": "sha512-/b4ZVsG7Z5XVtIxs/h9W8nvfLgSAyKYdtGWQLbqy6jA1icmgjf8WCoTKgeS4wy5tYaPePouzFMANbnj94c2Z+A==",
-      "dev": true
-    },
     "is-descriptor": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
-      "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+      "version": "0.1.6",
+      "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
+      "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==",
       "dev": true,
       "requires": {
-        "is-accessor-descriptor": "^1.0.0",
-        "is-data-descriptor": "^1.0.0",
-        "kind-of": "^6.0.2"
+        "is-accessor-descriptor": "^0.1.6",
+        "is-data-descriptor": "^0.1.4",
+        "kind-of": "^5.0.0"
+      },
+      "dependencies": {
+        "kind-of": {
+          "version": "5.1.0",
+          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
+          "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
+          "dev": true
+        }
       }
     },
     "is-directory": {
@@ -6601,13 +7715,10 @@
       "dev": true
     },
     "is-extendable": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
-      "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
-      "dev": true,
-      "requires": {
-        "is-plain-object": "^2.0.4"
-      }
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
+      "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=",
+      "dev": true
     },
     "is-extglob": {
       "version": "2.1.1",
@@ -6616,24 +7727,30 @@
       "dev": true
     },
     "is-fullwidth-code-point": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
-      "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+      "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
       "dev": true
     },
     "is-glob": {
-      "version": "4.0.1",
-      "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
-      "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
+      "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-interactive": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz",
+      "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==",
+      "dev": true
+    },
     "is-negative-zero": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz",
-      "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==",
+      "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": {
@@ -6657,10 +7774,13 @@
       }
     },
     "is-number-object": {
-      "version": "1.0.5",
-      "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.5.tgz",
-      "integrity": "sha512-RU0lI/n95pMoUKu9v1BZP5MBcZuNSVJkMkAG2dJqC4z2GlkGUNeH68SuHuBKBD/XFe+LHZ+f9BKkLET60Niedw==",
-      "dev": true
+      "version": "1.0.6",
+      "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.6.tgz",
+      "integrity": "sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==",
+      "dev": true,
+      "requires": {
+        "has-tostringtag": "^1.0.0"
+      }
     },
     "is-obj": {
       "version": "1.0.1",
@@ -6708,13 +7828,13 @@
       }
     },
     "is-regex": {
-      "version": "1.1.3",
-      "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.3.tgz",
-      "integrity": "sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ==",
+      "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-symbols": "^1.0.2"
+        "has-tostringtag": "^1.0.0"
       }
     },
     "is-regexp": {
@@ -6729,6 +7849,12 @@
       "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==",
       "dev": true
     },
+    "is-shared-array-buffer": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz",
+      "integrity": "sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA==",
+      "dev": true
+    },
     "is-stream": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
@@ -6736,10 +7862,13 @@
       "dev": true
     },
     "is-string": {
-      "version": "1.0.6",
-      "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.6.tgz",
-      "integrity": "sha512-2gdzbKUuqtQ3lYNrUTQYoClPhm7oQu4UdpSZMp1/DGgkHBT8E2Z1l0yMdb6D4zNAxwDiMv8MdulKROJGNl0Q0w==",
-      "dev": true
+      "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",
@@ -6756,6 +7885,21 @@
       "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=",
       "dev": true
     },
+    "is-unicode-supported": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
+      "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==",
+      "dev": true
+    },
+    "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"
+      }
+    },
     "is-what": {
       "version": "3.14.1",
       "resolved": "https://registry.npmjs.org/is-what/-/is-what-3.14.1.tgz",
@@ -6769,13 +7913,10 @@
       "dev": true
     },
     "is-wsl": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
-      "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==",
-      "dev": true,
-      "requires": {
-        "is-docker": "^2.0.0"
-      }
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz",
+      "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=",
+      "dev": true
     },
     "isarray": {
       "version": "1.0.0",
@@ -6807,6 +7948,64 @@
       "integrity": "sha512-JVAfqNPTvNq3sB/VHQJAFxN/sPgKnsKrCwyRt15zwNCdrMMJDdcEOdubuy+DuJYYdm0ox1J4uzEuYKkN+9yhVg==",
       "dev": true
     },
+    "jest-worker": {
+      "version": "27.4.6",
+      "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.4.6.tgz",
+      "integrity": "sha512-gHWJF/6Xi5CTG5QCvROr6GcmpIqNYpDJyc8A1h/DyXqH1tD6SnRCM0d3U5msV31D2LB/U+E0M+W4oyvKV44oNw==",
+      "dev": true,
+      "requires": {
+        "@types/node": "*",
+        "merge-stream": "^2.0.0",
+        "supports-color": "^8.0.0"
+      },
+      "dependencies": {
+        "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
+        },
+        "supports-color": {
+          "version": "8.1.1",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
+          "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
+          "dev": true,
+          "requires": {
+            "has-flag": "^4.0.0"
+          }
+        }
+      }
+    },
+    "joi": {
+      "version": "17.5.0",
+      "resolved": "https://registry.npmjs.org/joi/-/joi-17.5.0.tgz",
+      "integrity": "sha512-R7hR50COp7StzLnDi4ywOXHrBrgNXuUUfJWIR5lPY5Bm/pOD3jZaTwpluUXVLRWcoWZxkrHBBJ5hLxgnlehbdw==",
+      "dev": true,
+      "requires": {
+        "@hapi/hoek": "^9.0.0",
+        "@hapi/topo": "^5.0.0",
+        "@sideway/address": "^4.1.3",
+        "@sideway/formula": "^3.0.0",
+        "@sideway/pinpoint": "^2.0.0"
+      },
+      "dependencies": {
+        "@hapi/hoek": {
+          "version": "9.2.1",
+          "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.2.1.tgz",
+          "integrity": "sha512-gfta+H8aziZsm8pZa0vj04KO6biEiisppNgA1kbJvFrrWu9Vm7eaUEy76DIxsuTaWvti5fkJVhllWc6ZTE+Mdw==",
+          "dev": true
+        },
+        "@hapi/topo": {
+          "version": "5.1.0",
+          "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz",
+          "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==",
+          "dev": true,
+          "requires": {
+            "@hapi/hoek": "^9.0.0"
+          }
+        }
+      }
+    },
     "js-message": {
       "version": "1.0.7",
       "resolved": "https://registry.npmjs.org/js-message/-/js-message-1.0.7.tgz",
@@ -6863,9 +8062,9 @@
       "dev": true
     },
     "json-schema": {
-      "version": "0.2.3",
-      "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
-      "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=",
+      "version": "0.4.0",
+      "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz",
+      "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==",
       "dev": true
     },
     "json-schema-traverse": {
@@ -6926,14 +8125,14 @@
       "dev": true
     },
     "jsprim": {
-      "version": "1.4.1",
-      "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
-      "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=",
+      "version": "1.4.2",
+      "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz",
+      "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==",
       "dev": true,
       "requires": {
         "assert-plus": "1.0.0",
         "extsprintf": "1.3.0",
-        "json-schema": "0.2.3",
+        "json-schema": "0.4.0",
         "verror": "1.10.0"
       }
     },
@@ -6950,28 +8149,28 @@
       "dev": true
     },
     "launch-editor": {
-      "version": "2.2.1",
-      "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.2.1.tgz",
-      "integrity": "sha512-On+V7K2uZK6wK7x691ycSUbLD/FyKKelArkbaAMSSJU8JmqmhwN2+mnJDNINuJWSrh2L0kDk+ZQtbC/gOWUwLw==",
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.3.0.tgz",
+      "integrity": "sha512-3QrsCXejlWYHjBPFXTyGNhPj4rrQdB+5+r5r3wArpLH201aR+nWUgw/zKKkTmilCfY/sv6u8qo98pNvtg8LUTA==",
       "dev": true,
       "requires": {
-        "chalk": "^2.3.0",
+        "picocolors": "^1.0.0",
         "shell-quote": "^1.6.1"
       }
     },
     "launch-editor-middleware": {
-      "version": "2.2.1",
-      "resolved": "https://registry.npmjs.org/launch-editor-middleware/-/launch-editor-middleware-2.2.1.tgz",
-      "integrity": "sha512-s0UO2/gEGiCgei3/2UN3SMuUj1phjQN8lcpnvgLSz26fAzNWPQ6Nf/kF5IFClnfU2ehp6LrmKdMU/beveO+2jg==",
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/launch-editor-middleware/-/launch-editor-middleware-2.3.0.tgz",
+      "integrity": "sha512-GJR64trLdFFwCoL9DMn/d1SZX0OzTDPixu4mcfWTShQ4tIqCHCGvlg9fOEYQXyBlrSMQwylsJfUWncheShfV2w==",
       "dev": true,
       "requires": {
-        "launch-editor": "^2.2.1"
+        "launch-editor": "^2.3.0"
       }
     },
     "leaflet": {
-      "version": "1.5.1",
-      "resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.5.1.tgz",
-      "integrity": "sha512-ekM9KAeG99tYisNBg0IzEywAlp0hYI5XRipsqRXyRTeuU8jcuntilpp+eFf5gaE0xubc9RuSNIVtByEKwqFV0w=="
+      "version": "1.7.1",
+      "resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.7.1.tgz",
+      "integrity": "sha512-/xwPEBidtg69Q3HlqPdU3DnrXQOvQU/CCHA1tcDQVzOwm91YMYaILjNp7L4Eaw5Z4sOYdbBz6koWyibppd8Zqw=="
     },
     "leaflet-draw": {
       "version": "1.0.4",
@@ -7060,72 +8259,21 @@
       }
     },
     "levn": {
-      "version": "0.3.0",
-      "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
-      "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=",
+      "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.1.2",
-        "type-check": "~0.3.2"
+        "prelude-ls": "^1.2.1",
+        "type-check": "~0.4.0"
       }
     },
     "lines-and-columns": {
-      "version": "1.1.6",
-      "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz",
-      "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=",
+      "version": "1.2.4",
+      "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
+      "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
       "dev": true
     },
-    "loader-fs-cache": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/loader-fs-cache/-/loader-fs-cache-1.0.3.tgz",
-      "integrity": "sha512-ldcgZpjNJj71n+2Mf6yetz+c9bM4xpKtNds4LbqXzU/PTdeAX0g3ytnU1AJMEcTk2Lex4Smpe3Q/eCTsvUBxbA==",
-      "dev": true,
-      "requires": {
-        "find-cache-dir": "^0.1.1",
-        "mkdirp": "^0.5.1"
-      },
-      "dependencies": {
-        "find-cache-dir": {
-          "version": "0.1.1",
-          "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-0.1.1.tgz",
-          "integrity": "sha1-yN765XyKUqinhPnjHFfHQumToLk=",
-          "dev": true,
-          "requires": {
-            "commondir": "^1.0.1",
-            "mkdirp": "^0.5.1",
-            "pkg-dir": "^1.0.0"
-          }
-        },
-        "find-up": {
-          "version": "1.1.2",
-          "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz",
-          "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=",
-          "dev": true,
-          "requires": {
-            "path-exists": "^2.0.0",
-            "pinkie-promise": "^2.0.0"
-          }
-        },
-        "path-exists": {
-          "version": "2.1.0",
-          "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz",
-          "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=",
-          "dev": true,
-          "requires": {
-            "pinkie-promise": "^2.0.0"
-          }
-        },
-        "pkg-dir": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz",
-          "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=",
-          "dev": true,
-          "requires": {
-            "find-up": "^1.0.0"
-          }
-        }
-      }
-    },
     "loader-runner": {
       "version": "2.4.0",
       "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz",
@@ -7223,6 +8371,12 @@
       "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=",
       "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
+    },
     "lodash.template": {
       "version": "4.5.0",
       "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz",
@@ -7248,6 +8402,12 @@
       "integrity": "sha1-EjBkIvYzJK7YSD0/ODMrX2cFR6A=",
       "dev": true
     },
+    "lodash.truncate": {
+      "version": "4.4.2",
+      "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz",
+      "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=",
+      "dev": true
+    },
     "lodash.uniq": {
       "version": "4.5.0",
       "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz",
@@ -7264,9 +8424,9 @@
       }
     },
     "loglevel": {
-      "version": "1.7.1",
-      "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.7.1.tgz",
-      "integrity": "sha512-Hesni4s5UkWkwCGJMQGAh71PaLUmKFM60dHvq0zi/vDhhrzuk+4GgNbTXJ12YYQJn6ZKBDNIjYcuQGKudvqrIw==",
+      "version": "1.8.0",
+      "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.8.0.tgz",
+      "integrity": "sha512-G6A/nJLRgWOuuwdNuA6koovfEV1YpqqAG4pRUlFaz3jj2QNZ8M4vBqnVA+HBTmU/AMNUtlOsMmSpF6NyOjztbA==",
       "dev": true
     },
     "lower-case": {
@@ -7422,30 +8582,30 @@
       }
     },
     "mime": {
-      "version": "2.5.2",
-      "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.2.tgz",
-      "integrity": "sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==",
+      "version": "2.6.0",
+      "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz",
+      "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==",
       "dev": true
     },
     "mime-db": {
-      "version": "1.48.0",
-      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.48.0.tgz",
-      "integrity": "sha512-FM3QwxV+TnZYQ2aRqhlKBMHxk10lTbMt3bBkMAp54ddrNeVSfcQYOOKuGuy3Ddrm38I04If834fOUSq1yzslJQ==",
+      "version": "1.51.0",
+      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz",
+      "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==",
       "dev": true
     },
     "mime-types": {
-      "version": "2.1.31",
-      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.31.tgz",
-      "integrity": "sha512-XGZnNzm3QvgKxa8dpzyhFTHmpP3l5YNusmne07VUOXxou9CqUqYa/HBy124RqtVh/O2pECas/MOcsDgpilPOPg==",
+      "version": "2.1.34",
+      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz",
+      "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==",
       "dev": true,
       "requires": {
-        "mime-db": "1.48.0"
+        "mime-db": "1.51.0"
       }
     },
     "mimic-fn": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
-      "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz",
+      "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==",
       "dev": true
     },
     "mini-css-extract-plugin": {
@@ -7460,6 +8620,18 @@
         "webpack-sources": "^1.1.0"
       },
       "dependencies": {
+        "normalize-url": {
+          "version": "1.9.1",
+          "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-1.9.1.tgz",
+          "integrity": "sha1-LMDWazHqIwNkWENuNiDYWVTGbDw=",
+          "dev": true,
+          "requires": {
+            "object-assign": "^4.0.1",
+            "prepend-http": "^1.0.0",
+            "query-string": "^4.1.0",
+            "sort-keys": "^1.0.0"
+          }
+        },
         "schema-utils": {
           "version": "1.0.0",
           "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz",
@@ -7501,9 +8673,9 @@
       "dev": true
     },
     "minipass": {
-      "version": "3.1.3",
-      "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.3.tgz",
-      "integrity": "sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==",
+      "version": "3.1.6",
+      "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.6.tgz",
+      "integrity": "sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ==",
       "dev": true,
       "requires": {
         "yallist": "^4.0.0"
@@ -7543,6 +8715,17 @@
       "requires": {
         "for-in": "^1.0.2",
         "is-extendable": "^1.0.1"
+      },
+      "dependencies": {
+        "is-extendable": {
+          "version": "1.0.1",
+          "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
+          "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
+          "dev": true,
+          "requires": {
+            "is-plain-object": "^2.0.4"
+          }
+        }
       }
     },
     "mkdirp": {
@@ -7590,12 +8773,6 @@
       "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=",
       "dev": true
     },
-    "mute-stream": {
-      "version": "0.0.8",
-      "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz",
-      "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==",
-      "dev": true
-    },
     "mz": {
       "version": "2.7.0",
       "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
@@ -7608,9 +8785,9 @@
       }
     },
     "nan": {
-      "version": "2.14.2",
-      "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz",
-      "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==",
+      "version": "2.15.0",
+      "resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz",
+      "integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==",
       "dev": true,
       "optional": true
     },
@@ -7634,9 +8811,9 @@
       }
     },
     "native-request": {
-      "version": "1.0.8",
-      "resolved": "https://registry.npmjs.org/native-request/-/native-request-1.0.8.tgz",
-      "integrity": "sha512-vU2JojJVelUGp6jRcLwToPoWGxSx23z/0iX+I77J3Ht17rf2INGjrhOoQnjVo60nQd8wVsgzKkPfRXBiVdD2ag==",
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/native-request/-/native-request-1.1.0.tgz",
+      "integrity": "sha512-uZ5rQaeRn15XmpgE0xoPL8YWqcX90VtCFglYwAgkvKM5e8fog+vePLAhHxuuv/gRkrQxIeh5U3q9sMNUrENqWw==",
       "dev": true,
       "optional": true
     },
@@ -7673,6 +8850,15 @@
         "lower-case": "^1.1.1"
       }
     },
+    "node-fetch": {
+      "version": "2.6.6",
+      "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.6.tgz",
+      "integrity": "sha512-Z8/6vRlTUChSdIgMa51jxQ4lrw/Jy5SOW10ObaA47/RElsAN2c5Pn8bTgFGWn/ibwzXTE8qwr1Yzx28vsecXEA==",
+      "dev": true,
+      "requires": {
+        "whatwg-url": "^5.0.0"
+      }
+    },
     "node-forge": {
       "version": "0.10.0",
       "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz",
@@ -7730,9 +8916,9 @@
       }
     },
     "node-releases": {
-      "version": "1.1.73",
-      "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.73.tgz",
-      "integrity": "sha512-uW7fodD6pyW2FZNZnp/Z3hvWKeEW1Y8R1+1CnErE8cXFXzl5blBOoVB41CvMer6P6Q0S5FXDwcHgFd1Wj0U9zg==",
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.1.tgz",
+      "integrity": "sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA==",
       "dev": true
     },
     "normalize-package-data": {
@@ -7768,16 +8954,10 @@
       "dev": true
     },
     "normalize-url": {
-      "version": "1.9.1",
-      "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-1.9.1.tgz",
-      "integrity": "sha1-LMDWazHqIwNkWENuNiDYWVTGbDw=",
-      "dev": true,
-      "requires": {
-        "object-assign": "^4.0.1",
-        "prepend-http": "^1.0.0",
-        "query-string": "^4.1.0",
-        "sort-keys": "^1.0.0"
-      }
+      "version": "3.3.0",
+      "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-3.3.0.tgz",
+      "integrity": "sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg==",
+      "dev": true
     },
     "npm-run-path": {
       "version": "2.0.2",
@@ -7789,12 +8969,12 @@
       }
     },
     "nth-check": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.0.tgz",
-      "integrity": "sha512-i4sc/Kj8htBrAiH1viZ0TgU8Y5XqCaV/FziYK6TBczxmeKm3AEFWqqF3195yKudrarqy7Zu80Ra5dobFjn9X/Q==",
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz",
+      "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==",
       "dev": true,
       "requires": {
-        "boolbase": "^1.0.0"
+        "boolbase": "~1.0.0"
       }
     },
     "num2fraction": {
@@ -7835,43 +9015,6 @@
             "is-descriptor": "^0.1.0"
           }
         },
-        "is-accessor-descriptor": {
-          "version": "0.1.6",
-          "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
-          "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=",
-          "dev": true,
-          "requires": {
-            "kind-of": "^3.0.2"
-          }
-        },
-        "is-data-descriptor": {
-          "version": "0.1.4",
-          "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
-          "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=",
-          "dev": true,
-          "requires": {
-            "kind-of": "^3.0.2"
-          }
-        },
-        "is-descriptor": {
-          "version": "0.1.6",
-          "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
-          "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==",
-          "dev": true,
-          "requires": {
-            "is-accessor-descriptor": "^0.1.6",
-            "is-data-descriptor": "^0.1.4",
-            "kind-of": "^5.0.0"
-          },
-          "dependencies": {
-            "kind-of": {
-              "version": "5.1.0",
-              "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
-              "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
-              "dev": true
-            }
-          }
-        },
         "kind-of": {
           "version": "3.2.2",
           "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
@@ -7883,16 +9026,10 @@
         }
       }
     },
-    "object-hash": {
-      "version": "1.3.1",
-      "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-1.3.1.tgz",
-      "integrity": "sha512-OSuu/pU4ENM9kmREg0BdNrUDIl1heYa4mBZacJc+vVWz4GtAwu7jO8s4AIt2aGRUTqxykpWzI3Oqnsm13tTMDA==",
-      "dev": true
-    },
     "object-inspect": {
-      "version": "1.10.3",
-      "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.10.3.tgz",
-      "integrity": "sha512-e5mCJlSH7poANfC8z8S9s9S2IN5/4Zb3aZ33f5s8YqoazCFzNLloLU8r5VCG+G7WoqLvAAZoVMcy3tp/3X0Plw==",
+      "version": "1.12.0",
+      "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz",
+      "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==",
       "dev": true
     },
     "object-is": {
@@ -7933,14 +9070,14 @@
       }
     },
     "object.getownpropertydescriptors": {
-      "version": "2.1.2",
-      "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.2.tgz",
-      "integrity": "sha512-WtxeKSzfBjlzL+F9b7M7hewDzMwy+C8NRssHd1YrNlzHzIDrXcXiNOMrezdAEM4UXixgV+vvnyBeN7Rygl2ttQ==",
+      "version": "2.1.3",
+      "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.3.tgz",
+      "integrity": "sha512-VdDoCwvJI4QdC6ndjpqFmoL3/+HxffFBbcJzKi5hwLLqqx3mdbedRpfZDdK0SrOSauj8X4GzBvnDZl4vTN7dOw==",
       "dev": true,
       "requires": {
         "call-bind": "^1.0.2",
         "define-properties": "^1.1.3",
-        "es-abstract": "^1.18.0-next.2"
+        "es-abstract": "^1.19.1"
       }
     },
     "object.pick": {
@@ -7953,14 +9090,14 @@
       }
     },
     "object.values": {
-      "version": "1.1.4",
-      "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.4.tgz",
-      "integrity": "sha512-TnGo7j4XSnKQoK3MfvkzqKCi0nVe/D9I9IjwTNYdb/fxYHpjrluHVOgw0AF6jrRFGMPHdfuidR09tIDiIvnaSg==",
+      "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.18.2"
+        "es-abstract": "^1.19.1"
       }
     },
     "obuf": {
@@ -7994,12 +9131,12 @@
       }
     },
     "onetime": {
-      "version": "5.1.2",
-      "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
-      "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz",
+      "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=",
       "dev": true,
       "requires": {
-        "mimic-fn": "^2.1.0"
+        "mimic-fn": "^1.0.0"
       }
     },
     "open": {
@@ -8009,14 +9146,6 @@
       "dev": true,
       "requires": {
         "is-wsl": "^1.1.0"
-      },
-      "dependencies": {
-        "is-wsl": {
-          "version": "1.1.0",
-          "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz",
-          "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=",
-          "dev": true
-        }
       }
     },
     "opener": {
@@ -8032,28 +9161,20 @@
       "dev": true,
       "requires": {
         "is-wsl": "^1.1.0"
-      },
-      "dependencies": {
-        "is-wsl": {
-          "version": "1.1.0",
-          "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz",
-          "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=",
-          "dev": true
-        }
       }
     },
     "optionator": {
-      "version": "0.8.3",
-      "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz",
-      "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==",
+      "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.3.0",
-        "prelude-ls": "~1.1.2",
-        "type-check": "~0.3.2",
-        "word-wrap": "~1.2.3"
+        "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"
       }
     },
     "ora": {
@@ -8064,44 +9185,19 @@
       "requires": {
         "chalk": "^2.4.2",
         "cli-cursor": "^2.1.0",
-        "cli-spinners": "^2.0.0",
-        "log-symbols": "^2.2.0",
-        "strip-ansi": "^5.2.0",
-        "wcwidth": "^1.0.1"
-      },
-      "dependencies": {
-        "cli-cursor": {
-          "version": "2.1.0",
-          "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz",
-          "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=",
-          "dev": true,
-          "requires": {
-            "restore-cursor": "^2.0.0"
-          }
-        },
-        "mimic-fn": {
-          "version": "1.2.0",
-          "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz",
-          "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==",
-          "dev": true
-        },
-        "onetime": {
-          "version": "2.0.1",
-          "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz",
-          "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=",
-          "dev": true,
-          "requires": {
-            "mimic-fn": "^1.0.0"
-          }
-        },
-        "restore-cursor": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz",
-          "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=",
+        "cli-spinners": "^2.0.0",
+        "log-symbols": "^2.2.0",
+        "strip-ansi": "^5.2.0",
+        "wcwidth": "^1.0.1"
+      },
+      "dependencies": {
+        "strip-ansi": {
+          "version": "5.2.0",
+          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
+          "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
           "dev": true,
           "requires": {
-            "onetime": "^2.0.0",
-            "signal-exit": "^3.0.2"
+            "ansi-regex": "^4.1.0"
           }
         }
       }
@@ -8121,12 +9217,6 @@
       "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=",
       "dev": true
     },
-    "os-tmpdir": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
-      "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
-      "dev": true
-    },
     "p-finally": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
@@ -8229,13 +9319,15 @@
       }
     },
     "parse-json": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
-      "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=",
+      "version": "5.2.0",
+      "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
+      "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
       "dev": true,
       "requires": {
+        "@babel/code-frame": "^7.0.0",
         "error-ex": "^1.3.1",
-        "json-parse-better-errors": "^1.0.1"
+        "json-parse-even-better-errors": "^2.3.0",
+        "lines-and-columns": "^1.1.6"
       }
     },
     "parse5": {
@@ -8366,10 +9458,16 @@
       "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=",
       "dev": true
     },
+    "picocolors": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
+      "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
+      "dev": true
+    },
     "picomatch": {
-      "version": "2.3.0",
-      "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz",
-      "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==",
+      "version": "2.3.1",
+      "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+      "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
       "dev": true
     },
     "pify": {
@@ -8403,9 +9501,9 @@
       }
     },
     "pnp-webpack-plugin": {
-      "version": "1.6.4",
-      "resolved": "https://registry.npmjs.org/pnp-webpack-plugin/-/pnp-webpack-plugin-1.6.4.tgz",
-      "integrity": "sha512-7Wjy+9E3WwLOEL30D+m8TSTF7qJJUJLONBnwQp0518siuMxUQUbgZwssaFX+QKlZkjHZcw/IpZCt/H0srrntSg==",
+      "version": "1.7.0",
+      "resolved": "https://registry.npmjs.org/pnp-webpack-plugin/-/pnp-webpack-plugin-1.7.0.tgz",
+      "integrity": "sha512-2Rb3vm+EXble/sMXNSu6eoBx8e79gKqhNq9F5ZWW6ERNCTE/Q0wQNne5541tE5vKjfM8hpNCYL+LGc1YTfI0dg==",
       "dev": true,
       "requires": {
         "ts-pnp": "^1.1.6"
@@ -8445,30 +9543,26 @@
       "dev": true
     },
     "postcss": {
-      "version": "7.0.36",
-      "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
-      "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
+      "version": "7.0.39",
+      "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz",
+      "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==",
       "dev": true,
       "requires": {
-        "chalk": "^2.4.2",
-        "source-map": "^0.6.1",
-        "supports-color": "^6.1.0"
+        "picocolors": "^0.2.1",
+        "source-map": "^0.6.1"
       },
       "dependencies": {
+        "picocolors": {
+          "version": "0.2.1",
+          "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz",
+          "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==",
+          "dev": true
+        },
         "source-map": {
           "version": "0.6.1",
           "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
           "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
           "dev": true
-        },
-        "supports-color": {
-          "version": "6.1.0",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
-          "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
-          "dev": true,
-          "requires": {
-            "has-flag": "^3.0.0"
-          }
         }
       }
     },
@@ -8903,12 +9997,6 @@
         "postcss-value-parser": "^3.0.0"
       },
       "dependencies": {
-        "normalize-url": {
-          "version": "3.3.0",
-          "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-3.3.0.tgz",
-          "integrity": "sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg==",
-          "dev": true
-        },
         "postcss-value-parser": {
           "version": "3.3.1",
           "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz",
@@ -8987,9 +10075,9 @@
       }
     },
     "postcss-selector-parser": {
-      "version": "6.0.6",
-      "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.6.tgz",
-      "integrity": "sha512-9LXrvaaX3+mcv5xkg5kFwqSzSH1JIObIx51PrndZwlmznwXRfxMddDvo9gve3gVR8ZTKgoFDdWkbRFmEhT4PMg==",
+      "version": "6.0.8",
+      "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.8.tgz",
+      "integrity": "sha512-D5PG53d209Z1Uhcc0qAZ5U3t5HagH3cxu+WLZ22jt3gLUpXM4eXXfiO14jiDWST3NNooX/E8wISfOhZ9eIjGTQ==",
       "dev": true,
       "requires": {
         "cssesc": "^3.0.0",
@@ -9027,15 +10115,15 @@
       }
     },
     "postcss-value-parser": {
-      "version": "4.1.0",
-      "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz",
-      "integrity": "sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==",
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
+      "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
       "dev": true
     },
     "prelude-ls": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
-      "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=",
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+      "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
       "dev": true
     },
     "prepend-http": {
@@ -9045,9 +10133,9 @@
       "dev": true
     },
     "prettier": {
-      "version": "1.19.1",
-      "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.19.1.tgz",
-      "integrity": "sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew==",
+      "version": "2.5.1",
+      "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.5.1.tgz",
+      "integrity": "sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==",
       "dev": true,
       "optional": true
     },
@@ -9225,6 +10313,12 @@
       "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==",
       "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
+    },
     "randombytes": {
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
@@ -9251,13 +10345,13 @@
       "dev": true
     },
     "raw-body": {
-      "version": "2.4.0",
-      "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz",
-      "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==",
+      "version": "2.4.2",
+      "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.2.tgz",
+      "integrity": "sha512-RPMAFUJP19WIet/99ngh6Iv8fzAbqum4Li7AD6DtGaW2RpMB/11xDoalPiJMTbu6I3hkbMVkATvZrqb9EEqeeQ==",
       "dev": true,
       "requires": {
-        "bytes": "3.1.0",
-        "http-errors": "1.7.2",
+        "bytes": "3.1.1",
+        "http-errors": "1.8.1",
         "iconv-lite": "0.4.24",
         "unpipe": "1.0.0"
       }
@@ -9272,26 +10366,6 @@
         "normalize-package-data": "^2.5.0",
         "parse-json": "^5.0.0",
         "type-fest": "^0.6.0"
-      },
-      "dependencies": {
-        "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==",
-          "dev": true,
-          "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"
-          }
-        },
-        "type-fest": {
-          "version": "0.6.0",
-          "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz",
-          "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==",
-          "dev": true
-        }
       }
     },
     "readable-stream": {
@@ -9326,18 +10400,18 @@
       "dev": true
     },
     "regenerate-unicode-properties": {
-      "version": "8.2.0",
-      "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz",
-      "integrity": "sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA==",
+      "version": "9.0.0",
+      "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-9.0.0.tgz",
+      "integrity": "sha512-3E12UeNSPfjrgwjkR81m5J7Aw/T55Tu7nUyZVQYCKEOs+2dkxEY+DpPtZzO4YruuiPb7NkYLVcyJC4+zCbk5pA==",
       "dev": true,
       "requires": {
-        "regenerate": "^1.4.0"
+        "regenerate": "^1.4.2"
       }
     },
     "regenerator-runtime": {
-      "version": "0.13.7",
-      "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz",
-      "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==",
+      "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==",
       "dev": true
     },
     "regenerator-transform": {
@@ -9370,23 +10444,23 @@
       }
     },
     "regexpp": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz",
-      "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==",
+      "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": "4.7.1",
-      "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.7.1.tgz",
-      "integrity": "sha512-ywH2VUraA44DZQuRKzARmw6S66mr48pQVva4LBeRhcOltJ6hExvWly5ZjFLYo67xbIxb6W1q4bAGtgfEl20zfQ==",
+      "version": "4.8.0",
+      "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.8.0.tgz",
+      "integrity": "sha512-1F6bYsoYiz6is+oz70NWur2Vlh9KWtswuRuzJOfeYUrfPX2o8n74AnUVaOGDbUqVGO9fNHu48/pjJO4sNVwsOg==",
       "dev": true,
       "requires": {
-        "regenerate": "^1.4.0",
-        "regenerate-unicode-properties": "^8.2.0",
-        "regjsgen": "^0.5.1",
-        "regjsparser": "^0.6.4",
-        "unicode-match-property-ecmascript": "^1.0.4",
-        "unicode-match-property-value-ecmascript": "^1.2.0"
+        "regenerate": "^1.4.2",
+        "regenerate-unicode-properties": "^9.0.0",
+        "regjsgen": "^0.5.2",
+        "regjsparser": "^0.7.0",
+        "unicode-match-property-ecmascript": "^2.0.0",
+        "unicode-match-property-value-ecmascript": "^2.0.0"
       }
     },
     "register-service-worker": {
@@ -9401,9 +10475,9 @@
       "dev": true
     },
     "regjsparser": {
-      "version": "0.6.9",
-      "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.9.tgz",
-      "integrity": "sha512-ZqbNRz1SNjLAiYuwY0zoXW8Ne675IX5q+YHioAGbCw4X96Mjl2+dcX9B2ciaeyYjViDAfvIjFpQjJgLttTEERQ==",
+      "version": "0.7.0",
+      "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.7.0.tgz",
+      "integrity": "sha512-A4pcaORqmNMDVwUjWoTzuhwMGpP+NykpfqAsEgI1FSH/EzC7lrN5TMd+kN8YCovX+jMpu8eaqXgXPCa0g8FQNQ==",
       "dev": true,
       "requires": {
         "jsesc": "~0.5.0"
@@ -9448,6 +10522,62 @@
           "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
           "dev": true
         },
+        "css-select": {
+          "version": "4.2.1",
+          "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.2.1.tgz",
+          "integrity": "sha512-/aUslKhzkTNCQUB2qTX84lVmfia9NyjP3WpDGtj/WxhwBzWBYUV3DgUpurHTme8UTPcPlAD1DJ+b0nN/t50zDQ==",
+          "dev": true,
+          "requires": {
+            "boolbase": "^1.0.0",
+            "css-what": "^5.1.0",
+            "domhandler": "^4.3.0",
+            "domutils": "^2.8.0",
+            "nth-check": "^2.0.1"
+          }
+        },
+        "css-what": {
+          "version": "5.1.0",
+          "resolved": "https://registry.npmjs.org/css-what/-/css-what-5.1.0.tgz",
+          "integrity": "sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw==",
+          "dev": true
+        },
+        "dom-serializer": {
+          "version": "1.3.2",
+          "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz",
+          "integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==",
+          "dev": true,
+          "requires": {
+            "domelementtype": "^2.0.1",
+            "domhandler": "^4.2.0",
+            "entities": "^2.0.0"
+          }
+        },
+        "domelementtype": {
+          "version": "2.2.0",
+          "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz",
+          "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==",
+          "dev": true
+        },
+        "domutils": {
+          "version": "2.8.0",
+          "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz",
+          "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==",
+          "dev": true,
+          "requires": {
+            "dom-serializer": "^1.0.1",
+            "domelementtype": "^2.2.0",
+            "domhandler": "^4.2.0"
+          }
+        },
+        "nth-check": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.1.tgz",
+          "integrity": "sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==",
+          "dev": true,
+          "requires": {
+            "boolbase": "^1.0.0"
+          }
+        },
         "strip-ansi": {
           "version": "3.0.1",
           "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
@@ -9505,6 +10635,12 @@
       "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=",
       "dev": true
     },
+    "require-from-string": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
+      "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
+      "dev": true
+    },
     "require-main-filename": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
@@ -9518,13 +10654,14 @@
       "dev": true
     },
     "resolve": {
-      "version": "1.20.0",
-      "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz",
-      "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==",
+      "version": "1.21.0",
+      "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.21.0.tgz",
+      "integrity": "sha512-3wCbTpk5WJlyE4mSOtDLhqQmGFi0/TD9VPwmiolnk8U0wRgMEktqCXd3vy5buTO3tljvalNvKrjHEfrd2WpEKA==",
       "dev": true,
       "requires": {
-        "is-core-module": "^2.2.0",
-        "path-parse": "^1.0.6"
+        "is-core-module": "^2.8.0",
+        "path-parse": "^1.0.7",
+        "supports-preserve-symlinks-flag": "^1.0.0"
       }
     },
     "resolve-cwd": {
@@ -9557,12 +10694,12 @@
       "dev": true
     },
     "restore-cursor": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz",
-      "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==",
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz",
+      "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=",
       "dev": true,
       "requires": {
-        "onetime": "^5.1.0",
+        "onetime": "^2.0.0",
         "signal-exit": "^3.0.2"
       }
     },
@@ -9578,6 +10715,12 @@
       "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=",
       "dev": true
     },
+    "reusify": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
+      "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
+      "dev": true
+    },
     "rgb-regex": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/rgb-regex/-/rgb-regex-1.0.1.tgz",
@@ -9609,11 +10752,14 @@
         "inherits": "^2.0.1"
       }
     },
-    "run-async": {
-      "version": "2.4.1",
-      "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz",
-      "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==",
-      "dev": true
+    "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"
+      }
     },
     "run-queue": {
       "version": "1.0.3",
@@ -9624,15 +10770,6 @@
         "aproba": "^1.1.1"
       }
     },
-    "rxjs": {
-      "version": "6.6.7",
-      "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz",
-      "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==",
-      "dev": true,
-      "requires": {
-        "tslib": "^1.9.0"
-      }
-    },
     "safe-buffer": {
       "version": "5.1.2",
       "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
@@ -9693,9 +10830,9 @@
       "dev": true
     },
     "send": {
-      "version": "0.17.1",
-      "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz",
-      "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==",
+      "version": "0.17.2",
+      "resolved": "https://registry.npmjs.org/send/-/send-0.17.2.tgz",
+      "integrity": "sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww==",
       "dev": true,
       "requires": {
         "debug": "2.6.9",
@@ -9705,9 +10842,9 @@
         "escape-html": "~1.0.3",
         "etag": "~1.8.1",
         "fresh": "0.5.2",
-        "http-errors": "~1.7.2",
+        "http-errors": "1.8.1",
         "mime": "1.6.0",
-        "ms": "2.1.1",
+        "ms": "2.1.3",
         "on-finished": "~2.3.0",
         "range-parser": "~1.2.1",
         "statuses": "~1.5.0"
@@ -9737,9 +10874,9 @@
           "dev": true
         },
         "ms": {
-          "version": "2.1.1",
-          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
-          "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
+          "version": "2.1.3",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+          "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
           "dev": true
         }
       }
@@ -9810,15 +10947,15 @@
       }
     },
     "serve-static": {
-      "version": "1.14.1",
-      "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz",
-      "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==",
+      "version": "1.14.2",
+      "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.2.tgz",
+      "integrity": "sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ==",
       "dev": true,
       "requires": {
         "encodeurl": "~1.0.2",
         "escape-html": "~1.0.3",
         "parseurl": "~1.3.3",
-        "send": "0.17.1"
+        "send": "0.17.2"
       }
     },
     "set-blocking": {
@@ -9847,12 +10984,6 @@
           "requires": {
             "is-extendable": "^0.1.0"
           }
-        },
-        "is-extendable": {
-          "version": "0.1.1",
-          "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
-          "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=",
-          "dev": true
         }
       }
     },
@@ -9863,9 +10994,9 @@
       "dev": true
     },
     "setprototypeof": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
-      "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==",
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
+      "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
       "dev": true
     },
     "sha.js": {
@@ -9894,15 +11025,26 @@
       "dev": true
     },
     "shell-quote": {
-      "version": "1.7.2",
-      "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.2.tgz",
-      "integrity": "sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg==",
+      "version": "1.7.3",
+      "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.3.tgz",
+      "integrity": "sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw==",
       "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"
+      }
+    },
     "signal-exit": {
-      "version": "3.0.3",
-      "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz",
-      "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==",
+      "version": "3.0.6",
+      "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.6.tgz",
+      "integrity": "sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==",
       "dev": true
     },
     "simple-swizzle": {
@@ -9929,14 +11071,40 @@
       "dev": true
     },
     "slice-ansi": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz",
-      "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==",
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz",
+      "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==",
       "dev": true,
       "requires": {
-        "ansi-styles": "^3.2.0",
-        "astral-regex": "^1.0.0",
-        "is-fullwidth-code-point": "^2.0.0"
+        "ansi-styles": "^4.0.0",
+        "astral-regex": "^2.0.0",
+        "is-fullwidth-code-point": "^3.0.0"
+      },
+      "dependencies": {
+        "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"
+          }
+        },
+        "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
+        }
       }
     },
     "snapdragon": {
@@ -9982,69 +11150,6 @@
             "is-extendable": "^0.1.0"
           }
         },
-        "is-accessor-descriptor": {
-          "version": "0.1.6",
-          "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
-          "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=",
-          "dev": true,
-          "requires": {
-            "kind-of": "^3.0.2"
-          },
-          "dependencies": {
-            "kind-of": {
-              "version": "3.2.2",
-              "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-              "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
-              "dev": true,
-              "requires": {
-                "is-buffer": "^1.1.5"
-              }
-            }
-          }
-        },
-        "is-data-descriptor": {
-          "version": "0.1.4",
-          "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
-          "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=",
-          "dev": true,
-          "requires": {
-            "kind-of": "^3.0.2"
-          },
-          "dependencies": {
-            "kind-of": {
-              "version": "3.2.2",
-              "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-              "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
-              "dev": true,
-              "requires": {
-                "is-buffer": "^1.1.5"
-              }
-            }
-          }
-        },
-        "is-descriptor": {
-          "version": "0.1.6",
-          "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
-          "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==",
-          "dev": true,
-          "requires": {
-            "is-accessor-descriptor": "^0.1.6",
-            "is-data-descriptor": "^0.1.4",
-            "kind-of": "^5.0.0"
-          }
-        },
-        "is-extendable": {
-          "version": "0.1.1",
-          "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
-          "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=",
-          "dev": true
-        },
-        "kind-of": {
-          "version": "5.1.0",
-          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
-          "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
-          "dev": true
-        },
         "ms": {
           "version": "2.0.0",
           "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
@@ -10072,6 +11177,35 @@
           "requires": {
             "is-descriptor": "^1.0.0"
           }
+        },
+        "is-accessor-descriptor": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+          "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+          "dev": true,
+          "requires": {
+            "kind-of": "^6.0.0"
+          }
+        },
+        "is-data-descriptor": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+          "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+          "dev": true,
+          "requires": {
+            "kind-of": "^6.0.0"
+          }
+        },
+        "is-descriptor": {
+          "version": "1.0.2",
+          "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+          "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+          "dev": true,
+          "requires": {
+            "is-accessor-descriptor": "^1.0.0",
+            "is-data-descriptor": "^1.0.0",
+            "kind-of": "^6.0.2"
+          }
         }
       }
     },
@@ -10096,20 +11230,28 @@
       }
     },
     "sockjs": {
-      "version": "0.3.21",
-      "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.21.tgz",
-      "integrity": "sha512-DhbPFGpxjc6Z3I+uX07Id5ZO2XwYsWOrYjaSeieES78cq+JaJvVe5q/m1uvjIQhXinhIeCFRH6JgXe+mvVMyXw==",
+      "version": "0.3.24",
+      "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz",
+      "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==",
       "dev": true,
       "requires": {
         "faye-websocket": "^0.11.3",
-        "uuid": "^3.4.0",
+        "uuid": "^8.3.2",
         "websocket-driver": "^0.7.4"
+      },
+      "dependencies": {
+        "uuid": {
+          "version": "8.3.2",
+          "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
+          "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
+          "dev": true
+        }
       }
     },
     "sockjs-client": {
-      "version": "1.5.1",
-      "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.5.1.tgz",
-      "integrity": "sha512-VnVAb663fosipI/m6pqRXakEOw7nvd7TUgdr3PlR/8V2I95QIdwT8L4nMxhyU8SmDBHYXU1TOElaKOmKLfYzeQ==",
+      "version": "1.5.2",
+      "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.5.2.tgz",
+      "integrity": "sha512-ZzRxPBISQE7RpzlH4tKJMQbHM9pabHluk0WBaxAQ+wm/UieeBVBou0p4wVnSQGN9QmpAZygQ0cDIypWuqOFmFQ==",
       "dev": true,
       "requires": {
         "debug": "^3.2.6",
@@ -10117,7 +11259,7 @@
         "faye-websocket": "^0.11.3",
         "inherits": "^2.0.4",
         "json3": "^3.3.3",
-        "url-parse": "^1.5.1"
+        "url-parse": "^1.5.3"
       },
       "dependencies": {
         "debug": {
@@ -10179,9 +11321,9 @@
       }
     },
     "source-map-support": {
-      "version": "0.5.19",
-      "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz",
-      "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==",
+      "version": "0.5.21",
+      "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
+      "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
       "dev": true,
       "requires": {
         "buffer-from": "^1.0.0",
@@ -10229,9 +11371,9 @@
       }
     },
     "spdx-license-ids": {
-      "version": "3.0.9",
-      "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.9.tgz",
-      "integrity": "sha512-Ki212dKK4ogX+xDo4CtOZBVIwhsKBEfsEEcwmJfLQzirgc2jIWdzg40Unxz/HzEUqM1WFzVlQSMF9kZZ2HboLQ==",
+      "version": "3.0.11",
+      "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz",
+      "integrity": "sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==",
       "dev": true
     },
     "spdy": {
@@ -10307,12 +11449,12 @@
       }
     },
     "ssri": {
-      "version": "8.0.1",
-      "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz",
-      "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==",
+      "version": "6.0.2",
+      "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.2.tgz",
+      "integrity": "sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q==",
       "dev": true,
       "requires": {
-        "minipass": "^3.1.1"
+        "figgy-pudding": "^3.5.1"
       }
     },
     "stable": {
@@ -10345,63 +11487,6 @@
           "requires": {
             "is-descriptor": "^0.1.0"
           }
-        },
-        "is-accessor-descriptor": {
-          "version": "0.1.6",
-          "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
-          "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=",
-          "dev": true,
-          "requires": {
-            "kind-of": "^3.0.2"
-          },
-          "dependencies": {
-            "kind-of": {
-              "version": "3.2.2",
-              "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-              "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
-              "dev": true,
-              "requires": {
-                "is-buffer": "^1.1.5"
-              }
-            }
-          }
-        },
-        "is-data-descriptor": {
-          "version": "0.1.4",
-          "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
-          "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=",
-          "dev": true,
-          "requires": {
-            "kind-of": "^3.0.2"
-          },
-          "dependencies": {
-            "kind-of": {
-              "version": "3.2.2",
-              "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-              "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
-              "dev": true,
-              "requires": {
-                "is-buffer": "^1.1.5"
-              }
-            }
-          }
-        },
-        "is-descriptor": {
-          "version": "0.1.6",
-          "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
-          "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==",
-          "dev": true,
-          "requires": {
-            "is-accessor-descriptor": "^0.1.6",
-            "is-data-descriptor": "^0.1.4",
-            "kind-of": "^5.0.0"
-          }
-        },
-        "kind-of": {
-          "version": "5.1.0",
-          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
-          "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
-          "dev": true
         }
       }
     },
@@ -10457,30 +11542,14 @@
       "dev": true
     },
     "string-width": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
-      "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
+      "version": "4.2.3",
+      "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+      "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
       "dev": true,
       "requires": {
-        "is-fullwidth-code-point": "^2.0.0",
-        "strip-ansi": "^4.0.0"
-      },
-      "dependencies": {
-        "ansi-regex": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
-          "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
-          "dev": true
-        },
-        "strip-ansi": {
-          "version": "4.0.0",
-          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
-          "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
-          "dev": true,
-          "requires": {
-            "ansi-regex": "^3.0.0"
-          }
-        }
+        "emoji-regex": "^8.0.0",
+        "is-fullwidth-code-point": "^3.0.0",
+        "strip-ansi": "^6.0.1"
       }
     },
     "string.prototype.trimend": {
@@ -10524,12 +11593,20 @@
       }
     },
     "strip-ansi": {
-      "version": "5.2.0",
-      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
-      "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+      "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": "^4.1.0"
+        "ansi-regex": "^5.0.1"
+      },
+      "dependencies": {
+        "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
+        }
       }
     },
     "strip-comments": {
@@ -10599,6 +11676,12 @@
         "has-flag": "^3.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==",
+      "dev": true
+    },
     "svg-tags": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz",
@@ -10624,93 +11707,38 @@
         "stable": "^0.1.8",
         "unquote": "~1.1.1",
         "util.promisify": "~1.0.0"
-      },
-      "dependencies": {
-        "css-select": {
-          "version": "2.1.0",
-          "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.1.0.tgz",
-          "integrity": "sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ==",
-          "dev": true,
-          "requires": {
-            "boolbase": "^1.0.0",
-            "css-what": "^3.2.1",
-            "domutils": "^1.7.0",
-            "nth-check": "^1.0.2"
-          }
-        },
-        "css-what": {
-          "version": "3.4.2",
-          "resolved": "https://registry.npmjs.org/css-what/-/css-what-3.4.2.tgz",
-          "integrity": "sha512-ACUm3L0/jiZTqfzRM3Hi9Q8eZqd6IK37mMWPLz9PJxkLWllYeRf+EHUSHYEtFop2Eqytaq1FizFVh7XfBnXCDQ==",
-          "dev": true
-        },
-        "dom-serializer": {
-          "version": "0.2.2",
-          "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz",
-          "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==",
-          "dev": true,
-          "requires": {
-            "domelementtype": "^2.0.1",
-            "entities": "^2.0.0"
-          }
-        },
-        "domutils": {
-          "version": "1.7.0",
-          "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz",
-          "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==",
-          "dev": true,
-          "requires": {
-            "dom-serializer": "0",
-            "domelementtype": "1"
-          },
-          "dependencies": {
-            "domelementtype": {
-              "version": "1.3.1",
-              "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz",
-              "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==",
-              "dev": true
-            }
-          }
-        },
-        "nth-check": {
-          "version": "1.0.2",
-          "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz",
-          "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==",
-          "dev": true,
-          "requires": {
-            "boolbase": "~1.0.0"
-          }
-        }
       }
     },
     "table": {
-      "version": "5.4.6",
-      "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz",
-      "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==",
+      "version": "6.8.0",
+      "resolved": "https://registry.npmjs.org/table/-/table-6.8.0.tgz",
+      "integrity": "sha512-s/fitrbVeEyHKFa7mFdkuQMWlH1Wgw/yEXMt5xACT4ZpzWFluehAxRtUUQKPuWhaLAWhFcVx6w3oC8VKaUfPGA==",
       "dev": true,
       "requires": {
-        "ajv": "^6.10.2",
-        "lodash": "^4.17.14",
-        "slice-ansi": "^2.1.0",
-        "string-width": "^3.0.0"
+        "ajv": "^8.0.1",
+        "lodash.truncate": "^4.4.2",
+        "slice-ansi": "^4.0.0",
+        "string-width": "^4.2.3",
+        "strip-ansi": "^6.0.1"
       },
       "dependencies": {
-        "emoji-regex": {
-          "version": "7.0.3",
-          "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
-          "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==",
-          "dev": true
-        },
-        "string-width": {
-          "version": "3.1.0",
-          "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
-          "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
+        "ajv": {
+          "version": "8.8.2",
+          "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.8.2.tgz",
+          "integrity": "sha512-x9VuX+R/jcFj1DHo/fCp99esgGDWiHENrKxaCENuCxpoMCmAt/COCGVDwA7kleEpEzJjDnvh3yGoOuLu0Dtllw==",
           "dev": true,
           "requires": {
-            "emoji-regex": "^7.0.1",
-            "is-fullwidth-code-point": "^2.0.0",
-            "strip-ansi": "^5.1.0"
+            "fast-deep-equal": "^3.1.1",
+            "json-schema-traverse": "^1.0.0",
+            "require-from-string": "^2.0.2",
+            "uri-js": "^4.2.2"
           }
+        },
+        "json-schema-traverse": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
+          "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
+          "dev": true
         }
       }
     },
@@ -10731,12 +11759,6 @@
         "source-map-support": "~0.5.12"
       },
       "dependencies": {
-        "commander": {
-          "version": "2.20.3",
-          "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
-          "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
-          "dev": true
-        },
         "source-map": {
           "version": "0.6.1",
           "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
@@ -10782,12 +11804,6 @@
             "locate-path": "^3.0.0"
           }
         },
-        "is-wsl": {
-          "version": "1.1.0",
-          "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz",
-          "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=",
-          "dev": true
-        },
         "locate-path": {
           "version": "3.0.0",
           "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
@@ -10892,12 +11908,6 @@
         "neo-async": "^2.6.0"
       }
     },
-    "through": {
-      "version": "2.3.8",
-      "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
-      "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
-      "dev": true
-    },
     "through2": {
       "version": "2.0.5",
       "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz",
@@ -10929,15 +11939,6 @@
       "integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=",
       "dev": true
     },
-    "tmp": {
-      "version": "0.0.33",
-      "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
-      "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
-      "dev": true,
-      "requires": {
-        "os-tmpdir": "~1.0.2"
-      }
-    },
     "to-arraybuffer": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz",
@@ -10993,9 +11994,9 @@
       }
     },
     "toidentifier": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
-      "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==",
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
+      "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
       "dev": true
     },
     "topojson-client": {
@@ -11022,6 +12023,12 @@
         "punycode": "^2.1.1"
       }
     },
+    "tr46": {
+      "version": "0.0.3",
+      "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
+      "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=",
+      "dev": true
+    },
     "tryer": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/tryer/-/tryer-1.0.1.tgz",
@@ -11062,18 +12069,18 @@
       "dev": true
     },
     "type-check": {
-      "version": "0.3.2",
-      "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
-      "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=",
+      "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.1.2"
+        "prelude-ls": "^1.2.1"
       }
     },
     "type-fest": {
-      "version": "0.21.3",
-      "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz",
-      "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==",
+      "version": "0.6.0",
+      "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz",
+      "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==",
       "dev": true
     },
     "type-is": {
@@ -11135,31 +12142,31 @@
       }
     },
     "unicode-canonical-property-names-ecmascript": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz",
-      "integrity": "sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ==",
+      "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": "1.0.4",
-      "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz",
-      "integrity": "sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==",
+      "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": "^1.0.4",
-        "unicode-property-aliases-ecmascript": "^1.0.4"
+        "unicode-canonical-property-names-ecmascript": "^2.0.0",
+        "unicode-property-aliases-ecmascript": "^2.0.0"
       }
     },
     "unicode-match-property-value-ecmascript": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz",
-      "integrity": "sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ==",
+      "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": "1.1.0",
-      "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz",
-      "integrity": "sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg==",
+      "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
     },
     "union-value": {
@@ -11172,14 +12179,6 @@
         "get-value": "^2.0.6",
         "is-extendable": "^0.1.1",
         "set-value": "^2.0.1"
-      },
-      "dependencies": {
-        "is-extendable": {
-          "version": "0.1.1",
-          "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
-          "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=",
-          "dev": true
-        }
       }
     },
     "uniq": {
@@ -11327,9 +12326,9 @@
       }
     },
     "url-parse": {
-      "version": "1.5.1",
-      "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.1.tgz",
-      "integrity": "sha512-HOfCOUJt7iSYzEx/UqgtwKRMC6EU91NFhsCHMv9oM03VJcVo2Qrp8T8kI9D7amFf1cu+/3CEhgb3rF9zL7k85Q==",
+      "version": "1.5.4",
+      "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.4.tgz",
+      "integrity": "sha512-ITeAByWWoqutFClc/lRZnFplgXgEZr3WJ6XngMM/N9DMIm4K8zXPCZ1Jdu0rERwO84w1WC5wkle2ubwTA4NTBg==",
       "dev": true,
       "requires": {
         "querystringify": "^2.1.1",
@@ -11366,13 +12365,15 @@
       "dev": true
     },
     "util.promisify": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz",
-      "integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==",
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.1.tgz",
+      "integrity": "sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA==",
       "dev": true,
       "requires": {
-        "define-properties": "^1.1.2",
-        "object.getownpropertydescriptors": "^2.0.3"
+        "define-properties": "^1.1.3",
+        "es-abstract": "^1.17.2",
+        "has-symbols": "^1.0.1",
+        "object.getownpropertydescriptors": "^2.1.0"
       }
     },
     "utila": {
@@ -11452,9 +12453,9 @@
       "integrity": "sha512-x2284lgYvjOMj3Za7kqzRcUSxBboHqtgRE2zlos1qWaOye5yUmHn42LB1250NJBLRwEcdrB0JRwyPTEPhfQjiQ=="
     },
     "vue-eslint-parser": {
-      "version": "7.8.0",
-      "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-7.8.0.tgz",
-      "integrity": "sha512-ehmmrLZNYLUoKayvVW8l8HyPQIfuYZHiJoQLRP3dapDlTU7bGs4tqIKVGdAEpMuXS/b4R/PImCt7Tkj4UhX1SQ==",
+      "version": "7.11.0",
+      "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-7.11.0.tgz",
+      "integrity": "sha512-qh3VhDLeh773wjgNTl7ss0VejY9bMMa0GoDG2fQVyDzRFdiU3L7fw74tWZDHNQXdZqxO3EveQroa9ct39D2nqg==",
       "dev": true,
       "requires": {
         "debug": "^4.1.1",
@@ -11466,6 +12467,12 @@
         "semver": "^6.3.0"
       },
       "dependencies": {
+        "acorn": {
+          "version": "7.4.1",
+          "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz",
+          "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==",
+          "dev": true
+        },
         "eslint-scope": {
           "version": "5.1.1",
           "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
@@ -11475,13 +12482,30 @@
             "esrecurse": "^4.3.0",
             "estraverse": "^4.1.1"
           }
+        },
+        "eslint-visitor-keys": {
+          "version": "1.3.0",
+          "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz",
+          "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==",
+          "dev": true
+        },
+        "espree": {
+          "version": "6.2.1",
+          "resolved": "https://registry.npmjs.org/espree/-/espree-6.2.1.tgz",
+          "integrity": "sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw==",
+          "dev": true,
+          "requires": {
+            "acorn": "^7.1.1",
+            "acorn-jsx": "^5.2.0",
+            "eslint-visitor-keys": "^1.1.0"
+          }
         }
       }
     },
     "vue-frag": {
-      "version": "1.1.5",
-      "resolved": "https://registry.npmjs.org/vue-frag/-/vue-frag-1.1.5.tgz",
-      "integrity": "sha512-g+PP9pjW1gnrmPjy2Sa5jK/bfxYHK8Hgt1sVs/Y/7KT+srGJUwtGNwXNTUvWv/zJ2yGcvJVEH98eIrICyZX9Ng=="
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/vue-frag/-/vue-frag-1.4.0.tgz",
+      "integrity": "sha512-S3LfATqRwSMR6O8mf92wKF3y2E/Gs/3MFJXW4CozMOLUeOopNUlkcYuhVLagw7fkNmn/Pyb1zfRY5UCwU+X6Gw=="
     },
     "vue-hot-reload-api": {
       "version": "2.3.4",
@@ -11490,9 +12514,9 @@
       "dev": true
     },
     "vue-loader": {
-      "version": "15.9.7",
-      "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-15.9.7.tgz",
-      "integrity": "sha512-qzlsbLV1HKEMf19IqCJqdNvFJRCI58WNbS6XbPqK13MrLz65es75w392MSQ5TsARAfIjUw+ATm3vlCXUJSOH9Q==",
+      "version": "15.9.8",
+      "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-15.9.8.tgz",
+      "integrity": "sha512-GwSkxPrihfLR69/dSV3+5CdMQ0D+jXg8Ma1S4nQXKJAznYFX14vHdc/NetQc34Dw+rBbIJyP7JOuVb9Fhprvog==",
       "dev": true,
       "requires": {
         "@vue/component-compiler-utils": "^3.1.0",
@@ -11597,9 +12621,9 @@
       "integrity": "sha512-s7jmZPlm9FeueJg1RwJtnE9KNPtME/7C8uRWSfp9/yEN4M8XcS/d+bddoyVwVnvFyRh9msFo0HWeW0vTL8Qv+w=="
     },
     "vue-router": {
-      "version": "3.5.2",
-      "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.5.2.tgz",
-      "integrity": "sha512-807gn82hTnjCYGrnF3eNmIw/dk7/GE4B5h69BlyCK9KHASwSloD1Sjcn06zg9fVG4fYH2DrsNBZkpLtb25WtaQ=="
+      "version": "3.5.3",
+      "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.5.3.tgz",
+      "integrity": "sha512-FUlILrW3DGitS2h+Xaw8aRNvGTwtuaxrRkNSHWTizOfLUie7wuYwezeZ50iflRn8YPV5kxmU2LQuu3nM/b3Zsg=="
     },
     "vue-style-loader": {
       "version": "4.1.3",
@@ -11724,6 +12748,29 @@
             "nan": "^2.12.1"
           }
         },
+        "glob-parent": {
+          "version": "3.1.0",
+          "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
+          "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "is-glob": "^3.1.0",
+            "path-dirname": "^1.0.0"
+          },
+          "dependencies": {
+            "is-glob": {
+              "version": "3.1.0",
+              "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
+              "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=",
+              "dev": true,
+              "optional": true,
+              "requires": {
+                "is-extglob": "^2.1.0"
+              }
+            }
+          }
+        },
         "is-binary-path": {
           "version": "1.0.1",
           "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz",
@@ -11766,6 +12813,12 @@
         "defaults": "^1.0.3"
       }
     },
+    "webidl-conversions": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
+      "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=",
+      "dev": true
+    },
     "webpack": {
       "version": "4.46.0",
       "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.46.0.tgz",
@@ -11797,12 +12850,6 @@
         "webpack-sources": "^1.4.1"
       },
       "dependencies": {
-        "acorn": {
-          "version": "6.4.2",
-          "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz",
-          "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==",
-          "dev": true
-        },
         "schema-utils": {
           "version": "1.0.0",
           "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz",
@@ -11837,10 +12884,10 @@
         "ws": "^6.0.0"
       },
       "dependencies": {
-        "commander": {
-          "version": "2.20.3",
-          "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
-          "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
+        "acorn": {
+          "version": "7.4.1",
+          "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz",
+          "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==",
           "dev": true
         }
       }
@@ -11869,12 +12916,12 @@
       }
     },
     "webpack-dev-server": {
-      "version": "3.11.2",
-      "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.11.2.tgz",
-      "integrity": "sha512-A80BkuHRQfCiNtGBS1EMf2ChTUs0x+B3wGDFmOeT4rmJOHhHTCH2naNxIHhmkr0/UillP4U3yeIyv1pNp+QDLQ==",
+      "version": "3.11.3",
+      "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.11.3.tgz",
+      "integrity": "sha512-3x31rjbEQWKMNzacUZRE6wXvUFuGpH7vr0lIEbYpMAG9BOxi0928QU1BBswOAP3kg3H1O4hiS+sq4YyAn6ANnA==",
       "dev": true,
       "requires": {
-        "ansi-html": "0.0.7",
+        "ansi-html-community": "0.0.8",
         "bonjour": "^3.5.0",
         "chokidar": "^2.1.8",
         "compression": "^1.7.4",
@@ -12022,6 +13069,27 @@
             "nan": "^2.12.1"
           }
         },
+        "glob-parent": {
+          "version": "3.1.0",
+          "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
+          "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=",
+          "dev": true,
+          "requires": {
+            "is-glob": "^3.1.0",
+            "path-dirname": "^1.0.0"
+          },
+          "dependencies": {
+            "is-glob": {
+              "version": "3.1.0",
+              "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
+              "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=",
+              "dev": true,
+              "requires": {
+                "is-extglob": "^2.1.0"
+              }
+            }
+          }
+        },
         "http-proxy-middleware": {
           "version": "0.19.1",
           "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.19.1.tgz",
@@ -12049,6 +13117,12 @@
             "binary-extensions": "^1.0.0"
           }
         },
+        "is-fullwidth-code-point": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
+          "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
+          "dev": true
+        },
         "locate-path": {
           "version": "3.0.0",
           "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
@@ -12259,6 +13333,16 @@
       "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz",
       "integrity": "sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng=="
     },
+    "whatwg-url": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
+      "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=",
+      "dev": true,
+      "requires": {
+        "tr46": "~0.0.3",
+        "webidl-conversions": "^3.0.0"
+      }
+    },
     "which": {
       "version": "1.3.1",
       "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
@@ -12340,19 +13424,6 @@
         "workbox-streams": "^4.3.1",
         "workbox-sw": "^4.3.1",
         "workbox-window": "^4.3.1"
-      },
-      "dependencies": {
-        "fs-extra": {
-          "version": "4.0.3",
-          "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz",
-          "integrity": "sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg==",
-          "dev": true,
-          "requires": {
-            "graceful-fs": "^4.1.2",
-            "jsonfile": "^4.0.0",
-            "universalify": "^0.1.0"
-          }
-        }
       }
     },
     "workbox-cacheable-response": {
@@ -12481,9 +13552,9 @@
       }
     },
     "wrap-ansi": {
-      "version": "6.2.0",
-      "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
-      "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+      "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
       "dev": true,
       "requires": {
         "ansi-styles": "^4.0.0",
@@ -12491,12 +13562,6 @@
         "strip-ansi": "^6.0.0"
       },
       "dependencies": {
-        "ansi-regex": {
-          "version": "5.0.0",
-          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
-          "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
-          "dev": true
-        },
         "ansi-styles": {
           "version": "4.3.0",
           "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
@@ -12520,32 +13585,6 @@
           "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
           "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
           "dev": true
-        },
-        "is-fullwidth-code-point": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
-          "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
-          "dev": true
-        },
-        "string-width": {
-          "version": "4.2.2",
-          "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz",
-          "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==",
-          "dev": true,
-          "requires": {
-            "emoji-regex": "^8.0.0",
-            "is-fullwidth-code-point": "^3.0.0",
-            "strip-ansi": "^6.0.0"
-          }
-        },
-        "strip-ansi": {
-          "version": "6.0.0",
-          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
-          "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
-          "dev": true,
-          "requires": {
-            "ansi-regex": "^5.0.0"
-          }
         }
       }
     },
@@ -12555,15 +13594,6 @@
       "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
       "dev": true
     },
-    "write": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz",
-      "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==",
-      "dev": true,
-      "requires": {
-        "mkdirp": "^0.5.1"
-      }
-    },
     "ws": {
       "version": "6.2.2",
       "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.2.tgz",
@@ -12606,21 +13636,6 @@
         "yargs-parser": "^20.2.2"
       },
       "dependencies": {
-        "ansi-regex": {
-          "version": "5.0.0",
-          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
-          "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
-          "dev": true
-        },
-        "ansi-styles": {
-          "version": "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"
-          }
-        },
         "cliui": {
           "version": "7.0.4",
           "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
@@ -12632,58 +13647,6 @@
             "wrap-ansi": "^7.0.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
-        },
-        "is-fullwidth-code-point": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
-          "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
-          "dev": true
-        },
-        "string-width": {
-          "version": "4.2.2",
-          "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz",
-          "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==",
-          "dev": true,
-          "requires": {
-            "emoji-regex": "^8.0.0",
-            "is-fullwidth-code-point": "^3.0.0",
-            "strip-ansi": "^6.0.0"
-          }
-        },
-        "strip-ansi": {
-          "version": "6.0.0",
-          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
-          "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
-          "dev": true,
-          "requires": {
-            "ansi-regex": "^5.0.0"
-          }
-        },
-        "wrap-ansi": {
-          "version": "7.0.0",
-          "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
-          "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
-          "dev": true,
-          "requires": {
-            "ansi-styles": "^4.0.0",
-            "string-width": "^4.1.0",
-            "strip-ansi": "^6.0.0"
-          }
-        },
         "y18n": {
           "version": "5.0.8",
           "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
diff --git a/package.json b/package.json
index fa44bcd1207b3c48ee3f17186f546b7cdc42e50b..9f160f269e2249980727f2d4bfd5165f43c18558 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "geocontrib-frontend",
-  "version": "2.3.2",
+  "version": "3.0.0-rc1",
   "private": true,
   "scripts": {
     "serve": "npm run init-proxy & npm run init-serve",
@@ -18,8 +18,8 @@
     "@mapbox/vector-tile": "^1.3.1",
     "@turf/flip": "^6.5.0",
     "axios": "^0.21.1",
-    "core-js": "^3.6.5",
-    "leaflet": "^1.5.1",
+    "core-js": "^3.20.2",
+    "leaflet": "^1.7.1",
     "leaflet-draw": "^1.0.4",
     "leaflet.vectorgrid": "^1.3.0",
     "lodash": "^4.17.21",
@@ -27,21 +27,21 @@
     "register-service-worker": "^1.7.1",
     "sortablejs": "^1.14.0",
     "vue": "^2.6.11",
-    "vue-frag": "^1.1.5",
+    "vue-frag": "^1.4.0",
     "vue-multiselect": "~2.1.6",
-    "vue-router": "^3.2.0",
+    "vue-router": "^3.5.3",
     "vuex": "^3.6.2"
   },
   "devDependencies": {
     "@fortawesome/fontawesome-free": "^5.15.4",
     "@vue/cli-plugin-babel": "~4.5.0",
-    "@vue/cli-plugin-eslint": "~4.5.0",
+    "@vue/cli-plugin-eslint": "^5.0.0-beta.6",
     "@vue/cli-plugin-pwa": "~4.5.0",
     "@vue/cli-plugin-router": "~4.5.0",
     "@vue/cli-service": "~4.5.0",
-    "babel-eslint": "^10.1.0",
-    "eslint": "^6.7.2",
-    "eslint-plugin-vue": "^6.2.2",
+    "@babel/eslint-parser": "^7.15.8",
+    "eslint": "^7.32.0",
+    "eslint-plugin-vue": "^7.20.0",
     "less": "^3.0.4",
     "less-loader": "^5.0.0",
     "local-cors-proxy": "^1.1.0",
diff --git a/src/App.vue b/src/App.vue
index 2230b6d59aeb680b976a7e291ec8a23147803c5a..5de9b51cdcc23c72df5c23ef19ca14a10b50b8f4 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -4,9 +4,9 @@
       type="application/javascript"
       :src="
         baseUrl +
-        'resources/leaflet-control-geocoder-1.13.0/Control.Geocoder.js'
+          'resources/leaflet-control-geocoder-1.13.0/Control.Geocoder.js'
       "
-    ></script>
+    />
     <header class="header-menu">
       <div class="menu container">
         <div class="ui inverted icon menu">
@@ -14,7 +14,10 @@
             :to="isSharedProject ? '' : '/'"
             :class="['header item', {disable: isSharedProject}]"
           >
-            <img class="ui mini right spaced image" :src="logo" />
+            <img
+              class="ui mini right spaced image"
+              :src="logo"
+            >
             <span class="desktop">
               {{ APPLICATION_NAME }}
             </span>
@@ -30,7 +33,7 @@
             <span>
               <span v-if="project"> Projet : {{ project.title }} </span>
             </span>
-            <i class="dropdown icon"></i>
+            <i class="dropdown icon" />
             <div
               :class="[
                 'menu dropdown-list',
@@ -46,7 +49,7 @@
                 }"
                 class="item"
               >
-                <i class="home icon"></i>Accueil
+                <i class="home icon" />Accueil
               </router-link>
               <router-link
                 v-if="project"
@@ -56,13 +59,13 @@
                 }"
                 class="item"
               >
-                <i class="list icon"></i>Liste & Carte
+                <i class="list icon" />Liste & Carte
               </router-link>
 
               <router-link
                 v-if="
                   project &&
-                  (user.is_administrator || user.is_superuser || isAdmin)
+                    (user.is_administrator || user.is_superuser || isAdmin)
                 "
                 :to="{
                   name: 'project_mapping',
@@ -70,12 +73,12 @@
                 }"
                 class="item"
               >
-                <i class="map icon"></i>Fonds cartographiques
+                <i class="map icon" />Fonds cartographiques
               </router-link>
               <router-link
                 v-if="
                   project &&
-                  (user.is_administrator || user.is_superuser || isAdmin)
+                    (user.is_administrator || user.is_superuser || isAdmin)
                 "
                 :to="{
                   name: 'project_members',
@@ -83,11 +86,15 @@
                 }"
                 class="item"
               >
-                <i class="users icon"></i>Membres
+                <i class="users icon" />Membres
               </router-link>
 
               <div class="mobile">
-                <router-link v-if="user" to="/my_account/" class="item">
+                <router-link
+                  v-if="user"
+                  to="/my_account/"
+                  class="item"
+                >
                   {{ userFullname || user.username || "Utilisateur inconnu" }}
                 </router-link>
                 <div
@@ -95,7 +102,7 @@
                   class="item ui label vertical no-hover"
                 >
                   {{ USER_LEVEL_PROJECTS[project.slug] }}
-                  <br />
+                  <br>
                 </div>
                 <div
                   v-if="user && user.is_administrator"
@@ -103,17 +110,28 @@
                 >
                   Gestionnaire métier
                 </div>
-                <div v-frag v-if="!DISABLE_LOGIN_BUTTON">
-                  <a v-if="user" @click="logout" class="item"
-                    ><i class="ui logout icon"></i>
+                <div
+                  v-if="!DISABLE_LOGIN_BUTTON"
+                  v-frag
+                >
+                  <a
+                    v-if="user"
+                    class="item"
+                    @click="logout"
+                  ><i class="ui logout icon" />
                   </a>
                   <router-link
                     v-else-if="!user && !SSO_LOGIN_URL"
                     to="/connexion/"
                     class="item"
-                    >Se connecter</router-link
                   >
-                  <a v-else class="item" :href="SSO_LOGIN_URL">Se connecter</a>
+                    Se connecter
+                  </router-link>
+                  <a
+                    v-else
+                    class="item"
+                    :href="SSO_LOGIN_URL"
+                  >Se connecter</a>
                 </div>
               </div>
             </div>
@@ -125,7 +143,11 @@
           </div>
 
           <div class="desktop flex push-right-desktop">
-            <router-link v-if="user" :to="{name: 'my_account'}" class="item">
+            <router-link
+              v-if="user"
+              :to="{name: 'my_account'}"
+              class="item"
+            >
               {{ userFullname || user.username || "Utilisateur inconnu" }}
             </router-link>
             <div
@@ -133,7 +155,7 @@
               class="item ui label vertical no-hover"
             >
               {{ USER_LEVEL_PROJECTS[project.slug] }}
-              <br />
+              <br>
             </div>
             <div
               v-if="user && user.is_administrator"
@@ -141,47 +163,70 @@
             >
               Gestionnaire métier
             </div>
-            <div v-frag v-if="!DISABLE_LOGIN_BUTTON">
-              <a v-if="user" @click="logout" class="item"
-                ><i class="ui logout icon"></i>
+            <div
+              v-if="!DISABLE_LOGIN_BUTTON"
+              v-frag
+            >
+              <a
+                v-if="user"
+                class="item"
+                @click="logout"
+              ><i class="ui logout icon" />
               </a>
               <router-link
                 v-else-if="!user && !SSO_LOGIN_URL"
                 to="/connexion/"
                 class="item"
-                >Se Connecter</router-link
               >
-              <a v-else class="item" :href="SSO_LOGIN_URL">Se connecter</a>
+                Se Connecter
+              </router-link>
+              <a
+                v-else
+                class="item"
+                :href="SSO_LOGIN_URL"
+              >Se connecter</a>
             </div>
           </div>
         </div>
       </div>
     </header>
     <main>
-      <div id="content" class="ui stackable grid centered container">
+      <div
+        id="content"
+        class="ui stackable grid centered container"
+      >
         <transition name="fadeDownUp">
-        <div v-if="messages && messages.length > 0" class="row over-content">
-          <div class="fourteen wide column">
-            <div
-              v-for="(message, index) in messages"
-              :key="'message-' + index"
-              :class="['ui', message.level ? message.level : 'info', 'message']"
-            >
-              <i class="close icon" @click="DISCARD_MESSAGE(message)"></i>
-              <div class="header">
-                <i class="info circle icon"></i>
-                Informations
+          <div
+            v-if="messages && messages.length > 0"
+            class="row over-content"
+          >
+            <div class="fourteen wide column">
+              <div
+                v-for="(message, index) in messages"
+                :key="'message-' + index"
+                :class="['ui', message.level ? message.level : 'info', 'message']"
+              >
+                <i
+                  class="close icon"
+                  @click="DISCARD_MESSAGE(message)"
+                />
+                <div class="header">
+                  <i class="info circle icon" />
+                  Informations
+                </div>
+                <ul class="list">
+                  {{
+                    message.comment
+                  }}
+                </ul>
               </div>
-              <ul class="list">
-                {{
-                  message.comment
-                }}
-              </ul>
             </div>
           </div>
-        </div>
         </transition>
-        <div :class="{ active: loader.isLoading }" class="ui inverted dimmer">
+        <div
+          :class="{ active: loader.isLoading }"
+          class="ui inverted dimmer"
+        >
           <div class="ui text loader">
             {{ loader.message }}
           </div>
@@ -193,20 +238,32 @@
 
     <footer>
       <div class="ui compact text menu">
-        <router-link :to="{name: 'mentions'}" class="item">Mentions légales</router-link>
-        <router-link :to="{name: 'aide'}" class="item">Aide</router-link>
-        <p class="item">Version {{ PACKAGE_VERSION }}</p>
+        <router-link
+          :to="{name: 'mentions'}"
+          class="item"
+        >
+          Mentions légales
+        </router-link>
+        <router-link
+          :to="{name: 'aide'}"
+          class="item"
+        >
+          Aide
+        </router-link>
+        <p class="item">
+          Version {{ PACKAGE_VERSION }}
+        </p>
       </div>
     </footer>
   </div>
 </template>
 
 <script>
-import frag from "vue-frag";
-import { mapMutations, mapState } from "vuex";
+import frag from 'vue-frag';
+import { mapMutations, mapState, mapGetters } from 'vuex';
 
 export default {
-  name: "App",
+  name: 'App',
 
   directives: {
     frag,
@@ -223,11 +280,11 @@ export default {
 
   computed: {
     ...mapState([
-      "user",
-      "USER_LEVEL_PROJECTS",
-      "configuration",
-      "messages",
-      "loader",
+      'user',
+      'USER_LEVEL_PROJECTS',
+      'configuration',
+      'messages',
+      'loader',
     ]),
     ...mapState('projects', [
       'projects',
@@ -245,18 +302,18 @@ export default {
     SSO_LOGIN_URL() {
       return this.configuration.VUE_APP_LOGIN_URL;
     },
-    PACKAGE_VERSION: () => process.env.PACKAGE_VERSION || "0",
+    PACKAGE_VERSION: () => process.env.PACKAGE_VERSION || '0',
     logo() {
       return this.configuration.VUE_APP_LOGO_PATH;
     },
     userFullname() {
       if (this.user.first_name || this.user.last_name)
-        return this.user.first_name + " " + this.user.last_name;
+        return this.user.first_name + ' ' + this.user.last_name;
       return null;
     },
     isAdmin() {
       return this.USER_LEVEL_PROJECTS &&
-        this.USER_LEVEL_PROJECTS[this.project.slug] === "Administrateur projet"
+        this.USER_LEVEL_PROJECTS[this.project.slug] === 'Administrateur projet'
         ? true
         : false;
     },
@@ -265,25 +322,25 @@ export default {
     }
   },
 
+  created() {
+    window.addEventListener('mousedown', this.clickOutsideMenu);
+  },
+
+  beforeDestroy() {
+    window.removeEventListener('mousedown', this.clickOutsideMenu);
+  },
+
   methods: {
     ...mapMutations(['DISCARD_MESSAGE']),
     logout() {
-      this.$store.dispatch("LOGOUT");
+      this.$store.dispatch('LOGOUT');
     },
 
     clickOutsideMenu(e) {
-      if (e.target.closest && !e.target.closest("#menu-dropdown"))
+      if (e.target.closest && !e.target.closest('#menu-dropdown'))
         this.menuIsOpen = false;
     },
   },
-
-  created() {
-    window.addEventListener("mousedown", this.clickOutsideMenu);
-  },
-
-  beforeDestroy() {
-    window.removeEventListener("mousedown", this.clickOutsideMenu);
-  },
 };
 </script>
 
@@ -399,23 +456,6 @@ footer {
 }
 
 
-.bounce-enter-active {
-  animation: bounce-in .5s;
-}
-.bounce-leave-active {
-  animation: bounce-in .5s reverse;
-}
-@keyframes bounce-in {
-  0% {
-    transform: scale(0);
-  }
-  50% {
-    transform: scale(1.5);
-  }
-  100% {
-    transform: scale(1);
-  }
-}
 .ui.grid > .row.over-content {
   position: absolute;
   z-index: 99;
diff --git a/src/assets/js/formset_handlers.js b/src/assets/js/formset_handlers.js
deleted file mode 100644
index 504065b30a0def7c23709a082cc10e20e8304a76..0000000000000000000000000000000000000000
--- a/src/assets/js/formset_handlers.js
+++ /dev/null
@@ -1,49 +0,0 @@
-window.addEventListener('load', function () {
-
-  // ---------------------------------------------------------------------------
-  // Suppression d'un ligne de formset
-  // ---------------------------------------------------------------------------
-  let removables = document.getElementsByClassName('remove-row');
-  function RemoveIt() {
-
-    let getter = this.getAttribute('id').replace('-REM', '')
-    let hidden_input_delete = document.getElementById(''.concat('id_', getter, '-DELETE'));
-    let current_row = document.getElementById(getter + '-ROW');
-
-    hidden_input_delete.value = 'checked';
-    current_row.style.display = 'none';
-  };
-
-  for (let i = 0; i < removables.length; i++) {
-    removables[i].addEventListener('click', RemoveIt, false);
-  }
-
-  // ---------------------------------------------------------------------------
-  // Ajout d'un ligne de formset
-  // ---------------------------------------------------------------------------
-  let add_buttons = document.getElementsByClassName('add_button');
-
-  function AddRow() {
-    let prefix = this.getAttribute('data-related-fieldset');
-    let total_form = document.getElementById('id_' + prefix + '-TOTAL_FORMS')
-    let form_idx = total_form.value;
-
-    // Injection de l'indice de la ligne et ajout au formset
-    let empty_tbody = document.getElementById(prefix + '-EMPTY_TBODY').innerHTML.replace(/__prefix__/g, form_idx);
-    console.log(empty_tbody);
-    let tbody = document.getElementById(prefix + '-TBODY').insertAdjacentHTML('beforeend', empty_tbody);
-
-
-    // Ajout d'un event ciblant la nouvelle ancre de suppression
-    let remove_field = document.getElementById(prefix + '-' + form_idx + '-REM');
-    remove_field.addEventListener('click', RemoveIt, false);
-
-    total_form.setAttribute("value", parseInt(form_idx) + 1);
-    // total_form.value++
-  };
-
-  for (let i = 0; i < add_buttons.length; i++) {
-    add_buttons[i].addEventListener('click', AddRow, false);
-  }
-
-});
diff --git a/src/assets/js/map-util.js b/src/assets/js/map-util.js
index 9c279ef6e2634edb7751f6122e349debf5952bc2..4c2434bff8808af4071d7c522c5fc2ff601962a0 100644
--- a/src/assets/js/map-util.js
+++ b/src/assets/js/map-util.js
@@ -1,34 +1,28 @@
-/* eslint-disable no-mixed-spaces-and-tabs */
-/* eslint-disable no-unused-vars */
-/* eslint-disable no-undef */
-import L from "leaflet"
-import "leaflet/dist/leaflet.css";
-import flip from '@turf/flip'
+import L from 'leaflet';
+import 'leaflet/dist/leaflet.css';
+import flip from '@turf/flip';
 import axios from '@/axios-client.js';
-import "leaflet.vectorgrid";
-import store from '@/store';
-
-import { FillSymbolizer, PointSymbolizer, LineSymbolizer } from "@/assets/js/vector_tile_fix.js";
+import 'leaflet.vectorgrid';
 
 let map;
 let dictLayersToLeaflet = {};
 var layerMVT;
 let statusList = [
   {
-    name: "Brouillon",
-    value: "draft",
+    name: 'Brouillon',
+    value: 'draft',
   },
   {
-    name: "Publié",
-    value: "published",
+    name: 'Publié',
+    value: 'published',
   },
   {
-    name: "Archivé",
-    value: "archived",
+    name: 'Archivé',
+    value: 'archived',
   },
   {
-    name: "En attente de publication",
-    value: "pending",
+    name: 'En attente de publication',
+    value: 'pending',
   },
 ];
 L.TileLayer.BetterWMS = L.TileLayer.WMS.extend({
@@ -59,7 +53,6 @@ L.TileLayer.BetterWMS = L.TileLayer.WMS.extend({
           window.proxy_url,
           {
             params: params,
-            //dataType: "json",
           }
         ).then(response => {
           let data = response.data;
@@ -69,11 +62,9 @@ L.TileLayer.BetterWMS = L.TileLayer.WMS.extend({
           }
         })
           .catch(error => {
-            throw (error)
-            //xhr.status;
-            //xhr.responseText;
+            throw (error);
           }
-          )
+          );
 
       }
     }
@@ -116,7 +107,7 @@ L.TileLayer.BetterWMS = L.TileLayer.WMS.extend({
       content = `
 				<h4>${this.options.title}</h4>
 				<p>Données de la couche inaccessibles</p>
-			`
+			`;
 
       L.popup({ maxWidth: 800 })
         .setLatLng(latlng)
@@ -133,7 +124,7 @@ L.TileLayer.BetterWMS = L.TileLayer.WMS.extend({
           if (key !== 'bbox') {
             contentLines.push(`<div>${key}: ${value}</div>`);
           }
-        })
+        });
         contentTitle = `<h4>${this.options.title}</h4>`;
         content = contentTitle.concat(contentLines.join(''));
 
@@ -177,7 +168,7 @@ const mapUtil = {
       ],
       !zoom ? mapDefaultViewZoom : zoom
     );
-    map.setMaxBounds(  [[-90,-180],   [90,180]]  )
+    map.setMaxBounds(  [[-90,-180],   [90,180]]  );
     if (zoomControl) {
       L.control
         .zoom({
@@ -212,7 +203,7 @@ const mapUtil = {
       }
 
       L.Control.geocoder({
-        placeholder: "Chercher une adresse...",
+        placeholder: 'Chercher une adresse...',
         geocoder: geocoder,
       }).addTo(map);
     }
@@ -297,7 +288,7 @@ const mapUtil = {
     if (featureType && colorsStyle && colorsStyle.custom_field_name) {
       const currentValue = properties[colorsStyle.custom_field_name];
       const colorStyle = colorsStyle.colors[currentValue];
-      return colorStyle ? colorStyle : featureType.color
+      return colorStyle ? colorStyle : featureType.color;
     } else {
       return featureType.color;
     }
@@ -307,7 +298,7 @@ const mapUtil = {
     layerMVT = L.vectorGrid.protobuf(url, {
       noWrap:true,
       vectorTileLayerStyles: {
-        "default": (properties) => {
+        default: (properties) => {
           const featureType = featureTypes.find((x) => x.slug.split('-')[0] === '' + properties.feature_type_id);
 
           const color = this.retrieveFeatureColor(featureType, properties);
@@ -367,7 +358,7 @@ const mapUtil = {
       L.popup()
         .setContent(popupContent)
         .setLatLng(e.latlng)
-        .openOn(map)
+        .openOn(map);
     });
     layerMVT.addTo(map);
     window.layerMVT = layerMVT;
@@ -377,7 +368,8 @@ const mapUtil = {
     const featureGroup = new L.FeatureGroup();
     features.forEach((feature) => {
       const featureProperties = feature.properties ? feature.properties : feature;
-      const featureType = featureTypes.find((ft) => ft.slug === (featureProperties.feature_type.slug || featureProperties.feature_type));
+      const featureType = featureTypes
+        .find((ft) => ft.slug === (featureProperties.feature_type.slug || featureProperties.feature_type));
       let filters = [];
       if (filter) {
         const typeCheck = filter.featureType && featureProperties.feature_type.slug === filter.featureType;
@@ -398,8 +390,12 @@ const mapUtil = {
         // Look for a custom field
         let customField;
         let customFieldOption;
-        if (featureType.customfield_set && Object.keys(featureProperties).some(el => featureType.customfield_set.map(e => e.name).includes(el))) {
-          customField = Object.keys(featureProperties).filter(el => featureType.customfield_set.map(e => e.name).includes(el));
+        if (
+          featureType.customfield_set &&
+          Object.keys(featureProperties).some(el => featureType.customfield_set.map(e => e.name).includes(el))
+        ) {
+          customField = Object.keys(featureProperties)
+            .filter(el => featureType.customfield_set.map(e => e.name).includes(el));
           customFieldOption = featureProperties[customField[0]];
         }
         let color = this.retrieveFeatureColor(featureType, featureProperties) || featureProperties.color;
@@ -511,10 +507,10 @@ const mapUtil = {
 
   _createContentPopup: function (feature, featureTypes, project_slug) {
     const formatDate = (current_datetime) => {
-      let formatted_date = current_datetime.getFullYear() + "-" + ("0" + (current_datetime.getMonth() + 1)).slice(-2) + "-" + ("0" + current_datetime.getDate()).slice(-2) + " " +
-        ("0" + current_datetime.getHours()).slice(-2) + ":" + ("0" + current_datetime.getMinutes()).slice(-2);
+      let formatted_date = current_datetime.getFullYear() + '-' + ('0' + (current_datetime.getMonth() + 1)).slice(-2) + '-' + ('0' + current_datetime.getDate()).slice(-2) + ' ' +
+        ('0' + current_datetime.getHours()).slice(-2) + ':' + ('0' + current_datetime.getMinutes()).slice(-2);
       return formatted_date;
-    }
+    };
     let feature_type;
     let status;
     let date_maj;
@@ -546,7 +542,7 @@ const mapUtil = {
     }
 
     let author = '';
-    const creator = feature.properties ? feature.properties.creator : feature.creator
+    const creator = feature.properties ? feature.properties.creator : feature.creator;
     if (creator) {
       author = creator.full_name
         ? `<div>
@@ -574,4 +570,4 @@ const mapUtil = {
   },
 };
 
-export { mapUtil }
+export { mapUtil };
diff --git a/src/assets/js/utils.js b/src/assets/js/utils.js
index 53bcc6106352aeb538f6af7819f85f7dd3f282ef..c2e3395d7fd5079597d213130ee58ad76487c014 100644
--- a/src/assets/js/utils.js
+++ b/src/assets/js/utils.js
@@ -1,13 +1,13 @@
 export function fileConvertSize(aSize){
-	aSize = Math.abs(parseInt(aSize, 10));
-	const def = [[1, 'octets', 0], [1024, 'ko', 0], [1024*1024, 'Mo', 1], [1024*1024*1024, 'Go', 2], [1024*1024*1024*1024, 'To', 2]];
-	for (let i=0; i<def.length; i++) {
-		if (aSize<def[i][0]) return (aSize/def[i-1][0]).toFixed(def[i-1][2]) + ' ' + def[i-1][1];
-	}
+  aSize = Math.abs(parseInt(aSize, 10));
+  const def = [[1, 'octets', 0], [1024, 'ko', 0], [1024*1024, 'Mo', 1], [1024*1024*1024, 'Go', 2], [1024*1024*1024*1024, 'To', 2]];
+  for (let i=0; i<def.length; i++) {
+    if (aSize<def[i][0]) return (aSize/def[i-1][0]).toFixed(def[i-1][2]) + ' ' + def[i-1][1];
+  }
 }
 
 export function fileConvertSizeToMo(aSize){
-	aSize = Math.abs(parseInt(aSize, 10));
-	const def = [1024*1024, 'Mo', 1];
-	return (aSize/def[0]).toFixed(def[2]);
+  aSize = Math.abs(parseInt(aSize, 10));
+  const def = [1024*1024, 'Mo', 1];
+  return (aSize/def[0]).toFixed(def[2]);
 }
diff --git a/src/assets/js/vector_tile_fix.js b/src/assets/js/vector_tile_fix.js
index 5bad33736f8a492d54f4b7595ece4f639a3f8bcf..2e500e9e70952d1739be3c941f3e0c5c31357723 100644
--- a/src/assets/js/vector_tile_fix.js
+++ b/src/assets/js/vector_tile_fix.js
@@ -1,210 +1,209 @@
-/* eslint-disable no-unused-vars */
-import L from "leaflet"
+import L from 'leaflet';
 export var Symbolizer = L.Class.extend({
-	// 🍂method initialize(feature: GeoJSON, pxPerExtent: Number)
-	// Initializes a new Line Symbolizer given a GeoJSON feature and the
-	// pixel-to-coordinate-units ratio. Internal use only.
-
-	// 🍂method render(renderer, style)
-	// Renders this symbolizer in the given tiled renderer, with the given
-	// `L.Path` options.  Internal use only.
-	render: function(renderer, style) {
-		this._renderer = renderer;
-		this.options = style;
-		renderer._initPath(this);
-		renderer._updateStyle(this);
-	},
-
-	// 🍂method render(renderer, style)
-	// Updates the `L.Path` options used to style this symbolizer, and re-renders it.
-	// Internal use only.
-	updateStyle: function(renderer, style) {
-		this.options = style;
-		renderer._updateStyle(this);
-	},
-
-	_getPixelBounds: function() {
-		var parts = this._parts;
-		var bounds = L.bounds([]);
-		for (var i = 0; i < parts.length; i++) {
-			var part = parts[i];
-			for (var j = 0; j < part.length; j++) {
-				bounds.extend(part[j]);
-			}
-		}
-
-		var w = this._clickTolerance(),
-            p = new L.Point(w, w);
-
-		bounds.min._subtract(p);
-		bounds.max._add(p);
-
-		return bounds;
-	},
-	_clickTolerance: L.Path.prototype._clickTolerance,
-})
+  // 🍂method initialize(feature: GeoJSON, pxPerExtent: Number)
+  // Initializes a new Line Symbolizer given a GeoJSON feature and the
+  // pixel-to-coordinate-units ratio. Internal use only.
+
+  // 🍂method render(renderer, style)
+  // Renders this symbolizer in the given tiled renderer, with the given
+  // `L.Path` options.  Internal use only.
+  render: function(renderer, style) {
+    this._renderer = renderer;
+    this.options = style;
+    renderer._initPath(this);
+    renderer._updateStyle(this);
+  },
+
+  // 🍂method render(renderer, style)
+  // Updates the `L.Path` options used to style this symbolizer, and re-renders it.
+  // Internal use only.
+  updateStyle: function(renderer, style) {
+    this.options = style;
+    renderer._updateStyle(this);
+  },
+
+  _getPixelBounds: function() {
+    var parts = this._parts;
+    var bounds = L.bounds([]);
+    for (var i = 0; i < parts.length; i++) {
+      var part = parts[i];
+      for (var j = 0; j < part.length; j++) {
+        bounds.extend(part[j]);
+      }
+    }
+
+    var w = this._clickTolerance(),
+      p = new L.Point(w, w);
+
+    bounds.min._subtract(p);
+    bounds.max._add(p);
+
+    return bounds;
+  },
+  _clickTolerance: L.Path.prototype._clickTolerance,
+});
 
 export var PolyBase = {
-	_makeFeatureParts: function(feat, pxPerExtent) {
-		var rings = feat.geometry;
-		var coord;
-
-		this._parts = [];
-		for (var i = 0; i < rings.length; i++) {
-			var ring = rings[i];
-			var part = [];
-			for (var j = 0; j < ring.length; j++) {
-				coord = ring[j];
-				// Protobuf vector tiles return {x: , y:}
-				// Geojson-vt returns [,]
-				part.push(L.point(coord).scaleBy(pxPerExtent));
-			}
-			this._parts.push(part);
-		}
-	},
-
-	makeInteractive: function() {
-		this._pxBounds = this._getPixelBounds();
-	}
-}
+  _makeFeatureParts: function(feat, pxPerExtent) {
+    var rings = feat.geometry;
+    var coord;
+
+    this._parts = [];
+    for (var i = 0; i < rings.length; i++) {
+      var ring = rings[i];
+      var part = [];
+      for (var j = 0; j < ring.length; j++) {
+        coord = ring[j];
+        // Protobuf vector tiles return {x: , y:}
+        // Geojson-vt returns [,]
+        part.push(L.point(coord).scaleBy(pxPerExtent));
+      }
+      this._parts.push(part);
+    }
+  },
+
+  makeInteractive: function() {
+    this._pxBounds = this._getPixelBounds();
+  }
+};
 export var LineSymbolizer = L.Polyline.extend({
-	includes: [Symbolizer.prototype, PolyBase],
-
-	initialize: function(feature, pxPerExtent) {
-		this.properties = feature.properties;
-		this._makeFeatureParts(feature, pxPerExtent);
-	},
-
-	render: function(renderer, style) {
-		style.fill = false;
-		Symbolizer.prototype.render.call(this, renderer, style);
-		this._updatePath();
-	},
-
-	updateStyle: function(renderer, style) {
-		style.fill = false;
-		Symbolizer.prototype.updateStyle.call(this, renderer, style);
-	},
-})
+  includes: [Symbolizer.prototype, PolyBase],
+
+  initialize: function(feature, pxPerExtent) {
+    this.properties = feature.properties;
+    this._makeFeatureParts(feature, pxPerExtent);
+  },
+
+  render: function(renderer, style) {
+    style.fill = false;
+    Symbolizer.prototype.render.call(this, renderer, style);
+    this._updatePath();
+  },
+
+  updateStyle: function(renderer, style) {
+    style.fill = false;
+    Symbolizer.prototype.updateStyle.call(this, renderer, style);
+  },
+});
 export var FillSymbolizer = L.Polygon.extend({
-	includes: [Symbolizer.prototype, PolyBase],
-
-	initialize: function(feature, pxPerExtent) {
-		this.properties = feature.properties;
-		this._makeFeatureParts(feature, pxPerExtent);
-	},
-
-	render: function(renderer, style) {
-		Symbolizer.prototype.render.call(this, renderer, style);
-		this._updatePath();
-	}
-})
+  includes: [Symbolizer.prototype, PolyBase],
+
+  initialize: function(feature, pxPerExtent) {
+    this.properties = feature.properties;
+    this._makeFeatureParts(feature, pxPerExtent);
+  },
+
+  render: function(renderer, style) {
+    Symbolizer.prototype.render.call(this, renderer, style);
+    this._updatePath();
+  }
+});
 export var PointSymbolizer = L.CircleMarker.extend({
-	includes: Symbolizer.prototype,
-
-	statics: {
-		iconCache: {}
-	},
-
-	initialize: function(feature, pxPerExtent) {
-		this.properties = feature.properties;
-		this._makeFeatureParts(feature, pxPerExtent);
-	},
-
-	render: function(renderer, style) {
-		Symbolizer.prototype.render.call(this, renderer, style);
-		this._radius = style.radius || L.CircleMarker.prototype.options.radius;
-		this._updatePath();
-	},
-
-	_makeFeatureParts: function(feat, pxPerExtent) {
-		var coord = feat.geometry[0];
-		if (typeof coord[0] === 'object' && 'x' in coord[0]) {
-			// Protobuf vector tiles return [{x: , y:}]
-			this._point = L.point(coord[0]).scaleBy(pxPerExtent);
-			this._empty = L.Util.falseFn;
-		} else {
-			// Geojson-vt returns [,]
-			this._point = L.point(coord).scaleBy(pxPerExtent);
-			this._empty = L.Util.falseFn;
-		}
-	},
-
-	makeInteractive: function() {
-		this._updateBounds();
-	},
-
-	updateStyle: function(renderer, style) {
-		this._radius = style.radius || this._radius;
-		this._updateBounds();
-		return Symbolizer.prototype.updateStyle.call(this, renderer, style);
-	},
-
-	_updateBounds: function() {
-		var icon = this.options.icon
-		if (icon) {
-			var size = L.point(icon.options.iconSize),
-                anchor = icon.options.iconAnchor ||
+  includes: Symbolizer.prototype,
+
+  statics: {
+    iconCache: {}
+  },
+
+  initialize: function(feature, pxPerExtent) {
+    this.properties = feature.properties;
+    this._makeFeatureParts(feature, pxPerExtent);
+  },
+
+  render: function(renderer, style) {
+    Symbolizer.prototype.render.call(this, renderer, style);
+    this._radius = style.radius || L.CircleMarker.prototype.options.radius;
+    this._updatePath();
+  },
+
+  _makeFeatureParts: function(feat, pxPerExtent) {
+    var coord = feat.geometry[0];
+    if (typeof coord[0] === 'object' && 'x' in coord[0]) {
+      // Protobuf vector tiles return [{x: , y:}]
+      this._point = L.point(coord[0]).scaleBy(pxPerExtent);
+      this._empty = L.Util.falseFn;
+    } else {
+      // Geojson-vt returns [,]
+      this._point = L.point(coord).scaleBy(pxPerExtent);
+      this._empty = L.Util.falseFn;
+    }
+  },
+
+  makeInteractive: function() {
+    this._updateBounds();
+  },
+
+  updateStyle: function(renderer, style) {
+    this._radius = style.radius || this._radius;
+    this._updateBounds();
+    return Symbolizer.prototype.updateStyle.call(this, renderer, style);
+  },
+
+  _updateBounds: function() {
+    var icon = this.options.icon;
+    if (icon) {
+      var size = L.point(icon.options.iconSize),
+        anchor = icon.options.iconAnchor ||
                 size && size.divideBy(2, true),
-                p = this._point.subtract(anchor);
-			this._pxBounds = new L.Bounds(p, p.add(icon.options.iconSize));
-		} else {
-			L.CircleMarker.prototype._updateBounds.call(this);
-		}
-	},
-
-	_updatePath: function() {
-		if (this.options.icon) {
-			this._renderer._updateIcon(this)
-		} else {
-			L.CircleMarker.prototype._updatePath.call(this);
-		}
-	},
-
-	_getImage: function () {
-		if (this.options.icon) {
-			var url = this.options.icon.options.iconUrl,
-            img = PointSymbolizer.iconCache[url];
-			if (!img) {
-				var icon = this.options.icon;
-				img = PointSymbolizer.iconCache[url] = icon.createIcon();
-			}
-			return img;
-		} else {
-			return null;
-		}
-
-	},
-
-	_containsPoint: function(p) {
-		var icon = this.options.icon;
-		if (icon) {
-			return this._pxBounds.contains(p);
-		} else {
-			return L.CircleMarker.prototype._containsPoint.call(this, p);
-		}
-	}
-});
+        p = this._point.subtract(anchor);
+      this._pxBounds = new L.Bounds(p, p.add(icon.options.iconSize));
+    } else {
+      L.CircleMarker.prototype._updateBounds.call(this);
+    }
+  },
 
-L.VectorGrid.prototype._createLayer=function(feat, pxPerExtent, layerStyle) {
-    var layer;
-    switch (feat.type) {
-    case 1:
-        layer = new PointSymbolizer(feat, pxPerExtent);
-        // [YB 2019-10-23: prevent leaflet from treating these canvas points as real markers]
-        layer.getLatLng = null;         
-        break;
-    case 2:
-        layer = new LineSymbolizer(feat, pxPerExtent);
-        break;
-    case 3:
-        layer = new FillSymbolizer(feat, pxPerExtent);
-        break;
+  _updatePath: function() {
+    if (this.options.icon) {
+      this._renderer._updateIcon(this);
+    } else {
+      L.CircleMarker.prototype._updatePath.call(this);
     }
-  
-    if (this.options.interactive) {
-        layer.addEventParent(this);
+  },
+
+  _getImage: function () {
+    if (this.options.icon) {
+      var url = this.options.icon.options.iconUrl,
+        img = PointSymbolizer.iconCache[url];
+      if (!img) {
+        var icon = this.options.icon;
+        img = PointSymbolizer.iconCache[url] = icon.createIcon();
+      }
+      return img;
+    } else {
+      return null;
+    }
+
+  },
+
+  _containsPoint: function(p) {
+    var icon = this.options.icon;
+    if (icon) {
+      return this._pxBounds.contains(p);
+    } else {
+      return L.CircleMarker.prototype._containsPoint.call(this, p);
     }
+  }
+});
+
+L.VectorGrid.prototype._createLayer=function(feat, pxPerExtent) {
+  var layer;
+  switch (feat.type) {
+  case 1:
+    layer = new PointSymbolizer(feat, pxPerExtent);
+    // [YB 2019-10-23: prevent leaflet from treating these canvas points as real markers]
+    layer.getLatLng = null;         
+    break;
+  case 2:
+    layer = new LineSymbolizer(feat, pxPerExtent);
+    break;
+  case 3:
+    layer = new FillSymbolizer(feat, pxPerExtent);
+    break;
+  }
+  
+  if (this.options.interactive) {
+    layer.addEventParent(this);
+  }
   
-    return layer;
-  }
\ No newline at end of file
+  return layer;
+};
\ No newline at end of file
diff --git a/src/assets/resources/semantic-ui-2.4.2/semantic.min.css b/src/assets/resources/semantic-ui-2.4.2/semantic.min.css
index 1a81e0b53764d8404d0c8498bdba12917cb56504..e31f026a991481fef798eb0b167c0bdc10ab5284 100644
--- a/src/assets/resources/semantic-ui-2.4.2/semantic.min.css
+++ b/src/assets/resources/semantic-ui-2.4.2/semantic.min.css
@@ -26066,14 +26066,9 @@ select.ui.dropdown {
 .ui.modal>.actions {
     background: #f9fafb;
     padding: 1rem 1rem;
-    border-top: 1px solid rgba(34, 36, 38, .15);
     text-align: right
 }
 
-.ui.modal .actions>.button {
-    margin-left: .75em
-}
-
 @media only screen and (max-width:767px) {
     .ui.modal {
         width: 95%;
diff --git a/src/assets/styles/base.css b/src/assets/styles/base.css
index 6045409b25e2b91f98e8e6d834a4732cf4b6f99a..1cce63f229b04b9ee38be4f875f2ef072a870b4f 100644
--- a/src/assets/styles/base.css
+++ b/src/assets/styles/base.css
@@ -9,7 +9,16 @@ header {
 main {
   padding: 2em 0em;
 }
+/* ---------------------------------- */
+            /* UTILS */
+/* ---------------------------------- */
+.no-margin {
+  margin: 0 !important;
+}
 
+.margin-top {
+  margin-top: 1rem;
+}
 /* ---------------------------------- */
             /* UTILS */
 /* ---------------------------------- */
diff --git a/src/axios-client.js b/src/axios-client.js
index fa6b3d958ba2c8e4ec140a407d117a8137aee1c2..70640ddf1fb421bc193b29d99f9b30402f9aebe7 100644
--- a/src/axios-client.js
+++ b/src/axios-client.js
@@ -6,30 +6,30 @@ axios.defaults.withCredentials = true;
 axios.interceptors.request.use(function (config) {
 
   config.headers['X-CSRFToken'] = (name => {
-    const re = new RegExp(name + "=([^;]+)");
+    const re = new RegExp(name + '=([^;]+)');
     const value = re.exec(document.cookie);
     return (value != null) ? unescape(value[1]) : null;
   })('csrftoken');
 
   return config;
 
-  }, function (error) {
-    return Promise.reject(error);
-  });
+}, function (error) {
+  return Promise.reject(error);
+});
 
 // Add a response interceptor
 axios.interceptors.response.use(function (response) {
 
   response.headers['X-CSRFToken'] = (name => {
-    const re = new RegExp(name + "=([^;]+)");
+    const re = new RegExp(name + '=([^;]+)');
     const value = re.exec(document.cookie);
     return (value != null) ? unescape(value[1]) : null;
   })('csrftoken');
 
   return response;
 
-  }, function (error) {
-    return Promise.reject(error);
-  });
+}, function (error) {
+  return Promise.reject(error);
+});
 
 export default axios;
\ No newline at end of file
diff --git a/src/components/Dropdown.vue b/src/components/Dropdown.vue
index 0afade8d86427718d0918404aee33febad0d0c90..d658cb72f7df541516c86220855f4c620e50d6bc 100644
--- a/src/components/Dropdown.vue
+++ b/src/components/Dropdown.vue
@@ -10,37 +10,41 @@
   >
     <input
       v-if="search"
+      ref="input"
       v-model="input"
-      @input="isOpen = true"
-      v-on:keyup.enter="select(0)"
-      v-on:keyup.esc="toggleDropdown(false)"
       class="search"
       autocomplete="off"
       tabindex="0"
       :placeholder="placehold"
-      ref="input"
-    />
-    <div v-if="!input" class="default text">
-      <!-- {{ selected }} -->
+      @input="isOpen = true"
+      @keyup.enter="select(0)"
+      @keyup.esc="toggleDropdown(false)"
+    >
+    <div
+      v-if="!input"
+      class="default text"
+    >
       <div v-if="Array.isArray(selected)">
         <span v-if="selected[0]"> {{ selected[0] }} - </span>
         <span class="italic">{{ selected[1] }}</span>
       </div>
-      <div v-else>{{ selected }}</div>
+      <div v-else>
+        {{ selected }}
+      </div>
     </div>
     <i
       :class="['dropdown icon', { clear: clearable && selected }]"
       @click="clear"
-    ></i>
+    />
     <div :class="['menu', { 'visible transition': isOpen }]">
       <div
         v-for="(option, index) in filteredOptions || ['No results found.']"
-        @click="select(index)"
         :key="option + index"
         :class="[
           filteredOptions ? 'item' : 'message',
           { 'active selected': option.name === selected },
         ]"
+        @click="select(index)"
       >
         <div v-if="option.name && Array.isArray(option.name)">
           <span v-if="option.name[0]"> {{ option.name[0] }} - </span>
@@ -59,43 +63,70 @@
 
 <script>
 export default {
-  name: "Dropdown",
+  name: 'Dropdown',
+
+  props: {
+    clearable: {
+      type: Boolean,
+      default: null,
+    },
+    disabled: {
+      type: Boolean,
+      default: null,
+    },
+    options: {
+      type: Array,
+      default: null,
+    },
+    placeholder: {
+      type: String,
+      default: null,
+    },
+    selected: {
+      type: [String, Array],
+      default: null,
+    },
+    search: {
+      type: Boolean,
+      default: null,
+    },
+  },
 
-  props: [
-    "options",
-    "selected",
-    "disabled",
-    "search",
-    "placeholder",
-    "clearable",
-  ],
+  data() {
+    return {
+      isOpen: false,
+      input: '',
+      identifier: 0,
+    };
+  },
 
   computed: {
     filteredOptions: function () {
       let options = this.options;
-      if (this.search && this.input !== "") {
+      if (this.search && this.input !== '') {
         options = this.options.filter(this.matchInput);
       }
       return options.length > 0 ? options : null;
     },
 
     placehold() {
-      return this.input ? "" : this.placeholder;
+      return this.input ? '' : this.placeholder;
     },
   },
 
-  data() {
-    return {
-      isOpen: false,
-      input: "",
-      identifier: 0,
-    };
+  created() {
+    this.identifier = Math.floor(Math.random() * 10000);
+    window.addEventListener('mousedown', this.clickOutsideDropdown);
+  },
+
+  beforeDestroy() {
+    window.removeEventListener('mousedown', this.clickOutsideDropdown);
   },
 
   methods: {
     toggleDropdown(val) {
       if (this.isOpen) {
-        this.input = ""; // * clear input field when closing dropdown
+        this.input = ''; // * clear input field when closing dropdown
       } else if (this.search) {
         //* focus on input if is a search dropdown
         this.$refs.input.focus({
@@ -104,7 +135,7 @@ export default {
       } else if (this.clearable && val.target && this.selected) {
         this.clear(); //* clear selected and input
       }
-      this.isOpen = typeof val === "boolean" ? val : !this.isOpen;
+      this.isOpen = typeof val === 'boolean' ? val : !this.isOpen;
     },
 
     select(index) {
@@ -113,9 +144,9 @@ export default {
         this.isOpen = false;
       }, 0);
       if (this.filteredOptions) {
-        this.$emit("update:selection", this.filteredOptions[index]);
+        this.$emit('update:selection', this.filteredOptions[index]);
       }
-      this.input = "";
+      this.input = '';
     },
 
     matchInput(el) {
@@ -134,8 +165,8 @@ export default {
 
     clear() {
       if (this.clearable) {
-        this.input = "";
-        this.$emit("update:selection", "");
+        this.input = '';
+        this.$emit('update:selection', '');
         if (this.isOpen) this.toggleDropdown(false);
       }
     },
@@ -145,15 +176,6 @@ export default {
         this.toggleDropdown(false);
     },
   },
-
-  created() {
-    this.identifier = Math.floor(Math.random() * 10000);
-    window.addEventListener("mousedown", this.clickOutsideDropdown);
-  },
-
-  beforeDestroy() {
-    window.removeEventListener("mousedown", this.clickOutsideDropdown);
-  },
 };
 </script>
 
diff --git a/src/components/ImportTask.vue b/src/components/ImportTask.vue
index 9f307cab0b604209193b23289677ab5afe8d2a36..21ac2ec0b38053c707e0f967df93ef478aa0a609 100644
--- a/src/components/ImportTask.vue
+++ b/src/components/ImportTask.vue
@@ -8,7 +8,10 @@
         </tr>
       </thead>
       <tbody>
-        <tr :key="importFile.created_on" v-for="importFile in data">
+        <tr
+          v-for="importFile in data"
+          :key="importFile.created_on"
+        >
           <td>
             <h4 class="ui header align-right">
               <div :data-tooltip="importFile.geojson_file_name">
@@ -29,24 +32,27 @@
               <i
                 v-if="importFile.status === 'processing'"
                 class="orange hourglass half icon"
-              ></i>
+              />
               <i
                 v-else-if="importFile.status === 'finished'"
                 class="green check circle outline icon"
-              ></i>
+              />
               <i
                 v-else-if="importFile.status === 'failed'"
                 class="red x icon"
-              ></i>
-              <i v-else class="red ban icon"></i>
+              />
+              <i
+                v-else
+                class="red ban icon"
+              />
             </span>
             <span
               v-if="importFile.status === 'pending'"
               data-tooltip="Statut en attente. Clickez pour rafraichir."
             >
               <i
-                v-on:click="fetchImports()"
                 :class="['orange icon', ready && !reloading ? 'sync' : 'hourglass half rotate']"
+                @click="fetchImports()"
               />
             </span>
           </td>
@@ -58,31 +64,44 @@
 
 
 <script>
-import { mapState } from "vuex";
+import { mapState } from 'vuex';
 
 export default {
-  data() {
-    return {
-      open: false,
-      ready: true,
-    };
-  },
-
-  props: ["data", "reloading"],
-
   filters: {
     setDate: function (value) {
       let date = new Date(value);
-      let d = date.toLocaleDateString("fr", {
-        year: "numeric",
-        month: "long",
-        day: "numeric",
+      let d = date.toLocaleDateString('fr', {
+        year: 'numeric',
+        month: 'long',
+        day: 'numeric',
       });
       return d;
     },
     subString: function (value) {
-      return value.substring(0, 27) + "..";
+      return value.substring(0, 27) + '..';
+    },
+  },
+
+  props: {
+    data: {
+      type: Array,
+      default: null,
     },
+    reloading: {
+      type: Boolean,
+      default: false,
+    }
+  },
+
+  data() {
+    return {
+      open: false,
+      ready: true,
+    };
+  },
+
+  computed: {
+    ...mapState('feature', ['features']),
   },
 
   watch: {
@@ -92,20 +111,17 @@ export default {
       }
     },
   },
-   computed: {
-    ...mapState("feature", ["features"]),
-  },
 
   methods: {
     fetchImports() {
       this.$store.dispatch(
-        "feature_type/GET_IMPORTS", {
-        feature_type: this.$route.params.feature_type_slug
-      });
+        'feature_type/GET_IMPORTS', {
+          feature_type: this.$route.params.feature_type_slug
+        });
       this.$store.dispatch('feature/GET_PROJECT_FEATURES', {
         project_slug:  this.$route.params.slug,
         feature_type__slug:  this.$route.params.feature_type_slug
-      })
+      });
       //* show that the action was triggered, could be improved with animation (doesn't work)
       this.ready = false;
     },
diff --git a/src/components/Pagination.vue b/src/components/Pagination.vue
index dfee522be8eeed3dd10e7e80bd988f12bf79ca0f..d0f730bab725b56ccaab46e4c02835e7c197da65 100644
--- a/src/components/Pagination.vue
+++ b/src/components/Pagination.vue
@@ -14,7 +14,10 @@
             <i class="ui icon big angle left" />
           </a>
         </li>
-        <div v-if="nbPages > 5" style="display: contents;">
+        <div
+          v-if="nbPages > 5"
+          style="display: contents;"
+        >
           <li
             v-for="index in pagination(page, nbPages)"
             :key="index"
@@ -30,7 +33,10 @@
             </a>
           </li>
         </div>
-        <div v-else style="display: contents;">
+        <div
+          v-else
+          style="display: contents;"
+        >
           <li
             v-for="index in nbPages"
             :key="index"
@@ -84,7 +90,7 @@ export default {
   data() {
     return {
       page: 1
-    }
+    };
   },
 
   watch: {
@@ -99,25 +105,25 @@ export default {
   methods: {
     pagination(c, m) {
       const current = c,
-            last = m,
-            delta = 2,
-            left = current - delta,
-            right = current + delta + 1,
-            range = [],
-            rangeWithDots = [];
+        last = m,
+        delta = 2,
+        left = current - delta,
+        right = current + delta + 1,
+        range = [],
+        rangeWithDots = [];
       let   l;
 
       for (let i = 1; i <= last; i++) {
         if (i === 1 || i === last || i >= left && i < right) {
-            range.push(i);
+          range.push(i);
         }
       }
       for (const i of range) {
         if (l) {
           if (i - l === 2) {
-              rangeWithDots.push(l + 1);
+            rangeWithDots.push(l + 1);
           } else if (i - l !== 1) {
-              rangeWithDots.push('...');
+            rangeWithDots.push('...');
           }
         }
         rangeWithDots.push(i);
@@ -133,5 +139,5 @@ export default {
       }
     }
   }
-}
+};
 </script>
diff --git a/src/components/Projects/DropdownMenuItem.vue b/src/components/Projects/DropdownMenuItem.vue
index ae0ebdb63ad019c1cee232e43df0c10b6de8c580..6d43d80ee7abc2f2b81008bb68ad6a2fe0cd7cd4 100644
--- a/src/components/Projects/DropdownMenuItem.vue
+++ b/src/components/Projects/DropdownMenuItem.vue
@@ -1,22 +1,22 @@
 <template>
   <Multiselect
-		v-model="selection"
-		:options="options"
-		:allow-empty="true"
-		track-by="label"
-		label="label"
-		:reset-after="false"
-		select-label=""
-		selected-label=""
-		deselect-label=""
-		:searchable="false"
-		:placeholder="placeholder"
-		:clear-on-select="false"
-		:preserve-search="true"
-		@select="select"
-		@close="close"
-	>
-		<!-- <template slot="clear">
+    v-model="selection"
+    :options="options"
+    :allow-empty="true"
+    track-by="label"
+    label="label"
+    :reset-after="false"
+    select-label=""
+    selected-label=""
+    deselect-label=""
+    :searchable="false"
+    :placeholder="placeholder"
+    :clear-on-select="false"
+    :preserve-search="true"
+    @select="select"
+    @close="close"
+  >
+    <!-- <template slot="clear">
 			<div
 				v-if="selection"
 				class="multiselect__clear"
@@ -25,7 +25,7 @@
 				<i class="close icon"></i>
 			</div>
 		</template> -->
-	</Multiselect>
+  </Multiselect>
 </template>
 
 <script>
@@ -34,44 +34,44 @@ import Multiselect from 'vue-multiselect';
 export default {
   name: 'DropdownMenuItem',
 
-	components: {
-		Multiselect
-	},
+  components: {
+    Multiselect
+  },
 
-	props: {
-		placeholder: {
-			type: String,
-			default: 'Sélectionnez une valeur'
-		},
-		options: {
-			type: Array,
-			default: () => {
-				return [];
-			}
-		}
-	},
+  props: {
+    placeholder: {
+      type: String,
+      default: 'Sélectionnez une valeur'
+    },
+    options: {
+      type: Array,
+      default: () => {
+        return [];
+      }
+    }
+  },
 
   data() {
     return {
       selection: null,
-    }
+    };
   },
 
-	watch: {
-		selection: {
-			deep: true,
-			handler(newValue) {
-				if (!newValue) {
-					this.selection = this.options[0];
-					this.$emit('filter', this.selection);
-				}
-			}
-		}
-	},
+  watch: {
+    selection: {
+      deep: true,
+      handler(newValue) {
+        if (!newValue) {
+          this.selection = this.options[0];
+          this.$emit('filter', this.selection);
+        }
+      }
+    }
+  },
 
-	created() {
-		this.selection = this.options[0];
-	},
+  created() {
+    this.selection = this.options[0];
+  },
 
   methods: {
     select(e) {
@@ -81,7 +81,7 @@ export default {
       this.$emit('close', this.selection);
     }
   }
-}
+};
 </script>
 
 <style lang="less" scoped>
diff --git a/src/components/Projects/ProjectsMenu.vue b/src/components/Projects/ProjectsMenu.vue
index 8eea8a9a7fb4354dd571bbea1ac0a9ce636c3b42..7f8d3e6825dbcf77580deaa85b8c4a3e92d338e5 100644
--- a/src/components/Projects/ProjectsMenu.vue
+++ b/src/components/Projects/ProjectsMenu.vue
@@ -1,38 +1,55 @@
 <template>
-	<div class="ui menu projects">
-		<div class="item">
-			<label>
-				Modération
-			</label>
-			<DropdownMenuItem
-				:options="moderationOptions"
-				v-on="$listeners"
-			/>
-		</div>
-		<div class="item">
-			<label>
-				Niveau d'autorisation requis
-			</label>
-			<DropdownMenuItem
-				:options="accessLevelOptions"
-				v-on="$listeners"
-			/>
-		</div>
-		<div class="item">
-			<label>
-				Mon niveau d'autorisation
-			</label>
-			<DropdownMenuItem
-				:options="userAccessLevelOptions"
-				v-on="$listeners"
-			/>
-		</div>
-		<div class="right item">
-			<search-projects
-				:search-function="SEARCH_PROJECTS"
-			/>
-		</div>
-	</div>
+  <div class="filters-container">
+    <div class="ui styled accordion">
+      <div class="title collapsible-filters">
+        FILTRES
+        <i
+          :class="isFiltersVisible ? 'caret down' : 'caret right'"
+          class="ui icon"
+        />
+      </div>
+    </div>
+    <div
+      :class="isFiltersVisible ? '' : 'hidden'"
+      class="ui menu filters"
+    >
+      <div class="item">
+        <label>
+          Niveau d'autorisation requis
+        </label>
+        <DropdownMenuItem
+          :options="accessLevelOptions"
+          v-on="$listeners"
+        />
+      </div>
+      <div class="item">
+        <label>
+          Mon niveau d'autorisation
+        </label>
+        <DropdownMenuItem
+          :options="userAccessLevelOptions"
+          v-on="$listeners"
+        />
+      </div>
+      <div class="item">
+        <label>
+          Modération
+        </label>
+        <DropdownMenuItem
+          :options="moderationOptions"
+          v-on="$listeners"
+        />
+      </div>
+      <div class="right item">
+        <label>
+          Rechercher un projet
+        </label>
+        <search-projects
+          :search-function="SEARCH_PROJECTS"
+        />
+      </div>
+    </div>
+  </div>
 </template>
 
 <script>
@@ -42,114 +59,165 @@ import DropdownMenuItem from '@/components/Projects/DropdownMenuItem.vue';
 import SearchProjects from '@/components/Projects/SearchProjects.vue';
 
 export default {
-	name: 'ProjectsMenu',
+  name: 'ProjectsMenu',
 
-	components: {
-		DropdownMenuItem,
-		SearchProjects,
-	},
+  components: {
+    DropdownMenuItem,
+    SearchProjects,
+  },
 
-	data() {
-		return {
-			moderationOptions: [
-				{
-					label: 'Tous',
-					filter: 'moderation',
-					value: null
-				},
-				{
-					label: 'Projet modéré',
-					filter: 'moderation',
-					value: 'true'
-				},
-				{
-					label: 'Projet non modéré',
-					filter: 'moderation',
-					value: 'false'
-				},
-			],
-			accessLevelOptions: [
-				{
-					label: 'Tous',
-					filter: 'access_level',
-					value: null
-				},
-				{
-					label: 'Utilisateur connecté',
-					filter: 'access_level',
-					value: 'logged_user'
-				},
-				{
-					label: 'Contributeur',
-					filter: 'access_level',
-					value: 'contributor'
-				},
-				{
-					label: 'Modérateur',
-					filter: 'access_level',
-					value: 'moderator'
-				},
-				{
-					label: 'Administrateur projet',
-					filter: 'access_level',
-					value: 'admin'
-				},
-			],
-			userAccessLevelOptions: [
-				{
-					label: 'Tous',
-					filter: 'user_access_level',
-					value: null
-				},
-				{
-					label: 'Utilisateur connecté',
-					filter: 'user_access_level',
-					value: '1'
-				},
-				{
-					label: 'Contributeur',
-					filter: 'user_access_level',
-					value: '2'
-				},
-				{
-					label: 'Modérateur',
-					filter: 'user_access_level',
-					value: '3'
-				},
-				{
-					label: 'Administrateur projet',
-					filter: 'user_access_level',
-					value: '4'
-				},
-			]
-		}
-	},
+  data() {
+    return {
+      isFiltersVisible: false,
+      moderationOptions: [
+        {
+          label: 'Tous',
+          filter: 'moderation',
+          value: null
+        },
+        {
+          label: 'Projet modéré',
+          filter: 'moderation',
+          value: 'true'
+        },
+        {
+          label: 'Projet non modéré',
+          filter: 'moderation',
+          value: 'false'
+        },
+      ],
+      accessLevelOptions: [
+        {
+          label: 'Tous',
+          filter: 'access_level',
+          value: null
+        },
+        {
+          label: 'Utilisateur connecté',
+          filter: 'access_level',
+          value: 'logged_user'
+        },
+        {
+          label: 'Contributeur',
+          filter: 'access_level',
+          value: 'contributor'
+        },
+        {
+          label: 'Modérateur',
+          filter: 'access_level',
+          value: 'moderator'
+        },
+        {
+          label: 'Administrateur projet',
+          filter: 'access_level',
+          value: 'admin'
+        },
+      ],
+      userAccessLevelOptions: [
+        {
+          label: 'Tous',
+          filter: 'user_access_level',
+          value: null
+        },
+        {
+          label: 'Utilisateur connecté',
+          filter: 'user_access_level',
+          value: '1'
+        },
+        {
+          label: 'Contributeur',
+          filter: 'user_access_level',
+          value: '2'
+        },
+        {
+          label: 'Modérateur',
+          filter: 'user_access_level',
+          value: '3'
+        },
+        {
+          label: 'Administrateur projet',
+          filter: 'user_access_level',
+          value: '4'
+        },
+      ]
+    };
+  },
 
-	methods: {
-		...mapActions('projects', [
-			'SEARCH_PROJECTS'
-		])
-	}
-}
+  mounted() {
+    const el = document.getElementsByClassName('collapsible-filters');
+
+    el[0].addEventListener('click', function() {
+      const content = document.getElementsByClassName('filters');
+      content[0].classList.toggle('hidden');
+      if (content[0].style.maxHeight){
+        content[0].style.maxHeight = null;
+      } else {
+        content[0].style.maxHeight = content[0].scrollHeight + 5 + 'px';
+      }
+    });
+  },
+
+  methods: {
+    ...mapActions('projects', [
+      'SEARCH_PROJECTS'
+    ])
+  }
+};
 </script>
 
 <style lang="less" scoped>
-.projects {
-	.item {
-		display: flex;
-		flex-direction: column;
-		align-items: flex-start !important;
+.transition-properties(...) {
+  -webkit-transition: @arguments;
+  -moz-transition: @arguments;
+  -o-transition: @arguments;
+  transition: @arguments;
+}
 
-		padding: 0.4em 0.6em;
+.filters-container {
+	width: 100%;
+	display: flex;
+	flex-direction: column;
+	justify-content: flex-end;
+	align-items: flex-end;
+	.accordion {
+		width: fit-content;
+		.collapsible-filters {
+			cursor: pointer;
+			font-size: 1.25em;
+			padding-right: 0;
+		}
+	}
+	.filters {
+		width: 100%;
+		height:auto;
+		min-height: 0;
+		max-height:75px;
+		margin: 0 0 1em 0;
+		.transition-properties(max-height 0.2s ease-out;);
+		.item {
+			display: flex;
+			flex-direction: column;
+			align-items: flex-start !important;
+
+			padding: 0.4em 0.6em;
 
-		label {
-			margin-bottom: 0.2em;
-			font-size: 0.9em;
-			font-weight: 600;
+			label {
+				margin-bottom: 0.2em;
+				font-size: 0.9em;
+				font-weight: 600;
+			}
+		}
+		.item {
+			width: 25%;
+		}
+		.right.item::before {
+			width: 0;
 		}
 	}
-	.item {
-		width: 25%;
+	.filters.hidden {
+		max-height: 0;
+		overflow: hidden;
+		border: none;
 	}
 }
 </style>
diff --git a/src/components/Projects/SearchProjects.vue b/src/components/Projects/SearchProjects.vue
index 3fa8e94b4188ed80475c7d7c97628a87784d5b49..3f4c6eecd9914cfd838d2013157a6237fe8884e8 100644
--- a/src/components/Projects/SearchProjects.vue
+++ b/src/components/Projects/SearchProjects.vue
@@ -1,5 +1,5 @@
 <template>
-	<div id="search-projects">
+  <div id="search-projects">
     <input
       v-model="text"
       type="search"
@@ -18,14 +18,14 @@ export default {
   props: {
     searchFunction: {
       type: Function,
-      default: () => { return {} }
+      default: () => { return {}; }
     }
-	},
+  },
 
   data() {
     return {
       text: null
-    }
+    };
   },
 
   watch: {
@@ -44,7 +44,7 @@ export default {
       'SET_CURRENT_PAGE'
     ])
   }
-}
+};
 </script>
 
 <style lang="less" scoped>
@@ -55,7 +55,7 @@ export default {
   justify-content: flex-end;
   input {
     width: 100%;
-    height: 72%;
+    height: 98%;
     text-align: left;
     color: #35495e;
     padding: 8px 40px 0 8px;
diff --git a/src/components/SearchFeature.vue b/src/components/SearchFeature.vue
index 6ea7c0d5747542584fedcddacede3988782670cc..b0a661a24ab82eee7bc16852fbd6c671473c65cc 100644
--- a/src/components/SearchFeature.vue
+++ b/src/components/SearchFeature.vue
@@ -27,7 +27,7 @@
           class="multiselect__clear"
           @click.prevent.stop="selection = null"
         >
-          <i class="close icon"></i>
+          <i class="close icon" />
         </div>
       </template>
       <span slot="noResult">
@@ -58,7 +58,7 @@ export default {
       selection: null,
       text: null,
       results: []
-    }
+    };
   },
 
   computed: {
@@ -106,7 +106,7 @@ export default {
       this.$emit('close', this.selection);
     }
   }
-}
+};
 </script>
 
 <style scoped>
diff --git a/src/components/feature/FeatureAttachmentForm.vue b/src/components/feature/FeatureAttachmentForm.vue
index 26d93d3ac930559f7ed63bcad41f1ec92a3a5d9e..922f3c6a6d8714106b9c1294bb28ef43667ff4c1 100644
--- a/src/components/feature/FeatureAttachmentForm.vue
+++ b/src/components/feature/FeatureAttachmentForm.vue
@@ -4,11 +4,11 @@
       <h4>
         Pièce jointe
         <button
-          @click="removeAttachmentFormset(form.dataKey)"
           class="ui small compact right floated icon button remove-formset"
           type="button"
+          @click="removeAttachmentFormset(form.dataKey)"
         >
-          <i class="ui times icon"></i>
+          <i class="ui times icon" />
         </button>
       </h4>
       <!-- {{ form.errors }} -->
@@ -17,15 +17,21 @@
           <div class="required field">
             <label :for="form.title.id_for_label">{{ form.title.label }}</label>
             <input
+              :id="form.title.id_for_label"
+              v-model="form.title.value"
               type="text"
               required
               :maxlength="form.title.field.max_length"
               :name="form.title.html_name"
-              :id="form.title.id_for_label"
-              v-model="form.title.value"
-            />
-            <ul :id="form.title.id_for_error" class="errorlist">
-              <li v-for="error in form.title.errors" :key="error">
+            >
+            <ul
+              :id="form.title.id_for_error"
+              class="errorlist"
+            >
+              <li
+                v-for="error in form.title.errors"
+                :key="error"
+              >
                 {{ error }}
               </li>
             </ul>
@@ -36,22 +42,34 @@
               class="ui icon button"
               :for="'attachment_file' + attachmentForm.dataKey"
             >
-              <i class="file icon"></i>
-              <span v-if="form.attachment_file.value" class="label">{{
+              <i class="file icon" />
+              <span
+                v-if="form.attachment_file.value"
+                class="label"
+              >{{
                 form.attachment_file.value
               }}</span>
-              <span v-else class="label">Sélectionner un fichier ... </span>
+              <span
+                v-else
+                class="label"
+              >Sélectionner un fichier ... </span>
             </label>
             <input
-              @change="onFileChange"
+              :id="'attachment_file' + attachmentForm.dataKey"
               type="file"
               accept="application/pdf, image/jpeg, image/png"
               style="display: none"
               :name="form.attachment_file.html_name"
-              :id="'attachment_file' + attachmentForm.dataKey"
-            />
-            <ul :id="form.attachment_file.id_for_error" class="errorlist">
-              <li v-for="error in form.attachment_file.errors" :key="error">
+              @change="onFileChange"
+            >
+            <ul
+              :id="form.attachment_file.id_for_error"
+              class="errorlist"
+            >
+              <li
+                v-for="error in form.attachment_file.errors"
+                :key="error"
+              >
                 {{ error }}
               </li>
             </ul>
@@ -60,10 +78,10 @@
         <div class="field">
           <label for="form.info.id_for_label">{{ form.info.label }}</label>
           <textarea
+            v-model="form.info.value"
             name="form.info.html_name"
             rows="5"
-            v-model="form.info.value"
-          ></textarea>
+          />
           <!-- {{ form.info.errors }} -->
         </div>
       </div>
@@ -73,41 +91,46 @@
 
 <script>
 export default {
-  name: "FeatureAttachmentFormset",
+  name: 'FeatureAttachmentFormset',
 
-  props: ["attachmentForm"],
+  props:  {
+    attachmentForm: {
+      type: Object,
+      default: null,
+    }
+  },
 
   data() {
     return {
       fileToImport: null,
       form: {
         id: {
-          value: "",
+          value: '',
           errors: null,
-          label: "ID",
+          label: 'ID',
         },
         title: {
           errors: [],
           id_for_error: `errorlist-title-${this.attachmentForm.dataKey}`,
-          id_for_label: "titre",
+          id_for_label: 'titre',
           field: {
             max_length: 30, // todo : vérifier dans django
           },
-          html_name: "titre",
-          label: "Titre",
-          value: "",
+          html_name: 'titre',
+          label: 'Titre',
+          value: '',
         },
         attachment_file: {
           errors: [],
           id_for_error: `errorlist-file-${this.attachmentForm.dataKey}`,
-          html_name: "titre",
-          label: "Titre",
+          html_name: 'titre',
+          label: 'Titre',
           value: null,
         },
         info: {
-          value: "",
+          value: '',
           errors: null,
-          label: "Info",
+          label: 'Info',
         },
       },
     };
@@ -118,15 +141,15 @@ export default {
       this.initForm(newValue);
     },
     //* utilisation de watcher, car @change aurait un délai
-    "form.title.value": function (newValue, oldValue) {
-      if (oldValue !== "") {
+    'form.title.value': function (newValue, oldValue) {
+      if (oldValue !== '') {
         if (newValue !== oldValue) {
           this.updateStore();
         }
       }
     },
-    "form.info.value": function (newValue, oldValue) {
-      if (oldValue !== "") {
+    'form.info.value': function (newValue, oldValue) {
+      if (oldValue !== '') {
         if (newValue !== oldValue) {
           this.updateStore();
         }
@@ -134,12 +157,16 @@ export default {
     },
   },
 
+  mounted() {
+    this.initForm(this.attachmentForm);
+  },
+
   methods: {
     initForm(attachmentForm) {
       for (let el in attachmentForm) {
         if (el && this.form[el]) {
-          if (el === "attachment_file" && attachmentForm[el]) {
-            this.form[el].value = attachmentForm[el].split("/").pop(); //* keep only the file name, not the path
+          if (el === 'attachment_file' && attachmentForm[el]) {
+            this.form[el].value = attachmentForm[el].split('/').pop(); //* keep only the file name, not the path
           } else {
             this.form[el].value = attachmentForm[el];
           }
@@ -149,11 +176,11 @@ export default {
 
     removeAttachmentFormset() {
       this.$store.commit(
-        "feature/REMOVE_ATTACHMENT_FORM",
+        'feature/REMOVE_ATTACHMENT_FORM',
         this.attachmentForm.dataKey
       );
       if (this.form.id.value)
-        this.$store.commit("feature/ADD_ATTACHMENT_TO_DELETE", this.form.id.value);
+        this.$store.commit('feature/ADD_ATTACHMENT_TO_DELETE', this.form.id.value);
     },
 
     updateStore() {
@@ -165,7 +192,7 @@ export default {
         info: this.form.info.value,
         fileToImport: this.fileToImport,
       };
-      this.$store.commit("feature/UPDATE_ATTACHMENT_FORM", data);
+      this.$store.commit('feature/UPDATE_ATTACHMENT_FORM', data);
     },
 
     validateImgFile(files, handleFile) {
@@ -202,7 +229,7 @@ export default {
 
       if (files.length) {
         //* exception for pdf
-        if (files[0].type === "application/pdf") {
+        if (files[0].type === 'application/pdf') {
           handleFile(true);
         } else {
           this.form.attachment_file.errors = [];
@@ -214,18 +241,18 @@ export default {
 
     checkForm() {
       let isValid = true;
-      if (this.form.title.value === "") {
-        this.form.title.errors = ["Veuillez compléter ce champ."];
+      if (this.form.title.value === '') {
+        this.form.title.errors = ['Veuillez compléter ce champ.'];
         document
           .getElementById(this.form.title.id_for_error)
-          .scrollIntoView({ block: "start", inline: "nearest" });
+          .scrollIntoView({ block: 'start', inline: 'nearest' });
         isValid = false;
       } else if (this.form.attachment_file.value === null) {
-        this.form.attachment_file.errors = ["Veuillez compléter ce champ."];
+        this.form.attachment_file.errors = ['Veuillez compléter ce champ.'];
         this.form.title.errors = [];
         document
           .getElementById(this.form.attachment_file.id_for_error)
-          .scrollIntoView({ block: "start", inline: "nearest" });
+          .scrollIntoView({ block: 'start', inline: 'nearest' });
         isValid = false;
       } else {
         this.form.title.errors = [];
@@ -234,9 +261,5 @@ export default {
       return isValid;
     },
   },
-
-  mounted() {
-    this.initForm(this.attachmentForm);
-  },
 };
 </script>
\ No newline at end of file
diff --git a/src/components/feature/FeatureExtraForm.vue b/src/components/feature/FeatureExtraForm.vue
index 3171439c2262ff1711068dcad8abc6d2d2b21c8e..33a2216c102d46e9027cf8a67ce5a96535311651 100644
--- a/src/components/feature/FeatureExtraForm.vue
+++ b/src/components/feature/FeatureExtraForm.vue
@@ -1,16 +1,22 @@
 <template>
-  <div v-frag v-if="field.field_type === 'char'">
+  <div
+    v-if="field.field_type === 'char'"
+    v-frag
+  >
     <label for="field.name">{{ field.label }}</label>
     <input
+      :id="field.name"
+      :value="field.value"
       type="text"
       :name="field.name"
-      :id="field.name"
-      v-model="field.value"
       @blur="updateStore_extra_form"
-    />
+    >
   </div>
 
-  <div v-frag v-else-if="field.field_type === 'list'">
+  <div
+    v-else-if="field.field_type === 'list'"
+    v-frag
+  >
     <label for="field.name">{{ field.label }}</label>
     <Dropdown
       :options="field.options"
@@ -18,72 +24,87 @@
       :selection.sync="selected_extra_form_list"
     />
   </div>
-  <div v-frag v-else-if="field.field_type === 'integer'">
+  <div
+    v-else-if="field.field_type === 'integer'"
+    v-frag
+  >
     <label for="field.name">{{ field.label }}</label>
     <div class="ui input">
       <!-- //* si click sur fléche dans champ input, pas de focus, donc pas de blur, donc utilisation de @change -->
       <input
+        :id="field.name"
+        :value="field.value"
         type="number"
         :name="field.name"
-        :id="field.name"
-        v-model.number="field.value"
         @change="updateStore_extra_form"
-      />
+      >
     </div>
   </div>
-  <div v-frag v-else-if="field.field_type === 'boolean'">
+  <div
+    v-else-if="field.field_type === 'boolean'"
+    v-frag
+  >
     <div class="ui checkbox">
       <input
+        :id="field.name"
         class="hidden"
         type="checkbox"
         :checked="field.value"
         :name="field.name"
-        :id="field.name"
         @change="updateStore_extra_form"
-      />
+      >
       <label for="field.name">{{ field.label }}</label>
     </div>
   </div>
-  <div v-frag v-else-if="field.field_type === 'date'">
+  <div
+    v-else-if="field.field_type === 'date'"
+    v-frag
+  >
     <label for="field.name">{{ field.label }}</label>
     <input
+      :id="field.name"
+      :value="field.value"
       type="date"
       :name="field.name"
-      :id="field.name"
-      v-model="field.value"
       @blur="updateStore_extra_form"
-    />
+    >
   </div>
-  <div v-frag v-else-if="field.field_type === 'decimal'">
+  <div
+    v-else-if="field.field_type === 'decimal'"
+    v-frag
+  >
     <label for="field.name">{{ field.label }}</label>
     <div class="ui input">
       <input
+        :id="field.name"
+        :value="field.value"
         type="number"
         step=".01"
         :name="field.name"
-        :id="field.name"
-        v-model.number="field.value"
         @change="updateStore_extra_form"
-      />
+      >
     </div>
   </div>
-  <div v-frag v-else-if="field.field_type === 'text'">
+  <div
+    v-else-if="field.field_type === 'text'"
+    v-frag
+  >
     <label :for="field.name">{{ field.label }}</label>
     <textarea
+      :value="field.value"
       :name="field.name"
       rows="3"
-      v-model="field.value"
       @blur="updateStore_extra_form"
-    ></textarea>
+    />
   </div>
 </template>
 
 <script>
-import frag from "vue-frag";
-import Dropdown from "@/components/Dropdown.vue";
+import frag from 'vue-frag';
+import Dropdown from '@/components/Dropdown.vue';
 
 export default {
-  name: "FeatureExtraForm",
+  name: 'FeatureExtraForm',
 
   directives: {
     frag,
@@ -93,18 +114,23 @@ export default {
     Dropdown,
   },
 
-  props: ["field"],
+  props: {
+    field: {
+      type: Object,
+      default: null,
+    }
+  },
 
   computed: {
     selected_extra_form_list: {
       get() {
-        return this.field.value || "";
+        return this.field.value || '';
       },
       set(newValue) {
         //* set the value selected in the dropdown
         let newExtraForm = this.field;
-        newExtraForm["value"] = newValue;
-        this.$store.commit("feature/UPDATE_EXTRA_FORM", newExtraForm);
+        newExtraForm['value'] = newValue;
+        this.$store.commit('feature/UPDATE_EXTRA_FORM', newExtraForm);
       },
     },
   },
@@ -112,12 +138,12 @@ export default {
   methods: {
     updateStore_extra_form(evt) {
       let newExtraForm = this.field;
-      if (this.field.field_type === "boolean") {
-        newExtraForm["value"] = evt.target.checked; //* if checkbox use "checked"
+      if (this.field.field_type === 'boolean') {
+        newExtraForm['value'] = evt.target.checked; //* if checkbox use "checked"
       } else {
-        newExtraForm["value"] = evt.target.value;
+        newExtraForm['value'] = evt.target.value;
       }
-      this.$store.commit("feature/UPDATE_EXTRA_FORM", newExtraForm);
+      this.$store.commit('feature/UPDATE_EXTRA_FORM', newExtraForm);
     },
   },
 };
diff --git a/src/components/feature/FeatureLinkedForm.vue b/src/components/feature/FeatureLinkedForm.vue
index 27c60fbd5eaa879ae80d94c40df07bb04de5cc56..09f5686322a21c53c5d2ddf82fd8e7911add0eb2 100644
--- a/src/components/feature/FeatureLinkedForm.vue
+++ b/src/components/feature/FeatureLinkedForm.vue
@@ -3,15 +3,23 @@
     <h4>
       Liaison
       <button
-        @click="remove_linked_formset"
         class="ui small compact right floated icon button remove-formset"
         type="button"
+        @click="remove_linked_formset"
       >
-        <i class="ui times icon"></i>
+        <i class="ui times icon" />
       </button>
     </h4>
-    <ul id="errorlist-links" class="errorlist">
-      <li v-for="error in form.errors" :key="error" v-html="error"></li>
+    <ul
+      id="errorlist-links"
+      class="errorlist"
+    >
+      <li
+        v-for="error in form.errors"
+        :key="error"
+      >
+        {{ error }}
+      </li>
     </ul>
     <div class="visible-fields">
       <div class="two fields">
@@ -42,52 +50,57 @@
 </template>
 
 <script>
-import Dropdown from "@/components/Dropdown.vue";
+import Dropdown from '@/components/Dropdown.vue';
 import SearchFeature from '@/components/SearchFeature.vue';
 
 export default {
-  name: "FeatureLinkedForm",
-
-  props: ["linkedForm", "features"],
+  name: 'FeatureLinkedForm',
 
   components: {
     Dropdown,
     SearchFeature
   },
 
+  props: {
+    linkedForm: {
+      type: Object,
+      default: null,
+    }
+  },
+
   data() {
     return {
       form: {
         errors: null,
         relation_type: {
           errors: null,
-          id_for_label: "relation_type",
-          html_name: "relation_type",
-          label: "Type de liaison",
+          id_for_label: 'relation_type',
+          html_name: 'relation_type',
+          label: 'Type de liaison',
           value: {
-            name: "Doublon",
-            value: "doublon",
+            name: 'Doublon',
+            value: 'doublon',
           },
         },
         feature_to: {
           errors: null,
-          id_for_label: "feature_to",
+          id_for_label: 'feature_to',
           field: {
             max_length: 30,
           },
-          html_name: "feature_to",
-          label: "Signalement lié",
+          html_name: 'feature_to',
+          label: 'Signalement lié',
           value: {
-            name: "",
-            value: "",
+            name: '',
+            value: '',
           },
         },
       },
       relationTypeChoices: [
-        { name: "Doublon", value: "doublon" },
-        { name: "Remplace", value: "remplace" },
-        { name: "Est remplacé par", value: "est_remplace_par" },
-        { name: "Dépend de", value: "depend_de" },
+        { name: 'Doublon', value: 'doublon' },
+        { name: 'Remplace', value: 'remplace' },
+        { name: 'Est remplacé par', value: 'est_remplace_par' },
+        { name: 'Dépend de', value: 'depend_de' },
       ],
     };
   },
@@ -107,15 +120,21 @@ export default {
     }
   },
 
+  mounted() {
+    if (this.linkedForm.relation_type) {
+      this.getExistingRelation_type();
+    }
+  },
+
   methods: {
     formatDate(value) {
       let date = new Date(value);
-      date = date.toLocaleString().replace(",", "");
+      date = date.toLocaleString().replace(',', '');
       return date.substr(0, date.length - 3); //* quick & dirty way to remove seconds from date
     },
 
     remove_linked_formset() {
-      this.$store.commit("feature/REMOVE_LINKED_FORM", this.linkedForm.dataKey);
+      this.$store.commit('feature/REMOVE_LINKED_FORM', this.linkedForm.dataKey);
     },
 
     selectFeatureTo(e) {
@@ -123,7 +142,7 @@ export default {
     },
 
     updateStore() {
-      this.$store.commit("feature/UPDATE_LINKED_FORM", {
+      this.$store.commit('feature/UPDATE_LINKED_FORM', {
         dataKey: this.linkedForm.dataKey,
         relation_type: this.form.relation_type.value.value,
         feature_to: {
@@ -133,13 +152,13 @@ export default {
     },
 
     checkForm() {
-      if (this.form.feature_to.value === "") {
+      if (this.form.feature_to.value === '') {
         this.form.errors = [
-          "<strong>Choisir un signalement lié</strong><br/> Pourriez-vous choisir un signalement pour la nouvelle liaison ?",
+          '<strong>Choisir un signalement lié</strong><br/> Pourriez-vous choisir un signalement pour la nouvelle liaison ?',
         ];
         document
-          .getElementById("errorlist-links")
-          .scrollIntoView({ block: "start", inline: "nearest" });
+          .getElementById('errorlist-links')
+          .scrollIntoView({ block: 'start', inline: 'nearest' });
         return false;
       }
       this.form.errors = [];
@@ -164,11 +183,5 @@ export default {
       }
     },
   },
-
-  mounted() {
-    if (this.linkedForm.relation_type) {
-      this.getExistingRelation_type();
-    }
-  },
 };
 </script>
\ No newline at end of file
diff --git a/src/components/feature/FeatureListTable.vue b/src/components/feature/FeatureListTable.vue
index 5aa26043cf82cb948b39470a50b4cae4fc274e64..341c018889d7d781acf3994642c5f723c727b845 100644
--- a/src/components/feature/FeatureListTable.vue
+++ b/src/components/feature/FeatureListTable.vue
@@ -1,32 +1,46 @@
-
 <template>
-  <div data-tab="list" class="dataTables_wrapper no-footer">
-    <table id="table-features" class="ui compact table dataTable">
+  <div
+    data-tab="list"
+    class="dataTables_wrapper no-footer"
+  >
+    <table
+      id="table-features"
+      class="ui compact table dataTable"
+    >
       <thead>
         <tr>
           <th class="dt-center">
-            <div @click="switchMode" class="switch-buttons pointer" :data-tooltip="`Passer en mode ${mode === 'modify' ? 'suppression':'édition'}`">
-              <div><i :class="['icon pencil', {disabled: mode !== 'modify'}]"></i></div>
+            <div
+              class="switch-buttons pointer"
+              :data-tooltip="`Passer en mode ${mode === 'modify' ? 'suppression':'édition'}`"
+              @click="switchMode"
+            >
+              <div><i :class="['icon pencil', {disabled: mode !== 'modify'}]" /></div>
               <span class="grey">|&nbsp;</span>
-              <div><i :class="['icon trash', {disabled: mode !== 'delete'}]"></i></div>
+              <div><i :class="['icon trash', {disabled: mode !== 'delete'}]" /></div>
             </div>
           </th>
 
           <th class="dt-center">
-            <div class="pointer" @click="changeSort('status')">
-
-            Statut
-            <i
-              :class="{
-                down: isSortedAsc('status'),
-                up: isSortedDesc('status'),
-              }"
-              class="icon sort"
-            />
+            <div
+              class="pointer"
+              @click="changeSort('status')"
+            >
+              Statut
+              <i
+                :class="{
+                  down: isSortedAsc('status'),
+                  up: isSortedDesc('status'),
+                }"
+                class="icon sort"
+              />
             </div>
           </th>
           <th class="dt-center">
-            <div class="pointer" @click="changeSort('feature_type')">
+            <div
+              class="pointer"
+              @click="changeSort('feature_type')"
+            >
               Type
               <i
                 :class="{
@@ -38,31 +52,43 @@
             </div>
           </th>
           <th class="dt-center">
-            <div class="pointer" @click="changeSort('title')">
-            Nom
-            <i
-              :class="{
-                down: isSortedAsc('title'),
-                up: isSortedDesc('title'),
-              }"
-              class="icon sort"
-            />
+            <div
+              class="pointer"
+              @click="changeSort('title')"
+            >
+              Nom
+              <i
+                :class="{
+                  down: isSortedAsc('title'),
+                  up: isSortedDesc('title'),
+                }"
+                class="icon sort"
+              />
             </div>
           </th>
           <th class="dt-center">
-            <div class="pointer" @click="changeSort('updated_on')">
-            Dernière modification
-            <i
-              :class="{
-                down: isSortedAsc('updated_on'),
-                up: isSortedDesc('updated_on'),
-              }"
-              class="icon sort"
-            />
+            <div
+              class="pointer"
+              @click="changeSort('updated_on')"
+            >
+              Dernière modification
+              <i
+                :class="{
+                  down: isSortedAsc('updated_on'),
+                  up: isSortedDesc('updated_on'),
+                }"
+                class="icon sort"
+              />
             </div>
           </th>
-          <th class="dt-center" v-if="user">
-            <div class="pointer" @click="changeSort('display_creator')">
+          <th
+            v-if="user"
+            class="dt-center"
+          >
+            <div
+              class="pointer"
+              @click="changeSort('display_creator')"
+            >
               Auteur
               <i
                 :class="{
@@ -73,8 +99,14 @@
               />
             </div>
           </th>
-          <th class="dt-center" v-if="user">
-            <div class="pointer" @click="changeSort('display_last_editor')">
+          <th
+            v-if="user"
+            class="dt-center"
+          >
+            <div
+              class="pointer"
+              @click="changeSort('display_last_editor')"
+            >
               Dernier éditeur
               <i
                 :class="{
@@ -88,24 +120,25 @@
         </tr>
       </thead>
       <tbody>
-        <tr v-for="(feature, index) in paginatedFeatures" :key="index">
+        <tr
+          v-for="(feature, index) in paginatedFeatures"
+          :key="index"
+        >
           <td class="dt-center">
             <div
               :class="['ui checkbox', {disabled: !checkRights(feature)}]"
             >
               <input
-                type="checkbox"
-                v-model="checked"
-                @input="storeClickedFeature(feature)"
                 :id="feature.id"
+                v-model="checked"
+                type="checkbox"
                 :value="feature.id"
                 :disabled="!checkRights(feature)"
                 name="select"
-              />
-              <label for="select"></label>
+                @input="storeClickedFeature(feature)"
+              >
+              <label for="select" />
             </div>
-            <!-- {{canDeleteFeature(feature)}}
-            {{canEditFeature(feature)}} -->
           </td>
 
           <td class="dt-center">
@@ -113,25 +146,25 @@
               v-if="feature.properties.status.value === 'archived'"
               data-tooltip="Archivé"
             >
-              <i class="grey archive icon"></i>
+              <i class="grey archive icon" />
             </div>
             <div
               v-else-if="feature.properties.status.value === 'pending'"
               data-tooltip="En attente de publication"
             >
-              <i class="teal hourglass outline icon"></i>
+              <i class="teal hourglass outline icon" />
             </div>
             <div
               v-else-if="feature.properties.status.value === 'published'"
               data-tooltip="Publié"
             >
-              <i class="olive check icon"></i>
+              <i class="olive check icon" />
             </div>
             <div
               v-else-if="feature.properties.status.value === 'draft'"
               data-tooltip="Brouillon"
             >
-              <i class="orange pencil alternate icon"></i>
+              <i class="orange pencil alternate icon" />
             </div>
           </td>
           <td class="dt-center">
@@ -155,21 +188,35 @@
                   slug_signal: feature.properties.slug || feature.id,
                 },
               }"
-              >{{ getFeatureDisplayName(feature) }}</router-link
             >
+              {{ getFeatureDisplayName(feature) }}
+            </router-link>
           </td>
           <td class="dt-center">
             {{ feature.properties.updated_on }}
           </td>
-          <td class="dt-center" v-if="user">
+          <td
+            v-if="user"
+            class="dt-center"
+          >
             {{ getUserName(feature) }}
           </td>
-          <td class="dt-center" v-if="user">
+          <td
+            v-if="user"
+            class="dt-center"
+          >
             {{ feature.properties.display_last_editor }}
           </td>
         </tr>
-        <tr v-if="featuresCount === 0" class="odd">
-          <td colspan="5" class="dataTables_empty" valign="top">
+        <tr
+          v-if="featuresCount === 0"
+          class="odd"
+        >
+          <td
+            colspan="5"
+            class="dataTables_empty"
+            valign="top"
+          >
             Aucune donnée disponible
           </td>
         </tr>
@@ -192,7 +239,6 @@
       class="dataTables_paginate paging_simple_numbers"
     >
       <a
-        @click="$emit('update:page', 'previous')"
         id="table-features_previous"
         :class="[
           'paginate_button previous',
@@ -201,25 +247,23 @@
         aria-controls="table-features"
         data-dt-idx="0"
         tabindex="0"
-        >Précédent</a
-      >
+        @click="$emit('update:page', 'previous')"
+      >Précédent</a>
       <span>
         <span v-if="pagination.currentPage >= 5">
           <a
             key="page1"
-            @click="$emit('update:page', 1)"
             class="paginate_button"
             aria-controls="table-features"
             data-dt-idx="1"
             tabindex="0"
-            >{{ 1 }}</a
-          >
+            @click="$emit('update:page', 1)"
+          >{{ 1 }}</a>
           <span class="ellipsis">…</span>
         </span>
         <a
           v-for="pageNumber in displayedPageNumbers"
           :key="'page' + pageNumber"
-          @click="$emit('update:page', pageNumber)"
           :class="[
             'paginate_button',
             { current: pageNumber === pagination.currentPage },
@@ -227,19 +271,18 @@
           aria-controls="table-features"
           data-dt-idx="1"
           tabindex="0"
-          >{{ pageNumber }}</a
-        >
+          @click="$emit('update:page', pageNumber)"
+        >{{ pageNumber }}</a>
         <span v-if="(lastPageNumber - pagination.currentPage) >= 4">
           <span class="ellipsis">…</span>
           <a
             :key="'page' + lastPageNumber"
-            @click="$emit('update:page', lastPageNumber)"
             class="paginate_button"
             aria-controls="table-features"
             data-dt-idx="1"
             tabindex="0"
-            >{{ lastPageNumber }}</a
-          >
+            @click="$emit('update:page', lastPageNumber)"
+          >{{ lastPageNumber }}</a>
         </span>
       </span>
       <a
@@ -252,39 +295,60 @@
         data-dt-idx="7"
         tabindex="0"
         @click="$emit('update:page', 'next')"
-        >Suivant</a
-      >
+      >Suivant</a>
     </div>
   </div>
 </template>
 
 <script>
-import { mapState, mapGetters } from "vuex";
+
+import { mapState, mapGetters } from 'vuex';
 
 export default {
-  name: "FeatureListTable",
-
-  props: [
-    "paginatedFeatures",
-    "checkedFeatures",
-    "clickedFeatures",
-    "featuresCount",
-    "pagination",
-    "sort",
-    "mode"
-  ],
+  name: 'FeatureListTable',
+
+  props: {
+    paginatedFeatures: {
+      type: Array,
+      default: null,
+    },
+    checkedFeatures: {
+      type: Array,
+      default: null,
+    },
+    clickedFeatures: {
+      type: Array,
+      default: null,
+    },
+    featuresCount: {
+      type: Number,
+      default: 0,
+    },
+    pagination: {
+      type: Object,
+      default: null,
+    },
+    sort: {
+      type: Object,
+      default: null,
+    },
+    mode: {
+      type: String,
+      default: null,
+    }
+  },
 
   computed: {
-    ...mapState(["user"]),
-    ...mapGetters(["project", "permissions"]),
-    ...mapState(["user", "USER_LEVEL_PROJECTS"]),
+    ...mapState(['user']),
+    ...mapGetters(['project', 'permissions']),
+    ...mapState(['user', 'USER_LEVEL_PROJECTS']),
 
     checked: {
       get() {
         return this.checkedFeatures;
       },
       set(newChecked) {
-        this.$store.commit("feature/UPDATE_CHECKED_FEATURES", newChecked);
+        this.$store.commit('feature/UPDATE_CHECKED_FEATURES', newChecked);
       },
     },
 
@@ -310,14 +374,14 @@ export default {
 
     displayedPageNumbers() {
       //* s'il y a moins de 5 pages, renvoyer toutes les pages
-      if (this.lastPageNumber < 5) return this.pageNumbers
+      if (this.lastPageNumber < 5) return this.pageNumbers;
       //* si la page courante est inférieur à 5, la liste commence à l'index 0 et on retourne 5 pages
       let firstPageInList = 0;
       let pagesQuantity = 5;
       //* à partir de la 5ième page et jusqu'à la 4ième page avant la fin : n'afficher que 3 page entre les ellipses et la page courante doit être au milieu
       if (this.pagination.currentPage >= 5 && !((this.lastPageNumber - this.pagination.currentPage) < 4)) {
         firstPageInList = this.pagination.currentPage - 2;
-        pagesQuantity = 3
+        pagesQuantity = 3;
       }
       //* à partir de 4 résultat avant la fin afficher seulement les 5 derniers résultats
       if ((this.lastPageNumber - this.pagination.currentPage) < 4) {
@@ -326,57 +390,60 @@ export default {
       return this.pageNumbers.slice(firstPageInList, firstPageInList + pagesQuantity);
     },
   },
+  destroyed() {
+    this.$store.commit('feature/UPDATE_CHECKED_FEATURES', []);
+  },
 
   methods: {
     storeClickedFeature(feature) {
-      this.clickedFeatures.push({feature_id: feature.id, feature_type: feature.properties.feature_type.slug})
+      this.$emit('update:clickedFeatures', [...this.clickedFeatures, { feature_id: feature.id, feature_type: feature.properties.feature_type.slug }]);
     },
 
     canDeleteFeature(feature) {
       return feature.properties.creator.username !== this.user.username &&
                   !this.user.is_superuser &&
-                  !this.permissions.is_project_administrator
+                  !this.permissions.is_project_administrator;
     },
 
     canEditFeature(feature) {
       const userStatus = this.USER_LEVEL_PROJECTS[this.project.slug];
       const access = {
-        "Administrateur projet" : ["draft", "published", "archived"],
-        "Modérateur" : ["pending"],
-        "Super Contributeur" : ["draft", this.project.moderation ? "pending" : "published"],
-        "Contributeur" : ["draft", this.project.moderation ? "pending" : "published"],
+        'Administrateur projet' : ['draft', 'published', 'archived'],
+        Modérateur : ['pending'],
+        'Super Contributeur' : ['draft', this.project.moderation ? 'pending' : 'published'],
+        Contributeur : ['draft', this.project.moderation ? 'pending' : 'published'],
       };
 
       //if (userStatus === "Super Contributeur" || userStatus === "Contributeur") { //? should super contributeur behave the same, I don't think so
-      if (userStatus === "Contributeur" && feature.properties.creator.username !== this.user.username) {
+      if (userStatus === 'Contributeur' && feature.properties.creator.username !== this.user.username) {
         return false;
       } else if (access[userStatus]) {
         return access[userStatus].includes(feature.properties.status.value);
       } else {
-        return false
+        return false;
       }
     },
 
     checkRights(feature) {
       switch (this.mode) {
-        case 'modify':
-          return this.canEditFeature(feature)
-        case 'delete':
-          return this.canDeleteFeature(feature)
+      case 'modify':
+        return this.canEditFeature(feature);
+      case 'delete':
+        return this.canDeleteFeature(feature);
       } 
     },
 
     switchMode() {
       this.$emit('update:mode', this.mode === 'modify' ? 'delete' : 'modify');
       this.$emit('update:clickedFeatures', []);
-      this.$store.commit("feature/UPDATE_CHECKED_FEATURES", []);
+      this.$store.commit('feature/UPDATE_CHECKED_FEATURES', []);
     },
     
     getUserName(feature) {
       if (!feature.properties.creator) {
-        return " ---- ";
+        return ' ---- ';
       }
-      return feature.properties.creator.username || " ---- ";
+      return feature.properties.creator.username || ' ---- ';
     },
     getFeatureDisplayName(feature) {
       return feature.properties.title || feature.id;
@@ -391,21 +458,16 @@ export default {
 
     changeSort(column) {
       if (this.sort.column === column) {
-        //changer order
-        this.$emit("update:sort", {
+        //changer only order
+        this.$emit('update:sort', {
           column: this.sort.column,
           ascending: !this.sort.ascending,
         });
-      } else {
-        this.sort.column = column;
-        this.sort.ascending = true;
-        this.$emit("update:sort", { column, ascending: true });
+      } else { // change column and reset order
+        this.$emit('update:sort', { column, ascending: true });
       }
     },
   },
-  destroyed() {
-    this.$store.commit("feature/UPDATE_CHECKED_FEATURES", []);
-  },
 };
 </script>
 
diff --git a/src/components/feature/Feature_edit_modal.vue b/src/components/feature/Feature_edit_modal.vue
index 7f41a221211877a8603e34ab97075755a2f448e0..f7474fe277301a05a425883a673d22f91038ed2a 100644
--- a/src/components/feature/Feature_edit_modal.vue
+++ b/src/components/feature/Feature_edit_modal.vue
@@ -1,10 +1,14 @@
 
 <template>
   <div class="ui mini modal">
-    <i class="close icon"></i>
+    <i class="close icon" />
     <div class="content">
       <h3>Importer une image géoréférencée</h3>
-      <form id="form-geo-image" class="ui form" enctype="multipart/form-data">
+      <form
+        id="form-geo-image"
+        class="ui form"
+        enctype="multipart/form-data"
+      >
         {% csrf_token %}
         <p>
           Attention, si vous avez déjà saisi une géométrie, celle issue de
@@ -13,19 +17,25 @@
 
         <div class="field">
           <label>Image (png ou jpeg)</label>
-          <label class="ui icon button" for="image_file">
-            <i class="file icon"></i>
+          <label
+            class="ui icon button"
+            for="image_file"
+          >
+            <i class="file icon" />
             <span class="label">Sélectionner une image ...</span>
           </label>
           <input
+            id="image_file"
             type="file"
             accept="image/jpeg, image/png"
             style="display: none"
             name="image_file"
             class="image_file"
-            id="image_file"
+          >
+          <p
+            class="error-message"
+            style="color: red"
           />
-          <p class="error-message" style="color: red"></p>
         </div>
 
         <button
@@ -34,7 +44,7 @@
           class="ui positive right labeled icon button"
         >
           Importer
-          <i class="checkmark icon"></i>
+          <i class="checkmark icon" />
         </button>
       </form>
     </div>
@@ -43,6 +53,6 @@
 
 <script>
 export default {
-    name: "Feature_edit_modal"
-}
+  name: 'FeatureEditModal'
+};
 </script>
\ No newline at end of file
diff --git a/src/components/feature_type/FeatureTypeCustomForm.vue b/src/components/feature_type/FeatureTypeCustomForm.vue
index 19e82015335a96fe05ec0bfdd7c5653c2bca796b..ccf472c049ad181254a7f7ac78647a0a958fe322 100644
--- a/src/components/feature_type/FeatureTypeCustomForm.vue
+++ b/src/components/feature_type/FeatureTypeCustomForm.vue
@@ -3,11 +3,11 @@
     <h4>
       Champ personnalisé
       <button
-        @click="removeCustomForm()"
         class="ui small compact right floated icon button remove-field"
         type="button"
+        @click="removeCustomForm()"
       >
-        <i class="ui times icon"></i>
+        <i class="ui times icon" />
       </button>
     </h4>
     <div class="visible-fields">
@@ -15,17 +15,23 @@
         <div class="required field">
           <label :for="form.label.id_for_label">{{ form.label.label }}</label>
           <input
+            :id="form.label.id_for_label"
+            v-model="form.label.value"
             type="text"
             required
             :maxlength="form.label.field.max_length"
             :name="form.label.html_name"
-            :id="form.label.id_for_label"
-            v-model="form.label.value"
             @blur="updateStore"
-          />
+          >
           <small>{{ form.label.help_text }}</small>
-          <ul id="errorlist" class="errorlist">
-            <li v-for="error in form.label.errors" :key="error">
+          <ul
+            id="errorlist"
+            class="errorlist"
+          >
+            <li
+              v-for="error in form.label.errors"
+              :key="error"
+            >
               {{ error }}
             </li>
           </ul>
@@ -34,17 +40,23 @@
         <div class="required field">
           <label :for="form.name.id_for_label">{{ form.name.label }}</label>
           <input
+            :id="form.name.id_for_label"
+            v-model="form.name.value"
             type="text"
             required
             :maxlength="form.name.field.max_length"
             :name="form.name.html_name"
-            :id="form.name.id_for_label"
-            v-model="form.name.value"
             @blur="updateStore"
-          />
+          >
           <small>{{ form.name.help_text }}</small>
-          <ul id="errorlist" class="errorlist">
-            <li v-for="error in form.name.errors" :key="error">
+          <ul
+            id="errorlist"
+            class="errorlist"
+          >
+            <li
+              v-for="error in form.name.errors"
+              :key="error"
+            >
               {{ error }}
             </li>
           </ul>
@@ -58,17 +70,23 @@
           }}</label>
           <div class="ui input">
             <input
+              :id="form.position.id_for_label"
+              v-model="form.position.value"
               type="number"
               :min="form.position.field.min_value"
               :name="form.position.html_name"
-              :id="form.position.id_for_label"
-              v-model="form.position.value"
               @change="updateStore"
-            />
+            >
           </div>
           <small>{{ form.position.help_text }}</small>
-          <ul id="errorlist" class="errorlist">
-            <li v-for="error in form.position.errors" :key="error">
+          <ul
+            id="errorlist"
+            class="errorlist"
+          >
+            <li
+              v-for="error in form.position.errors"
+              :key="error"
+            >
               {{ error }}
             </li>
           </ul>
@@ -84,8 +102,14 @@
             :selected="selectedFieldType"
             :selection.sync="selectedFieldType"
           />
-          <ul id="errorlist" class="errorlist">
-            <li v-for="error in form.field_type.errors" :key="error">
+          <ul
+            id="errorlist"
+            class="errorlist"
+          >
+            <li
+              v-for="error in form.field_type.errors"
+              :key="error"
+            >
               {{ error }}
             </li>
           </ul>
@@ -99,16 +123,22 @@
             form.options.label
           }}</label>
           <input
+            :id="form.options.id_for_label"
+            v-model="arrayOption"
             type="text"
             :maxlength="form.options.field.max_length"
             :name="form.options.html_name"
-            :id="form.options.id_for_label"
-            v-model="arrayOption"
             class="options-field"
-          />
+          >
           <small>{{ form.options.help_text }}</small>
-          <ul id="errorlist" class="errorlist">
-            <li v-for="error in form.options.errors" :key="error">
+          <ul
+            id="errorlist"
+            class="errorlist"
+          >
+            <li
+              v-for="error in form.options.errors"
+              :key="error"
+            >
               {{ error }}
             </li>
           </ul>
@@ -119,36 +149,45 @@
 </template>
 
 <script>
-import Dropdown from "@/components/Dropdown.vue";
+import Dropdown from '@/components/Dropdown.vue';
 
 export default {
-  name: "FeatureTypeCustomForm",
+  name: 'FeatureTypeCustomForm',
 
   components: {
     Dropdown,
   },
 
-  props: ["customForm", "selectedColorStyle"],
+  props: {
+    customForm: {
+      type: Object,
+      default: null,
+    },
+    selectedColorStyle: {
+      type: String,
+      default: null,
+    },
+  },
 
   data() {
     return {
       fieldTypeChoices: [
-        { name: "Booléen", value: "boolean" },
-        { name: "Chaîne de caractères", value: "char" },
-        { name: "Date", value: "date" },
-        { name: "Liste de valeurs", value: "list" },
-        { name: "Nombre entier", value: "integer" },
-        { name: "Nombre décimal", value: "decimal" },
-        { name: "Texte multiligne", value: "text" },
+        { name: 'Booléen', value: 'boolean' },
+        { name: 'Chaîne de caractères', value: 'char' },
+        { name: 'Date', value: 'date' },
+        { name: 'Liste de valeurs', value: 'list' },
+        { name: 'Nombre entier', value: 'integer' },
+        { name: 'Nombre décimal', value: 'decimal' },
+        { name: 'Texte multiligne', value: 'text' },
       ],
       form: {
         dataKey: 0,
         label: {
           errors: [],
-          id_for_label: "label",
-          label: "Label",
-          help_text: "Nom en language naturel du champ",
-          html_name: "label",
+          id_for_label: 'label',
+          label: 'Label',
+          help_text: 'Nom en language naturel du champ',
+          html_name: 'label',
           field: {
             max_length: 128,
           },
@@ -156,9 +195,9 @@ export default {
         },
         name: {
           errors: [],
-          id_for_label: "name",
-          label: "Nom",
-          html_name: "name",
+          id_for_label: 'name',
+          label: 'Nom',
+          html_name: 'name',
           help_text:
             "Nom technique du champ tel qu'il apparaît dans la base de données ou dans l'export GeoJSON. Seuls les caractères alphanumériques et les traits d'union sont autorisés: a-z, A-Z, 0-9, _ et -)",
           field: {
@@ -168,10 +207,10 @@ export default {
         },
         position: {
           errors: [],
-          id_for_label: "position",
-          label: "Position",
+          id_for_label: 'position',
+          label: 'Position',
           min_value: 0, // ! check if good values (not found)
-          html_name: "position",
+          html_name: 'position',
           help_text:
             "Numéro d'ordre du champ dans le formulaire de saisie du signalement",
           field: {
@@ -181,21 +220,21 @@ export default {
         },
         field_type: {
           errors: [],
-          id_for_label: "field_type",
-          label: "Type de champ",
-          html_name: "field_type",
-          help_text: "",
+          id_for_label: 'field_type',
+          label: 'Type de champ',
+          html_name: 'field_type',
+          help_text: '',
           field: {
             max_length: 50,
           },
-          value: "boolean",
+          value: 'boolean',
         },
         options: {
           errors: [],
-          id_for_label: "options",
-          label: "Options",
-          html_name: "options",
-          help_text: "Valeurs possibles de ce champ, séparées par des virgules",
+          id_for_label: 'options',
+          label: 'Options',
+          html_name: 'options',
+          help_text: 'Valeurs possibles de ce champ, séparées par des virgules',
           field: {
             max_length: 256,
           },
@@ -231,7 +270,7 @@ export default {
       },
       // * create an array, because backend expects an array
       set(newValue) {
-        this.form.options.value = this.trimWhiteSpace(newValue).split(",");
+        this.form.options.value = this.trimWhiteSpace(newValue).split(',');
         if (!this.hasDuplicateOptions()) {
           this.updateStore();
         }
@@ -239,6 +278,11 @@ export default {
     },
   },
 
+  mounted() {
+    //* add datas from store to state to avoid mutating directly store with v-model (not good practice), could have used computed with getter and setter as well
+    this.fillCustomFormData(this.customForm);
+  },
+
   methods: {
     hasDuplicateOptions() {
       this.form.options.errors = [];
@@ -246,7 +290,7 @@ export default {
         new Set(this.form.options.value).size !==
         this.form.options.value.length;
       if (isDup) {
-        this.form.options.errors = ["Veuillez saisir des valeurs différentes"];
+        this.form.options.errors = ['Veuillez saisir des valeurs différentes'];
         return true;
       }
       return false;
@@ -266,7 +310,7 @@ export default {
 
     removeCustomForm() {
       this.$store.commit(
-        "feature_type/REMOVE_CUSTOM_FORM",
+        'feature_type/REMOVE_CUSTOM_FORM',
         this.customForm.dataKey
       );
     },
@@ -280,15 +324,15 @@ export default {
         field_type: this.form.field_type.value,
         options: this.form.options.value,
       };
-      this.$store.commit("feature_type/UPDATE_CUSTOM_FORM", data);
+      this.$store.commit('feature_type/UPDATE_CUSTOM_FORM', data);
       if (this.customForm.name === this.selectedColorStyle ) {
-        this.$emit("update", this.form.options.value);
+        this.$emit('update', this.form.options.value);
       }
     },
 
     trimWhiteSpace(string) {
       // TODO : supprimer les espaces pour chaque option au début et à la fin QUE à la validation
-      return string.replace(/\s*,\s*/gi, ",");
+      return string.replace(/\s*,\s*/gi, ',');
     },
 
     hasRegularCharacters(input) {
@@ -308,12 +352,12 @@ export default {
     },
 
     checkFilledOptions() {
-      if (this.form.field_type.value === "list") {
+      if (this.form.field_type.value === 'list') {
         if (this.form.options.value.length < 1) {
           return false;
         } else if (
           this.form.options.value.length === 1 &&
-          this.form.options.value[0] === ""
+          this.form.options.value[0] === ''
         ) {
           return false;
         }
@@ -327,27 +371,27 @@ export default {
       this.form.options.errors = [];
       if (!this.form.label.value) {
         //* vérifier que le label est renseigné
-        this.form.label.errors = ["Veuillez compléter ce champ."];
+        this.form.label.errors = ['Veuillez compléter ce champ.'];
         return false;
       } else if (!this.form.name.value) {
         //* vérifier que le nom est renseigné
-        this.form.name.errors = ["Veuillez compléter ce champ."];
+        this.form.name.errors = ['Veuillez compléter ce champ.'];
         return false;
       } else if (!this.hasRegularCharacters(this.form.name.value)) {
         //* vérifier qu'il n'y a pas de caractères spéciaux
         this.form.name.errors = [
-          "Veuillez utiliser seulement les caratères autorisés.",
+          'Veuillez utiliser seulement les caratères autorisés.',
         ];
         return false;
       } else if (!this.checkUniqueName()) {
         //* vérifier si les noms sont pas dupliqués
         this.form.name.errors = [
-          "Les champs personnalisés ne peuvent pas avoir des noms similaires.",
+          'Les champs personnalisés ne peuvent pas avoir des noms similaires.',
         ];
         return false;
       } else if (!this.checkFilledOptions()) {
         //* s'il s'agit d'un type liste, vérifier que le champ option est bien renseigné
-        this.form.options.errors = ["Veuillez compléter ce champ."];
+        this.form.options.errors = ['Veuillez compléter ce champ.'];
         return false;
       } else if (this.hasDuplicateOptions()) {
         //* pour le cas d'options dupliqués
@@ -356,10 +400,5 @@ export default {
       return true;
     },
   },
-
-  mounted() {
-    //* add datas from store to state to avoid mutating directly store with v-model (not good practice), could have used computed with getter and setter as well
-    this.fillCustomFormData(this.customForm);
-  },
 };
 </script>
diff --git a/src/components/feature_type/SymbologySelector.vue b/src/components/feature_type/SymbologySelector.vue
index 32c201bc0748bb34e354670d69974ee016be0af1..2aa443c1bc9b187b02b37654ca4d37e926750ff9 100644
--- a/src/components/feature_type/SymbologySelector.vue
+++ b/src/components/feature_type/SymbologySelector.vue
@@ -7,12 +7,12 @@
       <div class="required inline field">
         <label :for="form.color.id_for_label">{{ form.color.label }}</label>
         <input
+          :id="form.color.id_for_label"
+          v-model.lazy="form.color.value"
           type="color"
           required
           :name="form.color.html_name"
-          :id="form.color.id_for_label"
-          v-model.lazy="form.color.value"
-        />
+        >
       </div>
       <!-- <div class="required inline field">
         <label>Symbole</label>
@@ -30,11 +30,13 @@
       </div> -->
     </div>
     <div
+      ref="iconsPickerModal"
       :class="isIconPickerModalOpen ? 'active' : ''"
       class="ui dimmer modal transition"
-      ref="iconsPickerModal"
     >
-      <div class="header">Sélectionnez le symbole pour ce type de signalement :</div>
+      <div class="header">
+        Sélectionnez le symbole pour ce type de signalement :
+      </div>
       <div class="scrolling content">
         <div
           v-for="icon of iconsNamesList"
@@ -50,7 +52,12 @@
         </div>
       </div>
       <div class="actions">
-        <div class="ui cancel button" @click="isIconPickerModalOpen = false;">Fermer</div>
+        <div
+          class="ui cancel button"
+          @click="isIconPickerModalOpen = false;"
+        >
+          Fermer
+        </div>
       </div>
     </div>
   </div>
@@ -97,7 +104,7 @@ export default {
           value: '#000000',
         },
       }
-    }
+    };
   },
 
   watch: {
@@ -130,7 +137,7 @@ export default {
       this.form.icon = icon;
     }
   }
-}
+};
 </script>
 
 <style lang="less" scoped>
diff --git a/src/components/map-layers/SidebarLayers.vue b/src/components/map-layers/SidebarLayers.vue
index 2988e4e103eac542a17d83b7cb30233f9a7d1b85..59c9b2addd2efc52d51f9443d944be6af1ae4aba 100644
--- a/src/components/map-layers/SidebarLayers.vue
+++ b/src/components/map-layers/SidebarLayers.vue
@@ -1,12 +1,15 @@
 <template>
   <div :class="['sidebar-container', { expanded }]">
     <!-- <div class="sidebar-layers"></div> -->
-    <div @click="expanded = !expanded" class="layers-icon">
+    <div
+      class="layers-icon"
+      @click="expanded = !expanded"
+    >
       <!-- // ! svg point d'interrogation pas accepté par linter -->
       <!-- <?xml version="1.0" encoding="iso-8859-1"?> -->
       <svg
-        version="1.1"
         id="Capa_1"
+        version="1.1"
         xmlns="http://www.w3.org/2000/svg"
         xmlns:xlink="http://www.w3.org/1999/xlink"
         x="0px"
@@ -17,6 +20,7 @@
       >
         <g>
           <g>
+            <!-- eslint-disable max-len -->
             <path
               d="M487.298,326.733l-62.304-37.128l62.304-37.128c2.421-1.443,3.904-4.054,3.904-6.872s-1.483-5.429-3.904-6.872
                     l-62.304-37.128l62.304-37.128c3.795-2.262,5.038-7.172,2.776-10.968c-0.68-1.142-1.635-2.096-2.776-2.776l-237.6-141.6
@@ -29,6 +33,7 @@
                     L245.601,377.893L23.625,245.605z M245.601,465.893L23.625,333.605l58.208-34.68l159.672,95.2c2.524,1.504,5.668,1.504,8.192,0
                     l159.672-95.2l58.208,34.68L245.601,465.893z"
             />
+            <!--eslint-enable-->
           </g>
         </g>
       </svg>
@@ -58,21 +63,21 @@
         {{ basemap.title }}
       </div>
       <div
-        :id="`queryable-layers-selector-${basemap.id}`"
         v-if="isQueryable(basemap)"
+        :id="`queryable-layers-selector-${basemap.id}`"
       >
         <b>Couche requêtable</b>
         <Dropdown
-          @update:selection="onQueryLayerChange($event)"
           :options="getQueryableLayers(basemap)"
           :selected="selectedQueryLayer"
           :search="true"
+          @update:selection="onQueryLayerChange($event)"
         />
       </div>
       <div
+        :id="`list-${basemap.id}`"
         :class="{ active: isActive(basemap) }"
         class="content"
-        :id="`list-${basemap.id}`"
         :data-basemap-index="basemap.id"
       >
         <div
@@ -82,22 +87,22 @@
           :data-id="layer.id"
         >
           <p class="layer-handle-sort">
-            <i class="th icon"></i>{{ layer.title }}
+            <i class="th icon" />{{ layer.title }}
           </p>
           <label>Opacité &nbsp;<span>(%)</span></label>
           <div class="range-container">
             <input
-              @change="updateOpacity($event, layer)"
               type="range"
               min="0"
               max="1"
               :value="layer.opacity"
               step="0.01"
-            /><output class="range-output-bubble">{{
+              @change="updateOpacity($event, layer)"
+            ><output class="range-output-bubble">{{
               getOpacity(layer.opacity)
             }}</output>
           </div>
-          <div class="ui divider"></div>
+          <div class="ui divider" />
         </div>
       </div>
     </div>
@@ -105,13 +110,13 @@
 </template>
 
 <script>
-import { mapState } from "vuex";
-import Sortable from "sortablejs";
-import Dropdown from "@/components/Dropdown.vue";
-import { mapUtil } from "@/assets/js/map-util.js";
+import { mapState } from 'vuex';
+import Sortable from 'sortablejs';
+import Dropdown from '@/components/Dropdown.vue';
+import { mapUtil } from '@/assets/js/map-util.js';
 
 export default {
-  name: "SidebarLayers",
+  name: 'SidebarLayers',
 
   components: {
     Dropdown,
@@ -127,7 +132,50 @@ export default {
   },
 
   computed: {
-    ...mapState("map", ["availableLayers"]),
+    ...mapState('map', ['availableLayers']),
+  },
+
+  mounted() {
+    this.baseMaps = this.$store.state.map.basemaps;
+    let project = this.$route.params.slug;
+    const mapOptions =
+      JSON.parse(localStorage.getItem('geocontrib-map-options')) || {};
+    if (mapOptions && mapOptions[project]) {
+      // If already in the storage, we need to check if the admin did some
+      // modification in the basemaps on the server side. The rule is: if one layer has been added
+      // or deleted in the server, then we reset the localstorage.
+      const baseMapsFromLocalstorage = mapOptions[project]['basemaps'];
+      const areChanges = this.areChangesInBasemaps(
+        this.baseMaps,
+        baseMapsFromLocalstorage
+      );
+
+      if (areChanges) {
+        mapOptions[project] = {
+          'map-options': this.baseMaps,
+          'current-basemap-index': 0,
+        };
+        localStorage.setItem(
+          'geocontrib-map-options',
+          JSON.stringify(mapOptions)
+        );
+      } else {
+        this.baseMaps = baseMapsFromLocalstorage;
+      }
+    }
+
+    if (this.baseMaps.length > 0) {
+      this.baseMaps[0].active = true;
+      this.activeBasemap = this.baseMaps[0];
+      this.addLayers(this.baseMaps[0]);
+    } else {
+      mapUtil.addLayers(
+        null,
+        this.$store.state.configuration.DEFAULT_BASE_MAP.SERVICE,
+        this.$store.state.configuration.DEFAULT_BASE_MAP.OPTIONS
+      );
+    }
+    setTimeout(this.initSortable.bind(this), 1000);
   },
 
   methods: {
@@ -139,18 +187,18 @@ export default {
       this.baseMaps.forEach((basemap) => (basemap.active = false));
       basemap.active = true;
       this.activeBasemap = basemap;
-      basemap.title += " "; //weird!! Force refresh
+      basemap.title += ' '; //weird!! Force refresh
       this.addLayers(basemap);
 
-      let mapOptions = localStorage.getItem("geocontrib-map-options") || {};
+      let mapOptions = localStorage.getItem('geocontrib-map-options') || {};
       mapOptions = mapOptions.length ? JSON.parse(mapOptions) : {};
       let project = this.$route.params.slug;
       mapOptions[project] = {
         ...mapOptions[project],
-        "current-basemap-index": basemap.id,
+        'current-basemap-index': basemap.id,
       };
       localStorage.setItem(
-        "geocontrib-map-options",
+        'geocontrib-map-options',
         JSON.stringify(mapOptions)
       );
     },
@@ -176,7 +224,7 @@ export default {
     onlayerMove() {
       // Get the names of the current layers in order.
       const currentLayersNamesInOrder = Array.from(
-        document.getElementsByClassName("layer-item transition visible")
+        document.getElementsByClassName('layer-item transition visible')
       ).map((el) => el.children[0].innerText);
       // Create an array to put the layers in order.
       let movedLayers = [];
@@ -190,7 +238,7 @@ export default {
       movedLayers = movedLayers.filter(function (x) {
         return x !== undefined;
       });
-      const eventOrder = new CustomEvent("change-layers-order", {
+      const eventOrder = new CustomEvent('change-layers-order', {
         detail: {
           layers: movedLayers,
         },
@@ -201,7 +249,7 @@ export default {
     },
 
     setLocalstorageMapOptions(basemaps) {
-      let mapOptions = localStorage.getItem("geocontrib-map-options") || {};
+      let mapOptions = localStorage.getItem('geocontrib-map-options') || {};
       mapOptions = mapOptions.length ? JSON.parse(mapOptions) : {};
       let project = this.$route.params.slug;
       mapOptions[project] = {
@@ -209,7 +257,7 @@ export default {
         basemaps: basemaps,
       };
       localStorage.setItem(
-        "geocontrib-map-options",
+        'geocontrib-map-options',
         JSON.stringify(mapOptions)
       );
     },
@@ -220,14 +268,14 @@ export default {
         if(element) {
           new Sortable(element, {
             animation: 150,
-            handle: ".layer-handle-sort", // The element that is active to drag
-            ghostClass: "blue-background-class",
-            dragClass: "white-opacity-background-class",
+            handle: '.layer-handle-sort', // The element that is active to drag
+            ghostClass: 'blue-background-class',
+            dragClass: 'white-opacity-background-class',
             onEnd: this.onlayerMove.bind(this),
           });
         }
         else{
-          console.error(`list-${basemap.id} not found in dom`)
+          console.error(`list-${basemap.id} not found in dom`);
         }
 
       });
@@ -312,49 +360,6 @@ export default {
       mapUtil.addLayers(baseMap.layers.slice().reverse(), null, null);
     },
   },
-
-  mounted() {
-    this.baseMaps = this.$store.state.map.basemaps;
-    let project = this.$route.params.slug;
-    const mapOptions =
-      JSON.parse(localStorage.getItem("geocontrib-map-options")) || {};
-    if (mapOptions && mapOptions[project]) {
-      // If already in the storage, we need to check if the admin did some
-      // modification in the basemaps on the server side. The rule is: if one layer has been added
-      // or deleted in the server, then we reset the localstorage.
-      const baseMapsFromLocalstorage = mapOptions[project]["basemaps"];
-      const areChanges = this.areChangesInBasemaps(
-        this.baseMaps,
-        baseMapsFromLocalstorage
-      );
-
-      if (areChanges) {
-        mapOptions[project] = {
-          "map-options": this.baseMaps,
-          "current-basemap-index": 0,
-        };
-        localStorage.setItem(
-          "geocontrib-map-options",
-          JSON.stringify(mapOptions)
-        );
-      } else {
-        this.baseMaps = baseMapsFromLocalstorage;
-      }
-    }
-
-    if (this.baseMaps.length > 0) {
-      this.baseMaps[0].active = true;
-      this.activeBasemap = this.baseMaps[0];
-      this.addLayers(this.baseMaps[0]);
-    } else {
-      mapUtil.addLayers(
-        null,
-        this.$store.state.configuration.DEFAULT_BASE_MAP.SERVICE,
-        this.$store.state.configuration.DEFAULT_BASE_MAP.OPTIONS
-      );
-    }
-    setTimeout(this.initSortable.bind(this), 1000);
-  },
 };
 </script>
 
diff --git a/src/components/project/ProjectMappingContextLayer.vue b/src/components/project/ProjectMappingContextLayer.vue
index cfd82b70d16a14d08c4138848a515550dba02966..46d0968998eba574c939f5578fe4a5b6b7d771e6 100644
--- a/src/components/project/ProjectMappingContextLayer.vue
+++ b/src/components/project/ProjectMappingContextLayer.vue
@@ -1,15 +1,19 @@
 <template>
-  <div :id="layer.dataKey" class="ui segment layer-item">
+  <div
+    :id="layer.dataKey"
+    class="ui segment layer-item"
+  >
     <div class="ui divided form">
-      <div class="field" data-type="layer-field">
-        <label for="form.layer.id_for_label" class="layer-handle-sort">
-          <i class="th icon"></i>couche
+      <div
+        class="field"
+        data-type="layer-field"
+      >
+        <label
+          for="form.layer.id_for_label"
+          class="layer-handle-sort"
+        >
+          <i class="th icon" />couche
         </label>
-        <!-- {% if is_empty %} {# TODO arranger le dropdown pour les ajout à la volée
-        #} {# le selecteur de couche ne s'affichant pas correctement on passe
-        par un field django par defaut en attendant #} -->
-        <!--   {{ form.layer }} -->
-        <!-- {% else %} -->
         <Dropdown
           :options="availableLayerOptions"
           :selected="selectedLayer.name"
@@ -17,7 +21,6 @@
           :search="true"
           :placeholder="placeholder"
         />
-        <!-- {{ form.layer.errors }} -->
       </div>
       <div class="fields">
         <div
@@ -25,30 +28,36 @@
         >
           <label for="opacity">Opacité</label>
           <input
-            type="number"
             v-model.number="layerOpacity"
+            type="number"
             oninput="validity.valid||(value='');"
             step="0.01"
             min="0"
             max="1"
-          />
-          <!-- {{ form.opacity.errors }} -->
+          >
         </div>
         <div class="field three wide">
           <div
-            @click="updateLayer({ ...layer, queryable: !layer.queryable })"
             class="ui checkbox"
+            @click="updateLayer({ ...layer, queryable: !layer.queryable })"
           >
-            <input class="hidden" type="checkbox" v-model="layer.queryable" name="queryable" />
+            <input
+              :checked="layer.queryable"
+              class="hidden" 
+              type="checkbox"
+              name="queryable"
+            >
             <label for="queryable"> Requêtable</label>
           </div>
-          <!-- {{ form.queryable.errors }} -->
         </div>
       </div>
 
-      <div @click="removeLayer" class="field">
+      <div
+        class="field"
+        @click="removeLayer"
+      >
         <div class="ui compact small icon floated button button-hover-red">
-          <i class="ui grey trash alternate icon"></i>
+          <i class="ui grey trash alternate icon" />
           <span>Supprimer cette couche</span>
         </div>
       </div>
@@ -57,20 +66,31 @@
 </template>
 
 <script>
-import Dropdown from "@/components/Dropdown.vue";
-import { mapState } from "vuex";
+import Dropdown from '@/components/Dropdown.vue';
+import { mapState } from 'vuex';
 
 export default {
-  name: "ProjectMappingContextLayer",
-
-  props: ["layer", "basemapid"],
+  name: 'ProjectMappingContextLayer',
 
   components: {
     Dropdown,
   },
 
+  props: {
+    layer:
+     {
+       type: Object,
+       default: null,
+     },
+    basemapid:
+      {
+        type: Number,
+        default: null,
+      },
+  },
+
   computed: {
-    ...mapState("map", ["availableLayers"]),
+    ...mapState('map', ['availableLayers']),
 
     selectedLayer: {
       get() {
@@ -115,42 +135,42 @@ export default {
 
     placeholder: function () {
       return this.selectedLayer && this.selectedLayer.name
-        ? ""
-        : "Choisissez une couche";
+        ? ''
+        : 'Choisissez une couche';
     },
   },
 
+  mounted() {
+    const matchingLayer = this.retrieveLayer(this.layer.title);
+    if (matchingLayer !== undefined) {
+      this.updateLayer({
+        ...this.layer,
+        service: matchingLayer.service,
+        title: matchingLayer.title,
+        id: matchingLayer.id,
+      });
+    }
+  },
+
   methods: {
     retrieveLayer(title) {
       return this.availableLayerOptions.find((el) => el.title === title);
     },
 
     removeLayer() {
-      this.$store.commit("map/DELETE_BASEMAP_LAYER", {
+      this.$store.commit('map/DELETE_BASEMAP_LAYER', {
         basemapId: this.basemapid,
         layerId: this.layer.dataKey,
       });
     },
 
     updateLayer(layer) {
-      this.$store.commit("map/UPDATE_BASEMAP_LAYER", {
+      this.$store.commit('map/UPDATE_BASEMAP_LAYER', {
         basemapId: this.basemapid,
         layerId: this.layer.dataKey,
         layer,
       });
     },
   },
-
-  mounted() {
-    const matchingLayer = this.retrieveLayer(this.layer.title);
-    if (matchingLayer !== undefined) {
-      this.updateLayer({
-        ...this.layer,
-        service: matchingLayer.service,
-        title: matchingLayer.title,
-        id: matchingLayer.id,
-      });
-    }
-  },
 };
 </script>
\ No newline at end of file
diff --git a/src/components/project/project_mapping_basemap.vue b/src/components/project/project_mapping_basemap.vue
index 34399ea8a969706a4f84714d76b0ceb67bc6e3ef..1665ce7cfed78797df4bce22318156a3386de8b0 100644
--- a/src/components/project/project_mapping_basemap.vue
+++ b/src/components/project/project_mapping_basemap.vue
@@ -3,11 +3,12 @@
     <div class="field required">
       <label for="basemap-title">Titre</label>
       <input
-        v-model="basemap.title"
+        :value="basemap.title"
         type="text"
         name="basemap-title"
         required
-      />
+        @input="updateTitle"
+      >
       <ul
         v-if="basemap.errors && basemap.errors.length > 0"
         id="errorlist-title"
@@ -22,8 +23,7 @@
     <div class="nested">
       <div
         :id="`list-${basemap.id}`"
-        v-if="basemap.layers"
-        class="ui segments layers-container"
+        :class="[basemap.layers.length > 0 ? 'ui segments': '', 'layers-container']"
       >
         <ProjectMappingContextLayer
           v-for="layer in basemap.layers"
@@ -34,15 +34,18 @@
       </div>
       <div class="ui buttons">
         <a
-          @click="addLayer"
           class="ui compact small icon left floated button green"
+          @click="addLayer"
         >
-          <i class="ui plus icon"></i>
+          <i class="ui plus icon" />
           <span>Ajouter une couche</span>
         </a>
       </div>
 
-      <div @click="deleteBasemap" class="ui buttons">
+      <div
+        class="ui buttons"
+        @click="deleteBasemap"
+      >
         <a
           class="
             ui
@@ -55,7 +58,7 @@
             button button-hover-green
           "
         >
-          <i class="ui trash alternate icon"></i>
+          <i class="ui trash alternate icon" />
           <span>Supprimer ce fond cartographique</span>
         </a>
       </div>
@@ -64,18 +67,23 @@
 </template>
 
 <script>
-import Sortable from "sortablejs";
-import ProjectMappingContextLayer from "@/components/project/ProjectMappingContextLayer.vue";
+import Sortable from 'sortablejs';
+import ProjectMappingContextLayer from '@/components/project/ProjectMappingContextLayer.vue';
 
 export default {
-  name: "Project_mapping_basemap",
-
-  props: ["basemap"],
+  name: 'ProjectMappingBasemap',
 
   components: {
     ProjectMappingContextLayer,
   },
 
+  props: {
+    basemap: {
+      type: Object,
+      default: null,
+    }
+  },
+
   computed: {
     maxLayersCount: function () {
       return this.basemap.layers.reduce((acc, curr) => {
@@ -88,21 +96,32 @@ export default {
     },
   },
 
+  created() {
+    if (this.basemap.layers) {
+      //* add datakeys to layers coming from api
+      this.fillLayersWithDatakey(this.basemap.layers);
+    }
+  },
+
+  mounted() {
+    this.initSortable();
+  },
+
   methods: {
     deleteBasemap() {
-      this.$store.commit("map/DELETE_BASEMAP", this.basemap.id);
+      this.$store.commit('map/DELETE_BASEMAP', this.basemap.id);
     },
 
     addLayer(layer) {
       const newLayer = {
         dataKey: this.maxLayersCount + 1,
-        opacity: "1.00",
+        opacity: '1.00',
         order: 0,
         queryable: false,
-        title: "Open street map",
+        title: 'Open street map',
         ...layer,
       };
-      this.$store.commit("map/UPDATE_BASEMAP", {
+      this.$store.commit('map/UPDATE_BASEMAP', {
         layers: [...this.basemap.layers, newLayer],
         id: this.basemap.id,
         title: this.basemap.title,
@@ -111,11 +130,18 @@ export default {
     },
 
     updateTitle(evt) {
-      this.$store.commit("map/UPDATE_BASEMAP", {
+      let errors = '';
+      if(evt.target.value === '') { //* delete or add error message while typing
+        errors = 'Veuillez compléter ce champ.';
+      }
+      this.$store.commit('map/UPDATE_BASEMAP', {
         id: this.basemap.id,
-        title: evt.title,
-        errors: evt.errors,
+        title: evt.target.value,
+        errors,
       });
+
+
+
     },
 
     removeLayer(dataKey) {
@@ -124,7 +150,7 @@ export default {
 
     fillLayersWithDatakey(layers) {
       let dataKey = 0;
-      this.$store.commit("map/REPLACE_BASEMAP_LAYERS", {
+      this.$store.commit('map/REPLACE_BASEMAP_LAYERS', {
         basemapId: this.basemap.id,
         layers: layers.map((el) => {
           dataKey += 1;
@@ -134,11 +160,10 @@ export default {
     },
 
     //* drag & drop *//
-
     onlayerMove() {
       //* Get the names of the current layers in order.
       const currentLayersNamesInOrder = Array.from(
-        document.getElementsByClassName("layer-item")
+        document.getElementsByClassName('layer-item')
       ).map((el) => el.id);
 
       //* increment value 'order' in this.basemap.layers looping over layers from template ^
@@ -149,13 +174,13 @@ export default {
           (el) => el.dataKey === Number(id)
         );
         if (matchingLayer) {
-          matchingLayer["order"] = order;
+          matchingLayer['order'] = order;
           movedLayers.push(matchingLayer);
           order += 1;
         }
       }
       //* update the store
-      this.$store.commit("map/UPDATE_BASEMAP", {
+      this.$store.commit('map/UPDATE_BASEMAP', {
         layers: movedLayers,
         id: this.basemap.id,
         title: this.basemap.title,
@@ -166,49 +191,13 @@ export default {
     initSortable() {
       new Sortable(document.getElementById(`list-${this.basemap.id}`), {
         animation: 150,
-        handle: ".layer-handle-sort", // The element that is active to drag
-        ghostClass: "blue-background-class",
-        dragClass: "white-opacity-background-class",
+        handle: '.layer-handle-sort', // The element that is active to drag
+        ghostClass: 'blue-background-class',
+        dragClass: 'white-opacity-background-class',
         onEnd: this.onlayerMove.bind(this),
       });
     },
   },
-
-  watch: {
-    "basemap.title": {
-      deep: true,
-      handler: function (newValue, oldValue) {
-        if (newValue !== oldValue) {
-          this.basemap.title = newValue;
-          if (newValue === "")
-            this.basemap.errors = "Veuillez compléter ce champ.";
-          else this.basemap.errors = "";
-          this.updateTitle(this.basemap);
-        }
-      },
-    },
-  },
-
-  created() {
-    if (this.basemap.layers) {
-      //* add datakeys to layers coming from api
-      this.fillLayersWithDatakey(this.basemap.layers);
-    }
-  },
-  // destroyed(){
-  //   this.errors = [];
-  // }
-
-  mounted() {
-    //* not present in original
-    this.initSortable();
-    //   if (!this.basemap.title) {
-    //     this.$store.commit("map/UPDATE_BASEMAP", {
-    //       id: this.basemap.id,
-    //       title: newValue,
-    //     });
-    //   }
-  },
 };
 </script>
 
diff --git a/src/main.js b/src/main.js
index ce93c0f5b09554c85e0cb868f11aec25d9ee0517..2aaa4ad7377d468b804c8deb1513ee05de3a0e6a 100644
--- a/src/main.js
+++ b/src/main.js
@@ -1,43 +1,43 @@
-const axios = require("axios")
-import Vue from 'vue'
+const axios = require('axios');
+import Vue from 'vue';
 
-import App from './App.vue'
-import './registerServiceWorker'
-import router from '@/router'
-import store from '@/store'
+import App from './App.vue';
+import './registerServiceWorker';
+import router from '@/router';
+import store from '@/store';
 import 'leaflet/dist/leaflet.css';
 import 'leaflet-draw/dist/leaflet.draw.css';
 import '@/assets/resources/leaflet-control-geocoder-1.13.0/Control.Geocoder.css';
-import '@fortawesome/fontawesome-free/css/all.css'
-import '@fortawesome/fontawesome-free/js/all.js'
+import '@fortawesome/fontawesome-free/css/all.css';
+import '@fortawesome/fontawesome-free/js/all.js';
 import { library } from '@fortawesome/fontawesome-svg-core';
 import { fas } from '@fortawesome/free-solid-svg-icons';
 import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
 // Multiselect installation
 import 'vue-multiselect/dist/vue-multiselect.min.css';
 
-library.add(fas)
+library.add(fas);
 
-Vue.component('font-awesome-icon', FontAwesomeIcon);
+Vue.component(FontAwesomeIcon);
 
-Vue.config.productionTip = false
+Vue.config.productionTip = false;
 
 // gestion mise à jour du serviceWorker et du precache
 var refreshing=false;
 if(navigator.serviceWorker){
   navigator.serviceWorker.addEventListener('controllerchange', () => {
     // We'll also need to add 'refreshing' to our data originally set to false.
-    if (refreshing) return
-    refreshing = true
+    if (refreshing) return;
+    refreshing = true;
     // Here the actual reload of the page occurs
-    window.location.reload()
-  })
+    window.location.reload();
+  });
 }
 
 
 
 let onConfigLoaded = function(config){
-  store.commit("SET_CONFIG", config);
+  store.commit('SET_CONFIG', config);
 
   // set title and favico
   document.title= config.VUE_APP_APPLICATION_NAME+' '+config.VUE_APP_APPLICATION_ABSTRACT;
@@ -47,38 +47,38 @@ let onConfigLoaded = function(config){
   link.href = config.VUE_APP_APPLICATION_FAVICO;
   document.head.appendChild(link);
 
-  window.proxy_url=config.VUE_APP_DJANGO_API_BASE+"proxy/";
+  window.proxy_url=config.VUE_APP_DJANGO_API_BASE+'proxy/';
   axios.all([
-    store.dispatch("USER_INFO"),
+    store.dispatch('USER_INFO'),
     store.dispatch('projects/GET_PROJECTS'),
-    store.dispatch("GET_STATIC_PAGES"),
-    store.dispatch("GET_USER_LEVEL_PROJECTS"),
-    store.dispatch("map/GET_AVAILABLE_LAYERS"),
-    store.dispatch("GET_USER_LEVEL_PERMISSIONS"),
-    store.dispatch("GET_LEVELS_PERMISSIONS"),
+    store.dispatch('GET_STATIC_PAGES'),
+    store.dispatch('GET_USER_LEVEL_PROJECTS'),
+    store.dispatch('map/GET_AVAILABLE_LAYERS'),
+    store.dispatch('GET_USER_LEVEL_PERMISSIONS'),
+    store.dispatch('GET_LEVELS_PERMISSIONS'),
   ]).then(axios.spread(function () {
     new Vue({
       router,
       store,
       render: h => h(App)
-    }).$mount('#app')
+    }).$mount('#app');
   }));
 
-}
+};
 
-axios.get("./config/config.json")
+axios.get('./config/config.json')
   .catch((error)=>{
     console.error(error);
-    console.log("try to get From Localstorage");
-    let conf=localStorage.getItem("geontrib_conf");
+    console.log('try to get From Localstorage');
+    let conf=localStorage.getItem('geontrib_conf');
     if(conf){
-      onConfigLoaded(JSON.parse(conf))
+      onConfigLoaded(JSON.parse(conf));
     }
   })
   .then((response) => {
     if (response && response.status === 200) {
-      localStorage.setItem("geontrib_conf",JSON.stringify(response.data));
-      onConfigLoaded(response.data)
+      localStorage.setItem('geontrib_conf',JSON.stringify(response.data));
+      onConfigLoaded(response.data);
     }
   })
   .catch((error) => {
diff --git a/src/registerServiceWorker.js b/src/registerServiceWorker.js
index 0fea28955951af66f5cce9aa2df7e57716b5b329..8b95be07184a3e621b6072a250c1171bc711d80b 100644
--- a/src/registerServiceWorker.js
+++ b/src/registerServiceWorker.js
@@ -1,6 +1,6 @@
 /* eslint-disable no-console */
 
-import { register } from 'register-service-worker'
+import { register } from 'register-service-worker';
 
 if (process.env.NODE_ENV === 'production') {
   register(`${process.env.BASE_URL}service-worker.js`, {
@@ -8,37 +8,37 @@ if (process.env.NODE_ENV === 'production') {
       console.log(
         'App is being served from cache by a service worker.\n' +
         'For more details, visit https://goo.gl/AFskqB'
-      )
+      );
     },
     registered (registration) {
       //console.log('Service worker has been registered.')
       console.log(
         'Service worker has been registered and now polling for updates.'
-      )
+      );
       setInterval(() => {
-        registration.update()
-      }, 10000) // every 10 seconds
+        registration.update();
+      }, 10000); // every 10 seconds
     },
     cached () {
-      console.log('Content has been cached for offline use.')
+      console.log('Content has been cached for offline use.');
     },
     updatefound () {
-      console.log('New content is downloading.')
+      console.log('New content is downloading.');
     },
     updated (registration) {
       alert('Une nouvelle version de l\'application est disponible, l\'application va se recharger');
       console.log('New content is available; please refresh.');
       //
-      if (!registration || !registration.waiting) return
+      if (!registration || !registration.waiting) return;
       // Send message to SW to skip the waiting and activate the new SW
-      registration.waiting.postMessage({ type: 'SKIP_WAITING' })
+      registration.waiting.postMessage({ type: 'SKIP_WAITING' });
       //window.location.reload(true);
     },
     offline () {
-      console.log('No internet connection found. App is running in offline mode.')
+      console.log('No internet connection found. App is running in offline mode.');
     },
     error (error) {
-      console.error('Error during service worker registration:', error)
+      console.error('Error during service worker registration:', error);
     }
-  })
+  });
 }
diff --git a/src/router/index.js b/src/router/index.js
index 85eefd7ddfd95b36b6f5ecd3070303c80f20697d..3a60b4cb03aae86a9675ecf3375298e6ac0bf7c5 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -1,12 +1,12 @@
-import Vue from 'vue'
-import VueRouter from 'vue-router'
-import Projects from '../views/Projects.vue'
+import Vue from 'vue';
+import VueRouter from 'vue-router';
+import Projects from '../views/Projects.vue';
 
-Vue.use(VueRouter)
+Vue.use(VueRouter);
 
-let projectBase = "projet"
-if (window.location.pathname.includes("projet-partage")) {
-  projectBase = "projet-partage"
+let projectBase = 'projet';
+if (window.location.pathname.includes('projet-partage')) {
+  projectBase = 'projet-partage';
 }
 
 const routes = [
@@ -136,7 +136,7 @@ const routes = [
   },
 
   { path: '/:pathMatch(.*)*', name: 'NotFound', component: () => import('../views/NotFound.vue') },
-]
+];
 //let routerHistory = [];
 
 const router = new VueRouter({
@@ -154,6 +154,6 @@ const router = new VueRouter({
     }
     return savedPosition || { x: 0, y: 0 };
   },
-})
+});
 
-export default router
+export default router;
diff --git a/src/service-worker.js b/src/service-worker.js
index 8a743071b19d358e8943689d387cd3225c77e0c8..1b04819c7a0f9e3a915b944b3b5e3d53954d0d27 100644
--- a/src/service-worker.js
+++ b/src/service-worker.js
@@ -1,66 +1,67 @@
+/* global workbox */ //* allow undefined variable for 'workbox' in this file (because global variable) to avoid eslint error
 // custom service-worker.js
 if (workbox) {
-    // adjust log level for displaying workbox logs
-    //workbox.core.setLogLevel(workbox.core.LOG_LEVELS.debug)
+  // adjust log level for displaying workbox logs
+  //workbox.core.setLogLevel(workbox.core.LOG_LEVELS.debug)
 
-    // apply precaching. In the built version, the precacheManifest will
-    // be imported using importScripts (as is workbox itself) and we can 
-    // precache this. This is all we need for precaching
-    workbox.precaching.precacheAndRoute(self.__precacheManifest);
+  // apply precaching. In the built version, the precacheManifest will
+  // be imported using importScripts (as is workbox itself) and we can 
+  // precache this. This is all we need for precaching
+  workbox.precaching.precacheAndRoute(self.__precacheManifest);
 
-    //workbox.core.skipWaiting();
+  //workbox.core.skipWaiting();
 
-    // Make sure to return a specific response for all navigation requests.
-    // Since we have a SPA here, this should be index.html always.
-    // https://stackoverflow.com/questions/49963982/vue-router-history-mode-with-pwa-in-offline-mode
-    workbox.routing.registerNavigationRoute('/geocontrib/index.html', {
-        blacklist: [/\/api/,/\/admin/,/\/media/,/\/cas/],
-      })
+  // Make sure to return a specific response for all navigation requests.
+  // Since we have a SPA here, this should be index.html always.
+  // https://stackoverflow.com/questions/49963982/vue-router-history-mode-with-pwa-in-offline-mode
+  workbox.routing.registerNavigationRoute('/geocontrib/index.html', {
+    blacklist: [/\/api/,/\/admin/,/\/media/,/\/cas/],
+  });
 
-    workbox.routing.registerRoute(
-        new RegExp('.*/config/config.json'),
-        new workbox.strategies.StaleWhileRevalidate({
-            cacheName: 'config',
-        })
-    )
+  workbox.routing.registerRoute(
+    new RegExp('.*/config/config.json'),
+    new workbox.strategies.StaleWhileRevalidate({
+      cacheName: 'config',
+    })
+  );
 
-    workbox.routing.registerRoute(
-        new RegExp('.*/api/.*'),
-        new workbox.strategies.NetworkFirst({
-            cacheName: 'api',
-        })
-    )
-    workbox.routing.registerRoute(
-        /^https:\/\/c\.tile\.openstreetmap\.fr/,
-        new workbox.strategies.CacheFirst({
-            cacheName: 'osm',
-            plugins: [
-                new workbox.cacheableResponse.Plugin({
-                    statuses: [0, 200],
-                }),
-                new workbox.expiration.Plugin({
-                    maxAgeSeconds: 60 * 60 * 24 * 365,
-                    // maxEntries: 30, pour limiter le nombre d'entrée dans le cache
-                }),
-            ],
-        })
-    )
+  workbox.routing.registerRoute(
+    new RegExp('.*/api/.*'),
+    new workbox.strategies.NetworkFirst({
+      cacheName: 'api',
+    })
+  );
+  workbox.routing.registerRoute(
+    /^https:\/\/c\.tile\.openstreetmap\.fr/,
+    new workbox.strategies.CacheFirst({
+      cacheName: 'osm',
+      plugins: [
+        new workbox.cacheableResponse.Plugin({
+          statuses: [0, 200],
+        }),
+        new workbox.expiration.Plugin({
+          maxAgeSeconds: 60 * 60 * 24 * 365,
+          // maxEntries: 30, pour limiter le nombre d'entrée dans le cache
+        }),
+      ],
+    })
+  );
 
 }
 
 // This code listens for the user's confirmation to update the app.
 self.addEventListener('message', (e) => {
-    if (!e.data) {
-        return;
-    }
-    //console.log(e.data);
-    switch (e.data.type) {
-        case 'SKIP_WAITING':
-            self.skipWaiting();
-            break;
-        default:
-            // NOOP
-            break;
-    }
-})
+  if (!e.data) {
+    return;
+  }
+  //console.log(e.data);
+  switch (e.data.type) {
+  case 'SKIP_WAITING':
+    self.skipWaiting();
+    break;
+  default:
+    // NOOP
+    break;
+  }
+});
 
diff --git a/src/services/feature-api.js b/src/services/feature-api.js
index 3b21882327d377f1ea9013f83801ad40519f7c49..a2278387d8e0f5c1f1bd980a3e133d899253d710 100644
--- a/src/services/feature-api.js
+++ b/src/services/feature-api.js
@@ -1,12 +1,12 @@
-import axios from "@/axios-client.js";
-import store from '../store'
+import axios from '@/axios-client.js';
+import store from '../store';
 
 const baseUrl = store.state.configuration.VUE_APP_DJANGO_API_BASE;
 
 const featureAPI = {
   async getFeaturesBbox(project_slug, queryParams) {
     const response = await axios.get(
-      `${baseUrl}projects/${project_slug}/feature-bbox/${queryParams ? '?' + queryParams : ""}`
+      `${baseUrl}projects/${project_slug}/feature-bbox/${queryParams ? '?' + queryParams : ''}`
     );
     if (
       response.status === 200 &&
@@ -63,13 +63,13 @@ const featureAPI = {
   },
 
   async updateFeature({ feature_id, feature_type__slug, project__slug, newStatus }) {
-    let url = `${baseUrl}features/${feature_id}/?feature_type__slug=${feature_type__slug}&project__slug=${project__slug}`
+    let url = `${baseUrl}features/${feature_id}/?feature_type__slug=${feature_type__slug}&project__slug=${project__slug}`;
 
     const response = await axios({
       url,
-      method: "PATCH",
+      method: 'PATCH',
       data: { id: feature_id, status: newStatus, feature_type: feature_type__slug }
-    })
+    });
     if (response.status === 200 && response.data) {
       return response;
     } else {
@@ -93,8 +93,8 @@ const featureAPI = {
 
   async postCommentAttachment({ featureId, file, fileName, commentId, title }) {
     let formdata = new FormData();
-    formdata.append("file", file, fileName);
-    formdata.append("title", title);
+    formdata.append('file', file, fileName);
+    formdata.append('title', title);
 
     const response = await axios.put(
       `${baseUrl}features/${featureId}/comments/${commentId}/upload-file/`, formdata
@@ -125,7 +125,7 @@ const featureAPI = {
 
   async getFeaturesBlob(url) {
     const response = await axios
-      .get(url, { responseType: "blob" })
+      .get(url, { responseType: 'blob' });
     if (
       response.status === 200 &&
       response.data
@@ -135,6 +135,6 @@ const featureAPI = {
       return null;
     }
   },
-}
+};
 
 export default featureAPI;
diff --git a/src/services/featureType-api.js b/src/services/featureType-api.js
index dca96343ae4d474d3b612c83ce585912162f40ae..1aff32caedb23ebb9806dcd954964304ce4a2049 100644
--- a/src/services/featureType-api.js
+++ b/src/services/featureType-api.js
@@ -1,5 +1,5 @@
-import axios from "@/axios-client.js";
-import store from '../store'
+import axios from '@/axios-client.js';
+import store from '../store';
 
 const baseUrl = store.state.configuration.VUE_APP_DJANGO_API_BASE;
 
@@ -11,12 +11,12 @@ const featureTypeAPI = {
     if (
       response.status === 204
     ) {
-      return 'success'
+      return 'success';
     } else {
       return null;
     }
   },
 
-}
+};
 
 export default featureTypeAPI;
diff --git a/src/services/map-api.js b/src/services/map-api.js
index f4b8f45edf3b0f2d8835344f0fcb088f45059c88..f295ba76aa22034bca3d9562347032dc4fbef120 100644
--- a/src/services/map-api.js
+++ b/src/services/map-api.js
@@ -7,7 +7,7 @@ const baseUrl = store.state.configuration.VUE_APP_DJANGO_API_BASE;
 const mapAPI = {
 
   async postOrPut({ basemap, projectSlug, newBasemapIds }) {
-    basemap["project"] = projectSlug
+    basemap['project'] = projectSlug;
     if (newBasemapIds.includes(basemap.id)) {
       return axios
         .post(`${baseUrl}base-maps/`, basemap)
@@ -26,6 +26,6 @@ const mapAPI = {
   }
 
 
-}
+};
 
 export default mapAPI;
diff --git a/src/services/misc-api.js b/src/services/misc-api.js
index 64750eb4a78f7850a13a4b352056ec95165d4bed..ca91e3d5500e8f11004c610bdf0fe31e3086b1aa 100644
--- a/src/services/misc-api.js
+++ b/src/services/misc-api.js
@@ -14,19 +14,19 @@ const miscAPI = {
       if (
         response.status === 200 &&
         response.data
-        ) {
-          return response.data;
-        } else {
-          return null;
-        }
-      } catch (err) {
-        return err;
+      ) {
+        return response.data;
+      } else {
+        return null;
       }
+    } catch (err) {
+      return err;
+    }
   },
 
   async getExternalGeojson(queryParams) {
     const response = await axios.get(
-      `${baseUrl}external-geojson/${queryParams ? '?' + queryParams : ""}`
+      `${baseUrl}external-geojson/${queryParams ? '?' + queryParams : ''}`
     );
     if (
       response.status === 200 &&
@@ -38,6 +38,6 @@ const miscAPI = {
     }
   },
 
-}
+};
 
 export default miscAPI;
diff --git a/src/services/project-api.js b/src/services/project-api.js
index b130900fefed67827948619aca632797912267ac..92355eacd009a6c6729e5f2dd7e8b39cbb055b86 100644
--- a/src/services/project-api.js
+++ b/src/services/project-api.js
@@ -1,6 +1,5 @@
 import axios from '@/axios-client.js';
 
-
 const projectAPI = {
 
   async getProject( baseUrl, projectSlug ) {
@@ -80,6 +79,6 @@ const projectAPI = {
       return null;
     }
   },
-}
+};
 
 export default projectAPI;
diff --git a/src/store/index.js b/src/store/index.js
index 48d69d4ad487fcfdbe231f288b5aa0010b9e8674..8520138d0688b54b9b9752b5b0ae4edb6710acb6 100644
--- a/src/store/index.js
+++ b/src/store/index.js
@@ -1,7 +1,7 @@
 import axios from '@/axios-client.js';
 import Vue from 'vue';
 import Vuex from 'vuex';
-import router from '../router'
+import router from '../router';
 import modules from './modules';
 
 Vue.use(Vuex);
@@ -36,7 +36,7 @@ export default new Vuex.Store({
     events: null,
     loader: {
       isLoading: false,
-      message: "En cours de chargement"
+      message: 'En cours de chargement'
     },
     cancellableSearchRequest: [],
     reloadIntervalId: null
@@ -76,24 +76,24 @@ export default new Vuex.Store({
     },
     DISPLAY_MESSAGE(state, message) {
       state.messages = [message, ...state.messages];
-      if (document.getElementById("content")) document.getElementById("content").scrollIntoView({ block: "start", inline: "nearest" });
+      if (document.getElementById('content')) document.getElementById('content').scrollIntoView({ block: 'start', inline: 'nearest' });
       setTimeout(() => {
         state.messages = [];
       }, 3000);
     },
     DISCARD_MESSAGE(state, message) {
-      state.messages = state.messages.filter((el) => el.comment !== message.comment)
+      state.messages = state.messages.filter((el) => el.comment !== message.comment);
     },
     CLEAR_MESSAGES(state) {
       state.messages = [];
     },
     DISPLAY_LOADER(state, message) {
-      state.loader = { isLoading: true, message }
+      state.loader = { isLoading: true, message };
     },
     DISCARD_LOADER(state) {
       state.loader = {
         isLoading: false,
-        message: "En cours de chargement"
+        message: 'En cours de chargement'
       };
     },
 
@@ -121,7 +121,7 @@ export default new Vuex.Store({
     GET_STATIC_PAGES({ commit }) {
       return axios
         .get(`${this.state.configuration.VUE_APP_DJANGO_API_BASE}flat-pages/`)
-        .then((response) => (commit("SET_STATIC_PAGES", response.data)))
+        .then((response) => (commit('SET_STATIC_PAGES', response.data)))
         .catch((error) => {
           throw error;
         });
@@ -139,20 +139,20 @@ export default new Vuex.Store({
               // * use stored previous route to go back after login if page not open on login at first
               let routerHistory = '';
               if (router.options.routerHistory[0] !== undefined) {
-                routerHistory = router.options.routerHistory[0].name !== "login" ? router.options.routerHistory : "/";
+                routerHistory = router.options.routerHistory[0].name !== 'login' ? router.options.routerHistory : '/';
               } else {
-                routerHistory = "/";
+                routerHistory = '/';
               }
-              commit("SET_USER", response.data.user);
-              router.push(routerHistory[routerHistory.length - 1] || "/");
-              dispatch("GET_USER_LEVEL_PROJECTS");
-              dispatch("GET_USER_LEVEL_PERMISSIONS")
-              return response.status
+              commit('SET_USER', response.data.user);
+              router.push(routerHistory[routerHistory.length - 1] || '/');
+              dispatch('GET_USER_LEVEL_PROJECTS');
+              dispatch('GET_USER_LEVEL_PERMISSIONS');
+              return response.status;
             }
           })
           .catch(() => {
-            commit("SET_USER", false);
-            return "error";
+            commit('SET_USER', false);
+            return 'error';
           });
       }
     },
@@ -164,13 +164,13 @@ export default new Vuex.Store({
           .then((response) => {
             if (response && response.status === 200) {
               const user = response.data.user;
-              commit("SET_USER", user);
+              commit('SET_USER', user);
             }
           })
           .catch(() => {
             //* if an url to redirect to an external authentification system is present, do not redirect to the login page
             if (!state.configuration.VUE_APP_LOGIN_URL) {
-              router.push({ name: "login" });
+              router.push({ name: 'login' });
             }
           });
       }
@@ -183,12 +183,12 @@ export default new Vuex.Store({
           .then((response) => {
             if (response && response.status === 200) {
               const events = response.data;
-              commit("SET_EVENTS", events);
+              commit('SET_EVENTS', events);
               resolve(response.data);
             }
           })
           .catch(() => {
-            reject("Error");
+            reject('Error');
           });
       });
     },
@@ -198,10 +198,10 @@ export default new Vuex.Store({
         .get(`${this.state.configuration.VUE_APP_DJANGO_API_BASE}logout/`)
         .then((response) => {
           if (response && response.status === 200) {
-            commit("SET_USER", false);
-            commit("SET_USER_LEVEL_PROJECTS", null);
-            dispatch("GET_USER_LEVEL_PERMISSIONS");
-            if (router.history.current.name !== "index") router.push("/");
+            commit('SET_USER', false);
+            commit('SET_USER_LEVEL_PROJECTS', null);
+            dispatch('GET_USER_LEVEL_PERMISSIONS');
+            if (router.history.current.name !== 'index') router.push('/');
           }
         })
         .catch((error) => {
@@ -211,10 +211,10 @@ export default new Vuex.Store({
 
     GET_CONFIG({ commit }) {
       axios
-        .get("./config/config.json")
+        .get('./config/config.json')
         .then((response) => {
           if (response && response.status === 200) {
-            commit("SET_CONFIG", response.data);
+            commit('SET_CONFIG', response.data);
           }
         })
         .catch((error) => {
@@ -227,7 +227,7 @@ export default new Vuex.Store({
         .get(`${this.state.configuration.VUE_APP_DJANGO_API_BASE}user-level-projects/`)
         .then((response) => {
           if (response && response.status === 200) {
-            commit("SET_USER_LEVEL_PROJECTS", response.data);
+            commit('SET_USER_LEVEL_PROJECTS', response.data);
           }
         })
         .catch((error) => {
@@ -240,7 +240,7 @@ export default new Vuex.Store({
         .get(`${this.state.configuration.VUE_APP_DJANGO_API_BASE}user-permissions/`)
         .then((response) => {
           if (response && response.status === 200) {
-            commit("SET_USER_PERMISSIONS", response.data);
+            commit('SET_USER_PERMISSIONS', response.data);
           }
         })
         .catch((error) => {
@@ -252,7 +252,7 @@ export default new Vuex.Store({
         .get(`${this.state.configuration.VUE_APP_DJANGO_API_BASE}levels-permissions/`)
         .then((response) => {
           if (response && response.status === 200) {
-            commit("SET_LEVELS_PERMISSIONS", response.data);
+            commit('SET_LEVELS_PERMISSIONS', response.data);
           }
         })
         .catch((error) => {
diff --git a/src/store/modules/feature.store.js b/src/store/modules/feature.store.js
index 0edb559f9dcff2c9e119ce323e8e555391e6693a..29d1dcb5265cc21f1692311275bba0aa43a1c1c3 100644
--- a/src/store/modules/feature.store.js
+++ b/src/store/modules/feature.store.js
@@ -1,5 +1,5 @@
 import axios from '@/axios-client.js';
-import router from '../../router'
+import router from '../../router';
 
 
 const feature = {
@@ -17,20 +17,20 @@ const feature = {
     linked_features: [],
     statusChoices: [
       {
-        name: "Brouillon",
-        value: "draft",
+        name: 'Brouillon',
+        value: 'draft',
       },
       {
-        name: "En attente de publication",
-        value: "pending",
+        name: 'En attente de publication',
+        value: 'pending',
       },
       {
-        name: "Publié",
-        value: "published",
+        name: 'Publié',
+        value: 'published',
       },
       {
-        name: "Archivé",
-        value: "archived",
+        name: 'Archivé',
+        value: 'archived',
       },
     ],
   },
@@ -66,7 +66,7 @@ const feature = {
     },
     UPDATE_ATTACHMENT_FORM(state, payload) {
       const index = state.attachmentFormset.findIndex((el) => el.dataKey === payload.dataKey);
-      if (index !== -1) state.attachmentFormset[index] = payload
+      if (index !== -1) state.attachmentFormset[index] = payload;
     },
     REMOVE_ATTACHMENT_FORM(state, payload) {
       state.attachmentFormset = state.attachmentFormset.filter(form => form.dataKey !== payload);
@@ -79,7 +79,7 @@ const feature = {
     },
     UPDATE_LINKED_FORM(state, payload) {
       const index = state.linkedFormset.findIndex((el) => el.dataKey === payload.dataKey);
-      if (index !== -1) state.linkedFormset[index] = payload
+      if (index !== -1) state.linkedFormset[index] = payload;
     },
     REMOVE_LINKED_FORM(state, payload) {
       state.linkedFormset = state.linkedFormset.filter(form => form.dataKey !== payload);
@@ -105,7 +105,14 @@ const feature = {
   getters: {
   },
   actions: {
-    async GET_PROJECT_FEATURES({ commit, rootState }, { project_slug, feature_type__slug, ordering, search, limit, geojson = false }) {
+    async GET_PROJECT_FEATURES({ commit, rootState }, {
+      project_slug,
+      feature_type__slug,
+      ordering,
+      search,
+      limit,
+      geojson = false 
+    }) {
       if (rootState.cancellableSearchRequest.length > 0) {
         const currentRequestCancelToken =
           rootState.cancellableSearchRequest[rootState.cancellableSearchRequest.length - 1];
@@ -114,8 +121,8 @@ const feature = {
 
       const cancelToken = axios.CancelToken.source();
       commit('SET_CANCELLABLE_SEARCH_REQUEST', cancelToken, { root: true });
-      commit("SET_FEATURES", []);
-      commit("SET_FEATURES_COUNT", 0);
+      commit('SET_FEATURES', []);
+      commit('SET_FEATURES_COUNT', 0);
       let url = `${rootState.configuration.VUE_APP_DJANGO_API_BASE}projects/${project_slug}/feature/`;
       if (feature_type__slug) {
         url = url.concat('', `${url.includes('?') ? '&' : '?'}feature_type__slug=${feature_type__slug}`);
@@ -135,9 +142,9 @@ const feature = {
         const response = await axios.get(url, { cancelToken: cancelToken.token });
         if (response.status === 200 && response.data) {
           const features = response.data.features;
-          commit("SET_FEATURES", features);
+          commit('SET_FEATURES', features);
           const features_count = response.data.count;
-          commit("SET_FEATURES_COUNT", features_count);
+          commit('SET_FEATURES_COUNT', features_count);
         }
         return response;
       } catch (error) {
@@ -154,14 +161,14 @@ const feature = {
 
       const cancelToken = axios.CancelToken.source();
       commit('SET_CANCELLABLE_SEARCH_REQUEST', cancelToken, { root: true });
-      commit("SET_CURRENT_FEATURE", null);
+      commit('SET_CURRENT_FEATURE', null);
       let url = `${rootState.configuration.VUE_APP_DJANGO_API_BASE}projects/${project_slug}/feature/?id=${feature_id}`;
       return axios
         .get(url, { cancelToken: cancelToken.token })
         .then((response) => {
           if (response.status === 200 && response.data.features) {
             const feature = response.data.features[0];
-            commit("SET_CURRENT_FEATURE", feature);
+            commit('SET_CURRENT_FEATURE', feature);
           }
           return response;
         })
@@ -171,7 +178,7 @@ const feature = {
     },
 
     SEND_FEATURE({ state, rootState, commit, dispatch }, routeName) {
-      commit("DISPLAY_LOADER", "Le signalement est en cours de création", { root: true })
+      commit('DISPLAY_LOADER', 'Le signalement est en cours de création', { root: true });
       function redirect(featureId) {
         dispatch(
           'GET_PROJECT_FEATURE',
@@ -181,22 +188,22 @@ const feature = {
           }
         )
           .then(() => {
-            commit("DISCARD_LOADER", null, { root: true })
+            commit('DISCARD_LOADER', null, { root: true });
             router.push({
-              name: "details-signalement",
+              name: 'details-signalement',
               params: {
                 slug_type_signal: rootState.feature_type.current_feature_type_slug,
                 slug_signal: featureId,
-                message: routeName === "editer-signalement" ? "Le signalement a été mis à jour" : "Le signalement a été crée"
+                message: routeName === 'editer-signalement' ? 'Le signalement a été mis à jour' : 'Le signalement a été crée'
               },
             });
-            dispatch('projects/GET_ALL_PROJECTS', null, { root:true }) //* & refresh project list
+            dispatch('projects/GET_ALL_PROJECTS', null, { root:true }); //* & refresh project list
           });
       }
 
       async function handleOtherForms(featureId) {
-        await dispatch("SEND_ATTACHMENTS", featureId)
-        await dispatch("PUT_LINKED_FEATURES", featureId)
+        await dispatch('SEND_ATTACHMENTS', featureId);
+        await dispatch('PUT_LINKED_FEATURES', featureId);
         redirect(featureId);
       }
 
@@ -206,66 +213,68 @@ const feature = {
           extraFormObject[field.name] = field.value;
         }
         return {
-          "id": state.form.feature_id,
-          "type": "Feature",
-          "geometry": state.form.geometry,
-          "properties": {
-            "title": state.form.title,
-            "description": state.form.description.value,
-            "status": state.form.status.value,
-            "project": rootState.project_slug,
-            "feature_type": rootState.feature_type.current_feature_type_slug,
+          id: state.form.feature_id,
+          type: 'Feature',
+          geometry: state.form.geometry,
+          properties: {
+            title: state.form.title,
+            description: state.form.description.value,
+            status: state.form.status.value,
+            project: rootState.project_slug,
+            feature_type: rootState.feature_type.current_feature_type_slug,
             ...extraFormObject
           }
-        }
+        };
       }
 
       const geojson = createGeojson();
-      let url = `${rootState.configuration.VUE_APP_DJANGO_API_BASE}features/`
-      if (routeName === "editer-signalement") {
+      let url = `${rootState.configuration.VUE_APP_DJANGO_API_BASE}features/`;
+      if (routeName === 'editer-signalement') {
         url += `${state.form.feature_id}/?
         feature_type__slug=${rootState.feature_type.current_feature_type_slug} 
-        &project__slug=${rootState.project_slug}`
+        &project__slug=${rootState.project_slug}`;
       }
 
       return axios({
         url,
-        method: routeName === "editer-signalement" ? "PUT" : "POST",
+        method: routeName === 'editer-signalement' ? 'PUT' : 'POST',
         data: geojson
       }).then((response) => {
-          if ((response.status === 200 || response.status === 201) && response.data) {
-            if (state.attachmentFormset.length > 0 || state.linkedFormset.length > 0 || state.attachmentFormset.length > 0 || state.attachmentsToDelete.length > 0) {
-              handleOtherForms(response.data.id)
-            } else {
-              redirect(response.data.id)
-            }
+        if ((response.status === 200 || response.status === 201) && response.data) {
+          if (state.attachmentFormset.length > 0 ||
+            state.linkedFormset.length > 0 ||
+            state.attachmentsToDelete.length > 0) {
+            handleOtherForms(response.data.id);
+          } else {
+            redirect(response.data.id);
           }
-        })
+        }
+      })
         .catch((error) => {
-          commit("DISCARD_LOADER", null, { root: true })
-          if (error.message === "Network Error" || window.navigator.onLine === false) {
+          commit('DISCARD_LOADER', null, { root: true });
+          if (error.message === 'Network Error' || window.navigator.onLine === false) {
             let arraysOffline = [];
-            let localStorageArray = localStorage.getItem("geocontrib_offline");
+            let localStorageArray = localStorage.getItem('geocontrib_offline');
             if (localStorageArray) {
               arraysOffline = JSON.parse(localStorageArray);
             }
             let updateMsg = {
               project: rootState.project_slug,
-              type: routeName === "editer-signalement" ? "put" : "post",
+              type: routeName === 'editer-signalement' ? 'put' : 'post',
               featureId: state.form.feature_id,
               geojson: geojson
             };
             arraysOffline.push(updateMsg);
-            localStorage.setItem("geocontrib_offline", JSON.stringify(arraysOffline));
+            localStorage.setItem('geocontrib_offline', JSON.stringify(arraysOffline));
             router.push({
-              name: "offline-signalement",
+              name: 'offline-signalement',
               params: {
                 slug_type_signal: rootState.feature_type.current_feature_type_slug
               },
             });
           }
           else {
-            console.error(error)
+            console.error(error);
             throw error;
           }
           throw error;
@@ -277,7 +286,7 @@ const feature = {
       
       function addFile(attachment, attchmtId) {
         let formdata = new FormData();
-        formdata.append("file", attachment.fileToImport, attachment.fileToImport.name);
+        formdata.append('file', attachment.fileToImport, attachment.fileToImport.name);
         return axios
           .put(`${DJANGO_API_BASE}features/${featureId}/attachments/${attchmtId}/upload-file/`, formdata)
           .then((response) => {
@@ -285,42 +294,42 @@ const feature = {
           })
           .catch((error) => {
             console.error(error);
-            return error
+            return error;
           });
       }
 
       function putOrPostAttachement(attachment) {
         let formdata = new FormData();
-        formdata.append("title", attachment.title);
-        formdata.append("info", attachment.info);
+        formdata.append('title', attachment.title);
+        formdata.append('info', attachment.info);
 
-        let url = `${DJANGO_API_BASE}features/${featureId}/attachments/`
+        let url = `${DJANGO_API_BASE}features/${featureId}/attachments/`;
         if (attachment.id) {
-          url += `${attachment.id}/`
+          url += `${attachment.id}/`;
         }
 
         return axios({
           url,
-          method: attachment.id ? "PUT" : "POST",
+          method: attachment.id ? 'PUT' : 'POST',
           data: formdata
         }).then((response) => {
           if (response && (response.status === 200 || response.status === 201) && attachment.fileToImport) {
             return addFile(attachment, response.data.id);
           }
-          return response
+          return response;
         })
-        .catch((error) => {
-          console.error(error);
-          return error
-        });
+          .catch((error) => {
+            console.error(error);
+            return error;
+          });
       }
 
       function deleteAttachement(attachmentsId, featureId) {
         let payload = {
-          'attachmentsId': attachmentsId,
-          'featureId': featureId
-        }
-        return dispatch("DELETE_ATTACHMENTS", payload)
+          attachmentsId: attachmentsId,
+          featureId: featureId
+        };
+        return dispatch('DELETE_ATTACHMENTS', payload)
           .then((response) => response);
       }
 
@@ -329,24 +338,24 @@ const feature = {
         ...state.attachmentsToDelete.map((attachmentsId) => deleteAttachement(attachmentsId, featureId))
       ]
       );
-      state.attachmentsToDelete = []
-      return promisesResult
+      state.attachmentsToDelete = [];
+      return promisesResult;
     },
 
 
     DELETE_ATTACHMENTS({ commit }, payload) {
-      let url = `${this.state.configuration.VUE_APP_DJANGO_API_BASE}features/${payload.featureId}/attachments/${payload.attachmentsId}/`
+      let url = `${this.state.configuration.VUE_APP_DJANGO_API_BASE}features/${payload.featureId}/attachments/${payload.attachmentsId}/`;
       return axios
         .delete(url)
         .then((response) => {
           if (response && response.status === 204) {
-            commit("REMOVE_ATTACHMENTS_ID_TO_DELETE", payload.attachmentsId)
-            return response
+            commit('REMOVE_ATTACHMENTS_ID_TO_DELETE', payload.attachmentsId);
+            return response;
           }
         })
         .catch((error) => {
           console.error(error);
-          return error
+          return error;
         });
     },
 
@@ -355,7 +364,7 @@ const feature = {
         .put(`${rootState.configuration.VUE_APP_DJANGO_API_BASE}features/${featureId}/feature-links/`, state.linkedFormset)
         .then((response) => {
           if (response.status === 200 && response.data) {
-            return "La relation a bien été ajouté"
+            return 'La relation a bien été ajouté';
           }
         })
         .catch((error) => {
@@ -376,6 +385,6 @@ const feature = {
     },
   },
 
-}
+};
 
-export default feature
+export default feature;
diff --git a/src/store/modules/feature_type.store.js b/src/store/modules/feature_type.store.js
index 046d784a96ab51cd21d9930ea46d166c9050b6e7..f8d6dc4057312cd772136a83ccd621ea36c1c8f4 100644
--- a/src/store/modules/feature_type.store.js
+++ b/src/store/modules/feature_type.store.js
@@ -1,20 +1,22 @@
 import axios from '@/axios-client.js';
 
-const getColorsStyles = (customForms) => customForms.filter(customForm => customForm.options && customForm.options.length).map(el => {
+const getColorsStyles = (customForms) => customForms
+  .filter(customForm => customForm.options && customForm.options.length)
+  .map(el => {
   //* in dropdown, value is the name and name is the label to be displayed, could be changed...
-  return { value: el.name, name: el.label, options: el.options }
-});
+    return { value: el.name, name: el.label, options: el.options };
+  });
 
 const pending2draftFeatures = (features) => {
-  let result = []
+  let result = [];
   for (let el of features) {
-    if (el.properties.status === "pending") {
-      el.properties.status = "draft"
+    if (el.properties.status === 'pending') {
+      el.properties.status = 'draft';
     }
-    result.push(el)
+    result.push(el);
   }
   return result;
-}
+};
 
 const feature_type = {
   namespaced: true,
@@ -85,7 +87,7 @@ const feature_type = {
         .get(`${this.state.configuration.VUE_APP_DJANGO_API_BASE}projects/${project_slug}/feature-types/`)
         .then((response) => {
           if (response.status === 200 && response.data) {
-            commit("SET_FEATURE_TYPES", response.data.feature_types)
+            commit('SET_FEATURE_TYPES', response.data.feature_types);
             return response;
           }
         })
@@ -96,25 +98,25 @@ const feature_type = {
 
     async SEND_FEATURE_TYPE({ state, getters, rootGetters }, requestType) {
       const data = {
-        'title': state.form.title.value,
-        'title_optional': state.form.title_optional.value,
-        'geom_type': state.form.geom_type.value,
-        'color': state.form.color.value,
-        'colors_style': state.form.colors_style.value,
-        'project': rootGetters.project.slug,
-        'customfield_set': state.customForms.map(el => {
+        title: state.form.title.value,
+        title_optional: state.form.title_optional.value,
+        geom_type: state.form.geom_type.value,
+        color: state.form.color.value,
+        colors_style: state.form.colors_style.value,
+        project: rootGetters.project.slug,
+        customfield_set: state.customForms.map(el => {
           return {
-            'position': el.position,
-            'label': el.label,
-            'name': el.name,
-            'field_type': el.field_type,
-            'options': el.options,
-          }
+            position: el.position,
+            label: el.label,
+            name: el.name,
+            field_type: el.field_type,
+            options: el.options,
+          };
         }),
         //'is_editable': true,
-      }
+      };
 
-      if (requestType === "post") {
+      if (requestType === 'post') {
         return axios
           .post(`${this.state.configuration.VUE_APP_DJANGO_API_BASE}feature-types/`, data)
           .then((response) => {
@@ -127,7 +129,7 @@ const feature_type = {
           .catch((error) => {
             throw (error);
           });
-      } else if (requestType === "put") {
+      } else if (requestType === 'put') {
         return axios
           .put(`${this.state.configuration.VUE_APP_DJANGO_API_BASE}feature-types/${getters.feature_type.slug}/`, data)
           .then((response) => {
@@ -166,10 +168,10 @@ const feature_type = {
     async SEND_FEATURES_FROM_GEOJSON({ state, dispatch, rootGetters }, payload) {
       let { feature_type_slug, geojson } = payload;
       //* check if geojson then build a file
-      if(!geojson && !state.fileToImport && state.fileToImport.size === 0 ) return
+      if(!geojson && !state.fileToImport && state.fileToImport.size === 0 ) return;
       let formData = new FormData();
       let fileToImport;
-      const {name, type} = geojson || state.fileToImport;
+      const { name, type } = geojson || state.fileToImport;
 
       if (!rootGetters.project.moderation) {
         if (state.fileToImport && state.fileToImport.size > 0) { //* if data in a binary file, read it as text
@@ -178,29 +180,29 @@ const feature_type = {
         }
         const unmoderatedFeatures = pending2draftFeatures(geojson.features);
         geojson= {
-          "type": "FeatureCollection", "features": unmoderatedFeatures
+          type: 'FeatureCollection', features: unmoderatedFeatures
         };
       }
-      fileToImport = new File([JSON.stringify(geojson)], name, {type});
+      fileToImport = new File([JSON.stringify(geojson)], name, { type });
 
       formData.append('json_file', geojson ? fileToImport : state.fileToImport);
       formData.append('feature_type_slug', feature_type_slug);
       let url =
         this.state.configuration.VUE_APP_DJANGO_API_BASE +
-        'import-tasks/'
+        'import-tasks/';
       return axios
         .post(url, formData, {
           headers: {
-            "Content-Type": "multipart/form-data",
+            'Content-Type': 'multipart/form-data',
           },
         })
         .then((response) => {
           if (response && response.status === 200) {
-            return dispatch("GET_IMPORTS", {
+            return dispatch('GET_IMPORTS', {
               feature_type: feature_type_slug
             });
           }
-          return response
+          return response;
         })
         .catch((error) => {
           throw (error);
@@ -219,7 +221,7 @@ const feature_type = {
         .get(url)
         .then((response) => {
           if (response) {
-            commit("SET_IMPORT_FEATURE_TYPES_DATA", response.data);
+            commit('SET_IMPORT_FEATURE_TYPES_DATA', response.data);
           }
           return response;
         })
@@ -228,6 +230,6 @@ const feature_type = {
         });
     }
   }
-}
+};
 
-export default feature_type
\ No newline at end of file
+export default feature_type;
\ No newline at end of file
diff --git a/src/store/modules/map.store.js b/src/store/modules/map.store.js
index 57ae63836919b88664930870cdbfe96b7d83034f..a1e4b1b3ba0756635f1a1542fb48e58558a9e472 100644
--- a/src/store/modules/map.store.js
+++ b/src/store/modules/map.store.js
@@ -1,5 +1,5 @@
 import axios from '@/axios-client.js';
-import { mapUtil } from "@/assets/js/map-util.js";
+import { mapUtil } from '@/assets/js/map-util.js';
 
 // axios.defaults.headers.common['X-CSRFToken'] = (name => {
 //   var re = new RegExp(name + "=([^;]+)");
@@ -32,7 +32,7 @@ const map = {
       state.basemaps = basemaps;
     },
     CREATE_BASEMAP(state, id) {
-      state.basemaps = [...state.basemaps, { id, title: '', layers: [], errors: [] }]
+      state.basemaps = [...state.basemaps, { id, title: '', layers: [], errors: [] }];
     },
     UPDATE_BASEMAPS(state, basemaps) {
       state.basemaps = basemaps;
@@ -40,14 +40,10 @@ const map = {
     UPDATE_BASEMAP(state, { title, id, layers, errors }) {
       const index = state.basemaps.findIndex((el) => el.id === id);
       if (index !== -1) {
-        if (title) {
-          state.basemaps[index].title = title
-        }
+        state.basemaps[index].title = title;
+        state.basemaps[index].errors = errors;
         if (layers) {
-          state.basemaps[index].layers = layers
-        }
-        if (errors) {
-          state.basemaps[index].errors = errors
+          state.basemaps[index].layers = layers;
         }
       }
     },
@@ -94,7 +90,7 @@ const map = {
     GET_AVAILABLE_LAYERS({ commit }) {
       return axios
         .get(`${this.state.configuration.VUE_APP_DJANGO_API_BASE}layers/`)
-        .then((response) => (commit("SET_LAYERS", response.data)))
+        .then((response) => (commit('SET_LAYERS', response.data)))
         .catch((error) => {
           throw error;
         });
@@ -105,9 +101,9 @@ const map = {
         .get(`${this.state.configuration.VUE_APP_DJANGO_API_BASE}base-maps/?project__slug=${project_slug}`)
         .then((response) => {
           if (response.status === 200 && response.data) {
-            commit("SET_BASEMAPS", response.data)
+            commit('SET_BASEMAPS', response.data);
           }
-          return response
+          return response;
         })
         .catch((error) => {
           throw error;
@@ -115,7 +111,7 @@ const map = {
     },
 
     INITIATE_MAP({ state, rootGetters, commit }, el) {
-      const project = rootGetters.project
+      const project = rootGetters.project;
       let mapDefaultViewCenter = [46, 2]; // defaultMapView.center;
       let mapDefaultViewZoom = 5; // defaultMapView.zoom;
       mapUtil.createMap(el, {
@@ -134,12 +130,12 @@ const map = {
       if (state.baseMaps && state.baseMaps.length > 0) {
         // Use active one if exists, otherwise index 0 (first basemap in the list)
         const mapOptions =
-          JSON.parse(localStorage.getItem("geocontrib-map-options")) || {};
+          JSON.parse(localStorage.getItem('geocontrib-map-options')) || {};
         const basemapIndex =
           mapOptions &&
             mapOptions[project] &&
-            mapOptions[project]["current-basemap-index"]
-            ? mapOptions[project]["current-basemap-index"]
+            mapOptions[project]['current-basemap-index']
+            ? mapOptions[project]['current-basemap-index']
             : 0;
         layersToLoad = state.baseMaps[basemapIndex].layers;
         layersToLoad.forEach((layerToLoad) => {
@@ -151,7 +147,11 @@ const map = {
         });
         layersToLoad.reverse();
       }
-      mapUtil.addLayers(layersToLoad, this.state.configuration.DEFAULT_BASE_MAP.SERVICE, this.state.configuration.DEFAULT_BASE_MAP.OPTIONS);
+      mapUtil.addLayers(
+        layersToLoad,
+        this.state.configuration.DEFAULT_BASE_MAP.SERVICE,
+        this.state.configuration.DEFAULT_BASE_MAP.OPTIONS
+      );
 
       // Remove multiple interactions with the map
       //mapUtil.getMap().dragging.disable();
@@ -163,14 +163,14 @@ const map = {
     async SAVE_BASEMAPS({ state, rootState, dispatch }, newBasemapIds) {
       const DJANGO_API_BASE = this.state.configuration.VUE_APP_DJANGO_API_BASE;
       function postOrPut(basemap) {
-        basemap["project"] = rootState.project_slug
+        basemap['project'] = rootState.project_slug;
         if (newBasemapIds.includes(basemap.id)) {
           return axios
             .post(`${DJANGO_API_BASE}base-maps/`, basemap)
             .then((response) => response)
             .catch((error) => {
               console.error(error);
-              return error
+              return error;
             });
         } else {
           return axios
@@ -178,40 +178,42 @@ const map = {
             .then((response) => response)
             .catch((error) => {
               console.error(error);
-              return error
+              return error;
             });
         }
       }
 
       function deleteBMap(basemapId) {
         //* delete in the backend the basemaps that was rewoved from the front
-        return dispatch("DELETE_BASEMAP", basemapId)
+        return dispatch('DELETE_BASEMAP', basemapId)
           .then((response) => response);
       }
 
       const promisesResult = await Promise.all(
-        [...state.basemaps.map((basemap) => postOrPut(basemap)), ...state.basemapsToDelete.map((basemapId) => deleteBMap(basemapId))]
-
+        [
+          ...state.basemaps.map((basemap) => postOrPut(basemap)),
+          ...state.basemapsToDelete.map((basemapId) => deleteBMap(basemapId))
+        ]
       );
-      state.basemapsToDelete = []
-      return promisesResult
+      state.basemapsToDelete = [];
+      return promisesResult;
     },
 
     DELETE_BASEMAP({ commit }, basemapId) {
-      let url = `${this.state.configuration.VUE_APP_DJANGO_API_BASE}base-maps/` + basemapId
+      let url = `${this.state.configuration.VUE_APP_DJANGO_API_BASE}base-maps/` + basemapId;
       return axios
         .delete(url)
         .then((response) => {
           if (response && response.status === 204) {
-            commit("REMOVE_BASEMAP_ID_TO_DELETE", basemapId)
-            return response
+            commit('REMOVE_BASEMAP_ID_TO_DELETE', basemapId);
+            return response;
           }
         })
         .catch((error) => {
           console.error(error);
-          return error
+          return error;
         });
     }
   },
-}
-export default map
\ No newline at end of file
+};
+export default map;
\ No newline at end of file
diff --git a/src/utils/index.js b/src/utils/index.js
index f4e38a208239a1dea567de3f9059854fcbd7048e..1a6d59b56c11048441baa97c1373c39f8b267dfd 100644
--- a/src/utils/index.js
+++ b/src/utils/index.js
@@ -1,4 +1,4 @@
 export function parseDate(date) {
-  let dateArr = date.split("/").reverse();
+  let dateArr = date.split('/').reverse();
   return new Date(dateArr[0], dateArr[1] - 1, dateArr[2]);
 }
\ No newline at end of file
diff --git a/src/views/Catalog.vue b/src/views/Catalog.vue
index 675b6530594de30a289ee1c8a89ba40c16b24b47..10cec72d1576b75a8917ac8f437841dad5abb6c5 100644
--- a/src/views/Catalog.vue
+++ b/src/views/Catalog.vue
@@ -11,11 +11,10 @@
         <div>Dataset</div>
         <div>Ressource</div>
       </div>
-      <div v-if="resources && resources.length > 0" >
+      <div v-if="resources && resources.length > 0">
         <div
           v-for="(resource, index) in paginatedResources"
           :key="`${resource.resource_name}-${index}`"
-          @click="selectResource(resource)"
           :class="[
             'row',
             {
@@ -23,13 +22,19 @@
                 selectedResource && resource.layer === selectedResource.layer,
             },
           ]"
+          @click="selectResource(resource)"
         >
           <div>{{ resource.organization_name }}</div>
           <div>{{ resource.dataset_name }}</div>
           <div>{{ resource.resource_name }}</div>
         </div>
       </div>
-      <div class="no-response" v-else>Pas de données trouvées pour l'utilisateur {{this.user.username}}</div>
+      <div
+        v-else
+        class="no-response"
+      >
+        Pas de données trouvées pour l'utilisateur {{ user.username }}
+      </div>
     </div>
 
     <div class="pagination_wrapper">
@@ -48,25 +53,23 @@
         class="dataTables_paginate paging_simple_numbers"
       >
         <a
-          @click="toPreviousPage"
           id="table-features_previous"
           :class="[
             'paginate_button previous',
             { disabled: pagination.currentPage === 1 },
           ]"
-          >Précédent</a
-        >
+          @click="toPreviousPage"
+        >Précédent</a>
         <span>
           <a
             v-for="pageNumber in nbPages"
             :key="'page' + pageNumber"
-            @click="toPage(pageNumber)"
             :class="[
               'paginate_button',
               { current: pageNumber === pagination.currentPage },
             ]"
-            >{{ pageNumber }}</a
-          >
+            @click="toPage(pageNumber)"
+          >{{ pageNumber }}</a>
         </span>
         <!-- // TODO : <span v-if="nbPages > 4" class="ellipsis">...</span> -->
         <a
@@ -76,18 +79,17 @@
             { disabled: pagination.currentPage === nbPages.length },
           ]"
           @click="toNextPage"
-          >Suivant</a
-        >
+        >Suivant</a>
       </div>
     </div>
 
     <div class="import">
       <button
         :disabled="!selectedResource"
-        @click="launchImport"
         class="ui fluid teal icon button"
+        @click="launchImport"
       >
-        <i class="upload icon"></i> Lancer l'import avec le fichier
+        <i class="upload icon" /> Lancer l'import avec le fichier
         <span v-if="selectedResource">
           {{ selectedResource.resource }}
         </span>
@@ -97,11 +99,11 @@
 </template>
 
 <script>
-import { mapGetters, mapState } from "vuex";
-import miscAPI from "@/services/misc-api";
+import { mapGetters, mapState } from 'vuex';
+import miscAPI from '@/services/misc-api';
 
 export default {
-  name: "Catalog",
+  name: 'Catalog',
 
   data() {
     return {
@@ -141,6 +143,15 @@ export default {
     },
   },
 
+  mounted() {
+    this.$store.commit('DISPLAY_LOADER', 'Interrogation du catologue datasud.');
+    this.$store.dispatch('projects/GET_PROJECT', this.$route.params.slug);
+    miscAPI.getIdgoCatalog(this.user.username).then((data) => {
+      if (data && data.layers) this.resources = data.layers;
+      this.$store.commit('DISCARD_LOADER');
+    });
+  },
+
   methods: {
     selectResource(resource) {
       this.selectedResource = resource;
@@ -171,14 +182,14 @@ export default {
 
     redirect(geojson) {
       const name =
-        this.$route.params.feature_type_slug === "create"
-          ? "ajouter-type-signalement"
-          : "details-type-signalement";
+        this.$route.params.feature_type_slug === 'create'
+          ? 'ajouter-type-signalement'
+          : 'details-type-signalement';
       this.$router.push({
         name: name,
         params: {
           geojson,
-          type: "external-geojson",
+          type: 'external-geojson',
         },
       });
     },
@@ -190,16 +201,6 @@ export default {
       });
     },
   },
-
-  mounted() {
-    this.$store.commit("DISPLAY_LOADER", "Interrogation du catologue datasud.");
-    this.$store.dispatch("GET_PROJECT", this.$route.params.slug);
-    //this.$store.dispatch("GET_PROJECT_INFO", this.$route.params.slug);
-    miscAPI.getIdgoCatalog(this.user.username).then((data) => {
-      if (data && data.layers) this.resources = data.layers;
-      this.$store.commit("DISCARD_LOADER");
-    });
-  },
 };
 </script>
 
diff --git a/src/views/My_account.vue b/src/views/My_account.vue
index 857eaf99b04122f5f4083e0d32d661b59e634c9d..6043f4fcf238996d08a87b0e412bcc3553566a58 100644
--- a/src/views/My_account.vue
+++ b/src/views/My_account.vue
@@ -6,7 +6,9 @@
 
     <div class="row">
       <div class="five wide column">
-        <h4 class="ui horizontal divider header">PROFIL</h4>
+        <h4 class="ui horizontal divider header">
+          PROFIL
+        </h4>
         <div class="ui divided list">
           <div class="item">
             <div class="right floated content">
@@ -14,7 +16,9 @@
                 <span v-if="user.username">{{ user.username }} </span>
               </div>
             </div>
-            <div class="content">Nom d'utilisateur</div>
+            <div class="content">
+              Nom d'utilisateur
+            </div>
           </div>
           <div class="item">
             <div class="right floated content">
@@ -22,7 +26,9 @@
                 {{ userFullname }}
               </div>
             </div>
-            <div class="content">Nom complet</div>
+            <div class="content">
+              Nom complet
+            </div>
           </div>
           <div class="item">
             <div class="right floated content">
@@ -30,7 +36,9 @@
                 {{ user.email }}
               </div>
             </div>
-            <div class="content">Adresse e-mail</div>
+            <div class="content">
+              Adresse e-mail
+            </div>
           </div>
           <div class="item">
             <div class="right floated content">
@@ -38,18 +46,29 @@
                 {{ user.is_superuser ? "Oui" : "Non" }}
               </div>
             </div>
-            <div class="content">Administrateur</div>
+            <div class="content">
+              Administrateur
+            </div>
           </div>
         </div>
       </div>
 
       <div class="nine wide column">
-        <h4 class="ui horizontal divider header">MES PROJETS</h4>
+        <h4 class="ui horizontal divider header">
+          MES PROJETS
+        </h4>
 
         <div class="ui divided items">
-          <div v-for="project in projects" :key="project.slug" class="item">
+          <div
+            v-for="project in projects"
+            :key="project.slug"
+            class="item"
+          >
             <!-- {% if permissions|lookup:project.slug %} -->
-            <div v-frag v-if="user_permissions[project.slug].can_view_project">
+            <div
+              v-if="user_permissions[project.slug].can_view_project"
+              v-frag
+            >
               <div class="ui tiny image">
                 <img
                   v-if="project.thumbnail"
@@ -60,7 +79,7 @@
                       : DJANGO_BASE_URL + project.thumbnail + refreshId()
                   "
                   height="200"
-                />
+                >
               </div>
               <div class="middle aligned content">
                 <router-link
@@ -69,19 +88,18 @@
                     params: { slug: project.slug },
                   }"
                   class="header"
-                  >{{ project.title }}</router-link
                 >
+                  {{ project.title }}
+                </router-link>
                 <div class="description">
                   <p>{{ project.description }}</p>
                 </div>
                 <div class="meta">
-                  <span class="right floated"
-                    >Projet {{ project.moderation ? "" : "non" }} modéré</span
-                  >
                   <span
-                    >Niveau d'autorisation requis :
-                    {{ project.access_level_pub_feature }}</span
-                  ><br />
+                    class="right floated"
+                  >Projet {{ project.moderation ? "" : "non" }} modéré</span>
+                  <span>Niveau d'autorisation requis :
+                    {{ project.access_level_pub_feature }}</span><br>
                   <span>
                     Mon niveau d'autorisation :
                     <span v-if="USER_LEVEL_PROJECTS && project">{{
@@ -97,20 +115,20 @@
                     class="right floated"
                     :data-tooltip="`Projet créé le ${project.created_on}`"
                   >
-                    <i class="calendar icon"></i>&nbsp;{{ project.created_on }}
+                    <i class="calendar icon" />&nbsp;{{ project.created_on }}
                   </span>
                   <span data-tooltip="Membres">
-                    {{ project.nb_contributors }}&nbsp;<i class="user icon"></i>
+                    {{ project.nb_contributors }}&nbsp;<i class="user icon" />
                   </span>
                   <span data-tooltip="Signalements publiés">
                     {{ project.nb_published_features }}&nbsp;<i
                       class="map marker icon"
-                    ></i>
+                    />
                   </span>
                   <span data-tooltip="Commentaires">
                     {{ project.nb_published_features_comments }}&nbsp;<i
                       class="comment icon"
-                    ></i>
+                    />
                   </span>
                 </div>
               </div>
@@ -130,7 +148,11 @@
               </div>
               <div class="center aligned description">
                 <div class="ui relaxed list">
-                  <div v-for="item in events" :key="item.id" class="item">
+                  <div
+                    v-for="item in events"
+                    :key="item.id"
+                    class="item"
+                  >
                     <div class="content">
                       <div v-if="item.event_type === 'create'">
                         <a
@@ -169,7 +191,7 @@
                         <a
                           v-else-if="item.object_type === 'project'"
                           :href="item.project_url"
-                          >à Projet mis à jour
+                        >à Projet mis à jour
                         </a>
                       </div>
 
@@ -180,84 +202,89 @@
                         <i v-else>Événement inconnu</i>
                       </div>
                       <div class="description">
-                        <i
-                          >[ {{ item.created_on }}
+                        <i>[ {{ item.created_on }}
                           <span v-if="user.is_authenticated">
                             , par {{ item.display_user }}
                           </span>
-                          ]</i
-                        >
+                          ]</i>
                       </div>
                     </div>
                   </div>
-                  <i v-if="!events || events.length === 0"
-                    >Aucune notification pour le moment.</i
-                  >
+                  <i
+                    v-if="!events || events.length === 0"
+                  >Aucune notification pour le moment.</i>
                 </div>
               </div>
             </div>
           </div>
           <div class="orange card">
             <div class="content">
-              <div class="center aligned header">Mes derniers signalements</div>
+              <div class="center aligned header">
+                Mes derniers signalements
+              </div>
               <div class="center aligned description">
                 <div class="ui relaxed list">
-                  <div v-for="item in features" :key="item.id" class="item">
+                  <div
+                    v-for="item in features"
+                    :key="item.id"
+                    class="item"
+                  >
                     <div class="content">
                       <div>
                         <a
                           v-if="item.related_feature"
                           :href="item.related_feature.feature_url"
-                          >{{ item.related_feature.title }}</a
-                        >
+                        >{{ item.related_feature.title }}</a>
                         <span v-else>
                           {{ item.data.feature_title }} (supprimé)
                         </span>
                       </div>
                       <div class="description">
-                        <i
-                          >[ {{ item.created_on }}
+                        <i>[ {{ item.created_on }}
                           <span v-if="user.is_authenticated">
                             , par {{ item.display_user }}
                           </span>
-                          ]</i
-                        >
+                          ]</i>
                       </div>
                     </div>
                   </div>
-                  <i v-if="!features || features.length === 0"
-                    >Aucun signalement pour le moment.</i
-                  >
+                  <i
+                    v-if="!features || features.length === 0"
+                  >Aucun signalement pour le moment.</i>
                 </div>
               </div>
             </div>
           </div>
           <div class="yellow card">
             <div class="content">
-              <div class="center aligned header">Mes derniers commentaires</div>
+              <div class="center aligned header">
+                Mes derniers commentaires
+              </div>
               <div class="center aligned description">
                 <div class="ui relaxed list">
-                  <div v-for="item in comments" :key="item.id" class="item">
+                  <div
+                    v-for="item in comments"
+                    :key="item.id"
+                    class="item"
+                  >
                     <div class="content">
                       <div>
-                        <a :href="item.related_feature.feature_url"
-                          >"{{ item.related_comment.comment }}"</a
-                        >
+                        <a
+                          :href="item.related_feature.feature_url"
+                        >"{{ item.related_comment.comment }}"</a>
                       </div>
                       <div class="description">
-                        <i
-                          >[ {{ item.created_on }}
+                        <i>[ {{ item.created_on }}
                           <span v-if="user.is_authenticated">
                             , par {{ item.display_user }}
                           </span>
-                          ]</i
-                        >
+                          ]</i>
                       </div>
                     </div>
                   </div>
-                  <i v-if="!comments || comments.length === 0"
-                    >Aucun commentaire pour le moment.</i
-                  >
+                  <i
+                    v-if="!comments || comments.length === 0"
+                  >Aucun commentaire pour le moment.</i>
                 </div>
               </div>
             </div>
@@ -269,11 +296,11 @@
 </template>
 
 <script>
-import frag from "vue-frag";
-import { mapState } from "vuex";
+import frag from 'vue-frag';
+import { mapState } from 'vuex';
 
 export default {
-  name: "My_account",
+  name: 'MyAccount',
 
   directives: {
     frag,
@@ -290,9 +317,9 @@ export default {
   computed: {
     // todo : filter projects to user
     ...mapState([
-      "user",
-      "USER_LEVEL_PROJECTS",
-      "user_permissions",
+      'user',
+      'USER_LEVEL_PROJECTS',
+      'user_permissions',
     ]),
     ...mapState('projects', [
       'projects'
@@ -302,14 +329,17 @@ export default {
     },
     userFullname: function () {
       if (this.user.first_name || this.user.last_name)
-        return this.user.first_name + " " + this.user.last_name;
+        return this.user.first_name + ' ' + this.user.last_name;
       return null;
     },
   },
+  created(){
+    this.getEvents();
+  },
 
   methods: {
     refreshId() {
-      return "?ver=" + Math.random();
+      return '?ver=' + Math.random();
     },
     setEvents(data){
       this.events = data.events;
@@ -318,14 +348,11 @@ export default {
     },
     getEvents(){
       this.$store
-        .dispatch("USER_EVENTS")
+        .dispatch('USER_EVENTS')
         .then((data)=>{
-          this.setEvents(data)
-        })
+          this.setEvents(data);
+        });
     }
-  },
-  created(){
-    this.getEvents();
   }
 };
 </script>
\ No newline at end of file
diff --git a/src/views/NotFound.vue b/src/views/NotFound.vue
index 57d7e54f229a9ed836f9de938c0265bbb4dfb6d6..dc80d876da727a8b530d02064b0bd03c04dcd11e 100644
--- a/src/views/NotFound.vue
+++ b/src/views/NotFound.vue
@@ -3,7 +3,9 @@
     <h1>Not Found</h1>
     <p>
       Oups, la page demandée n'a pas été trouvée. Essayez de retourner à la
-      <router-link to="/">page d'accueil</router-link>
+      <router-link to="/">
+        page d'accueil
+      </router-link>
     </p>
   </div>
 </template>
diff --git a/src/views/Projects.vue b/src/views/Projects.vue
index 1fe2c9497f51ba7d58f2aa4d60b7f95f50aad986..4c799bdc7e6d6758102136fb156f832073e5d450 100644
--- a/src/views/Projects.vue
+++ b/src/views/Projects.vue
@@ -1,6 +1,5 @@
 <template>
   <div class="fourteen wide column">
-
     <h2 class="ui horizontal divider header">
       PROJETS
     </h2>
@@ -11,7 +10,7 @@
         :to="{ name: 'project_create', params: { action: 'create' } }"
         class="ui green basic button"
       >
-        <i class="plus icon"></i> Créer un nouveau projet
+        <i class="plus icon" /> Créer un nouveau projet
       </router-link>
       <router-link
         v-if="user && user.can_create_project && isOffline() != true"
@@ -20,7 +19,7 @@
         }"
         class="ui blue basic button"
       >
-        <i class="copy icon"></i> Accéder à la liste des modèles de projets
+        <i class="copy icon" /> Accéder à la liste des modèles de projets
       </router-link>
     </div>
 
@@ -37,15 +36,28 @@
       <input
         v-model="displayForbiddenProjects"
         type="checkbox"
-      />
+      >
       <label>
         N'afficher que les projets disponibles à la consultation
       </label>
     </div>
 
     <!-- LISTE DES PROJETS -->
-    <div v-if="projects" class="ui divided items">
-      <div v-for="project in projects" class="item" :key="project.slug">
+    <div
+      v-if="projects"
+      class="ui divided items dimmable dimmed"
+    >
+      <div
+        :class="{ active: loading }"
+        class="ui inverted dimmer"
+      >
+        <div class="ui loader" />
+      </div>
+      <div
+        v-for="project in projects"
+        :key="project.slug"
+        class="item"
+      >
         <div class="ui tiny image">
           <img
             :src="
@@ -53,7 +65,7 @@
                 ? require('@/assets/img/default.png')
                 : DJANGO_BASE_URL + project.thumbnail + refreshId()
             "
-          />
+          >
         </div>
         <div class="middle aligned content">
           <router-link
@@ -62,8 +74,9 @@
               params: { slug: project.slug },
             }"
             class="header"
-            >{{ project.title }}</router-link
           >
+            {{ project.title }}
+          </router-link>
 
           <div class="description">
             <p>{{ project.description }}</p>
@@ -73,10 +86,8 @@
               <strong v-if="project.moderation">Projet modéré</strong>
               <strong v-else>Projet non modéré</strong>
             </span>
-            <span
-              >Niveau d'autorisation requis :
-              {{ project.access_level_pub_feature }}</span
-            ><br />
+            <span>Niveau d'autorisation requis :
+              {{ project.access_level_pub_feature }}</span><br>
             <span v-if="user">
               Mon niveau d'autorisation :
               <span v-if="USER_LEVEL_PROJECTS && project">{{
@@ -89,39 +100,39 @@
           </div>
           <div class="meta">
             <span class="right floated">
-              <i class="calendar icon"></i>&nbsp; {{ project.created_on }}
+              <i class="calendar icon" />&nbsp; {{ project.created_on }}
             </span>
             <span data-tooltip="Membres">
-              {{ project.nb_contributors }}&nbsp;<i class="user icon"></i>
+              {{ project.nb_contributors }}&nbsp;<i class="user icon" />
             </span>
             <span data-tooltip="Signalements publiés">
               {{ project.nb_published_features }}&nbsp;<i
                 class="map marker icon"
-              ></i>
+              />
             </span>
             <span data-tooltip="Commentaires">
               {{ project.nb_published_features_comments }}&nbsp;<i
                 class="comment icon"
-              ></i>
+              />
             </span>
           </div>
         </div>
       </div>
 
-      <span v-if="!projects || projects.length === 0"
-        >Vous n'avez accès à aucun projet.</span
-      >
+      <span
+        v-if="!projects || projects.length === 0"
+      >Vous n'avez accès à aucun projet.</span>
 
-      <div class="item"></div>
+      <div class="item" />
     </div>
 
     <!-- PAGINATION -->
     <pagination
-      :nbPages="Math.ceil(count/10)"
+      v-if="count"
+      :nb-pages="Math.ceil(count/10)"
       :on-page-change="SET_CURRENT_PAGE"
       @change-page="changePage"
     />
-
   </div>
 </template>
 
@@ -141,8 +152,9 @@ export default {
   
   data() {
     return {
+      loading: false,
       displayForbiddenProjects: false
-    }
+    };
   },
 
   computed: {
@@ -218,7 +230,7 @@ export default {
     },
     refreshId() {
       //* change path of thumbnail to update image
-      return "?ver=" + Math.random();
+      return '?ver=' + Math.random();
     },
 
     getData(page) {
@@ -250,6 +262,11 @@ export default {
   justify-content: space-between;
 }
 
+#filters-divider {
+  padding-top: 0;
+  color: gray !important;
+}
+
 #forbidden-projects.checkbox {
   font-size: 1.2em;
   font-weight: 600;
diff --git a/src/views/feature/Feature_detail.vue b/src/views/feature/Feature_detail.vue
index bf97c9702bd6405d6966a05d84b05fd3e83242dc..1567f09052906cf03ae50bfca849de4039e968bc 100644
--- a/src/views/feature/Feature_detail.vue
+++ b/src/views/feature/Feature_detail.vue
@@ -1,6 +1,9 @@
 <template>
   <div v-frag>
-    <div v-frag v-if="feature">
+    <div
+      v-if="feature"
+      v-frag
+    >
       <div class="row">
         <div class="fourteen wide column">
           <h1 class="ui header">
@@ -19,13 +22,13 @@
                   data-tooltip="Ajouter un signalement"
                   data-position="bottom left"
                 >
-                  <i class="plus fitted icon"></i>
+                  <i class="plus fitted icon" />
                 </router-link>
                 <router-link
                   v-if="
                     (permissions && permissions.can_update_feature) ||
-                    isFeatureCreator ||
-                    isModerator
+                      isFeatureCreator ||
+                      isModerator
                   "
                   :to="{
                     name: 'editer-signalement',
@@ -36,18 +39,18 @@
                   }"
                   class="ui button button-hover-orange"
                 >
-                  <i class="inverted grey pencil alternate icon"></i>
+                  <i class="inverted grey pencil alternate icon" />
                 </router-link>
                 <a
                   v-if="isFeatureCreator"
-                  @click="isCanceling = true"
                   id="feature-delete"
                   class="ui button button-hover-red"
+                  @click="isCanceling = true"
                 >
-                  <i class="inverted grey trash alternate icon"></i>
+                  <i class="inverted grey trash alternate icon" />
                 </a>
               </div>
-              <div class="ui hidden divider"></div>
+              <div class="ui hidden divider" />
               <div class="sub header prewrap">
                 {{ feature.description }}
               </div>
@@ -61,9 +64,9 @@
           <table class="ui very basic table">
             <tbody>
               <div
-                v-frag
                 v-for="(field, index) in feature.feature_data"
                 :key="'field' + index"
+                v-frag
               >
                 <tr v-if="field">
                   <td>
@@ -77,7 +80,7 @@
                           'icon',
                           field.value ? 'olive check' : 'grey times',
                         ]"
-                      ></i>
+                      />
                       <span v-else>
                         {{ field.value }}
                       </span>
@@ -92,7 +95,10 @@
               <tr>
                 <td>Statut</td>
                 <td>
-                  <i v-if="feature.status" :class="['icon', statusIcon]"></i>
+                  <i
+                    v-if="feature.status"
+                    :class="['icon', statusIcon]"
+                  />
                   {{ statusLabel }}
                 </td>
               </tr>
@@ -108,18 +114,6 @@
                   {{ feature.updated_on | formatDate }}
                 </td>
               </tr>
-              <!-- <tr>
-                <td>Date d'archivage automatique</td>
-                <td v-if="feature.archived_on">
-                  {{ feature.archived_on }}
-                </td>
-              </tr>
-              <tr>
-                <td>Date de suppression automatique</td>
-                <td v-if="feature.deletion_on">
-                  {{ feature.deletion_on }}
-                </td>
-              </tr> -->
             </tbody>
           </table>
 
@@ -142,15 +136,24 @@
         </div>
 
         <div class="seven wide column">
-          <div id="map" ref="map"></div>
+          <div
+            id="map"
+            ref="map"
+          />
         </div>
       </div>
 
       <div class="row">
         <div class="seven wide column">
-          <h2 class="ui header">Pièces jointes</h2>
+          <h2 class="ui header">
+            Pièces jointes
+          </h2>
 
-          <div v-for="pj in attachments" :key="pj.id" class="ui divided items">
+          <div
+            v-for="pj in attachments"
+            :key="pj.id"
+            class="ui divided items"
+          >
             <div class="item">
               <a
                 class="ui tiny image"
@@ -163,10 +166,14 @@
                       ? require('@/assets/img/pdf.png')
                       : pj.attachment_file
                   "
-                />
+                >
               </a>
               <div class="middle aligned content">
-                <a class="header" target="_blank" :href="pj.attachment_file">{{
+                <a
+                  class="header"
+                  target="_blank"
+                  :href="pj.attachment_file"
+                >{{
                   pj.title
                 }}</a>
                 <div class="description">
@@ -175,18 +182,33 @@
               </div>
             </div>
           </div>
-          <i v-if="attachments.length === 0"
-            >Aucune pièce jointe associée au signalement.</i
-          >
+          <i
+            v-if="attachments.length === 0"
+          >Aucune pièce jointe associée au signalement.</i>
         </div>
 
         <div class="seven wide column">
-          <h2 class="ui header">Activité et commentaires</h2>
+          <h2 class="ui header">
+            Activité et commentaires
+          </h2>
 
-          <div id="feed-event" class="ui feed">
-            <div v-frag v-for="(event, index) in events" :key="'event' + index">
-              <div v-frag v-if="event.event_type === 'create'">
-                <div v-if="event.object_type === 'feature'" class="event">
+          <div
+            id="feed-event"
+            class="ui feed"
+          >
+            <div
+              v-for="(event, index) in events"
+              :key="'event' + index"
+              v-frag
+            >
+              <div
+                v-if="event.event_type === 'create'"
+                v-frag
+              >
+                <div
+                  v-if="event.object_type === 'feature'"
+                  class="event"
+                >
                   <div class="content">
                     <div class="summary">
                       <div class="date">
@@ -197,7 +219,10 @@
                     </div>
                   </div>
                 </div>
-                <div v-else-if="event.object_type === 'comment'" class="event">
+                <div
+                  v-else-if="event.object_type === 'comment'"
+                  class="event"
+                >
                   <div class="content">
                     <div class="summary">
                       <div class="date">
@@ -208,22 +233,27 @@
                     </div>
                     <div class="extra text">
                       {{ event.related_comment.comment }}
-                      <div v-frag v-if="event.related_comment.attachment">
-                        <br /><a
+                      <div
+                        v-if="event.related_comment.attachment"
+                        v-frag
+                      >
+                        <br><a
                           :href="
                             DJANGO_BASE_URL +
-                            event.related_comment.attachment.url
+                              event.related_comment.attachment.url
                           "
                           target="_blank"
-                          ><i class="paperclip fitted icon"></i>
-                          {{ event.related_comment.attachment.title }}</a
-                        >
+                        ><i class="paperclip fitted icon" />
+                          {{ event.related_comment.attachment.title }}</a>
                       </div>
                     </div>
                   </div>
                 </div>
               </div>
-              <div v-else-if="event.event_type === 'update'" class="event">
+              <div
+                v-else-if="event.event_type === 'update'"
+                class="event"
+              >
                 <div class="content">
                   <div class="summary">
                     <div class="date">
@@ -246,10 +276,13 @@
               class="ui form"
             >
               <div class="required field">
-                <label :for="comment_form.comment.id_for_label"
-                  >Ajouter un commentaire</label
+                <label
+                  :for="comment_form.comment.id_for_label"
+                >Ajouter un commentaire</label>
+                <ul
+                  v-if="comment_form.comment.errors"
+                  class="errorlist"
                 >
-                <ul v-if="comment_form.comment.errors" class="errorlist">
                   <li>
                     {{ comment_form.comment.errors }}
                   </li>
@@ -258,13 +291,16 @@
                   v-model="comment_form.comment.value"
                   :name="comment_form.comment.html_name"
                   rows="2"
-                ></textarea>
+                />
               </div>
               <label>Pièce jointe (facultative)</label>
               <div class="two fields">
                 <div class="field">
-                  <label class="ui icon button" for="attachment_file">
-                    <i class="paperclip icon"></i>
+                  <label
+                    class="ui icon button"
+                    for="attachment_file"
+                  >
+                    <i class="paperclip icon" />
                     <span class="label">{{
                       comment_form.attachment_file.value
                         ? comment_form.attachment_file.value
@@ -272,35 +308,38 @@
                     }}</span>
                   </label>
                   <input
+                    id="attachment_file"
                     type="file"
                     accept="application/pdf, image/jpeg, image/png"
                     style="display: none"
                     name="attachment_file"
-                    id="attachment_file"
                     @change="onFileChange"
-                  />
+                  >
                 </div>
                 <div class="field">
                   <input
+                    id="title"
                     v-model="comment_form.attachment_file.title"
                     type="text"
                     name="title"
-                    id="title"
-                  />
+                  >
                   {{ comment_form.attachment_file.errors }}
                 </div>
               </div>
-              <ul v-if="comment_form.attachment_file.errors" class="errorlist">
+              <ul
+                v-if="comment_form.attachment_file.errors"
+                class="errorlist"
+              >
                 <li>
                   {{ comment_form.attachment_file.errors }}
                 </li>
               </ul>
               <button
-                @click="postComment"
                 type="button"
                 class="ui compact green icon button"
+                @click="postComment"
               >
-                <i class="plus icon"></i> Poster le commentaire
+                <i class="plus icon" /> Poster le commentaire
               </button>
             </form>
           </div>
@@ -318,47 +357,57 @@
             { 'active visible': isCanceling },
           ]"
         >
-          <i @click="isCanceling = false" class="close icon"></i>
+          <i
+            class="close icon"
+            @click="isCanceling = false"
+          />
           <div class="ui icon header">
-            <i class="trash alternate icon"></i>
+            <i class="trash alternate icon" />
             Supprimer le signalement
           </div>
           <div class="actions">
-            <form
-              action="{% url 'geocontrib:feature_delete' slug=feature.project.slug feature_type_slug=feature.feature_type.slug feature_id=feature.feature_id %}"
-              method="POST"
+            <button
+              type="button"
+              class="ui red compact fluid button"
+              @click="deleteFeature"
             >
-              <input type="hidden" name="_method" value="delete" />
-              <button
-                @click="deleteFeature"
-                type="button"
-                class="ui red compact fluid button"
-              >
-                Confirmer la suppression
-              </button>
-            </form>
+              Confirmer la suppression
+            </button>
           </div>
         </div>
       </div>
     </div>
-    <div v-frag v-else>Pas de signalement correspondant trouvé</div>
+    <div
+      v-else
+      v-frag
+    >
+      Pas de signalement correspondant trouvé
+    </div>
   </div>
 </template>
 
 <script>
-import frag from "vue-frag";
-import { mapGetters, mapState, mapActions } from "vuex";
-import { mapUtil } from "@/assets/js/map-util.js";
-import featureAPI from "@/services/feature-api";
+import frag from 'vue-frag';
+import { mapGetters, mapState, mapActions } from 'vuex';
+import { mapUtil } from '@/assets/js/map-util.js';
+import featureAPI from '@/services/feature-api';
 import axios from '@/axios-client.js';
 
 export default {
-  name: "Feature_detail",
+  name: 'FeatureDetail',
 
   directives: {
     frag,
   },
 
+  filters: {
+    formatDate(value) {
+      let date = new Date(value);
+      date = date.toLocaleString().replace(',', '');
+      return date.substr(0, date.length - 3); //* quick & dirty way to remove seconds from date
+    },
+  },
+
   data() {
     return {
       isCanceling: false,
@@ -367,13 +416,13 @@ export default {
       comment_form: {
         attachment_file: {
           errors: null,
-          title: "",
+          title: '',
           file: null,
         },
         comment: {
-          id_for_label: "add-comment",
-          html_name: "add-comment",
-          errors: "",
+          id_for_label: 'add-comment',
+          html_name: 'add-comment',
+          errors: '',
           value: null,
         },
       },
@@ -411,23 +460,23 @@ export default {
 
     isModerator() {
       return this.USER_LEVEL_PROJECTS && this.project &&
-        this.USER_LEVEL_PROJECTS[this.project.slug] === "Modérateur"
+        this.USER_LEVEL_PROJECTS[this.project.slug] === 'Modérateur'
         ? true
         : false;
     },
 
     statusIcon() {
       switch (this.feature.status) {
-        case "archived":
-          return "grey archive";
-        case "pending":
-          return "teal hourglass outline";
-        case "published":
-          return "olive check";
-        case "draft":
-          return "orange pencil alternate";
-        default:
-          return "";
+      case 'archived':
+        return 'grey archive';
+      case 'pending':
+        return 'teal hourglass outline';
+      case 'published':
+        return 'olive check';
+      case 'draft':
+        return 'orange pencil alternate';
+      default:
+        return '';
       }
     },
 
@@ -435,15 +484,52 @@ export default {
       const status = this.statusChoices.find(
         (el) => el.value === this.feature.status
       );
-      return status ? status.name : "";
+      return status ? status.name : '';
     },
   },
-  filters: {
-    formatDate(value) {
-      let date = new Date(value);
-      date = date.toLocaleString().replace(",", "");
-      return date.substr(0, date.length - 3); //* quick & dirty way to remove seconds from date
-    },
+
+  created() {
+    this.$store.commit(
+      'feature_type/SET_CURRENT_FEATURE_TYPE_SLUG',
+      this.$route.params.slug_type_signal
+    );
+    this.getFeatureEvents();
+    this.getFeatureAttachments();
+    this.getLinkedFeatures();
+  },
+
+  mounted() {
+    this.$store.commit('DISPLAY_LOADER', 'Recherche du signalement');
+    if (!this.project) {
+      // Chargements des features et infos projet en cas d'arrivée directe sur la page ou de refresh
+      axios.all([
+        this.$store
+          .dispatch('GET_PROJECT_INFO', this.$route.params.slug),
+        this.$store.dispatch('feature/GET_PROJECT_FEATURE', {
+          project_slug: this.$route.params.slug,
+          feature_id: this.$route.params.slug_signal
+        })])
+        .then(() => {
+          this.$store.commit('DISCARD_LOADER');
+          this.initMap();
+        });
+    } if (!this.feature || this.feature.feature_id != this.$route.params.slug_signal) {
+      this.$store.dispatch('feature/GET_PROJECT_FEATURE', {
+        project_slug: this.$route.params.slug,
+        feature_id: this.$route.params.slug_signal
+      })
+        .then(() => {
+          this.$store.commit('DISCARD_LOADER');
+          this.initMap();
+        });
+    } else {
+      this.$store.commit('DISCARD_LOADER');
+      this.initMap();
+    }
+  },
+
+  beforeDestroy() {
+    this.$store.commit('CLEAR_MESSAGES');
   },
 
   methods: {
@@ -455,7 +541,7 @@ export default {
     },
     pushNgo(link) {
       this.$router.push({
-        name: "details-signalement",
+        name: 'details-signalement',
         params: {
           slug_type_signal: link.feature_to.feature_type_slug,
           slug_signal: link.feature_to.feature_id,
@@ -468,9 +554,9 @@ export default {
     },
 
     validateForm() {
-      this.comment_form.comment.errors = ""
+      this.comment_form.comment.errors = '';
       if (!this.comment_form.comment.value) {
-        this.comment_form.comment.errors = "Le commentaire ne peut pas être vide"
+        this.comment_form.comment.errors = 'Le commentaire ne peut pas être vide';
         return false;
       }
       return true;
@@ -479,36 +565,36 @@ export default {
     postComment() {
       if (this.validateForm()) {
         featureAPI
-        .postComment({
-          featureId: this.$route.params.slug_signal,
-          comment: this.comment_form.comment.value,
-        })
-        .then((response) => {
-          if (response && this.comment_form.attachment_file.file) {
-            featureAPI
-              .postCommentAttachment({
-                featureId: this.$route.params.slug_signal,
-                file: this.comment_form.attachment_file.file,
-                fileName: this.comment_form.attachment_file.fileName,
-                title: this.comment_form.attachment_file.title,
-                commentId: response.data.id,
-              })
-              .then(() => {
-                this.confirmComment();
-              });
-          } else {
-            this.confirmComment();
-          }
-        });
+          .postComment({
+            featureId: this.$route.params.slug_signal,
+            comment: this.comment_form.comment.value,
+          })
+          .then((response) => {
+            if (response && this.comment_form.attachment_file.file) {
+              featureAPI
+                .postCommentAttachment({
+                  featureId: this.$route.params.slug_signal,
+                  file: this.comment_form.attachment_file.file,
+                  fileName: this.comment_form.attachment_file.fileName,
+                  title: this.comment_form.attachment_file.title,
+                  commentId: response.data.id,
+                })
+                .then(() => {
+                  this.confirmComment();
+                });
+            } else {
+              this.confirmComment();
+            }
+          });
       }
     },
 
     confirmComment() {
-      this.$store.commit("DISPLAY_MESSAGE", {comment: "Ajout du commentaire confirmé", level: "positive"});
+      this.$store.commit('DISPLAY_MESSAGE', { comment: 'Ajout du commentaire confirmé', level: 'positive' });
       this.getFeatureEvents(); //* display new comment on the page
       this.comment_form.attachment_file.file = null;
-      this.comment_form.attachment_file.fileName = "";
-      this.comment_form.attachment_file.title = "";
+      this.comment_form.attachment_file.fileName = '';
+      this.comment_form.attachment_file.title = '';
       this.comment_form.comment.value = null;
     },
 
@@ -533,11 +619,11 @@ export default {
       const handleFile = (isValid) => {
         if (isValid) {
           this.comment_form.attachment_file.file = files[0]; //* store the file to post afterwards
-          let title = files[0].name
+          let title = files[0].name;
           this.comment_form.attachment_file.fileName = title; //* name of the file
-          const fileExtension = title.substring(title.lastIndexOf(".") + 1);
+          const fileExtension = title.substring(title.lastIndexOf('.') + 1);
           if ((title.length - fileExtension.length) > 11) {
-            title = title.slice(0, 10) + "[...]." + fileExtension;
+            title = title.slice(0, 10) + '[...].' + fileExtension;
           }
           this.comment_form.attachment_file.title = title; //* title for display
           this.comment_form.attachment_file.errors = null;
@@ -545,11 +631,11 @@ export default {
           this.comment_form.attachment_file.errors =
             "Transférez une image valide. Le fichier que vous avez transféré n'est pas une image, ou il est corrompu.";
         }
-      }
+      };
 
       if (files.length) {
         //* exception for pdf
-        if (files[0].type === "application/pdf") {
+        if (files[0].type === 'application/pdf') {
           handleFile(true);
         } else {
           this.comment_form.attachment_file.errors = null;
@@ -561,7 +647,7 @@ export default {
 
     goBackToProject(message) {
       this.$router.push({
-        name: "project_detail",
+        name: 'project_detail',
         params: {
           slug: this.$store.state.project_slug,
           message,
@@ -571,7 +657,7 @@ export default {
 
     deleteFeature() {
       this.$store
-        .dispatch("feature/DELETE_FEATURE", this.feature.feature_id)
+        .dispatch('feature/DELETE_FEATURE', this.feature.feature_id)
         .then((response) => {
           if (response.status === 204) {
             this.GET_PROJECT_FEATURES({
@@ -593,7 +679,7 @@ export default {
       });
 
       // Update link to feature list with map zoom and center
-      mapUtil.addMapEventListener("moveend", function () {
+      mapUtil.addMapEventListener('moveend', function () {
         // update link to feature list with map zoom and center
         /*var $featureListLink = $("#feature-list-link")
         var baseUrl = $featureListLink.attr("href").split("?")[0]
@@ -671,54 +757,10 @@ export default {
       featureAPI
         .getFeatureLinks(this.$route.params.slug_signal)
         .then((data) =>
-          this.$store.commit("feature/SET_LINKED_FEATURES", data)
+          this.$store.commit('feature/SET_LINKED_FEATURES', data)
         );
     },
   },
-
-  created() {
-    this.$store.commit(
-      "feature_type/SET_CURRENT_FEATURE_TYPE_SLUG",
-      this.$route.params.slug_type_signal
-    );
-    this.getFeatureEvents();
-    this.getFeatureAttachments();
-    this.getLinkedFeatures();
-  },
-
-  mounted() {
-    this.$store.commit("DISPLAY_LOADER", "Recherche du signalement");
-    if (!this.project) {
-      // Chargements des features et infos projet en cas d'arrivée directe sur la page ou de refresh
-      axios.all([
-        this.$store
-        .dispatch("GET_PROJECT_INFO", this.$route.params.slug),
-        this.$store.dispatch('feature/GET_PROJECT_FEATURE', {
-          project_slug: this.$route.params.slug,
-          feature_id: this.$route.params.slug_signal
-        })])
-        .then(() => {
-          this.$store.commit("DISCARD_LOADER");
-          this.initMap();
-        });
-    } if (!this.feature || this.feature.feature_id != this.$route.params.slug_signal) {
-        this.$store.dispatch('feature/GET_PROJECT_FEATURE', {
-          project_slug: this.$route.params.slug,
-          feature_id: this.$route.params.slug_signal
-        })
-        .then(() => {
-          this.$store.commit("DISCARD_LOADER");
-          this.initMap();
-        });
-    } else {
-      this.$store.commit("DISCARD_LOADER");
-      this.initMap();
-    }
-  },
-
-  beforeDestroy() {
-    this.$store.commit("CLEAR_MESSAGES");
-  },
 };
 </script>
 
diff --git a/src/views/feature/Feature_edit.vue b/src/views/feature/Feature_edit.vue
index 1b8a9f1ffddf514d68f28c54af9f70fcaf25b664..7fc6e51ac18cc4cfd2ce148947ddea292c6401d7 100644
--- a/src/views/feature/Feature_edit.vue
+++ b/src/views/feature/Feature_edit.vue
@@ -22,16 +22,22 @@
           <div :class="field_title">
             <label :for="form.title.id_for_label">{{ form.title.label }}</label>
             <input
+              :id="form.title.id_for_label"
+              v-model="form.title.value"
               type="text"
               required
               :maxlength="form.title.field.max_length"
               :name="form.title.html_name"
-              :id="form.title.id_for_label"
-              v-model="form.title.value"
               @blur="updateStore"
-            />
-            <ul id="errorlist-title" class="errorlist">
-              <li v-for="error in form.title.errors" :key="error">
+            >
+            <ul
+              id="errorlist-title"
+              class="errorlist"
+            >
+              <li
+                v-for="error in form.title.errors"
+                :key="error"
+              >
                 {{ error }}
               </li>
             </ul>
@@ -52,11 +58,11 @@
             form.description.label
           }}</label>
           <textarea
+            v-model="form.description.value"
             :name="form.description.html_name"
             rows="5"
-            v-model="form.description.value"
             @blur="updateStore"
-          ></textarea>
+          />
         </div>
 
         <!-- Geom Field -->
@@ -64,15 +70,18 @@
           <label :for="form.geom.id_for_label">{{ form.geom.label }}</label>
 
           <!-- Import GeoImage -->
-          <div v-frag v-if="feature_type && feature_type.geom_type === 'point'">
+          <div
+            v-if="feature_type && feature_type.geom_type === 'point'"
+            v-frag
+          >
             <p v-if="isOffline() !== true">
               <button
-                @click="toggleGeoRefModal"
                 id="add-geo-image"
                 type="button"
                 class="ui compact button"
+                @click="toggleGeoRefModal"
               >
-                <i class="file image icon"></i>Importer une image géoréférencée
+                <i class="file image icon" />Importer une image géoréférencée
               </button>
               Vous pouvez utiliser une image géoréférencée pour localiser le
               signalement.
@@ -87,7 +96,10 @@
                 class="ui mini modal transition visible active"
                 style="display: block !important"
               >
-                <i class="close icon" @click="toggleGeoRefModal"></i>
+                <i
+                  class="close icon"
+                  @click="toggleGeoRefModal"
+                />
                 <div class="content">
                   <h3>Importer une image géoréférencée</h3>
                   <form
@@ -101,28 +113,33 @@
                     </p>
                     <div class="field georef-btn">
                       <label>Image (png ou jpeg)</label>
-                      <label class="ui icon button" for="image_file">
-                        <i class="file icon"></i>
+                      <label
+                        class="ui icon button"
+                        for="image_file"
+                      >
+                        <i class="file icon" />
                         <span class="label">{{ geoRefFileLabel }}</span>
                       </label>
                       <input
+                        id="image_file"
+                        ref="file"
                         type="file"
                         accept="image/jpeg, image/png"
                         style="display: none"
-                        ref="file"
-                        v-on:change="handleFileUpload"
                         name="image_file"
                         class="image_file"
-                        id="image_file"
-                      />
-                      <ul v-if="erreurUploadMessage" class="errorlist">
+                        @change="handleFileUpload"
+                      >
+                      <ul
+                        v-if="erreurUploadMessage"
+                        class="errorlist"
+                      >
                         <li>
                           {{ erreurUploadMessage }}
                         </li>
                       </ul>
                     </div>
                     <button
-                      @click="georeferencement"
                       id="get-geom-from-image-file"
                       type="button"
                       :class="[
@@ -130,8 +147,9 @@
                         file && !erreurUploadMessage ? 'green' : 'disabled',
                         { red: erreurUploadMessage },
                       ]"
+                      @click="georeferencement"
                     >
-                      <i class="plus icon"></i>
+                      <i class="plus icon" />
                       Importer
                     </button>
                   </form>
@@ -141,18 +159,18 @@
 
             <p v-if="showGeoPositionBtn">
               <button
-                @click="create_point_geoposition"
                 id="create-point-geoposition"
                 type="button"
                 class="ui compact button"
+                @click="create_point_geoposition"
               >
-                <i class="ui map marker alternate icon"></i>Positionner le
+                <i class="ui map marker alternate icon" />Positionner le
                 signalement à partir de votre géolocalisation
               </button>
             </p>
             <span
-              id="erreur-geolocalisation"
               v-if="erreurGeolocalisationMessage"
+              id="erreur-geolocalisation"
             >
               <div class="ui negative message">
                 <div class="header">
@@ -163,30 +181,44 @@
                   {{ erreurGeolocalisationMessage }}
                 </p>
               </div>
-              <br />
+              <br>
             </span>
           </div>
-          <ul id="errorlist-geom" class="errorlist">
-            <li v-for="error in form.geom.errors" :key="error">
+          <ul
+            id="errorlist-geom"
+            class="errorlist"
+          >
+            <li
+              v-for="error in form.geom.errors"
+              :key="error"
+            >
               {{ error }}
             </li>
           </ul>
           <!-- Map -->
           <input
-            type="hidden"
-            :name="form.geom.html_name"
             :id="form.geom.id_for_label"
             v-model="form.geom.value"
+            type="hidden"
+            :name="form.geom.html_name"
             @blur="updateStore"
-          />
-          <div class="ui tab active map-container" data-tab="map">
-            <div id="map" ref="map"></div>
+          >
+          <div
+            class="ui tab active map-container"
+            data-tab="map"
+          >
+            <div
+              id="map"
+              ref="map"
+            />
             <SidebarLayers v-if="basemaps && map" />
           </div>
         </div>
 
         <!-- Extra Fields -->
-        <div class="ui horizontal divider">DONNÉES MÉTIER</div>
+        <div class="ui horizontal divider">
+          DONNÉES MÉTIER
+        </div>
         <div
           v-for="(field, index) in orderedCustomFields"
           :key="field.field_type + index"
@@ -198,51 +230,61 @@
 
         <!-- Pièces jointes -->
         <div v-if="isOffline() !== true">
-          <div class="ui horizontal divider">PIÈCES JOINTES</div>
-          <div v-if="isOffline() !== true" id="formsets-attachment">
+          <div class="ui horizontal divider">
+            PIÈCES JOINTES
+          </div>
+          <div
+            v-if="isOffline() !== true"
+            id="formsets-attachment"
+          >
             <FeatureAttachmentForm
-              v-for="form in attachmentFormset"
-              :key="form.dataKey"
-              :attachmentForm="form"
+              v-for="attachForm in attachmentFormset"
+              :key="attachForm.dataKey"
               ref="attachementForm"
+              :attachment-form="attachForm"
             />
           </div>
 
           <button
-            @click="add_attachement_formset"
             id="add-attachment"
             type="button"
             class="ui compact basic button button-hover-green"
+            @click="add_attachement_formset"
           >
-            <i class="ui plus icon"></i>Ajouter une pièce jointe
+            <i class="ui plus icon" />Ajouter une pièce jointe
           </button>
         </div>
 
         <!-- Signalements liés -->
         <div v-if="isOffline() !== true">
-          <div class="ui horizontal divider">SIGNALEMENTS LIÉS</div>
+          <div class="ui horizontal divider">
+            SIGNALEMENTS LIÉS
+          </div>
           <div id="formsets-link">
             <FeatureLinkedForm
-              v-for="form in linkedFormset"
-              :key="form.dataKey"
-              :linkedForm="form"
-              :features="features"
+              v-for="linkForm in linkedFormset"
+              :key="linkForm.dataKey"
               ref="linkedForm"
+              :linked-form="linkForm"
             />
           </div>
           <button
-            @click="add_linked_formset"
             id="add-link"
             type="button"
             class="ui compact basic button button-hover-green"
+            @click="add_linked_formset"
           >
-            <i class="ui plus icon"></i>Ajouter une liaison
+            <i class="ui plus icon" />Ajouter une liaison
           </button>
         </div>
-        <div class="ui divider"></div>
+        <div class="ui divider" />
 
-        <button @click="postForm" type="button" class="ui teal icon button">
-          <i class="white save icon"></i> Enregistrer les changements
+        <button
+          type="button"
+          class="ui teal icon button"
+          @click="postForm"
+        >
+          <i class="white save icon" /> Enregistrer les changements
         </button>
       </form>
     </div>
@@ -250,29 +292,23 @@
 </template>
 
 <script>
-import frag from "vue-frag";
-import { mapState, mapGetters } from "vuex";
-import FeatureAttachmentForm from "@/components/feature/FeatureAttachmentForm";
-import FeatureLinkedForm from "@/components/feature/FeatureLinkedForm";
-import FeatureExtraForm from "@/components/feature/FeatureExtraForm";
-import Dropdown from "@/components/Dropdown.vue";
-import SidebarLayers from "@/components/map-layers/SidebarLayers";
-import featureAPI from "@/services/feature-api";
-
-import L from "leaflet";
-import "leaflet-draw";
-import { mapUtil } from "@/assets/js/map-util.js";
-import axios from "@/axios-client.js";
-import flip from "@turf/flip";
-
-// axios.defaults.headers.common["X-CSRFToken"] = ((name) => {
-//   var re = new RegExp(name + "=([^;]+)");
-//   var value = re.exec(document.cookie);
-//   return value !== null ? unescape(value[1]) : null;
-// })("csrftoken");
+import frag from 'vue-frag';
+import { mapState, mapGetters } from 'vuex';
+import FeatureAttachmentForm from '@/components/feature/FeatureAttachmentForm';
+import FeatureLinkedForm from '@/components/feature/FeatureLinkedForm';
+import FeatureExtraForm from '@/components/feature/FeatureExtraForm';
+import Dropdown from '@/components/Dropdown.vue';
+import SidebarLayers from '@/components/map-layers/SidebarLayers';
+import featureAPI from '@/services/feature-api';
+
+import L from 'leaflet';
+import 'leaflet-draw';
+import { mapUtil } from '@/assets/js/map-util.js';
+import axios from '@/axios-client.js';
+import flip from '@turf/flip';
 
 export default {
-  name: "Feature_edit",
+  name: 'FeatureEdit',
 
   directives: {
     frag,
@@ -300,33 +336,33 @@ export default {
       form: {
         title: {
           errors: [],
-          id_for_label: "name",
+          id_for_label: 'name',
           field: {
             max_length: 30,
           },
-          html_name: "name",
-          label: "Nom",
-          value: "",
+          html_name: 'name',
+          label: 'Nom',
+          value: '',
         },
         status: {
-          id_for_label: "status",
-          html_name: "status",
-          label: "Statut",
+          id_for_label: 'status',
+          html_name: 'status',
+          label: 'Statut',
           value: {
-            value: "draft",
-            name: "Brouillon",
+            value: 'draft',
+            name: 'Brouillon',
           },
         },
         description: {
           errors: [],
-          id_for_label: "description",
-          html_name: "description",
-          label: "Description",
-          value: "",
+          id_for_label: 'description',
+          html_name: 'description',
+          label: 'Description',
+          value: '',
         },
         geom: {
           errors: [],
-          label: "Localisation",
+          label: 'Localisation',
           value: null,
         },
       },
@@ -334,28 +370,25 @@ export default {
   },
 
   computed: {
-    ...mapGetters(["project", "permissions"]),
-    ...mapGetters("feature_type", ["feature_type"]),
-    ...mapState(["user", "USER_LEVEL_PROJECTS"]),
-    ...mapState("map", ["basemaps"]),
-    ...mapState("feature", [
-      "attachmentFormset",
-      "attachmentsToDelete",
-      "attachmentsToPut",
-      "linkedFormset",
-      "features",
-      "extra_form",
-      "linked_features",
-      "statusChoices",
+    ...mapGetters(['project', 'permissions']),
+    ...mapGetters('feature_type', ['feature_type']),
+    ...mapState(['user', 'USER_LEVEL_PROJECTS']),
+    ...mapState('map', ['basemaps']),
+    ...mapState('feature', [
+      'attachmentFormset',
+      'linkedFormset',
+      'features',
+      'extra_form',
+      'statusChoices',
     ]),
 
     field_title() {
       if (this.feature_type) {
         if (this.feature_type.title_optional) {
-          return "field";
+          return 'field';
         }
       }
-      return "required field";
+      return 'required field';
     },
 
     currentRouteName() {
@@ -374,7 +407,7 @@ export default {
       if (this.file) {
         return this.file.name;
       }
-      return "Sélectionner une image ...";
+      return 'Sélectionner une image ...';
     },
 
     selected_status: {
@@ -396,38 +429,38 @@ export default {
           : false; //* si le contributeur est l'auteur du signalement
         if (
           //* si admin, modérateur ou super contributeur, statuts toujours disponible: Brouillon, Publié, Archivé
-          userStatus === "Modérateur" ||
-          userStatus === "Administrateur projet" ||
-          (userStatus === "Super Contributeur" && !isModerate)
+          userStatus === 'Modérateur' ||
+          userStatus === 'Administrateur projet' ||
+          (userStatus === 'Super Contributeur' && !isModerate)
         ) {
-          return this.statusChoices.filter((el) => el.value !== "pending");
-        } else if (userStatus === "Super Contributeur" && isModerate) {
+          return this.statusChoices.filter((el) => el.value !== 'pending');
+        } else if (userStatus === 'Super Contributeur' && isModerate) {
           return this.statusChoices.filter(
-            (el) => el.value === "draft" || el.value === "pending"
+            (el) => el.value === 'draft' || el.value === 'pending'
           );
-        } else if (userStatus === "Contributeur") {
+        } else if (userStatus === 'Contributeur') {
           //* cas particuliers du contributeur
           if (
-            this.currentRouteName === "ajouter-signalement" ||
+            this.currentRouteName === 'ajouter-signalement' ||
             !isOwnFeature
           ) {
             //* même cas à l'ajout d'une feature ou si feature n'a pas été créé par le contributeur
             return isModerate
               ? this.statusChoices.filter(
-                  (el) => el.value === "draft" || el.value === "pending"
-                )
+                (el) => el.value === 'draft' || el.value === 'pending'
+              )
               : this.statusChoices.filter(
-                  (el) => el.value === "draft" || el.value === "published"
-                );
+                (el) => el.value === 'draft' || el.value === 'published'
+              );
           } else {
             //* à l'édition d'une feature et si le contributeur est l'auteur de la feature
             return isModerate
               ? this.statusChoices.filter(
-                  (el) => el.value !== "published" //* toutes sauf "Publié"
-                )
+                (el) => el.value !== 'published' //* toutes sauf "Publié"
+              )
               : this.statusChoices.filter(
-                  (el) => el.value !== "pending" //* toutes sauf "En cours de publication"
-                );
+                (el) => el.value !== 'pending' //* toutes sauf "En cours de publication"
+              );
           }
         }
       }
@@ -435,15 +468,66 @@ export default {
     },
   },
 
+  created() {
+    this.$store.commit(
+      'feature_type/SET_CURRENT_FEATURE_TYPE_SLUG',
+      this.$route.params.slug_type_signal
+    );
+    //* empty previous feature data, not emptying by itself since it doesn't update by itself anymore
+    if (this.currentRouteName === 'ajouter-signalement') {
+      this.$store.commit('feature/SET_CURRENT_FEATURE', []);
+    }
+
+    if (this.$route.params.slug_signal) {
+      this.getFeatureAttachments();
+      this.getLinkedFeatures();
+    }
+  },
+
+  mounted() {
+    let promises = [
+      this.$store.dispatch('GET_PROJECT_INFO', this.$route.params.slug),
+    ];
+    if (this.$route.params.slug_signal) {
+      promises.push(
+        this.$store.dispatch('feature/GET_PROJECT_FEATURE', {
+          project_slug: this.$route.params.slug,
+          feature_id: this.$route.params.slug_signal,
+        })
+      );
+    }
+
+    Promise.all(promises).then(() => {
+      this.initForm();
+      this.initMap();
+      this.onFeatureTypeLoaded();
+      this.initExtraForms(this.feature);
+
+      setTimeout(
+        function () {
+          mapUtil.addGeocoders(this.$store.state.configuration);
+        }.bind(this),
+        1000
+      );
+    });
+  },
+
+  destroyed() {
+    //* be sure that previous Formset have been cleared for creation
+    this.$store.commit('feature/CLEAR_ATTACHMENT_FORM');
+    this.$store.commit('feature/CLEAR_LINKED_FORM');
+    this.$store.commit('feature/CLEAR_EXTRA_FORM');
+  },
+
   methods: {
     isOffline() {
       return navigator.onLine == false;
     },
     initForm() {
-      if (this.currentRouteName === "editer-signalement") {
+      if (this.currentRouteName === 'editer-signalement') {
         for (let key in this.feature) {
           if (key && this.form[key]) {
-            if (key === "status") {
+            if (key === 'status') {
               const value = this.feature[key];
               this.form[key].value = this.statusChoices.find(
                 (key) => key.value === value
@@ -469,7 +553,7 @@ export default {
 
       function error(err) {
         this.erreurGeolocalisationMessage = err.message;
-        if (err.message === "User denied geolocation prompt") {
+        if (err.message === 'User denied geolocation prompt') {
           this.erreurGeolocalisationMessage =
             "La géolocalisation a été désactivée par l'utilisateur";
         }
@@ -489,35 +573,35 @@ export default {
     toggleGeoRefModal() {
       if (this.showGeoRef) {
         //* when popup closes, empty form
-        this.erreurUploadMessage = "";
+        this.erreurUploadMessage = '';
         this.file = null;
       }
       this.showGeoRef = !this.showGeoRef;
     },
 
     handleFileUpload() {
-      this.erreurUploadMessage = "";
+      this.erreurUploadMessage = '';
       this.file = this.$refs.file.files[0];
     },
 
     georeferencement() {
       const url = `${this.$store.state.configuration.VUE_APP_DJANGO_API_BASE}exif-geom-reader/`;
       let formData = new FormData();
-      formData.append("image_file", this.file);
+      formData.append('image_file', this.file);
       axios
         .post(url, formData, {
           headers: {
-            "Content-Type": "multipart/form-data",
+            'Content-Type': 'multipart/form-data',
           },
         })
         .then((response) => {
-          if (response.data.geom.indexOf("POINT") >= 0) {
+          if (response.data.geom.indexOf('POINT') >= 0) {
             let regexp = /POINT\s\((.*)\s(.*)\)/;
             let arr = regexp.exec(response.data.geom);
             let json = {
-              type: "Feature",
+              type: 'Feature',
               geometry: {
-                type: "Point",
+                type: 'Point',
                 coordinates: [parseFloat(arr[1]), parseFloat(arr[2])],
               },
               properties: {},
@@ -526,9 +610,9 @@ export default {
             this.updateGeomField(json);
             // Set Attachment
             this.addAttachment({
-              title: "Localisation",
-              info: "",
-              id: "loc",
+              title: 'Localisation',
+              info: '',
+              id: 'loc',
               attachment_file: this.file.name,
               fileToImport: this.file,
             });
@@ -561,18 +645,18 @@ export default {
               : null,
         };
       });
-      this.$store.commit("feature/SET_EXTRA_FORM", extraForm);
+      this.$store.commit('feature/SET_EXTRA_FORM', extraForm);
     },
 
     add_attachement_formset() {
-      this.$store.commit("feature/ADD_ATTACHMENT_FORM", {
+      this.$store.commit('feature/ADD_ATTACHMENT_FORM', {
         dataKey: this.attachmentDataKey,
       }); // * create an object with the counter in store
       this.attachmentDataKey += 1; // * increment counter for key in v-for
     },
 
     addAttachment(attachment) {
-      this.$store.commit("feature/ADD_ATTACHMENT_FORM", {
+      this.$store.commit('feature/ADD_ATTACHMENT_FORM', {
         dataKey: this.attachmentDataKey,
         title: attachment.title,
         attachment_file: attachment.attachment_file,
@@ -590,7 +674,7 @@ export default {
     },
 
     add_linked_formset() {
-      this.$store.commit("feature/ADD_LINKED_FORM", {
+      this.$store.commit('feature/ADD_LINKED_FORM', {
         dataKey: this.linkedDataKey,
       }); // * create an object with the counter in store
       this.linkedDataKey += 1; // * increment counter for key in v-for
@@ -598,7 +682,7 @@ export default {
 
     addExistingLinkedFormset(linkedFormset) {
       for (const linked of linkedFormset) {
-        this.$store.commit("feature/ADD_LINKED_FORM", {
+        this.$store.commit('feature/ADD_LINKED_FORM', {
           dataKey: this.linkedDataKey,
           relation_type: linked.relation_type,
           feature_to: linked.feature_to,
@@ -608,12 +692,12 @@ export default {
     },
 
     updateStore() {
-      this.$store.commit("feature/UPDATE_FORM", {
+      this.$store.commit('feature/UPDATE_FORM', {
         title: this.form.title.value,
         status: this.form.status.value,
         description: this.form.description,
         geometry: this.form.geom.value,
-        feature_id: this.feature ? this.feature.feature_id : "",
+        feature_id: this.feature ? this.feature.feature_id : '',
       });
     },
 
@@ -622,12 +706,12 @@ export default {
         this.form.title.errors = [];
         return true;
       } else if (
-        !this.form.title.errors.includes("Veuillez compléter ce champ.")
+        !this.form.title.errors.includes('Veuillez compléter ce champ.')
       ) {
-        this.form.title.errors.push("Veuillez compléter ce champ.");
+        this.form.title.errors.push('Veuillez compléter ce champ.');
         document
-          .getElementById("errorlist-title")
-          .scrollIntoView({ block: "end", inline: "nearest" });
+          .getElementById('errorlist-title')
+          .scrollIntoView({ block: 'end', inline: 'nearest' });
       }
       return false;
     },
@@ -637,12 +721,12 @@ export default {
         this.form.geom.errors = [];
         return true;
       } else if (
-        !this.form.geom.errors.includes("Valeur géométrique non valide.")
+        !this.form.geom.errors.includes('Valeur géométrique non valide.')
       ) {
-        this.form.geom.errors.push("Valeur géométrique non valide.");
+        this.form.geom.errors.push('Valeur géométrique non valide.');
         document
-          .getElementById("errorlist-geom")
-          .scrollIntoView({ block: "end", inline: "nearest" });
+          .getElementById('errorlist-geom')
+          .scrollIntoView({ block: 'end', inline: 'nearest' });
       }
       return false;
     },
@@ -681,15 +765,15 @@ export default {
         //* in a moderate project, at edition of a published feature by someone else than admin or moderator, switch published status to draft.
         if (
           this.project.moderation &&
-          this.currentRouteName === "editer-signalement" &&
-          this.form.status.value.value === "published" &&
+          this.currentRouteName === 'editer-signalement' &&
+          this.form.status.value.value === 'published' &&
           !this.permissions.is_project_administrator &&
           !this.permissions.is_project_moderator
         ) {
-          this.form.status.value = { name: "Brouillon", value: "draft" };
+          this.form.status.value = { name: 'Brouillon', value: 'draft' };
           this.updateStore();
         }
-        this.$store.dispatch("feature/SEND_FEATURE", this.currentRouteName);
+        this.$store.dispatch('feature/SEND_FEATURE', this.currentRouteName);
       }
     },
 
@@ -697,9 +781,9 @@ export default {
 
     onFeatureTypeLoaded() {
       var geomLeaflet = {
-        point: "circlemarker",
-        linestring: "polyline",
-        polygon: "polygon",
+        point: 'circlemarker',
+        linestring: 'polyline',
+        polygon: 'polygon',
       };
       var geomType = this.feature_type.geom_type;
       var drawConfig = {
@@ -716,66 +800,66 @@ export default {
         draw: {
           toolbar: {
             actions: {
-              title: "Annuler le dessin",
-              text: "Annuler",
+              title: 'Annuler le dessin',
+              text: 'Annuler',
             },
             finish: {
-              title: "Terminer le dessin",
-              text: "Terminer",
+              title: 'Terminer le dessin',
+              text: 'Terminer',
             },
             undo: {
-              title: "Supprimer le dernier point dessiné",
-              text: "Supprimer le dernier point",
+              title: 'Supprimer le dernier point dessiné',
+              text: 'Supprimer le dernier point',
             },
             buttons: {
-              polyline: "Dessiner une polyligne",
-              polygon: "Dessiner un polygone",
-              rectangle: "Dessiner un rectangle",
-              circle: "Dessiner un cercle",
-              marker: "Dessiner une balise",
-              circlemarker: "Dessiner un point",
+              polyline: 'Dessiner une polyligne',
+              polygon: 'Dessiner un polygone',
+              rectangle: 'Dessiner un rectangle',
+              circle: 'Dessiner un cercle',
+              marker: 'Dessiner une balise',
+              circlemarker: 'Dessiner un point',
             },
           },
           handlers: {
             circle: {
               tooltip: {
-                start: "Cliquer et glisser pour dessiner le cercle.",
+                start: 'Cliquer et glisser pour dessiner le cercle.',
               },
-              radius: "Rayon",
+              radius: 'Rayon',
             },
             circlemarker: {
               tooltip: {
-                start: "Cliquer sur la carte pour placer le point.",
+                start: 'Cliquer sur la carte pour placer le point.',
               },
             },
             marker: {
               tooltip: {
-                start: "Cliquer sur la carte pour placer la balise.",
+                start: 'Cliquer sur la carte pour placer la balise.',
               },
             },
             polygon: {
               tooltip: {
-                start: "Cliquer pour commencer à dessiner.",
-                cont: "Cliquer pour continuer à dessiner.",
-                end: "Cliquer sur le premier point pour terminer le dessin.",
+                start: 'Cliquer pour commencer à dessiner.',
+                cont: 'Cliquer pour continuer à dessiner.',
+                end: 'Cliquer sur le premier point pour terminer le dessin.',
               },
             },
             polyline: {
-              error: "<strong>Error:</strong> shape edges cannot cross!",
+              error: '<strong>Error:</strong> shape edges cannot cross!',
               tooltip: {
-                start: "Cliquer pour commencer à dessiner.",
-                cont: "Cliquer pour continuer à dessiner.",
-                end: "Cliquer sur le dernier point pour terminer le dessin.",
+                start: 'Cliquer pour commencer à dessiner.',
+                cont: 'Cliquer pour continuer à dessiner.',
+                end: 'Cliquer sur le dernier point pour terminer le dessin.',
               },
             },
             rectangle: {
               tooltip: {
-                start: "Cliquer et glisser pour dessiner le rectangle.",
+                start: 'Cliquer et glisser pour dessiner le rectangle.',
               },
             },
             simpleshape: {
               tooltip: {
-                end: "Relâcher la souris pour terminer de dessiner.",
+                end: 'Relâcher la souris pour terminer de dessiner.',
               },
             },
           },
@@ -784,36 +868,36 @@ export default {
           toolbar: {
             actions: {
               save: {
-                title: "Sauver les modifications",
-                text: "Sauver",
+                title: 'Sauver les modifications',
+                text: 'Sauver',
               },
               cancel: {
                 title:
-                  "Annuler la modification, annule toutes les modifications",
-                text: "Annuler",
+                  'Annuler la modification, annule toutes les modifications',
+                text: 'Annuler',
               },
               clearAll: {
                 title: "Effacer l'objet",
-                text: "Effacer",
+                text: 'Effacer',
               },
             },
             buttons: {
               edit: "Modifier l'objet",
-              editDisabled: "Aucun objet à modifier",
+              editDisabled: 'Aucun objet à modifier',
               remove: "Supprimer l'objet",
-              removeDisabled: "Aucun objet à supprimer",
+              removeDisabled: 'Aucun objet à supprimer',
             },
           },
           handlers: {
             edit: {
               tooltip: {
                 text: "Faites glisser les marqueurs ou les balises pour modifier l'élément.",
-                subtext: "Cliquez sur Annuler pour annuler les modifications..",
+                subtext: 'Cliquez sur Annuler pour annuler les modifications..',
               },
             },
             remove: {
               tooltip: {
-                text: "Cliquez sur un élément pour le supprimer.",
+                text: 'Cliquez sur un élément pour le supprimer.',
               },
             },
           },
@@ -824,7 +908,7 @@ export default {
       this.map.addLayer(this.drawnItems);
 
       this.drawControlFull = new L.Control.Draw({
-        position: "topright",
+        position: 'topright',
         edit: {
           featureGroup: this.drawnItems,
         },
@@ -832,14 +916,14 @@ export default {
       });
 
       this.drawControlEditOnly = new L.Control.Draw({
-        position: "topright",
+        position: 'topright',
         edit: {
           featureGroup: this.drawnItems,
         },
         draw: false,
       });
 
-      if (this.currentRouteName === "editer-signalement") {
+      if (this.currentRouteName === 'editer-signalement') {
         this.map.addControl(this.drawControlEditOnly);
       } else {
         this.map.addControl(this.drawControlFull);
@@ -847,7 +931,7 @@ export default {
       this.changeMobileBtnOrder();
 
       this.map.on(
-        "draw:created",
+        'draw:created',
         function (e) {
           var layer = e.layer;
           this.add_layer_call_back(layer);
@@ -856,26 +940,25 @@ export default {
       //var wellknown;// TODO Remplacer par autre chose
 
       this.map.on(
-        "draw:edited",
+        'draw:edited',
         function (e) {
           var layers = e.layers;
           let self = this;
           layers.eachLayer(function (layer) {
-            //this.updateGeomField(wellknown.stringify(layer.toGeoJSON()))
             self.updateGeomField(layer.toGeoJSON());
           });
         }.bind(this)
       );
 
       this.map.on(
-        "draw:deleted",
+        'draw:deleted',
         function () {
           this.drawControlEditOnly.remove(this.map);
           this.drawControlFull.addTo(this.map);
-          this.updateGeomField("");
-          if (geomType === "point") {
+          this.updateGeomField('');
+          if (geomType === 'point') {
             this.showGeoPositionBtn = true;
-            this.erreurGeolocalisationMessage = "";
+            this.erreurGeolocalisationMessage = '';
           }
         }.bind(this)
       );
@@ -885,12 +968,12 @@ export default {
       if (this.drawnItems) this.drawnItems.clearLayers();
       var geomType = this.feature_type.geom_type;
       if (geomFeatureJSON) {
-        var geomJSON = flip(geomFeatureJSON.geometry); //turf.flip(geomFeatureJSON)
-        if (geomType === "point") {
+        var geomJSON = flip(geomFeatureJSON.geometry);
+        if (geomType === 'point') {
           L.circleMarker(geomJSON.coordinates).addTo(this.drawnItems);
-        } else if (geomType === "linestring") {
+        } else if (geomType === 'linestring') {
           L.polyline(geomJSON.coordinates).addTo(this.drawnItems);
-        } else if (geomType === "polygon") {
+        } else if (geomType === 'polygon') {
           L.polygon(geomJSON.coordinates).addTo(this.drawnItems);
         }
         this.map.fitBounds(this.drawnItems.getBounds(), { padding: [25, 25] });
@@ -920,7 +1003,7 @@ export default {
       });
       const currentFeatureId = this.$route.params.slug_signal;
       setTimeout(() => {
-        let project_id = this.$route.params.slug.split("-")[0];
+        let project_id = this.$route.params.slug.split('-')[0];
         const mvtUrl = `${this.$store.state.configuration.VUE_APP_DJANGO_API_BASE}features.mvt/?tile={z}/{x}/{y}&project_id=${project_id}`;
 
         mapUtil.addVectorTileLayer(
@@ -944,7 +1027,7 @@ export default {
               true,
               this.$store.state.feature_type.feature_types
             );
-            if (this.currentRouteName === "editer-signalement") {
+            if (this.currentRouteName === 'editer-signalement') {
               const currentFeature = features.filter(
                 (feat) => feat.id === currentFeatureId
               )[0];
@@ -956,7 +1039,7 @@ export default {
           throw error;
         });
 
-      document.addEventListener("change-layers-order", (event) => {
+      document.addEventListener('change-layers-order', (event) => {
         // Reverse is done because the first layer in order has to be added in the map in last.
         // Slice is done because reverse() changes the original array, so we make a copy first
         mapUtil.updateOrder(event.detail.layers.slice().reverse());
@@ -968,28 +1051,27 @@ export default {
       this.drawControlFull.remove(this.map);
       this.drawControlEditOnly.addTo(this.map);
       //var wellknown;// TODO Remplacer par autre chose
-      //this.updateGeomField(wellknown.stringify(layer.toGeoJSON()))
       this.updateGeomField(layer.toGeoJSON());
-      if (this.feature_type.geomType === "point") {
+      if (this.feature_type.geomType === 'point') {
         this.showGeoPositionBtn = false;
-        this.erreurGeolocalisationMessage = "";
+        this.erreurGeolocalisationMessage = '';
       }
     },
 
     changeMobileBtnOrder() { //* move large toolbar for polygon creation, cutting map in the middle
       function changeDisplay() {
-        let buttons = document.querySelector(".leaflet-draw-actions.leaflet-draw-actions-top.leaflet-draw-actions-bottom")
+        let buttons = document.querySelector('.leaflet-draw-actions.leaflet-draw-actions-top.leaflet-draw-actions-bottom');
         if (buttons && buttons.style) {
-          buttons.style.display = "flex"
-          buttons.style["flex-direction"] = "column"
+          buttons.style.display = 'flex';
+          buttons.style['flex-direction'] = 'column';
         }
       }
       if (window.screen.availWidth < 767) { //* change button order all the time to keep homogeinity on mobile
-        let wrapper = document.querySelector(".leaflet-top.leaflet-right");
+        let wrapper = document.querySelector('.leaflet-top.leaflet-right');
         if (wrapper) wrapper.appendChild(wrapper.children[0]);
-        if (this.feature_type.geom_type === "polygon") { //* if it's a polygon, change tools direction to vertical
-          let polygonBtn = document.querySelector(".leaflet-draw-draw-polygon"); //* since elements are generated
-          if (polygonBtn) polygonBtn.addEventListener("click", changeDisplay) //* it should be done at each click
+        if (this.feature_type.geom_type === 'polygon') { //* if it's a polygon, change tools direction to vertical
+          let polygonBtn = document.querySelector('.leaflet-draw-draw-polygon'); //* since elements are generated
+          if (polygonBtn) polygonBtn.addEventListener('click', changeDisplay); //* it should be done at each click
         }
       }
     },
@@ -1006,57 +1088,6 @@ export default {
         .then((data) => this.addExistingLinkedFormset(data));
     },
   },
-
-  created() {
-    this.$store.commit(
-      "feature_type/SET_CURRENT_FEATURE_TYPE_SLUG",
-      this.$route.params.slug_type_signal
-    );
-    //* empty previous feature data, not emptying by itself since it doesn't update by itself anymore
-    if (this.currentRouteName === "ajouter-signalement") {
-      this.$store.commit("feature/SET_CURRENT_FEATURE", []);
-    }
-
-    if (this.$route.params.slug_signal) {
-      this.getFeatureAttachments();
-      this.getLinkedFeatures();
-    }
-  },
-
-  mounted() {
-    let promises = [
-      this.$store.dispatch("GET_PROJECT_INFO", this.$route.params.slug),
-    ];
-    if (this.$route.params.slug_signal) {
-      promises.push(
-        this.$store.dispatch("feature/GET_PROJECT_FEATURE", {
-          project_slug: this.$route.params.slug,
-          feature_id: this.$route.params.slug_signal,
-        })
-      );
-    }
-
-    Promise.all(promises).then(() => {
-      this.initForm();
-      this.initMap();
-      this.onFeatureTypeLoaded();
-      this.initExtraForms(this.feature);
-
-      setTimeout(
-        function () {
-          mapUtil.addGeocoders(this.$store.state.configuration);
-        }.bind(this),
-        1000
-      );
-    });
-  },
-
-  destroyed() {
-    //* be sure that previous Formset have been cleared for creation
-    this.$store.commit("feature/CLEAR_ATTACHMENT_FORM");
-    this.$store.commit("feature/CLEAR_LINKED_FORM");
-    this.$store.commit("feature/CLEAR_EXTRA_FORM");
-  },
 };
 </script>
 
@@ -1077,13 +1108,13 @@ export default {
     height: 80vh;
   }
 }
-/* // ! missing style in semantic.min.css, je ne comprends pas comment... */
+/* // ! missing style in semantic.min.css */
 .ui.right.floated.button {
   float: right;
   margin-right: 0;
   margin-left: 0.25em;
 }
-/* // ! margin écrasé par class last-child first-child, pas normal ... */
+/* // ! margin écrasé par class last-child first-child */
 .ui.segment {
   margin: 1rem 0 !important;
 }
diff --git a/src/views/feature/Feature_list.vue b/src/views/feature/Feature_list.vue
index 9f08055a416e30b2b9627ff828d3ee9d23b37f13..094e4aa9c0fa3e5c0d023ad27855d3b8eaaff510 100644
--- a/src/views/feature/Feature_list.vue
+++ b/src/views/feature/Feature_list.vue
@@ -1,65 +1,67 @@
 <template>
   <div class="fourteen wide column">
-    <div id="feature-list-container" class="ui grid mobile-column">
+    <div
+      id="feature-list-container"
+      class="ui grid mobile-column"
+    >
       <div class="four wide column mobile-fullwidth">
         <h1>Signalements</h1>
       </div>
       <div class="twelve-wide column no-padding-mobile mobile-fullwidth">
-        <div class="ui large text loader">Chargement</div>
+        <div class="ui large text loader">
+          Chargement
+        </div>
         <div class="ui secondary menu no-margin">
           <a
-            @click="showMap = true"
             :class="['item no-margin', { active: showMap }]"
             data-tab="map"
             data-tooltip="Carte"
-            ><i class="map fitted icon"></i
-          ></a>
+            @click="showMap = true"
+          ><i class="map fitted icon" /></a>
           <a
-            @click="showMap = false"
             :class="['item no-margin', { active: !showMap }]"
             data-tab="list"
             data-tooltip="Liste"
-            ><i class="list fitted icon"></i
-          ></a>
+            @click="showMap = false"
+          ><i class="list fitted icon" /></a>
           <div class="item">
             <h4>
               {{ featuresCount }} signalement{{ featuresCount > 1 ? "s" : "" }}
-              <!-- {{ filteredFeatures.length }} signalement{{
-                filteredFeatures.length > 1 ? "s" : ""
-              }} -->
             </h4>
           </div>
 
           <div
             v-if="
               project &&
-              feature_types.length > 0 &&
-              permissions.can_create_feature
+                feature_types.length > 0 &&
+                permissions.can_create_feature
             "
             id="button-dropdown"
             class="item right"
           >
             <div
-              @click="toggleAddFeature"
               class="ui dropdown button compact button-hover-green"
               data-tooltip="Ajouter un signalement"
               data-position="bottom right"
+              @click="toggleAddFeature"
             >
-              <i class="plus fitted icon"></i>
+              <i class="plus fitted icon" />
               <div
                 v-if="showAddFeature"
                 class="menu left transition visible"
                 style="z-index: 9999"
               >
-                <div class="header">Ajouter un signalement du type</div>
+                <div class="header">
+                  Ajouter un signalement du type
+                </div>
                 <div class="scrolling menu text-wrap">
                   <router-link
+                    v-for="(type, index) in feature_types"
+                    :key="type.slug + index"
                     :to="{
                       name: 'ajouter-signalement',
                       params: { slug_type_signal: type.slug },
                     }"
-                    v-for="(type, index) in feature_types"
-                    :key="type.slug + index"
                     class="item"
                   >
                     {{ type.title }}
@@ -68,27 +70,28 @@
               </div>
             </div>
 
-
             <div
               v-if="checkedFeatures.length > 0 && mode === 'modify'"
-              @click="toggleModifyStatus"
               class="ui dropdown button compact button-hover-green margin-left-25"
               data-tooltip="Modifier le statut des Signalements"
               data-position="bottom right"
+              @click="toggleModifyStatus"
             >
-              <i class="pencil fitted icon"></i>
+              <i class="pencil fitted icon" />
               <div
                 v-if="showModifyStatus"
                 class="menu left transition visible"
                 style="z-index: 9999"
               >
-                <div class="header">Modifier le statut des Signalements</div>
+                <div class="header">
+                  Modifier le statut des Signalements
+                </div>
                 <div class="scrolling menu text-wrap">
                   <span
                     v-for="status in availableStatus"
                     :key="status.value"
-                    @click="modifyStatus(status.value)"
                     class="item"
+                    @click="modifyStatus(status.value)"
                   >
                     {{ status.name }}
                   </span>
@@ -98,19 +101,22 @@
 
             <div
               v-if="checkedFeatures.length > 0 && mode === 'delete'"
-              @click="modalAllDelete"
               class="ui button compact button-hover-red margin-left-25"
               data-tooltip="Effacer tous les types de signalements sélectionnés"
               data-position="bottom right"
+              @click="modalAllDelete"
             >
-              <i class="grey trash fitted icon"></i>
+              <i class="grey trash fitted icon" />
             </div>
           </div>
         </div>
       </div>
     </div>
 
-    <section id="form-filters" class="ui form grid">
+    <section
+      id="form-filters"
+      class="ui form grid"
+    >
       <div class="field wide four column no-margin-mobile">
         <label>Type</label>
         <Dropdown
@@ -135,47 +141,64 @@
       <div class="field wide four column">
         <label>Nom</label>
         <div class="ui icon input">
-          <i class="search icon"></i>
+          <i class="search icon" />
           <div class="ui action input">
             <input
+              v-model="form.title"
               type="text"
               name="title"
-              v-model="form.title"
-              v-on:keyup.enter="fetchPagedFeatures"
-            />
+              @keyup.enter="fetchPagedFeatures"
+            >
             <button
-              @click="fetchPagedFeatures"
               id="submit-search"
               class="ui teal icon button"
+              @click="fetchPagedFeatures"
             >
-              <i class="search icon"></i>
+              <i class="search icon" />
             </button>
           </div>
         </div>
       </div>
       <!-- map params, updated on map move -->
-      <input type="hidden" name="zoom" v-model="zoom" />
-      <input type="hidden" name="lat" v-model="lat" />
-      <input type="hidden" name="lng" v-model="lng" />
+      <input
+        v-model="zoom"
+        type="hidden"
+        name="zoom"
+      >
+      <input
+        v-model="lat"
+        type="hidden"
+        name="lat"
+      >
+      <input
+        v-model="lng"
+        type="hidden"
+        name="lng"
+      >
     </section>
 
-    <div v-show="showMap" class="ui tab active map-container" data-tab="map">
-      <div id="map" ref="map"></div>
+    <div
+      v-show="showMap"
+      class="ui tab active map-container"
+      data-tab="map"
+    >
+      <div
+        id="map"
+        ref="map"
+      />
       <SidebarLayers v-if="basemaps && map" />
     </div>
-    <!-- | -->
-      <!-- v-on:update:clickedFeatures="handleClickedFeatures" -->
     <FeatureListTable
       v-show="!showMap"
-      v-on:update:page="handlePageChange"
-      v-on:update:sort="handleSortChange"
-      :paginatedFeatures="paginatedFeatures"
-      :checkedFeatures="checkedFeatures"
-      :clickedFeatures.sync="clickedFeatures"
+      :paginated-features="paginatedFeatures"
+      :checked-features.sync="checkedFeatures"
+      :features-count="featuresCount"
+      :clicked-features.sync="clickedFeatures"
       :mode.sync="mode"
-      :featuresCount="featuresCount"
       :pagination="pagination"
       :sort="sort"
+      @update:page="handlePageChange"
+      @update:sort="handleSortChange"
     />
 
     <!-- MODAL ALL DELETE FEATURE TYPE -->
@@ -190,18 +213,21 @@
           { 'active visible': modalAllDeleteOpen },
         ]"
       >
-        <i @click="modalAllDeleteOpen = false" class="close icon"></i>
+        <i
+          class="close icon"
+          @click="modalAllDeleteOpen = false"
+        />
         <div class="ui icon header">
-          <i class="trash alternate icon"></i>
+          <i class="trash alternate icon" />
           Êtes-vous sûr de vouloir effacer
           <span v-if="checkedFeatures.length === 1"> un signalement ? </span>
           <span v-else> ces {{ checkedFeatures.length }} signalements ? </span>
         </div>
         <div class="actions">
           <button
-            @click="deleteAllFeatureSelection"
             type="button"
-            class="ui red compact fluid button no-margin"
+            class="ui red compact fluid button"
+            @click="deleteAllFeatureSelection"
           >
             Confirmer la suppression
           </button>
@@ -212,16 +238,16 @@
 </template>
 
 <script>
-import { mapGetters, mapState, mapActions } from "vuex";
-import { mapUtil } from "@/assets/js/map-util.js";
-import featureAPI from "@/services/feature-api";
-import SidebarLayers from "@/components/map-layers/SidebarLayers";
-import FeatureListTable from "@/components/feature/FeatureListTable";
-import Dropdown from "@/components/Dropdown.vue";
-import axios from "@/axios-client.js";
+import { mapGetters, mapState, mapActions } from 'vuex';
+import { mapUtil } from '@/assets/js/map-util.js';
+import featureAPI from '@/services/feature-api';
+import SidebarLayers from '@/components/map-layers/SidebarLayers';
+import FeatureListTable from '@/components/feature/FeatureListTable';
+import Dropdown from '@/components/Dropdown.vue';
+import axios from '@/axios-client.js';
 
 export default {
-  name: "Feature_list",
+  name: 'FeatureList',
 
   components: {
     SidebarLayers,
@@ -233,26 +259,26 @@ export default {
     return {
       form: {
         type: {
-          selected: "",
+          selected: '',
         },
         status: {
-          selected: "",
+          selected: '',
           choices: [
             {
-              name: "Brouillon",
-              value: "draft",
+              name: 'Brouillon',
+              value: 'draft',
             },
             {
-              name: "En attente de publication",
-              value: "pending",
+              name: 'En attente de publication',
+              value: 'pending',
             },
             {
-              name: "Publié",
-              value: "published",
+              name: 'Publié',
+              value: 'published',
             },
             {
-              name: "Archivé",
-              value: "archived",
+              name: 'Archivé',
+              value: 'archived',
             },
           ],
         },
@@ -261,7 +287,7 @@ export default {
       baseUrl: this.$store.state.configuration.BASE_URL,
       clickedFeatures: [],
       modalAllDeleteOpen: false,
-      mode: "modify",
+      mode: 'modify',
       map: null,
       zoom: null,
       lat: null,
@@ -278,7 +304,7 @@ export default {
       previous: null,
       next: null,
       sort: {
-        column: "",
+        column: '',
         ascending: true,
       },
       showMap: true,
@@ -287,52 +313,8 @@ export default {
     };
   },
 
-  watch: {
-    "form.type.selected"() {
-      this.fetchPagedFeatures();
-    },
-    "form.status.selected.value"() {
-      this.fetchPagedFeatures();
-    },
-    map(newValue) {
-      if (newValue && this.paginatedFeatures && this.paginatedFeatures.length) {
-        if (this.currentLayer) {
-          this.map.removeLayer(this.currentLayer);
-        }
-        this.currentLayer = mapUtil.addFeatures(
-          this.paginatedFeatures,
-          {},
-          true,
-          this.feature_types
-        );
-      }
-    },
-    paginatedFeatures: {
-      deep: true,
-      handler(newValue, oldValue) {
-        if (newValue && newValue.length && newValue !== oldValue && this.map) {
-          if (this.currentLayer) {
-            this.map.removeLayer(this.currentLayer);
-            this.currentLayer = null;
-          }
-          this.currentLayer = mapUtil.addFeatures(
-            newValue,
-            {},
-            true,
-            this.feature_types
-          );
-        } else if (newValue && newValue.length === 0) {
-          if (this.currentLayer) {
-            this.map.removeLayer(this.currentLayer);
-            this.currentLayer = null;
-          }
-        }
-      }
-    }
-  },
-
   computed: {
-    ...mapState(["user", "USER_LEVEL_PROJECTS"]),
+    ...mapState(['user', 'USER_LEVEL_PROJECTS']),
     ...mapGetters([
       'project', 'permissions'
     ]),
@@ -353,13 +335,11 @@ export default {
     statusChoices() {
       //* if project is not moderate, remove pending status
       return this.form.status.choices.filter((el) =>
-        this.project && this.project.moderation ? true : el.value !== "pending"
+        this.project && this.project.moderation ? true : el.value !== 'pending'
       );
     },
 
-    availableStatus() { //* attente de réponse sur le ticket
-      //return this.statusChoices.filter((status) => status)
-
+    availableStatus() {
       if (this.project) {
         const isModerate = this.project.moderation;
         const userStatus = this.USER_LEVEL_PROJECTS[this.project.slug];
@@ -368,41 +348,41 @@ export default {
           : false; //* si le contributeur est l'auteur du signalement
         if (
           //* si admin, modérateur ou super contributeur, statuts toujours disponible: Brouillon, Publié, Archivé
-          userStatus === "Administrateur projet" ||
-          (userStatus === "Super Contributeur" && !isModerate)
+          userStatus === 'Administrateur projet' ||
+          (userStatus === 'Super Contributeur' && !isModerate)
         ) {
-          return this.statusChoices.filter((el) => el.value !== "pending");
-        } else if (userStatus === "Super Contributeur" && isModerate) {
+          return this.statusChoices.filter((el) => el.value !== 'pending');
+        } else if (userStatus === 'Super Contributeur' && isModerate) {
           return this.statusChoices.filter(
-            (el) => el.value === "draft" || el.value === "pending"
+            (el) => el.value === 'draft' || el.value === 'pending'
           );
-        } else if (userStatus === "Modérateur") {
+        } else if (userStatus === 'Modérateur') {
           return this.statusChoices.filter(
-            (el) => el.value === "draft" || el.value === "published"
+            (el) => el.value === 'draft' || el.value === 'published'
           );
-        } else if (userStatus === "Contributeur") {
+        } else if (userStatus === 'Contributeur') {
           //* cas particuliers du contributeur
           if (
-            this.currentRouteName === "ajouter-signalement" ||
+            this.currentRouteName === 'ajouter-signalement' ||
             !isOwnFeature
           ) {
             //* même cas à l'ajout d'une feature ou si feature n'a pas été créé par le contributeur
             return isModerate
               ? this.statusChoices.filter(
-                  (el) => el.value === "draft" || el.value === "pending"
-                )
+                (el) => el.value === 'draft' || el.value === 'pending'
+              )
               : this.statusChoices.filter(
-                  (el) => el.value === "draft" || el.value === "published"
-                );
+                (el) => el.value === 'draft' || el.value === 'published'
+              );
           } else {
             //* à l'édition d'une feature et si le contributeur est l'auteur de la feature
             return isModerate
               ? this.statusChoices.filter(
-                  (el) => el.value !== "published" //* toutes sauf "Publié"
-                )
+                (el) => el.value !== 'published' //* toutes sauf "Publié"
+              )
               : this.statusChoices.filter(
-                  (el) => el.value !== "pending" //* toutes sauf "En cours de publication"
-                );
+                (el) => el.value !== 'pending' //* toutes sauf "En cours de publication"
+              );
           }
         }
       }
@@ -414,6 +394,69 @@ export default {
     },
   },
 
+  watch: {
+    'form.type.selected'() {
+      this.fetchPagedFeatures();
+    },
+    'form.status.selected.value'() {
+      this.fetchPagedFeatures();
+    },
+    map(newValue) {
+      if (newValue && this.paginatedFeatures && this.paginatedFeatures.length) {
+        if (this.currentLayer) {
+          this.map.removeLayer(this.currentLayer);
+        }
+        this.currentLayer = mapUtil.addFeatures(
+          this.paginatedFeatures,
+          {},
+          true,
+          this.feature_types
+        );
+      }
+    },
+    paginatedFeatures: {
+      deep: true,
+      handler(newValue, oldValue) {
+        if (newValue && newValue.length && newValue !== oldValue && this.map) {
+          if (this.currentLayer) {
+            this.map.removeLayer(this.currentLayer);
+            this.currentLayer = null;
+          }
+          this.currentLayer = mapUtil.addFeatures(
+            newValue,
+            {},
+            true,
+            this.feature_types
+          );
+        } else if (newValue && newValue.length === 0) {
+          if (this.currentLayer) {
+            this.map.removeLayer(this.currentLayer);
+            this.currentLayer = null;
+          }
+        }
+      }
+    }
+  },
+
+  mounted() {
+    if (!this.project) {
+      // Chargements des features et infos projet en cas d'arrivée directe sur la page ou de refresh
+      this.$store
+        .dispatch('GET_PROJECT_INFO', this.$route.params.slug)
+        .then(() => this.initMap());
+    } else {
+      this.initMap();
+    }
+    this.fetchPagedFeatures();
+    window.addEventListener('mousedown', this.clickOutsideDropdown);
+  },
+
+  destroyed() {
+    window.removeEventListener('mousedown', this.clickOutsideDropdown);
+    //* allow user to change page if ever stuck on loader
+    this.$store.commit('DISCARD_LOADER');
+  },
+
   methods: {
     ...mapActions('feature', [
       'GET_PROJECT_FEATURES',
@@ -435,7 +478,7 @@ export default {
     },
 
     clickOutsideDropdown(e) {
-      if (!e.target.closest("#button-dropdown")) {
+      if (!e.target.closest('#button-dropdown')) {
         this.showModifyStatus = false;
         setTimeout(() => { //* timout necessary to give time to click on link to add feature
           this.showAddFeature = false;
@@ -444,42 +487,42 @@ export default {
     },
 
     async modifyStatus(newStatus) {
-      let errorCount = 0
+      let errorCount = 0;
       const promises = this.checkedFeatures.map((feature_id) => {
-        let feature = this.clickedFeatures.find((el) => el.feature_id === feature_id)
+        let feature = this.clickedFeatures.find((el) => el.feature_id === feature_id);
         if (feature) {
-        return featureAPI.updateFeature({
-          feature_id,
-          feature_type__slug: feature.feature_type,
-          project__slug: this.$route.params.slug, newStatus
-        })
+          return featureAPI.updateFeature({
+            feature_id,
+            feature_type__slug: feature.feature_type,
+            project__slug: this.$route.params.slug, newStatus
+          });
         } else {
           errorCount += 1;
         }
-      })
-      const promisesResult = await Promise.all(promises)
+      });
+      const promisesResult = await Promise.all(promises);
       promisesResult.forEach((response) => {
         if (response && response.data && response.status === 200) {
           this.checkedFeatures.splice(this.checkedFeatures.indexOf(response.data.id), 2);
         } else {
           errorCount += 1;
         }
-      })
+      });
       let message = {
-        comment: "Tous les signalements ont été modifié avec succès.",
-        level: "positive"
-      } 
+        comment: 'Tous les signalements ont été modifié avec succès.',
+        level: 'positive'
+      }; 
       if (errorCount) {
         //* display error message
         if(errorCount === 1) {
-          message.comment = "Un signalement n'a pas pu être modifié. (Il reste sélectionné)"
+          message.comment = "Un signalement n'a pas pu être modifié. (Il reste sélectionné)";
         } else {
-          message.comment = `${errorCount} signalements n'ont pas pu être modifiés. (Ils restent sélectionnés)`
+          message.comment = `${errorCount} signalements n'ont pas pu être modifiés. (Ils restent sélectionnés)`;
         }
-        message.level = "negative"
+        message.level = 'negative';
       }
       this.fetchPagedFeatures();
-      this.$store.commit("DISPLAY_MESSAGE", message);
+      this.$store.commit('DISPLAY_MESSAGE', message);
     },
 
 
@@ -523,9 +566,9 @@ export default {
     },
 
     initMap() {
-      this.zoom = this.$route.query.zoom || "";
-      this.lat = this.$route.query.lat || "";
-      this.lng = this.$route.query.lng || "";
+      this.zoom = this.$route.query.zoom || '';
+      this.lat = this.$route.query.lat || '';
+      this.lng = this.$route.query.lng || '';
 
       var mapDefaultViewCenter =
         this.$store.state.configuration.DEFAULT_MAP_VIEW.center;
@@ -542,7 +585,7 @@ export default {
 
       this.fetchBboxNfit();
 
-      document.addEventListener("change-layers-order", (event) => {
+      document.addEventListener('change-layers-order', (event) => {
         // Reverse is done because the first layer in order has to be added in the map in last.
         // Slice is done because reverse() changes the original array, so we make a copy first
         mapUtil.updateOrder(event.detail.layers.slice().reverse());
@@ -551,7 +594,7 @@ export default {
       // --------- End sidebar events ----------
 
       setTimeout(() => {
-        const project_id = this.$route.params.slug.split("-")[0];
+        const project_id = this.$route.params.slug.split('-')[0];
         const mvtUrl = `${this.API_BASE_URL}features.mvt/?tile={z}/{x}/{y}&project_id=${project_id}`;
         mapUtil.addVectorTileLayer(
           mvtUrl,
@@ -581,16 +624,16 @@ export default {
 
     getAvalaibleField(orderField) {
       let result = orderField;
-      if (orderField === "display_creator") {
-        result = "creator";
-      } else if (orderField === "display_last_editor") {
-        result = "last_editor";
+      if (orderField === 'display_creator') {
+        result = 'creator';
+      } else if (orderField === 'display_last_editor') {
+        result = 'last_editor';
       }
       return result;
     },
 
     buildQueryString() {
-      let urlParams = "";
+      let urlParams = '';
       let typeFilter = this.getFeatureTypeSlug(this.form.type.selected);
       let statusFilter = this.form.status.selected.value;
 
@@ -599,7 +642,7 @@ export default {
       if (this.form.title) urlParams += `&title=${this.form.title}`;
       if (this.sort.column) {
         urlParams += `&ordering=${
-          this.sort.ascending ? "-" : ""
+          this.sort.ascending ? '-' : ''
         }${this.getAvalaibleField(this.sort.column)}`;
       }
       return urlParams;
@@ -609,7 +652,7 @@ export default {
       this.onFilterChange(); //* use paginated event to watch change in filters and modify features on map
       let url = `${this.API_BASE_URL}projects/${this.$route.params.slug}/feature-paginated/?output=geojson&limit=${this.pagination.pagesize}&offset=${this.pagination.start}`;
       //* if receiving next & previous url
-      if (newUrl && typeof newUrl === "string") {
+      if (newUrl && typeof newUrl === 'string') {
         //newUrl = newUrl.replace("8000", "8010"); //* for dev uncomment to use proxy link
         url = newUrl;
       }
@@ -617,8 +660,8 @@ export default {
       url += queryString;
 
       this.$store.commit(
-        "DISPLAY_LOADER",
-        "Récupération des signalements en cours..."
+        'DISPLAY_LOADER',
+        'Récupération des signalements en cours...'
       );
       featureAPI.getPaginatedFeatures(url)
         .then((data) => {
@@ -630,18 +673,18 @@ export default {
           }
           //* bbox needs to be updated with the same filters
           if (this.paginatedFeatures.length) this.fetchBboxNfit(queryString);
-          this.$store.commit("DISCARD_LOADER");
+          this.$store.commit('DISCARD_LOADER');
         });
     },
 
     //* Pagination for table *//
 
     handlePageChange(page) {
-      if (page === "next") {
+      if (page === 'next') {
         this.toNextPage();
-      } else if (page === "previous") {
+      } else if (page === 'previous') {
         this.toPreviousPage();
-      } else if (typeof page === "number") {
+      } else if (typeof page === 'number') {
         //* update limit and offset
         this.toPage(page);
       }
@@ -686,25 +729,6 @@ export default {
       }
     },
   },
-
-  mounted() {
-    if (!this.project) {
-      // Chargements des features et infos projet en cas d'arrivée directe sur la page ou de refresh
-      this.$store
-        .dispatch("GET_PROJECT_INFO", this.$route.params.slug)
-        .then(() => this.initMap());
-    } else {
-      this.initMap();
-    }
-    this.fetchPagedFeatures();
-    window.addEventListener("mousedown", this.clickOutsideDropdown);
-  },
-
-  destroyed() {
-    window.removeEventListener("mousedown", this.clickOutsideDropdown);
-    //* allow user to change page if ever stuck on loader
-    this.$store.commit("DISCARD_LOADER");
-  },
 };
 </script>
 
@@ -737,10 +761,6 @@ export default {
   margin-left: 0.25em !important;
 }
 
-.no-margin {
-  margin: 0 !important;
-}
-
 .no-padding {
   padding: 0 !important;
 }
diff --git a/src/views/feature/Feature_offline.vue b/src/views/feature/Feature_offline.vue
index fb8a89bd8e14f663924e90e294a8a43dc60956dd..8bbe1718e7dff467c10f594dcf6921b1ee310d07 100644
--- a/src/views/feature/Feature_offline.vue
+++ b/src/views/feature/Feature_offline.vue
@@ -1,41 +1,35 @@
 <template>
-  <div v-frag>
-    Erreur Réseau lors de l'envoi du signalement. Votre signalement devra être envoyé au serveur quand vous aurez de nouveau accès à internet.
-    Veuillez à ce moment là cliquer sur Envoyer sur la page principale du projet 
+  <div>
+    <div class="margin-1">
+      Erreur réseau lors de l'envoi du signalement.
+    </div>
+    <div class="margin-1">
+      Votre signalement devra être envoyé au serveur quand vous aurez de nouveau accès à internet.
+    </div>
+    <div class="margin-1">
+      Veuillez à ce moment là, cliquer sur le bouton "Envoyer", sur la page principale du projet 
+    </div>
     <router-link
-            :to="{
-              name: 'project_detail',
-              params: { slug: $route.params.slug },
-            }"
-            class="header"
-            >Retour au projet</router-link
-          >
+      :to="{
+        name: 'project_detail',
+        params: { slug: $route.params.slug },
+      }"
+      class="ui positive left labeled icon button margin-1"
+    >
+      <i class="arrow left icon" />Retour au projet
+    </router-link>
   </div>
 </template>
 
 <script>
-import frag from "vue-frag";
 
 export default {
-  name: "Feature_offline",
-
-  directives: {
-    frag,
-  },
-
-  data() {
-    return {
-    };
-  },
-
-  computed: {
-  },
-  methods: {
-    
-  }
+  name: 'FeatureOffline',
 };
 </script>
 
-<style>
-
-</style>
\ No newline at end of file
+<style scoped>
+.margin-1 {
+  margin: 1rem;
+}
+</style>
diff --git a/src/views/feature_type/Feature_type_detail.vue b/src/views/feature_type/Feature_type_detail.vue
index 1bbaef1d40e9862489f22184f5c268f0a4f3785b..08642f62fc38bc95d2fe0c65f1b3d9d9cdfaa7d4 100644
--- a/src/views/feature_type/Feature_type_detail.vue
+++ b/src/views/feature_type/Feature_type_detail.vue
@@ -1,5 +1,8 @@
 <template>
-  <div v-if="structure" class="row">
+  <div
+    v-if="structure"
+    class="row"
+  >
     <div class="five wide column">
       <div class="ui attached secondary segment">
         <h1 class="ui center aligned header ellipsis">
@@ -7,17 +10,17 @@
             v-if="structure.geom_type === 'point'"
             class="ui medium image"
             src="@/assets/img/marker.png"
-          />
+          >
           <img
             v-if="structure.geom_type === 'linestring'"
             class="ui medium image"
             src="@/assets/img/line.png"
-          />
+          >
           <img
             v-if="structure.geom_type === 'polygon'"
             class="ui medium image"
             src="@/assets/img/polygon.png"
-          />
+          >
           {{ structure.title }}
         </h1>
       </div>
@@ -28,7 +31,7 @@
               :class="{ active: featuresLoading }"
               class="ui inverted dimmer"
             >
-             <div class="ui text loader">
+              <div class="ui text loader">
                 Récupération des signalements en cours...
               </div>
             </div>
@@ -40,7 +43,9 @@
             </div>
           </div>
 
-          <h3 class="ui header">Champs</h3>
+          <h3 class="ui header">
+            Champs
+          </h3>
           <div class="ui divided list">
             <div
               v-for="(field, index) in orderedCustomFields"
@@ -48,21 +53,28 @@
               class="item"
             >
               <div class="right floated content">
-                <div class="description">{{ field.field_type }}</div>
+                <div class="description">
+                  {{ field.field_type }}
+                </div>
+              </div>
+              <div class="content">
+                {{ field.label }} ({{ field.name }})
               </div>
-              <div class="content">{{ field.label }} ({{ field.name }})</div>
             </div>
           </div>
         </div>
       </div>
 
       <div class="ui bottom attached secondary segment">
-        <div v-if="permissions.can_create_feature" class="ui styled accordion">
+        <div
+          v-if="permissions.can_create_feature"
+          class="ui styled accordion"
+        >
           <div
-            @click="toggleShowImport"
             :class="['title', { active: showImport }]"
+            @click="toggleShowImport"
           >
-            <i class="dropdown icon"></i>
+            <i class="dropdown icon" />
             Importer des signalements
           </div>
           <div :class="['content', { active: showImport }]">
@@ -72,50 +84,60 @@
               :class="loadingImportFile ? 'loading' : ''"
             >
               <div class="field">
-                <label class="ui icon button ellipsis" for="json_file">
-                  <i class="file icon"></i>
+                <label
+                  class="ui icon button ellipsis"
+                  for="json_file"
+                >
+                  <i class="file icon" />
                   <span class="label">{{ fileToImport.name }}</span>
                 </label>
                 <input
-                  @change="onFileChange"
+                  id="json_file"
                   type="file"
                   accept="application/json, .json, .geojson"
                   style="display: none"
                   name="json_file"
-                  id="json_file"
-                />
+                  @change="onFileChange"
+                >
               </div>
 
               <router-link
                 v-if="
                   IDGO &&
-                  permissions &&
-                  permissions.can_create_feature
+                    permissions &&
+                    permissions.can_create_feature
                 "
                 :to="{
                   name: 'catalog-import',
                   params: {
                     slug,
                     feature_type_slug: $route.params.feature_type_slug
-                   },
+                  },
                 }"
                 class="ui icon button import-catalog"
-              >Importer les signalements à partir de {{ CATALOG_NAME|| 'IDGO'}}
+              >
+                Importer les signalements à partir de {{ CATALOG_NAME|| 'IDGO' }}
               </router-link>
-              <div v-if="$route.params.geojson" class="ui button import-catalog basic active teal no-hover">
-                Ressource {{$route.params.geojson.name}}
+              <div
+                v-if="$route.params.geojson"
+                class="ui button import-catalog basic active teal no-hover"
+              >
+                Ressource {{ $route.params.geojson.name }}
               </div>
-              <ul v-if="importError" class="errorlist">
+              <ul
+                v-if="importError"
+                class="errorlist"
+              >
                 <li>
                   {{ importError }}
                 </li>
               </ul>
               <button
                 :disabled="fileToImport.size === 0 && !$route.params.geojson"
-                @click="importGeoJson"
                 class="ui fluid teal icon button"
+                @click="importGeoJson"
               >
-                <i class="upload icon"></i> Lancer l'import
+                <i class="upload icon" /> Lancer l'import
               </button>
               <ImportTask
                 v-if="importFeatureTypeData && importFeatureTypeData.length"
@@ -127,10 +149,10 @@
         </div>
         <div class="ui styled accordion">
           <div
-            @click="toggleShowImport"
             :class="['title', { active: !showImport }]"
+            @click="toggleShowImport"
           >
-            <i class="dropdown icon"></i>
+            <i class="dropdown icon" />
             Exporter les signalements
           </div>
           <div :class="['content', { active: !showImport }]">
@@ -143,14 +165,16 @@
               class="ui fluid teal icon button"
               @click="exportFeatures"
             >
-              <i class="download icon"></i> Exporter
+              <i class="download icon" /> Exporter
             </button>
           </div>
         </div>
       </div>
     </div>
     <div class="nine wide column">
-      <h3 class="ui header">Derniers signalements</h3>
+      <h3 class="ui header">
+        Derniers signalements
+      </h3>
       <div
         :class="{ active: featuresLoading }"
         class="ui inverted dimmer"
@@ -161,13 +185,15 @@
       </div>
       <div
         v-if="
-          importFeatureTypeData && importFeatureTypeData.length && importFeatureTypeData.some(el => el.status === 'pending')
+          importFeatureTypeData &&
+            importFeatureTypeData.length &&
+            importFeatureTypeData.some((el) => el.status === 'pending')
         "
         class="ui message info"
       >
         <p>
-          Des signalements sont en cours d'import.
-          Pour suivre le statut de l'import, cliquez sur "Importer des Signalements".
+          Des signalements sont en cours d'import. Pour suivre le statut de
+          l'import, cliquez sur "Importer des Signalements".
         </p>
       </div>
       <div
@@ -184,20 +210,29 @@
         :key="feature.feature_id + index"
         class="ui small header"
       >
-        <span v-if="feature.status === 'archived'" data-tooltip="Archivé">
-          <i class="grey archive icon"></i>
+        <span
+          v-if="feature.status === 'archived'"
+          data-tooltip="Archivé"
+        >
+          <i class="grey archive icon" />
         </span>
         <span
           v-else-if="feature.status === 'pending'"
           data-tooltip="En attente de publication"
         >
-          <i class="teal hourglass outline icon"></i>
+          <i class="teal hourglass outline icon" />
         </span>
-        <span v-else-if="feature.status === 'published'" data-tooltip="Publié">
-          <i class="olive check icon"></i>
+        <span
+          v-else-if="feature.status === 'published'"
+          data-tooltip="Publié"
+        >
+          <i class="olive check icon" />
         </span>
-        <span v-else-if="feature.status === 'draft'" data-tooltip="Brouillon">
-          <i class="orange pencil alternate icon"></i>
+        <span
+          v-else-if="feature.status === 'draft'"
+          data-tooltip="Brouillon"
+        >
+          <i class="orange pencil alternate icon" />
         </span>
         <router-link
           :to="{
@@ -222,8 +257,7 @@
           <div>
             [ Créé le {{ feature.created_on | formatDate }}
             <span v-if="$store.state.user">
-              par {{ feature.display_creator }}</span
-            >
+              par {{ feature.display_creator }}</span>
             ]
           </div>
         </div>
@@ -233,7 +267,7 @@
         :to="{ name: 'liste-signalements', params: { slug } }"
         class="ui right labeled icon button margin-25"
       >
-        <i class="right arrow icon"></i>
+        <i class="right arrow icon" />
         Voir tous les signalements
       </router-link>
       <router-link
@@ -246,31 +280,45 @@
       >
         Ajouter un signalement
       </router-link>
-      <br />
+      <br>
     </div>
   </div>
 </template>
 
 <script>
-import { mapActions, mapMutations, mapGetters, mapState } from "vuex";
-import ImportTask from "@/components/ImportTask";
-import featureAPI from "@/services/feature-api";
+import { mapActions, mapMutations, mapGetters, mapState } from 'vuex';
+import ImportTask from '@/components/ImportTask';
+import featureAPI from '@/services/feature-api';
 
 import { fileConvertSizeToMo } from '@/assets/js/utils';
 
 export default {
-  name: "Feature_type_detail",
+  name: 'FeatureTypeDetail',
+  
   components: {
     ImportTask: ImportTask,
   },
 
-  props: ["geojson", "typename", ],
+  filters: {
+    formatDate(value) {
+      let date = new Date(value);
+      date = date.toLocaleString().replace(',', ' à');
+      return date.substr(0, date.length - 3); //* quick & dirty way to remove seconds from date
+    },
+  },
+
+  props: {
+    geojson: {
+      type: Object,
+      default: null,
+    },
+  },
 
   data() {
     return {
-      importError: "",
+      importError: '',
       fileToImport: {
-        name: "Sélectionner un fichier GeoJSON ...",
+        name: 'Sélectionner un fichier GeoJSON ...',
         size: 0,
       },
       showImport: false,
@@ -282,14 +330,6 @@ export default {
     };
   },
 
-  filters: {
-    formatDate(value) {
-      let date = new Date(value);
-      date = date.toLocaleString().replace(",", " à");
-      return date.substr(0, date.length - 3); //* quick & dirty way to remove seconds from date
-    },
-  },
-
   computed: {
     ...mapGetters([
       'permissions'
@@ -320,24 +360,23 @@ export default {
         let st = this.feature_types.find(
           (el) => el.slug === this.$route.params.feature_type_slug
         );
-        if (st)
-          return st
+        if (st) return st;
       }
       return {};
     },
 
     feature_type_features: function () {
-      if(this.features.length)
+      if (this.features.length)
         return this.features.filter(
           (el) => el.feature_type.slug === this.$route.params.feature_type_slug
         );
-      return {}
+      return {};
     },
 
     lastFeatures: function () {
       if (this.feature_type_features.length)
         return this.feature_type_features.slice(0, 5);
-      return []
+      return [];
     },
 
     orderedCustomFields() {
@@ -345,16 +384,16 @@ export default {
         return [...this.structure.customfield_set].sort(
           (a, b) => a.position - b.position
         );
-      return {}
+      return {};
     },
   },
 
-  watch:{
-    structure(newValue){
-      if (newValue.slug){
+  watch: {
+    structure(newValue) {
+      if (newValue.slug) {
         this.GET_IMPORTS({
           feature_type: this.$route.params.feature_type_slug
-        })
+        });
       }
     },
 
@@ -370,7 +409,7 @@ export default {
               setTimeout(() => {
                 this.reloadingImport = false;
               }, 1000);
-            })
+            });
           }, this.$store.state.configuration.VUE_APP_RELOAD_INTERVAL);
         } else if (oldValue && oldValue.some(el => el.status === 'pending')) {
           this.getLastFeatures();
@@ -384,56 +423,51 @@ export default {
       this.$store.dispatch('projects/GET_PROJECT', this.slug);
       this.$store.dispatch("projects/GET_PROJECT_INFO", this.slug);
     }
-    this.$store.commit("feature/SET_FEATURES", []); //* empty remaining features in case they were in geojson format and will be fetch anyway
+    this.$store.commit('feature/SET_FEATURES', []); //* empty remaining features in case they were in geojson format and will be fetch anyway
     this.getLastFeatures();
     this.SET_CURRENT_FEATURE_TYPE_SLUG(
       this.$route.params.feature_type_slug
     );
-    if (this.$route.params.type === "external-geojson") {
+    if (this.$route.params.type === 'external-geojson') {
       this.showImport = true;
     }
   },
 
   methods: {
-    ...mapMutations('feature_type', [
-      'SET_CURRENT_FEATURE_TYPE_SLUG'
-    ]),
-    ...mapActions('feature_type', [
-      'GET_IMPORTS'
-    ]),
-    ...mapActions('feature', [
-      'GET_PROJECT_FEATURES'
-    ]),
+    ...mapMutations('feature_type', ['SET_CURRENT_FEATURE_TYPE_SLUG']),
+    ...mapActions('feature_type', ['GET_IMPORTS']),
+    ...mapActions('feature', ['GET_PROJECT_FEATURES']),
     toggleShowImport() {
       this.showImport = !this.showImport;
       if (this.showImport) {
         this.GET_IMPORTS({
-          feature_type: this.$route.params.feature_type_slug        });
+          feature_type: this.$route.params.feature_type_slug
+        });
       }
     },
 
     transformProperties(prop) {
       const type = typeof prop;
       const date = new Date(prop);
-      if (type === "boolean") {
-        return "boolean";
+      if (type === 'boolean') {
+        return 'boolean';
       } else if (Number.isSafeInteger(prop)) {
-        return "integer";
+        return 'integer';
       } else if (
-        type === "string" &&
-        ['/', ':', '-'].some(el => prop.includes(el)) && // check for chars found in datestring
+        type === 'string' &&
+        ['/', ':', '-'].some((el) => prop.includes(el)) && // check for chars found in datestring
         date instanceof Date &&
         !isNaN(date.valueOf())
       ) {
-        return "date";
-      } else if (type === "number" && !isNaN(parseFloat(prop))) {
-        return "decimal";
+        return 'date';
+      } else if (type === 'number' && !isNaN(parseFloat(prop))) {
+        return 'decimal';
       }
-      return "char"; //* string by default, most accepted type in database
+      return 'char'; //* string by default, most accepted type in database
     },
 
     checkJsonValidity(json) {
-      this.importError = "";
+      this.importError = '';
       const fields = this.structure.customfield_set.map((el) => {
         return {
           name: el.name,
@@ -449,7 +483,7 @@ export default {
             //* if custom field value is not null, then check validity of field
             if (fieldInFeature !== null) {
               //* if field type is list, it's not possible to guess from value type
-              if (field_type === "list") {
+              if (field_type === 'list') {
                 //*then check if the value is an available option
                 if (!options.includes(fieldInFeature)) {
                   return false;
@@ -475,7 +509,7 @@ export default {
       }
 
       let reader = new FileReader();
-      reader.addEventListener("load", (e) => {
+      reader.addEventListener('load', (e) => {
         // bypass json check for files larger then 10 Mo
         let jsonValidity;
         if (parseFloat(fileConvertSizeToMo(files[0])) <= 10) {
@@ -487,7 +521,7 @@ export default {
         if (jsonValidity) {
           this.fileToImport = files[0]; // todo : remove this value from state as it stored (first attempt didn't work)
           this.$store.commit(
-            "feature_type/SET_FILE_TO_IMPORT",
+            'feature_type/SET_FILE_TO_IMPORT',
             this.fileToImport
           );
         }
@@ -503,12 +537,12 @@ export default {
           feature_type_slug: this.$route.params.feature_type_slug,
         }
       if (this.$route.params.geojson) {
-        payload["geojson"] = this.$route.params.geojson
+        payload['geojson'] = this.$route.params.geojson;
       } else if (this.fileToImport && !this.fileToImport.name) {
-        payload["fileToImport"] = this.fileToImport;
+        payload['fileToImport'] = this.fileToImport;
       } else {
-        this.importError = "La ressource n'a pas pu être récupéré."
-        return
+        this.importError = "La ressource n'a pas pu être récupéré.";
+        return;
       }
       this.$store.dispatch('feature_type/SEND_FEATURES_FROM_GEOJSON', payload)
         .then(() => {
@@ -520,7 +554,7 @@ export default {
       const url = `${this.$store.state.configuration.VUE_APP_DJANGO_API_BASE}projects/${this.slug}/feature-type/${this.$route.params.feature_type_slug}/export/`;
       featureAPI.getFeaturesBlob(url).then((blob) => {
         if (blob) {
-          const link = document.createElement("a");
+          const link = document.createElement('a');
           link.href = URL.createObjectURL(blob);
           link.download = `${this.project.title}-${this.structure.title}.json`;
           link.click();
@@ -537,11 +571,11 @@ export default {
           limit: '5'
         });
 
-      if (response){
+      if (response) {
         this.featuresLoading = false;
       }
-    }
-  }
+    },
+  },
 };
 </script>
 
diff --git a/src/views/feature_type/Feature_type_edit.vue b/src/views/feature_type/Feature_type_edit.vue
index 807bf488b6ccce22aa3b92ac7adb04aa9c37c049..82a12b5435cd4e096175963639acd63d7057bfc9 100644
--- a/src/views/feature_type/Feature_type_edit.vue
+++ b/src/views/feature_type/Feature_type_edit.vue
@@ -1,8 +1,14 @@
 <template>
   <div v-frag>
-    <div id="message" class="fullwidth">
-      <div v-if="error" class="ui negative message">
-        <p><i class="cross icon"></i> {{ error }}</p>
+    <div
+      id="message"
+      class="fullwidth"
+    >
+      <div
+        v-if="error"
+        class="ui negative message"
+      >
+        <p><i class="cross icon" /> {{ error }}</p>
       </div>
     </div>
     <div class="fourteen wide column">
@@ -10,7 +16,7 @@
         :class="{ active: loading }"
         class="ui inverted dimmer"
       >
-       <div class="ui loader" />
+        <div class="ui loader" />
       </div>
       <form
         v-if="project"
@@ -37,17 +43,23 @@
           <div class="required field">
             <label :for="form.title.id_for_label">{{ form.title.label }}</label>
             <input
+              :id="form.title.id_for_label"
+              v-model="form.title.value"
               type="text"
               required
               :maxlength="form.title.field.max_length"
               :name="form.title.html_name"
-              :id="form.title.id_for_label"
-              v-model="form.title.value"
               @blur="updateStore"
-            />
-            <ul id="errorlist" class="errorlist">
-              <li v-for="error in form.title.errors" :key="error">
-                {{ error }}
+            >
+            <ul
+              id="errorlist"
+              class="errorlist"
+            >
+              <li
+                v-for="err in form.title.errors"
+                :key="err"
+              >
+                {{ err }}
               </li>
             </ul>
           </div>
@@ -61,32 +73,33 @@
               :selected="selectedGeomType"
               :selection.sync="selectedGeomType"
             />
-            <!-- {{ form.geom_type.errors }} -->
           </div>
 
-          <div v-if="selectedGeomType !== 'Point'" class="required field">
+          <div
+            v-if="selectedGeomType !== 'Point'"
+            class="required field"
+          >
             <label :for="form.color.id_for_label">{{ form.color.label }}</label>
             <input
+              :id="form.color.id_for_label"
+              v-model="form.color.value"
               type="color"
               required
               style="width: 100%; height: 38px"
               :name="form.color.html_name"
-              :id="form.color.id_for_label"
-              v-model="form.color.value"
               @blur="updateStore"
-            />
-            <!-- {{ form.color.errors }} -->
+            >
           </div>
         </div>
         <div class="field">
           <div class="ui checkbox">
             <input
-              class="hidden"
               :id="form.title_optional.html_name"
-              :name="form.title_optional.html_name"
               v-model="form.title_optional.value"
+              class="hidden"
+              :name="form.title_optional.html_name"
               type="checkbox"
-            />
+            >
             <label :for="form.title_optional.html_name">{{ form.title_optional.label }}</label>
           </div>
         </div>
@@ -94,10 +107,13 @@
         <!--  //* s'affiche après sélection d'option de type liste dans type de champ -->
         <div
           v-if="colorsStyleList.length > 0 && selectedGeomType !== 'Point'"
-          class="custom_style"
           id="id_style_container"
+          class="custom_style"
         >
-          <div class="list_selection" id="id_list_selection">
+          <div
+            id="id_list_selection"
+            class="list_selection"
+          >
             <Dropdown
               :options="colorsStyleList"
               :selected="selected_colors_style"
@@ -105,55 +121,60 @@
               :placeholder="'Sélectionner la liste de valeurs'"
             />
           </div>
-          <div class="colors_selection" id="id_colors_selection" hidden>
+          <div
+            id="id_colors_selection"
+            class="colors_selection"
+            hidden
+          >
             <div
               v-for="(value, key, index) in form.colors_style.value.colors"
               :key="'colors_style-' + index"
             >
-              <div v-if="key" class="color-input">
-                <label>{{ key }}</label
-                ><input
+              <div
+                v-if="key"
+                class="color-input"
+              >
+                <label>{{ key }}</label><input
                   :name="key"
                   type="color"
                   :value="value"
                   @input="setColorStyles"
-                />
+                >
               </div>
             </div>
           </div>
-
         </div>
 
-        <span v-if="action === 'duplicate' || action === 'edit'"> </span>
+        <span v-if="action === 'duplicate' || action === 'edit'" />
 
         <div id="formsets">
           <FeatureTypeCustomForm
             v-for="customForm in customForms"
             :key="customForm.dataKey"
-            :dataKey="customForm.dataKey"
-            :customForm="customForm"
-            :selectedColorStyle="form.colors_style.value.custom_field_name"
-            v-on:update="updateColorsStyle($event)"
             ref="customForms"
+            :data-key="customForm.dataKey"
+            :custom-form="customForm"
+            :selected-color-style="form.colors_style.value.custom_field_name"
+            @update="updateColorsStyle($event)"
           />
         </div>
 
         <button
-          type="button"
-          @click="addCustomForm"
           id="add-field"
+          type="button"
           class="ui compact basic button button-hover-green"
+          @click="addCustomForm"
         >
-          <i class="ui plus icon"></i>Ajouter un champ personnalisé
+          <i class="ui plus icon" />Ajouter un champ personnalisé
         </button>
 
-        <div class="ui divider"></div>
+        <div class="ui divider" />
         <button
           class="ui teal icon button margin-25"
           type="button"
           @click="sendFeatureType"
         >
-          <i class="white save icon"></i>
+          <i class="white save icon" />
           {{ action === "create" ? "Créer" : "Sauvegarder" }} le type de
           signalement
         </button>
@@ -163,7 +184,7 @@
           type="button"
           @click="postFeatureTypeThenFeatures"
         >
-          <i class="white save icon"></i>
+          <i class="white save icon" />
           Créer et importer le(s) signalement(s) du geojson
         </button>
       </form>
@@ -172,13 +193,13 @@
 </template>
 
 <script>
-import frag from "vue-frag";
-import { mapGetters, mapState } from "vuex";
-import Dropdown from "@/components/Dropdown.vue";
-import FeatureTypeCustomForm from "@/components/feature_type/FeatureTypeCustomForm.vue";
+import frag from 'vue-frag';
+import { mapGetters, mapState } from 'vuex';
+import Dropdown from '@/components/Dropdown.vue';
+import FeatureTypeCustomForm from '@/components/feature_type/FeatureTypeCustomForm.vue';
 
 export default {
-  name: "Feature_type_edit",
+  name: 'FeatureTypeEdit',
 
   directives: {
     frag,
@@ -189,78 +210,83 @@ export default {
     FeatureTypeCustomForm,
   },
 
-  props: ["geojson", "typename", ],
+  props: {
+    geojson: {
+      type: Object,
+      default: null,
+    },
+  },
 
   data() {
     return {
       loading: false,
-      action: "create",
+      action: 'create',
       dataKey: 0,
       error: null,
       geomTypeChoices: [
-        { value: "linestring", name: "Ligne" },
-        { value: "point", name: "Point" },
-        { value: "polygon", name: "Polygone" },
+        { value: 'linestring', name: 'Ligne' },
+        { value: 'point', name: 'Point' },
+        { value: 'polygon', name: 'Polygone' },
       ],
       form: {
         colors_style: {
           fields: [],
           value: {
             colors: {},
-            custom_field_name: "",
+            custom_field_name: '',
           },
         },
         color: {
-          id_for_label: "couleur",
-          label: "Couleur",
+          id_for_label: 'couleur',
+          label: 'Couleur',
           field: {
             max_length: 128, // ! Vérifier la valeur dans django
           },
-          html_name: "couleur",
-          value: "#000000",
+          html_name: 'couleur',
+          value: '#000000',
         },
         title: {
           errors: [],
-          id_for_label: "title",
-          label: "Titre",
+          id_for_label: 'title',
+          label: 'Titre',
           field: {
             max_length: 128, // ! Vérifier la valeur dans django
           },
-          html_name: "title",
+          html_name: 'title',
           value: null,
         },
         title_optional: {
           errors: null,
-          id_for_label: "title_optional",
-          html_name: "title_optional",
-          label: "Titre du signalement optionnel",
+          id_for_label: 'title_optional',
+          html_name: 'title_optional',
+          label: 'Titre du signalement optionnel',
           value: false,
         },
         geom_type: {
-          id_for_label: "geom_type",
-          label: "Type de géométrie",
+          id_for_label: 'geom_type',
+          label: 'Type de géométrie',
           field: {
             max_length: 128, // ! Vérifier la valeur dans django
           },
-          html_name: "geom_type",
-          value: "point",
+          html_name: 'geom_type',
+          value: 'point',
         },
       },
       slug: this.$route.params.slug,
       reservedKeywords: [
         // todo : add keywords for mapstyle (strokewidth...)
-        "title",
-        "description",
-        "status",
-        "created_on",
-        "updated_on",
-        "archived_on",
-        "deletion_on",
-        "feature_type",
-        "display_creator",
-        "display_last_editor",
-        "project",
-        "creator",
+        'title',
+        'description',
+        'status',
+        'created_on',
+        'updated_on',
+        'archived_on',
+        'deletion_on',
+        'feature_type',
+        'display_creator',
+        'display_last_editor',
+        'project',
+        'creator',
       ],
     };
   },
@@ -305,7 +331,7 @@ export default {
           } else {
             const newColorsStyle = {
               colors: newValue.options.reduce((obj, key) => {
-                obj[key] = "#000000";
+                obj[key] = '#000000';
                 return obj;
               }, {}),
             };
@@ -333,25 +359,73 @@ export default {
           //* if the customForm corresponding doesn't exist reset colors_style values
           this.form.colors_style.value = {
             colors: {},
-            custom_field_name: "",
+            custom_field_name: '',
           };
         }
       }
     },
   },
 
+  created() {
+    if (!this.project) {
+      this.$store.dispatch('projects/GET_PROJECT', this.$route.params.slug);
+      this.$store.dispatch('projects/GET_PROJECT_INFO', this.$route.params.slug);
+    }
+    this.$store.commit(
+      'feature_type/SET_CURRENT_FEATURE_TYPE_SLUG',
+      this.$route.params.slug_type_signal
+    );
+
+    this.definePageType();
+  },
+
+  mounted() {
+    if (this.action === 'edit' || this.action === 'duplicate') {
+      if (this.feature_type) {
+        //* add datas from store to state to avoid mutating directly store with v-model (not good practice), could have used computed with getter and setter as well
+        this.fillFormData(this.feature_type);
+      }
+      if (this.action === 'duplicate') {
+        //* replace original name with new default title
+        this.form.title.value += ` (Copie-${new Date()
+          .toLocaleString()
+          .slice(0, -3)
+          .replace(',', '')})`;
+        this.updateStore(); // * initialize form in store in case this.form would not be modified
+      }
+    }
+    //* when creation from a geojson
+    if (this.geojson) {
+      this.importGeoJsonFeatureType();
+      if (this.fileToImport && this.fileToImport.name) {
+        this.form.title.value = // * use the filename as title by default
+          this.fileToImport.name.split('.')[0];
+      } else { //* case when the geojson comes from datasud catalog
+        this.form.title.value = this.geojson.name;// * use the typename as title by default
+      }
+    }
+  },
+  beforeDestroy() {
+    this.$store.commit('feature_type/EMPTY_FORM');
+    this.$store.commit('feature_type/EMPTY_CUSTOM_FORMS');
+    this.$store.commit(
+      'feature_type/SET_FILE_TO_IMPORT',
+      null
+    );
+  },
+
   methods: {
     definePageType() {
-      if (this.$router.history.current.name === "ajouter-type-signalement") {
-        this.action = "create";
+      if (this.$router.history.current.name === 'ajouter-type-signalement') {
+        this.action = 'create';
       } else if (
-        this.$router.history.current.name === "editer-type-signalement"
+        this.$router.history.current.name === 'editer-type-signalement'
       ) {
-        this.action = "edit";
+        this.action = 'edit';
       } else if (
-        this.$router.history.current.name === "dupliquer-type-signalement"
+        this.$router.history.current.name === 'dupliquer-type-signalement'
       ) {
-        this.action = "duplicate";
+        this.action = 'duplicate';
       }
     },
 
@@ -371,7 +445,7 @@ export default {
         //* if adding an existing customForm -> add its property to newCustomForm containing only dataKey
         newCustomForm = { ...newCustomForm, ...customForm };
       }
-      this.$store.commit("feature_type/ADD_CUSTOM_FORM", newCustomForm); // * create an object with the counter in store
+      this.$store.commit('feature_type/ADD_CUSTOM_FORM', newCustomForm); // * create an object with the counter in store
     },
 
     fillFormData(formData) {
@@ -396,7 +470,7 @@ export default {
         for (const key of newOptions) {
           if (key && !optionNames.includes(key)) {
             //* check if key is not en empty string
-            this.form.colors_style.value.colors[key] = "#000000"; //* add new entry
+            this.form.colors_style.value.colors[key] = '#000000'; //* add new entry
           }
         }
         //* if modified or deleted
@@ -414,7 +488,7 @@ export default {
     },
 
     updateStore() {
-      this.$store.commit("feature_type/UPDATE_FORM", {
+      this.$store.commit('feature_type/UPDATE_FORM', {
         color: this.form.color,
         title: this.form.title,
         title_optional: this.form.title_optional,
@@ -439,19 +513,19 @@ export default {
         this.form.title.errors = [];
         return this.checkCustomForms(); //* if customForms are ok, validate, if get out function
       } else if (
-        !this.form.title.errors.includes("Veuillez compléter ce champ.")
+        !this.form.title.errors.includes('Veuillez compléter ce champ.')
       ) {
-        this.form.title.errors.push("Veuillez compléter ce champ.");
+        this.form.title.errors.push('Veuillez compléter ce champ.');
         document
-          .getElementById("errorlist")
-          .scrollIntoView({ block: "end", inline: "nearest" });
+          .getElementById('errorlist')
+          .scrollIntoView({ block: 'end', inline: 'nearest' });
       }
       return false;
     },
 
     goBackToProject(message) {
       this.$router.push({
-        name: "project_detail",
+        name: 'project_detail',
         params: {
           slug: this.slug,
           message,
@@ -461,15 +535,15 @@ export default {
 
     sendFeatureType() {
       // * si édition d'une feature_type déja existante, faire un put
-      const requestType = this.action === "edit" ? "put" : "post";
+      const requestType = this.action === 'edit' ? 'put' : 'post';
       if (this.checkForms()) {
         this.$store
-          .dispatch("feature_type/SEND_FEATURE_TYPE", requestType)
+          .dispatch('feature_type/SEND_FEATURE_TYPE', requestType)
           .then(({ status }) => {
             if (status === 200) {
-              this.goBackToProject("Le type de signalement a été mis à jour");
+              this.goBackToProject('Le type de signalement a été mis à jour');
             } else if (status === 201) {
-              this.goBackToProject("Le nouveau type de signalement a été créé");
+              this.goBackToProject('Le nouveau type de signalement a été créé');
             } else {
               this.displayMessage(
                 "Une erreur est survenue lors de l'import du type de signalement"
@@ -503,65 +577,65 @@ export default {
     },
 
     async postFeatureTypeThenFeatures() {
-      const requestType = this.action === "edit" ? "put" : "post";
+      const requestType = this.action === 'edit' ? 'put' : 'post';
       if (this.checkForms()) {
         this.loading = true;
         await this.$store
-          .dispatch("feature_type/SEND_FEATURE_TYPE", requestType)
-            .then(({ feature_type_slug }) => {
-              if (feature_type_slug) {
-                this.postFeatures(feature_type_slug);
-              } else {
-                this.loading = false;
-              }
-            })
-            .catch(() => {
+          .dispatch('feature_type/SEND_FEATURE_TYPE', requestType)
+          .then(({ feature_type_slug }) => {
+            if (feature_type_slug) {
+              this.postFeatures(feature_type_slug);
+            } else {
               this.loading = false;
-            });
+            }
+          })
+          .catch(() => {
+            this.loading = false;
+          });
       }
     },
 
     displayMessage(message) {
       this.error = message;
       document
-        .getElementById("message")
-        .scrollIntoView({ block: "end", inline: "nearest" });
+        .getElementById('message')
+        .scrollIntoView({ block: 'end', inline: 'nearest' });
     },
 
     // ****** Methodes for geojson import ****** //
     toNewFeatureType() {
       this.$router.push({
-        name: "ajouter-type-signalement",
+        name: 'ajouter-type-signalement',
         params: { geojson: this.jsonDict },
       });
     },
 
     translateLabel(value) {
-      if (value === "LineString") {
-        return "linestring";
-      } else if (value === "Polygon" || value === "MultiPolygon") {
-        return "polygon";
+      if (value === 'LineString') {
+        return 'linestring';
+      } else if (value === 'Polygon' || value === 'MultiPolygon') {
+        return 'polygon';
       }
-      return "point";
+      return 'point';
     },
 
     transformProperties(prop) {
       const type = typeof prop;
       const date = new Date(prop);
-      if (type === "boolean") {
-        return "boolean";
+      if (type === 'boolean') {
+        return 'boolean';
       } else if (Number.isSafeInteger(prop)) {
-        return "integer";
+        return 'integer';
       } else if (
-        type === "string" &&
+        type === 'string' &&
         date instanceof Date &&
         !isNaN(date.valueOf())
       ) {
-        return "date";
-      } else if (type === "number" && !isNaN(parseFloat(prop))) {
-        return "decimal";
+        return 'date';
+      } else if (type === 'number' && !isNaN(parseFloat(prop))) {
+        return 'decimal';
       }
-      return "char"; //* string by default, most accepted type in database
+      return 'char'; //* string by default, most accepted type in database
     },
 
     importGeoJsonFeatureType() {
@@ -578,8 +652,8 @@ export default {
           // todo: add map style keywords
           if (!this.reservedKeywords.includes(key)) {
             const customForm = {
-              label: { value: key || "" },
-              name: { value: key || "" },
+              label: { value: key || '' },
+              name: { value: key || '' },
               position: this.dataKey, // * use dataKey already incremented by addCustomForm
               field_type: { value: this.transformProperties(val) }, // * guessed from the type
               options: { value: [] }, // * not available in export
@@ -590,55 +664,6 @@ export default {
       }
     },
   },
-
-  created() {
-    if (!this.project) {
-      this.$store.dispatch('projects/GET_PROJECT', this.slug);
-      this.$store.dispatch("GET_PROJECT_INFO", this.slug);
-      //this.$store.dispatch('feature_type/GET_PROJECT_FEATURE_TYPES', this.$route.params.slug);
-    }
-    this.$store.commit(
-      "feature_type/SET_CURRENT_FEATURE_TYPE_SLUG",
-      this.$route.params.slug_type_signal
-    );
-
-    this.definePageType();
-  },
-
-  mounted() {
-    if (this.action === "edit" || this.action === "duplicate") {
-      if (this.feature_type) {
-        //* add datas from store to state to avoid mutating directly store with v-model (not good practice), could have used computed with getter and setter as well
-        this.fillFormData(this.feature_type);
-      }
-      if (this.action === "duplicate") {
-        //* replace original name with new default title
-        this.form.title.value += ` (Copie-${new Date()
-          .toLocaleString()
-          .slice(0, -3)
-          .replace(",", "")})`;
-        this.updateStore(); // * initialize form in store in case this.form would not be modified
-      }
-    }
-    //* when creation from a geojson
-    if (this.geojson) {
-      this.importGeoJsonFeatureType();
-      if (this.fileToImport && this.fileToImport.name) {
-        this.form.title.value = // * use the filename as title by default
-          this.fileToImport.name.split(".")[0];
-      } else { //* case when the geojson comes from datasud catalog
-        this.form.title.value = this.geojson.name;// * use the typename as title by default
-      }
-    }
-  },
-  beforeDestroy() {
-    this.$store.commit("feature_type/EMPTY_FORM");
-    this.$store.commit("feature_type/EMPTY_CUSTOM_FORMS");
-    this.$store.commit(
-      "feature_type/SET_FILE_TO_IMPORT",
-      null
-    );
-  },
 };
 </script>
 
diff --git a/src/views/feature_type/Feature_type_symbology.vue b/src/views/feature_type/Feature_type_symbology.vue
index 6baac62261e7ecb6a52ee4a6d6a9f46edbe2891f..ca88dcd6dfd1e729cbc0f3a63b3824c2592cbfd0 100644
--- a/src/views/feature_type/Feature_type_symbology.vue
+++ b/src/views/feature_type/Feature_type_symbology.vue
@@ -1,13 +1,25 @@
 <template>
   <div>
-    <div :class="{ active: loading }" class="ui inverted dimmer">
+    <div
+      :class="{ active: loading }"
+      class="ui inverted dimmer"
+    >
       <div class="ui loader" />
     </div>
-    <div id="message" class="fullwidth">
-      <div v-if="error" class="ui negative message">
-        <p><i class="close icon"></i> {{ error }}</p>
+    <div
+      id="message"
+      class="fullwidth"
+    >
+      <div
+        v-if="error"
+        class="ui negative message"
+      >
+        <p><i class="close icon" /> {{ error }}</p>
       </div>
-      <div v-if="success" class="ui positive message">
+      <div
+        v-if="success"
+        class="ui positive message"
+      >
         <i
           class="close icon"
           @click="success = null"
@@ -29,36 +41,37 @@
         </h1>
         <SymbologySelector
           v-if="feature_type"
-          :initColor="feature_type.color"
-          :initIcon="feature_type.icon"
-          :geomType="feature_type.geom_type"
+          :init-color="feature_type.color"
+          :init-icon="feature_type.icon"
+          :geom-type="feature_type.geom_type"
           @set="setDefaultStyle"
         />
         <div
           v-if="
             feature_type &&
-            feature_type.customfield_set.length > 0 &&
-            feature_type.customfield_set.some(el => el.field_type === 'list')
+              feature_type.customfield_set.length > 0 &&
+              feature_type.customfield_set.some(el => el.field_type === 'list')
           "
         >
           <div class="ui divider" />
           <label
+            id="customfield-select-label"
             for="customfield-select"
-            id="customfield-select-label">
+          >
             Personnaliser la symbologie d'une liste de valeurs:
           </label>
           <select
-            v-model="selectedCustomfield"
             id="customfield-select"
+            v-model="selectedCustomfield"
             class="ui dropdown"
           >
-             <option
+            <option
               v-for="customfieldList of feature_type.customfield_set.filter(el => el.field_type === 'list')"
               :key="customfieldList.name"
               :value="customfieldList.name"
             >
-               {{ customfieldList.label }}
-              </option>
+              {{ customfieldList.label }}
+            </option>
           </select>
         </div>
         <div v-if="selectedCustomfield">
@@ -68,30 +81,30 @@
           >
             <SymbologySelector
               :title="option"
-              :initColor="feature_type.colors_style.value ?
+              :init-color="feature_type.colors_style.value ?
                 feature_type.colors_style.value.colors[option] ?
                   feature_type.colors_style.value.colors[option].value :
                   feature_type.colors_style.value.colors[option]
                 : null
               "
-              :initIcon="feature_type.colors_style.value ?
+              :init-icon="feature_type.colors_style.value ?
                 feature_type.colors_style.value.icons[option] :
                 null
               "
-              :geomType="feature_type.customfield_set.geomType"
+              :geom-type="feature_type.customfield_set.geomType"
               @set="setColorsStyle"
             />
           </div>
         </div>
-        <div class="ui divider"></div>
+        <div class="ui divider" />
         <button
           class="ui teal icon button margin-25"
           type="button"
           :disabled="!canSaveSymbology"
           @click="sendFeatureSymbology"
         >
-          <i class="white save icon"></i>
-            Sauvegarder la symbologie du type de signalement
+          <i class="white save icon" />
+          Sauvegarder la symbologie du type de signalement
         </button>
       </form>
     </div>
@@ -138,11 +151,11 @@ export default {
         },
       },
       canSaveSymbology: false
-    }
+    };
   },
 
   computed: {
-    ...mapGetters([
+    ...mapGetters('projects', [
       'project'
     ]),
     ...mapState('feature_type', [
@@ -226,7 +239,9 @@ export default {
       };
       if (this.feature_type.colors_style && Object.keys(this.feature_type.colors_style.colors).length > 0) {
         this.selectedCustomfield =
-          this.feature_type.customfield_set.find(el => el.name === this.feature_type.colors_style.custom_field_name).name;
+          this.feature_type.customfield_set.find(
+            el => el.name === this.feature_type.colors_style.custom_field_name
+          ).name;
       }
     },
 
@@ -259,12 +274,12 @@ export default {
                   params: {
                     slug: this.$store.state.project_slug,
                   },
-                })
+                });
               }, 1500);
             })
             .catch((err) => {
               console.error(err);
-            })
+            });
         })
         .catch((err) => {
           console.error(err);
@@ -272,7 +287,7 @@ export default {
         });
     }
   }
-}
+};
 </script>
 
 <style lang="less" scoped>
diff --git a/src/views/flatpages/Default.vue b/src/views/flatpages/Default.vue
index 9c8443814c424080936686fbc796b77fc955070d..e095712207ca4c80eed6491ed7ba3c2e3b453cf8 100644
--- a/src/views/flatpages/Default.vue
+++ b/src/views/flatpages/Default.vue
@@ -1,20 +1,25 @@
 <template>
-  <div v-if="flatpage" class="row">
+  <div
+    v-if="flatpage"
+    class="row"
+  >
     <div class="ten wide column">
       <h1>{{ flatpage.title }}</h1>
-      <div v-html="flatpage.content"></div>
+      <!-- eslint-disable vue/no-v-html -->
+      <div v-html="flatpage.content" />
+      <!--eslint-enable-->
     </div>
   </div>
 </template>
 
 <script>
-import { mapState } from "vuex";
+import { mapState } from 'vuex';
 
 export default {
-  name: "Default",
+  name: 'Default',
 
   computed: {
-    ...mapState(["staticPages"]),
+    ...mapState(['staticPages']),
     flatpage() {
       if (this.staticPages) {
         return this.staticPages.find(
diff --git a/src/views/flatpages/with_right_menu.vue b/src/views/flatpages/with_right_menu.vue
index c04a20b34a1990deba6f54b482f0eb40f0ec27c7..46a5ff9bccf2f6e18d4fcb81c189be7da932c87c 100644
--- a/src/views/flatpages/with_right_menu.vue
+++ b/src/views/flatpages/with_right_menu.vue
@@ -2,19 +2,27 @@
   <div class="row">
     <div class="ten wide column">
       <h1>{{ flatpage.title }}</h1>
-      <div v-html="flatpage.content"></div>
-
+      <!-- eslint-disable vue/no-v-html -->
+      <div v-html="flatpage.content" />
+      <!--eslint-enable-->
       <div class="ui right rail">
-        <div id="toc-container" class="ui sticky fixed">
-          <h4 class="ui header">Table des matières</h4>
-          <div id="page-toc" class="ui vertical large text menu">
+        <div
+          id="toc-container"
+          class="ui sticky fixed"
+        >
+          <h4 class="ui header">
+            Table des matières
+          </h4>
+          <div
+            id="page-toc"
+            class="ui vertical large text menu"
+          >
             <a
               v-for="h2 in sections"
               :key="h2.id"
               class="item"
               :href="'#' + h2.id"
-              >{{ h2.text }}</a
-            >
+            >{{ h2.text }}</a>
           </div>
         </div>
       </div>
@@ -23,10 +31,10 @@
 </template>
 
 <script>
-import { mapState } from "vuex";
+import { mapState } from 'vuex';
 
 export default {
-  name: "With_right_menu",
+  name: 'WithRightMenu',
 
   data() {
     return {
@@ -35,7 +43,7 @@ export default {
   },
 
   computed: {
-    ...mapState(["staticPages"]),
+    ...mapState(['staticPages']),
     flatpage() {
       if (this.staticPages) {
         return this.staticPages.find(
@@ -45,11 +53,17 @@ export default {
       return null;
     },
   },
+  mounted() {
+    this.$nextTick(() => {
+      // The whole view is rendered, so we can safely access or query the DOM.
+      this.createMenu();
+    });
+  },
 
   methods: {
     createMenu() {
       // parse the ToC content (looking for h2 elements)
-      let list = document.querySelectorAll("h2");
+      let list = document.querySelectorAll('h2');
       let tocArr = [];
 
       for (let i = 0; i < list.length; i++) {
@@ -57,8 +71,8 @@ export default {
         let id = e.id;
 
         // add id in html if not present
-        if (id === "") {
-          id = "toc-id-" + i;
+        if (id === '') {
+          id = 'toc-id-' + i;
           e.id = id;
         }
 
@@ -70,11 +84,5 @@ export default {
       this.sections = tocArr;
     },
   },
-  mounted() {
-    this.$nextTick(() => {
-      // The whole view is rendered, so we can safely access or query the DOM.
-      this.createMenu();
-    });
-  },
 };
 </script>
diff --git a/src/views/project/Project_detail.vue b/src/views/project/Project_detail.vue
index 58e03b5ccaaf976848130695a1ee079f97e1d2f2..8c1fcdb06d17dbfc4209c2b1bb069c16642b5ef7 100644
--- a/src/views/project/Project_detail.vue
+++ b/src/views/project/Project_detail.vue
@@ -1,19 +1,31 @@
 <template>
   <div v-frag>
-    <div v-frag v-if="permissions && permissions.can_view_project && project">
-      <div id="message" class="fullwidth">
-        <div v-if="tempMessage" class="ui positive message">
-          <p><i class="check icon"></i> {{ tempMessage }}</p>
+    <div
+      v-if="permissions && permissions.can_view_project && project"
+      v-frag
+    >
+      <div
+        id="message"
+        class="fullwidth"
+      >
+        <div
+          v-if="tempMessage"
+          class="ui positive message"
+        >
+          <p><i class="check icon" /> {{ tempMessage }}</p>
         </div>
       </div>
-      <div id="message_info" class="fullwidth">
+      <div
+        id="message_info"
+        class="fullwidth"
+      >
         <div
           v-if="infoMessage"
           class="ui info message"
           style="text-align: left"
         >
           <div class="header">
-            <i class="info circle icon"></i> Informations
+            <i class="info circle icon" /> Informations
           </div>
           <ul class="list">
             {{
@@ -32,25 +44,35 @@
                 ? require('@/assets/img/default.png')
                 : DJANGO_BASE_URL + project.thumbnail + refreshId()
             "
-          />
-          <div class="ui hidden divider"></div>
-          <div class="ui basic teal label" data-tooltip="Membres">
-            <i class="user icon"></i>{{ project.nb_contributors }}
+          >
+          <div class="ui hidden divider" />
+          <div
+            class="ui basic teal label"
+            data-tooltip="Membres"
+          >
+            <i class="user icon" />{{ project.nb_contributors }}
           </div>
-          <div class="ui basic teal label" data-tooltip="Signalements publiés">
-            <i class="map marker icon"></i>{{ project.nb_published_features }}
+          <div
+            class="ui basic teal label"
+            data-tooltip="Signalements publiés"
+          >
+            <i class="map marker icon" />{{ project.nb_published_features }}
           </div>
-          <div class="ui basic teal label" data-tooltip="Commentaires">
-            <i class="comment icon"></i
-            >{{ project.nb_published_features_comments }}
+          <div
+            class="ui basic teal label"
+            data-tooltip="Commentaires"
+          >
+            <i class="comment icon" />{{
+              project.nb_published_features_comments
+            }}
           </div>
         </div>
         <div class="ten wide column important-flex space-between">
           <div>
             <h1 class="ui header">
-                {{ project.title }}
+              {{ project.title }}
             </h1>
-            <div class="ui hidden divider"></div>
+            <div class="ui hidden divider" />
             <div class="sub header">
               {{ project.description }}
             </div>
@@ -63,9 +85,9 @@
                   <a
                     v-if="
                       user &&
-                      permissions &&
-                      permissions.can_view_project &&
-                      isOffline() !== true
+                        permissions &&
+                        permissions.can_view_project &&
+                        isOffline() !== true
                     "
                     id="subscribe-button"
                     class="ui button button-hover-green"
@@ -74,13 +96,13 @@
                     data-variation="mini"
                     @click="modalType = 'subscribe'"
                   >
-                    <i class="inverted grey envelope icon"></i>
+                    <i class="inverted grey envelope icon" />
                   </a>
                   <router-link
                     v-if="
                       permissions &&
-                      permissions.can_update_project &&
-                      isOffline() !== true
+                        permissions.can_update_project &&
+                        isOffline() !== true
                     "
                     :to="{ name: 'project_edit', params: { slug: project.slug } }"
                     class="ui button button-hover-orange"
@@ -88,14 +110,14 @@
                     data-position="top center"
                     data-variation="mini"
                   >
-                    <i class="inverted grey pencil alternate icon"></i>
+                    <i class="inverted grey pencil alternate icon" />
                   </router-link>
                   <a
                     v-if="
                       user_permissions &&
-                      user_permissions[project.slug] &&
-                      user_permissions[project.slug].is_project_administrator &&
-                      isOffline() !== true
+                        user_permissions[project.slug] &&
+                        user_permissions[project.slug].is_project_administrator &&
+                        isOffline() !== true
                     "
                     id="delete-button"
                     class="ui button button-hover-red"
@@ -104,7 +126,7 @@
                     data-variation="mini"
                     @click="modalType = 'deleteProject'"
                   >
-                    <i class="inverted grey trash icon"></i>
+                    <i class="inverted grey trash icon" />
                   </a>
                 </div>
                 <button
@@ -112,7 +134,7 @@
                   class="ui teal left labeled icon button"
                   @click="copyLink"
                 >
-                  <i class="left icon share square"></i>
+                  <i class="left icon share square" />
                   Copier le lien de partage
                 </button>
               </div>
@@ -122,7 +144,10 @@
                     Le lien a été copié dans le presse-papier
                   </span>
                   &nbsp;
-                  <i class="close icon" @click="confirmMsg = ''" />
+                  <i
+                    class="close icon"
+                    @click="confirmMsg = ''"
+                  />
                 </div>
               </div>
             </div>
@@ -132,10 +157,10 @@
           {{ arraysOffline.length }} modification<span v-if="arraysOffline.length>1">s</span> en attente
           <button
             :disabled="isOffline()"
-            @click="sendOfflineFeatures()"
             class="ui fluid labeled teal icon button"
+            @click="sendOfflineFeatures()"
           >
-            <i class="upload icon"></i>
+            <i class="upload icon" />
             Envoyer au serveur
           </button>
         </div>
@@ -143,10 +168,12 @@
 
       <div class="row">
         <div class="seven wide column">
-          <h3 class="ui header">Types de signalements</h3>
+          <h3 class="ui header">
+            Types de signalements
+          </h3>
           <div class="ui middle aligned divided list">
             <div
-              :class="{ active : projectInfoLoading }"
+              :class="{ active: projectInfoLoading }"
               class="ui inverted dimmer"
             >
               <div class="ui text loader">
@@ -178,17 +205,17 @@
                     v-if="type.geom_type === 'point'"
                     class="list-image-type"
                     src="@/assets/img/marker.png"
-                  />
+                  >
                   <img
                     v-if="type.geom_type === 'linestring'"
                     class="list-image-type"
                     src="@/assets/img/line.png"
-                  />
+                  >
                   <img
                     v-if="type.geom_type === 'polygon'"
                     class="list-image-type"
                     src="@/assets/img/polygon.png"
-                  />
+                  >
                   {{ type.title }}
                 </router-link>
 
@@ -214,19 +241,19 @@
                     data-position="top right"
                     data-variation="mini"
                   >
-                    <i class="ui plus icon"></i>
+                    <i class="ui plus icon" />
                   </router-link>
                   <router-link
+                    v-if="
+                      project &&
+                        permissions &&
+                        permissions.can_create_feature_type &&
+                        isOffline() !== true
+                    "
                     :to="{
                       name: 'dupliquer-type-signalement',
                       params: { slug_type_signal: type.slug },
                     }"
-                    v-if="
-                      project &&
-                      permissions &&
-                      permissions.can_create_feature_type &&
-                      isOffline() !== true
-                    "
                     class="
                       ui
                       compact
@@ -240,7 +267,7 @@
                     data-position="top right"
                     data-variation="mini"
                   >
-                    <i class="inverted grey copy alternate icon"></i>
+                    <i class="inverted grey copy alternate icon" />
                   </router-link>
                   <div
                     v-if="isImporting(type)"
@@ -249,83 +276,86 @@
                     <i class="info circle icon" />
                     Import en cours
                   </div>
-                  <div v-else v-frag>
-                  <a
-                    v-if="
-                      user_permissions &&
-                      user_permissions[project.slug] &&
-                      user_permissions[project.slug].is_project_administrator &&
-                      isOffline() !== true
-                    "
-                    @click="toggleDeleteFeatureType(type)"
-                    class="
-                      ui
-                      compact
-                      small
-                      icon
-                      right
-                      floated
-                      button button-hover-red
-                    "
-                    data-tooltip="Supprimer le type de signalement"
-                    data-position="top center"
-                    data-variation="mini"
-                  >
-                    <i class="inverted grey trash alternate icon"></i>
-                  </a>
-                  <router-link
-                    :to="{
-                      name: 'editer-symbologie-signalement',
-                      params: { slug_type_signal: type.slug },
-                    }"
-                    v-if="
-                      project &&
-                      permissions &&
-                      permissions.can_create_feature_type &&
-                      isOffline() != true
-                    "
-                    class="
-                      ui
-                      compact
-                      small
-                      icon
-                      right
-                      floated
-                      button button-hover-orange
-                    "
-                    data-tooltip="Éditer la symbologie du type de signalement"
-                    data-position="top center"
-                    data-variation="mini"
-                  >
-                    <i class="inverted grey paint brush alternate icon"></i>
-                  </router-link>
-                  <router-link
-                    :to="{
-                      name: 'editer-type-signalement',
-                      params: { slug_type_signal: type.slug },
-                    }"
-                    v-if="
-                      project &&
-                      type.is_editable &&
-                      permissions &&
-                      permissions.can_create_feature_type &&
-                      isOffline() !== true
-                    "
-                    class="
-                      ui
-                      compact
-                      small
-                      icon
-                      right
-                      floated
-                      button button-hover-orange
-                    "
-                    data-tooltip="Éditer le type de signalement"
-                    data-position="top left"
-                    data-variation="mini"
+                  <div
+                    v-else
+                    v-frag
                   >
-                    <i class="inverted grey pencil alternate icon"></i>
-                  </router-link>
+                    <a
+                      v-if="
+                        user_permissions &&
+                          user_permissions[project.slug] &&
+                          user_permissions[project.slug].is_project_administrator &&
+                          isOffline() !== true
+                      "
+                      class="
+                        ui
+                        compact
+                        small
+                        icon
+                        right
+                        floated
+                        button button-hover-red
+                      "
+                      data-tooltip="Supprimer le type de signalement"
+                      data-position="top center"
+                      data-variation="mini"
+                      @click="toggleDeleteFeatureType(type)"
+                    >
+                      <i class="inverted grey trash alternate icon" />
+                    </a>
+                    <router-link
+                      v-if="
+                        project &&
+                          permissions &&
+                          permissions.can_create_feature_type &&
+                          isOffline() != true
+                      "
+                      :to="{
+                        name: 'editer-symbologie-signalement',
+                        params: { slug_type_signal: type.slug },
+                      }"
+                      class="
+                        ui
+                        compact
+                        small
+                        icon
+                        right
+                        floated
+                        button button-hover-orange
+                      "
+                      data-tooltip="Éditer la symbologie du type de signalement"
+                      data-position="top center"
+                      data-variation="mini"
+                    >
+                      <i class="inverted grey paint brush alternate icon" />
+                    </router-link>
+                    <router-link
+                      v-if="
+                        project &&
+                          type.is_editable &&
+                          permissions &&
+                          permissions.can_create_feature_type &&
+                          isOffline() !== true
+                      "
+                      :to="{
+                        name: 'editer-type-signalement',
+                        params: { slug_type_signal: type.slug },
+                      }"
+                      class="
+                        ui
+                        compact
+                        small
+                        icon
+                        right
+                        floated
+                        button button-hover-orange
+                      "
+                      data-tooltip="Éditer le type de signalement"
+                      data-position="top center"
+                      data-variation="mini"
+                    >
+                      <i class="inverted grey pencil alternate icon" />
+                    </router-link>
                   </div>
                 </div>
               </div>
@@ -339,8 +369,8 @@
             <router-link
               v-if="
                 permissions &&
-                permissions.can_update_project &&
-                isOffline() !== true
+                  permissions.can_update_project &&
+                  isOffline() !== true
               "
               :to="{
                 name: 'ajouter-type-signalement',
@@ -348,15 +378,15 @@
               }"
               class="ui compact basic button button-hover-green"
             >
-              <i class="ui plus icon"></i>Créer un nouveau type de signalement
+              <i class="ui plus icon" />Créer un nouveau type de signalement
             </router-link>
           </div>
           <div class="nouveau-type-signalement">
             <div
               v-if="
                 permissions &&
-                permissions.can_update_project &&
-                isOffline() !== true
+                  permissions.can_update_project &&
+                  isOffline() !== true
               "
               class="
                 ui
@@ -366,21 +396,24 @@
                 button-align-left
               "
             >
-              <i class="ui plus icon"></i>
-              <label class="ui" for="json_file">
-                <span class="label"
-                  >Créer un nouveau type de signalement à partir d'un
-                  GeoJSON</span
-                >
+              <i class="ui plus icon" />
+              <label
+                class="ui"
+                for="json_file"
+              >
+                <span
+                  class="label"
+                >Créer un nouveau type de signalement à partir d'un
+                  GeoJSON</span>
               </label>
               <input
+                id="json_file"
                 type="file"
                 accept="application/json, .json, .geojson"
                 style="display: none"
                 name="json_file"
-                id="json_file"
                 @change="onFileChange"
-              />
+              >
             </div>
           </div>
 
@@ -388,9 +421,9 @@
             <router-link
               v-if="
                 IDGO &&
-                permissions &&
-                permissions.can_update_project &&
-                isOffline() !== true
+                  permissions &&
+                  permissions.can_update_project &&
+                  isOffline() !== true
               "
               :to="{
                 name: 'catalog-import',
@@ -401,31 +434,38 @@
               }"
               class="ui compact basic button button-hover-green button-align-left"
             >
-              <i class="ui plus icon"></i>Créer un nouveau type de signalement à partir du catalogue {{ CATALOG_NAME|| 'IDGO'}}
+              <i class="ui plus icon" />
+              Créer un nouveau type de signalement à partir du catalogue {{ CATALOG_NAME|| 'IDGO' }}
             </router-link>
           </div>
 
-          <div id="button-import" v-if="fileToImport.size > 0">
+          <div
+            v-if="fileToImport.size > 0"
+            id="button-import"
+          >
             <button
               :disabled="fileToImport.size === 0"
-              @click="toNewFeatureType"
               class="ui fluid teal icon button"
+              @click="toNewFeatureType"
             >
-              <i class="upload icon"></i> Lancer l'import avec le fichier
+              <i class="upload icon" /> Lancer l'import avec le fichier
               {{ fileToImport.name }}
             </button>
           </div>
         </div>
         <div class="seven wide column">
           <div
-            :class="{ active : mapLoading }"
+            :class="{ active: mapLoading }"
             class="ui inverted dimmer"
           >
             <div class="ui text loader">
               Chargement de la carte...
             </div>
           </div>
-          <div id="map" ref="map"></div>
+          <div
+            id="map"
+            ref="map"
+          />
         </div>
       </div>
 
@@ -434,7 +474,9 @@
           <div class="ui two stackable cards">
             <div class="red card">
               <div class="content">
-                <div class="center aligned header">Derniers signalements</div>
+                <div class="center aligned header">
+                  Derniers signalements
+                </div>
                 <div class="center aligned description">
                   <div
                     :class="{ active: featuresLoading }"
@@ -457,23 +499,24 @@
                               name: 'details-signalement',
                               params: {
                                 slug: project.slug,
-                                slug_type_signal: item.properties.feature_type.slug,
+                                slug_type_signal:
+                                  item.properties.feature_type.slug,
                                 slug_signal: item.id,
                               },
                             }"
-                            >{{ item.properties.title || item.id }}</router-link
                           >
+                            {{ item.properties.title || item.id }}
+                          </router-link>
                         </div>
                         <div class="description">
                           <i>
-                            [{{ item.properties.created_on}}
-                            <span
-                              v-if="user && item.properties.creator"
-                            >
-                              , par {{
-                                item.properties.creator.full_name ?
-                                  item.properties.creator.full_name :
-                                  item.properties.creator.username
+                            [{{ item.properties.created_on }}
+                            <span v-if="user && item.properties.creator">
+                              , par
+                              {{
+                                item.properties.creator.full_name
+                                  ? item.properties.creator.full_name
+                                  : item.properties.creator.username
                               }}
                             </span>
                             ]
@@ -481,16 +524,18 @@
                         </div>
                       </div>
                     </div>
-                    <i v-if="features.length === 0"
-                      >Aucun signalement pour le moment.</i
-                    >
+                    <i
+                      v-if="features.length === 0"
+                    >Aucun signalement pour le moment.</i>
                   </div>
                 </div>
               </div>
             </div>
             <div class="orange card">
               <div class="content">
-                <div class="center aligned header">Derniers commentaires</div>
+                <div class="center aligned header">
+                  Derniers commentaires
+                </div>
                 <div class="center aligned description">
                   <div
                     :class="{ active: projectInfoLoading }"
@@ -510,23 +555,23 @@
                         <div>
                           <router-link
                             :to="getRouteUrl(item.related_feature.feature_url)"
-                            >"{{ item.comment }}"</router-link
                           >
+                            "{{ item.comment }}"
+                          </router-link>
                         </div>
                         <div class="description">
-                          <i
-                            >[ {{ item.created_on
-                            }}<span v-if="user && item.display_author"
-                              >, par {{ item.display_author }}
-                            </span>
-                            ]</i
-                          >
+                          <i>[ {{ item.created_on
+                          }}<span
+                            v-if="user && item.display_author"
+                          >, par {{ item.display_author }}
+                          </span>
+                            ]</i>
                         </div>
                       </div>
                     </div>
-                    <i v-if="!last_comments || last_comments.length === 0"
-                      >Aucun commentaire pour le moment.</i
-                    >
+                    <i
+                      v-if="!last_comments || last_comments.length === 0"
+                    >Aucun commentaire pour le moment.</i>
                   </div>
                 </div>
               </div>
@@ -538,13 +583,17 @@
       <div class="row">
         <div class="fourteen wide column">
           <div class="ui grey segment">
-            <h3 class="ui header">Paramètres du projet</h3>
+            <h3 class="ui header">
+              Paramètres du projet
+            </h3>
             <div class="ui five stackable cards">
               <div class="card">
                 <div class="center aligned content">
                   <h4 class="ui center aligned icon header">
-                    <i class="disabled grey archive icon"></i>
-                    <div class="content">Délai avant archivage automatique</div>
+                    <i class="disabled grey archive icon" />
+                    <div class="content">
+                      Délai avant archivage automatique
+                    </div>
                   </h4>
                 </div>
                 <div class="center aligned extra content">
@@ -554,7 +603,7 @@
               <div class="card">
                 <div class="content">
                   <h4 class="ui center aligned icon header">
-                    <i class="disabled grey trash alternate icon"></i>
+                    <i class="disabled grey trash alternate icon" />
                     <div class="content">
                       Délai avant suppression automatique
                     </div>
@@ -567,7 +616,7 @@
               <div class="card">
                 <div class="content">
                   <h4 class="ui center aligned icon header">
-                    <i class="disabled grey eye icon"></i>
+                    <i class="disabled grey eye icon" />
                     <div class="content">
                       Visibilité des signalements publiés
                     </div>
@@ -580,7 +629,7 @@
               <div class="card">
                 <div class="content">
                   <h4 class="ui center aligned icon header">
-                    <i class="disabled grey eye icon"></i>
+                    <i class="disabled grey eye icon" />
                     <div class="content">
                       Visibilité des signalements archivés
                     </div>
@@ -593,8 +642,10 @@
               <div class="card">
                 <div class="content">
                   <h4 class="ui center aligned icon header">
-                    <i class="disabled grey cogs icon"></i>
-                    <div class="content">Modération</div>
+                    <i class="disabled grey cogs icon" />
+                    <div class="content">
+                      Modération
+                    </div>
                   </h4>
                 </div>
                 <div class="center aligned extra content">
@@ -607,11 +658,9 @@
       </div>
     </div>
     <span v-else>
-      <i class="icon exclamation triangle"></i>
-      <span
-        >Vous ne disposez pas des droits nécessaires pour consulter ce
-        projet.</span
-      >
+      <i class="icon exclamation triangle" />
+      <span>Vous ne disposez pas des droits nécessaires pour consulter ce
+        projet.</span>
     </span>
 
     <div
@@ -625,9 +674,12 @@
           { 'transition visible active': modalType },
         ]"
       >
-        <i @click="modalType = false" class="close icon"></i>
+        <i
+          class="close icon"
+          @click="modalType = false"
+        />
         <div class="ui icon header">
-          <i :class="[modalType === 'subscribe' ? 'envelope' : 'trash', 'icon']"></i>
+          <i :class="[modalType === 'subscribe' ? 'envelope' : 'trash', 'icon']" />
           {{
             modalType === 'subscribe' ? 'Notifications' : 'Suppression'
           }} du {{
@@ -635,34 +687,37 @@
           }}
         </div>
         <div class="content">
-          <div  v-if="modalType !== 'subscribe'" >
-
-          <p class="centered-text">
-            Confirmez vous la suppression du {{ modalType === 'deleteProject' ? 'projet, ainsi que les types de signalements' : 'type de signalement'}} et tous les signalements associés&nbsp;?
-          </p>
-          <p class="centered-text alert">
-            Attention cette action est irreversible !
-          </p>
+          <div v-if="modalType !== 'subscribe'">
+            <p class="centered-text">
+              Confirmez vous la suppression du {{
+                modalType === 'deleteProject' ?
+                  'projet, ainsi que les types de signalements' :
+                  'type de signalement'
+              }} et tous les signalements associés&nbsp;?
+            </p>
+            <p class="centered-text alert">
+              Attention cette action est irreversible !
+            </p>
           </div>
           <button
-            @click="handleModalClick"
             :class="['ui compact fluid button', modalType === 'subscribe' && !is_suscriber ? 'green' : 'red']"
+            @click="handleModalClick"
           >
-          <span v-if="modalType === 'subscribe'">
-            {{
-              is_suscriber
-                ? "Se désabonner de ce projet"
-                : "S'abonner à ce projet"
-            }}
-          </span>
-          <span v-else>
-            Supprimer le 
-            {{
-              modalType === 'deleteProject'
-              ? 'projet'
-              : 'type de signalement'
-            }}
-          </span>
+            <span v-if="modalType === 'subscribe'">
+              {{
+                is_suscriber
+                  ? "Se désabonner de ce projet"
+                  : "S'abonner à ce projet"
+              }}
+            </span>
+            <span v-else>
+              Supprimer le 
+              {{
+                modalType === 'deleteProject'
+                  ? 'projet'
+                  : 'type de signalement'
+              }}
+            </span>
           </button>
         </div>
       </div>
@@ -681,8 +736,8 @@
         </div>
         <div class="content">
           <p>
-            Impossible de créer un type de signalement à partir d'un fichier GeoJSON 
-            de plus de 10Mo (celui importé fait {{ fileSize }} Mo).
+            Impossible de créer un type de signalement à partir d'un fichier
+            GeoJSON de plus de 10Mo (celui importé fait {{ fileSize }} Mo).
           </p>
         </div>
         <div class="actions">
@@ -699,21 +754,19 @@
 </template>
 
 <script>
-import frag from "vue-frag";
-import { mapUtil } from "@/assets/js/map-util.js";
-import { mapGetters, mapState, mapActions, mapMutations } from "vuex";
-import projectAPI from "@/services/project-api";
-import featureTypeAPI from "@/services/featureType-api";
-import featureAPI from "@/services/feature-api";
+import frag from 'vue-frag';
+import { mapUtil } from '@/assets/js/map-util.js';
+import { mapGetters, mapState, mapActions, mapMutations } from 'vuex';
+import projectAPI from '@/services/project-api';
+import featureTypeAPI from '@/services/featureType-api';
+import featureAPI from '@/services/feature-api';
 
-import axios from "@/axios-client.js";
+import axios from '@/axios-client.js';
 
 import { fileConvertSizeToMo } from '@/assets/js/utils';
 
 export default {
-  name: "Project_details",
-
-  props: ["message"],
+  name: 'ProjectDetails',
 
   directives: {
     frag,
@@ -722,24 +775,31 @@ export default {
   filters: {
     setDate(value) {
       const date = new Date(value);
-      const d = date.toLocaleDateString("fr", {
-        year: "2-digit",
-        month: "numeric",
-        day: "numeric",
+      const d = date.toLocaleDateString('fr', {
+        year: '2-digit',
+        month: 'numeric',
+        day: 'numeric',
       });
       return d;
     },
   },
 
+  props: {
+    message: {
+      type: String,
+      default: ''
+    }
+  },
+
   data() {
     return {
-      infoMessage: "",
+      infoMessage: '',
       importMessage: null,
       arraysOffline: [],
       arraysOfflineErrors: [],
       confirmMsg: false,
       geojsonImport: [],
-      fileToImport: { name: "", size: 0 },
+      fileToImport: { name: '', size: 0 },
       slug: this.$route.params.slug,
       modalType: false,
       is_suscriber: false,
@@ -806,41 +866,50 @@ export default {
       handler(newValue, oldValue) {
         if (newValue && newValue !== oldValue) {
           this.GET_IMPORTS({
-            project_slug: this.$route.params.slug
+            project_slug: this.$route.params.slug,
           });
         }
-      }
+      },
     },
 
     importFeatureTypeData: {
       deep: true,
       handler(newValue) {
-        if (newValue && newValue.some(el => el.status === 'pending') && !this.reloadIntervalId) {
-          this.SET_RELOAD_INTERVAL_ID(setInterval(() => {
-            this.GET_IMPORTS({
-              project_slug: this.$route.params.slug
-            });
-          }, this.$store.state.configuration.VUE_APP_RELOAD_INTERVAL));
-        } else if (newValue && !newValue.some(el => el.status === 'pending') && this.reloadIntervalId) {
+        if (
+          newValue &&
+          newValue.some((el) => el.status === 'pending') &&
+          !this.reloadIntervalId
+        ) {
+          this.SET_RELOAD_INTERVAL_ID(
+            setInterval(() => {
+              this.GET_IMPORTS({
+                project_slug: this.$route.params.slug,
+              });
+            }, this.$store.state.configuration.VUE_APP_RELOAD_INTERVAL)
+          );
+        } else if (
+          newValue &&
+          !newValue.some((el) => el.status === 'pending') &&
+          this.reloadIntervalId
+        ) {
           this.GET_PROJECT_FEATURE_TYPES(this.project.slug);
           this.CLEAR_RELOAD_INTERVAL_ID();
         }
-      }
+      },
     },
   },
 
   created() {
-
     if (this.user) {
       projectAPI
         .getProjectSubscription({
           baseUrl: this.$store.state.configuration.VUE_APP_DJANGO_API_BASE,
           projectSlug: this.$route.params.slug
         })
-          .then((data) => (this.is_suscriber = data.is_suscriber));
+        .then((data) => (this.is_suscriber = data.is_suscriber));
     }
-    this.$store.commit("feature/SET_FEATURES", []); //* empty features remaining in case they were in geojson format and will be fetch after map initialization anyway
-    this.$store.commit("feature_type/SET_FEATURE_TYPES", []); //* empty feature_types remaining from previous project
+    this.$store.commit('feature/SET_FEATURES', []); //* empty features remaining in case they were in geojson format and will be fetch after map initialization anyway
+    this.$store.commit('feature_type/SET_FEATURE_TYPES', []); //* empty feature_types remaining from previous project
   },
 
   mounted() {
@@ -849,14 +918,14 @@ export default {
     if (this.message) {
       this.tempMessage = this.message;
       document
-        .getElementById("message")
-        .scrollIntoView({ block: "end", inline: "nearest" });
+        .getElementById('message')
+        .scrollIntoView({ block: 'end', inline: 'nearest' });
       setTimeout(() => (this.tempMessage = null), 5000); //* hide message after 5 seconds
     }
   },
 
   destroyed() {
-     this.CLEAR_RELOAD_INTERVAL_ID();
+    this.CLEAR_RELOAD_INTERVAL_ID();
   },
 
   methods: {
@@ -882,34 +951,36 @@ export default {
       'GET_PROJECT_FEATURE_TYPES'
     ]),
     refreshId() {
-      return "?ver=" + Math.random();
+      return '?ver=' + Math.random();
     },
     getRouteUrl(url) {
       if (this.isSharedProject) {
-        url = url.replace("projet", "projet-partage")
+        url = url.replace('projet', 'projet-partage');
       }
-      return url.replace(this.$store.state.configuration.BASE_URL, ""); //* remove duplicate /geocontrib
+      return url.replace(this.$store.state.configuration.BASE_URL, ''); //* remove duplicate /geocontrib
     },
     isOffline() {
       return navigator.onLine === false;
     },
     isImporting(type) {
       if (this.importFeatureTypeData) {
-        const singleImportData = this.importFeatureTypeData.find(el => el.feature_type_title === type.slug);
-        return singleImportData && singleImportData.status === 'pending'
+        const singleImportData = this.importFeatureTypeData.find(
+          (el) => el.feature_type_title === type.slug
+        );
+        return singleImportData && singleImportData.status === 'pending';
       }
       return false;
     },
 
     copyLink() {
-      const sharedLink = window.location.href.replace("projet", "projet-partage");
+      const sharedLink = window.location.href.replace('projet', 'projet-partage');
       navigator.clipboard.writeText(sharedLink).then(()=> {
-          console.log("success")
-          this.confirmMsg = true;
-        }, () => {
-          console.log("failed")
-        }
-      )
+        console.log('success');
+        this.confirmMsg = true;
+      }, () => {
+        console.log('failed');
+      }
+      );
     },
 
     retrieveProjectInfo() {
@@ -924,14 +995,14 @@ export default {
           }, 1000);
         })
         .catch((err) => {
-          console.error(err)
+          console.error(err);
           this.projectInfoLoading = false;
         });
     },
 
     checkForOfflineFeature() {
       let arraysOffline = [];
-      let localStorageArray = localStorage.getItem("geocontrib_offline");
+      let localStorageArray = localStorage.getItem('geocontrib_offline');
       if (localStorageArray) {
         arraysOffline = JSON.parse(localStorageArray);
         this.arraysOffline = arraysOffline.filter(
@@ -945,15 +1016,14 @@ export default {
       let self = this;
       this.arraysOfflineErrors = [];
       this.arraysOffline.forEach((feature) => {
-        if (feature.type === "post") {
+        if (feature.type === 'post') {
           promises.push(
             axios
               .post(`${this.API_BASE_URL}features/`, feature.geojson)
               .then((response) => {
                 if (response.status === 201 && response.data) {
-                  return "OK"
-                }
-                else{
+                  return 'OK';
+                } else {
                   self.arraysOfflineErrors.push(feature);
                 }
               })
@@ -962,7 +1032,7 @@ export default {
                 self.arraysOfflineErrors.push(feature);
               })
           );
-        } else if (feature.type === "put") {
+        } else if (feature.type === 'put') {
           promises.push(
             axios
               .put(
@@ -971,9 +1041,8 @@ export default {
               )
               .then((response) => {
                 if (response.status === 200 && response.data) {
-                  return "OK"
-                }
-                else{
+                  return 'OK';
+                } else {
                   self.arraysOfflineErrors.push(feature);
                 }
               })
@@ -992,7 +1061,7 @@ export default {
 
     updateLocalStorage() {
       let arraysOffline = [];
-      let localStorageArray = localStorage.getItem("geocontrib_offline");
+      let localStorageArray = localStorage.getItem('geocontrib_offline');
       if (localStorageArray) {
         arraysOffline = JSON.parse(localStorageArray);
       }
@@ -1000,14 +1069,16 @@ export default {
         (x) => x.project !== this.project.slug
       );
       this.arraysOffline = [];
-      arraysOffline = arraysOfflineOtherProject.concat(this.arraysOfflineErrors);
-      localStorage.setItem("geocontrib_offline", JSON.stringify(arraysOffline));
+      arraysOffline = arraysOfflineOtherProject.concat(
+        this.arraysOfflineErrors
+      );
+      localStorage.setItem('geocontrib_offline', JSON.stringify(arraysOffline));
     },
 
     toNewFeatureType() {
       this.featureTypeImporting = true;
       this.$router.push({
-        name: "ajouter-type-signalement",
+        name: 'ajouter-type-signalement',
         params: {
           geojson: this.geojsonImport,
           fileToImport: this.fileToImport,
@@ -1034,12 +1105,12 @@ export default {
           fr.readAsText(this.fileToImport);
           //* stock filename to import features afterward
           this.$store.commit(
-            "feature_type/SET_FILE_TO_IMPORT",
+            'feature_type/SET_FILE_TO_IMPORT',
             this.fileToImport
           );
         } catch (err) {
           console.error(err);
-          this.featureTypeImporting = false
+          this.featureTypeImporting = false;
         }
       } else {
         this.featureTypeImporting = false;
@@ -1047,7 +1118,7 @@ export default {
     },
 
     closeFileSizeModal() {
-      this.fileToImport = { name: "", size: 0 };
+      this.fileToImport = { name: '', size: 0 };
       this.featureTypeImporting = false;
       this.isFileSizeModalOpen = false;
     },
@@ -1064,11 +1135,11 @@ export default {
           this.modalType = false;
           if (this.is_suscriber)
             this.infoMessage =
-              "Vous êtes maintenant abonné aux notifications de ce projet.";
+              'Vous êtes maintenant abonné aux notifications de ce projet.';
           else
             this.infoMessage =
-              "Vous ne recevrez plus les notifications de ce projet.";
-          setTimeout(() => (this.infoMessage = ""), 3000);
+              'Vous ne recevrez plus les notifications de ce projet.';
+          setTimeout(() => (this.infoMessage = ''), 3000);
         });
     },
 
@@ -1077,11 +1148,11 @@ export default {
         .then((response) => {
           if (response === 'success') {
             this.$router.push('/');
-            this.DISPLAY_MESSAGE(`Le projet ${this.project.title} a bien été supprimé.`)
+            this.DISPLAY_MESSAGE(`Le projet ${this.project.title} a bien été supprimé.`);
           } else {
-            this.DISPLAY_MESSAGE(`Une erreur est survenu lors de la suppression du projet ${this.project.title}.`)
+            this.DISPLAY_MESSAGE(`Une erreur est survenu lors de la suppression du projet ${this.project.title}.`);
           }
-        })
+        });
     },
 
     deleteFeatureType() {
@@ -1091,26 +1162,26 @@ export default {
           if (response === 'success') {
             this.GET_PROJECT();
             this.retrieveProjectInfo();
-            this.DISPLAY_MESSAGE(`Le type de signalement ${this.featureTypeToDelete.title} a bien été supprimé.`)
+            this.DISPLAY_MESSAGE(`Le type de signalement ${this.featureTypeToDelete.title} a bien été supprimé.`);
           } else {
-            this.DISPLAY_MESSAGE(`Une erreur est survenu lors de la suppression du type de signalement ${this.featureTypeToDelete.title}.`)
+            this.DISPLAY_MESSAGE(`Une erreur est survenu lors de la suppression du type de signalement ${this.featureTypeToDelete.title}.`);
           }
           this.featureTypeToDelete = null;
-        })
+        });
     },
 
     handleModalClick() {
       switch (this.modalType) {
-        case 'subscribe':
-          this.subscribeProject();
-          break;
-        case 'deleteProject':
-          this.deleteProject();
-          break;
-        case 'deleteFeatureType':
-          this.deleteFeatureType();
-          break;
-        }
+      case 'subscribe':
+        this.subscribeProject();
+        break;
+      case 'deleteProject':
+        this.deleteProject();
+        break;
+      case 'deleteFeatureType':
+        this.deleteFeatureType();
+        break;
+      }
     },
 
     toggleDeleteFeatureType(featureType) {
@@ -1122,14 +1193,14 @@ export default {
       if (this.project && this.permissions.can_view_project) {
         await this.INITIATE_MAP(this.$refs.map);
         this.checkForOfflineFeature();
-        let project_id = this.$route.params.slug.split("-")[0];
+        let project_id = this.$route.params.slug.split('-')[0];
         const mvtUrl = `${this.API_BASE_URL}features.mvt/?tile={z}/{x}/{y}&project_id=${project_id}`;
         mapUtil.addVectorTileLayer(
           mvtUrl,
           this.$route.params.slug,
           this.$store.state.feature_type.feature_types
         );
-        this.arraysOffline.forEach((x) => (x.geojson.properties.color = "red"));
+        this.arraysOffline.forEach((x) => (x.geojson.properties.color = 'red'));
         const features = this.arraysOffline.map((x) => x.geojson);
         mapUtil.addFeatures(
           features,
@@ -1143,23 +1214,21 @@ export default {
           project_slug: this.slug,
           ordering: '-created_on',
           limit: null,
-          geojson: true
+          geojson: true,
         })
           .then(() => {
             this.featuresLoading = false;
           })
           .catch((err) => {
-            console.error(err)
+            console.error(err);
             this.featuresLoading = false;
           });
 
-        featureAPI
-          .getFeaturesBbox(this.project.slug)
-          .then((bbox) => {
-            if (bbox) {
-              mapUtil.getMap().fitBounds(bbox, { padding: [25, 25] });
-            }
-          });
+        featureAPI.getFeaturesBbox(this.project.slug).then((bbox) => {
+          if (bbox) {
+            mapUtil.getMap().fitBounds(bbox, { padding: [25, 25] });
+          }
+        });
       }
     },
   },
diff --git a/src/views/project/Project_edit.vue b/src/views/project/Project_edit.vue
index f8ad6836291f32b91d8060c5b17d6c57ab0218d4..27aaa3ebac7141e9931e8e916b79c242fd676a94 100644
--- a/src/views/project/Project_edit.vue
+++ b/src/views/project/Project_edit.vue
@@ -1,33 +1,47 @@
 <template>
   <div class="fourteen wide column">
-    <div :class="{ active: loading }" class="ui inverted dimmer">
+    <div
+      :class="{ active: loading }"
+      class="ui inverted dimmer"
+    >
       <div class="ui text loader">
         Projet en cours de création. Vous allez être redirigé.
       </div>
     </div>
-    <form id="form-project-edit" class="ui form">
+    <form
+      id="form-project-edit"
+      class="ui form"
+    >
       <h1>
-        <span v-if="action === 'edit'"
-          >Édition du projet "{{ form.title }}"</span
-        >
+        <span
+          v-if="action === 'edit'"
+        >Édition du projet "{{ form.title }}"</span>
         <span v-else-if="action === 'create'">Création d'un projet</span>
       </h1>
 
-      <div class="ui horizontal divider">INFORMATIONS</div>
+      <div class="ui horizontal divider">
+        INFORMATIONS
+      </div>
 
       <div class="two fields">
         <div class="required field">
           <label for="title">Titre</label>
           <input
+            id="title"
+            v-model="form.title"
             type="text"
             required
             maxlength="128"
             name="title"
-            id="title"
-            v-model="form.title"
-          />
-          <ul id="errorlist-title" class="errorlist">
-            <li v-for="error in errors.title" :key="error">
+          >
+          <ul
+            id="errorlist-title"
+            class="errorlist"
+          >
+            <li
+              v-for="error in errors.title"
+              :key="error"
+            >
               {{ error }}
             </li>
           </ul>
@@ -35,29 +49,32 @@
         <div class="field">
           <label>Illustration du projet</label>
           <img
-            class="ui small image"
             id="form-input-file-logo"
+            class="ui small image"
             :src="
               thumbnailFileSrc
                 ? thumbnailFileSrc
                 : DJANGO_BASE_URL + form.thumbnail
             "
-          />
-          <label class="ui icon button" for="thumbnail">
-            <i class="file icon"></i>
+          >
+          <label
+            class="ui icon button"
+            for="thumbnail"
+          >
+            <i class="file icon" />
             <span class="label">{{
               form.thumbnail_name ? form.thumbnail_name : fileToImport.name
             }}</span>
           </label>
           <input
-            @change="onFileChange"
+            id="thumbnail"
             class="file-selection"
             type="file"
             accept="image/jpeg, image/png"
             style="display: none"
             name="thumbnail"
-            id="thumbnail"
-          />
+            @change="onFileChange"
+          >
           <ul
             v-if="errorThumbnail.length"
             id="errorlist-thumbnail"
@@ -75,27 +92,31 @@
           v-model="form.description"
           name="description"
           rows="5"
-        ></textarea>
+        />
         <!-- {{ form.description.errors }} -->
       </div>
 
-      <div class="ui horizontal divider">PARAMÈTRES</div>
+      <div class="ui horizontal divider">
+        PARAMÈTRES
+      </div>
 
       <div class="four fields">
         <div class="field">
           <label for="archive_feature">Délai avant archivage</label>
           <div class="ui right labeled input">
             <input
+              id="archive_feature"
+              v-model="form.archive_feature"
               type="number"
               min="0"
               oninput="validity.valid||(value=0);"
               style="padding: 1px 2px"
               name="archive_feature"
-              id="archive_feature"
               @blur="checkEmpty"
-              v-model="form.archive_feature"
-            />
-            <div class="ui label">jour(s)</div>
+            >
+            <div class="ui label">
+              jour(s)
+            </div>
           </div>
           <ul
             v-if="errors_archive_feature.length"
@@ -111,29 +132,37 @@
           <label for="delete_feature">Délai avant suppression</label>
           <div class="ui right labeled input">
             <input
+              id="delete_feature"
+              v-model="form.delete_feature"
               type="number"
               min="0"
               oninput="validity.valid||(value=0);"
               style="padding: 1px 2px"
               name="delete_feature"
-              id="delete_feature"
               @blur="checkEmpty"
-              v-model="form.delete_feature"
-            />
-            <div class="ui label">jour(s)</div>
+            >
+            <div class="ui label">
+              jour(s)
+            </div>
           </div>
         </div>
         <div class="required field">
-          <label for="access_level_pub_feature"
-            >Visibilité des signalements publiés</label
-          >
+          <label
+            for="access_level_pub_feature"
+          >Visibilité des signalements publiés</label>
           <Dropdown
             :options="levelPermissionsPub"
             :selected="form.access_level_pub_feature.name"
             :selection.sync="form.access_level_pub_feature"
           />
-          <ul id="errorlist-access_level_pub_feature" class="errorlist">
-            <li v-for="error in errors.access_level_pub_feature" :key="error">
+          <ul
+            id="errorlist-access_level_pub_feature"
+            class="errorlist"
+          >
+            <li
+              v-for="error in errors.access_level_pub_feature"
+              :key="error"
+            >
               {{ error }}
             </li>
           </ul>
@@ -147,8 +176,14 @@
             :selected="form.access_level_arch_feature.name"
             :selection.sync="form.access_level_arch_feature"
           />
-          <ul id="errorlist-access_level_arch_feature" class="errorlist">
-            <li v-for="error in errors.access_level_arch_feature" :key="error">
+          <ul
+            id="errorlist-access_level_arch_feature"
+            class="errorlist"
+          >
+            <li
+              v-for="error in errors.access_level_arch_feature"
+              :key="error"
+            >
               {{ error }}
             </li>
           </ul>
@@ -158,12 +193,12 @@
       <div class="field">
         <div class="ui checkbox">
           <input
+            id="moderation"
+            v-model="form.moderation"
             class="hidden"
             type="checkbox"
-            v-model="form.moderation"
             name="moderation"
-            id="moderation"
-          />
+          >
           <label for="moderation">Modération</label>
         </div>
       </div>
@@ -171,33 +206,37 @@
       <div class="field">
         <div class="ui checkbox">
           <input
+            id="is_project_type"
+            v-model="form.is_project_type"
             class="hidden"
             type="checkbox"
-            v-model="form.is_project_type"
             name="is_project_type"
-            id="is_project_type"
-          />
+          >
           <label for="is_project_type">Est un projet type</label>
         </div>
       </div>
 
       <div class="field">
         <div class="ui checkbox">
-            <input
-              class="hidden"
-              type="checkbox"
-              v-model="form.generate_share_link"
-              name="generate_share_link"
-              id="generate_share_link"
-            />
+          <input
+            id="generate_share_link"
+            v-model="form.generate_share_link"
+            class="hidden"
+            type="checkbox"
+            name="generate_share_link"
+          >
           <label for="generate_share_link">Génération d'un lien de partage externe</label>
         </div>
       </div>
 
-      <div class="ui divider"></div>
+      <div class="ui divider" />
 
-      <button @click="postForm" type="button" class="ui teal icon button">
-        <i class="white save icon"></i> Enregistrer les changements
+      <button
+        type="button"
+        class="ui teal icon button"
+        @click="postForm"
+      >
+        <i class="white save icon" /> Enregistrer les changements
       </button>
     </form>
   </div>
@@ -205,12 +244,12 @@
 
 <script>
 import axios from '@/axios-client.js';
-import Dropdown from "@/components/Dropdown.vue";
+import Dropdown from '@/components/Dropdown.vue';
 
-import { mapState, mapGetters, mapActions } from "vuex";
+import { mapState, mapGetters, mapActions } from 'vuex';
 
 export default {
-  name: "Project_edit",
+  name: 'ProjectEdit',
 
   components: {
     Dropdown,
@@ -219,9 +258,9 @@ export default {
   data() {
     return {
       loading: false,
-      action: "create",
+      action: 'create',
       fileToImport: {
-        name: "Sélectionner une image ...",
+        name: 'Sélectionner une image ...',
         size: 0,
       },
       errors_archive_feature: [],
@@ -232,17 +271,17 @@ export default {
       },
       errorThumbnail: [],
       form: {
-        title: "",
-        slug: "",
-        created_on: "",
-        updated_on: "",
-        description: "",
+        title: '',
+        slug: '',
+        created_on: '',
+        updated_on: '',
+        description: '',
         moderation: false,
-        thumbnail: "", // todo : utiliser l'image par défaut
-        thumbnail_name: "", // todo: delete after getting image in jpg or png instead of data64 (require post to django)
+        thumbnail: '', // todo : utiliser l'image par défaut
+        thumbnail_name: '', // todo: delete after getting image in jpg or png instead of data64 (require post to django)
         creator: null,
-        access_level_pub_feature: { name: "", value: "" },
-        access_level_arch_feature: { name: "", value: "" },
+        access_level_pub_feature: { name: '', value: '' },
+        access_level_arch_feature: { name: '', value: '' },
         archive_feature: 0,
         delete_feature: 0,
         nb_features: 0,
@@ -253,15 +292,15 @@ export default {
         is_project_type: false,
         generate_share_link: false,
       },
-      thumbnailFileSrc: "",
+      thumbnailFileSrc: '',
     };
   },
 
   computed: {
     ...mapState([
-      "levelsPermissions",
+      'levelsPermissions',
     ]),
-    ...mapGetters(["project"]),
+    ...mapGetters(['project']),
     DJANGO_BASE_URL: function () {
       return this.$store.state.configuration.VUE_APP_DJANGO_BASE;
     },
@@ -270,15 +309,15 @@ export default {
       let levels = new Array();
       if(self.levelsPermissions){
         self.levelsPermissions.map(function(item) {
-          if (item.user_type_id != "super_contributor")
-          levels.push({
-              'name': self.traslateRoleToFrench(item.user_type_id), 
-              'value': item.user_type_id,
-            })
-            if (!self.form.moderation && item.user_type_id == "moderator"){
-              levels.pop()
-            }
-          });
+          if (item.user_type_id != 'super_contributor')
+            levels.push({
+              name: self.traslateRoleToFrench(item.user_type_id), 
+              value: item.user_type_id,
+            });
+          if (!self.form.moderation && item.user_type_id == 'moderator'){
+            levels.pop();
+          }
+        });
       }
       return levels;
     },
@@ -287,50 +326,66 @@ export default {
       let levels = new Array();
       if(self.levelsPermissions){
         self.levelsPermissions.map(function(item) {
-          if (item.user_type_id != "super_contributor" 
-            && item.user_type_id != "admin"
-            && item.user_type_id != "moderator"){
-          levels.push({
-              'name': self.traslateRoleToFrench(item.user_type_id), 
-              'value': item.user_type_id,
-            })
+          if (item.user_type_id != 'super_contributor' 
+            && item.user_type_id != 'admin'
+            && item.user_type_id != 'moderator'){
+            levels.push({
+              name: self.traslateRoleToFrench(item.user_type_id), 
+              value: item.user_type_id,
+            });
           }
         });
       }
       return levels;
     }
   },
+  watch: {
+    'form.moderation': function (newValue){
+      if(!newValue){
+        this.form.access_level_pub_feature = { name: '', value: '' };
+        this.form.access_level_arch_feature = { name: '', value: '' };
+      }
+    }
+  },
+  created() {
+    this.definePageType();
+    if (this.action === 'create') {
+      this.thumbnailFileSrc = require('@/assets/img/default.png');
+    } else if (this.action === 'edit' || this.action === 'create_from') {
+      this.fillProjectForm();
+    }
+  },
 
   methods: {
     ...mapActions('projects', [
       'GET_ALL_PROJECTS'
     ]),
     definePageType() {
-      if (this.$router.history.current.name === "project_create") {
-        this.action = "create";
-      } else if (this.$router.history.current.name === "project_edit") {
-        this.action = "edit";
-      } else if (this.$router.history.current.name === "project_create_from") {
-        this.action = "create_from";
+      if (this.$router.history.current.name === 'project_create') {
+        this.action = 'create';
+      } else if (this.$router.history.current.name === 'project_edit') {
+        this.action = 'edit';
+      } else if (this.$router.history.current.name === 'project_create_from') {
+        this.action = 'create_from';
       }
     },
    
     traslateRoleToFrench(role){
-      if (role == "admin") return "Administrateur projet";
-      if (role == "moderator") return "Modérateur";
-      if (role == "contributor") return "Contributeur";
-      if (role == "logged_user") return "Utilisateur connecté";
-      if (role == "anonymous") return "Utilisateur anonyme";
+      if (role == 'admin') return 'Administrateur projet';
+      if (role == 'moderator') return 'Modérateur';
+      if (role == 'contributor') return 'Contributeur';
+      if (role == 'logged_user') return 'Utilisateur connecté';
+      if (role == 'anonymous') return 'Utilisateur anonyme';
     },
 
     truncate(n, len) {
-      let ext = n.substring(n.lastIndexOf(".") + 1, n.length).toLowerCase();
-      let filename = n.replace("." + ext, "");
+      let ext = n.substring(n.lastIndexOf('.') + 1, n.length).toLowerCase();
+      let filename = n.replace('.' + ext, '');
       if (filename.length <= len) {
         return n;
       }
-      filename = filename.substr(0, len) + (n.length > len ? "[...]" : "");
-      return filename + "." + ext;
+      filename = filename.substr(0, len) + (n.length > len ? '[...]' : '');
+      return filename + '.' + ext;
     },
 
     validateImgFile(files, handleFile) {
@@ -382,13 +437,13 @@ export default {
 
     goBackNrefresh(slug) {
       Promise.all([
-        this.$store.dispatch("GET_USER_LEVEL_PROJECTS"), //* refresh projects user levels
-        this.$store.dispatch("GET_USER_LEVEL_PERMISSIONS"), //* refresh projects permissions
+        this.$store.dispatch('GET_USER_LEVEL_PROJECTS'), //* refresh projects user levels
+        this.$store.dispatch('GET_USER_LEVEL_PERMISSIONS'), //* refresh projects permissions
         this.GET_ALL_PROJECTS(), //* & refresh project list
       ]).then(() =>
         // * go back to project list
         this.$router.push({
-          name: "project_detail",
+          name: 'project_detail',
           params: { slug },
         })
       );
@@ -398,16 +453,16 @@ export default {
       //* send img to the backend when feature_type is created
       if (this.fileToImport) {
         let formData = new FormData();
-        formData.append("file", this.fileToImport);
+        formData.append('file', this.fileToImport);
         const url =
           this.$store.state.configuration.VUE_APP_DJANGO_API_BASE +
-          "projects/" +
+          'projects/' +
           projectSlug +
-          "/thumbnail/";
+          '/thumbnail/';
         return axios
           .put(url, formData, {
             headers: {
-              "Content-Type": "multipart/form-data",
+              'Content-Type': 'multipart/form-data',
             },
           })
           .then((response) => {
@@ -433,17 +488,17 @@ export default {
         return false;
       }
       for (const key in this.errors) {
-        if ((key === "title" && this.form[key]) || this.form[key].value) {
+        if ((key === 'title' && this.form[key]) || this.form[key].value) {
           this.errors[key] = [];
         } else if (!this.errors[key].length) {
           this.errors[key].push(
-            key === "title"
-              ? "Veuillez compléter ce champ."
-              : "Sélectionnez un choix valide. Ce choix ne fait pas partie de ceux disponibles."
+            key === 'title'
+              ? 'Veuillez compléter ce champ.'
+              : 'Sélectionnez un choix valide. Ce choix ne fait pas partie de ceux disponibles.'
           );
           document
             .getElementById(`errorlist-${key}`)
-            .scrollIntoView({ block: "end", inline: "nearest" });
+            .scrollIntoView({ block: 'end', inline: 'nearest' });
           return false;
         }
       }
@@ -465,7 +520,7 @@ export default {
       };
       let url = `${this.$store.state.configuration.VUE_APP_DJANGO_API_BASE}projects/`;
 
-      if (this.action === "edit") {
+      if (this.action === 'edit') {
         await axios
           .put((url += `${this.project.slug}/`), projectData)
           .then((response) => {
@@ -485,7 +540,7 @@ export default {
             throw error;
           });
       } else {
-        if (this.action === "create_from") {
+        if (this.action === 'create_from') {
           url += `${this.project.slug}/duplicate/`;
         }
         this.loading = true;
@@ -513,24 +568,24 @@ export default {
     },
     fillProjectForm() {
       if (!this.project) {
-        this.$store.dispatch("GET_PROJECT_INFO", this.$route.params.slug);
+        this.$store.dispatch('GET_PROJECT_INFO', this.$route.params.slug);
       }
       this.form = { ...this.project }; //* create a new object to avoid modifying original one
-      if (this.action === "create_from") {
+      if (this.action === 'create_from') {
         this.form.title =
           this.project.title +
           ` (Copie-${new Date()
             .toLocaleString()
             .slice(0, -3)
-            .replace(",", "")})`;
+            .replace(',', '')})`;
         this.form.is_project_type = false;
       }
       //* transform string values to objects for dropdowns display (could be in a computed)
       if(this.levelPermissionsPub){
-        let value = {}
+        let value = {};
         value = this.levelPermissionsPub.find(
-            (el) => el.name === this.project.access_level_pub_feature
-          )
+          (el) => el.name === this.project.access_level_pub_feature
+        );
         if(value){
           this.form.access_level_pub_feature = {
             name: this.project.access_level_pub_feature,
@@ -538,11 +593,11 @@ export default {
           };
         }
       }
-     if(this.levelPermissions){
-        let value = {}
+      if(this.levelPermissions){
+        let value = {};
         value = this.levelPermissions.find(
-            (el) => el.name === this.project.access_level_arch_feature
-          )
+          (el) => el.name === this.project.access_level_arch_feature
+        );
         if(value){
           this.form.access_level_arch_feature = {
             name: this.project.access_level_arch_feature,
@@ -552,22 +607,6 @@ export default {
       }
     },
   },
-  watch: {
-    'form.moderation': function (newValue){
-      if(!newValue){
-        this.form.access_level_pub_feature = { name: "", value: "" };
-        this.form.access_level_arch_feature = { name: "", value: "" };
-      }
-    }
-  },
-  created() {
-    this.definePageType();
-    if (this.action === "create") {
-      this.thumbnailFileSrc = require("@/assets/img/default.png");
-    } else if (this.action === "edit" || this.action === "create_from") {
-      this.fillProjectForm();
-    }
-  },
 };
 </script>
 
diff --git a/src/views/project/Project_mapping.vue b/src/views/project/Project_mapping.vue
index 7ab8de8b85ed98b6d09f9a00100cfb7e8180b97b..ff4c03513e883b223f5b9cfcbe22331ca74d2940 100644
--- a/src/views/project/Project_mapping.vue
+++ b/src/views/project/Project_mapping.vue
@@ -1,6 +1,9 @@
 <template>
   <div class="fourteen wide column">
-    <div id="message_info" class="fullwidth">
+    <div
+      id="message_info"
+      class="fullwidth"
+    >
       <div v-if="infoMessage.length > 0">
         <div
           v-for="(message, index) of infoMessage"
@@ -9,13 +12,15 @@
           style="text-align: left"
         >
           <div class="header">
-            <i class="info circle icon"></i> Informations
+            <i class="info circle icon" /> Informations
           </div>
           {{ message.comment }}
         </div>
       </div>
     </div>
-    <h1 class="ui header">Administration des fonds cartographiques</h1>
+    <h1 class="ui header">
+      Administration des fonds cartographiques
+    </h1>
 
     <form
       id="form-layers"
@@ -31,36 +36,40 @@
           data-variation="mini"
           @click="addBasemap"
         >
-          <i class="ui plus icon"></i>
-          <span>Créer un fond cartographique</span>
+          <i class="ui plus icon" />
+          <span>&nbsp;Créer un fond cartographique</span>
         </a>
       </div>
 
-      <div v-if="basemaps" class="ui">
+      <div
+        v-if="basemaps"
+        class="ui"
+      >
         <ProjectMappingBasemap
           v-for="basemap in basemaps"
           :key="basemap.id"
           :basemap="basemap"
         />
       </div>
-
-      <button
-        @click="saveChanges"
-        type="button"
-        class="ui teal icon floated button"
-      >
-        <i class="white save icon"></i> Enregistrer les changements
-      </button>
+      <div class="margin-top">
+        <button
+          type="button"
+          class="ui teal icon floated button"
+          @click="saveChanges"
+        >
+          <i class="white save icon" /> Enregistrer les changements
+        </button>
+      </div>
     </form>
   </div>
 </template>
 
 <script>
-import Project_mapping_basemap from "@/components/project/project_mapping_basemap.vue";
-import { mapState, mapGetters } from "vuex";
+import Project_mapping_basemap from '@/components/project/project_mapping_basemap.vue';
+import { mapState, mapGetters } from 'vuex';
 
 export default {
-  name: "Project_mapping",
+  name: 'ProjectMapping',
 
   components: {
     ProjectMappingBasemap: Project_mapping_basemap,
@@ -74,27 +83,33 @@ export default {
   },
 
   computed: {
-    ...mapState("map", ["basemaps"]),
-    ...mapGetters("map", ["basemapMaxId"]),
+    ...mapState('map', ['basemaps']),
+    ...mapGetters('map', ['basemapMaxId']),
+  },
+
+  created() {
+    if (!this.$store.getters.project) {
+      this.$store.dispatch('GET_PROJECT_INFO', this.$route.params.slug);
+    }
   },
 
   methods: {
     addBasemap() {
       this.newBasemapIds.push(this.basemapMaxId + 1); //* register new basemaps to seperate post and put
-      this.$store.commit("map/CREATE_BASEMAP", this.basemapMaxId + 1);
+      this.$store.commit('map/CREATE_BASEMAP', this.basemapMaxId + 1);
     },
     
     checkTitles() {
       let isValid = true;
       this.basemaps.forEach((basemap) => {
-        if (basemap.title === null || basemap.title === "") {
-          basemap.errors = "Veuillez compléter ce champ.";
+        if (basemap.title === null || basemap.title === '') { //* check title when saving basemaps
+          basemap.errors = 'Veuillez compléter ce champ.';
           isValid = false;
         } else if (basemap.layers.length === 0) {
-          basemap.errors = "Veuillez ajouter au moins un layer.";
+          basemap.errors = 'Veuillez ajouter au moins un layer.';
           isValid = false;
         } else {
-          basemap.errors = "";
+          basemap.errors = '';
         }
       });
       return isValid;
@@ -103,7 +118,7 @@ export default {
     saveChanges() {
       if (this.checkTitles()) {
         this.$store
-          .dispatch("map/SAVE_BASEMAPS", this.newBasemapIds)
+          .dispatch('map/SAVE_BASEMAPS', this.newBasemapIds)
           .then((response) => {
             const errors = response.filter(
               (res) =>
@@ -112,7 +127,7 @@ export default {
             if (errors.length === 0) {
               this.infoMessage.push({
                 success: true,
-                comment: "Enregistrement effectué.",
+                comment: 'Enregistrement effectué.',
               });
               this.newBasemapIds = [];
             } else {
@@ -123,8 +138,8 @@ export default {
             }
 
             document
-              .getElementById("message_info")
-              .scrollIntoView({ block: "end", inline: "nearest" });
+              .getElementById('message_info')
+              .scrollIntoView({ block: 'end', inline: 'nearest' });
             setTimeout(
               function () {
                 this.infoMessage = [];
@@ -138,11 +153,5 @@ export default {
       }
     },
   },
-
-  created() {
-    if (!this.$store.getters.project) {
-      this.$store.dispatch("GET_PROJECT_INFO", this.$route.params.slug);
-    }
-  },
 };
 </script>
\ No newline at end of file
diff --git a/src/views/project/Project_members.vue b/src/views/project/Project_members.vue
index dc2dff3db450ad731794a04efdeaa16d70b010fb..e811df993aa3bad01d6a003254a771f1816dda42 100644
--- a/src/views/project/Project_members.vue
+++ b/src/views/project/Project_members.vue
@@ -1,14 +1,18 @@
 <template>
   <div class="fourteen wide column">
-    <h1 class="ui header">Gérer les membres</h1>
+    <h1 class="ui header">
+      Gérer les membres
+    </h1>
 
     <h4>Ajouter un membre</h4>
 
-    <div id="form-feature-edit" class="ui form" name="add-member">
+    <div
+      id="form-feature-edit"
+      class="ui form"
+      name="add-member"
+    >
       <div class="two fields">
         <div class="field">
-          <!-- <label :for="">{{ form.title.label }}</label> -->
-          <!-- <input type="text" v-model="newMember.name" /> -->
           <Dropdown
             :options="userOptions"
             :selected="newMember.user.name"
@@ -16,14 +20,19 @@
             :search="true"
             :clearable="true"
           />
-          <ul id="errorlist" class="errorlist">
-            <li v-for="error in newMember.errors" :key="error">
+          <ul
+            id="errorlist"
+            class="errorlist"
+          >
+            <li
+              v-for="error in newMember.errors"
+              :key="error"
+            >
               {{ error }}
             </li>
           </ul>
         </div>
         <div class="field">
-          <!-- <label for="add-member"></label> -->
           <Dropdown
             :options="levelOptions"
             :selected="newMember.role.name"
@@ -31,16 +40,22 @@
           />
         </div>
       </div>
-      <button @click="addMember" type="button" class="ui teal icon button">
-        <i class="white save icon"></i>
+      <button
+        type="button"
+        class="ui green icon button"
+        :disabled="newMember.user"
+        @click="addMember"
+      >
+        <i class="white add icon" />
         <span class="padding-1">Ajouter</span>
       </button>
     </div>
 
-    <!-- <input type="text" v-model="newMember.name" /> -->
-
     <h4>Modifier le rôle d'un membre</h4>
-    <div id="form-members" class="ui form">
+    <div
+      id="form-members"
+      class="ui form"
+    >
       <table class="ui red table">
         <thead>
           <tr>
@@ -69,11 +84,12 @@
           </tr>
         </thead>
         <tbody>
-          <tr v-for="member in projectMembers" :key="member.username">
+          <tr
+            v-for="member in projectMembers"
+            :key="member.username"
+          >
             <td>
-              {{ member.user.last_name }} {{ member.user.first_name }}<br /><i
-                >{{ member.user.username }}</i
-              >
+              {{ member.user.last_name }} {{ member.user.first_name }}<br><i>{{ member.user.username }}</i>
             </td>
             <td>
               <div class="required field online">
@@ -84,11 +100,11 @@
                   :search="true"
                 />
                 <button
-                  @click="removeMember(member)"
                   type="button"
                   class="ui icon button"
+                  @click="removeMember(member)"
                 >
-                  <i class="times icon"></i>
+                  <i class="times icon" />
                 </button>
               </div>
             </td>
@@ -96,10 +112,14 @@
         </tbody>
       </table>
 
-      <div class="ui divider"></div>
+      <div class="ui divider" />
 
-      <button @click="saveMembers" type="button" class="ui teal icon button">
-        <i class="white save icon"></i> Enregistrer les changements
+      <button
+        type="button"
+        class="ui teal icon button"
+        @click="saveMembers"
+      >
+        <i class="white save icon" />&nbsp;Enregistrer les changements
       </button>
     </div>
   </div>
@@ -107,12 +127,12 @@
 
 <script>
 import axios from '@/axios-client.js';
-import frag from "vue-frag";
-import { mapGetters } from "vuex";
-import Dropdown from "@/components/Dropdown.vue";
+import frag from 'vue-frag';
+import { mapGetters } from 'vuex';
+import Dropdown from '@/components/Dropdown.vue';
 
 export default {
-  name: "Project_members",
+  name: 'ProjectMembers',
 
   directives: {
     frag,
@@ -125,40 +145,40 @@ export default {
     return {
       projectUsers: [],
       options: [
-        { name: "Utilisateur connecté", value: "logged_user" },
-        { name: "Contributeur", value: "contributor" },
-        { name: "Super Contributeur", value: "super_contributor" },
-        { name: "Modérateur", value: "moderator" },
-        { name: "Administrateur projet", value: "admin" },
+        { name: 'Utilisateur connecté', value: 'logged_user' },
+        { name: 'Contributeur', value: 'contributor' },
+        { name: 'Super Contributeur', value: 'super_contributor' },
+        { name: 'Modérateur', value: 'moderator' },
+        { name: 'Administrateur projet', value: 'admin' },
       ],
       newMember: {
         errors: [],
         user: {
-          name: "",
-          value: "",
+          name: '',
+          value: '',
         },
         role: {
-          name: "Contributeur",
-          value: "contributor",
+          name: 'Contributeur',
+          value: 'contributor',
         },
       },
       sort: {
-        column: "",
+        column: '',
         ascending: true,
       },
     };
   },
 
   computed: {
-    ...mapGetters(["project"]),
+    ...mapGetters(['project']),
 
     userOptions: function () {
       return this.projectUsers
-        .filter((el) => el.userLevel.value === "logged_user")
+        .filter((el) => el.userLevel.value === 'logged_user')
         .map((el) => {
-          let name = el.user.first_name || "";
+          let name = el.user.first_name || '';
           if (el.user.last_name) {
-            name = name + " " + el.user.last_name;
+            name = name + ' ' + el.user.last_name;
           }
           return {
             name: [name, el.user.username],
@@ -170,17 +190,17 @@ export default {
     levelOptions: function () {
       return this.options.filter(
         (el) =>
-          (this.project.moderation ? el : el.value !== "moderator") &&
-          el.value !== "logged_user"
+          (this.project.moderation ? el : el.value !== 'moderator') &&
+          el.value !== 'logged_user'
       );
     },
 
     projectMembers() {
       return this.projectUsers
-        .filter((el) => el.userLevel.value !== "logged_user")
+        .filter((el) => el.userLevel.value !== 'logged_user')
         .sort((a, b) => {
-          if (this.sort.column !== "") {
-            if (this.sort.column === "member") {
+          if (this.sort.column !== '') {
+            if (this.sort.column === 'member') {
               const textA = a.user.username.toUpperCase();
               const textB = b.user.username.toUpperCase();
               if (this.sort.ascending) {
@@ -188,7 +208,7 @@ export default {
               } else {
                 return textA > textB ? -1 : textA < textB ? 1 : 0;
               }
-            } else if (this.sort.column === "role") {
+            } else if (this.sort.column === 'role') {
               const textA = a.userLevel.name.toUpperCase();
               const textB = b.userLevel.name.toUpperCase();
               if (this.sort.ascending) {
@@ -204,11 +224,23 @@ export default {
     },
   },
 
+  created() {
+    if (!this.project) {
+      this.$store.dispatch('GET_PROJECT_INFO', this.$route.params.slug);
+    }
+    this.populateMembers();
+  },
+
+  destroyed() {
+    //* allow user to change page if ever stuck on loader
+    this.$store.commit('DISCARD_LOADER');
+  },
+
   methods: {
     validateNewMember() {
       this.newMember.errors = [];
       if (!this.newMember.user.value) {
-        this.newMember.errors.push("Veuillez compléter ce champ.");
+        this.newMember.errors.push('Veuillez compléter ce champ.');
         return false;
       }
       return true;
@@ -226,7 +258,7 @@ export default {
       if (this.validateNewMember()) {
         this.changeUserRole(this.newMember.user.value, this.newMember.role);
         //* empty add form
-        this.newMember.user = { value: "", name: "" };
+        this.newMember.user = { value: '', name: '' };
       }
     },
 
@@ -249,8 +281,8 @@ export default {
 
     removeMember(member) {
       this.changeUserRole(member.user.id, {
-        name: "Utilisateur connecté",
-        value: "logged_user",
+        name: 'Utilisateur connecté',
+        value: 'logged_user',
       });
     },
 
@@ -272,14 +304,14 @@ export default {
         )
         .then((response) => {
           if (response.status === 200) {
-            this.$store.dispatch("GET_USER_LEVEL_PROJECTS"); //* update user status in top right menu
-            this.$store.commit("DISPLAY_MESSAGE", {comment: "Permissions mises à jour", level: "positive"});
+            this.$store.dispatch('GET_USER_LEVEL_PROJECTS'); //* update user status in top right menu
+            this.$store.commit('DISPLAY_MESSAGE', { comment: 'Permissions mises à jour', level: 'positive' });
           } else {
             this.$store.commit(
-              "DISPLAY_MESSAGE",
+              'DISPLAY_MESSAGE',
               {
                 comment : "Une erreur s'est produite pendant la mises à jour des permissions",
-                level: "negative"
+                level: 'negative'
               }
             );
           }
@@ -303,11 +335,11 @@ export default {
 
     populateMembers() {
       this.$store.commit(
-        "DISPLAY_LOADER",
-        "Récupération des membres en cours..."
+        'DISPLAY_LOADER',
+        'Récupération des membres en cours...'
       );
       this.fetchMembers().then((members) => {
-        this.$store.commit("DISCARD_LOADER");
+        this.$store.commit('DISCARD_LOADER');
         this.projectUsers = members.map((el) => {
           return {
             userLevel: { name: el.level.display, value: el.level.codename },
@@ -317,18 +349,6 @@ export default {
       });
     },
   },
-
-  created() {
-    if (!this.project) {
-      this.$store.dispatch("GET_PROJECT_INFO", this.$route.params.slug);
-    }
-    this.populateMembers();
-  },
-
-  destroyed() {
-    //* allow user to change page if ever stuck on loader
-    this.$store.commit("DISCARD_LOADER");
-  },
 };
 </script>
 
diff --git a/src/views/project/Project_type_list.vue b/src/views/project/Project_type_list.vue
index 99fa39ab293819dbf580887a3f33c2a987976d8a..17d64188705f9d487356995d58d9696d96af41a7 100644
--- a/src/views/project/Project_type_list.vue
+++ b/src/views/project/Project_type_list.vue
@@ -5,7 +5,11 @@
         Créer un projet à partir d'un modèle disponible:
       </h3>
       <div class="ui divided items">
-        <div v-for="project in project_types" :key="project.slug" class="item">
+        <div
+          v-for="project in project_types"
+          :key="project.slug"
+          class="item"
+        >
           <div class="ui tiny image">
             <img
               :src="
@@ -13,7 +17,7 @@
                   ? require('@/assets/img/default.png')
                   : DJANGO_BASE_URL + project.thumbnail + refreshId()
               "
-            />
+            >
           </div>
           <div class="middle aligned content">
             <div class="description">
@@ -24,55 +28,56 @@
                     slug: project.slug,
                   },
                 }"
-                >{{ project.title }}</router-link
               >
+                {{ project.title }}
+              </router-link>
               <p>{{ project.description }}</p>
               <strong v-if="project.moderation">Projet modéré</strong>
               <strong v-else>Projet non modéré</strong>
             </div>
             <div class="meta">
               <span data-tooltip="Délai avant archivage">
-                {{ project.archive_feature }}&nbsp;<i class="box icon"></i>
+                {{ project.archive_feature }}&nbsp;<i class="box icon" />
               </span>
               <span data-tooltip="Délai avant suppression">
                 {{ project.archive_feature }}&nbsp;<i
                   class="trash alternate icon"
-                ></i>
+                />
               </span>
               <span data-tooltip="Date de création">
-                {{ project.created_on }}&nbsp;<i class="calendar icon"></i>
+                {{ project.created_on }}&nbsp;<i class="calendar icon" />
               </span>
             </div>
             <div class="meta">
               <span data-tooltip="Visibilité des signalement publiés">
                 {{ project.access_level_pub_feature }}&nbsp;<i
                   class="eye icon"
-                ></i>
+                />
               </span>
               <span data-tooltip="Visibilité des signalement archivés">
                 {{ project.access_level_arch_feature }}&nbsp;<i
                   class="archive icon"
-                ></i>
+                />
               </span>
             </div>
           </div>
         </div>
-        <span v-if="!project_types || project_types.length === 0"
-          >Aucun projet type n'est défini.</span
-        >
+        <span
+          v-if="!project_types || project_types.length === 0"
+        >Aucun projet type n'est défini.</span>
       </div>
     </div>
   </div>
 </template>
 
 <script>
-import { mapGetters } from "vuex";
+import { mapGetters } from 'vuex';
 
 export default {
-  name: "Project_type_list",
+  name: 'ProjectTypeList',
 
   computed: {
-    ...mapGetters(["project_types"]),
+    ...mapGetters(['project_types']),
     DJANGO_BASE_URL: function () {
       return this.$store.state.configuration.VUE_APP_DJANGO_BASE;
     },
@@ -80,7 +85,7 @@ export default {
 
   methods: {
     refreshId() {
-      return "?ver=" + Math.random();
+      return '?ver=' + Math.random();
     },
   },
 };
diff --git a/src/views/registration/Login.vue b/src/views/registration/Login.vue
index f9614efa8e415cb53704a50200c3668d964152cb..2e5d99c9f8c7477feb667c2b0b99e00edf8ed992 100644
--- a/src/views/registration/Login.vue
+++ b/src/views/registration/Login.vue
@@ -2,51 +2,69 @@
   <div>
     <div class="row">
       <div class="fourteen wide column">
-        <img class="ui centered small image" :src="logo" />
+        <img
+          class="ui centered small image"
+          :src="logo"
+        >
         <h2 class="ui center aligned icon header">
           <div class="content">
             {{ APPLICATION_NAME }}
-            <div class="sub header">{{ APPLICATION_ABSTRACT }}</div>
+            <div class="sub header">
+              {{ APPLICATION_ABSTRACT }}
+            </div>
           </div>
         </h2>
       </div>
     </div>
     <div class="row">
       <div class="six wide column">
-        <h3 class="ui horizontal divider header">CONNEXION</h3>
+        <h3 class="ui horizontal divider header">
+          CONNEXION
+        </h3>
 
-        <div v-if="form.errors" class="ui warning message">
+        <div
+          v-if="form.errors"
+          class="ui warning message"
+        >
           <div class="header">
             Les informations d'identification sont incorrectes.
           </div>
           NB: Seuls les comptes actifs peuvent se connecter.
         </div>
 
-        <form class="ui form" role="form" type="post" @submit.prevent="login">
+        <form
+          class="ui form"
+          role="form"
+          type="post"
+          @submit.prevent="login"
+        >
           <div class="ui stacked secondary segment">
             <div class="six field required">
               <div class="ui left icon input">
-                <i class="user icon"></i>
+                <i class="user icon" />
                 <input
                   v-model="username_value"
                   type="text"
                   name="username"
                   placeholder="Utilisateur"
-                />
+                >
               </div>
             </div>
             <div class="six field required">
               <div class="ui left icon input">
-                <i class="lock icon"></i>
+                <i class="lock icon" />
                 <input
                   v-model="password_value"
                   type="password"
                   name="password"
                   placeholder="Mot de passe"
-                />
+                >
               </div>
             </div>
-            <button class="ui fluid large teal submit button" type="submit">
+            <button
+              class="ui fluid large teal submit button"
+              type="submit"
+            >
               Login
             </button>
           </div>
@@ -58,7 +76,7 @@
 
 <script>
 export default {
-  name: "Login",
+  name: 'Login',
   data() {
     return {
       username_value: null,
@@ -80,32 +98,32 @@ export default {
       return this.$store.state.configuration.VUE_APP_APPLICATION_ABSTRACT;
     },
   },
+
+  mounted() {
+    if (this.$store.state.user) {
+      this.$store.commit(
+        'DISPLAY_MESSAGE',
+        "Vous êtes déjà connecté, vous allez être redirigé vers la page d'accueil."
+      );
+      setTimeout(() => this.$router.push('/'), 3100);
+    }
+  },
   methods: {
     login() {
       this.$store
-        .dispatch("LOGIN", {
+        .dispatch('LOGIN', {
           username: this.username_value,
           password: this.password_value,
         })
         .then((status) => {
           if (status === 200) {
             this.form.errors = null;
-          } else if (status === "error") {
+          } else if (status === 'error') {
             this.form.errors = status;
           }
         })
         .catch();
     },
   },
-
-  mounted() {
-    if (this.$store.state.user) {
-      this.$store.commit(
-        "DISPLAY_MESSAGE",
-        {comment :"Vous êtes déjà connecté, vous allez être redirigé vers la page d'accueil."}
-      );
-      setTimeout(() => this.$router.push("/"), 3100);
-    }
-  },
 };
 </script>
\ No newline at end of file
diff --git a/vue.config.js b/vue.config.js
index f9d74727c971c84a1b1afb45270b6a2162a71b69..f2c618d55dcf8dd40d435ad25287d12b37171dfa 100644
--- a/vue.config.js
+++ b/vue.config.js
@@ -1,46 +1,46 @@
-const webpack = require('webpack')
-const fs = require('fs')
-const packageJson = fs.readFileSync('./package.json')
-const version = JSON.parse(packageJson).version || 0
+const webpack = require('webpack');
+const fs = require('fs');
+const packageJson = fs.readFileSync('./package.json');
+const version = JSON.parse(packageJson).version || 0;
 module.exports = {
-    publicPath: '/geocontrib/',
-    devServer: {
-        proxy: {
-            '^/api': {
-                target: 'https://geocontrib.dev.neogeo.fr/api',
-                ws: true,
-                changeOrigin: true
-            }
-        }
+  publicPath: '/geocontrib/',
+  devServer: {
+    proxy: {
+      '^/api': {
+        target: 'https://geocontrib.dev.neogeo.fr/api',
+        ws: true,
+        changeOrigin: true
+      }
+    }
+  },
+  pwa: {
+    workboxPluginMode: 'InjectManifest',
+    workboxOptions: {
+      swSrc: 'src/service-worker.js',
+      exclude: [
+        /\.map$/, 
+        /config\/config.*\.json$/,
+        /manifest\.json$/ 
+      ],
     },
-    pwa: {
-        workboxPluginMode: 'InjectManifest',
-        workboxOptions: {
-            swSrc: 'src/service-worker.js',
-            exclude: [
-                /\.map$/, 
-                /config\/config.*\.json$/,
-                /manifest\.json$/ 
-            ],
-        },
-        iconPaths: {
-            faviconSVG: null,
-            favicon32: null,
-            favicon16: null,
-            appleTouchIcon: null,
-            maskIcon: null,
-            msTileImage: null,
-          },
-        themeColor: '#1da025'
-      },
-    configureWebpack: {
-        plugins: [
-            new webpack.DefinePlugin({
-                'process.env': {
-                    PACKAGE_VERSION: '"' + version + '"'
-                }
-            })
-        ]
+    iconPaths: {
+      faviconSVG: null,
+      favicon32: null,
+      favicon16: null,
+      appleTouchIcon: null,
+      maskIcon: null,
+      msTileImage: null,
     },
+    themeColor: '#1da025'
+  },
+  configureWebpack: {
+    plugins: [
+      new webpack.DefinePlugin({
+        'process.env': {
+          PACKAGE_VERSION: '"' + version + '"'
+        }
+      })
+    ]
+  },
 // the rest of your original module.exports code goes here
-}
+};