diff --git a/.gitignore b/.gitignore
index 21877928fcb83cbc97c8024b638c0e63130ed025..d303f30d012896035f50862c86f60c250f226b82 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,6 +14,5 @@ public
 galaxy-tools-tk.txt
 tmp-exp-files/
 .venv
-
 *~
-deploy-manually.sh
\ No newline at end of file
+deploy-manually.sh
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 10bcc564a18d44dcddf6da4177e4c6cbd92576de..32942824da4a3d8bea8c29bf0e133f977f30162f 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -78,6 +78,9 @@ services:
       --set galaxy.url=${GALAXY_BASE_URL}
       --set galaxy.key=${GALAXY_API_KEY}
       --set redis.auth.password=${REDIS_PASSWORD}
+      --set django.secretKey=${SECRET_KEY}
+      --set django.hostLabel=${HOSTLABEL}
+      --set celery.replicaCount=${CELERY_REPLICA_COUNT}
       ${CI_COMMIT_REF_SLUG} ./chart/
 
 stages:
@@ -111,7 +114,7 @@ test-server:
     - poetry run pytest --cov-report term-missing --cov=.
 
 test-client:
-  image: node:15.14.0-buster
+  image: node:16.11.1-buster
   stage: test
   # only:
   #   refs:
@@ -160,6 +163,13 @@ build-client:
   needs:
     - test-client
 
+build-cronjob:
+  extends: .docker-build
+  variables:
+    DOCKERFILE: ./server/Dockerfile.cronJob
+    CONTEXT: ./server
+    IMAGE_NAME: cronjob
+
 deploy-dev:
   extends: .deploy
   variables:
@@ -168,6 +178,8 @@ deploy-dev:
     PUBLIC_URL: "cc-qtl.${CI_COMMIT_REF_SLUG}.pasteur.cloud"
     DEBUG: "True"
     NODE_ENV: development
+    HOSTLABEL: cc-qtl-dev
+    CELERY_REPLICA_COUNT: 1
   environment:
     name: "k8sdev-01/${CI_COMMIT_REF_SLUG}"
     url: "https://cc-qtl.${CI_COMMIT_REF_SLUG}.pasteur.cloud"
@@ -178,6 +190,7 @@ deploy-dev:
     - build-server
     - build-client
     - build-static
+    - build-cronjob
 
 deploy-prod:
   extends: .deploy
@@ -186,7 +199,10 @@ deploy-prod:
     CI_DEBUG_TRACE: "false"
     NAMESPACE: "cc-qtl-prod"
     PUBLIC_URL: "cc-qtl.pasteur.cloud"
-    DEBUG: "True"
+    DEBUG: "False"
+    HOSTLABEL: cc-qtl-prod
+    CELERY_REPLICA_COUNT: 3
+
   environment:
     name: "k8sprod-02/${CI_COMMIT_REF_SLUG}"
     url: "https://cc-qtl.pasteur.cloud"
@@ -197,6 +213,7 @@ deploy-prod:
     - build-server
     - build-client
     - build-static
+    - build-cronjob
 
 delete-helm-release:
   except:
@@ -213,6 +230,20 @@ delete-helm-release:
   script:
     - echo "Removing $CI_COMMIT_REF_SLUG"
     - helm delete -n ${NAMESPACE} ${CI_COMMIT_REF_SLUG}
+
+delete-helm-release-prod:
+  stage: deploy
+  when: manual
+  image: alpine/helm:3.2.4
+  variables:
+    GIT_STRATEGY: none # important to not checkout source when branch is deleted
+    NAMESPACE: "cc-qtl-prod"
+  environment:
+    name: "k8sprod-02/${CI_COMMIT_REF_SLUG}"
+    action: stop
+  script:
+    - echo "Removing $CI_COMMIT_REF_SLUG"
+    - helm delete -n ${NAMESPACE} ${CI_COMMIT_REF_SLUG}
   only:
     refs:
-      - dev
+      - master
diff --git a/chart/templates/_helpers.tpl b/chart/templates/_helpers.tpl
index 96d1b62632d2c40b3832941868f8495e12381da1..8b3eacc46a4957f28d5ddc63bb0766e7f17a2d64 100644
--- a/chart/templates/_helpers.tpl
+++ b/chart/templates/_helpers.tpl
@@ -84,3 +84,11 @@ fullname for celery
 {{- define "chart.fullnameCelery" -}}
 {{- printf "%s-%s" (include "chart.fullname" .) .Values.celery.name }}
 {{- end }}
+
+
+{{/*
+fullname for cronjob clean tmp files
+*/}}
+{{- define "chart.fullnameCleanTmpFiles" -}}
+{{- printf "%s-clean-tmp-files" (include "chart.fullname" .) }}
+{{- end }}
diff --git a/chart/templates/cron-job.yaml b/chart/templates/cron-job.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..c453e24c361fafc8bf5922b1fdb8148149a45245
--- /dev/null
+++ b/chart/templates/cron-job.yaml
@@ -0,0 +1,35 @@
+apiVersion: batch/v1beta1
+kind: CronJob
+metadata:
+  name:  {{ include "chart.fullnameCleanTmpFiles" . }}
+  labels:
+    {{- include "chart.labels" . | nindent 4 }}
+    role: "clean-tmp-files"
+spec:
+  successfulJobsHistoryLimit: 1
+  failedJobsHistoryLimit: 2
+  schedule: "0 */2 * * *"
+  concurrencyPolicy: Forbid
+  jobTemplate:
+    spec:
+      template:
+        spec:
+          restartPolicy: Never
+          {{- with .Values.imagePullSecrets }}
+          imagePullSecrets:
+            {{- toYaml . | nindent 12 }}
+          {{- end }}
+          containers:
+          - name: {{ printf "%s-clean-tmp-files" .Release.Name }}
+            image: {{ printf "%s/cronjob/%s:%s" .Values.CI_REGISTRY_IMAGE .Release.Name .Values.image.tag }}
+            imagePullPolicy: Always
+            volumeMounts:
+              - name: server-static
+                mountPath: /app/static
+            securityContext:
+              {{- toYaml .Values.securityContext | nindent 14 }}
+          volumes:
+            - name: server-static
+              persistentVolumeClaim:
+                claimName: "server-static"
+
diff --git a/chart/templates/deployment-celery.yaml b/chart/templates/deployment-celery.yaml
index 6a62ea606fa66bd31db49a8c9fc6d9320f2630c7..2254e8e1eb296545aac45b1755066e29af8e49f9 100644
--- a/chart/templates/deployment-celery.yaml
+++ b/chart/templates/deployment-celery.yaml
@@ -44,24 +44,38 @@ spec:
           {{- toYaml .Values.securityContext | nindent 12 }}
         env:
           - name: REDIS_HOST
-            value: {{ printf "redis://:%s@%s-redis-master" .Values.redis.auth.password .Release.Name }}
+            valueFrom:
+              secretKeyRef:
+                name: {{ printf "%s-credentials" .Release.Name }}
+                key: redis_host
           - name: GALAXY_BASE_URL
             value: {{ .Values.galaxy.url }}
           - name: GALAXY_API_KEY
-            value: {{ .Values.galaxy.key }}
+            valueFrom:
+              secretKeyRef:
+                name: {{ printf "%s-credentials" .Release.Name }}
+                key: galaxy_api_key
           - name: DATABASE_HOST
             value: {{ printf "%s-postgresql" .Release.Name }}
           - name: DATABASE_NAME
             value: {{ .Values.postgresql.postgresqlDatabase}}
           - name: DATABASE_PASSWORD
-            value: {{ .Values.postgresql.postgresqlPassword }}
+            valueFrom:
+              secretKeyRef:
+                name: {{ printf "%s-credentials" .Release.Name }}
+                key: database_password
           - name: DATABASE_USER
-            value: "postgres"
+            valueFrom:
+              secretKeyRef:
+                name: {{ printf "%s-credentials" .Release.Name }}
+                key: database_user
         resources:
           {{- toYaml .Values.celery.resources | nindent 12 }}
         volumeMounts:
           - name: tmp-exp-files
             mountPath: /tmp-exp-files
+          - name : server-static
+            mountPath: /app/django-static
       {{- with .Values.nodeSelector }}
       nodeSelector:
         {{- toYaml . | nindent 8 }}
@@ -76,7 +90,11 @@ spec:
       {{- end }}
       volumes:
         - name: server-static
-          emptyDir: {}
+          persistentVolumeClaim:
+            claimName: "server-static"
+
+        # - name: server-static
+        #   emptyDir: {}
         - name: tmp-exp-files
           persistentVolumeClaim:
             claimName: {{ printf "tmp-exp-files-%s" .Release.Name}}
diff --git a/chart/templates/deployment-django.yaml b/chart/templates/deployment-django.yaml
index abdb613a93708c0c387282e33c11220f61beaada..4e7a5b41764e384bcb010d76420b9c1862f328c6 100644
--- a/chart/templates/deployment-django.yaml
+++ b/chart/templates/deployment-django.yaml
@@ -60,17 +60,26 @@ spec:
           - name: DATABASE_NAME
             value: {{ .Values.postgresql.postgresqlDatabase}}
           - name: DATABASE_PASSWORD
-            value: {{ .Values.postgresql.postgresqlPassword }}
+            valueFrom:
+              secretKeyRef:
+                name: {{ printf "%s-credentials" .Release.Name }}
+                key: database_password
           - name: DATABASE_USER
-            value: "postgres"
+            valueFrom:
+              secretKeyRef:
+                name: {{ printf "%s-credentials" .Release.Name }}
+                key: database_user
           - name: GALAXY_BASE_URL
             value: {{ .Values.galaxy.url }}
           - name: GALAXY_API_KEY
-            value: {{ .Values.galaxy.key }}
+            valueFrom:
+              secretKeyRef:
+                name: {{ printf "%s-credentials" .Release.Name }}
+                key: galaxy_api_key
           - name: SECRET_KEY
             valueFrom:
               secretKeyRef:
-                name: backend-secret
+                name: {{ printf "%s-credentials" .Release.Name }}
                 key: secret_key
           - name: ALLOWED_HOSTS
             value: "*"
@@ -78,6 +87,8 @@ spec:
             value: prod
           - name: REDIS_HOST
             value: {{ printf "redis://:%s@%s-redis-master" .Values.redis.auth.password .Release.Name }}
+          - name: HOSTLABEL
+            value: {{ .Values.django.hostLabel }}
         ports:
           - name: http
             containerPort: 8000
@@ -118,8 +129,8 @@ spec:
         {{- toYaml . | nindent 8 }}
       {{- end }}
       volumes:
-        - name: server-static
-          emptyDir: {}
+        # - name: server-static
+        #   emptyDir: {}
         - name: tmp-exp-files
           persistentVolumeClaim:
             claimName: {{ printf "tmp-exp-files-%s" .Release.Name}}
diff --git a/chart/templates/deployment-nuxt.yaml b/chart/templates/deployment-nuxt.yaml
index 78c157a50c6c6cc0f582fe6ce9c2284ac057e633..cf7721f2049b38229f899bf5ebda46651b8e46ee 100644
--- a/chart/templates/deployment-nuxt.yaml
+++ b/chart/templates/deployment-nuxt.yaml
@@ -73,8 +73,3 @@ spec:
       tolerations:
         {{- toYaml . | nindent 8 }}
       {{- end }}
-      volumes:
-        - name: backend-secret
-          secret:
-            secretName: backend-secret
-
diff --git a/chart/templates/pvc-django-static.yaml b/chart/templates/pvc-django-static.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..418301b50f21cd5e34ef89b5527ff169124dc320
--- /dev/null
+++ b/chart/templates/pvc-django-static.yaml
@@ -0,0 +1,11 @@
+apiVersion: v1
+kind: PersistentVolumeClaim
+metadata:
+  name: "server-static"
+spec:
+  accessModes:
+    - ReadWriteMany
+  resources:
+    requests:
+      storage: 1Gi
+status: {}
\ No newline at end of file
diff --git a/chart/templates/secret-credentials.yaml b/chart/templates/secret-credentials.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..0ffff8badc4168f2ed9d5b7845a0464daceb7e88
--- /dev/null
+++ b/chart/templates/secret-credentials.yaml
@@ -0,0 +1,11 @@
+apiVersion: v1
+kind: Secret
+metadata:
+  name: {{ printf "%s-credentials" .Release.Name }}
+type: Opaque
+data:
+  secret_key: {{ .Values.django.secretKey | b64enc | quote }}
+  database_user: {{ .Values.postgresql.postgresqlUsername | b64enc | quote }}
+  database_password: {{ .Values.postgresql.postgresqlPassword | b64enc | quote }}
+  galaxy_api_key : {{ .Values.galaxy.key | b64enc | quote }}
+  redis_host: {{ printf "redis://:%s@%s-redis-master" .Values.redis.auth.password .Release.Name | b64enc | quote }}
\ No newline at end of file
diff --git a/chart/values.yaml b/chart/values.yaml
index e2cd0a2226683e42b994f5d93352deea9981823c..4268b0018ddae10b705d7c73861c711a4d956c34 100644
--- a/chart/values.yaml
+++ b/chart/values.yaml
@@ -190,7 +190,7 @@ redis:
   # volumePermissions:
   #   enabled: true
   replica:
-    replicaCount: 1
+    replicaCount: 2
 
 galaxy:
   url: ""
@@ -205,5 +205,5 @@ celery:
       memory: "1Gi"
       cpu: "500m"
     limits:
-      memory: "3Gi"
+      memory: "2Gi"
       cpu: "1000m"
diff --git a/client-nuxt/Dockerfile b/client-nuxt/Dockerfile
index b3e875e6206f634ede7b3facbbd8be49e7e744a2..07496eb233caa15e4d8fb8d8c171291ff7c741d4 100644
--- a/client-nuxt/Dockerfile
+++ b/client-nuxt/Dockerfile
@@ -1,4 +1,4 @@
-FROM node:15.14.0-buster-slim AS dev
+FROM node:16.11.1-buster-slim AS dev
 
 RUN apt-get update && apt-get install -y git python3 make g++
 
@@ -6,7 +6,7 @@ WORKDIR /usr/src/app/
 
 RUN chown -R node:node /usr/src/app
 
-COPY --chown=node:node package*.json yarn.lock /usr/src/app/
+COPY --chown=node:node package*.json yarn* /usr/src/app/
 
 USER node
 
@@ -21,7 +21,7 @@ CMD ["yarn", "dev"]
 
 
 # PROD
-FROM node:15.14.0-buster-slim as prod
+FROM node:16.11.1-buster-slim as prod
 
 # RUN apt-get update
 
diff --git a/client-nuxt/components/AddExperimentForm.vue b/client-nuxt/components/AddExperimentForm.vue
index cdcbcb2cfd87bc207fb6e55b64121ab299eb4088..bad50a568cbe32b1c56a675363fbb8736ba4974c 100644
--- a/client-nuxt/components/AddExperimentForm.vue
+++ b/client-nuxt/components/AddExperimentForm.vue
@@ -1,106 +1,171 @@
 <template>
-  <div>
-    <error-alert v-if="error" :error-message="error"></error-alert>
-    <!-- <div>{{ projectId }}</div> -->
+  <v-card>
     <ValidationObserver
-      ref="observer"
-      v-slot="{ invalid, validated, handleSubmit }"
+      ref="experimentFormObserver"
+      v-slot="{
+        invalid,
+        /* validated */
+      }"
     >
-      <form>
-        <ValidationProvider
-          v-slot="{ errors, valid }"
-          name="Name"
-          rules="required|max:50"
-        >
-          <v-text-field
-            v-model="experiment.name"
-            :counter="50"
-            :error-messages="errors"
-            :success="valid"
-            label="Name"
-            required
-          ></v-text-field>
-        </ValidationProvider>
-        <ValidationProvider
-          v-slot="{ errors, valid }"
-          name="Experiment description"
-          rules="required"
-        >
-          <v-textarea
-            v-model="experiment.description"
-            name="description"
-            filled
-            label="Description"
-            auto-grow
-            counter
-            clearable
-            :error-messages="errors"
-            :success="valid"
-          ></v-textarea>
-        </ValidationProvider>
-        <!-- upload files -->
-        <ValidationProvider
-          v-slot="{ errors, valid }"
-          name="Experiement file input"
-          rules="required"
-        >
-          <v-file-input
-            v-model="experiment.file"
-            accept=".csv"
-            label="File input"
-            :success="valid"
-            :error-messages="errors"
-            @change="readFile"
-          ></v-file-input>
-        </ValidationProvider>
-        <v-simple-table>
-          <thead>
-            <tr>
-              <th
-                v-for="item in preview.headers"
-                :key="item.value"
-                class="text-left"
+      <!-- @submit.prevent="submit" -->
+      <v-form @submit.prevent="submit">
+        <v-card-text>
+          <ValidationProvider
+            v-slot="{ valid, errors }"
+            mode="eager"
+            name="Name"
+            rules="required|max:50"
+          >
+            <v-text-field
+              v-model="computedExperimentName"
+              :counter="50"
+              :success="valid"
+              :error-messages="errors"
+              label="Experiment name"
+              required
+            ></v-text-field>
+          </ValidationProvider>
+          <ValidationProvider
+            v-slot="{ valid, errors }"
+            mode="eager"
+            name="Experiment description"
+            rules="required"
+          >
+            <v-textarea
+              v-model="computedExperimentDescription"
+              name="description"
+              filled
+              label="Experiment description"
+              auto-grow
+              counter
+              clearable
+              :success="valid"
+              :error-messages="errors"
+            ></v-textarea>
+          </ValidationProvider>
+          <!-- upload files -->
+          <v-card flat class="d-flex flex-row">
+            <v-card flat class="flex-grow-1 mx-2 align-self-baseline">
+              <ValidationProvider
+                v-slot="{ valid, errors }"
+                name="Experiement file input"
+                rules="required"
               >
-                {{ item.text }}
-              </th>
-            </tr>
-          </thead>
-          <tbody>
-            <tr v-for="row in preview.content" :key="row.id">
-              <td v-for="cell in row.row" :key="cell.id">
-                {{ cell.text }}
-              </td>
-            </tr>
-          </tbody>
-          <tfoot>
-            <tr>
-              <td
-                v-for="(metadata, index) in experimentMetaData"
-                :key="metadata.colIndex"
-              >
-                <select-variable-category
-                  v-model="experimentMetaData[index]"
-                  :variable-categories="variableCategories"
-                />
-              </td>
-            </tr>
-          </tfoot>
-        </v-simple-table>
+                <v-file-input
+                  v-model="computedExperimentFile"
+                  accept=".csv"
+                  label="Experiment file input"
+                  persistent-hint
+                  hint="Input file must be csv"
+                  :success="valid"
+                  :error-messages="errors"
+                ></v-file-input>
+              </ValidationProvider>
+            </v-card>
+            <v-card
+              flat
+              class="flex-grow-0 flex-shrink-1 mx-2 align-self-baseline"
+            >
+              <v-dialog transition="dialog-bottom-transition" fullscreen>
+                <template v-slot:activator="{ on, attrs }">
+                  <v-btn color="primary" icon v-bind="attrs" v-on="on"
+                    ><v-icon>mdi-help-circle</v-icon></v-btn
+                  >
+                </template>
+                <template v-slot:default="dialog">
+                  <v-card>
+                    <v-toolbar flat class="mb-6">
+                      <v-toolbar-title class="text-h4">
+                        General help on experiment input file
+                      </v-toolbar-title>
+                      <v-spacer></v-spacer>
+                      <v-toolbar-items>
+                        <v-btn
+                          color="primary"
+                          text
+                          @click="dialog.value = false"
+                        >
+                          Close
+                        </v-btn>
+                      </v-toolbar-items></v-toolbar
+                    >
+                    <v-card-text>
+                      <experiment-file-input-help></experiment-file-input-help>
+                    </v-card-text>
+                  </v-card>
+                </template>
+              </v-dialog>
+            </v-card>
+          </v-card>
+          <v-simple-table class="my-4">
+            <thead>
+              <tr>
+                <th
+                  v-for="item in preview.headers"
+                  :key="item.value"
+                  class="text-left"
+                >
+                  {{ item.text }}
+                </th>
+              </tr>
+            </thead>
+            <tbody>
+              <tr v-for="row in preview.content" :key="row.id">
+                <td v-for="cell in row.row" :key="cell.id">
+                  {{ cell.text }}
+                </td>
+              </tr>
+            </tbody>
+            <tfoot>
+              <tr>
+                <td
+                  v-for="(metadata, index) in experimentMetadata"
+                  :key="metadata.colIndex"
+                >
+                  <ValidationProvider
+                    :ref="'phenotypeCategoryProvider-' + index"
+                    :name="'phenotype-metadata-' + index"
+                    rules="requiredpheno"
+                  >
+                    <select-phenotype-category
+                      v-model="computedPhenotypeCategory[index]"
+                      :phenotype-categories="phenotypeCategories"
+                      :phenotype-category-permissions="
+                        phenotypeCategoryPermissions
+                      "
+                      :phenotype-category-options="phenotypeCategoryOptions"
+                      @update-phenotype-categories="
+                        $emit('update-phenotype-categories')
+                      "
+                    />
+                  </ValidationProvider>
+                </td>
+              </tr>
+            </tfoot>
+          </v-simple-table>
 
-        <!-- end upload files -->
-        <v-btn
-          color="primary"
-          class="mr-4"
-          :disabled="invalid || !validated"
-          @click="handleSubmit(submit)"
-          >submit</v-btn
-        >
-      </form>
+          <!-- end upload files -->
+        </v-card-text>
+        <v-card-text>
+          <error-alert v-if="error" :error-message="error"></error-alert
+        ></v-card-text>
+        <v-card-actions>
+          <v-btn color="error" @click="clearExperimentForm">clear</v-btn>
+          <!-- :disabled="invalid || !validated" -->
+          <v-btn type="submit" color="primary" class="mr-4" :disabled="invalid"
+            >submit</v-btn
+          >
+          <!-- <v-btn color="primary" class="mr-4" @click="submit">submit</v-btn> -->
+          <!-- <v-btn @click="tryValidate()">validate ? </v-btn> -->
+        </v-card-actions>
+      </v-form>
     </ValidationObserver>
-  </div>
+  </v-card>
 </template>
 
 <script>
+import { mapActions, mapMutations } from 'vuex'
+
 import { required, max } from 'vee-validate/dist/rules'
 import {
   extend,
@@ -109,8 +174,9 @@ import {
   setInteractionMode,
 } from 'vee-validate'
 import ErrorAlert from '@/components/ErrorAlert'
-import SelectVariableCategory from '@/components/SelectVariableCategory'
+import SelectPhenotypeCategory from '@/components/SelectPhenotypeCategory'
 import Papa from 'papaparse'
+import ExperimentFileInputHelp from '@/components/ExperimentFileInputHelp.vue'
 
 setInteractionMode('aggressive')
 
@@ -119,6 +185,16 @@ extend('required', {
   message: '{_field_} can not be empty',
 })
 
+extend('requiredpheno', {
+  validate(value) {
+    return {
+      required: true,
+      valid: !['', null, undefined].includes(value.id),
+    }
+  },
+  computesRequired: true,
+})
+
 extend('max', {
   ...max,
   message: '{_field_} may not be greater than {length} characters',
@@ -128,24 +204,25 @@ export default {
     ValidationProvider,
     ValidationObserver,
     ErrorAlert,
-    SelectVariableCategory,
+    SelectPhenotypeCategory,
+    ExperimentFileInputHelp,
   },
   props: {
     projectId: { type: Number, required: true },
-    variableCategories: { type: Array, default: () => [] },
+    phenotypeCategories: { type: Array, default: () => [] },
+    phenotypeCategoryPermissions: { type: Set, default: () => new Set() },
+    phenotypeCategoryOptions: { type: Object, default: () => ({}) },
+    experimentName: { type: String, default: '' },
+    experimentFile: { type: File, default: null },
+    experimentDescription: { type: String, default: '' },
+    experimentMetadata: { type: Array, default: () => [] },
   },
   data() {
     return {
       error: null,
-      experiment: {
-        name: '',
-        description: '',
-        file: null,
-      },
       users: [],
       preview: { headers: [], content: [] },
-      experimentMetaData: [],
-      initVariableCategory: {
+      initPhenotypeCategory: {
         dataclass: null,
         datatype: null,
         location: null,
@@ -156,97 +233,159 @@ export default {
       },
     }
   },
+  computed: {
+    computedExperimentName: {
+      get() {
+        return this.experimentName
+      },
+      set(name) {
+        this.$emit('update:experiment-name', name)
+      },
+    },
+    computedExperimentDescription: {
+      get() {
+        return this.experimentDescription
+      },
+      set(desc) {
+        this.$emit('update:experiment-description', desc)
+      },
+    },
+    computedExperimentFile: {
+      get() {
+        return this.experimentFile
+      },
+      set(file) {
+        this.$emit('update:experiment-file', file)
+      },
+    },
+    computedPhenotypeCategory: {
+      get() {
+        return this.experimentMetadata
+      },
+      set(metadata) {
+        this.$emit('update:experiment-metadata', metadata)
+      },
+    },
+    hasExperimentFile() {
+      return this.computedExperimentFile !== null
+    },
+  },
+  watch: {
+    hasExperimentFile(newHasFile) {
+      this.readFile()
+    },
+  },
+
+  created() {
+    if (!this.$store.getters.getExperimentToAdd(this.projectId)) {
+      this.initExperimentToAdd(this.projectId)
+    }
+    if (this.hasExperimentFile) {
+      this.readFile()
+    }
+  },
   methods: {
+    // tryValidate() {
+    //   this.$refs.experimentFormObserver
+    //     .validate()
+    //     .then((success) => console.log(success))
+    //     .catch((error) => console.log(error))
+    // },
+    clearExperimentForm() {
+      this.clearExperiment(this.projectId)
+      const {
+        experiment: { name, description, file },
+        experimentMetadata,
+      } = this.$store.getters.getExperimentToAdd(this.projectId)
+      this.computedExperimentName = name
+      this.computedExperimentDescription = description
+      this.computedExperimentFile = file
+      this.computedPhenotypeCategory = experimentMetadata
+    },
+
     submit() {
-      this.$refs.observer.validate().then((success) => {
+      this.$refs.experimentFormObserver.validate().then((success) => {
         this.addExperiment()
       })
     },
 
     readFile() {
-      // console.log(Papa)
-      Papa.parse(this.experiment.file, {
-        preview: 6,
-        complete: async (results) => {
-          const sliceIndex = 4
-          // headers
-          const headers = results.data[0]
-            .slice(sliceIndex)
-            .map((item, index) => ({
-              text: item,
-              value: item,
-              type: null,
-              colIndex: index + sliceIndex,
-            }))
-          this.preview.headers = headers
+      if (this.computedExperimentFile) {
+        Papa.parse(this.computedExperimentFile, {
+          preview: 6,
+          complete: async (results) => {
+            const sliceIndex = 4
+            // headers
+            const headers = results.data[0]
+              .slice(sliceIndex)
+              .map((item, index) => ({
+                text: item,
+                value: item,
+                type: null,
+                colIndex: index + sliceIndex,
+              }))
+            this.preview.headers = headers
 
-          // content
-          const content = results.data.slice(1).map((row, i) => {
-            return {
-              id: i,
-              row: row
-                .slice(sliceIndex)
-                .map((item, j) => ({ id: headers[j].value, text: item })),
-            }
-          })
-          this.preview.content = content
+            // content
+            const content = results.data.slice(1).map((row, i) => {
+              return {
+                id: i,
+                row: row
+                  .slice(sliceIndex)
+                  .map((item, j) => ({ id: headers[j].value, text: item })),
+              }
+            })
+            this.preview.content = content
 
-          try {
-            const response = await this.$axios.$post(
-              '/api/variable-categories-resolve/',
-              headers.map((item) => {
-                const [
-                  name,
-                  dataclass,
-                  datatype,
-                  nature,
-                  location,
-                ] = item.value.split('_', 5)
-                return {
-                  colid: item.colIndex,
-                  dataclass,
-                  datatype,
-                  location,
-                  name,
-                  nature,
+            try {
+              const response = await this.$axios.$post(
+                '/api/phenotype-categories-resolve/',
+                headers.map((item) => {
+                  return {
+                    colid: item.colIndex,
+                    name: item.value,
+                  }
+                })
+              )
+              const experimentMetadata = response.map((item, index) => {
+                const baseMetadata = {
+                  colIndex: item.colid,
+                  colName: headers[item.colid - sliceIndex].text,
                 }
-              })
-            )
-            this.experimentMetaData = response.map((item) => {
-              const baseMetadata = {
-                colIndex: item.colid,
-                colName: headers[item.colid - sliceIndex].text,
-              }
-              if (item.id) {
-                return {
-                  ...item,
-                  ...baseMetadata,
+                if (this.experimentMetadata[index]?.id) {
+                  return { ...this.experimentMetadata[index] }
                 }
-              } else {
-                return {
-                  ...this.initVariableCategory,
-                  ...baseMetadata,
+                if (item.id) {
+                  return {
+                    ...item,
+                    ...baseMetadata,
+                  }
+                } else {
+                  return {
+                    ...this.initPhenotypeCategory,
+                    ...baseMetadata,
+                  }
                 }
-              }
-            })
-          } catch (error) {}
-        },
-      })
+              })
+              this.$emit('update:experiment-metadata', experimentMetadata)
+            } catch (error) {}
+          },
+        })
+      } else {
+        this.preview = { headers: [], content: [] }
+        this.$emit('update:experiment-metadata', [])
+      }
     },
-
     async addExperiment() {
       try {
         const formData = new FormData()
-        // formData.append('file', this.file)
-        // formData.append('experiment', this.experiment)
-        for (const entry of Object.entries(this.experiment)) {
-          formData.append(entry[0], entry[1])
-        }
-
+        formData.append('name', this.experimentName)
+        formData.append('description', this.experimentDescription)
+        formData.append('file', this.experimentFile)
         formData.append(
           'experiment-metadata',
           // transform dataType array as string. Not super clean. Sorry :(
-          JSON.stringify(this.experimentMetaData)
+          JSON.stringify(this.experimentMetadata)
         )
         // formData.append();
         const { id: experimentId } = await this.$axios.$post(
@@ -258,22 +397,34 @@ export default {
             },
           }
         )
+        this.updateExperimentsCount()
+        this.$emit('update-experiments')
         this.$router.push({
           name: 'projects-id-experiments-experimentId',
           params: { projectId: this.projectId, experimentId },
         })
       } catch (err) {
         const { response } = err
-        if (response.status === 400 && response.data.length === 1) {
+
+        if (response?.data?.non_field_errors) {
+          this.error = response.data.non_field_errors[0]
+        } else if (response.status === 400 && response.data.length === 1) {
           this.error = response.data[0]
         } else {
           this.error = err.message
         }
+      } finally {
+        this.clearExperiment(this.$route.params.id)
       }
     },
-    variableTypeLabel(varType) {
-      return varType.label + ' types'
-    },
+
+    ...mapMutations({
+      initExperimentToAdd: 'initExperimentToAdd',
+      clearExperiment: 'clearExperiment',
+    }),
+    ...mapActions({
+      updateExperimentsCount: 'updateExperimentsCount',
+    }),
   },
 }
 </script>
diff --git a/client-nuxt/components/AddProjectForm.vue b/client-nuxt/components/AddProjectForm.vue
index e1fed94c04ecb8a59c54742309150916d4f2448f..4dc532b4cbf0957cab42b854f100520b41237a66 100644
--- a/client-nuxt/components/AddProjectForm.vue
+++ b/client-nuxt/components/AddProjectForm.vue
@@ -1,11 +1,11 @@
 <template>
-  <div>
+  <v-card flat>
     <error-alert v-if="error" :error-message="error"></error-alert>
-    <ValidationObserver ref="observer" v-slot="{}">
-      <form>
+    <ValidationObserver ref="observer" v-slot="{ invalid }">
+      <v-form @submit.prevent="submit">
         <ValidationProvider
           v-slot="{ errors }"
-          name="Name"
+          name="name"
           rules="required|max:50"
         >
           <v-text-field
@@ -16,7 +16,11 @@
             required
           ></v-text-field>
         </ValidationProvider>
-        <ValidationProvider v-slot="{ errors }" name="Name" rules="required">
+        <ValidationProvider
+          v-slot="{ errors }"
+          name="description"
+          rules="required"
+        >
           <v-textarea
             v-model="project.description"
             name="description"
@@ -29,14 +33,17 @@
           ></v-textarea>
         </ValidationProvider>
 
-        <v-btn color="primary" class="mr-4" @click="submit">submit</v-btn>
-        <v-btn color="error" :to="'/projects'">Cancel</v-btn>
-      </form>
+        <v-btn type="submit" color="primary" class="mr-4" :disabled="invalid"
+          >Submit</v-btn
+        >
+        <v-btn color="error" @click="$emit('cancel')">Cancel</v-btn>
+      </v-form>
     </ValidationObserver>
-  </div>
+  </v-card>
 </template>
 
 <script>
+import { mapActions } from 'vuex'
 import { required, max } from 'vee-validate/dist/rules'
 import {
   extend,
@@ -49,7 +56,7 @@ setInteractionMode('aggressive')
 
 extend('required', {
   ...required,
-  message: '{_field_} can not be empty',
+  message: 'The {_field_} can not be empty',
 })
 
 extend('max', {
@@ -62,30 +69,69 @@ export default {
     ValidationObserver,
     ErrorAlert,
   },
+  props: {
+    project: {
+      type: Object,
+      default: () => ({ project_name: '', description: '' }),
+    },
+    update: { type: Boolean, default: () => false },
+  },
   data() {
     return {
       error: null,
-      project: {
-        project_name: '',
-        description: '',
-      },
       users: [],
     }
   },
   methods: {
     submit() {
       this.$refs.observer.validate().then((success) => {
-        this.addProject()
+        if (this.update) {
+          this.updateProject()
+        } else {
+          this.addProject()
+        }
       })
     },
     async addProject() {
       try {
         await this.$axios.$post('/api/projects/', this.project)
+        this.updateProjectsCount()
         this.$router.push({ name: 'projects' })
       } catch (err) {
-        this.error = err.message
+        if (err?.response?.data?.project_name.length > 0) {
+          this.error = err.response.data.project_name[0]
+        } else {
+          this.$nuxt.error({
+            statusCode: err.response.status,
+            message: err.response.data.toString(),
+          })
+        }
+      }
+    },
+    async updateProject() {
+      try {
+        await this.$axios.$put(
+          `/api/projects/${this.project.id}/`,
+          this.project
+        )
+        // this.updateProjectsCount()
+        // this.$router.push({ name: 'projects' })
+        this.$emit('project-updated', this.project)
+      } catch (err) {
+        console.dir(err)
+        if (err?.response?.data?.project_name.length > 0) {
+          this.error = err.response.data.project_name[0]
+        } else {
+          this.$nuxt.error({
+            statusCode: err.response.status,
+            message: err.response.data.toString(),
+          })
+        }
       }
     },
+    ...mapActions({
+      updateProjectsCount: 'updateProjectsCount',
+    }),
   },
 }
 </script>
diff --git a/client-nuxt/components/AnalysisState.vue b/client-nuxt/components/AnalysisState.vue
new file mode 100644
index 0000000000000000000000000000000000000000..2e1bd70ce7a7556ce119a273ae250a1db08148ef
--- /dev/null
+++ b/client-nuxt/components/AnalysisState.vue
@@ -0,0 +1,40 @@
+<template>
+  <v-card flat color="transparent">
+    <v-progress-circular
+      v-if="state == 'running'"
+      indeterminate
+      color="primary"
+      :size="16"
+      :width="2"
+    ></v-progress-circular>
+
+    <v-progress-circular
+      v-else-if="state == 'queued'"
+      indeterminate
+      color="orange darken-2"
+      :size="16"
+      :width="2"
+    ></v-progress-circular>
+
+    <v-icon v-else-if="state == 'ok'" color="success" :size="20"
+      >mdi-check-circle</v-icon
+    >
+    <v-icon v-else-if="state == 'new'" color="primary" :size="20"
+      >mdi-new-box</v-icon
+    >
+    <v-icon v-else-if="state == 'paused'" color="primary" :size="20"
+      >mdi-pause-circle</v-icon
+    >
+    <v-icon v-else-if="state == 'error'" color="error" :size="20"
+      >mdi-alert-circle</v-icon
+    >
+    <v-icon v-else :size="20" color="warning">mdi-help-circle</v-icon>
+  </v-card>
+</template>
+<script>
+export default {
+  props: {
+    state: { type: String, default: '' },
+  },
+}
+</script>
diff --git a/client-nuxt/components/DataTableActions.vue b/client-nuxt/components/DataTableActions.vue
new file mode 100644
index 0000000000000000000000000000000000000000..800ce4c3284ae255330ba4b7b582aae47f29d13b
--- /dev/null
+++ b/client-nuxt/components/DataTableActions.vue
@@ -0,0 +1,158 @@
+<template>
+  <v-card flat color="transparent">
+    <error-alert v-if="error" :error-message="error"></error-alert>
+    <delete-dialog
+      v-if="itemToDelete"
+      v-model="deleteDialog"
+      :type="itemType"
+      :item="itemToDelete"
+      :name="itemToDelete[titleKey]"
+      @delete="deleteItem"
+    ></delete-dialog>
+    <v-data-table
+      :headers="headers"
+      :items="items"
+      :sort-by="sortBy"
+      :sort-desc="sortDesc"
+      :search="search"
+      :item-class="getRowClass"
+      :loading="loading"
+      multi-sort
+      @click:row="goToItemPage"
+    >
+      <template v-slot:top>
+        <v-toolbar flat>
+          <v-toolbar-title> {{ title }} </v-toolbar-title>
+          <v-divider class="mx-4" inset vertical></v-divider>
+          <v-tooltip bottom>
+            <template v-slot:activator="{ on, attrs }">
+              <v-btn
+                v-if="addRoute"
+                color="primary"
+                fab
+                small
+                class="mx-3"
+                :to="addRoute"
+                v-bind="attrs"
+                v-on="on"
+              >
+                <v-icon> mdi-plus </v-icon>
+              </v-btn>
+            </template>
+            <span>Add {{ itemType }}</span></v-tooltip
+          >
+          <v-spacer></v-spacer>
+          <v-text-field
+            v-model="search"
+            append-icon="mdi-magnify"
+            label="Search"
+            single-line
+            hide-details
+            dense
+          ></v-text-field>
+
+          <v-spacer></v-spacer>
+          <v-chip color="accent" small class="text-capitalize">{{
+            itemType
+          }}</v-chip>
+        </v-toolbar>
+      </template>
+
+      <template #[`item.creation_date`]="{ item }">
+        <v-chip>{{ item.creation_date.toDateString() }}</v-chip>
+      </template>
+
+      <template #[`item.cclines`]="{ item }">
+        <v-chip>{{ item.cclines.length }}</v-chip>
+      </template>
+      <template #[`item.history_status`]="{ value }">
+        <analysis-state
+          v-if="value && value.state"
+          :state="value.state"
+        ></analysis-state>
+        <analysis-state v-else :state="null"></analysis-state>
+      </template>
+      <template #[`item.workflow_invocation_status`]="{ value }">
+        <invocation-state :state="value"></invocation-state>
+      </template>
+      <template #[`item.actions`]="{ item }">
+        <v-btn icon @click.stop="openDeleteDialog(item)">
+          <v-icon small> mdi-delete </v-icon>
+        </v-btn>
+      </template>
+    </v-data-table>
+  </v-card>
+</template>
+
+<script>
+import ErrorAlert from '@/components/ErrorAlert'
+import DeleteDialog from './DeleteDialog.vue'
+import AnalysisState from './AnalysisState.vue'
+import InvocationState from './InvocationState.vue'
+export default {
+  components: {
+    ErrorAlert,
+    DeleteDialog,
+    AnalysisState,
+    InvocationState,
+  },
+  props: {
+    headers: { type: Array, default: () => [] },
+    items: { type: Array, default: () => [] },
+    sortBy: { type: Array, default: () => [] },
+    sortDesc: { type: Array, default: () => [] },
+    title: { type: String, default: '' },
+    titleKey: { type: String, default: 'name' },
+    itemType: { type: String, required: true, default: 'object' },
+    addRoute: { type: Object, default: () => null },
+    selectedItem: { type: Number, default: null },
+    loading: { type: Boolean, default: false },
+  },
+  data() {
+    return {
+      error: null,
+      deleteDialog: false,
+      itemToDelete: null,
+      search: '',
+    }
+  },
+  methods: {
+    openDeleteDialog(item) {
+      this.itemToDelete = item
+      this.deleteDialog = true
+    },
+    deleteItem(item) {
+      this.$emit('delete', this.itemToDelete.id)
+      this.itemToDelete = null
+    },
+    goToItemPage(item) {
+      if (item.itemRoute) {
+        this.$router.push(item.itemRoute)
+      } else {
+        this.error = 'No page define for this item'
+      }
+    },
+    getRowClass(item) {
+      const classes = []
+      if (item.itemRoute) {
+        classes.push('has-item-route')
+      }
+      if (item.id === this.selectedItem) {
+        classes.push('row-selected')
+      }
+      return classes.join(' ')
+    },
+  },
+}
+</script>
+
+<style>
+.has-item-route {
+  cursor: pointer;
+}
+.row-selected {
+  background-color: var(--v-accent-lighten1);
+  /* color: var(--v-accent-darken4); */
+  opacity: 0.9;
+}
+</style>
diff --git a/client-nuxt/components/DeleteDialog.vue b/client-nuxt/components/DeleteDialog.vue
index 61f705f9bfef0f79036847e1c73017ccd556b1fb..166870f03a68f15456154a605373f5005d07b339 100644
--- a/client-nuxt/components/DeleteDialog.vue
+++ b/client-nuxt/components/DeleteDialog.vue
@@ -1,11 +1,12 @@
 <template>
-  <v-dialog v-model="dialog" max-width="500">
-    <template v-slot:activator="{ on, attrs }">
-      <v-btn color="error" dark v-bind="attrs" v-on="on">
-        <v-icon>mdi-trash-can-outline</v-icon>
-      </v-btn>
-    </template>
-
+  <v-dialog
+    :value="dialog"
+    max-width="500"
+    @click:outside="$emit('change', false)"
+  >
+    <!-- <template #activator="{ on, attrs }">
+      <v-slot name="activator" :on="on" :attrs="attrs"> </v-slot>
+    </template> -->
     <v-card>
       <v-card-title class="headline grey darken-3" primary-title>
         Confirmation required
@@ -58,9 +59,15 @@
 
 <script>
 export default {
+  model: {
+    prop: 'dialog',
+    event: 'change',
+  },
   props: {
     name: { type: String, required: true },
+    item: { type: Object, required: true },
     type: { type: String, required: true },
+    dialog: { type: Boolean, default: false },
     // entry: {
     //   type: Object,
     //   required: true,
@@ -69,7 +76,6 @@ export default {
   data() {
     return {
       deleteConfirmation: null,
-      dialog: false,
     }
   },
   methods: {
@@ -80,12 +86,12 @@ export default {
     },
     close() {
       this.deleteConfirmation = null
-      this.dialog = false
+      this.$emit('change', false)
     },
     deleteEntry() {
       this.deleteConfirmation = null
-      this.dialog = false
-      this.$emit('delete')
+      this.$emit('change', false)
+      this.$emit('delete', this.item)
     },
   },
 }
diff --git a/client-nuxt/components/DeleteProject.vue b/client-nuxt/components/DeleteProject.vue
index f2dc1042cdd1182b3769978fed2b1008dac573e3..ce0dfa164387449169a12e4a2a13fd95a112a689 100644
--- a/client-nuxt/components/DeleteProject.vue
+++ b/client-nuxt/components/DeleteProject.vue
@@ -1,7 +1,7 @@
 <template>
   <v-dialog v-model="dialog" max-width="500">
     <template v-slot:activator="{ on, attrs }">
-      <v-btn color="error" dark v-bind="attrs" v-on="on">
+      <v-btn color="error" v-bind="attrs" v-on="on">
         <v-icon>mdi-trash-can-outline</v-icon>
       </v-btn>
     </template>
diff --git a/client-nuxt/components/ErrorAlert.vue b/client-nuxt/components/ErrorAlert.vue
index 582cbd81ab29e17eca1b0e583369feaf7fba438f..0585661c12b8b07d82562ce1efd39dcaf2b15426 100644
--- a/client-nuxt/components/ErrorAlert.vue
+++ b/client-nuxt/components/ErrorAlert.vue
@@ -1,9 +1,9 @@
 <template>
   <v-alert
-    dense
     prominent
+    text
+    :dark="$vuetify.theme.dark"
     border="left"
-    color="red darken-4"
     dismissible
     type="error"
   >
@@ -12,7 +12,14 @@
         {{ errorMessage }}
       </v-col>
       <v-col class="shrink">
-        <v-btn v-if="home" icon text nuxt to="/"
+        <v-btn
+          v-if="home"
+          icon
+          text
+          :dark="$vuetify.theme.dark"
+          color="error"
+          nuxt
+          to="/"
           ><v-icon>mdi-home</v-icon></v-btn
         ></v-col
       ><v-col v-if="url" class="shrink">
diff --git a/client-nuxt/components/ExperimentFileInputHeader.vue b/client-nuxt/components/ExperimentFileInputHeader.vue
new file mode 100644
index 0000000000000000000000000000000000000000..0fda245287ab6a09db52f122db9fdeefa62ecaa1
--- /dev/null
+++ b/client-nuxt/components/ExperimentFileInputHeader.vue
@@ -0,0 +1,29 @@
+<template>
+  <v-dialog v-if="header.helpText" v-model="dialog" width="500px">
+    <template v-slot:activator="{ on, attrs }">
+      <v-btn icon color="primary" v-bind="attrs" v-on="on"
+        ><v-icon>mdi-help-circle</v-icon></v-btn
+      >
+    </template>
+    <v-card flat
+      ><v-card-title> {{ header.text }} field help</v-card-title
+      ><v-card-text>{{ header.helpText }}</v-card-text
+      ><v-card-actions class="justify-end">
+        <v-btn text @click="dialog = false">Close</v-btn>
+      </v-card-actions></v-card
+    >
+  </v-dialog>
+</template>
+
+<script>
+export default {
+  props: {
+    header: { type: Object, default: () => ({}) },
+  },
+  data() {
+    return { dialog: null }
+  },
+}
+</script>
+
+<style></style>
diff --git a/client-nuxt/components/ExperimentFileInputHelp.vue b/client-nuxt/components/ExperimentFileInputHelp.vue
new file mode 100644
index 0000000000000000000000000000000000000000..3daab502db48f05a5b70655185b9379b273724ea
--- /dev/null
+++ b/client-nuxt/components/ExperimentFileInputHelp.vue
@@ -0,0 +1,365 @@
+<template>
+  <v-card flat>
+    <v-card outlined class="my-3">
+      <v-card-title>Experiment input file</v-card-title>
+      <v-card-text>
+        The input file must be in csv format and formatted as shown below :
+      </v-card-text>
+      <v-card-text>
+        <v-data-table :headers="headers" :items="items" hide-default-footer>
+          <!-- mouse id -->
+          <template #[`header.mouseId`]="{ header }">
+            {{ header.text }}
+            <experiment-file-input-header
+              :header="header"
+            ></experiment-file-input-header>
+          </template>
+
+          <!-- phenotype -->
+          <template #[`header.phenotype`]="{ header }">
+            {{ header.text }}
+            <experiment-file-input-header
+              :header="header"
+            ></experiment-file-input-header>
+          </template>
+          <template #[`header.phenotypeI`]="{ header }">
+            <span v-html="header.text"></span>
+          </template>
+          <template #[`item.phenotypeI`]="{ item }">
+            <span v-html="item.phenotypeI"></span>
+          </template>
+
+          <!-- covariate -->
+          <template #[`header.covariate`]="{ header }">
+            {{ header.text }}
+            <experiment-file-input-header
+              :header="header"
+            ></experiment-file-input-header>
+          </template>
+          <template #[`header.covariateI`]="{ header }">
+            <span v-html="header.text"></span>
+          </template>
+          <template #[`item.covariateI`]="{ item }">
+            <span v-html="item.covariateI"></span>
+          </template>
+          <!-- sex -->
+          <template #[`header.sex`]="{ header }">
+            {{ header.text }}
+            <experiment-file-input-header
+              :header="header"
+            ></experiment-file-input-header>
+          </template>
+
+          <!-- CC Mother -->
+          <template #[`header.ccMother`]="{ header }">
+            {{ header.text }}
+            <experiment-file-input-header
+              :header="header"
+            ></experiment-file-input-header>
+          </template>
+
+          <!-- CC Father -->
+          <template #[`header.ccFather`]="{ header }">
+            {{ header.text }}
+            <experiment-file-input-header
+              :header="header"
+            ></experiment-file-input-header>
+          </template>
+        </v-data-table>
+      </v-card-text>
+      <v-card-text
+        ><v-alert type="info" prominent text
+          >You can add as many phenotypes or covariates columns as you
+          need</v-alert
+        ></v-card-text
+      >
+    </v-card>
+    <v-card outlined class="my-3">
+      <v-card-title>Experiment input file - Q&amp;A</v-card-title>
+      <v-card-text>
+        <v-card flat class="my-2">
+          <v-card-title class="text-subtitle-2 font-weight-bold">
+            Is my data appropriate for QTL mapping in CC-QTL ?
+          </v-card-title>
+          <v-card-text>
+            <p>
+              Current statistical framework underlying CC-QTL uses linear
+              regression for QTL mapping, which is appropriate for continuous
+              traits that exhibit a roughly gaussian distribution.
+            </p>
+            <p>
+              To validate this assumption, it is highly advised that you explore
+              the distribution of phenotypic values and possibly proceed with
+              mathematical (log, inv, sqrt) transformation of the data. In that
+              respect, a plotting/transformation module is proposed in CC-QTL.
+            </p>
+            <p>
+              Should your trait depart from such distribution, even after
+              mathematical transformation of the data (see infra), QTL detection
+              will be greatly impeded, possibly raising fallacious QTL peaks.
+            </p>
+            <p>
+              QTL mapping can nonetheless be performed on such data, treating
+              your trait not as continuous but as binary (eg, infection scoring,
+              <span>&#62;</span> or <span>&#60;</span> to a given score instead
+              of a continuum of score values) ; which is then performed under a
+              logistic regression framework currently not implemented (future
+              improvements) in CC-QTL.
+            </p>
+          </v-card-text>
+        </v-card>
+        <v-divider></v-divider>
+        <v-card flat class="my-2">
+          <v-card-title class="text-subtitle-2 font-weight-bold">
+            Should I provide mean values ? Individual values ?
+          </v-card-title>
+          <v-card-text>
+            The permutation procedure incorporated in CC-QTL allow you to do
+            both!
+            <ul>
+              <li>
+                Individual values: this is most appropriate should you have
+                unequal block sizes (eg, n=3 per arm for CC001 mice vs n=5 for
+                CC005), as means calculated in such settings are inproper
+                (variance heterogeneity: one cannot compare a mean acquired from
+                5 individuals with one acquired from 50)… at the cost of a
+                reduced power. Hence, working with individual values is more
+                amenable to unperfect settings.
+              </li>
+              <li>
+                Means: this is possible if you have equal blocks size for the
+                phenotypes under scrutiny. However, be careful with what you
+                average together! a minimal sanity check would be looking at the
+                distributions of individual values (the plotting module of
+                CC-QTL can help you in that respect). Should you work with
+                means, it is advised to use LS means insteads (namely, mean
+                values adjusted given a model, that can incorporate spatial
+                and/or temporal batch effects, eg cage position/experiment
+                rounds).
+              </li>
+            </ul>
+          </v-card-text>
+          <v-card-text>
+            <v-row>
+              <v-col>
+                <v-simple-table dense>
+                  <template v-slot:default>
+                    <thead>
+                      <tr>
+                        <th colspan="2" class="text-left">
+                          Passing individual values, example
+                        </th>
+                      </tr>
+                    </thead>
+                    <tbody>
+                      <tr>
+                        <td>1</td>
+                        <td>CC001</td>
+                      </tr>
+                      <tr>
+                        <td>2</td>
+                        <td>CC001</td>
+                      </tr>
+                      <tr>
+                        <td>3</td>
+                        <td>CC002</td>
+                      </tr>
+                      <tr>
+                        <td>4</td>
+                        <td>CC002</td>
+                      </tr>
+                      <tr>
+                        <td><span>&hellip;</span></td>
+                        <td><span>&hellip;</span></td>
+                      </tr>
+                    </tbody>
+                  </template>
+                </v-simple-table>
+              </v-col>
+              <v-col
+                ><v-simple-table dense>
+                  <template v-slot:default>
+                    <thead>
+                      <tr>
+                        <th colspan="2" class="text-left">
+                          Passing mean values, example
+                        </th>
+                      </tr>
+                    </thead>
+                    <tbody>
+                      <tr>
+                        <td>1</td>
+                        <td>CC001</td>
+                      </tr>
+                      <tr>
+                        <td>2</td>
+                        <td>CC002</td>
+                      </tr>
+                      <tr>
+                        <td>3</td>
+                        <td>CC003</td>
+                      </tr>
+                      <tr>
+                        <td>4</td>
+                        <td>CC004</td>
+                      </tr>
+                      <tr>
+                        <td><span>&hellip;</span></td>
+                        <td><span>&hellip;</span></td>
+                      </tr>
+                    </tbody>
+                  </template>
+                </v-simple-table></v-col
+              >
+            </v-row>
+            <v-alert type="info" text prominent class="my-3"
+              >Do note however that you cannot pass both means and individual
+              values within a same dataset.
+            </v-alert>
+          </v-card-text>
+        </v-card>
+        <v-divider></v-divider>
+        <template v-for="(qa, index) in inputFileQA">
+          <v-card :key="qa.question" flat class="my-2">
+            <v-card-title class="text-subtitle-2 font-weight-bold"
+              >{{ qa.question }}
+            </v-card-title>
+            <v-card-text>
+              {{ qa.answer }}
+            </v-card-text>
+          </v-card>
+          <v-divider v-if="qa.divider" :key="index"></v-divider>
+        </template>
+      </v-card-text>
+    </v-card>
+  </v-card>
+</template>
+
+<script>
+import ExperimentFileInputHeader from '@/components/ExperimentFileInputHeader.vue'
+export default {
+  components: {
+    ExperimentFileInputHeader,
+  },
+  data() {
+    return {
+      headers: [
+        {
+          text: 'Individual_ID',
+          value: 'mouseId',
+          helpText: 'This identifier must be unique among each experience',
+        },
+        {
+          text: 'Mother_Line',
+          value: 'ccMother',
+          helpText: 'Dam of the cross',
+        },
+        {
+          text: 'Father_Line',
+          value: 'ccFather',
+          helpText: 'Sire of the cross',
+        },
+        {
+          text: 'Sex',
+          value: 'sex',
+          helpText: 'The sex values must be encoded as "F" or "M"',
+        },
+        {
+          text: 'NameOfPhenotype1',
+          value: 'phenotype',
+          helpText:
+            'Phenotypic values must be written US/UK format: dots instead of comma',
+        },
+        {
+          text: '&hellip;',
+          value: 'phenotypeI',
+        },
+        {
+          text: 'NameOfPhenotypeN',
+          value: 'phenotypeN',
+        },
+
+        {
+          text: 'NameOfCovariate1',
+          value: 'covariate',
+          helpText:
+            'Covariate values must be written US/UK format: dots instead of comma',
+        },
+        {
+          text: '&hellip;',
+          value: 'covariateI',
+        },
+        {
+          text: 'NameOfCovariateN',
+          value: 'covariateN',
+          helpText:
+            'Covariate values must be written US/UK format: dots instead of comma',
+        },
+      ],
+      dialogs: {},
+      items: [
+        {
+          mouseId: '1',
+          ccMother: 'CC001',
+          ccFather: 'CC001',
+          sex: 'F',
+          phenotype: 5.456,
+          phenotypeI: '&hellip;',
+          covariateI: '&hellip;',
+          phenotypeN: 24,
+          covariate: 10,
+          covariateN: 5,
+        },
+        {
+          mouseId: '2',
+          ccMother: 'CC001',
+          ccFather: 'CC001',
+          sex: 'M',
+          phenotype: 8.732,
+          phenotypeN: 12,
+          covariate: 2,
+          covariateN: 18,
+          phenotypeI: '&hellip;',
+          covariateI: '&hellip;',
+        },
+        {
+          mouseId: '3',
+          ccMother: 'CC002',
+          ccFather: 'CC002',
+          sex: 'M',
+          phenotype: 7.238,
+          phenotypeN: 17,
+          covariate: 5,
+          covariateN: 31,
+          phenotypeI: '&hellip;',
+          covariateI: '&hellip;',
+        },
+      ],
+      transformationHelp: [
+        { text: 'Strongly right-skewed', type: 'log' },
+        { text: 'Slitghly right-skewed', type: 'square-root' },
+        { text: 'left-skewed', type: 'power' },
+      ],
+      inputFileQA: [
+        {
+          question: 'Can I provide both Males and Females ?',
+          answer: `Sex needs to be passed as a covariate in the model for QTL detection ; and covariates cannot be taken into account yet. Unless you are highly confident that there is no sex effects on your trait of interest, It is thus recommended to work on male vs female mice separately at present.`,
+          divider: true,
+        },
+        {
+          question: 'What is/ is not Covariate for (future improvement)',
+          answer: `Current model available in CC-QTL does not support covariates yet. Please note that covariate at the stage of QTL mapping shall be intepreted as biological covariate (eg, sex, age) and not technical (eg, cage number). This latter type, if it exists, should be fixed prior to loading the data into the interface (eg, by producing LS means).`,
+        },
+        //
+      ],
+    }
+  },
+  methods: {
+    getHelpHeaderClass(id) {
+      return `help-${id}`
+    },
+  },
+}
+</script>
+
+<style></style>
diff --git a/client-nuxt/components/GalaxyForm/IntegerToolParameter.vue b/client-nuxt/components/GalaxyForm/IntegerToolParameter.vue
index a80b7f07fa53da6f7ddc94bd721ebf8c112370f1..3fa9392026027c650300f728ee24aa213abbcdb3 100644
--- a/client-nuxt/components/GalaxyForm/IntegerToolParameter.vue
+++ b/client-nuxt/components/GalaxyForm/IntegerToolParameter.vue
@@ -49,7 +49,6 @@ export default {
       this.$emit('input', value.toString())
     },
     clickInput(ev) {
-      console.log(ev)
       this.$emit('input', ev.target.value.toString())
     },
   },
diff --git a/client-nuxt/components/GalaxyForm/PhenotypeColumnsParameter.vue b/client-nuxt/components/GalaxyForm/PhenotypeColumnsParameter.vue
new file mode 100644
index 0000000000000000000000000000000000000000..a375b55b7aeee8425a37906e8e930400471e5537
--- /dev/null
+++ b/client-nuxt/components/GalaxyForm/PhenotypeColumnsParameter.vue
@@ -0,0 +1,43 @@
+<template>
+  <ValidationProvider
+    v-if="input.options"
+    v-slot="{ errors }"
+    name="phenotype"
+    rules="required"
+  >
+    <v-select
+      label="Phenotype"
+      :items="input.options"
+      :error-messages="errors"
+      :value="value"
+      @change="handleInput"
+    ></v-select>
+  </ValidationProvider>
+</template>
+
+<script>
+import { ValidationProvider, setInteractionMode } from 'vee-validate'
+setInteractionMode('aggressive')
+
+export default {
+  components: { ValidationProvider },
+  model: {
+    prop: 'value',
+    event: 'input',
+  },
+  props: {
+    input: { type: Object, default: () => ({}) },
+    value: { type: String, default: null },
+  },
+  data() {
+    return { select: null }
+  },
+  methods: {
+    handleInput(value) {
+      this.$emit('input', value.toString())
+    },
+  },
+}
+</script>
+
+<style></style>
diff --git a/client-nuxt/components/GenericDataIterator.vue b/client-nuxt/components/GenericDataIterator.vue
deleted file mode 100644
index 3ad7ad878a187c01ccb3cb6e5807ab9ad45d97b2..0000000000000000000000000000000000000000
--- a/client-nuxt/components/GenericDataIterator.vue
+++ /dev/null
@@ -1,269 +0,0 @@
-<template>
-  <v-card class="mt-4" flat>
-    <v-container fluid>
-      <v-data-iterator
-        :items="items"
-        :items-per-page.sync="itemsPerPage"
-        :disable-pagination="disablePagination"
-        :page="page"
-        :search="search"
-        :sort-by="sortBy.toLowerCase()"
-        :sort-desc="sortDesc"
-        hide-default-footer
-      >
-        <template v-slot:header>
-          <v-toolbar dense class="mb-4">
-            <!-- <v-toolbar-title>{{ title }}</v-toolbar-title> -->
-            <!-- <v-spacer></v-spacer> -->
-            <v-text-field
-              v-model="search"
-              clearable
-              flat
-              dense
-              solo-inverted
-              hide-details
-              prepend-inner-icon="mdi-text-search"
-              label="Search"
-              class="mx-2"
-            ></v-text-field>
-            <v-spacer></v-spacer>
-
-            <template v-if="$vuetify.breakpoint.mdAndUp">
-              <v-select
-                v-model="sortBy"
-                flat
-                dense
-                solo-inverted
-                hide-details
-                :items="keys"
-                prepend-inner-icon="mdi-magnify"
-                label="Sort by"
-                class="mx-2"
-              ></v-select>
-              <v-btn-toggle
-                v-model="sortDesc"
-                dense
-                mandatory
-                color="secondary"
-                class="mx-2"
-              >
-                <v-btn :value="false">
-                  <v-icon>mdi-arrow-up</v-icon>
-                </v-btn>
-                <v-btn :value="true">
-                  <v-icon>mdi-arrow-down</v-icon>
-                </v-btn>
-              </v-btn-toggle>
-              <v-spacer></v-spacer>
-
-              <v-btn v-if="addRoute" :to="addRoute" small fab color="primary">
-                <v-icon>mdi-plus</v-icon></v-btn
-              >
-            </template>
-          </v-toolbar>
-        </template>
-
-        <template v-slot:default="props">
-          <v-row>
-            <v-col
-              v-for="item in props.items"
-              :key="item.id"
-              cols="12"
-              sm="12"
-              md="6"
-              lg="4"
-            >
-              <v-card elevation="3">
-                <v-toolbar flat dense>
-                  <v-toolbar-title
-                    ><v-checkbox
-                      v-if="selectable"
-                      v-model="selected"
-                      :value="item.name"
-                    ></v-checkbox
-                    >{{ item.name }}
-                  </v-toolbar-title>
-                  <v-spacer></v-spacer>
-                  <v-menu bottom left :offset-y="offset"
-                    ><template v-slot:activator="{ on, attrs }">
-                      <v-btn dark icon v-bind="attrs" v-on="on">
-                        <v-icon>mdi-dots-vertical</v-icon>
-                      </v-btn>
-                    </template>
-                    <v-list>
-                      <v-list-item>
-                        <v-list-item-title>Detail</v-list-item-title>
-                      </v-list-item>
-                      <v-list-item>
-                        <v-list-item-title>Delete</v-list-item-title>
-                      </v-list-item>
-                    </v-list>
-                  </v-menu>
-                </v-toolbar>
-
-                <v-card-text>
-                  <v-list dense>
-                    <v-list-item-group>
-                      <v-list-item
-                        v-for="(key, index) in filteredKeys"
-                        :key="index"
-                      >
-                        <v-list-item-content
-                          :class="{ 'blue--text': sortBy === key }"
-                          >{{ key }}:</v-list-item-content
-                        >
-                        <v-list-item-content
-                          class="align-end"
-                          :class="{ 'blue--text': sortBy === key }"
-                          >{{ item[key.toLowerCase()] }}</v-list-item-content
-                        >
-                      </v-list-item>
-                    </v-list-item-group>
-                  </v-list>
-                </v-card-text>
-                <v-card-actions>
-                  <v-btn
-                    class="mx-2"
-                    color="primary"
-                    @click="$emit('show-detail', item.id)"
-                    ><v-icon>mdi-eye</v-icon></v-btn
-                  >
-                  <delete-dialog
-                    v-if="canDelete"
-                    :type="type"
-                    :name="item.name"
-                    @delete="$emit('delete', item.id)"
-                  ></delete-dialog>
-                </v-card-actions>
-              </v-card>
-            </v-col>
-          </v-row>
-        </template>
-
-        <template v-slot:footer>
-          <v-card-text>
-            <v-row class="mt-2" align="center" justify="center">
-              <span class="grey--text">Items per page</span>
-              <v-menu offset-y>
-                <template v-slot:activator="{ on, attrs }">
-                  <v-btn
-                    dark
-                    text
-                    color="primary"
-                    class="ml-2"
-                    v-bind="attrs"
-                    v-on="on"
-                  >
-                    {{ itemsPerPage }}
-                    <v-icon>mdi-chevron-down</v-icon>
-                  </v-btn>
-                </template>
-                <v-list>
-                  <v-list-item
-                    v-for="(number, index) in itemsPerPageArray"
-                    :key="index"
-                    @click="updateItemsPerPage(number)"
-                  >
-                    <v-list-item-title>{{ number }}</v-list-item-title>
-                  </v-list-item>
-                </v-list>
-              </v-menu>
-
-              <v-spacer></v-spacer>
-
-              <span class="mr-4 grey--text">
-                Page {{ page }} of {{ numberOfPages }}
-              </span>
-              <v-btn
-                fab
-                small
-                dark
-                color="blue darken-3"
-                class="mr-1"
-                @click="formerPage"
-              >
-                <v-icon>mdi-chevron-left</v-icon>
-              </v-btn>
-              <v-btn
-                fab
-                small
-                dark
-                color="blue darken-3"
-                class="ml-1"
-                @click="nextPage"
-              >
-                <v-icon>mdi-chevron-right</v-icon>
-              </v-btn>
-            </v-row>
-          </v-card-text>
-        </template>
-      </v-data-iterator>
-    </v-container>
-  </v-card>
-</template>
-<script>
-import DeleteDialog from '@/components/DeleteDialog.vue'
-
-export default {
-  // define components
-  components: { DeleteDialog },
-  props: {
-    title: { type: String, default: () => '' },
-    type: { type: String, required: true },
-    items: { type: Array, required: true, default: () => [] },
-    keys: { type: Array, required: true, default: () => [] },
-    projectId: { type: Number, required: true },
-    selectable: { type: Boolean, default: () => false },
-    itemsPerPageArray: {
-      type: Array,
-      default: () => [4, 8, 12],
-    },
-    itemsPerPage: { type: Number, default: () => 4 },
-    addRoute: { type: Object, default: () => {} },
-    canDelete: { type: Boolean, default: () => false },
-  },
-  data() {
-    return {
-      error: null,
-      search: '',
-      filter: {},
-      sortDesc: false,
-      page: 1,
-      disableFiltering: false,
-      disablePagination: false,
-      sortBy: 'name',
-      selected: [],
-      offset: true,
-    }
-  },
-  computed: {
-    numberOfPages() {
-      return Math.ceil(this.items.length / this.itemsPerPage)
-    },
-    filteredKeys() {
-      return this.keys.filter((key) => key !== `Name`)
-    },
-  },
-  methods: {
-    nextPage() {
-      if (this.page + 1 <= this.numberOfPages) this.page += 1
-    },
-    formerPage() {
-      if (this.page - 1 >= 1) this.page -= 1
-    },
-    updateItemsPerPage(number) {
-      this.itemsPerPage = number
-    },
-    customFilter(items, search) {
-      search = search.toString().toLowerCase()
-      return [items[0]]
-    },
-    toGenericEntry({ name }) {
-      return {
-        name,
-        type: 'experiment',
-      }
-    },
-  },
-}
-</script>
diff --git a/client-nuxt/components/GenericTable.vue b/client-nuxt/components/GenericTable.vue
new file mode 100644
index 0000000000000000000000000000000000000000..f1b1a1d07710f1eb8c92bba88d3e3d2fc43fc427
--- /dev/null
+++ b/client-nuxt/components/GenericTable.vue
@@ -0,0 +1,117 @@
+<template>
+  <v-data-table
+    :headers="headers"
+    :items="items"
+    :sort-by="sortBy"
+    :sort-desc="sortDesc"
+    :search="search"
+    :items-per-page="itemsPerPage"
+    :item-class="getRowClass"
+    :footer-props="footerProps"
+    :loading="loading"
+    multi-sort
+    @click:row="$emit('go-to-item', $event)"
+  >
+    <template #top>
+      <v-toolbar flat>
+        <v-toolbar-title class="text-h5 font-weight-medium">
+          {{ title }}
+        </v-toolbar-title>
+        <v-divider class="mx-4" inset vertical></v-divider>
+        <v-text-field
+          v-model="search"
+          append-icon="mdi-magnify"
+          label="Search"
+          single-line
+          hide-details
+        ></v-text-field>
+      </v-toolbar>
+    </template>
+    <template #[`item.creation_date`]="{ item }">
+      <v-chip>{{ item.creation_date.toDateString() }}</v-chip>
+    </template>
+    <template #[`item.project.project_name`]="{ item }">
+      <v-chip color="primary" @click.stop="goToProject(item.project)">{{
+        item.project.project_name
+      }}</v-chip>
+    </template>
+    <template #[`item.experiment.name`]="{ item }">
+      <v-chip
+        v-if="item.experiment"
+        color="primary"
+        @click.stop="goToExperiment(item.project, item.experiment)"
+        >{{ item.experiment.name }}</v-chip
+      >
+      <v-chip v-else color="error"> No experiment</v-chip>
+    </template>
+    <template #[`item.history_status`]="{ value }">
+      <analysis-state
+        v-if="value && value.state"
+        :state="value.state"
+      ></analysis-state>
+    </template>
+    <template #[`item.workflow_invocation_status`]="{ value }">
+      <InvocationState v-if="value" :state="value"></InvocationState>
+    </template>
+  </v-data-table>
+</template>
+<script>
+import AnalysisState from './AnalysisState.vue'
+import InvocationState from './InvocationState.vue'
+
+export default {
+  components: { AnalysisState, InvocationState },
+  props: {
+    type: { type: String, default: null },
+    items: { type: Array, default: () => [] },
+    headers: { type: Array, default: () => [] },
+    sortBy: { type: Array, default: () => [] },
+    sortDesc: { type: Array, default: () => [] },
+    title: { type: String, default: '' },
+    itemsPerPage: { type: Number, default: 15 },
+    footerProps: {
+      type: Object,
+      default: () => ({ 'items-per-page-options': [15, 30, 45, -1] }),
+    },
+    loading: { type: Boolean, default: false },
+  },
+  data() {
+    return { search: '' }
+  },
+  methods: {
+    getRowClass() {
+      return 'is-route'
+    },
+    goToProject(project) {
+      if (this.type === 'experiments') {
+        this.$router.push({
+          name: 'projects-id-experiments',
+          params: { id: project.id },
+        })
+      } else if (this.type === 'analysis') {
+        this.$router.push({
+          name: 'projects-id-analysis',
+          params: { id: project.id },
+        })
+      } else {
+        this.$router.push({
+          name: 'projects-id',
+          params: { id: project.id },
+        })
+      }
+    },
+    goToExperiment(project, experiment) {
+      this.$router.push({
+        name: 'projects-id-experiments-experimentId',
+        params: { id: project.id, experimentId: experiment.id },
+      })
+    },
+  },
+}
+</script>
+
+<style lang="scss">
+.is-route {
+  cursor: pointer;
+}
+</style>
diff --git a/client-nuxt/components/InvocationState.vue b/client-nuxt/components/InvocationState.vue
new file mode 100644
index 0000000000000000000000000000000000000000..850870611ee5d814aa5ecd1b2dae16f2b1f81f1d
--- /dev/null
+++ b/client-nuxt/components/InvocationState.vue
@@ -0,0 +1,29 @@
+<template>
+  <v-card flat color="transparent">
+    <v-progress-circular
+      v-if="state == 'new' || state == 'ready'"
+      indeterminate
+      color="primary"
+      :size="16"
+      :width="2"
+    ></v-progress-circular>
+
+    <v-icon v-else-if="state == 'scheduled'" color="success" :size="20"
+      >mdi-check-circle</v-icon
+    >
+    <v-icon v-else-if="state == 'cancelled'" color="primary" :size="20"
+      >mdi-cancel</v-icon
+    >
+    <v-icon v-else-if="state == 'failed'" color="error" :size="20"
+      >mdi-alert-circle</v-icon
+    >
+    <v-icon v-else :size="20" color="warning">mdi-help-circle</v-icon>
+  </v-card>
+</template>
+<script>
+export default {
+  props: {
+    state: { type: String, default: '' },
+  },
+}
+</script>
diff --git a/client-nuxt/components/PhenotypeCategoryForm.vue b/client-nuxt/components/PhenotypeCategoryForm.vue
new file mode 100644
index 0000000000000000000000000000000000000000..1f24d94d193b508495fe42088cb4a10f6196161a
--- /dev/null
+++ b/client-nuxt/components/PhenotypeCategoryForm.vue
@@ -0,0 +1,248 @@
+<template>
+  <v-card flat>
+    <v-card-title>
+      <span class="text-h5">{{ formTitle }}</span>
+    </v-card-title>
+    <ValidationObserver ref="observer" v-slot="{ invalid }">
+      <v-form @submit.prevent="submit">
+        <v-card-text>
+          <v-container>
+            <v-row>
+              <v-col cols="12">
+                <ValidationProvider
+                  v-slot="{ errors, valid }"
+                  name="Name"
+                  rules="required|max:50"
+                >
+                  <v-text-field
+                    v-model="computedName"
+                    label="Name"
+                    :counter="50"
+                    :error-messages="errors"
+                    :success="valid"
+                  ></v-text-field>
+                </ValidationProvider>
+              </v-col>
+              <v-col cols="12">
+                <ValidationProvider
+                  v-slot="{ errors, valid }"
+                  name="Phenotype category description"
+                  rules="required|max:400"
+                >
+                  <v-textarea
+                    v-model="computedDescription"
+                    outlined
+                    name="input-7-4"
+                    label="Description"
+                    :counter="400"
+                    :error-messages="errors"
+                    :success="valid"
+                  ></v-textarea>
+                </ValidationProvider>
+              </v-col>
+              <v-col cols="12">
+                <v-select
+                  v-model="computedDataclass"
+                  label="Class"
+                  item-text="display_name"
+                  item-value="value"
+                  outlined
+                  :items="options.dataclass.choices"
+                ></v-select>
+              </v-col>
+              <v-col cols="12">
+                <v-select
+                  v-model="computedDatatype"
+                  :items="options.datatype.choices"
+                  label="Type"
+                  item-text="display_name"
+                  item-value="value"
+                  outlined
+                ></v-select>
+              </v-col>
+              <v-col cols="12">
+                <v-select
+                  v-model="computedNature"
+                  :items="options.nature.choices"
+                  label="Nature"
+                  item-text="display_name"
+                  item-value="value"
+                  outlined
+                ></v-select>
+              </v-col>
+              <v-col cols="12">
+                <v-select
+                  v-model="computedLocation"
+                  :items="options.location.choices"
+                  label="Location"
+                  item-text="display_name"
+                  item-value="value"
+                  outlined
+                ></v-select>
+              </v-col>
+            </v-row>
+          </v-container>
+        </v-card-text>
+
+        <v-card-actions>
+          <v-spacer></v-spacer>
+          <v-btn v-if="hasCancelBtn" color="blue darken-1" text @click="cancel">
+            <slot name="cancel-btn-text"> Cancel</slot>
+          </v-btn>
+          <v-btn type="submit" color="primary" :disabled="invalid">
+            <slot name="save-btn-text">Save</slot>
+          </v-btn>
+        </v-card-actions>
+      </v-form>
+    </ValidationObserver>
+  </v-card>
+</template>
+
+<script>
+import { required, max } from 'vee-validate/dist/rules'
+import { extend, ValidationObserver, ValidationProvider } from 'vee-validate'
+
+extend('required', {
+  ...required,
+  message: '{_field_} can not be empty',
+})
+
+extend('max', {
+  ...max,
+  message: '{_field_} may not be greater than {length} characters',
+})
+
+export default {
+  components: {
+    ValidationObserver,
+    ValidationProvider,
+  },
+  props: {
+    options: { type: Object, default: () => ({}) },
+    formTitle: { type: String, default: () => '' },
+    name: { type: String, default: () => '' },
+    description: { type: String, default: () => '' },
+    datatype: { type: String, default: () => 'Unassigned' },
+    dataclass: { type: String, default: () => 'Phenotype' },
+    nature: { type: String, default: () => 'Unassigned' },
+    location: { type: String, default: () => 'Unassigned' },
+    id: { type: Number, default: null },
+    newItem: { type: Boolean, default: true },
+    hasCancelBtn: { type: Boolean, default: true },
+  },
+  data() {
+    return {
+      defaultPhenotypeCategory: {
+        name: '',
+        description: '',
+        datatype: 'Unassigned',
+        dataclass: 'Phenotype',
+        nature: 'Unassigned',
+        location: 'Unassigned',
+      },
+    }
+  },
+  computed: {
+    computedName: {
+      set(name) {
+        this.$emit('update:name', name)
+      },
+      get() {
+        return this.name
+      },
+    },
+    computedDescription: {
+      set(description) {
+        this.$emit('update:description', description)
+      },
+      get() {
+        return this.description
+      },
+    },
+    computedDataclass: {
+      set(dataclass) {
+        this.$emit('update:dataclass', dataclass)
+      },
+      get() {
+        return this.dataclass
+      },
+    },
+    computedDatatype: {
+      set(datatype) {
+        this.$emit('update:datatype', datatype)
+      },
+      get() {
+        return this.datatype
+      },
+    },
+    computedNature: {
+      set(nature) {
+        this.$emit('update:nature', nature)
+      },
+      get() {
+        return this.nature
+      },
+    },
+    computedLocation: {
+      set(location) {
+        this.$emit('update:nature', location)
+      },
+      get() {
+        return this.location
+      },
+    },
+  },
+  methods: {
+    submit() {
+      this.$refs.observer
+        .validate()
+        .then((success) => {
+          // this.$refs.observer.validate()
+          this.save()
+        })
+        .finally(() => this.$refs.observer.reset())
+    },
+    cancel() {
+      this.clearForm()
+      this.$emit('cancel')
+    },
+    async save() {
+      try {
+        const phenotypeCategory = {
+          name: this.computedName,
+          description: this.computedDescription,
+          datatype: this.computedDatatype,
+          dataclass: this.computedDataclass,
+          nature: this.computedNature,
+          location: this.computedLocation,
+        }
+        if (this.newItem) {
+          await this.$axios.$post(
+            '/api/phenotype-categories/',
+            phenotypeCategory
+          )
+        } else {
+          await this.$axios.$patch(
+            `/api/phenotype-categories/${this.id}/`,
+            phenotypeCategory
+          )
+        }
+        this.clearForm()
+        this.$emit('save')
+      } catch (err) {
+        this.error = err.message
+      }
+    },
+    clearForm() {
+      this.computedName = this.defaultPhenotypeCategory.name
+      this.computedDescription = this.defaultPhenotypeCategory.description
+      this.computedDatatype = this.defaultPhenotypeCategory.datatype
+      this.computedDataclass = this.defaultPhenotypeCategory.dataclass
+      this.computedNature = this.defaultPhenotypeCategory.nature
+      this.computedLocation = this.defaultPhenotypeCategory.location
+    },
+  },
+}
+</script>
+
+<style></style>
diff --git a/client-nuxt/components/ProgressBar.vue b/client-nuxt/components/ProgressBar.vue
index a806af18dbe90538e0198ee931241255c8bbbe22..7949685ce9093c23b0ff0d4ba43bdca3e3f2f856 100644
--- a/client-nuxt/components/ProgressBar.vue
+++ b/client-nuxt/components/ProgressBar.vue
@@ -7,7 +7,7 @@
   >
     {{ message }}
     <v-progress-linear
-      color="secondary"
+      color="accent"
       indeterminate
       rounded
       height="6"
diff --git a/client-nuxt/components/ProjectActions.vue b/client-nuxt/components/ProjectActions.vue
new file mode 100644
index 0000000000000000000000000000000000000000..4f94fd0b532b7ff0bc04dac2c6ff1bdfd419695a
--- /dev/null
+++ b/client-nuxt/components/ProjectActions.vue
@@ -0,0 +1,88 @@
+<template>
+  <v-card flat color="transparent">
+    <v-badge
+      v-for="action in formattedActions"
+      :key="action.type"
+      overlap
+      :content="action.size.toString()"
+      class="mx-2"
+    >
+      <v-tooltip bottom>
+        <template v-slot:activator="{ on, attrs }">
+          <v-btn
+            small
+            icon
+            fab
+            nuxt
+            :to="action.route"
+            v-bind="attrs"
+            @click.stop
+            v-on="on"
+            ><v-icon>{{ action.icon }}</v-icon></v-btn
+          >
+        </template>
+        <span>{{ action.tooltip }}</span>
+      </v-tooltip>
+    </v-badge>
+  </v-card>
+</template>
+
+<script>
+export default {
+  props: {
+    projectId: { type: Number, default: null },
+    experimentSize: { type: Number, default: 0 },
+    analysisSize: { type: Number, default: 0 },
+    memberSize: { type: Number, default: 0 },
+  },
+  data() {
+    return {
+      actions: [
+        {
+          type: 'experiment',
+          route: {
+            name: 'projects-id-experiments',
+          },
+          tooltip: 'Experiments',
+          icon: 'mdi-flask',
+        },
+        {
+          type: 'analysis',
+          route: {
+            name: 'projects-id-analysis',
+          },
+          tooltip: 'Analysis',
+          icon: 'mdi-file-chart',
+        },
+        {
+          type: 'member',
+          route: {
+            name: 'projects-id-member',
+          },
+          tooltip: 'Members',
+          icon: 'mdi-account-group',
+        },
+      ],
+    }
+  },
+  computed: {
+    formattedActions() {
+      return this.actions.map((action) => {
+        return {
+          ...action,
+          size: this[`${action.type}Size`],
+          route: { ...action.route, params: { id: this.projectId } },
+        }
+      })
+    },
+  },
+  methods: {
+    experimentRoute(id) {
+      return {
+        name: 'projects-id-experiments',
+        params: { id },
+      }
+    },
+  },
+}
+</script>
diff --git a/client-nuxt/components/ProjectsDataIterator.vue b/client-nuxt/components/ProjectsDataIterator.vue
new file mode 100644
index 0000000000000000000000000000000000000000..37a4ad0f44ff8e483cb6a86c28052bdb0919dfe6
--- /dev/null
+++ b/client-nuxt/components/ProjectsDataIterator.vue
@@ -0,0 +1,336 @@
+<template>
+  <v-card flat color="transparent">
+    <delete-dialog
+      v-if="selectedItem"
+      v-model="deleteDialog"
+      :type="type"
+      :item="selectedItem"
+      :name="selectedItem[itemNameKey]"
+      @delete="deleteItem"
+    ></delete-dialog>
+    <v-dialog v-model="changeDialog">
+      <v-card flat>
+        <v-toolbar
+          ><v-toolbar-title v-if="selectedItem"
+            >Edit project</v-toolbar-title
+          ></v-toolbar
+        >
+        <v-card-text class="mt-4">
+          <add-project-form
+            :project="selectedItem"
+            update
+            @project-updated="projectUpdated"
+            @cancel="changeDialog = false"
+          ></add-project-form>
+        </v-card-text>
+      </v-card>
+    </v-dialog>
+    <v-data-iterator
+      :items="sanitizedProjects"
+      :items-per-page.sync="itemsPerPage"
+      :disable-pagination="disablePagination"
+      :page="page"
+      :search="search"
+      :sort-by="sortBy.toLowerCase()"
+      :sort-desc="sortDesc"
+      hide-default-footer
+    >
+      <template #header>
+        <v-toolbar elevation="1" class="mb-4">
+          <v-toolbar-title class="text-h5 font-weight-medium">
+            {{ title }}
+          </v-toolbar-title>
+          <v-divider class="mx-4" inset vertical></v-divider>
+          <v-text-field
+            v-model="search"
+            clearable
+            flat
+            dense
+            outlined
+            hide-details
+            prepend-inner-icon="mdi-text-search"
+            label="Search"
+            class="mx-2"
+          ></v-text-field>
+          <v-spacer></v-spacer>
+
+          <template v-if="$vuetify.breakpoint.mdAndUp">
+            <v-select
+              v-model="sortBy"
+              flat
+              dense
+              outlined
+              hide-details
+              :items="keys"
+              prepend-inner-icon="mdi-magnify"
+              label="Sort by"
+              class="mx-2"
+            ></v-select>
+            <v-btn-toggle
+              v-model="sortDesc"
+              dense
+              mandatory
+              color="primary"
+              class="mx-2"
+            >
+              <v-btn :value="false">
+                <v-icon>mdi-arrow-up</v-icon>
+              </v-btn>
+              <v-btn :value="true">
+                <v-icon>mdi-arrow-down</v-icon>
+              </v-btn>
+            </v-btn-toggle>
+            <v-spacer></v-spacer>
+
+            <v-btn v-if="addRoute" :to="addRoute" small fab color="primary">
+              <v-icon>mdi-plus</v-icon></v-btn
+            >
+          </template>
+        </v-toolbar>
+      </template>
+
+      <template #default="props">
+        <v-row>
+          <v-col
+            v-for="item in props.items"
+            :key="item.id"
+            cols="12"
+            sm="12"
+            md="6"
+            lg="4"
+            class="d-flex flex-column"
+          >
+            <v-hover v-slot="{ hover }">
+              <v-card
+                class="project-card flex-grow-1"
+                :elevation="hover ? 10 : 2"
+                @click="$emit('show-detail', item.id)"
+              >
+                <v-toolbar flat dense :color="toolbarColor()">
+                  <v-toolbar-title class="mr-2 text-uppercase">
+                    {{ item[itemNameKey] }}
+                  </v-toolbar-title>
+                  <v-spacer></v-spacer>
+                  <v-btn
+                    v-if="canChangeProject(item)"
+                    small
+                    fab
+                    icon
+                    @click.stop="openChangeDialog(item)"
+                  >
+                    <v-icon small>mdi-pencil</v-icon>
+                  </v-btn>
+                  <v-btn
+                    v-if="canDeleteProject(item)"
+                    small
+                    fab
+                    icon
+                    @click.stop="openDeleteDialog(item)"
+                  >
+                    <v-icon small>mdi-delete</v-icon>
+                  </v-btn>
+                  <v-chip color="primary">{{
+                    item.creation_date.toDateString()
+                  }}</v-chip>
+                </v-toolbar>
+                <v-card-text>
+                  {{ item.description }}
+                </v-card-text>
+                <v-card-text class="project-items-btn">
+                  <project-actions
+                    :project-id="item.id"
+                    :experiment-size="item.experiments.length"
+                    :analysis-size="item.analysis.length"
+                    :member-size="item.members.length"
+                  ></project-actions>
+                </v-card-text>
+                <!-- <v-fade-transition>
+                  <v-overlay v-if="hover" absolute color="accent" opacity="0.2">
+                  </v-overlay>
+                </v-fade-transition> -->
+              </v-card>
+            </v-hover>
+          </v-col>
+        </v-row>
+      </template>
+
+      <template #footer>
+        <v-card-text>
+          <v-row class="mt-2" align="center" justify="center">
+            <span class="grey--text">Items per page</span>
+            <v-menu offset-y>
+              <template #activator="{ on, attrs }">
+                <v-btn
+                  text
+                  color="primary"
+                  class="ml-2"
+                  v-bind="attrs"
+                  v-on="on"
+                >
+                  {{ itemsPerPage }}
+                  <v-icon>mdi-chevron-down</v-icon>
+                </v-btn>
+              </template>
+              <v-list>
+                <v-list-item
+                  v-for="(number, index) in itemsPerPageArray"
+                  :key="index"
+                  @click="updateItemsPerPage(number)"
+                >
+                  <v-list-item-title>{{ number }}</v-list-item-title>
+                </v-list-item>
+              </v-list>
+            </v-menu>
+
+            <v-spacer></v-spacer>
+
+            <span class="mr-4 grey--text">
+              Page {{ page }} of {{ numberOfPages }}
+            </span>
+            <v-btn fab small class="mr-1" @click="formerPage">
+              <v-icon>mdi-chevron-left</v-icon>
+            </v-btn>
+            <v-btn fab small class="ml-1" @click="nextPage">
+              <v-icon>mdi-chevron-right</v-icon>
+            </v-btn>
+          </v-row>
+        </v-card-text>
+      </template>
+    </v-data-iterator>
+  </v-card>
+</template>
+<script>
+import DeleteDialog from '@/components/DeleteDialog.vue'
+import ProjectActions from '@/components/ProjectActions.vue'
+import AddProjectForm from '@/components/AddProjectForm.vue'
+
+export default {
+  // define components
+  components: {
+    DeleteDialog,
+    ProjectActions,
+    AddProjectForm,
+  },
+  props: {
+    title: { type: String, default: () => '' },
+    itemNameKey: { type: String, default: 'name' },
+    type: { type: String, required: true },
+    items: { type: Array, required: true, default: () => [] },
+    keys: { type: Array, required: true, default: () => [] },
+    selectable: { type: Boolean, default: () => false },
+    itemsPerPageArray: {
+      type: Array,
+      default: () => [4, 8, 12],
+    },
+    itemsPerPage: { type: Number, default: () => 4 },
+    addRoute: { type: Object, default: () => ({}) },
+    keyToFilter: { type: Array, default: () => ['Name'] },
+  },
+  data() {
+    return {
+      error: null,
+      search: '',
+      filter: {},
+      sortDesc: false,
+      page: 1,
+      disableFiltering: false,
+      disablePagination: false,
+      sortBy: 'name',
+      selected: [],
+      offset: true,
+      deleteDialog: false,
+      selectedItem: null,
+      toggle_exclusive: 1,
+      changeDialog: false,
+    }
+  },
+  computed: {
+    numberOfPages() {
+      return Math.ceil(this.items.length / this.itemsPerPage)
+    },
+    keyToFilterSet() {
+      return new Set(this.keyToFilter)
+    },
+    filteredKeys() {
+      return this.keys.filter((key) => !this.keyToFilterSet.has(key))
+    },
+    sanitizedProjects() {
+      return this.items
+    },
+  },
+  methods: {
+    canChangeProject(item) {
+      return (
+        this.$auth.user.is_superuser || item.permissions.has('change_project')
+      )
+    },
+    canDeleteProject(item) {
+      return (
+        this.$auth.user.is_superuser || item.permissions.has('delete_project')
+      )
+    },
+    nextPage() {
+      if (this.page + 1 <= this.numberOfPages) this.page += 1
+    },
+    formerPage() {
+      if (this.page - 1 >= 1) this.page -= 1
+    },
+    updateItemsPerPage(number) {
+      this.itemsPerPage = number
+    },
+    customFilter(items, search) {
+      search = search.toString().toLowerCase()
+      return [items[0]]
+    },
+    toGenericEntry({ name }) {
+      return {
+        name,
+        type: 'experiment',
+      }
+    },
+    openDeleteDialog(item) {
+      this.selectedItem = item
+      this.deleteDialog = true
+    },
+    deleteItem(item) {
+      this.$emit('delete', item.id)
+    },
+    getHoverClass(hover) {
+      if (hover) {
+        return this.$vuetify.theme.dark ? 'card-hover-dark' : 'card-hover-light'
+      } else {
+        return ''
+      }
+    },
+    toolbarColor() {
+      return this.$vuetify.theme.dark ? '' : 'secondary lighten-6'
+    },
+    openChangeDialog(item) {
+      this.selectedItem = { ...item }
+      this.changeDialog = true
+    },
+    projectUpdated(updatedProject) {
+      this.changeDialog = false
+      this.$emit('project-updated')
+    },
+  },
+}
+</script>
+<style scoped>
+.project-card {
+  cursor: pointer;
+}
+.project-items-btn .v-btn--active {
+  color: var(--v-secondary-base) !important;
+}
+.card-hover-dark {
+  background-color: var(--v-secondary-lighten1);
+}
+
+.card-hover-light {
+  background-color: var(--v-secondary-lighten6);
+}
+.toolbar__items {
+  flex-wrap: wrap;
+}
+</style>
diff --git a/client-nuxt/components/RunAnalysisForm.vue b/client-nuxt/components/RunAnalysisForm.vue
index 417f7f283944f57c60e4f61b460a7ea7a9b024b8..4484208aa72c64b6fd8659be4c3b4fe7d171e7e1 100644
--- a/client-nuxt/components/RunAnalysisForm.vue
+++ b/client-nuxt/components/RunAnalysisForm.vue
@@ -1,76 +1,225 @@
 <template>
-  <div>
+  <v-card flat color="transparent">
     <error-alert v-if="error" :error-message="error"></error-alert>
-
-    <ValidationObserver
-      ref="observer"
-      v-slot="{ invalid, validated, handleSubmit }"
-    >
-      <v-form>
-        <ValidationProvider
-          v-slot="{ errors }"
-          name="Name"
-          rules="required|max:50"
-        >
-          <v-text-field
-            v-model="analysis.name"
-            :counter="50"
-            :error-messages="errors"
-            label="Name"
-            required
-          ></v-text-field>
-        </ValidationProvider>
-
-        <v-data-table
-          v-model="analysis.experiments"
-          :headers="headers"
-          :items="experiments"
-          :single-select="singleSelect"
-          item-key="id"
-          show-select
-          class="elevation-1"
-        >
-        </v-data-table>
-
-        <v-expansion-panels focusable>
-          <v-expansion-panel
-            v-for="param in toolsInputsFiltred"
-            :key="param.stepId"
+    <v-card-text>
+      <ValidationObserver ref="observer" v-slot="{ invalid }">
+        <v-stepper v-model="step" vertical flat color="transparent">
+          <ValidationProvider
+            v-slot="{ errors }"
+            name="experiment"
+            rules="requiredExperiment"
           >
-            <v-expansion-panel-header>{{
-              param.name
-            }}</v-expansion-panel-header>
-            <v-expansion-panel-content>
-              <div v-for="input in param.inputs" :key="input.name" class="mt-5">
-                <select-tool-parameter
-                  v-if="input.model_class == 'SelectToolParameter'"
-                  v-model="wfParams[param.stepId][input.name]"
-                  :input="input"
-                />
-                <integer-tool-parameter
-                  v-if="input.model_class == 'IntegerToolParameter'"
-                  v-model="wfParams[param.stepId][input.name]"
-                  :input="input"
-                />
-              </div>
-            </v-expansion-panel-content>
-          </v-expansion-panel>
-        </v-expansion-panels>
+            <v-stepper-step
+              :complete="step > 1"
+              step="1"
+              editable
+              :rules="[() => errors.length < 1]"
+            >
+              Select an experiment
+              <small>{{ errors[0] }}</small>
+            </v-stepper-step>
+            <v-stepper-content step="1">
+              <v-card flat color="transparent">
+                <v-card-text>
+                  <v-data-table
+                    v-model="selectedExperiments"
+                    :headers="headers"
+                    :items="experiments"
+                    :single-select="singleSelect"
+                    item-key="id"
+                    show-select
+                    class="elevation-1"
+                  >
+                  </v-data-table>
+                  <span>{{ errors[0] }}</span>
+                </v-card-text>
+                <v-card-actions>
+                  <v-btn
+                    v-if="selectedExperiments && selectedExperiments.length"
+                    color="primary"
+                    @click="step = 2"
+                    >Continue</v-btn
+                  >
+                </v-card-actions>
+              </v-card>
+            </v-stepper-content>
+          </ValidationProvider>
+          <template v-if="workflows">
+            <v-stepper-step :complete="step > 2" step="2" editable>
+              Select a workflow
+            </v-stepper-step>
+            <v-stepper-content step="2">
+              <v-card flat color="transparent">
+                <workflow-item-groups
+                  v-model="workflow"
+                  :workflows="detailedWorkflows"
+                  @selection="getDefaultWorkflowParameters"
+                ></workflow-item-groups>
+                <v-card-actions>
+                  <v-btn v-if="workflow" color="primary" @click="step = 3"
+                    >Continue</v-btn
+                  ></v-card-actions
+                >
+              </v-card>
+            </v-stepper-content>
+          </template>
+          <v-stepper-step :step="lastWorkflowStep"
+            >Set workflow parameters
+            <small v-if="workflow">
+              {{ workflow.name }}
+              <v-chip pill x-small color="secondary">{{
+                workflow.tags[0]
+              }}</v-chip></small
+            ></v-stepper-step
+          >
+          <v-stepper-content :step="lastWorkflowStep"
+            ><v-form v-model="valid" @submit.prevent="submit">
+              <v-card flat color="transparent">
+                <v-card-text>
+                  <ValidationProvider
+                    v-slot="{ errors }"
+                    name="Name"
+                    rules="required|max:50"
+                  >
+                    <v-text-field
+                      v-model="analysis.name"
+                      :counter="50"
+                      :error-messages="errors"
+                      label="Analyis Name"
+                      hint="Set the analysis name"
+                      persistent-hint
+                      outlined
+                      required
+                    ></v-text-field>
+                  </ValidationProvider>
+                  <ValidationProvider
+                    v-slot="{ errors }"
+                    name="analysis description"
+                    rules="required"
+                  >
+                    <v-textarea
+                      v-model="analysis.description"
+                      name="description"
+                      filled
+                      label="Description"
+                      auto-grow
+                      counter
+                      clearable
+                      :error-messages="errors"
+                    ></v-textarea>
+                  </ValidationProvider>
+                </v-card-text>
+                <!-- <v-card-title>Set workflow parameters</v-card-title> -->
+                <v-card-text>
+                  <v-expansion-panels focusable>
+                    <v-expansion-panel
+                      v-for="wfStep in formattedWorkflowTools"
+                      :key="wfStep.stepId"
+                    >
+                      <v-expansion-panel-header
+                        ><v-row no-gutters>
+                          <v-col cols="5">
+                            {{ wfStep.name }}
+                            <v-chip pill small>
+                              {{ wfStep.version }}</v-chip
+                            ></v-col
+                          >
+                          <v-col cols="7"> {{ wfStep.description }}</v-col>
+                        </v-row>
+                      </v-expansion-panel-header>
 
-        <v-btn
-          color="primary"
-          class="mt-4"
-          :disabled="invalid || !validated"
-          @click="handleSubmit(runAnalysis)"
-          >Run</v-btn
-        >
-      </v-form>
-    </ValidationObserver>
+                      <v-expansion-panel-content
+                        v-if="workflowParameters"
+                        eager
+                      >
+                        <template v-if="wfStep.inputs.length > 0">
+                          <div
+                            v-for="stepInput in wfStep.inputs"
+                            :key="stepInput.name"
+                            class="mt-5"
+                          >
+                            <select-tool-parameter
+                              v-if="
+                                stepInput.model_class ==
+                                  'SelectToolParameter' &&
+                                workflowParameters[wfStep.stepId][
+                                  stepInput.name
+                                ]
+                              "
+                              v-model="
+                                workflowParameters[wfStep.stepId][
+                                  stepInput.name
+                                ]
+                              "
+                              :input="stepInput"
+                            />
+                            <template
+                              v-if="
+                                stepInput.name === 'column_pheno' &&
+                                stepInput.options
+                              "
+                            >
+                              <phenotype-columns-parameter
+                                v-model="
+                                  workflowParameters[wfStep.stepId][
+                                    stepInput.name
+                                  ]
+                                "
+                                :input="stepInput"
+                              ></phenotype-columns-parameter>
+                            </template>
+                            <template
+                              v-else-if="
+                                stepInput.model_class ==
+                                  'IntegerToolParameter' &&
+                                workflowParameters[wfStep.stepId][
+                                  stepInput.name
+                                ]
+                              "
+                            >
+                              <integer-tool-parameter
+                                v-model="
+                                  workflowParameters[wfStep.stepId][
+                                    stepInput.name
+                                  ]
+                                "
+                                :input="stepInput"
+                              />
+                            </template>
+                          </div>
+                        </template>
+                        <v-card v-else flat>
+                          <v-card-text>
+                            <v-alert text type="info">
+                              No parameter to set
+                            </v-alert></v-card-text
+                          ></v-card
+                        >
+                      </v-expansion-panel-content>
+                    </v-expansion-panel>
+                  </v-expansion-panels>
+                </v-card-text>
+                <v-card-actions>
+                  <v-btn
+                    type="submit"
+                    color="primary"
+                    class="mt-4"
+                    :disabled="invalid"
+                    >Run</v-btn
+                  >
+                </v-card-actions>
+              </v-card>
+            </v-form></v-stepper-content
+          >
+        </v-stepper>
+      </ValidationObserver>
+    </v-card-text>
     <ProgressBar :waiting="waiting" message="Starting Analysis" />
-  </div>
+  </v-card>
 </template>
 
 <script>
+import { mapActions } from 'vuex'
 import { required, max } from 'vee-validate/dist/rules'
 import {
   extend,
@@ -79,17 +228,21 @@ import {
   setInteractionMode,
 } from 'vee-validate'
 import ProgressBar from '@/components/ProgressBar'
-
+import WorkflowItemGroups from '@/components/WorkflowItemGroups'
 import ErrorAlert from '@/components/ErrorAlert'
 import SelectToolParameter from '~/components/GalaxyForm/SelectToolParameter.vue'
 import IntegerToolParameter from '~/components/GalaxyForm/IntegerToolParameter.vue'
+import PhenotypeColumnsParameter from '~/components/GalaxyForm/PhenotypeColumnsParameter.vue'
 setInteractionMode('aggressive')
 
 extend('required', {
   ...required,
   message: '{_field_} can not be empty',
 })
-
+extend('requiredExperiment', {
+  ...required,
+  message: 'You must select one {_field_}',
+})
 extend('max', {
   ...max,
   message: '{_field_} may not be greater than {length} characters',
@@ -102,59 +255,191 @@ export default {
     ValidationObserver,
     ErrorAlert,
     ProgressBar,
+    WorkflowItemGroups,
+    PhenotypeColumnsParameter,
   },
   props: {
     projectId: { type: Number, required: true },
     experiments: { type: Array, required: true },
-    toolsInputs: { type: Array, default: () => [] },
-    wfParams: { type: Object, default: () => {} },
+    workflows: { type: Array, default: () => null },
+    analysis: {
+      type: Object,
+      default: () => ({ name: '', galaxy_history_id: '', experiments: [] }),
+    },
   },
   data() {
     return {
+      step: 1,
+      workflow: null,
       error: null,
       waiting: false,
+      valid: false,
       headers: [
         { text: 'Name', value: 'name' },
         { text: 'Creation Date', value: 'creation_date' },
         { text: 'Description', value: 'description' },
       ],
       singleSelect: true,
-      analysis: {
-        name: '',
-        galaxy_history_id: '',
-        experiments: [],
-      },
+      workflowTools: null,
+      workflowParameters: null,
+      selectedExperiments: [],
     }
   },
+
   computed: {
-    toolsInputsFiltred() {
-      return this.toolsInputs
-        .map((tool) => {
-          tool.inputs = tool.inputs.filter(
-            (input) => input.model_class !== 'DataToolParameter'
-          )
-          return tool
+    formattedWorkflowTools() {
+      const phenotypeColumnOptions = this.selectedExperimentPhenotypeCategory
+        .filter((phenoCat) => phenoCat.dataclass !== 'Covariate')
+        .map((option) => {
+          return {
+            ...option,
+            value: option.name,
+            text: option.name,
+          }
         })
-        .filter((tool) => tool.inputs.length > 0)
+      if (this.workflowTools) {
+        return Object.entries(this.workflowTools).map(
+          ([stepId, { name, inputs, version, description }]) => {
+            return {
+              stepId,
+              name,
+              version,
+              description,
+              // Format inputs
+              inputs: inputs
+                .filter((input) => input.model_class !== 'DataToolParameter')
+                // Add phenotype category option for this experiment
+                .map((input) => {
+                  if (input.name === 'column_pheno') {
+                    input.options = phenotypeColumnOptions
+                  }
+                  return { ...input }
+                }),
+            }
+          }
+        )
+      } else {
+        return []
+      }
+    },
+    workflowId() {
+      if (this.workflow) {
+        return this.workflow.id
+      }
+      if (this.analysis?.galaxy_workflow_id) {
+        return this.analysis.galaxy_workflow_id
+      }
+      return null
+    },
+    selectedExperimentPhenotypeCategory() {
+      return this.selectedExperiments &&
+        this.selectedExperiments.length > 0 &&
+        this.selectedExperiments[0].phenotype_categories
+        ? this.selectedExperiments[0].phenotype_categories
+        : []
+    },
+    detailedWorkflows() {
+      return this.workflows
+        ? this.workflows.map((w) => w.details)
+        : this.workflows
+    },
+    lastWorkflowStep() {
+      return this.workflows ? 3 : 2
     },
   },
-
+  mounted() {
+    if (this.analysis.galaxy_workflow_id) {
+      this.getWorkflowTools()
+      this.getWorkflowParametersFromAnalysis()
+      // find experiment used for this analysis within the list of experiments:
+      const analysisExperiment = this.experiments.find(
+        (exp) => exp.id === this.analysis.experiments[0].id
+      )
+      if (analysisExperiment) {
+        this.selectedExperiments = [analysisExperiment]
+      } else {
+        this.error = 'The experiments used for this analysis is not available'
+      }
+    }
+  },
   methods: {
     isSelect(modelClass) {
       return modelClass === 'SelectToolParameter'
     },
-    async runAnalysis() {
+    async getWorkflowTools() {
+      try {
+        this.workflowTools = await this.$axios.$get(
+          `/api/workflow-tools/${this.workflowId}/`
+        )
+      } catch (error) {
+        this.error = error.message
+        this.workflowTools = null
+      }
+    },
+    async getDefaultWorkflowParameters() {
+      try {
+        const wfParams = await this.$axios.$get(
+          `/api/workflow-default-parameters/${this.workflowId}/`
+        )
+        const workflowParameters = this.sanitizeWorkflowParameters(wfParams)
+        if (workflowParameters[1]?.column_pheno) {
+          workflowParameters[1].column_pheno = null
+        }
+        this.workflowParameters = workflowParameters
+
+        this.getWorkflowTools()
+      } catch (error) {
+        this.error = error.message
+        this.workflowParameters = null
+      }
+    },
+    async getWorkflowParametersFromAnalysis() {
+      try {
+        const wfJobParams = await this.$axios.$get(
+          `/api/projects/${this.projectId}/analysis/${this.analysis.id}/workflow_job_parameters/`
+        )
+        const workflowParameters = this.sanitizeWorkflowParameters(wfJobParams)
+
+        if (
+          workflowParameters[1]?.column_pheno &&
+          this?.analysis?.phenotype_categories[0]?.name
+        ) {
+          workflowParameters[1].column_pheno =
+            this.analysis.phenotype_categories[0].name
+        }
+        this.workflowParameters = workflowParameters
+      } catch (error) {
+        this.error = error
+        this.workflowParameters = null
+      }
+    },
+    sanitizeWorkflowParameters(workflowParameters) {
+      return Object.keys(workflowParameters).reduce(
+        // Filter steps where there is no parameters
+        (acc, stepId) => {
+          if (Object.keys(workflowParameters[stepId]).length > 0) {
+            acc[stepId] = { ...workflowParameters[stepId] }
+          }
+          return acc
+        },
+        {}
+      )
+    },
+    async submit() {
       try {
         this.waiting = true
         const { id } = await this.$axios.$post(
           `/api/projects/${this.projectId}/analysis/`,
           {
             ...this.analysis,
-            experiments: this.analysis.experiments.map((exp) => exp.id),
-            toolsParams: this.wfParams,
+            experiments: this.selectedExperiments.map((exp) => exp.id),
+            toolsParams: this.workflowParameters,
+            galaxy_workflow_id: this.workflowId,
           }
         )
         this.waiting = false
+        this.updateAnalysisCount()
+        this.$emit('update-analysis')
         this.$router.push({
           name: 'projects-id-analysis-analysisId',
           params: { id: this.projectId, analysisId: id },
@@ -163,6 +448,9 @@ export default {
         this.error = err.message
       }
     },
+    ...mapActions({
+      updateAnalysisCount: 'updateAnalysisCount',
+    }),
   },
 }
 </script>
diff --git a/client-nuxt/components/SelectPhenotypeCategory.vue b/client-nuxt/components/SelectPhenotypeCategory.vue
new file mode 100644
index 0000000000000000000000000000000000000000..158c4aa644ebbc4de5982f7b1d8729b26a6152c8
--- /dev/null
+++ b/client-nuxt/components/SelectPhenotypeCategory.vue
@@ -0,0 +1,290 @@
+<template>
+  <v-card flat color="transparent">
+    <v-dialog v-model="dialog" fullscreen>
+      <template v-slot:activator="{ on, attrs }">
+        <v-btn
+          :color="categorySelected()"
+          v-bind="attrs"
+          v-on="on"
+          @click="initDialog()"
+        >
+          <span>{{ selectedCategoryLabel() }}</span>
+        </v-btn>
+      </template>
+
+      <v-card flat>
+        <v-toolbar flat>
+          <v-toolbar-title class="headline">
+            Select Phenotype category for
+            <v-chip class="ma-2" label>
+              {{ phenotypeCategory.colName }}
+            </v-chip>
+          </v-toolbar-title>
+          <v-spacer></v-spacer>
+          <!-- @click="openAddPhenoDialog" -->
+          <v-btn small color="primary" fab to="/phenotype-categories/add">
+            <v-icon> mdi-plus </v-icon>
+          </v-btn>
+        </v-toolbar>
+        <error-alert v-if="error" :error-message="error"></error-alert>
+        <v-card-text>
+          <v-radio-group
+            v-model="selectedDataclass"
+            label="Select the dataclass: "
+            row
+          >
+            <v-radio
+              v-for="varType in phenotypeTypes"
+              :key="varType.value"
+              :label="varType.label"
+              :value="varType.value"
+            ></v-radio>
+          </v-radio-group>
+        </v-card-text>
+        <v-card-text>
+          <v-data-table
+            v-model="selectedCategory"
+            :headers="getPhenotypeTypes.header"
+            :items="getPhenotypeTypes.dataTypes"
+            :items-per-page="-1"
+            :single-select="true"
+            show-select
+            item-key="name"
+            class="elevation-1"
+            :search="search"
+            :height="400"
+          >
+            <template v-slot:top>
+              <v-toolbar flat dense>
+                <v-toolbar-title>
+                  {{ getPhenotypeTypes.label }}
+                </v-toolbar-title>
+                <v-divider class="mx-4" inset vertical></v-divider>
+                <v-text-field
+                  v-model="search"
+                  append-icon="mdi-magnify"
+                  label="Search"
+                  single-line
+                  hide-details
+                ></v-text-field>
+                <v-spacer></v-spacer>
+              </v-toolbar> </template></v-data-table
+        ></v-card-text>
+        <v-card-actions>
+          <v-btn color="secondary" @click="dialog = false"> Close </v-btn>
+          <v-btn color="primary" @click="emitSetCategory()"> Save </v-btn>
+        </v-card-actions>
+      </v-card>
+    </v-dialog>
+  </v-card>
+</template>
+
+<script>
+// import PhenotypeCategoryForm from '@/components/PhenotypeCategoryForm'
+import ErrorAlert from '@/components/ErrorAlert'
+
+export default {
+  components: {
+    ErrorAlert,
+    // PhenotypeCategoryForm,
+  },
+  model: {
+    prop: 'phenotypeCategory',
+    event: 'set-category',
+  },
+  props: {
+    phenotypeCategories: { type: Array, default: () => [] },
+    phenotypeCategory: {
+      type: Object,
+      default: () => ({
+        colIndex: null,
+        dataclass: null,
+        datatype: null,
+        description: null,
+        id: null,
+        location: null,
+        name: null,
+        nature: null,
+      }),
+    },
+    phenotypeCategoryPermissions: { type: Set, default: () => new Set() },
+    phenotypeCategoryOptions: { type: Object, default: () => ({}) },
+  },
+  data() {
+    return {
+      search: '',
+      error: null,
+      dialog: false,
+      newItem: true,
+      dialogAddPheno: false,
+      e: 1,
+      phenotypeTypes: [
+        {
+          label: 'Phenotype',
+          value: 'Phenotype',
+        },
+        {
+          label: 'Covariate',
+          value: 'Covariate',
+        },
+      ],
+      selectedCategory: [],
+      selectedDataclass: null,
+      phenotypeCategoryToAdd: {
+        name: '',
+        description: '',
+        datatype: 'Unassigned',
+        dataclass: 'Phenotype',
+        nature: 'Unassigned',
+        location: 'Unassigned',
+      },
+      defaultPhenotypeCategory: {
+        name: '',
+        description: '',
+        datatype: 'Unassigned',
+        dataclass: 'Phenotype',
+        nature: 'Unassigned',
+        location: 'Unassigned',
+      },
+    }
+  },
+  computed: {
+    canAddPheno() {
+      return this.phenotypeCategoryPermissions.has('add')
+    },
+    getPhenotypeTypes() {
+      if (this.selectedDataclass === 'Phenotype') {
+        const phenotypes = this.phenotypeCategories.filter(
+          (d) => d.dataclass === 'Phenotype'
+        )
+        return {
+          label: 'Phenotype',
+          value: 'Phenotype',
+          dataTypes: phenotypes,
+          header: Object.keys(phenotypes[0]).map((d) => ({
+            text: d,
+            value: d,
+          })),
+        }
+      } else {
+        const covariates = this.phenotypeCategories.filter(
+          (d) => d.dataclass === 'Covariate'
+        )
+        return {
+          label: 'Covariate',
+          value: 'covariate',
+          dataTypes: covariates,
+          header: Object.keys(covariates[0]).map((d) => ({
+            text: d,
+            value: d,
+          })),
+        }
+      }
+    },
+  },
+  methods: {
+    initDialog() {
+      this.selectedCategory = [{ ...this.phenotypeCategory }]
+      this.selectedDataclass =
+        this.phenotypeCategory.dataclass &&
+        this.phenotypeCategory.dataclass !== ''
+          ? this.phenotypeCategory.dataclass
+          : 'Phenotype'
+    },
+    selectedCategoryLabel() {
+      const selectedDataclassTable =
+        this.selectedCategory.length > 0
+          ? this.selectedCategory[0].dataclass
+          : null
+
+      const selectedDataclasses = [
+        this.phenotypeCategory.dataclass,
+        selectedDataclassTable,
+      ]
+      const dataclass = selectedDataclasses.reduce((acc, curr) => {
+        return curr !== null ? curr : acc
+      }, '')
+      const selectedCatNameTable =
+        this.selectedCategory.length > 0 ? this.selectedCategory[0].name : null
+      const selectedPhenotypeCategoryNames = [
+        this.phenotypeCategory.name,
+        selectedCatNameTable,
+      ]
+      const selectedPhenotypeCategoryName =
+        selectedPhenotypeCategoryNames.reduce((acc, curr) => {
+          return curr !== null ? curr : acc
+        }, '')
+      if (dataclass === '' && selectedPhenotypeCategoryName === '') {
+        return 'Select Phenotype Category'
+      } else {
+        return `${dataclass} - ${selectedPhenotypeCategoryName}`
+      }
+    },
+    getHeader(dataType) {
+      return Object.keys(dataType)
+    },
+    emitSetCategory() {
+      if (this.selectedCategory.length >= 1) {
+        const phenotypeCategory = {
+          ...this.phenotypeCategory,
+          ...this.selectedCategory[0],
+        }
+        this.$emit('set-category', phenotypeCategory)
+      } else {
+        this.$emit('set-category', this.phenotypeCategory)
+      }
+      this.dialog = false
+    },
+    categorySelected() {
+      if (
+        (this.phenotypeCategory.dataclass !== null &&
+          this.phenotypeCategory.name !== null) ||
+        (this.selectedDataclass !== null &&
+          this.selectedCategory[0].name !== null)
+      ) {
+        return 'success'
+      } else {
+        return 'error'
+      }
+    },
+    close() {
+      this.dialogAddPheno = false
+      this.$nextTick(() => {
+        this.phenotypeCategoryToAdd = { ...this.defaultPhenotypeCategory }
+        this.newItem = false
+      })
+    },
+    async save() {
+      try {
+        if (this.newItem) {
+          await this.$axios.$post(
+            '/api/phenotype-categories/',
+            this.phenotypeCategoryToAdd
+          )
+        } else {
+          await this.$axios.$patch(
+            `/api/phenotype-categories/${this.phenotypeCategoryToAdd.id}/`,
+            this.phenotypeCategoryToAdd
+          )
+        }
+        // this.$fetch()
+        this.$emit('update-phenotype-categories')
+      } catch (err) {
+        if (err?.response.data.name) {
+          this.error = err.response.data.name[0]
+        } else {
+          this.error = err.message
+        }
+      } finally {
+        this.close()
+      }
+    },
+    openAddPhenoDialog() {
+      this.newItem = true
+      this.dialogAddPheno = !this.dialogAddPheno
+    },
+  },
+}
+</script>
+
+<style></style>
diff --git a/client-nuxt/components/SelectVariableCategory.vue b/client-nuxt/components/SelectVariableCategory.vue
deleted file mode 100644
index f9b44bc19b777717362c54681d3989fdd98aa9d7..0000000000000000000000000000000000000000
--- a/client-nuxt/components/SelectVariableCategory.vue
+++ /dev/null
@@ -1,221 +0,0 @@
-<template>
-  <div>
-    <v-dialog v-model="dialog" max-width="900">
-      <template v-slot:activator="{ on, attrs }">
-        <v-card>
-          <v-card-text>
-            <v-btn
-              :color="categorySelected()"
-              dark
-              v-bind="attrs"
-              v-on="on"
-              @click="initDialog()"
-            >
-              <span>{{ selectedCategoryLabel() }}</span>
-            </v-btn>
-          </v-card-text>
-        </v-card>
-      </template>
-      <v-card>
-        <v-toolbar flat>
-          <v-toolbar-title class="headline">
-            Select Variable category for
-            <v-chip class="ma-2" label>
-              {{ variableCategory.colName }}
-            </v-chip>
-          </v-toolbar-title>
-        </v-toolbar>
-        <v-card-text>
-          <v-radio-group
-            v-model="selectedDataclass"
-            label="Select the dataclass: "
-            row
-          >
-            <v-radio
-              v-for="varType in variableTypes"
-              :key="varType.value"
-              :label="varType.label"
-              :value="varType.value"
-            ></v-radio>
-          </v-radio-group>
-        </v-card-text>
-        <v-card-text>
-          <v-data-table
-            v-model="selectedCategory"
-            :headers="getVariableTypes.header"
-            :items="getVariableTypes.dataTypes"
-            :items-per-page="5"
-            :single-select="true"
-            show-select
-            item-key="name"
-            class="elevation-1"
-            :search="search"
-          >
-            <template v-slot:top>
-              <v-toolbar flat dense>
-                <v-toolbar-title>
-                  {{ getVariableTypes.value }}
-                </v-toolbar-title>
-                <v-divider class="mx-4" inset vertical></v-divider>
-                <v-text-field
-                  v-model="search"
-                  append-icon="mdi-magnify"
-                  label="Search"
-                  single-line
-                  hide-details
-                ></v-text-field>
-              </v-toolbar> </template></v-data-table
-        ></v-card-text>
-        <v-card-actions
-          ><v-btn color="primary" @click="emitSetCategory()"> Save </v-btn>
-          <v-btn text> Cancel </v-btn></v-card-actions
-        >
-      </v-card>
-    </v-dialog>
-  </div>
-</template>
-
-<script>
-export default {
-  model: {
-    prop: 'variableCategory',
-    event: 'set-category',
-  },
-  props: {
-    variableCategories: { type: Array, default: () => [] },
-    variableCategory: {
-      type: Object,
-      default: () => ({
-        colIndex: null,
-        dataclass: null,
-        datatype: null,
-        description: null,
-        id: null,
-        location: null,
-        name: null,
-        nature: null,
-      }),
-    },
-  },
-
-  data() {
-    return {
-      search: '',
-      dialog: false,
-      e: 1,
-      variableTypes: [
-        {
-          label: 'Variable',
-          value: 'Variable',
-        },
-        {
-          label: 'Covariate',
-          value: 'Covariate',
-        },
-      ],
-      selectedCategory: [],
-      selectedDataclass: null,
-    }
-  },
-  computed: {
-    getVariableTypes() {
-      if (this.selectedDataclass === 'Variable') {
-        const variables = this.variableCategories.filter(
-          (d) => d.dataclass === 'Variable'
-        )
-        return {
-          label: 'Variable',
-          value: 'variable',
-          dataTypes: variables,
-          header: Object.keys(variables[0]).map((d) => ({
-            text: d,
-            value: d,
-          })),
-        }
-      } else {
-        const covariates = this.variableCategories.filter(
-          (d) => d.dataclass === 'Covariate'
-        )
-        return {
-          label: 'Covariate',
-          value: 'covariate',
-          dataTypes: covariates,
-          header: Object.keys(covariates[0]).map((d) => ({
-            text: d,
-            value: d,
-          })),
-        }
-      }
-    },
-  },
-  methods: {
-    initDialog() {
-      this.selectedCategory = [{ ...this.variableCategory }]
-      this.selectedDataclass = this.variableCategory.dataclass
-    },
-    selectedCategoryLabel() {
-      const selectedDataclassTable =
-        this.selectedCategory.length > 0
-          ? this.selectedCategory[0].dataclass
-          : null
-
-      const selectedDataclasses = [
-        this.variableCategory.dataclass,
-        selectedDataclassTable,
-      ]
-      const dataclass = selectedDataclasses.reduce((acc, curr) => {
-        return curr !== null ? curr : acc
-      }, '')
-      const selectedCatNameTable =
-        this.selectedCategory.length > 0 ? this.selectedCategory[0].name : null
-      const selectedVariableCategoryNames = [
-        this.variableCategory.name,
-        selectedCatNameTable,
-      ]
-      const selectedVariableCategoryName = selectedVariableCategoryNames.reduce(
-        (acc, curr) => {
-          return curr !== null ? curr : acc
-        },
-        ''
-      )
-      if (dataclass === '' && selectedVariableCategoryName === '') {
-        return 'Select Variable Category'
-      } else {
-        return `${dataclass} - ${selectedVariableCategoryName}`
-      }
-    },
-    variableTypeLabel(varType) {
-      return varType.label + ' types'
-    },
-    getHeader(dataType) {
-      return Object.keys(dataType)
-    },
-    emitSetCategory() {
-      if (this.selectedCategory.length >= 1) {
-        const variableCategory = {
-          ...this.variableCategory,
-          ...this.selectedCategory[0],
-        }
-        this.$emit('set-category', variableCategory)
-      } else {
-        this.$emit('set-category', this.variableCategory)
-      }
-      this.dialog = false
-    },
-    categorySelected() {
-      if (
-        (this.variableCategory.dataclass !== null &&
-          this.variableCategory.name !== null) ||
-        (this.selectedDataclass !== null &&
-          this.selectedCategory[0].name !== null)
-      ) {
-        return 'success'
-      } else {
-        return 'error'
-      }
-    },
-  },
-}
-</script>
-
-<style></style>
diff --git a/client-nuxt/components/User.vue b/client-nuxt/components/User.vue
index 73f178c08a8894922a01df0a6fcc0db4fe293333..107f9086df741566d4b7e14aa97bd57fae10f9bb 100644
--- a/client-nuxt/components/User.vue
+++ b/client-nuxt/components/User.vue
@@ -6,16 +6,22 @@
         <v-list>
           <v-list-item>
             <v-list-item-icon>
-              <v-icon color="indigo">mdi-account</v-icon>
+              <v-icon v-if="user.is_superuser" color="primary"
+                >mdi-account-star</v-icon
+              >
+              <v-icon v-else color="primary">mdi-account</v-icon>
             </v-list-item-icon>
             <v-list-item-content>
               <v-list-item-title>{{ user.username }}</v-list-item-title>
+              <v-list-item-subtitle v-if="user.is_superuser"
+                >superuser</v-list-item-subtitle
+              >
             </v-list-item-content>
           </v-list-item>
 
           <v-list-item>
             <v-list-item-icon>
-              <v-icon color="indigo">mdi-email</v-icon>
+              <v-icon color="primary">mdi-email</v-icon>
             </v-list-item-icon>
             <v-list-item-content>
               <v-list-item-title>{{ user.email }}</v-list-item-title>
@@ -23,15 +29,23 @@
           </v-list-item>
           <v-list-item>
             <v-list-item-icon>
-              <v-icon color="indigo">mdi-account-group</v-icon>
+              <v-icon color="primary">mdi-account-group</v-icon>
             </v-list-item-icon>
             <v-list-item-content>
-              <v-list-item-title v-for="group in user.groups" :key="group">{{
-                group
+              <v-list-item-title v-for="group in user.groups" :key="group.id">{{
+                group.name
               }}</v-list-item-title>
             </v-list-item-content>
           </v-list-item>
         </v-list>
+        <v-btn
+          v-if="$auth.user.id === $route.params.userId"
+          text
+          color="primary"
+          :to="passwordChangeRoute()"
+        >
+          Change password
+        </v-btn>
       </v-card-text>
     </v-card>
     <div></div>
@@ -40,6 +54,27 @@
 
 <script>
 export default {
-  props: { user: { type: Object, required: true } },
+  name: 'User',
+  props: {
+    user: {
+      type: Object,
+      required: true,
+      default: () => ({
+        username: '',
+        first_name: '',
+        last_name: '',
+        email: '',
+        groups: [],
+      }),
+    },
+  },
+  methods: {
+    passwordChangeRoute() {
+      return {
+        name: 'users-userId-password-change',
+        params: { userId: this.$auth.user.id },
+      }
+    },
+  },
 }
 </script>
diff --git a/client-nuxt/components/WorkflowInvocation.vue b/client-nuxt/components/WorkflowInvocation.vue
new file mode 100644
index 0000000000000000000000000000000000000000..c7a47264408568969ef7090ae8f4b1a2b1cb8369
--- /dev/null
+++ b/client-nuxt/components/WorkflowInvocation.vue
@@ -0,0 +1,72 @@
+<template>
+  <v-card flat>
+    <v-expansion-panels focusable multiple>
+      <v-expansion-panel v-for="step in steps" :key="step.step_id">
+        <v-expansion-panel-header disable-icon-rotate>
+          <v-row no-gutters>
+            <v-col>
+              {{ step.step_id }}. {{ step.tool.name }}
+              <span class="text-caption text--secondary ml-2"
+                ><v-chip small>{{ step.tool.version }}</v-chip></span
+              >
+            </v-col>
+            <v-col>{{ step.tool.description }}</v-col>
+          </v-row>
+          <template #actions>
+            <analysis-state :state="step.job.state"></analysis-state>
+          </template>
+        </v-expansion-panel-header>
+        <v-expansion-panel-content>
+          <template v-if="Object.keys(step.job.params).length > 0">
+            <v-list-item
+              v-for="k in Object.keys(step.job.params)"
+              :key="k"
+              dense
+            >
+              <template #default>
+                <v-list-item-content>
+                  <v-list-item-subtitle>
+                    <v-badge
+                      color="secondary"
+                      inline
+                      :content="step.job.params[k]"
+                      >{{ k }} :
+                    </v-badge>
+                  </v-list-item-subtitle>
+                </v-list-item-content></template
+              >
+            </v-list-item>
+          </template>
+          <v-card v-else flat>
+            <v-card-text class="pb-0">
+              <v-alert border="left" text type="info" class="mt-4">
+                No parameter
+              </v-alert></v-card-text
+            ></v-card
+          >
+        </v-expansion-panel-content></v-expansion-panel
+      >
+    </v-expansion-panels>
+  </v-card>
+</template>
+<script>
+import AnalysisState from '@/components/AnalysisState'
+
+export default {
+  components: {
+    AnalysisState,
+  },
+  props: { steps: { type: Array, default: () => [] } },
+  methods: {
+    getCols() {
+      if (this.$vuetify.breakpoint.xlOnly) {
+        return false
+      } else if (this.$vuetify.breakpoint.smAndDown) {
+        return 12
+      } else {
+        return 4
+      }
+    },
+  },
+}
+</script>
diff --git a/client-nuxt/components/WorkflowItemGroups.vue b/client-nuxt/components/WorkflowItemGroups.vue
new file mode 100644
index 0000000000000000000000000000000000000000..de52ec77c9923f2f59a86eef823457842c9c0dd4
--- /dev/null
+++ b/client-nuxt/components/WorkflowItemGroups.vue
@@ -0,0 +1,86 @@
+<template>
+  <v-item-group>
+    <v-container fluid>
+      <v-row>
+        <v-col
+          v-for="workflow in workflows"
+          :key="workflow.id"
+          cols="12"
+          md="4"
+        >
+          <v-item v-slot="{ active, toggle }">
+            <v-card
+              class="d-flex flex-column"
+              @click="
+                toggle($event)
+                selectWorkflow(workflow)
+              "
+            >
+              <v-toolbar elevation="2">
+                <v-toolbar-title class="text-h5">
+                  {{ workflow.name }} </v-toolbar-title
+                ><v-spacer></v-spacer>
+                <v-chip
+                  v-for="tag in workflow.tags"
+                  :key="tag"
+                  color="secondary"
+                >
+                  {{ tag }}</v-chip
+                >
+              </v-toolbar>
+              <v-card-text color="transparent">
+                {{ workflow.annotation }}
+              </v-card-text>
+              <v-divider></v-divider>
+              <v-list dense>
+                <v-subheader>Steps</v-subheader>
+                <template v-for="step in workflow.steps">
+                  <v-list-item v-if="step.tool_id" :key="step.id" dense>
+                    <v-list-item-content>
+                      <v-list-item-title>
+                        <v-badge color="accent" :content="step.id" inline left>
+                          {{ getToolName(step.tool_id) }}</v-badge
+                        >
+                        <v-chip x-small>{{ step.tool_version }}</v-chip>
+                      </v-list-item-title>
+                    </v-list-item-content>
+                  </v-list-item>
+                </template>
+              </v-list>
+              <v-fade-transition>
+                <v-overlay v-if="active" absolute color="primary" opacity="0.2">
+                  <v-icon x-large color="accent darken-1"
+                    >mdi-check-bold</v-icon
+                  >
+                </v-overlay>
+              </v-fade-transition>
+            </v-card>
+          </v-item>
+        </v-col>
+      </v-row>
+    </v-container>
+  </v-item-group>
+</template>
+<script>
+export default {
+  model: {
+    prop: 'selectedWorkflow',
+    event: 'selection',
+  },
+  props: {
+    selectedWorklow: { type: Object, default: () => ({}) },
+    workflows: { type: Array, default: () => [] },
+  },
+  methods: {
+    getToolName(toolId) {
+      return toolId.split('/').slice(-2, -1).toString()
+    },
+    getActiveColor(isActive) {
+      return isActive ? 'primary' : 'transparent'
+    },
+    selectWorkflow(workflow) {
+      this.$emit('selection', workflow)
+    },
+  },
+}
+</script>
diff --git a/client-nuxt/components/charts/GenomeScan.vue b/client-nuxt/components/charts/GenomeScan.vue
new file mode 100644
index 0000000000000000000000000000000000000000..be87e958e094b1d07e9ee01fe24d1d519cf1ad79
--- /dev/null
+++ b/client-nuxt/components/charts/GenomeScan.vue
@@ -0,0 +1,145 @@
+<template>
+  <v-container fluid>
+    <v-card flat>
+      <ProgressBar :waiting="computedWaiting" message="Rendering Genome Scan" />
+      <highcharts
+        ref="chart"
+        :options="formattedchartOptions"
+        :update-args="[true, true, false]"
+        :deep-copy-on-update="true"
+      ></highcharts>
+    </v-card>
+  </v-container>
+</template>
+<script>
+import ProgressBar from '@/components/ProgressBar'
+import * as d3ScaleChromatic from 'd3-scale-chromatic'
+import * as d3Scale from 'd3-scale'
+import * as d3Array from 'd3-array'
+export default {
+  components: {
+    ProgressBar,
+  },
+  props: {
+    series: { type: Array, default: () => [] },
+    thresholdValues: { type: Array, default: () => [] },
+    thresholdPlotLines: { type: Boolean, default: true },
+    waiting: { type: Boolean, default: false },
+  },
+  data() {
+    return {
+      colorScheme: d3ScaleChromatic.schemeReds,
+      chartOptions: {
+        title: { text: 'Genome Scan' },
+        // boost: { enabled: true },
+        yAxis: {
+          // alternateGridColor: '#FDFFD5',
+          title: {
+            text: 'LOD',
+          },
+        },
+        xAxis: {
+          // alternateGridColor: '#FDFFD5',
+          visible: false,
+        },
+        chart: {
+          type: 'line',
+          zoomType: 'xy',
+          height: 500,
+          events: {
+            render() {
+              this.computedWaiting = false
+            },
+          },
+        },
+        exporting: {
+          enabled: true,
+          fallbackToExportServer: false,
+          showTable: false,
+          buttons: {
+            contextButton: {
+              menuItems: [
+                'viewFullscreen',
+                'downloadPNG',
+                'downloadJPEG',
+                'downloadSVG',
+              ],
+            },
+          },
+          sourceWidth: 2000,
+          sourceHeight: 400,
+        },
+
+        tooltip: {
+          // eslint-disable-next-line object-shorthand
+          formatter: function () {
+            return `<b>${this.point.marker}</b> <br/>Chromosome: ${this.point.chromosome}<br/>LOD : ${this.y} <br/> Position: ${this.point.position}`
+          },
+        },
+        credits: false,
+      },
+    }
+  },
+  computed: {
+    computedWaiting: {
+      set(waiting) {
+        this.$emit('update:waiting', waiting)
+      },
+      get() {
+        return this.waiting
+      },
+    },
+    thresholdDomain() {
+      return d3Array.extent(this.thresholdValues.map((t) => t.significance))
+    },
+    thresholdColors() {
+      return d3Scale.scaleQuantize(this.thresholdDomain, this.colorScheme[5])
+    },
+    formattedchartOptions() {
+      const plotLines = this.thresholdPlotLines
+        ? this.thresholdValues.map(this.thresholdToPlotLines)
+        : null
+      return {
+        ...this.chartOptions,
+        yAxis: {
+          ...this.chartOptions.yAxis,
+          plotLines,
+        },
+        series: this.series.map((serie) => ({
+          ...serie,
+          lineWidth: 1,
+          turboThreshold: serie.data.length,
+        })),
+      }
+    },
+  },
+  methods: {
+    thresholdToPlotLines({ threshold, significance }, i) {
+      return {
+        value: threshold,
+        // dashStyle: 'ShortDash',
+        width: 1,
+        color: this.thresholdColors(significance),
+        label: {
+          text: '',
+          textAlign: 'center',
+          style: {
+            fontWeight: 'bold',
+            fontSize: '1rem',
+          },
+        },
+        events: {
+          // eslint-disable-next-line object-shorthand
+          mouseover: function (e) {
+            this.label.element.innerHTML = significance
+          },
+          // eslint-disable-next-line object-shorthand
+          mouseout: function (e) {
+            this.label.element.innerHTML = ''
+          },
+        },
+      }
+    },
+  },
+}
+</script>
diff --git a/client-nuxt/components/charts/Haplotype.vue b/client-nuxt/components/charts/Haplotype.vue
new file mode 100644
index 0000000000000000000000000000000000000000..74f6004684ec332bcb4c0fa57d9236a2737f9562
--- /dev/null
+++ b/client-nuxt/components/charts/Haplotype.vue
@@ -0,0 +1,131 @@
+<template>
+  <v-container fluid>
+    <v-card flat>
+      <highcharts
+        ref="chart"
+        :options="formattedchartOptions"
+        :update-args="[true, true, false]"
+      ></highcharts>
+    </v-card>
+  </v-container>
+</template>
+<script>
+import * as d3Array from 'd3-array'
+import * as d3Color from 'd3-color'
+export default {
+  props: {
+    haplotypes: { type: Array, default: () => [] },
+    colorMap: { type: Map, default: () => new Map() },
+  },
+  data() {
+    return {
+      chartOptions: {
+        title: { text: 'Haplotypes' },
+        chart: {
+          type: 'boxplot',
+          // height: (9 / 16) * 100 + '%',
+          height: 500,
+        },
+
+        yAxis: {
+          title: { text: 'Phenotype' },
+        },
+        exporting: {
+          sourceWidth: 1600,
+          sourceHeight: 900,
+          buttons: {
+            contextButton: {
+              menuItems: [
+                'viewFullscreen',
+                'printChart',
+                'separator',
+                'downloadPNG',
+                'downloadJPEG',
+                'downloadPDF',
+                'downloadSVG',
+                'separator',
+                'downloadCSV',
+                'downloadXLS',
+              ],
+            },
+          },
+        },
+        credits: false,
+      },
+    }
+  },
+  computed: {
+    formattedchartOptions() {
+      const groupedHaplotypes = d3Array.group(
+        this.haplotypes,
+        (d) => d.haplotype,
+        (d) => d.ccline
+      )
+
+      const haplotypeList = Array.from(groupedHaplotypes.keys()).sort()
+      const phenotypeSerie = { name: 'Phenotypes boxplot', data: [] }
+      const categories = []
+      const scatterSeries = []
+      let xAxisIndex = -1
+
+      haplotypeList.forEach((haplo) => {
+        const cclines = Array.from(groupedHaplotypes.get(haplo).keys()).sort()
+        const scatterSerie = {
+          type: 'scatter',
+          color: this.colorMap.get(haplo),
+          name: haplo,
+          marker: { radius: 3 },
+          tooltip: {
+            headerFormat:
+              '<b>Genotype</b>: <tspan style="fill:{series.color}"><b>{series.name}</b></tspan></br>',
+            pointFormat: `<b>Phenotype</b>: {point.y}</br><b>Ccline</b>: {point.ccline}`,
+          },
+          data: [],
+        }
+        for (const ccline of cclines) {
+          xAxisIndex = xAxisIndex + 1
+          const serieData = []
+
+          for (const { phenotype } of groupedHaplotypes
+            .get(haplo)
+            .get(ccline)) {
+            scatterSerie.data.push({ x: xAxisIndex, y: phenotype, ccline })
+            serieData.push(phenotype)
+          }
+          const sortedSerieData = serieData.sort()
+          // push the series
+          phenotypeSerie.data.push({
+            x: xAxisIndex,
+            low: d3Array.min(sortedSerieData),
+            q1: d3Array.quantileSorted(sortedSerieData, 0.25),
+            median: d3Array.quantileSorted(sortedSerieData, 0.5),
+            q3: d3Array.quantileSorted(sortedSerieData, 0.75),
+            high: d3Array.max(sortedSerieData),
+            color: this.colorMap.get(haplo),
+            name: ccline,
+            fillColor: d3Color
+              .color(this.colorMap.get(haplo))
+              .copy({ opacity: 0.4 })
+              .toString(),
+          })
+        }
+        scatterSeries.push(scatterSerie)
+
+        // push the categories
+        categories.push(...cclines)
+      })
+
+      return {
+        ...this.chartOptions,
+        xAxis: {
+          categories,
+          title: {
+            text: 'CC lines',
+          },
+        },
+        series: [phenotypeSerie, ...scatterSeries],
+      }
+    },
+  },
+}
+</script>
diff --git a/client-nuxt/components/charts/PhenotypeBarPlot.vue b/client-nuxt/components/charts/PhenotypeBarPlot.vue
new file mode 100644
index 0000000000000000000000000000000000000000..0afed0c241295e76faa0d93aaecbaf50dcbcb9c8
--- /dev/null
+++ b/client-nuxt/components/charts/PhenotypeBarPlot.vue
@@ -0,0 +1,103 @@
+<template>
+  <v-card flat
+    ><highcharts
+      ref="chart"
+      :options="sanitizedchartOptions"
+      :update-args="[true, true, true]"
+    ></highcharts>
+  </v-card>
+</template>
+
+<script>
+export default {
+  props: {
+    groupedPhenotypes: { type: Array, default: () => [] },
+    phenotypeName: { type: String, default: () => '' },
+  },
+  data() {
+    return {
+      chartOptions: {
+        chart: {
+          type: 'column',
+        },
+        legend: { enabled: false },
+        title: {
+          text: 'Histogram using a column chart',
+        },
+
+        xAxis: {
+          title: { text: 'Genotypes' },
+          type: 'category',
+          // crosshair: true,
+        },
+        yAxis: {
+          min: 0,
+          title: {
+            text: '',
+          },
+        },
+        tooltip: {
+          headerFormat: '<b>{point.key}</b><br>',
+          pointFormat: 'Mean : {point.y:.3f}<br>Sample size : {point.count}',
+          shared: true,
+          useHTML: true,
+        },
+        plotOptions: {
+          column: {
+            // colorByPoint: true,
+            pointPadding: 0,
+            // borderWidth: 0,
+            groupPadding: 0,
+            // shadow: false,
+          },
+        },
+        series: [
+          {
+            name: 'Data',
+            // data: [
+            //   49.9, 71.5, 106.4, 129.2, 144.0, 176.0, 135.6, 124.1, 95.6, 54.4,
+            // ],
+          },
+        ],
+        exporting: {
+          sourceWidth: 1600,
+          sourceHeight: 900,
+        },
+        credits: false,
+      },
+    }
+  },
+  computed: {
+    categories() {
+      return this.groupedPhenotypes.map((d) => d[0])
+    },
+    phenotypes() {
+      return this.groupedPhenotypes.map((d) => d[1])
+    },
+    sanitizedchartOptions() {
+      return {
+        ...this.chartOptions,
+        title: {
+          ...this.chartOptions,
+          text: `Mean of <b>${this.phenotypeName}</b>`,
+        },
+        // xAxis: { ...this.chartOptions.xAxis, categories: this.categories },
+        yAxis: {
+          title: {
+            text: `Mean of ${this.phenotypeName}`,
+          },
+        },
+        series: this.chartOptions.series.map((s, i) => {
+          if (i === 0) {
+            return { ...s, data: this.groupedPhenotypes }
+          } else {
+            return s
+          }
+        }),
+      }
+    },
+  },
+}
+</script>
+
+<style></style>
diff --git a/client-nuxt/components/charts/PhenotypeBoxPlot.vue b/client-nuxt/components/charts/PhenotypeBoxPlot.vue
new file mode 100644
index 0000000000000000000000000000000000000000..a0fc37741f8f7ac554f8e4aab1fbd59b04a36ea3
--- /dev/null
+++ b/client-nuxt/components/charts/PhenotypeBoxPlot.vue
@@ -0,0 +1,124 @@
+<template>
+  <v-card flat
+    ><highcharts
+      ref="chart"
+      :options="sanitizedchartOptions"
+      :update-args="[true, true, true]"
+    ></highcharts>
+  </v-card>
+</template>
+
+<script>
+import * as d3Array from 'd3-array'
+
+export default {
+  props: {
+    phenotypePerGenotype: { type: Map, default: () => new Map([]) },
+    phenotypeName: { type: String, default: () => '' },
+  },
+  data() {
+    return {
+      chartOptions: {
+        title: { text: 'Boxplot' },
+        chart: {
+          type: 'boxplot',
+          height: 500,
+        },
+        legend: { enabled: false },
+        xAxis: {
+          title: {
+            text: 'Genotypes',
+          },
+        },
+        yAxis: {
+          title: { text: 'Phenotype' },
+        },
+
+        exporting: {
+          sourceWidth: 1600,
+          sourceHeight: 900,
+          // buttons: {
+          //   contextButton: {
+          //     menuItems: [
+          //       'viewFullscreen',
+          //       'printChart',
+          //       'separator',
+          //       'downloadPNG',
+          //       'downloadJPEG',
+          //       'downloadPDF',
+          //       'downloadSVG',
+          //       'separator',
+          //       'downloadCSV',
+          //       'downloadXLS',
+          //     ],
+          //   },
+          // },
+        },
+        credits: false,
+      },
+    }
+  },
+  computed: {
+    sanitizedchartOptions() {
+      const entries = Array.from(this.phenotypePerGenotype.entries())
+      // const categories = entries.map((d) => d[0].split('-')[0])
+      // const phenotypePerGenotypeSeries = entries.map((d) =>
+      //   d[1].map((d) => d.y)
+      // )
+      const sortedPhenotypeByMeans = entries
+        .map((d) => [d[0], d3Array.mean(d[1].map((e) => e.y))])
+        .sort((a, b) => a[1] - b[1])
+      return {
+        ...this.chartOptions,
+        title: {
+          ...this.chartOptions.title,
+          text: `Boxplot for <b>${this.phenotypeName}</b>`,
+        },
+        xAxis: {
+          ...this.chartOptions.xAxis,
+          categories: sortedPhenotypeByMeans.map((d) => d[0]),
+        },
+        yAxis: {
+          title: {
+            text: `${this.phenotypeName}`,
+          },
+        },
+        series: [
+          {
+            name: 'Observations',
+            data: sortedPhenotypeByMeans.map(([key, mean], i) => {
+              const sortedPhenotype = this.phenotypePerGenotype
+                .get(key)
+                .map((d) => d.y)
+                .sort()
+              return {
+                x: i,
+                low: d3Array.min(sortedPhenotype),
+                q1: d3Array.quantileSorted(sortedPhenotype, 0.25),
+                median: d3Array.quantileSorted(sortedPhenotype, 0.5),
+                q3: d3Array.quantileSorted(sortedPhenotype, 0.75),
+                high: d3Array.max(sortedPhenotype),
+                count: sortedPhenotype.length,
+                name: key,
+              }
+            }),
+            tooltip: {
+              headerFormat: null,
+              pointFormat:
+                '<span style="color:{point.color}">●</span> <b> {point.name}</b><br/>' +
+                'Maximum: {point.high}<br/>' +
+                'Upper quartile: {point.q3}<br/>' +
+                'Median: {point.median}<br/>' +
+                'Lower quartile: {point.q1}<br/>' +
+                'Minimum: {point.low}<br/>' +
+                'Sample size: {point.count}',
+            },
+          },
+        ],
+      }
+    },
+  },
+}
+</script>
+
+<style></style>
diff --git a/client-nuxt/components/charts/PhenotypeDistribution.vue b/client-nuxt/components/charts/PhenotypeDistribution.vue
new file mode 100644
index 0000000000000000000000000000000000000000..e93ffc0c29c4b84c8ce237e1bfdc3395d6a31fe4
--- /dev/null
+++ b/client-nuxt/components/charts/PhenotypeDistribution.vue
@@ -0,0 +1,231 @@
+<template>
+  <v-card flat>
+    <v-toolbar flat>
+      <v-radio-group
+        v-if="hasTransformFn"
+        v-model="phenotypeTransformType"
+        label="Select transformation function: "
+        row
+        hide-details
+      >
+        <v-tooltip
+          v-for="transform in phenotypeTransformTypes"
+          :key="transform.value"
+          bottom
+          :disabled="!transform.help"
+        >
+          <template v-slot:activator="{ on, attrs }">
+            <v-radio
+              :label="transform.label"
+              :value="transform"
+              v-bind="attrs"
+              v-on="on"
+            ></v-radio>
+          </template>
+          <span v-if="transform.help">{{ transform.help.text }}</span>
+        </v-tooltip>
+      </v-radio-group>
+      <v-spacer></v-spacer>
+      <download-csv
+        :data="transformedPhenotype"
+        :name="chartTitle + '.csv'"
+        :labels="sanitizedLabels"
+      >
+        <v-btn class="mx-2" color="secondary" small fab>
+          <v-icon>mdi-table-arrow-down</v-icon>
+        </v-btn>
+      </download-csv>
+    </v-toolbar>
+    <highcharts
+      v-if="transformedPhenotype && transformedPhenotype.length > 2"
+      ref="chart"
+      :options="formattedchartOptions"
+      :update-args="[true, true, true]"
+    ></highcharts>
+  </v-card>
+</template>
+
+<script>
+import JsonCSV from 'vue-json-csv'
+
+export default {
+  components: { downloadCsv: JsonCSV },
+  model: {
+    prop: 'axis',
+    event: 'selection',
+  },
+  props: {
+    phenotype: { type: Array, default: () => [] },
+    phenotypeName: { type: String, default: () => '' },
+    phenotypeTransformTypes: { type: Array, default: () => [] },
+  },
+  data() {
+    return {
+      labels: {
+        ccline_id: 'Individual_ID',
+        id_cc_f: 'Mother_Line',
+        id_cc_m: 'Father_Line',
+        ccline_sex: 'Sex',
+      },
+      phenotypeTransformType: null,
+      chartOptions: {
+        title: {
+          text: 'Highcharts Histogram',
+        },
+        chart: {
+          // height: 565,
+          // width: 1000,
+          zoomType: 'x',
+        },
+        xAxis: [
+          {
+            title: { text: 'Count' },
+            alignTicks: false,
+            opposite: true,
+            // reversed: true,
+          },
+          {
+            title: { text: 'Histogram' },
+            alignTicks: false,
+          },
+        ],
+
+        yAxis: [
+          {
+            title: { text: 'Data' },
+            opposite: true,
+          },
+          {
+            title: { text: 'Frequency' },
+          },
+        ],
+        exporting: {
+          sourceWidth: 1600,
+          sourceHeight: 900,
+          buttons: {
+            contextButton: {
+              menuItems: [
+                'viewFullscreen',
+                'printChart',
+                'separator',
+                'downloadPNG',
+                'downloadJPEG',
+                'downloadPDF',
+                'downloadSVG',
+              ],
+            },
+          },
+        },
+        credits: false,
+        plotOptions: {
+          histogram: {
+            accessibility: {
+              point: {
+                valueDescriptionFormat:
+                  '{index}. {point.x:.3f} to {point.x2:.3f}, {point.y}.',
+              },
+            },
+          },
+          scatter: {
+            tooltip: {
+              headerFormat: '{series.name}<br>',
+            },
+          },
+        },
+
+        series: [
+          {
+            name: 'Histogram',
+            type: 'histogram',
+            xAxis: 1,
+            yAxis: 1,
+            baseSeries: 's1',
+            zIndex: 0,
+          },
+          {
+            name: 'Data',
+            type: 'scatter',
+            id: 's1',
+            // dataSorting: { enabled: true },
+            marker: {
+              radius: 1.5,
+            },
+            zIndex: 2,
+          },
+        ],
+      },
+    }
+  },
+  computed: {
+    hasTransformFn() {
+      return this.phenotypeTransformTypes.length >= 1
+    },
+    chartTitle() {
+      return this.hasTransformFn
+        ? `${this.phenotypeTransformType?.value}(${this.phenotypeName})`
+        : this.phenotypeName
+    },
+    sanitizedLabels() {
+      return { ...this.labels, y: this.chartTitle }
+    },
+    formattedchartOptions() {
+      return {
+        ...this.chartOptions,
+        title: {
+          ...this.chartOptions.title,
+          text: this.chartTitle,
+        },
+        yAxis: this.chartOptions.yAxis.map((axis, i) => {
+          if (i === 0) {
+            axis.title.text = this.chartTitle
+          }
+          return axis
+        }),
+        xAxis: this.chartOptions.xAxis.map((axis, i) => {
+          if (i === 1) {
+            axis.title.text = this.chartTitle
+          }
+          return axis
+        }),
+        plotOptions: {
+          ...this.chartOptions.plotOptions,
+
+          scatter: {
+            ...this.chartOptions.plotOptions.scatter,
+            tooltip: {
+              ...this.chartOptions.plotOptions.scatter.tooltip,
+              pointFormat:
+                'CC Mother : <b>{point.id_cc_f}</b> , CC Father <b>{point.id_cc_m}</b> <br>' +
+                ' Sex : {point.ccline_sex}<br>' +
+                'phenotype: <b>{point.y}</b>',
+            },
+          },
+        },
+        series: this.chartOptions.series.map((s) => {
+          if (s.type === 'scatter') {
+            return {
+              ...s,
+              data: this.transformedPhenotype,
+              name: `Scatter for ${this.chartTitle}`,
+            }
+          } else {
+            return { ...s, name: `Histogram for ${this.chartTitle}` }
+          }
+        }),
+      }
+    },
+
+    transformedPhenotype() {
+      if (this.phenotypeTransformType?.fn) {
+        return this.phenotype.map(this.phenotypeTransformType.fn)
+      } else {
+        return this.phenotype
+      }
+    },
+  },
+  mounted() {
+    if (this.hasTransformFn)
+      this.phenotypeTransformType = this.phenotypeTransformTypes[0]
+  },
+}
+</script>
diff --git a/client-nuxt/components/charts/QtlEffect.vue b/client-nuxt/components/charts/QtlEffect.vue
new file mode 100644
index 0000000000000000000000000000000000000000..d04ad41b854af6ec23621d4f31f9d36d4ca405e3
--- /dev/null
+++ b/client-nuxt/components/charts/QtlEffect.vue
@@ -0,0 +1,125 @@
+<template>
+  <v-container fluid>
+    <v-card flat>
+      <highcharts
+        ref="chart"
+        :options="formattedchartOptions"
+        :update-args="[true, true, false]"
+      ></highcharts>
+    </v-card>
+  </v-container>
+</template>
+
+<script>
+export default {
+  model: {
+    prop: 'axis',
+    event: 'selection',
+  },
+  props: {
+    effects: { type: Array, default: () => [] },
+    colorMap: { type: Map, default: () => new Map() },
+    axis: { type: Object, default: () => null },
+  },
+  data() {
+    return {
+      serieNames: ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'lodscore'],
+      chartOptions: {
+        title: { text: 'QTL Effects' },
+        chart: {
+          height: 800,
+          // height: (9 / 16) * 100 + '%',
+          zoomType: 'x',
+          panning: true,
+          panKey: 'shift',
+        },
+        plotOptions: {
+          series: {
+            marker: {
+              enabledThreshold: 2,
+              radius: 5,
+            },
+          },
+        },
+        yAxis: [
+          {
+            title: {
+              text: 'QTL Effects',
+            },
+            height: '50%',
+            zoomEnabled: true,
+          },
+          {
+            title: {
+              text: 'LOD',
+            },
+            top: '54%',
+            height: '46%',
+            offset: 0,
+            endOnTick: true,
+            // lineWidth: 3,
+          },
+        ],
+        tooltip: {
+          // eslint-disable-next-line object-shorthand
+          formatter: function () {
+            return `SNP: <b>${this.point.marker}</b><br/> LOD: ${this.y}<br/>Position: ${this.x}`
+          },
+        },
+        credits: false,
+      },
+    }
+  },
+  computed: {
+    formattedchartOptions() {
+      return {
+        ...this.chartOptions,
+        chart: {
+          ...this.chartOptions.chart,
+          events: {
+            selection: this.selectionEventHandler,
+          },
+        },
+        series: this.effects.reduce((acc, curr) => {
+          this.serieNames.forEach((sName, i) => {
+            acc[i].data.push({
+              marker: curr.marker,
+              [sName]: curr[sName],
+              x: curr.position,
+              y: curr[sName],
+            })
+            acc[i].turboThreshold = acc[i].data.length
+          })
+          return acc
+        }, this.initSeries()),
+      }
+    },
+  },
+  methods: {
+    initSeries() {
+      return this.serieNames.map((sName) => {
+        return {
+          name: sName,
+          data: [],
+          yAxis: sName === 'lodscore' ? 1 : 0,
+          color: sName === 'lodscore' ? 'black' : this.colorMap.get(sName),
+        }
+      })
+    },
+    selectionEventHandler(event) {
+      if (event?.resetSelection) {
+        this.$emit('selection', null)
+      } else {
+        const { min: minX, max: maxX } = event.xAxis[0]
+        // const { min: minY, max: maxY } = event.yAxis[0]
+
+        const axis = {
+          x: [minX, maxX],
+          // y: [minY, maxY],
+        }
+        this.$emit('selection', axis)
+      }
+    },
+  },
+}
+</script>
diff --git a/client-nuxt/components/charts/SnpsAssociation.vue b/client-nuxt/components/charts/SnpsAssociation.vue
new file mode 100644
index 0000000000000000000000000000000000000000..a87493b361b3ed39f57639675bfbe8274d75c6fd
--- /dev/null
+++ b/client-nuxt/components/charts/SnpsAssociation.vue
@@ -0,0 +1,135 @@
+<template>
+  <v-container fluid>
+    <v-card flat>
+      <highcharts
+        ref="chart"
+        :options="formattedchartOptions"
+        :update-args="[true, true, false]"
+      ></highcharts> </v-card
+  ></v-container>
+</template>
+<script>
+export default {
+  model: {
+    prop: 'axis',
+    event: 'selection',
+  },
+  props: {
+    serie: { type: Array, default: () => [] },
+    axis: { type: Object, default: () => null },
+  },
+  data() {
+    return {
+      chartOptions: {
+        title: { text: 'SNPs association' },
+        yAxis: {
+          title: {
+            text: '- Log(p-value)',
+          },
+        },
+        xAxis: {
+          title: {
+            text: 'Chromosome',
+          },
+          startOnTick: true,
+          endOnTick: true,
+          showLastLabel: true,
+        },
+        chart: {
+          type: 'scatter',
+          zoomType: 'xy',
+          // height: (9 / 16) * 100 + '%',
+        },
+        plotOptions: {
+          scatter: {
+            marker: {
+              radius: 2.5,
+            },
+          },
+        },
+        legend: {
+          enabled: false,
+        },
+        exporting: {
+          sourceWidth: 1600,
+          sourceHeight: 500,
+          buttons: {
+            contextButton: {
+              menuItems: [
+                'viewFullscreen',
+                'printChart',
+                'separator',
+                'downloadPNG',
+                'downloadJPEG',
+                'downloadPDF',
+                'downloadSVG',
+                'separator',
+                'downloadCSV',
+                'downloadXLS',
+              ],
+            },
+          },
+        },
+        tooltip: {
+          // eslint-disable-next-line object-shorthand
+          formatter: function () {
+            return `SNP: <b>${this.point.snp_id}</b><br/> LOD: ${this.y}<br/>Position: ${this.x}`
+          },
+        },
+        credits: false,
+      },
+    }
+  },
+  computed: {
+    chromosome() {
+      return this.serie[0].chromosome
+    },
+
+    formattedchartOptions() {
+      return {
+        ...this.chartOptions,
+        xAxis: {
+          ...this.chartOptions.xAxis,
+          title: {
+            text: `Chromosome ${this.chromosome}`,
+          },
+        },
+        chart: {
+          ...this.chartOptions.chart,
+          events: {
+            selection: this.selectionEventHandler,
+          },
+        },
+        series: [
+          {
+            turboThreshold: this.serie.length,
+            // name: this.series[0].chromosome,
+            data: this.serie.map((d) => ({
+              ...d,
+              x: d.position,
+              y: d.lodscore,
+            })),
+          },
+        ],
+      }
+    },
+  },
+
+  methods: {
+    selectionEventHandler(event) {
+      if (event?.resetSelection) {
+        this.$emit('selection', null)
+      } else {
+        const { min: minX, max: maxX } = event.xAxis[0]
+        const { min: minY, max: maxY } = event.yAxis[0]
+
+        const axis = {
+          x: [minX, maxX],
+          y: [minY, maxY],
+        }
+        this.$emit('selection', axis)
+      }
+    },
+  },
+}
+</script>
diff --git a/client-nuxt/components/charts/TopSnp.vue b/client-nuxt/components/charts/TopSnp.vue
new file mode 100644
index 0000000000000000000000000000000000000000..0d7ef12d1f07be23e05d50ecde38b1f992d9db82
--- /dev/null
+++ b/client-nuxt/components/charts/TopSnp.vue
@@ -0,0 +1,159 @@
+<template>
+  <v-container fluid>
+    <v-card flat>
+      <highcharts
+        ref="chart"
+        :options="formattedchartOptions"
+        :update-args="[true, true, true]"
+      ></highcharts>
+    </v-card>
+  </v-container>
+</template>
+<script>
+import * as d3Array from 'd3-array'
+import * as d3Color from 'd3-color'
+// import highcharts from 'highcharts'
+
+export default {
+  model: {
+    prop: 'selectedPoints',
+    event: 'selection',
+  },
+  props: {
+    selectedPoints: { type: Set, default: () => null },
+    topSnp: { type: Array, default: () => [] },
+    colorMap: { type: Map, default: () => new Map() },
+  },
+  data() {
+    return {
+      chartOptions: {
+        title: { text: 'Top SNP' },
+        chart: {
+          type: 'boxplot',
+          // height: (9 / 16) * 100 + '%',
+          height: 500,
+          // zoomType: 'xy',
+        },
+
+        yAxis: {
+          title: { text: 'Phenotype' },
+        },
+        exporting: {
+          sourceWidth: 1600,
+          sourceHeight: 900,
+          buttons: {
+            contextButton: {
+              menuItems: [
+                'viewFullscreen',
+                'printChart',
+                'separator',
+                'downloadPNG',
+                'downloadJPEG',
+                'downloadPDF',
+                'downloadSVG',
+                'separator',
+                'downloadCSV',
+                'downloadXLS',
+              ],
+            },
+          },
+        },
+        credits: false,
+      },
+    }
+  },
+  computed: {
+    formattedchartOptions() {
+      const groupedByGenotype = d3Array.group(this.topSnp, (d) => d.genotype)
+      const genotypeList = Array.from(groupedByGenotype.keys()).sort()
+      const genotypeBoxPlotSerie = {
+        name: 'Boxplot',
+        color: 'black',
+        marker: { radius: 1 },
+        data: genotypeList.map((genotype, x) => {
+          const data = groupedByGenotype
+            .get(genotype)
+            .map(({ phenotype }) => phenotype)
+            .sort()
+          return {
+            x,
+            low: d3Array.min(data),
+            q1: d3Array.quantileSorted(data, 0.25),
+            median: d3Array.quantileSorted(data, 0.5),
+            q3: d3Array.quantileSorted(data, 0.75),
+            high: d3Array.max(data),
+            color: this.colorMap.get(genotype),
+            name: genotype,
+            fillColor: d3Color
+              .color(this.colorMap.get(genotype))
+              .copy({ opacity: 0.5 })
+              .toString(),
+          }
+        }),
+      }
+      const genotypeScatterSeries = genotypeList.map((genotype, x) => {
+        return {
+          name: genotype,
+          type: 'scatter',
+          color: this.colorMap.get(genotype),
+          marker: { radius: 3 },
+          jitter: {
+            x: 0.1,
+            y: 0,
+          },
+          tooltip: {
+            headerFormat:
+              '<b>Genotype</b>: <tspan style="fill:{series.color}"><b>{series.name}</b></tspan></br>',
+            pointFormat: `<b>Phenotype</b>: {point.y}</br><b>Ccline</b>: {point.ccline}`,
+          },
+          data: groupedByGenotype
+            .get(genotype)
+            .map(({ phenotype, ccline, genotype, id }) => ({
+              id,
+              x,
+              y: phenotype,
+              genotype,
+              ccline,
+            })),
+        }
+      })
+
+      return {
+        ...this.chartOptions,
+        chart: {
+          ...this.chartOptions.chart,
+          // events: {
+          //   redraw: this.selectionEventHandler,
+          // },
+        },
+        xAxis: {
+          categories: genotypeList,
+          title: {
+            text: 'CC lines',
+          },
+        },
+        series: [genotypeBoxPlotSerie, ...genotypeScatterSeries],
+      }
+    },
+  },
+  // methods: {
+  //   selectionEventHandler(event) {
+  //     const selectedPoint = new Set()
+  //     if (event?.resetSelection) {
+  //       this.$emit('selection', null)
+  //     } else {
+  //       highcharts.each(event.target.series, (serie) => {
+  //         if (serie.type === 'scatter') {
+  //           highcharts.each(serie.points, (point) => {
+  //             if (point.isInside) {
+  //               selectedPoint.add(point.id)
+  //             }
+  //           })
+  //         }
+  //       })
+  //       this.$emit('selection', selectedPoint)
+  //     }
+  //   },
+  // },
+}
+</script>
diff --git a/client-nuxt/layouts/default.vue b/client-nuxt/layouts/default.vue
index d08536488f1c9eb8b8c6b359a3258de7db1d8b75..2e31009478cfb44188b3bc9b022d042190d0bdb4 100644
--- a/client-nuxt/layouts/default.vue
+++ b/client-nuxt/layouts/default.vue
@@ -1,25 +1,64 @@
 <template>
-  <v-app dark>
+  <v-app>
     <v-navigation-drawer
+      v-if="$auth.loggedIn"
       v-model="drawer"
       :mini-variant="miniVariant"
+      :mini-variant-width="70"
       :clipped="clipped"
       fixed
+      floating
       app
     >
       <v-list>
+        <v-list-item nuxt :to="authUserRoute">
+          <v-list-item-icon>
+            <v-icon>mdi-account-circle</v-icon>
+          </v-list-item-icon>
+          <v-list-item-content>
+            <v-list-item-title>{{ $auth.user.username }} </v-list-item-title>
+            <v-list-item-subtitle
+              >{{ $auth.user.first_name }}
+              {{ $auth.user.last_name }}</v-list-item-subtitle
+            >
+          </v-list-item-content>
+        </v-list-item>
+        <v-divider></v-divider>
         <v-list-item
-          v-for="(item, i) in items"
+          v-for="(item, i) in sanitizedItems"
           :key="i"
           :to="item.to"
           router
           exact
         >
           <v-list-item-action>
-            <v-icon>{{ item.icon }}</v-icon>
+            <v-badge
+              v-if="item.hasOwnProperty('count') && miniVariant"
+              :content="item.count.value"
+              :offset-y="10"
+            >
+              <v-icon>{{ item.icon }}</v-icon></v-badge
+            >
+            <v-icon v-else>{{ item.icon }}</v-icon>
           </v-list-item-action>
           <v-list-item-content>
-            <v-list-item-title v-text="item.title" />
+            <v-list-item-title
+              v-if="item.hasOwnProperty('count') && !miniVariant"
+            >
+              <v-badge :content="item.count.value">
+                {{ item.title }}</v-badge
+              ></v-list-item-title
+            >
+            <v-list-item-title v-else v-text="item.title" />
+          </v-list-item-content>
+        </v-list-item>
+
+        <v-list-item v-if="$auth.loggedIn" @click="$auth.logout()">
+          <v-list-item-icon>
+            <v-icon color="error">mdi-logout</v-icon>
+          </v-list-item-icon>
+          <v-list-item-content>
+            <v-list-item-title>Logout</v-list-item-title>
           </v-list-item-content>
         </v-list-item>
       </v-list>
@@ -37,10 +76,6 @@
       </v-btn>
       <v-toolbar-title v-text="title" />
       <v-spacer />
-
-      <v-btn v-if="this.$auth.loggedIn" color="error" @click="$auth.logout()">
-        LOGOUT
-      </v-btn>
     </v-app-bar>
     <v-main>
       <v-container fluid>
@@ -48,33 +83,66 @@
       </v-container>
     </v-main>
     <v-footer :fixed="fixed" app>
-      <span>&copy; {{ new Date().getFullYear() }}</span>
+      <v-container fluid>
+        <v-card class="d-flex justify-space-between" flat color="transparent">
+          <v-card flat color="transparent"> </v-card>
+          <v-card flat color="transparent">
+            <v-btn icon @click="switchTheme()"
+              ><v-icon>{{ themeIcon }}</v-icon></v-btn
+            ></v-card
+          >
+        </v-card>
+      </v-container>
     </v-footer>
   </v-app>
 </template>
 
 <script>
+import { mapActions } from 'vuex'
+
 export default {
   data() {
     return {
-      clipped: false,
+      clipped: true,
       drawer: true,
       fixed: false,
       items: [
         {
-          icon: 'mdi-apps',
-          title: 'Welcome',
+          icon: 'mdi-home',
+          title: 'Home',
           to: '/',
         },
         {
-          icon: 'mdi-baguette',
+          icon: 'mdi-account-multiple',
+          title: 'Users',
+          to: '/users',
+        },
+        {
+          icon: 'mdi-rodent',
           title: 'Projects',
           to: '/projects',
+          count: {
+            name: 'projects',
+            value: 0,
+          },
         },
         {
-          icon: 'mdi-bread-slice',
+          icon: 'mdi-file-chart',
           title: 'Analysis',
           to: '/analysis',
+          count: {
+            name: 'analysis',
+            value: 0,
+          },
+        },
+        {
+          icon: 'mdi-flask',
+          title: 'Experiments',
+          to: '/experiments',
+          count: {
+            name: 'experiments',
+            value: 0,
+          },
         },
         // {
         //   icon: 'mdi-account-group',
@@ -83,8 +151,8 @@ export default {
         // },
         {
           icon: 'mdi-shape',
-          title: 'Variable Categories',
-          to: '/variable-categories',
+          title: 'Phenotype Categories',
+          to: '/phenotype-categories',
         },
       ],
       miniVariant: false,
@@ -92,5 +160,81 @@ export default {
       title: 'Pasteur CC-QTL',
     }
   },
+  computed: {
+    authUserRoute() {
+      return {
+        name: 'users-userId',
+        params: { userId: this.$auth.user.id },
+      }
+    },
+    themeIcon() {
+      return this.$vuetify.theme.dark
+        ? this.$store.state.theme.lightIcon
+        : this.$store.state.theme.darkIcon
+    },
+    analysisCount() {
+      return this.$store.state.analysis.count
+    },
+    projectsCount() {
+      return this.$store.state.projects.count
+    },
+    experimentsCount() {
+      return this.$store.state.experiments.count
+    },
+
+    sanitizedItems() {
+      return this.items.map((item) => {
+        if (item?.count?.name === 'analysis') {
+          return {
+            ...item,
+            count: { ...item.count, value: this.analysisCount },
+          }
+        } else if (item?.count?.name === 'experiments') {
+          return {
+            ...item,
+            count: { ...item.count, value: this.experimentsCount },
+          }
+        } else if (item?.count?.name === 'projects') {
+          return {
+            ...item,
+            count: { ...item.count, value: this.projectsCount },
+          }
+        } else {
+          return item
+        }
+      })
+    },
+  },
+  beforeMount() {
+    const theme = localStorage.getItem('useDarkTheme')
+    if (theme) {
+      if (theme === 'true') {
+        this.$vuetify.theme.dark = true
+      } else {
+        this.$vuetify.theme.dark = false
+      }
+    }
+  },
+  mounted() {
+    this.updateAnalysisCount()
+    this.updateProjectsCount()
+    this.updateExperimentsCount()
+  },
+  beforeUpdate() {
+    this.updateAnalysisCount()
+    this.updateProjectsCount()
+    this.updateExperimentsCount()
+  },
+  methods: {
+    switchTheme() {
+      this.$vuetify.theme.dark = !this.$vuetify.theme.dark
+      // localStorage.setItem('useDarkTheme', this.$vuetify.theme.dark.toString())
+    },
+    ...mapActions({
+      updateAnalysisCount: 'updateAnalysisCount',
+      updateProjectsCount: 'updateProjectsCount',
+      updateExperimentsCount: 'updateExperimentsCount',
+    }),
+  },
 }
 </script>
diff --git a/client-nuxt/layouts/error.vue b/client-nuxt/layouts/error.vue
index 1c154b45c3b14b04d088a673b6465e734e1b5424..81663fa915e93de6c5de0d36d917de1072287e24 100644
--- a/client-nuxt/layouts/error.vue
+++ b/client-nuxt/layouts/error.vue
@@ -1,5 +1,5 @@
 <template>
-  <v-app dark>
+  <v-app>
     <h1 v-if="error.statusCode === 404">
       {{ pageNotFound }}
       <NuxtLink to="/"> Home page </NuxtLink>
diff --git a/client-nuxt/nuxt.config.js b/client-nuxt/nuxt.config.js
index 148729a0c62a8148d9c764547e7c628934bc08c4..95e2b9eecbd4425ec5b9614b13af292aa6804157 100644
--- a/client-nuxt/nuxt.config.js
+++ b/client-nuxt/nuxt.config.js
@@ -11,8 +11,8 @@ export default {
    ** Headers of the page
    */
   head: {
-    titleTemplate: '%s - ' + process.env.npm_package_name,
-    title: process.env.npm_package_name || '',
+    titleTemplate: '%s',
+    title: 'CC-QTL @ Pasteur',
     meta: [
       { charset: 'utf-8' },
       { name: 'viewport', content: 'width=device-width, initial-scale=1' },
@@ -27,7 +27,7 @@ export default {
   /*
    ** Customize the progress-bar color
    */
-  loading: { color: colors.amber.darken3, height: '8px' },
+  loading: { color: colors.amber.darken3, height: '4px' },
   /*
    ** Global CSS
    */
@@ -35,7 +35,12 @@ export default {
   /*
    ** Plugins to load before mounting the App
    */
-  plugins: [],
+  plugins: [
+    {
+      src: '~/plugins/highcharts.js',
+      ssr: true,
+    },
+  ],
   /*
    ** Nuxt.js dev-modules
    */
@@ -84,7 +89,8 @@ export default {
           maxAge: false,
         },
         user: {
-          property: 'id',
+          property: false,
+          autoFetch: true,
         },
         clientId: false,
         grantType: false,
@@ -107,24 +113,51 @@ export default {
   vuetify: {
     customVariables: ['~/assets/variables.scss'],
     theme: {
-      dark: true,
+      options: {
+        customProperties: true,
+      },
+      dark: false,
       themes: {
         dark: {
-          primary: colors.blue.darken2,
-          accent: colors.grey.darken3,
-          secondary: colors.amber.darken3,
-          info: colors.teal.lighten1,
-          warning: colors.amber.base,
-          error: colors.deepOrange.accent4,
-          success: colors.green.darken3,
+          //     primary: colors.blue.darken2,
+          //     accent: colors.grey.darken3,
+          //     secondary: colors.amber.darken3,
+          //     info: colors.teal.lighten1,
+          //     warning: colors.amber.base,
+          //     error: colors.deepOrange.accent4,
+          //     success: colors.green.darken3,
+        },
+        light: {
+          //     primary: '#1976D2',
+          secondary: {
+            base: '#424242',
+            lighten6: colors.grey.lighten3,
+            lighten5: '#c1c1c1',
+            lighten4: '#a6a6a6',
+            lighten3: '#8b8b8b',
+            lighten2: '#727272',
+            lighten1: '#595959',
+            darken1: '#2c2c2c',
+            darken2: '#171717',
+            darken3: '#000000',
+            darken4: '#000000',
+          },
+          //     accent: '#82B1FF',
+          //     error: '#FF5252',
+          //     info: '#2196F3',
+          //     success: '#4CAF50',
+          //     warning: '#FFC107',
         },
       },
     },
   },
+
   /*
    ** Build configuration
    */
   build: {
+    // Add exception
+    transpile: ['vee-validate/dist/rules'],
     /*
      ** You can extend webpack config here
      */
diff --git a/client-nuxt/package.json b/client-nuxt/package.json
index c0df779bfaf24c4312e3b487acd0d88c3bd59431..1785a3a5335016316f45c20dfab0fbde2d7e018b 100644
--- a/client-nuxt/package.json
+++ b/client-nuxt/package.json
@@ -2,7 +2,7 @@
   "name": "client-nuxt",
   "version": "1.0.0",
   "description": "A nuxt client for cc-qtl analysis",
-  "author": "Remi Planel",
+  "author": "Remi Planell",
   "private": true,
   "scripts": {
     "dev": "nuxt",
@@ -17,9 +17,13 @@
     "@nuxtjs/auth-next": "^5.0.0-1588866376.2380814",
     "@nuxtjs/axios": "^5.12.0",
     "@nuxtjs/proxy": "^1.3.3",
-    "bioviz-js": "0.1.4",
-    "d3-array": "^2.8.0",
+    "d3-array": "^3.0.2",
+    "d3-color": "^3.0.1",
+    "d3-scale": "^4.0.0",
+    "d3-scale-chromatic": "^3.0.0",
     "d3-selection": "^2.0.0",
+    "highcharts": "^9.2.2",
+    "highcharts-vue": "^1.4.0",
     "nuxt": "^2.14.0",
     "papaparse": "^5.3.0",
     "vee-validate": "^3.3.0",
@@ -30,6 +34,7 @@
     "@nuxtjs/eslint-config": "^3.1.0",
     "@nuxtjs/eslint-module": "^2.0.0",
     "@nuxtjs/vuetify": "^1.11.2",
+    "@vue/runtime-dom": "^3.2.32",
     "@vue/test-utils": "^1.0.3",
     "babel-core": "7.0.0-bridge.0",
     "babel-eslint": "^10.1.0",
diff --git a/client-nuxt/pages/analysis.vue b/client-nuxt/pages/analysis.vue
index 81b906fdd62a0fc663eaaba410521b85f1ae871e..d22ac86440f9d04e7c5733a45d608ea1cebc35ab 100644
--- a/client-nuxt/pages/analysis.vue
+++ b/client-nuxt/pages/analysis.vue
@@ -1,82 +1,67 @@
 <template>
-  <v-card
-    ><v-card-title>
-      Analysis
-      <v-spacer></v-spacer>
-      <v-text-field
-        v-model="search"
-        append-icon="mdi-magnify"
-        label="Search"
-        single-line
-        hide-details
-      ></v-text-field>
-    </v-card-title>
-    <v-data-table
+  <v-card>
+    <generic-table
+      type="analysis"
+      :items="sanitizedAnalysis"
       :headers="headers"
-      :items="analysis"
-      :items-per-page="15"
-      :search="search"
-      :footer-props="dataTableFooterProps"
-      class="elevation-1"
-      @click:row="goToAnalysis"
-    >
-      <template v-slot:[`item.history_status.state`]="row">
-        <v-icon v-if="row.item.history_status.state == 'ok'" color="success"
-          >mdi-check-circle</v-icon
-        >
-        <v-progress-circular
-          v-else-if="row.item.history_status.state == 'running'"
-          indeterminate
-          :width="2"
-          :size="25"
-          color="primary"
-        ></v-progress-circular>
-        <v-icon
-          v-else-if="row.item.history_status.state == 'new'"
-          color="primary"
-          >mdi-new-box</v-icon
-        >
-        <v-icon
-          v-else-if="row.item.history_status.state == 'paused'"
-          color="primary"
-          >mdi-pause-circle</v-icon
-        >
-        <v-icon
-          v-else-if="row.item.history_status.state == 'error'"
-          color="error"
-          >mdi-alert-circle</v-icon
-        >
-        <v-icon v-else color="warning">mdi-alert-circle</v-icon>
-      </template>
-    </v-data-table>
+      :sort-by="['id']"
+      :loading="$fetchState.pending"
+      title="Analysis"
+      @go-to-item="goToAnalysis"
+    ></generic-table>
+    <v-card-text>
+      <error-alert v-if="error" :error-message="error"></error-alert>
+    </v-card-text>
   </v-card>
 </template>
 
 <script>
+import GenericTable from '@/components/GenericTable.vue'
+import ErrorAlert from '@/components/ErrorAlert'
+
 export default {
-  async asyncData({ $axios, params, $auth }) {
-    const analysis = (await $axios.$get(`/api/analysis`)).map((item) => ({
-      ...item,
-      creation_date: new Date(item.creation_date).toDateString(),
-    }))
-    return {
-      analysis,
+  components: {
+    GenericTable,
+    ErrorAlert,
+  },
+  async fetch() {
+    try {
+      this.analysis = await this.$axios.$get(`/api/analysis/`)
+    } catch (error) {
+      this.error = error
     }
   },
+
   data() {
     return {
       analysis: [],
+      error: null,
       search: '',
       headers: [
         { text: 'Id', value: 'id' },
         { text: 'Name', value: 'name' },
+        { text: 'Description', value: 'description' },
         { text: 'Creation Date', value: 'creation_date' },
-        { text: 'Project Name', value: 'project.project_name' },
-        { text: 'Status', value: 'history_status.state' },
+        { text: 'Galaxy history state', value: 'history_status' },
+        { text: 'Galaxy workflow State', value: 'workflow_invocation_status' },
+        { text: 'Project', value: 'project.project_name' },
+        { text: 'Experiment', value: 'experiment.name' },
       ],
-      dataTableFooterProps: { 'items-per-page-options': [10, 20, 30, -1] },
+      dataTableFooterProps: { 'items-per-page-options': [15, 30, 45, -1] },
     }
   },
+  computed: {
+    sanitizedAnalysis() {
+      return this.analysis.map((item) => ({
+        ...item,
+        creation_date: new Date(item.creation_date),
+        experiment: item.experiments.length > 0 ? item.experiments[0] : null,
+      }))
+    },
+  },
+  mounted() {
+    this.$fetch()
+  },
   methods: {
     goToAnalysis(ev) {
       const {
@@ -88,8 +73,9 @@ export default {
         params: { id: projectId, analysisId },
       })
     },
+    getRowClass() {
+      return 'is-route'
+    },
   },
 }
 </script>
-
-<style></style>
diff --git a/client-nuxt/pages/experiments.vue b/client-nuxt/pages/experiments.vue
new file mode 100644
index 0000000000000000000000000000000000000000..7a56d8cdc4b4f0188c3d0f22542bee509198c46d
--- /dev/null
+++ b/client-nuxt/pages/experiments.vue
@@ -0,0 +1,75 @@
+<template>
+  <v-card>
+    <generic-table
+      type="experiments"
+      :items="sanitizedExperiments"
+      :headers="headers"
+      :sort-by="['id']"
+      :loading="$fetchState.pending"
+      title="Experiments"
+      @go-to-item="goToExperiments"
+    ></generic-table>
+    <v-card-text>
+      <error-alert v-if="error" :error-message="error"></error-alert>
+    </v-card-text>
+  </v-card>
+</template>
+
+<script>
+import ErrorAlert from '@/components/ErrorAlert'
+import GenericTable from '@/components/GenericTable.vue'
+export default {
+  components: {
+    GenericTable,
+    ErrorAlert,
+  },
+  async fetch() {
+    try {
+      this.experiments = await this.$axios.$get(`/api/experiments/`)
+    } catch (error) {
+      this.error = error
+    }
+  },
+  data() {
+    return {
+      experiments: [],
+      error: null,
+      search: '',
+      headers: [
+        { text: 'Id', value: 'id' },
+        { text: 'Name', value: 'name' },
+        { text: 'Description', value: 'description' },
+        { text: 'Creation Date', value: 'creation_date' },
+        { text: 'Project', value: 'project.project_name' },
+      ],
+      dataTableFooterProps: { 'items-per-page-options': [15, 30, 45, -1] },
+    }
+  },
+  computed: {
+    sanitizedExperiments() {
+      return this.experiments.map((item) => ({
+        ...item,
+        creation_date: new Date(item.creation_date),
+      }))
+    },
+  },
+  mounted() {
+    this.$fetch()
+  },
+  methods: {
+    goToExperiments(ev) {
+      const {
+        project: { id: projectId },
+        id: experimentId,
+      } = ev
+      this.$router.push({
+        name: 'projects-id-experiments-experimentId',
+        params: { id: projectId, experimentId },
+      })
+    },
+    getRowClass() {
+      return 'is-route'
+    },
+  },
+}
+</script>
diff --git a/client-nuxt/pages/index.vue b/client-nuxt/pages/index.vue
index 8e5fa4700c6a24ad3c49f25420e8235928f4924f..01320276e668df9f886fa88dbc02ed9a2fda52d6 100644
--- a/client-nuxt/pages/index.vue
+++ b/client-nuxt/pages/index.vue
@@ -1,22 +1,50 @@
 <template>
-  <v-layout column justify-center align-center>
-    <v-flex xs12 sm8 md6>
-      <div class="text-center">
-        <logo />
-        <vuetify-logo />
-      </div>
-    </v-flex>
-  </v-layout>
+  <v-row align-content="center" justify="center">
+    <v-col>
+      <v-card>
+        <v-card-title>Welcome on the CC-QTL interface!</v-card-title>
+        <v-card-text>
+          CC-QTL interface is meant to facilitate QTL mapping and SNP
+          association in the Collaborative Cross, providing experimentalists
+          with a graphical user interface to run such analyses.
+        </v-card-text>
+        <v-card-text>
+          Beyond the analysis modules, CC-QTL also host a database.</v-card-text
+        >
+        <v-card-text>
+          CC-QTL is still under development, reach us for help or
+          suggestions!</v-card-text
+        >
+      </v-card>
+      <v-card class="my-5">
+        <v-list-item two-line>
+          <v-list-item-content>
+            <v-list-item-title>Interface and database</v-list-item-title>
+            <v-list-item-subtitle
+              >Rémi Planel, Hub Bioinformatics
+              Biostatistics</v-list-item-subtitle
+            >
+          </v-list-item-content>
+        </v-list-item>
+        <v-list-item two-line>
+          <v-list-item-content>
+            <v-list-item-title>UX/UI</v-list-item-title>
+            <v-list-item-subtitle
+              >Rachel Torchet, Hub Bioinformatics Biostatistics
+            </v-list-item-subtitle>
+          </v-list-item-content>
+        </v-list-item>
+        <v-list-item two-line>
+          <v-list-item-content>
+            <v-list-item-title>Analysis</v-list-item-title>
+            <v-list-item-subtitle>
+              Victoire Baillet, Pascal Campagne* Hub Bioinformatics
+              Biostatistics
+            </v-list-item-subtitle>
+          </v-list-item-content>
+        </v-list-item>
+      </v-card>
+      <v-card> </v-card>
+    </v-col>
+  </v-row>
 </template>
-
-<script>
-import Logo from '~/components/Logo.vue'
-import VuetifyLogo from '~/components/VuetifyLogo.vue'
-
-export default {
-  components: {
-    Logo,
-    VuetifyLogo,
-  },
-}
-</script>
diff --git a/client-nuxt/pages/login.vue b/client-nuxt/pages/login.vue
index 893ea83895c63bd062c0e45bf52a29922684d566..b951de8956b22f959e504d954e5adf93b3947d8d 100644
--- a/client-nuxt/pages/login.vue
+++ b/client-nuxt/pages/login.vue
@@ -1,65 +1,74 @@
 <template>
-  <div class="login-form">
-    <ValidationObserver ref="observer" v-slot="{ invalid }">
-      <form @submit.prevent="submit">
-        <v-container fluid>
-          <error-alert v-if="logError" :error-message="logError"></error-alert>
-          <v-card>
-            <v-card-title>{{ title }}</v-card-title>
-            <v-card-text>
-              <v-row>
-                <v-col cols="12" sm="12" md="6" lg="5">
-                  <ValidationProvider
-                    v-slot="{ errors }"
-                    name="username"
-                    rules="required|max:50"
+  <v-container>
+    <v-row justify="center">
+      <v-col cols="12" sm="12" md="10" lg="8">
+        <v-card class="login-form">
+          <ValidationObserver ref="observer" v-slot="{ invalid }">
+            <v-form v-model="valid" @submit.prevent="submit">
+              <error-alert
+                v-if="logError"
+                :error-message="logError"
+              ></error-alert>
+              <v-card>
+                <v-card-title>{{ title }}</v-card-title>
+                <v-card-text>
+                  <v-container>
+                    <v-row justify="center">
+                      <v-col>
+                        <ValidationProvider
+                          v-slot="{ errors }"
+                          name="username"
+                          rules="required|max:50"
+                        >
+                          <v-text-field
+                            v-model="login.username"
+                            placeholder="Enter your username"
+                            label="Username"
+                            :counter="50"
+                            :error-messages="errors"
+                            outlined
+                            required
+                          ></v-text-field>
+                        </ValidationProvider>
+                      </v-col>
+                    </v-row>
+                    <v-row justify="center">
+                      <v-col>
+                        <ValidationProvider
+                          v-slot="{ errors }"
+                          name="password"
+                          rules="required"
+                        >
+                          <v-text-field
+                            v-model="login.password"
+                            :error-messages="errors"
+                            type="password"
+                            placeholder="Enter your password"
+                            label="Password"
+                            outlined
+                            required
+                          ></v-text-field>
+                        </ValidationProvider>
+                      </v-col>
+                    </v-row>
+                  </v-container>
+                </v-card-text>
+                <v-card-actions>
+                  <v-btn
+                    id="submit-auth-btn"
+                    type="submit"
+                    class="submit-auth"
+                    :disabled="invalid"
+                    >Sign In</v-btn
                   >
-                    <v-text-field
-                      v-model="login.username"
-                      placeholder="Enter your username"
-                      label="Username"
-                      :counter="50"
-                      :error-messages="errors"
-                      outlined
-                      required
-                    ></v-text-field>
-                  </ValidationProvider>
-                </v-col>
-              </v-row>
-              <v-row>
-                <v-col cols="12" sm="12" md="6" lg="5">
-                  <ValidationProvider
-                    v-slot="{ errors }"
-                    name="password"
-                    rules="required"
-                  >
-                    <v-text-field
-                      v-model="login.password"
-                      :error-messages="errors"
-                      type="password"
-                      placeholder="Enter yout password"
-                      label="Password"
-                      outlined
-                      required
-                    ></v-text-field>
-                  </ValidationProvider>
-                </v-col>
-              </v-row>
-            </v-card-text>
-            <v-card-actions>
-              <v-btn
-                id="submit-auth-btn"
-                class="submit-auth"
-                :disabled="invalid"
-                @click="submit"
-                >Sign In</v-btn
-              >
-            </v-card-actions>
-          </v-card>
-        </v-container>
-      </form>
-    </ValidationObserver>
-  </div>
+                </v-card-actions>
+              </v-card>
+            </v-form>
+          </ValidationObserver>
+        </v-card>
+      </v-col>
+    </v-row>
+  </v-container>
 </template>
 
 <script>
@@ -92,8 +101,9 @@ export default {
   },
   data() {
     return {
+      valid: false,
       logError: null,
-      title: 'Sign Up to CC-QTL-DB',
+      title: 'Sign up',
       login: {
         username: '',
         password: '',
@@ -116,7 +126,7 @@ export default {
         if (err.response.status === 401) {
           this.logError = 'Wrong password or username.'
         } else {
-          this.logError = err
+          this.logError = err.message
         }
       }
     },
diff --git a/client-nuxt/pages/phenotype-categories.vue b/client-nuxt/pages/phenotype-categories.vue
new file mode 100644
index 0000000000000000000000000000000000000000..64acba1f7ab44b8dd5b352fee7f34911b10f0673
--- /dev/null
+++ b/client-nuxt/pages/phenotype-categories.vue
@@ -0,0 +1,9 @@
+<template>
+  <nuxt-child></nuxt-child>
+</template>
+
+<script>
+export default {}
+</script>
+
+<style></style>
diff --git a/client-nuxt/pages/phenotype-categories/add.vue b/client-nuxt/pages/phenotype-categories/add.vue
new file mode 100644
index 0000000000000000000000000000000000000000..e6ff1418f5b72da8567a90038b72fbc321b8aa7b
--- /dev/null
+++ b/client-nuxt/pages/phenotype-categories/add.vue
@@ -0,0 +1,114 @@
+<template>
+  <v-card>
+    <v-toolbar v-if="isFromAddExperiment" flat>
+      <v-btn text nuxt x-small :to="fromAddExperiment">
+        <v-icon left> mdi-arrow-left</v-icon> Upload experiment in project :
+        <span class="primary--text"> {{ projectName }}</span>
+      </v-btn></v-toolbar
+    >
+    <v-card-text>
+      <phenotype-category-form
+        v-if="canAdd"
+        :options="options"
+        :form-title="formTitle"
+        v-bind.sync="phenotypeCategory"
+        :has-cancel-btn="!isFromAddExperiment"
+        @save="goBackOrToPhenotypeCategories"
+        @cancel="goBackOrToPhenotypeCategories"
+      >
+        <template v-if="fromAddExperiment" #save-btn-text>
+          Save
+          <span class="text-disabled text-lowercase text-caption"
+            >(And go back to upload experiment in
+            <span class="font-weight-bold"> {{ projectName }}</span
+            >)</span
+          ></template
+        >
+      </phenotype-category-form>
+      <v-alert v-else type="error" prominent text>
+        You don't have the permissions to add new phenotype categories</v-alert
+      ></v-card-text
+    >
+  </v-card>
+</template>
+<script>
+import PhenotypeCategoryForm from '@/components/PhenotypeCategoryForm'
+export default {
+  components: {
+    PhenotypeCategoryForm,
+  },
+  async asyncData({ $axios }) {
+    const permissions = await $axios.$get(
+      '/api/phenotype-categories/permissions/'
+    )
+    const endpointOptions = await $axios.$options('/api/phenotype-categories/')
+    let options = null
+    if (endpointOptions?.actions?.POST) {
+      options = endpointOptions.actions.POST
+    }
+    return {
+      options,
+      permissions: new Set(permissions),
+    }
+  },
+
+  data() {
+    return {
+      formTitle: 'New phenotype category',
+      phenotypeCategory: {
+        name: '',
+        description: '',
+        datatype: 'Unassigned',
+        dataclass: 'Phenotype',
+        nature: 'Unassigned',
+        location: 'Unassigned',
+      },
+      fromAddExperiment: null,
+      projectName: null,
+    }
+  },
+  computed: {
+    canAdd() {
+      return this.permissions.has('add')
+    },
+    projectId() {
+      return this?.fromAddExperiment?.params?.id
+    },
+    isFromAddExperiment() {
+      return this.fromAddExperiment?.name
+    },
+  },
+  watch: {
+    async projectId(newProjectId) {
+      if (newProjectId !== undefined) {
+        try {
+          const {
+            data: { project_name: projectName },
+          } = await this.$axios.get(`/api/projects/${newProjectId}/`)
+          this.projectName = projectName
+        } catch (err) {}
+      }
+    },
+  },
+  methods: {
+    goBackOrToPhenotypeCategories() {
+      if (this.isFromAddExperiment) {
+        this.$router.push(this.fromAddExperiment)
+      } else {
+        this.$router.push({ name: 'phenotype-categories' })
+      }
+    },
+    async getProject(projectId) {},
+  },
+  beforeRouteEnter(to, from, next) {
+    next((vm) => {
+      if (from.name === 'projects-id-experiments-add')
+        vm.fromAddExperiment = from
+    })
+  },
+  beforeRouteLeave(to, from, next) {
+    this.fromAddExperiment = null
+    next()
+  },
+}
+</script>
diff --git a/client-nuxt/pages/phenotype-categories/index.vue b/client-nuxt/pages/phenotype-categories/index.vue
new file mode 100644
index 0000000000000000000000000000000000000000..c9538639c7f34c6388dc88ac7bb2471df7ee87b2
--- /dev/null
+++ b/client-nuxt/pages/phenotype-categories/index.vue
@@ -0,0 +1,217 @@
+<template>
+  <v-card flat>
+    <error-alert v-if="error" :error-message="error"></error-alert>
+    <v-data-table
+      :headers="headers"
+      :items="phenotypeCategories"
+      :sort-by="['dataclass', 'name']"
+      :sort-desc="[true, false]"
+      :search="search"
+      :loading="$fetchState.pending"
+      multi-sort
+      class="elevation-1"
+    >
+      <template v-slot:top>
+        <v-toolbar flat>
+          <v-toolbar-title> Phenotype Categories </v-toolbar-title>
+          <v-divider class="mx-4" inset vertical></v-divider>
+          <v-text-field
+            v-model="search"
+            append-icon="mdi-magnify"
+            label="Search"
+            single-line
+            hide-details
+          ></v-text-field>
+          <v-spacer></v-spacer>
+          <v-btn
+            v-if="canAdd"
+            small
+            color="primary"
+            fab
+            nuxt
+            :to="addPhenotypeCategoryRoute"
+          >
+            <v-icon> mdi-plus </v-icon>
+          </v-btn>
+          <v-dialog v-model="dialogDelete" max-width="800px">
+            <v-card>
+              <v-card-title class="text-h5"
+                >Are you sure you want to delete this phenotype
+                category?</v-card-title
+              >
+              <v-card-actions>
+                <v-spacer></v-spacer>
+                <v-btn color="blue darken-1" text @click="closeDelete"
+                  >Cancel</v-btn
+                >
+                <v-btn color="blue darken-1" text @click="deleteItemConfirm"
+                  >OK</v-btn
+                >
+                <v-spacer></v-spacer>
+              </v-card-actions>
+            </v-card>
+          </v-dialog>
+        </v-toolbar>
+      </template>
+      <template #[`item.actions`]="{ item }">
+        <v-icon
+          v-if="permissions.has('change')"
+          small
+          class="mr-2"
+          @click="editItem(item)"
+        >
+          mdi-pencil
+        </v-icon>
+        <v-icon
+          v-if="permissions.has('delete')"
+          small
+          @click="deleteItem(item)"
+        >
+          mdi-delete
+        </v-icon>
+      </template>
+      <template v-slot:no-data>
+        <v-btn color="primary" @click="initialize"> Reset </v-btn>
+      </template></v-data-table
+    >
+    <v-dialog v-model="dialog" max-width="800px">
+      <phenotype-category-form
+        :options="options"
+        form-title="Edit Phenotype Category"
+        :new-item="newItem"
+        v-bind.sync="phenotypeCategory"
+        @save="save"
+        @cancel="close"
+      ></phenotype-category-form
+    ></v-dialog>
+  </v-card>
+</template>
+<script>
+import ErrorAlert from '@/components/ErrorAlert'
+
+import PhenotypeCategoryForm from '@/components/PhenotypeCategoryForm'
+export default {
+  components: {
+    PhenotypeCategoryForm,
+    ErrorAlert,
+  },
+  async fetch() {
+    try {
+      this.phenotypeCategories = await this.$axios.$get(
+        `/api/phenotype-categories/`
+      )
+    } catch (error) {
+      return { error: error.message }
+    }
+  },
+  async asyncData({ $axios }) {
+    const permissions = await $axios.$get(
+      '/api/phenotype-categories/permissions/'
+    )
+    const endpointOptions = await $axios.$options('/api/phenotype-categories/')
+    let options = null
+    if (endpointOptions?.actions?.POST) {
+      options = endpointOptions.actions.POST
+    }
+    return {
+      options,
+      permissions: new Set(permissions),
+    }
+  },
+  data() {
+    return {
+      fromAddExperiment: null,
+      search: '',
+      dialog: false,
+      dialogDelete: false,
+      newItem: true,
+      error: null,
+      phenotypeCategory: {
+        name: '',
+        description: '',
+        datatype: 'Unassigned',
+        dataclass: 'Phenotype',
+        nature: 'Unassigned',
+        location: 'Unassigned',
+      },
+      allHeaders: [
+        {
+          text: 'Name',
+          align: 'start',
+          value: 'name',
+        },
+        { text: 'Description', value: 'description' },
+        { text: 'Data Class', value: 'dataclass' },
+        { text: 'Datatype', value: 'datatype' },
+        { text: 'Nature', value: 'nature' },
+        { text: 'Location', value: 'location' },
+        { text: 'Actions', value: 'actions', sortable: false },
+      ],
+      phenotypeCategories: [],
+    }
+  },
+  computed: {
+    addPhenotypeCategoryRoute() {
+      return { name: 'phenotype-categories-add' }
+    },
+    canChangeOrDelete() {
+      return this.permissions.has('change') || this.permissions.has('delete')
+    },
+    headers() {
+      return this.canChangeOrDelete
+        ? this.allHeaders
+        : this.allHeaders.filter(({ value }) => value !== 'actions')
+    },
+    canAdd() {
+      return this.permissions.has('add')
+    },
+  },
+  mounted() {
+    this.$fetch()
+  },
+  methods: {
+    editItem(item) {
+      this.phenotypeCategory = { ...item }
+      this.dialog = true
+      this.newItem = false
+    },
+    deleteItem(item) {
+      this.phenotypeCategory = { ...item }
+      this.dialogDelete = true
+    },
+    async deleteItemConfirm() {
+      try {
+        await this.$axios.$delete(
+          `/api/phenotype-categories/${this.phenotypeCategory.id}`
+        )
+        this.$fetch()
+      } catch (err) {
+        console.dir(err)
+        if (err?.response?.data && err.response.data.length > 0) {
+          this.error = err.response.data[0]
+        } else {
+          this.error = err.message
+        }
+      } finally {
+        this.closeDelete()
+      }
+    },
+    closeDelete() {
+      this.dialogDelete = false
+      this.$nextTick(() => {
+        this.newItem = false
+      })
+    },
+    close() {
+      this.dialog = false
+      this.$nextTick(() => {
+        this.newItem = false
+      })
+    },
+    save() {
+      this.$fetch()
+      this.close()
+    },
+  },
+}
+</script>
diff --git a/client-nuxt/pages/projects.vue b/client-nuxt/pages/projects.vue
index 7899445d732450e6fac11b78283159037fb9de97..f5b0e72946e2a6852b2dd8311c696116c793e503 100644
--- a/client-nuxt/pages/projects.vue
+++ b/client-nuxt/pages/projects.vue
@@ -1,26 +1,5 @@
 <template>
-  <div>
-    <User :user="user" />
+  <v-card flat color="transparent">
     <nuxt-child />
-  </div>
+  </v-card>
 </template>
-<script>
-import User from '~/components/User'
-
-export default {
-  components: {
-    User,
-  },
-  async asyncData({ $axios, params, $auth }) {
-    const user = await $axios.$get(`/api/users/${$auth.user}`)
-    return {
-      user,
-    }
-  },
-  data() {
-    return {
-      user: {},
-    }
-  },
-}
-</script>
diff --git a/client-nuxt/pages/projects/_id.vue b/client-nuxt/pages/projects/_id.vue
index d8500fc97896708fef3f99c8080ea5ea069da635..718f9297a9503a4059657880eebc86fd50929e88 100644
--- a/client-nuxt/pages/projects/_id.vue
+++ b/client-nuxt/pages/projects/_id.vue
@@ -1,84 +1,128 @@
 <template>
-  <div class="project">
+  <v-card flat color="transparent" class="my-2">
     <error-alert v-if="error" :error-message="error"></error-alert>
-    <v-card v-if="project" class="my-4">
-      <v-toolbar>
-        <v-toolbar-title
-          >Project : {{ project.project_name }}
-          <v-chip class="ma-2" color="primary">
-            {{ project.creation_date.toDateString() }}
-          </v-chip></v-toolbar-title
+    <v-card v-if="sanitizedProject">
+      <v-toolbar flat>
+        <v-btn nuxt x-small text class="mr-3" @click="goProjectsList()"
+          ><v-icon left>mdi-arrow-left</v-icon>Projects</v-btn
         >
+        <v-divider vertical inset></v-divider>
+
+        <v-toolbar-title class="text-uppercase ml-2">
+          <v-btn text class="text-h5" @click="goProjectRoute()"
+            ><v-icon left>mdi-rodent</v-icon
+            >{{ sanitizedProject.project_name }}</v-btn
+          >
+        </v-toolbar-title>
         <v-spacer></v-spacer>
-        <v-btn-toggle v-model="toggle_exclusive" tile group color="secondary">
-          <v-btn :to="getExperimentsLocation(project.id)">Experiments</v-btn>
-          <v-btn :to="getAnalysisLocation(project.id)">Analysis</v-btn>
-          <v-btn :to="editMemberLocation(project.id)">members</v-btn>
-        </v-btn-toggle>
+        <v-chip small color="secondary" class="mx-2">{{
+          sanitizedProject.creation_date.toDateString()
+        }}</v-chip>
+        <v-chip small color="accent">Project</v-chip>
       </v-toolbar>
 
-      <!-- <v-card-subtitle>Team</v-card-subtitle>
       <v-card-text>
-        <v-list>
-          <v-list-item v-for="team in project.teams" :key="team.name">{{
-            team.name
-          }}</v-list-item>
-        </v-list>
-      </v-card-text> -->
-      <nuxt-child />
+        <v-card flat>
+          <v-toolbar dense flat
+            ><v-toolbar-title>Description</v-toolbar-title>
+          </v-toolbar>
+          <v-card-text>
+            {{ sanitizedProject.description }}
+          </v-card-text>
+        </v-card>
+      </v-card-text>
+      <v-toolbar flat bottom color="transparent">
+        <project-actions
+          :project-id="sanitizedProject.id"
+          :experiment-size="sanitizedProject.experiments.length"
+          :analysis-size="sanitizedProject.analysis.length"
+          :member-size="sanitizedProject.members.length"
+        ></project-actions>
+        <v-spacer></v-spacer>
+      </v-toolbar>
     </v-card>
-  </div>
+
+    <nuxt-child
+      :project="sanitizedProject"
+      @update-analysis="updateProjectList()"
+      @update-experiments="updateProjectList()"
+      @project-updated="updateProjectList()"
+    />
+  </v-card>
 </template>
 
 <script>
 import ErrorAlert from '@/components/ErrorAlert'
+import ProjectActions from '@/components/ProjectActions.vue'
 
 export default {
   components: {
     ErrorAlert,
+    ProjectActions,
   },
   validate({ params }) {
     // Must be a number
     return /^\d+$/.test(params.id)
   },
-  async asyncData({ $axios, params, route }) {
-    const rawProject = await $axios.$get(`/api/projects/${route.params.id}`)
 
-    return { rawProject }
+  async fetch() {
+    const { id: projectId } = this.$route.params
+    try {
+      const project = await this.$axios.$get(`/api/projects/${projectId}/`)
+      const members = await this.$axios.$get(
+        `/api/projects/${projectId}/members/`
+      )
+      this.project = { ...project, members }
+    } catch (error) {
+      this.error = error.message
+    }
+  },
+
+  async asyncData({ $axios, $auth, params }) {
+    const { id: projectId } = params
+
+    const project = await $axios.$get(`/api/projects/${projectId}/`)
+    const members = await $axios.$get(`/api/projects/${projectId}/members/`)
+
+    return {
+      project: {
+        ...project,
+        members,
+      },
+    }
   },
   data() {
     return {
-      rawProject: null,
       error: null,
       toggle_exclusive: undefined,
     }
   },
   computed: {
-    project() {
+    sanitizedProject() {
+      const member = this.project.members.find(
+        (member) => member.id === this.$auth.user.id
+      )
       return {
-        ...this.rawProject,
-        creation_date: new Date(this.rawProject.creation_date),
+        ...this.project,
+        creation_date: new Date(this.project.creation_date),
+        membersCount: this.project.members.length,
+        role: member ? member.role.name : null,
+        permissions: member ? new Set(member.permissions) : new Set(),
       }
     },
   },
   methods: {
-    getExperimentsLocation(id) {
-      return {
-        name: 'projects-id-experiments',
-        params: { id },
-      }
+    goProjectRoute() {
+      this.$router.push({
+        name: 'projects-id',
+        params: { id: this.$route.params.id },
+      })
     },
-    getAnalysisLocation(id) {
-      return {
-        name: 'projects-id-analysis',
-        params: { id },
-      }
+    goProjectsList() {
+      this.$router.push({ name: 'projects' })
     },
-    editMemberLocation(id) {
-      return {
-        name: 'projects-id-member',
-        params: { id },
-      }
+    updateProjectList() {
+      this.$fetch()
     },
   },
 }
diff --git a/client-nuxt/pages/projects/_id/analysis.vue b/client-nuxt/pages/projects/_id/analysis.vue
new file mode 100644
index 0000000000000000000000000000000000000000..aa2a5482a885204f33d6667f9584547b8827755e
--- /dev/null
+++ b/client-nuxt/pages/projects/_id/analysis.vue
@@ -0,0 +1,15 @@
+<template>
+  <v-card flat color="transparent" class="my-10">
+    <nuxt-child
+      :project="project"
+      @update-analysis="$emit('update-analysis')"
+    />
+  </v-card>
+</template>
+<script>
+export default {
+  props: {
+    project: { type: Object, default: () => ({}) },
+  },
+}
+</script>
diff --git a/client-nuxt/pages/projects/_id/analysis/_analysisId.vue b/client-nuxt/pages/projects/_id/analysis/_analysisId.vue
index ef3ea57387ff3a85251a5c78f2f579ae82bfb3ac..4270e1878140d0a7f8100dd5c8b358af8ff332b7 100644
--- a/client-nuxt/pages/projects/_id/analysis/_analysisId.vue
+++ b/client-nuxt/pages/projects/_id/analysis/_analysisId.vue
@@ -1,157 +1,412 @@
 <template>
-  <div>
-    <error-alert v-if="error" :error-message="error"></error-alert>
-    <v-card v-if="analyse" flat class="mt-4">
-      <v-container fluid>
-        <v-toolbar>
-          <v-toolbar-title>
-            <span v-if="analyse.history_status.state == 'running'" class="mr-2"
-              ><v-progress-circular
-                indeterminate
-                color="primary"
-              ></v-progress-circular
-            ></span>
-            <span
-              v-else-if="analyse.history_status.state == 'queued'"
-              class="mr-2"
-              ><v-progress-circular
-                indeterminate
-                color="orange darken-2"
-              ></v-progress-circular
-            ></span>
-            <span v-else-if="analyse.history_status.state == 'ok'" class="mr-2"
-              ><v-icon color="green">mdi-check-circle</v-icon></span
-            >
-            <v-btn
-              class="analysis-name"
-              depressed
-              text
-              nuxt
-              :to="analysisLocation()"
-            >
-              Analysis :
-              {{ analyse.name }}
-            </v-btn>
-            <v-chip class="ma-2" color="primary">
-              {{ analyse.creation_date.toDateString() }}
-            </v-chip>
-          </v-toolbar-title>
-          <v-spacer></v-spacer>
-          <v-btn-toggle tile group color="secondary">
-            <v-btn :to="goToLodScores()">Genome scan</v-btn>
-            <v-btn :to="showPeak()">Peaks</v-btn>
-          </v-btn-toggle>
-          <v-tooltip bottom>
+  <v-card flat color="transparent">
+    <v-card flat color="transparent" class="mt-3">
+      <error-alert v-if="error" :error-message="error"></error-alert>
+      <v-skeleton-loader
+        v-if="$fetchState.pending"
+        elevation="2"
+        type="card-heading, list-item-avatar-two-line@3, article, table-heading, table-thead, table-tfoot"
+      ></v-skeleton-loader>
+      <v-card
+        v-else
+        :id="`projects-${$route.params.id}-analysis-${$route.params.analysisId}`"
+        class="mt-3"
+      >
+        <v-toolbar flat>
+          <v-btn nuxt x-small text class="mr-3" @click="goToAnalysisListRoute()"
+            ><v-icon left>mdi-arrow-left</v-icon>Analysis</v-btn
+          >
+          <v-divider vertical inset></v-divider>
+          <v-toolbar-title v-if="sanitizedAnalysis" class="text-uppercase ml-2">
+            <!-- <v-icon color="primary">mdi-chart-box</v-icon> -->
+            <v-btn text class="text-h5" @click="goAnalysisRoute()"
+              ><v-icon left>mdi-file-chart</v-icon>
+              {{ sanitizedAnalysis.name }}</v-btn
+            ></v-toolbar-title
+          >
+          <!-- <v-progress-linear
+            :active="$fetchState.pending"
+            :indeterminate="$fetchState.pending"
+            absolute
+            bottom
+            color="primary"
+          ></v-progress-linear> -->
+          <v-tooltip v-if="experimentId" bottom>
             <template v-slot:activator="{ on, attrs }">
               <v-btn
                 class="mx-2"
-                small
-                fab
-                color="blue-grey"
+                :color="$vuetify.theme.dark ? null : 'secondary'"
+                icon
+                large
                 :to="copyAnalysisLocation()"
                 v-bind="attrs"
                 v-on="on"
                 ><v-icon>mdi-refresh</v-icon></v-btn
               >
             </template>
-            <span>run this analysis again</span>
+            <span>Copy this analysis</span>
           </v-tooltip>
           <v-tooltip bottom>
             <template v-slot:activator="{ on, attrs }">
               <v-btn
                 class="mx-2"
-                fab
-                small
-                color="blue-grey"
+                :color="$vuetify.theme.dark ? null : 'secondary'"
+                icon
+                large
                 v-bind="attrs"
                 v-on="on"
                 @click="downloadQtl2Data()"
                 ><v-icon>mdi-download</v-icon></v-btn
               >
             </template>
-            <span>Download input r-qtl2 data</span>
+            <span>Download qtl2 inputs</span>
+          </v-tooltip>
+          <!-- <v-tooltip v-if="experimentId" bottom>
+            <template v-slot:activator="{ on, attrs }">
+              <v-btn
+                icon
+                nuxt
+                :to="experimentLocation()"
+                v-bind="attrs"
+                v-on="on"
+              >
+                <v-icon>mdi-flask</v-icon></v-btn
+              >
+            </template>
+            <span>Go to experiment</span>
           </v-tooltip>
+          <v-chip v-else small color="error"
+            >Experiment has been deleted</v-chip
+          > -->
+
+          <v-spacer></v-spacer>
+          <v-chip v-if="sanitizedAnalysis" small color="secondary" class="mx-2">
+            {{ sanitizedAnalysis.creation_date.toDateString() }}
+          </v-chip>
+          <v-chip small color="accent"> Analysis </v-chip>
         </v-toolbar>
+        <v-card-text v-if="sanitizedAnalysis">
+          <v-card flat>
+            <v-toolbar dense flat
+              ><v-toolbar-title>Description</v-toolbar-title>
+            </v-toolbar>
+            <v-card-text>
+              {{ sanitizedAnalysis.description }}
+            </v-card-text>
+          </v-card>
+        </v-card-text>
+
+        <v-card-text>
+          <v-card flat outlined>
+            <v-toolbar flat>
+              <v-toolbar-title> Workflow invocation</v-toolbar-title></v-toolbar
+            >
 
-        <v-card-text><nuxt-child /></v-card-text>
-      </v-container>
+            <workflow-invocation
+              v-if="
+                invocation &&
+                wfInvocationError === null &&
+                invocation.steps.length > 0
+              "
+              :steps="stepsWithJobMetrics"
+            ></workflow-invocation>
+            <v-card-text v-else>
+              <v-alert
+                v-if="wfInvocationError"
+                border="left"
+                text
+                type="error"
+                :dark="$vuetify.theme.dark"
+              >
+                {{ wfInvocationError }}</v-alert
+              >
+              <v-alert
+                v-else
+                type="info"
+                text
+                border="left"
+                :dark="$vuetify.theme.dark"
+              >
+                The workflow has been queued on Galaxy
+              </v-alert></v-card-text
+            >
+          </v-card>
+        </v-card-text>
+        <v-card-text>
+          <v-card v-if="experimentId" flat outlined>
+            <v-toolbar dense flat
+              ><v-toolbar-title>
+                {{ sanitizedAnalysis.experiments[0].name }}
+              </v-toolbar-title>
+              <v-tooltip bottom>
+                <template v-slot:activator="{ on, attrs }">
+                  <v-btn
+                    class="mx-2"
+                    :color="$vuetify.theme.dark ? null : 'secondary'"
+                    large
+                    icon
+                    :to="experimentLocation()"
+                    v-bind="attrs"
+                    v-on="on"
+                    ><v-icon>mdi-eye</v-icon></v-btn
+                  >
+                </template>
+                <span>View experiment</span>
+              </v-tooltip>
+              <v-spacer></v-spacer>
+              <v-chip small color="accent">Experiment</v-chip>
+            </v-toolbar>
+            <v-card-title class="text-subtitle-1">Description</v-card-title>
+            <v-card-text>
+              {{ sanitizedAnalysis.experiments[0].description }}
+            </v-card-text>
+          </v-card>
+          <v-alert
+            v-else-if="!$fetchState.pending"
+            text
+            type="error"
+            border="left"
+          >
+            Experiment has been deleted</v-alert
+          >
+        </v-card-text>
+        <v-card-text>
+          <v-card flat outlined>
+            <v-data-table
+              v-if="sanitizedAnalysis"
+              :headers="phenotypeCategoriesHeader"
+              :items="sanitizedAnalysis.phenotype_categories"
+              :sort-by="['dataclass', 'name']"
+              :sort-desc="[true, false]"
+              :search="phenotype_search"
+              multi-sort
+              class="elevation-0"
+            >
+              <template v-slot:top>
+                <v-toolbar flat dense>
+                  <v-toolbar-title> Phenotype Categories </v-toolbar-title>
+                  <v-divider class="mx-4" inset vertical></v-divider>
+                  <v-text-field
+                    v-model="phenotype_search"
+                    append-icon="mdi-magnify"
+                    label="Search"
+                    single-line
+                    hide-details
+                  ></v-text-field>
+                </v-toolbar>
+              </template>
+            </v-data-table>
+          </v-card>
+        </v-card-text>
+        <v-toolbar flat bottom color="transparent">
+          <v-btn :to="resultsRoute()"
+            ><v-icon left>mdi-chart-timeline-variant</v-icon>LOD Plot</v-btn
+          >
+        </v-toolbar>
+      </v-card>
     </v-card>
-  </div>
+    <nuxt-child :project="project" :analysis="sanitizedAnalysis" />
+    <ProgressBar :waiting="waiting" message="Creating archive" />
+  </v-card>
 </template>
 <script>
 import ErrorAlert from '@/components/ErrorAlert'
+import WorkflowInvocation from '@/components/WorkflowInvocation'
+import ProgressBar from '@/components/ProgressBar'
 
 export default {
   components: {
     ErrorAlert,
+    WorkflowInvocation,
+    ProgressBar,
   },
-  async asyncData({ $axios, params, $auth }) {
-    const { id: projectId, analysisId } = params
-
-    const analyse = await $axios.$get(
-      `/api/projects/${projectId}/analysis/${analysisId}`
-    )
-
-    return {
-      analyse: { ...analyse, creation_date: new Date(analyse.creation_date) },
-      projectId,
-      analysisId,
-    }
+  loading: {
+    continuous: true,
+  },
+  props: { project: { type: Object, default: () => ({}) } },
+  async fetch() {
+    const { id: projectId, analysisId } = this.$route.params
+    const [analysis, invocation] = await Promise.all([
+      this.$axios.$get(`/api/projects/${projectId}/analysis/${analysisId}/`),
+      this.$axios
+        .$get(
+          `/api/projects/${projectId}/analysis/${analysisId}/workflow_invocation_parameters/`
+        )
+        .catch((e) => {
+          const {
+            response: { data },
+          } = e
+          if (data.type === 'galaxy') {
+            this.wfInvocationError = data.message
+          } else {
+            throw e
+          }
+        }),
+    ])
+    this.analysis = analysis
+    this.invocation = invocation === '' ? null : invocation
   },
+  // async asyncData({ $axios, params }) {
+  //   const { id: projectId, analysisId } = params
+  // let wfInvocationError = null
+  // const [analysis, invocation] = await Promise.all([
+  //   $axios.$get(`/api/projects/${projectId}/analysis/${analysisId}/`),
+  //   $axios
+  //     .$get(
+  //       `/api/projects/${projectId}/analysis/${analysisId}/workflow_invocation_parameters/`
+  //     )
+  //     .catch((e) => {
+  //       const {
+  //         response: { data },
+  //       } = e
+  //       if (data.type === 'galaxy') {
+  //         wfInvocationError = data.message
+  //       } else {
+  //         throw e
+  //       }
+  //     }),
+  // ])
+  // return {
+  // analysis,
+  // wfInvocationError,
+  // invocation: invocation === '' ? null : invocation,
+  //     projectId,
+  //     analysisId,
+  //   }
+  // },
   data() {
     return {
-      projectId: null,
-      analysisId: null,
-      analyse: null,
+      waiting: false,
+      invocation: null,
+      analysis: null,
       error: null,
-      analysisResults: [
-        { name: 'lodscores', status: true },
-        { name: 'coefficient', status: false },
+      wfInvocationError: null,
+      phenotype_search: '',
+      phenotypeCategoriesHeader: [
+        {
+          text: 'Name',
+          align: 'start',
+          value: 'name',
+        },
+        { text: 'Description', value: 'description' },
+        { text: 'Data Class', value: 'dataclass' },
+        { text: 'Datatype', value: 'datatype' },
+        { text: 'Nature', value: 'nature' },
+        { text: 'Location', value: 'location' },
       ],
     }
   },
+  computed: {
+    sanitizedAnalysis() {
+      if (this.analysis) {
+        return {
+          ...this.analysis,
+          creation_date: new Date(this.analysis.creation_date),
+          experiments: this.analysis.experiments.map((e) => ({
+            ...e,
+            creation_date: new Date(e.creation_date),
+          })),
+        }
+      } else {
+        return null
+      }
+    },
+    sanitizedInvocation() {
+      if (!this.invocation) {
+        return { steps: [] }
+      } else {
+        return { ...this.invocation }
+      }
+    },
 
+    stepsWithJobMetrics() {
+      return this.sanitizedInvocation.steps.map((step, i) => {
+        step.job.metrics = Object.fromEntries(
+          step.job.metrics.map((metric) => [metric.name, metric])
+        )
+        step.job.params = Object.fromEntries(
+          Object.entries(step.job.params).map(([key, value]) => {
+            // Get the display name from tool informations
+            const inputObj = step.tool.inputs.find((input) => {
+              return input.name === key
+            })
+            // console.log(inputObj)
+            let inputNameToDisplay = ''
+            if (inputObj?.type === 'select') {
+              // Get the option displayed name
+              const sanitizedValue = value.replaceAll('"', '')
+              const inputValue = inputObj.options.find(([displayName, v]) => {
+                return v === sanitizedValue
+              })
+              inputNameToDisplay = inputValue[0]
+            } else {
+              // console.log(value)
+              inputNameToDisplay = value.slice(0, -1).slice(1)
+            }
+            return [inputObj.label, inputNameToDisplay]
+          })
+        )
+        return step
+      })
+    },
+    experimentId() {
+      return this?.sanitizedAnalysis?.experiments.length > 0
+        ? this.sanitizedAnalysis.experiments[0].id
+        : null
+    },
+    rerunAnalysisHash() {
+      return 'rerun-analysis'
+    },
+  },
+  mounted() {
+    this.$fetch()
+  },
   methods: {
-    resultsLocation() {
+    analysisListRoute() {
       return {
-        name: 'projects-id-analysis-analysisId-results',
-        params: {
-          id: this.projectId,
-          analysisId: this.analysisId,
-        },
+        name: 'projects-id-analysis',
+        params: { id: this.$route.params.id },
       }
     },
+    goToAnalysisListRoute() {
+      this.$router.push(this.analysisListRoute())
+    },
     analysisLocation() {
       return {
         name: 'projects-id-analysis-analysisId',
-        params: { id: this.projectId, analysisId: this.analysisId },
+        params: {
+          id: this.$route.params.id,
+          analysisId: this.$route.params.analysisId,
+        },
       }
     },
-
+    goAnalysisRoute() {
+      this.$router.push(this.analysisLocation())
+    },
     copyAnalysisLocation() {
       return {
         name: 'projects-id-analysis-analysisId-copy',
-        params: { id: this.projectId, analysisId: this.analysisId },
+        params: {
+          id: this.$route.params.id,
+          analysisId: this.$route.params.analysisId,
+        },
+        hash: `#${this.rerunAnalysisHash}`,
       }
     },
-    showPeak() {
+    resultsRoute() {
       const { id, analysisId } = this.$route.params
       return {
         name: 'projects-id-analysis-analysisId-results-peaks',
         params: { id, analysisId },
-      }
-    },
-    goToLodScores() {
-      const { id, analysisId } = this.$route.params
-      return {
-        name: 'projects-id-analysis-analysisId-results-lodscores',
-        params: { id, analysisId },
+        hash: '#genome-scan',
       }
     },
     async downloadQtl2Data() {
       try {
+        this.waiting = true
+
         const { archive_name: archiveName } = await this.$axios.$get(
-          `/api/projects/${this.projectId}/analysis/${this.analysisId}/download_qtl2_data/`
+          `/api/projects/${this.$route.params.id}/analysis/${this.$route.params.analysisId}/download_qtl2_data/`
         )
         // this.$axios.setHeader('Content-Type', false, ['post'])
         const link = document.createElement('a')
@@ -162,8 +417,25 @@ export default {
         link.remove()
       } catch (error) {
         this.error = error.message
-        console.log(error)
+      } finally {
+        this.waiting = false
+      }
+    },
+    experimentLocation() {
+      return {
+        name: 'projects-id-experiments-experimentId',
+        params: {
+          id: this.$route.params.id,
+          experimentId: this.experimentId,
+        },
+      }
+    },
+    formatDate(date) {
+      const options = {
+        hour: 'numeric',
+        minute: 'numeric',
       }
+      return new Date(date).toLocaleDateString('en', options)
     },
   },
 }
diff --git a/client-nuxt/pages/projects/_id/analysis/_analysisId/copy.vue b/client-nuxt/pages/projects/_id/analysis/_analysisId/copy.vue
index 51afe51a2b3dcf1843d0337504de81243d2567d7..705b3de214a227ff5484004c3aab987466927de7 100644
--- a/client-nuxt/pages/projects/_id/analysis/_analysisId/copy.vue
+++ b/client-nuxt/pages/projects/_id/analysis/_analysisId/copy.vue
@@ -1,12 +1,19 @@
 <template>
   <v-card class="my-4">
+    <v-toolbar flat>
+      <v-toolbar-title
+        >Copy analysis
+        <span class="font-weight-bold">{{
+          analysis.name
+        }}</span></v-toolbar-title
+      ></v-toolbar
+    >
     <error-alert v-if="error" :error-message="error"></error-alert>
-    <v-card-text>
+    <v-card-text :id="$route.hash.substring(1)">
       <RunAnalysisForm
         :project-id="projectId"
-        :experiments="experiments"
-        :wf-params="wfJobParams"
-        :tools-inputs="toolsInputs"
+        :experiments="sanitizedExperiments"
+        :analysis="analysisCopy"
       />
     </v-card-text>
   </v-card>
@@ -17,49 +24,43 @@ import ErrorAlert from '@/components/ErrorAlert'
 import RunAnalysisForm from '~/components/RunAnalysisForm.vue'
 export default {
   components: { RunAnalysisForm, ErrorAlert },
+  props: {
+    analysis: { type: Object, default: () => ({}) },
+  },
   async asyncData({ params, $axios, route }) {
-    const { id: projectId, analysisId } = params
+    const { id: projectId } = params
     try {
       const experiments = await $axios.$get(
-        `/api/projects/${route.params.id}/experiments`
-      )
-      const expWithVarTypes = experiments.map(async (exp) => {
-        const variables = await $axios.$get(
-          `/api/projects/${route.params.id}/experiments/${exp.id}/variable_types/`
-        )
-        return {
-          ...exp,
-          variables,
-          creation_date: new Date(exp.creation_date).toDateString(),
-        }
-      })
-      const workflowTools = await $axios.$get('/api/workflow-tools')
-      const wfJobParams = await $axios.$get(
-        `/api/projects/${projectId}/analysis/${analysisId}/workflow_job_params`
+        `/api/projects/${params.id}/experiments/`
       )
-      const toolsInputs = Object.keys(workflowTools)
-        .filter((stepId) => stepId !== 'null')
-        .map((stepId) => {
-          workflowTools[stepId].stepId = stepId
-          return workflowTools[stepId]
-        })
+
       return {
-        experiments: await Promise.all(expWithVarTypes),
-        toolsInputs,
-        wfJobParams: Object.keys(wfJobParams).reduce((acc, stepId) => {
-          if (Object.keys(wfJobParams[stepId]).length > 0) {
-            acc[stepId] = { ...wfJobParams[stepId] }
-          }
-          return acc
-        }, {}),
-        projectId: parseInt(params.id),
+        experiments,
+        projectId: parseInt(projectId),
       }
     } catch (error) {
       return { error: error.message }
     }
   },
   data() {
-    return { error: null }
+    return { error: null, selectedWorkflow: null }
+  },
+  computed: {
+    sanitizedExperiments() {
+      return this.experiments.map((experiment) => ({
+        ...experiment,
+        creation_date: new Date(experiment.creation_date).toDateString(),
+      }))
+    },
+    analysisCopy() {
+      return {
+        ...this.analysis,
+        name: `Copy of ${this.analysis.name}`,
+        creation_date: undefined,
+        galaxy_workflow_invocation_id: '',
+        galaxy_history_id: '',
+      }
+    },
   },
 }
 </script>
diff --git a/client-nuxt/pages/projects/_id/analysis/_analysisId/index.vue b/client-nuxt/pages/projects/_id/analysis/_analysisId/index.vue
index 0d048f1f3bd836d6b600a2735db3c10d65c5398f..37eff5fd095cdd5e25be39c12ce119a6d7e5afdc 100644
--- a/client-nuxt/pages/projects/_id/analysis/_analysisId/index.vue
+++ b/client-nuxt/pages/projects/_id/analysis/_analysisId/index.vue
@@ -1,134 +1,3 @@
 <template>
-  <v-card flat>
-    <error-alert v-if="error" :error-message="error"></error-alert>
-    <v-card-title>Analysis Parameters</v-card-title>
-    <v-card-text>
-      <v-btn text :to="experimentLocation()">Experiment</v-btn>
-
-      <v-simple-table>
-        <template v-slot:default>
-          <thead>
-            <tr>
-              <th class="text-left">Tool Name</th>
-              <th class="text-left">Tool Version</th>
-              <th class="text-left">Start</th>
-              <th class="text-left">Duration</th>
-              <th class="text-left">State</th>
-              <th class="text-left">Parameters</th>
-            </tr>
-          </thead>
-          <tbody>
-            <tr v-for="step in stepsWithJobMetrics" :key="step.step_id">
-              <td>{{ step.tool.name }}</td>
-              <td>{{ step.tool.version }}</td>
-              <td v-if="step.job.metrics.start_epoch">
-                {{ formatDate(step.job.metrics.start_epoch.value) }}
-              </td>
-              <td v-else><v-icon>mdi-null</v-icon></td>
-              <td v-if="step.job.metrics.runtime_seconds">
-                {{ step.job.metrics.runtime_seconds.value }}
-              </td>
-              <td v-else><v-icon>mdi-null</v-icon></td>
-              <td>
-                <v-icon v-if="step.job.state == 'ok'" color="success"
-                  >mdi-check-circle</v-icon
-                >
-                <v-progress-circular
-                  v-else-if="step.job.state == 'running'"
-                  indeterminate
-                  :width="2"
-                  :size="25"
-                  color="primary"
-                ></v-progress-circular>
-                <v-icon v-else-if="step.job.state == 'new'" color="primary"
-                  >mdi-new-box</v-icon
-                >
-                <v-icon v-else-if="step.job.state == 'paused'" color="primary"
-                  >mdi-pause-circle</v-icon
-                >
-                <v-icon v-else-if="step.job.state == 'error'" color="error"
-                  >mdi-alert-circle</v-icon
-                >
-                <v-icon v-else color="warning">mdi-alert-circle</v-icon>
-              </td>
-              <td>
-                <ul>
-                  <li v-for="k in Object.keys(step.job.params)" :key="k">
-                    {{ k }} : {{ step.job.params[k] }}
-                  </li>
-                </ul>
-              </td>
-            </tr>
-          </tbody>
-        </template>
-      </v-simple-table>
-    </v-card-text>
-  </v-card>
+  <v-card flat> </v-card>
 </template>
-
-<script>
-import ErrorAlert from '@/components/ErrorAlert'
-
-export default {
-  components: {
-    ErrorAlert,
-  },
-  async asyncData({ $axios, params, $auth }) {
-    const { id: projectId, analysisId } = params
-    const analyse = await $axios.$get(
-      `/api/projects/${projectId}/analysis/${analysisId}`
-    )
-    const invocation = await $axios.$get(
-      `/api/projects/${projectId}/analysis/${analysisId}/workflow_invocation_parameters`
-    )
-    return {
-      projectId,
-      invocation: {
-        ...invocation,
-        steps: invocation.steps.sort((a, b) => a.step_id - b.step_id),
-      },
-      analysisId,
-      experimentId: analyse.experiments[0],
-    }
-  },
-  data() {
-    return {
-      error: null,
-      analysisResults: [
-        { name: 'lodscores', status: true },
-        { name: 'coefficient', status: false },
-      ],
-    }
-  },
-  computed: {
-    stepsWithJobMetrics() {
-      return this.invocation.steps.map((step, i) => {
-        step.job.metrics = Object.fromEntries(
-          step.job.metrics.map((metric) => [metric.name, metric])
-        )
-        return step
-      })
-    },
-  },
-  methods: {
-    experimentLocation() {
-      return {
-        name: 'projects-id-experiments-experimentId',
-        params: {
-          id: this.projectId,
-          experimentId: this.experimentId,
-        },
-      }
-    },
-    formatDate(date) {
-      const options = {
-        hour: 'numeric',
-        minute: 'numeric',
-      }
-      return new Date(date).toLocaleDateString('en', options)
-    },
-  },
-}
-</script>
-
-<style></style>
diff --git a/client-nuxt/pages/projects/_id/analysis/_analysisId/results.vue b/client-nuxt/pages/projects/_id/analysis/_analysisId/results.vue
index f05da4192030bf957d58a8fa1080dd27a317ecaf..f7838fad461db59ed00d421f066440f128c4d395 100644
--- a/client-nuxt/pages/projects/_id/analysis/_analysisId/results.vue
+++ b/client-nuxt/pages/projects/_id/analysis/_analysisId/results.vue
@@ -1,11 +1,222 @@
 <template>
-  <div>
-    <nuxt-child />
-  </div>
+  <v-card flat color="transparent" class="my-10">
+    <v-card>
+      <v-toolbar id="genome-scan" flat>
+        <v-toolbar-title> Genome Scan</v-toolbar-title>
+        <v-divider class="mx-4" inset vertical></v-divider>
+        <v-spacer></v-spacer>
+        <v-switch
+          v-model="showThresholdPlotLines"
+          hide-details
+          label="Threshold"
+        ></v-switch>
+        <!-- <v-tooltip bottom>
+          <template v-slot:activator="{ on, attrs }">
+            <v-btn icon v-bind="attrs" v-on="on" @click.stop="dialog = true">
+              <v-icon>mdi-cog</v-icon>
+            </v-btn>
+          </template>
+          <span>Select chromosomes</span>
+        </v-tooltip> -->
+      </v-toolbar>
+      <v-dialog v-model="dialog" persistent max-width="600px">
+        <v-card>
+          <v-toolbar dense>
+            <v-toolbar-title>Select chromosomes</v-toolbar-title>
+            <v-spacer></v-spacer>
+            <v-btn text @click="toggle">
+              <template v-if="someChromosomeSelected"
+                ><v-icon left>mdi-minus-box</v-icon></template
+              >
+              <template v-else-if="allChromosomeSelected"
+                ><v-icon left>mdi-checkbox-marked</v-icon></template
+              >
+              <template v-else>
+                <v-icon left>mdi-checkbox-blank</v-icon></template
+              >
+              All
+            </v-btn>
+            <v-spacer></v-spacer>
+
+            <v-btn
+              x-small
+              fab
+              color="accent"
+              @click="updateChromosomeToDisplay()"
+            >
+              <v-icon>mdi-check</v-icon>
+            </v-btn>
+          </v-toolbar>
+          <v-card-text>
+            <v-chip-group
+              v-if="chromosomes"
+              v-model="selectedChromosomes"
+              multiple
+              column
+              active-class="primary"
+            >
+              <v-chip v-for="chr in chromosomes" :key="chr">
+                {{ chr }}
+              </v-chip>
+            </v-chip-group>
+          </v-card-text>
+        </v-card>
+      </v-dialog>
+      <v-skeleton-loader
+        v-if="$fetchState.pending"
+        elevation="2"
+        type="card"
+      ></v-skeleton-loader>
+      <v-card-text v-else>
+        <genome-scan
+          v-if="significanceThresholds"
+          :series="highchartSerie"
+          :threshold-values="significanceThresholds"
+          :threshold-plot-lines="showThresholdPlotLines"
+          :waiting.sync="waiting"
+        ></genome-scan>
+      </v-card-text>
+      <!-- <v-card-text v-else>
+        <v-alert border="left" type="error">No genome scan found</v-alert>
+      </v-card-text> -->
+    </v-card>
+    <nuxt-child :project="project" :analysis="analysis" />
+  </v-card>
 </template>
 
 <script>
-export default {}
+import GenomeScan from '@/components/charts/GenomeScan'
+
+export default {
+  components: {
+    GenomeScan,
+  },
+  props: {
+    project: { type: Object, default: () => ({}) },
+    analysis: { type: Object, default: () => ({}) },
+  },
+
+  async fetch() {
+    const { id: projectId, analysisId } = this.$route.params
+    try {
+      const lod = await this.$axios.$get(
+        `/api/projects/${projectId}/analysis/${analysisId}/lodscores/`
+      )
+      this.lod = { lod_scores: lod.lod_scores }
+      this.chromosomes = Array.from(
+        new Set(lod.lod_scores.map((l) => l.chromosome))
+      )
+      this.significanceThresholds = lod.significance_thresholds
+    } catch (error) {
+      this.lod = {}
+    }
+  },
+  data() {
+    return {
+      showThresholdPlotLines: true,
+      waiting: false,
+      dialog: false,
+      lod: null,
+      significanceThresholds: null,
+      chromosomes: [
+        ...[...Array(19).keys()].map((i) => (i + 1).toString()),
+        ...['X', 'Y', 'M'],
+      ],
+      selectedChromosomes: [...Array(22).keys()],
+      userSelectedChromosomes: [...Array(22).keys()],
+    }
+  },
+  computed: {
+    highchartSerie() {
+      if (this?.lod?.lod_scores) {
+        let genomeX = 0
+        let currentX = 0
+        // const selectedChromosomesSet = new Set(
+        //   this.userSelectedChromosomes.map((idx) => this.chromosomes[idx])
+        // )
+        const lodscoresClone = [...this.lod.lod_scores]
+        // const lodscores = this.allChromosomeSelectedSaved
+        //   ? lodscoresClone
+        //   : lodscoresClone.filter(({ chromosome }) => {
+        //       return selectedChromosomesSet.has(chromosome.toString())
+        //     })
+        // const sortedLod = lodscores.sort((a, b) => a.chromosome - b.chromosome)
+        const sortedLod = lodscoresClone.sort(
+          (a, b) => a.chromosome - b.chromosome
+        )
+        let currentChr = sortedLod[0].chromosome
+        const series = []
+        let data = []
+        for (const { marker, chromosome, position, lod } of sortedLod) {
+          if (chromosome !== currentChr) {
+            series.push({ data, name: currentChr, id: currentChr })
+            currentChr = chromosome
+            genomeX = currentX
+            data = []
+          }
+          currentX = genomeX + parseInt(position)
+          data.push({
+            marker,
+            chromosome,
+            position,
+            lod,
+            y: lod,
+            x: currentX,
+          })
+        }
+        series.push({ data, name: currentChr, id: currentChr })
+        return series
+      } else {
+        return []
+      }
+    },
+    allChromosomeSelected() {
+      if (this.chromosomes) {
+        return this.selectedChromosomes.length === this.chromosomes.length
+      } else {
+        return false
+      }
+    },
+    allChromosomeSelectedSaved() {
+      return this.userSelectedChromosomes.length === this.chromosomes.length
+    },
+    someChromosomeSelected() {
+      return this.selectedChromosomes.length > 0 && !this.allChromosomeSelected
+    },
+    icon() {
+      if (this.allChromosomeSelected) return 'mdi-close-box'
+      if (this.someChromosomeSelected) return 'mdi-minus-box'
+      return 'mdi-checkbox-blank-outline'
+    },
+  },
+  mounted() {
+    this.$fetch()
+  },
+  methods: {
+    listPeaksRoute() {
+      const { id, analysisId } = this.$route.params
+      return {
+        name: 'projects-id-analysis-analysisId-results-peaks',
+        params: { id, analysisId },
+      }
+    },
+
+    toggle() {
+      this.$nextTick(() => {
+        if (this.allChromosomeSelected) {
+          this.selectedChromosomes = []
+        } else {
+          this.selectedChromosomes = [...Array(22).keys()]
+        }
+      })
+    },
+    updateChromosomeToDisplay() {
+      this.userSelectedChromosomes = [...this.selectedChromosomes]
+      // this.drawLodScores()
+      this.dialog = false
+    },
+  },
+}
 </script>
 
 <style></style>
diff --git a/client-nuxt/pages/projects/_id/analysis/_analysisId/results/lodscores/index.vue b/client-nuxt/pages/projects/_id/analysis/_analysisId/results/lodscores/index.vue
deleted file mode 100644
index 0c219091194f3cae2529e7770555843a7f781da7..0000000000000000000000000000000000000000
--- a/client-nuxt/pages/projects/_id/analysis/_analysisId/results/lodscores/index.vue
+++ /dev/null
@@ -1,93 +0,0 @@
-<template>
-  <div>
-    <error-alert v-if="error" :error-message="error"></error-alert>
-    <v-card-title>Genome scan</v-card-title>
-    <div class="lod-scores"></div>
-  </div>
-</template>
-<script>
-import ErrorAlert from '@/components/ErrorAlert'
-import { GenomeScan } from 'bioviz-js'
-import { select } from 'd3-selection'
-
-export default {
-  components: { ErrorAlert },
-  async asyncData({ $axios, params, $auth }) {
-    const { id: projectId, analysisId } = params
-    try {
-      const lod = await $axios.$get(
-        `/api/projects/${projectId}/analysis/${analysisId}/lodscores/`
-      )
-      if (lod && lod.lod_scores) {
-        const { lod_scores: lodscores } = lod
-        const significanceThresholds = await $axios.$get(
-          `/api/projects/${projectId}/analysis/${analysisId}/significance_thresholds/`
-        )
-
-        const customLodscores = lodscores
-          .map((lod) => ({
-            marker: lod.marker,
-            chr: lod.chromosome,
-            pos: lod.position,
-            lod: lod.lod,
-          }))
-          .sort((a, b) => a.chr - b.chr)
-        return {
-          lodscores: {
-            lod_score_per_chromosome: customLodscores,
-            significance_thresholds: significanceThresholds,
-          },
-        }
-      } else {
-        return {
-          lodscores: {
-            lod_score_per_chromosome: [],
-            significance_thresholds: [],
-          },
-        }
-      }
-    } catch (error) {
-      return {
-        lodscores: {
-          lod_score_per_chromosome: [],
-          significance_thresholds: [],
-          error: error.message,
-        },
-      }
-    }
-  },
-  data() {
-    return {
-      lodscores: { lod_score_per_chromosome: [], significance_thresholds: [] },
-      // lodscores: [],
-      error: null,
-    }
-  },
-  mounted() {
-    this.drawLodScores(this.lodscores)
-  },
-  methods: {
-    drawLodScores(lodScores) {
-      select('.lod-scores')
-        .datum(lodScores)
-        .call(
-          GenomeScan(),
-          (event) => {
-            const [, chr] = event.data[event.curveNumber].name.split(' ')
-            this.drawLodScores({
-              ...this.lodscores,
-              lod_score_per_chromosome: this.lodscores.lod_score_per_chromosome.filter(
-                (item) => item.chr === chr
-              ),
-            })
-            return false
-          },
-          (event) => {
-            console.log('double click')
-            return true
-          }
-        )
-    },
-  },
-}
-</script>
diff --git a/client-nuxt/pages/projects/_id/analysis/_analysisId/results/peaks.vue b/client-nuxt/pages/projects/_id/analysis/_analysisId/results/peaks.vue
index b63a44df4c075625bab47e93309c4931436b8d0e..2934d15c1400d2ebea64fb0d62abea4af4483e15 100644
--- a/client-nuxt/pages/projects/_id/analysis/_analysisId/results/peaks.vue
+++ b/client-nuxt/pages/projects/_id/analysis/_analysisId/results/peaks.vue
@@ -1,65 +1,23 @@
 <template>
-  <div>
-    <v-card>
-      <error-alert v-if="error" :error-message="error"></error-alert>
-      <Peaks
-        :title="titleList"
-        :type="type"
-        :project-id="projectId"
-        :items="peaks"
-        :keys="peaksKeys"
-        @show-detail="viewPeakDetail"
-      />
-    </v-card>
-    <nuxt-child />
-  </div>
+  <v-card flat color="transparent" class="my-10">
+    <!-- <v-container fluid>
+      <v-row justify="center">
+        <v-divider></v-divider>
+        <v-col cols="12" class="px-0">
+          <v-card flat color="grey lighten-3" class="text-center">
+            <v-card-text class="px-0"> PEAKS </v-card-text>
+          </v-card>
+        </v-col>
+      </v-row>
+    </v-container> -->
+    <nuxt-child :project="project" :analysis="analysis" />
+  </v-card>
 </template>
 <script>
-import ErrorAlert from '@/components/ErrorAlert'
-import Peaks from '~/components/GenericDataIterator'
-
 export default {
-  components: {
-    Peaks,
-    ErrorAlert,
-  },
-
-  async fetch() {
-    const { projectId, analysisId } = this.$route.params
-    this.peaks = await this.$axios.$get(
-      `/api/projects/${projectId}/analysis/${analysisId}/peaks/`
-    )
-  },
-
-  async asyncData({ $axios, params, $auth, route }) {
-    const { id: projectId, analysisId } = params
-    const peaks = await $axios.$get(
-      `/api/projects/${projectId}/analysis/${analysisId}/peaks/`
-    )
-    return {
-      peaks: peaks.map((peak) => ({ ...peak, name: peak.variable_name })),
-      projectId: parseInt(route.params.id),
-      analysisId: parseInt(route.params.analysisId),
-    }
-  },
-  data() {
-    return {
-      error: null,
-      peaks: null,
-      type: 'peak',
-      projectId: null,
-      titleList: 'Significant peaks',
-      peaksKeys: ['Id', 'variable_name', 'chromosome', 'position', 'lod'],
-    }
-  },
-  methods: {
-    viewPeakDetail(peakId) {
-      this.$router.push({
-        name:
-          'projects-id-analysis-analysisId-results-peaks-peakId-coefficients',
-        params: { id: this.projectId, analysisId: this.analysisId, peakId },
-      })
-    },
+  props: {
+    project: { type: Object, default: () => ({}) },
+    analysis: { type: Object, default: () => ({}) },
   },
 }
 </script>
diff --git a/client-nuxt/pages/projects/_id/analysis/_analysisId/results/peaks/_peakId.vue b/client-nuxt/pages/projects/_id/analysis/_analysisId/results/peaks/_peakId.vue
index c6c7b4227130194eb518482374e594661d12e1be..ecc64ee8c556910b196c62ff826236f3746d4c3b 100644
--- a/client-nuxt/pages/projects/_id/analysis/_analysisId/results/peaks/_peakId.vue
+++ b/client-nuxt/pages/projects/_id/analysis/_analysisId/results/peaks/_peakId.vue
@@ -1,66 +1,117 @@
 <template>
   <div>
     <v-card class="my-4">
-      <v-toolbar dense>
-        <v-toolbar-title
-          >Peak {{ peak.id }}
-          <small
-            >chromosome {{ peak.chromosome }}, position
+      <v-toolbar flat>
+        <v-btn nuxt x-small text class="mr-3" @click="goToPeaksListRoute()"
+          ><v-icon left>mdi-arrow-left</v-icon> Peaks</v-btn
+        >
+        <v-divider vertical inset></v-divider>
+        <v-toolbar-title class="text-uppercase ml-2">
+          <v-btn text class="text-h5" @click="goToPeak()"
+            >Peak {{ peak.id }}
+          </v-btn>
+          <small class="text--secondary">
+            chromosome {{ peak.chromosome }}, position
             {{ peak.position }}</small
           ></v-toolbar-title
         >
-
         <v-spacer></v-spacer>
-        <v-btn-toggle
-          v-model="toggle_exclusive"
-          dense
-          tile
-          group
-          color="secondary"
-        >
-          <v-btn :to="showCoefficients()"> QTL effects </v-btn>
-          <v-btn :to="showHaplotypes()"> Haplotypes </v-btn>
-          <v-btn :to="showSnpsAssociations()">SNPs associations</v-btn>
-          <v-btn :to="showTopSnps()">Top SNP</v-btn>
-        </v-btn-toggle>
+        <v-chip small color="accent">Peak</v-chip>
       </v-toolbar>
-      <!-- <v-card-title>Peak {{ peak.id }}</v-card-title>
-      <v-card-subtitle>
-        chromosome {{ peak.chromosome }}, position {{ peak.position }}
-      </v-card-subtitle>
-      <v-card-actions>
-        <v-btn color="primary" :to="showCoefficients()">Show QTL effects</v-btn>
-        <v-btn color="primary" :to="showSnpsAssociations()"
-          >Show snps associations</v-btn
-        >
-        <v-btn color="primary" :to="showTopSnps()">Show top snps</v-btn>
-      </v-card-actions> -->
-      <nuxt-child />
+      <v-card class="d-flex justify-center mb-6 mt-2" flat tile>
+        <v-card flat>
+          <v-card-text>
+            <v-slide-group show-arrows>
+              <v-slide-item v-slot="{ active, toggle }">
+                <v-btn
+                  depressed
+                  rounded
+                  class="mx-2"
+                  :input-value="active"
+                  :to="showCoefficients()"
+                  @click="toggle"
+                >
+                  <v-icon left> mdi-chart-line</v-icon> Effects
+                </v-btn>
+              </v-slide-item>
+              <v-slide-item v-slot="{ active }">
+                <v-btn
+                  depressed
+                  rounded
+                  class="mx-2"
+                  :input-value="active"
+                  :to="showHaplotypes()"
+                >
+                  <v-icon left> mdi-chart-bar</v-icon> Haplotypes
+                </v-btn>
+              </v-slide-item>
+              <v-slide-item v-slot="{ active }">
+                <v-btn
+                  depressed
+                  rounded
+                  class="mx-2"
+                  :input-value="active"
+                  :to="showSnpsAssociations()"
+                >
+                  <v-icon left> mdi-chart-scatter-plot</v-icon>SNPs</v-btn
+                >
+              </v-slide-item>
+              <v-slide-item v-slot="{ active }">
+                <v-btn
+                  class="mx-2"
+                  depressed
+                  rounded
+                  :input-value="active"
+                  :to="showTopSnps()"
+                  ><v-icon left> mdi-chart-box-outline</v-icon>Top SNPs</v-btn
+                >
+              </v-slide-item>
+              <v-slide-item v-slot="{ active }">
+                <v-btn
+                  class="mx-2"
+                  depressed
+                  rounded
+                  :input-value="active"
+                  :to="showGenes()"
+                  ><v-icon left> mdi-chart-box-outline</v-icon>Genes</v-btn
+                >
+              </v-slide-item>
+            </v-slide-group>
+          </v-card-text>
+        </v-card>
+      </v-card>
+      <nuxt-child :project="project" :analysis="analysis" :peak="peak" />
     </v-card>
   </div>
 </template>
 
 <script>
 export default {
+  props: {
+    project: { type: Object, default: () => ({}) },
+    analysis: { type: Object, default: () => ({}) },
+  },
+
   async asyncData({ $axios, params, $auth }) {
     const { id: projectId, analysisId, peakId } = params
     const peak = await $axios.$get(
-      `/api/projects/${projectId}/analysis/${analysisId}/peaks/${peakId}`
+      `/api/projects/${projectId}/analysis/${analysisId}/peaks/${peakId}/`
     )
     return { peak }
   },
   data() {
     return {
-      toggle_exclusive: 1,
       peak: null,
     }
   },
   methods: {
     showCoefficients() {
       const { id: projectId, analysisId, peakId } = this.$route.params
+
       return {
         name:
-          'projects-id-analysis-analysisId-results-peaks-peakId-coefficients',
+          'projects-id-analysis-analysisId' +
+          '-results-peaks-peakId-coefficients',
         params: { id: projectId, analysisId, peakId },
       }
     },
@@ -85,6 +136,30 @@ export default {
         params: { id: projectId, analysisId, peakId },
       }
     },
+    showGenes() {
+      const { id: projectId, analysisId, peakId } = this.$route.params
+      return {
+        name: 'projects-id-analysis-analysisId-results-peaks-peakId-genes',
+        params: { id: projectId, analysisId, peakId },
+      }
+    },
+    peaksListRoute() {
+      const { id, analysisId } = this.$route.params
+      return {
+        name: 'projects-id-analysis-analysisId-results-peaks',
+        params: { id, analysisId },
+      }
+    },
+    goToPeaksListRoute() {
+      this.$router.push(this.peaksListRoute())
+    },
+    goToPeak() {
+      const { id, analysisId, peakId } = this.$route.params
+      this.$router.push({
+        name: 'projects-id-analysis-analysisId-results-peaks-peakId',
+        params: { id, analysisId, peakId },
+      })
+    },
   },
 }
 </script>
diff --git a/client-nuxt/pages/projects/_id/analysis/_analysisId/results/peaks/_peakId/coefficients/index.vue b/client-nuxt/pages/projects/_id/analysis/_analysisId/results/peaks/_peakId/coefficients/index.vue
index 18f0eb1d9d97f2079ae1900724629a16a88e2c81..6bb5e314c9dd763d6c36908548bba0abae13d2f2 100644
--- a/client-nuxt/pages/projects/_id/analysis/_analysisId/results/peaks/_peakId/coefficients/index.vue
+++ b/client-nuxt/pages/projects/_id/analysis/_analysisId/results/peaks/_peakId/coefficients/index.vue
@@ -1,25 +1,10 @@
 <template>
-  <div>
-    <v-card-title>QTL Effects</v-card-title>
-    <v-card-text><div class="coefficients"></div></v-card-text>
-    <v-card-title>
-      SNPs associated
-      <download-csv :data="filterCoeff" :name="getFilename">
-        <v-fab-transition>
-          <v-btn class="mx-2" color="secondary" small dark elevation="5" fab>
-            <v-icon>mdi-table-arrow-down</v-icon>
-          </v-btn>
-        </v-fab-transition>
-      </download-csv>
-      <v-spacer></v-spacer>
-      <v-text-field
-        v-model="search"
-        append-icon="mdi-magnify"
-        label="Search"
-        single-line
-        hide-details
-      ></v-text-field>
-    </v-card-title>
+  <v-card flat>
+    <qtl-effect
+      v-model="axis"
+      :effects="filterCoeff"
+      :color-map="colorMap"
+    ></qtl-effect>
     <v-card-text>
       <v-data-table
         dense
@@ -31,115 +16,112 @@
         :sort-desc="[false]"
         multi-sort
         item-key="pos"
-      ></v-data-table>
+      >
+        <template #top>
+          <v-toolbar flat>
+            <v-toolbar-title>QTL Effects data</v-toolbar-title>
+            <v-divider class="mx-4" inset vertical></v-divider>
+            <v-text-field
+              v-model="search"
+              append-icon="mdi-magnify"
+              label="Search"
+              single-line
+              hide-details
+              clearable
+            ></v-text-field>
+            <v-spacer></v-spacer>
+            <download-csv :data="filterCoeff" :name="getFilename">
+              <v-fab-transition>
+                <v-btn class="mx-2" color="secondary" small elevation="5" fab>
+                  <v-icon>mdi-table-arrow-down</v-icon>
+                </v-btn>
+              </v-fab-transition>
+            </download-csv>
+          </v-toolbar>
+        </template></v-data-table
+      >
     </v-card-text>
-  </div>
+  </v-card>
 </template>
 
 <script>
-import { extent } from 'd3-array'
-import { QtlCoefficient } from 'bioviz-js'
-import { select } from 'd3-selection'
+// import { extent } from 'd3-array'
+// import { QtlCoefficient } from 'bioviz-js'
+// import { select } from 'd3-selection'
 import JsonCSV from 'vue-json-csv'
+import QtlEffect from '@/components/charts/QtlEffect'
 
 export default {
   components: {
     downloadCsv: JsonCSV,
+    QtlEffect,
+  },
+  props: {
+    project: { type: Object, default: () => ({}) },
+    analysis: { type: Object, default: () => ({}) },
+    peak: { type: Object, default: () => ({}) },
   },
   async asyncData({ $axios, params, $auth }) {
     const { id: projectId, analysisId, peakId } = params
     const { coefficients } = await $axios.$get(
-      `/api/projects/${projectId}/analysis/${analysisId}/peaks/${peakId}/coefficients`
-    )
-    const founders = await $axios.$get('/api/founders')
-    const project = await $axios.$get(`/api/projects/${projectId}`)
-    const analysis = await $axios.$get(
-      `/api/projects/${projectId}/analysis/${analysisId}`
+      `/api/projects/${projectId}/analysis/${analysisId}/peaks/${peakId}/coefficients/`
     )
+    const founders = await $axios.$get('/api/founders/')
 
     return {
       // think of an other way to do id
       coefficients,
       founders,
-      project,
-      analysis,
-      peakId,
-      xAxis: extent(coefficients.map((d) => d.position)),
-      yAxis: extent(coefficients.map((d) => d.lodscore)),
     }
   },
   data() {
     return {
       coefficients: null,
       founders: null,
-      project: null,
-      analysis: null,
-      peakId: null,
       search: '',
+      axis: null,
     }
   },
   computed: {
-    getColorMap() {
-      return new Map(this.founders.map((d) => [d.cc_designation, d.color]))
+    colorMap() {
+      if (this.founders) {
+        return new Map(this.founders.map((d) => [d.cc_designation, d.color]))
+      } else {
+        return new Map()
+      }
     },
     getHeader() {
-      return Object.keys(this.coefficients[0]).map((d) => ({
-        text: d,
-        value: d,
-      }))
+      if (this.coefficients) {
+        return Object.keys(this.coefficients[0]).map((d) => ({
+          text: d,
+          value: d,
+        }))
+      } else {
+        return []
+      }
     },
     filterCoeff() {
-      return this.coefficients.filter(
-        (d) =>
-          d.position >= this.xAxis[0] &&
-          d.position <= this.xAxis[1] &&
-          d.lodscore >= this.yAxis[0] &&
-          d.lodscore <= this.yAxis[1]
-      )
+      if (this.coefficients) {
+        if (this.axis) {
+          return this.coefficients.filter(
+            (d) => d.position >= this.axis.x[0] && d.position <= this.axis.x[1]
+          )
+          // &&
+          // d.lodscore >= this.axis.y[0] &&
+          // d.lodscore <= this.axis.y[1]
+        } else {
+          return this.coefficients
+        }
+      } else {
+        return []
+      }
     },
     getFilename() {
-      return `coefficients-${this.project.project_name}-${this.analysis.name}-${this.peakId}.csv`
-    },
-  },
-  mounted() {
-    this.$nextTick(function () {
-      this.draw(this.coefficients)
-    })
-  },
-  beforeUpdate() {
-    this.draw(this.coefficients)
-  },
-  methods: {
-    draw(coefficients) {
-      const self = this
-      const container = select('.coefficients')
-      container
-        .datum(coefficients)
-        .call(
-          QtlCoefficient(),
-          `Chromosome ${this.coefficients[0].chromosome}`,
-          this.getColorMap
-        )
-      container.node().on('plotly_relayout', function (eventdata) {
-        if ('xaxis.range[0]' in eventdata) {
-          self.xAxis = [eventdata['xaxis.range[0]'], self.xAxis[1]]
-        }
-        if ('xaxis.range[1]' in eventdata) {
-          self.xAxis = [self.xAxis[0], eventdata['xaxis.range[1]']]
-        }
-        if ('yaxis2.range[0]' in eventdata) {
-          self.yAxis = [eventdata['yaxis2.range[0]'], self.yAxis[1]]
-        }
-        if ('yaxis2.range[1]' in eventdata) {
-          self.yAxis = [self.yAxis[0], eventdata['yaxis2.range[1]']]
-        }
-        if ('xaxis.autorange' in eventdata) {
-          self.xAxis = extent(self.coefficients.map((d) => d.position))
-        }
-        if ('yaxis2.autorange' in eventdata) {
-          self.yAxis = extent(self.coefficients.map((d) => d.lodscore))
-        }
-      })
+      if (this.project && this.analysis && this.peak) {
+        return `coefficients-${this.project.project_name}-${this.analysis.name}-${this.peak.id}.csv`
+      } else {
+        return ''
+      }
     },
   },
 }
diff --git a/client-nuxt/pages/projects/_id/analysis/_analysisId/results/peaks/_peakId/genes/index.vue b/client-nuxt/pages/projects/_id/analysis/_analysisId/results/peaks/_peakId/genes/index.vue
new file mode 100644
index 0000000000000000000000000000000000000000..5fa1e248af4038be6921c8c1a3be10f2cd88e390
--- /dev/null
+++ b/client-nuxt/pages/projects/_id/analysis/_analysisId/results/peaks/_peakId/genes/index.vue
@@ -0,0 +1,242 @@
+<template>
+  <v-card flat>
+    <v-card-text>
+      <v-data-table
+        dense
+        :headers="header"
+        :items="genes"
+        :items-per-page="10"
+        :search="search"
+        :sort-by="['start']"
+        :sort-desc="[false]"
+        multi-sort
+        item-key="id.id"
+      >
+        <template #top>
+          <v-toolbar flat class="mb-2">
+            <v-toolbar-title>Genes</v-toolbar-title>
+            <v-divider class="mx-4" inset vertical></v-divider>
+            <v-text-field
+              v-model="search"
+              append-icon="mdi-magnify"
+              label="Search"
+              single-line
+              hide-details
+              clearable
+            ></v-text-field>
+            <v-spacer></v-spacer>
+            <download-csv :data="rawGenes" :name="getFilename">
+              <v-fab-transition>
+                <v-btn class="mx-2" color="secondary" small elevation="5" fab>
+                  <v-icon>mdi-table-arrow-down</v-icon>
+                </v-btn>
+              </v-fab-transition>
+            </download-csv>
+          </v-toolbar>
+        </template>
+        <template #[`item.id`]="{ value }">
+          <v-chip
+            :href="value.url"
+            :color="value.color"
+            :text-color="value.textColor"
+            target="_blank"
+            link
+            nuxt
+            small
+            >{{ value.id }}</v-chip
+          >
+        </template>
+        <template #[`item.dbxref`]="{ value }">
+          <div class="d-flex flex-wrap">
+            <v-chip
+              v-for="v in value"
+              :key="v.id"
+              :href="v.url"
+              :color="v.color"
+              :text-color="v.textColor"
+              target="_blank"
+              link
+              nuxt
+              small
+              class="ma-1"
+            >
+              {{ v.database }} : {{ v.id }}
+            </v-chip>
+          </div>
+        </template></v-data-table
+      >
+    </v-card-text>
+  </v-card>
+</template>
+
+<script>
+import JsonCSV from 'vue-json-csv'
+
+export default {
+  components: {
+    downloadCsv: JsonCSV,
+  },
+  props: {
+    project: { type: Object, default: () => ({}) },
+    analysis: { type: Object, default: () => ({}) },
+    peak: { type: Object, default: () => ({}) },
+  },
+
+  async asyncData({ $axios, params }) {
+    const { id: projectId, analysisId, peakId } = params
+    const { genes: rawGenes } = await $axios.$get(
+      `/api/projects/${projectId}/analysis/${analysisId}/peaks/${peakId}/genes/`
+    )
+    return { rawGenes }
+  },
+  data() {
+    return {
+      search: '',
+      header: [
+        { text: 'Id', value: 'id' },
+        { text: 'Chromosome', value: 'chromosome' },
+        { text: 'Start', value: 'start' },
+        { text: 'Stop', value: 'stop' },
+        { text: 'Strand', value: 'strand' },
+        { text: 'Type', value: 'type' },
+        { text: 'Biotype ', value: 'bioType' },
+        { text: 'Name', value: 'name' },
+        { text: 'MGI Name', value: 'mgiName' },
+        { text: 'Alias', value: 'alias' },
+        // { text: 'Source', value: 'source' },
+        { text: 'Database cross-reference', value: 'dbxref' },
+        { text: 'Score', value: 'score' },
+        // { text: 'Parent', value: 'parent' },
+        // { text: 'Phase', value: 'phase' },
+        { text: '', value: '' },
+        { text: '', value: '' },
+        { text: '', value: '' },
+      ],
+      dbxref: {
+        ncbi: {
+          database: 'NCBI',
+          url: 'https://www.ncbi.nlm.nih.gov/gene',
+          color: '#369',
+          textColor: 'white',
+        },
+        vega: {
+          database: 'VEGA',
+          url: 'https://vega.archive.ensembl.org/Mus_musculus/Gene/Summary?g',
+          color: '#abe',
+          textColor: '#000000de',
+        },
+        ensembl: {
+          database: 'ENSEMBL',
+          url: 'http://www.ensembl.org/Mus_musculus/Gene/Summary?g',
+          color: '#336',
+          textColor: 'white',
+        },
+        mirbase: {
+          database: 'miRBase',
+          url: 'https://www.mirbase.org/cgi-bin/mirna_entry.pl?acc',
+          color: '#006',
+          textColor: 'white',
+        },
+        genbank: {
+          database: 'GenBank',
+          url: 'https://www.ncbi.nlm.nih.gov/nuccore',
+          color: '#369',
+          textColor: 'white',
+        },
+        mgi: {
+          database: 'MGI',
+          url: 'http://www.informatics.jax.org/marker/',
+          color: '#DFEFFF',
+          textColor: '#000000de',
+        },
+        default: {
+          database: null,
+          url: null,
+          color: null,
+        },
+      },
+    }
+  },
+  computed: {
+    genes() {
+      return this.rawGenes.map((g) => ({
+        ...g,
+        id: this.idStringToObj(g.id),
+        dbxref: g.dbxref.split(',').map((dbxref) => {
+          const [db, id] = dbxref.split(':')
+          switch (db) {
+            case 'NCBI_Gene':
+              return {
+                ...this.dbxref.ncbi,
+                url: `${this.dbxref.ncbi.url}/${id}`,
+                id,
+              }
+            case 'VEGA':
+              return {
+                ...this.dbxref.vega,
+                url: `${this.dbxref.vega.url}=${id}`,
+                id,
+              }
+            case 'ENSEMBL':
+              return {
+                ...this.dbxref.ensembl,
+                url: `${this.dbxref.ensembl.url}=${id}`,
+                id,
+              }
+            case 'miRBase':
+              return {
+                ...this.dbxref.mirbase,
+                url: `${this.dbxref.mirbase.url}=${id}`,
+                id,
+              }
+            case 'GenBank':
+              return {
+                ...this.dbxref.genbank,
+                url: `${this.dbxref.genbank.url}/${id}`,
+                id,
+              }
+            default:
+              return {
+                ...this.dbxref.default,
+                database: db,
+                id,
+                color: null,
+                url: null,
+              }
+          }
+        }),
+      }))
+    },
+    // header() {
+    //   return this.genes.length > 0
+    //     ? // ? Object.keys(this.genes[0]).map((d) => ({ text: d, value: d }))
+    //       this.defaultHeader.map((it) => ({ text: it, value: it }))
+    //     : []
+    // },
+    getFilename() {
+      return `genes-${this.project.project_name}-${this.analysis.name}-${this.peak.id}.csv`
+    },
+  },
+  methods: {
+    idStringToObj(dbxref) {
+      const idSplit = dbxref.split(':')
+      if (idSplit.length === 3) {
+        const id = idSplit.slice(-2).join(':')
+        return {
+          ...this.dbxref.mgi,
+          url: `${this.dbxref.mgi.url}/${id}`,
+          id,
+        }
+      } else {
+        return {
+          ...this.dbxref.default,
+          url: null,
+          id: dbxref,
+        }
+      }
+    },
+  },
+}
+</script>
+
+<style></style>
diff --git a/client-nuxt/pages/projects/_id/analysis/_analysisId/results/peaks/_peakId/haplotypes/index.vue b/client-nuxt/pages/projects/_id/analysis/_analysisId/results/peaks/_peakId/haplotypes/index.vue
index d023d9fad5f0e30996ea3dcc416b0c4ab6c53b47..71f0e3e956ae6f3149a9fd3571ae0c62d96e2ed2 100644
--- a/client-nuxt/pages/projects/_id/analysis/_analysisId/results/peaks/_peakId/haplotypes/index.vue
+++ b/client-nuxt/pages/projects/_id/analysis/_analysisId/results/peaks/_peakId/haplotypes/index.vue
@@ -1,52 +1,96 @@
 <template>
-  <div>
-    <v-card-title>Haplotypes</v-card-title>
-    <div class="haplotypes"></div>
-  </div>
+  <v-card flat color="transparent">
+    <haplotype :haplotypes="haplotypes" :color-map="colorMap"></haplotype>
+
+    <v-card-text>
+      <v-data-table
+        dense
+        :headers="headers"
+        :items="haplotypes"
+        :items-per-page="10"
+        :search="search"
+        :sort-by="['ccline']"
+        :sort-desc="[false]"
+        multi-sort
+      >
+        <template #top>
+          <v-toolbar flat>
+            <v-toolbar-title> Haplotypes data</v-toolbar-title>
+            <v-divider class="mx-4" inset vertical></v-divider>
+            <v-text-field
+              v-model="search"
+              append-icon="mdi-magnify"
+              label="Search"
+              single-line
+              hide-details
+              clearable
+            ></v-text-field>
+            <v-spacer></v-spacer>
+            <download-csv :data="haplotypes" :name="getFilename">
+              <v-fab-transition>
+                <v-btn class="mx-2" color="secondary" small elevation="5" fab>
+                  <v-icon>mdi-table-arrow-down</v-icon>
+                </v-btn>
+              </v-fab-transition>
+            </download-csv>
+          </v-toolbar>
+        </template>
+      </v-data-table>
+    </v-card-text>
+  </v-card>
 </template>
 
 <script>
-import { Haplotype } from 'bioviz-js'
-import { select } from 'd3-selection'
+import Haplotype from '@/components/charts/Haplotype'
+import JsonCSV from 'vue-json-csv'
 
 export default {
+  components: { downloadCsv: JsonCSV, Haplotype },
+  props: {
+    project: { type: Object, default: () => ({}) },
+    analysis: { type: Object, default: () => ({}) },
+    peak: { type: Object, default: () => ({}) },
+  },
+
   async asyncData({ $axios, params, $auth }) {
     const { id: projectId, analysisId, peakId } = params
     const { haplotypes: rawHaplotypes } = await $axios.$get(
-      `/api/projects/${projectId}/analysis/${analysisId}/peaks/${peakId}/haplotypes`
+      `/api/projects/${projectId}/analysis/${analysisId}/peaks/${peakId}/haplotypes/`
     )
-    const founders = await $axios.$get('/api/founders')
+    const founders = await $axios.$get('/api/founders/')
 
     return {
       haplotypes: rawHaplotypes.map((haplo) => ({
-        phenotype: haplo.phenotype,
-        haplotype: haplo.haplotype,
-        line: haplo.ccline,
+        ...haplo,
+        phenotype: parseFloat(haplo.phenotype),
       })),
       founders,
     }
   },
   data() {
     return {
+      search: '',
       haplotypes: [],
       founders: [],
     }
   },
   computed: {
-    getColorMap() {
-      return new Map(
-        this.founders.map((d) => [d.cc_designation + d.cc_designation, d.color])
-      )
+    headers() {
+      return this.haplotypes.length > 0
+        ? Object.keys(this.haplotypes[0]).map((d) => ({ text: d, value: d }))
+        : []
     },
-  },
-  mounted() {
-    this.draw(this.haplotypes)
-  },
-  methods: {
-    draw(haplotypes) {
-      select('.haplotypes')
-        .datum(haplotypes)
-        .call(Haplotype(), this.getColorMap)
+    getFilename() {
+      return `haplotypes-${this.project.project_name}-${this.analysis.name}-${this.peak.id}.csv`
+    },
+    colorMap() {
+      return new Map([
+        ...this.founders.map((d) => [
+          d.cc_designation + d.cc_designation,
+          d.color,
+        ]),
+        ['NA', '#000000'],
+      ])
     },
   },
 }
diff --git a/client-nuxt/pages/projects/_id/analysis/_analysisId/results/peaks/_peakId/snps/index.vue b/client-nuxt/pages/projects/_id/analysis/_analysisId/results/peaks/_peakId/snps/index.vue
index 1ceaab728753b356a32978389cff806cabdce30b..50ecfd9cc12a957f0292fe6470962a6a12d937f8 100644
--- a/client-nuxt/pages/projects/_id/analysis/_analysisId/results/peaks/_peakId/snps/index.vue
+++ b/client-nuxt/pages/projects/_id/analysis/_analysisId/results/peaks/_peakId/snps/index.vue
@@ -1,83 +1,82 @@
 <template>
-  <div>
-    <v-card-title>SNPs associations</v-card-title>
-    <div class="snps-associations"></div>
-    <v-card-title>
-      SNPs associated
-      <download-csv :data="filterSnps" :name="getFilename">
-        <v-fab-transition>
-          <v-btn class="mx-2" color="secondary" small dark elevation="5" fab>
-            <v-icon>mdi-table-arrow-down</v-icon>
-          </v-btn>
-        </v-fab-transition>
-      </download-csv>
-      <v-spacer></v-spacer>
-      <v-text-field
-        v-model="search"
-        append-icon="mdi-magnify"
-        label="Search"
-        single-line
-        hide-details
-      ></v-text-field>
-    </v-card-title>
+  <v-card flat>
+    <v-card-text>
+      <snps-association v-model="axis" :serie="filteredSnps"></snps-association>
+    </v-card-text>
+    <v-card-text> <div class="snps-associations"></div></v-card-text>
     <v-card-text>
       <v-data-table
         dense
         :headers="getHeader"
-        :items="filterSnps"
+        :items="filteredSnps"
         :items-per-page="10"
         :search="search"
-        :sort-by="['pos']"
+        :sort-by="['position']"
         :sort-desc="[false]"
         multi-sort
         item-key="snp_id"
-      ></v-data-table>
+      >
+        <template #top>
+          <v-toolbar flat>
+            <v-toolbar-title>Associated SNPs data</v-toolbar-title>
+            <v-divider class="mx-4" inset vertical></v-divider>
+            <v-text-field
+              v-model="search"
+              append-icon="mdi-magnify"
+              label="Search"
+              single-line
+              hide-details
+              clearable
+            ></v-text-field>
+            <v-spacer></v-spacer>
+            <download-csv :data="filteredSnps" :name="getFilename">
+              <v-fab-transition>
+                <v-btn class="mx-2" color="secondary" small elevation="5" fab>
+                  <v-icon>mdi-table-arrow-down</v-icon>
+                </v-btn>
+              </v-fab-transition>
+            </download-csv>
+          </v-toolbar>
+        </template></v-data-table
+      >
     </v-card-text>
-  </div>
+  </v-card>
 </template>
 
 <script>
-import { Snps } from 'bioviz-js'
-import { select } from 'd3-selection'
-import { extent } from 'd3-array'
+import SnpsAssociation from '@/components/charts/SnpsAssociation'
+
 import JsonCSV from 'vue-json-csv'
 
 export default {
   components: {
     downloadCsv: JsonCSV,
+    SnpsAssociation,
+  },
+  props: {
+    project: { type: Object, default: () => ({}) },
+    analysis: { type: Object, default: () => ({}) },
+    peak: { type: Object, default: () => ({}) },
   },
   async asyncData({ $axios, params, $auth }) {
     const { id: projectId, analysisId, peakId } = params
     const { snps_association: rawSnps } = await $axios.$get(
-      `/api/projects/${projectId}/analysis/${analysisId}/peaks/${peakId}/snps_association`
-    )
-    const project = await $axios.$get(`/api/projects/${projectId}`)
-    const analysis = await $axios.$get(
-      `/api/projects/${projectId}/analysis/${analysisId}`
+      `/api/projects/${projectId}/analysis/${analysisId}/peaks/${peakId}/snps_association/`
     )
     return {
       snps: rawSnps.map((d) => ({
         snp_id: d.snp_id,
-        chr: d.chromosome,
-        pos: d.position,
-        lod: d.lodscore,
+        chromosome: d.chromosome,
+        position: parseInt(d.position),
+        lodscore: parseFloat(d.lodscore),
       })),
-      xAxis: extent(rawSnps.map((d) => d.position)),
-      yAxis: extent(rawSnps.map((d) => d.lodscore)),
-      project,
-      analysis,
-      peakId,
     }
   },
   data() {
     return {
       search: '',
       snps: [],
-      xAxis: [],
-      yAxis: [],
-      project: null,
-      analysis: null,
-      peakId: null,
+      axis: null,
     }
   },
   computed: {
@@ -86,52 +85,21 @@ export default {
         ? Object.keys(this.snps[0]).map((d) => ({ text: d, value: d }))
         : []
     },
-    filterSnps() {
-      return this.snps.filter(
-        (d) =>
-          d.pos >= this.xAxis[0] &&
-          d.pos <= this.xAxis[1] &&
-          d.lod >= this.yAxis[0] &&
-          d.lod <= this.yAxis[1]
-      )
-    },
     getFilename() {
-      return `associated-snps-${this.project.project_name}-${this.analysis.name}-${this.peakId}.csv`
-    },
-    computDraw() {
-      return true
+      return `associated-snps-${this.project.project_name}-${this.analysis.name}-${this.peak.id}.csv`
     },
-  },
-  mounted() {
-    this.draw()
-  },
-  methods: {
-    draw() {
-      const self = this
-      const container = select('.snps-associations')
-      container
-        .datum(this.filterSnps)
-        .call(Snps(), `Chromosome ${this.filterSnps[0].chr}`)
-      container.node().on('plotly_relayout', function (eventdata) {
-        if ('xaxis.range[0]' in eventdata) {
-          self.xAxis = [eventdata['xaxis.range[0]'], self.xAxis[1]]
-        }
-        if ('xaxis.range[1]' in eventdata) {
-          self.xAxis = [self.xAxis[0], eventdata['xaxis.range[1]']]
-        }
-        if ('yaxis.range[0]' in eventdata) {
-          self.yAxis = [eventdata['yaxis.range[0]'], self.yAxis[1]]
-        }
-        if ('yaxis.range[1]' in eventdata) {
-          self.yAxis = [self.yAxis[0], eventdata['yaxis.range[1]']]
-        }
-        if ('xaxis.autorange' in eventdata) {
-          self.xAxis = extent(self.snps.map((d) => d.pos))
-        }
-        if ('yaxis.autorange' in eventdata) {
-          self.yAxis = extent(self.snps.map((d) => d.lod))
-        }
-      })
+    filteredSnps() {
+      if (this.axis) {
+        return this.snps.filter(
+          (d) =>
+            d.position >= this.axis.x[0] &&
+            d.position <= this.axis.x[1] &&
+            d.lodscore >= this.axis.y[0] &&
+            d.lodscore <= this.axis.y[1]
+        )
+      } else {
+        return this.snps
+      }
     },
   },
 }
diff --git a/client-nuxt/pages/projects/_id/analysis/_analysisId/results/peaks/_peakId/topsnps/index.vue b/client-nuxt/pages/projects/_id/analysis/_analysisId/results/peaks/_peakId/topsnps/index.vue
index 142409ec9d954fabaa0da4fb475ce3743cad1ef6..bf7aee01e855c05a436de7c7cf4b8afce7d6c937 100644
--- a/client-nuxt/pages/projects/_id/analysis/_analysisId/results/peaks/_peakId/topsnps/index.vue
+++ b/client-nuxt/pages/projects/_id/analysis/_analysisId/results/peaks/_peakId/topsnps/index.vue
@@ -1,30 +1,26 @@
 <template>
   <div>
-    <v-card-title>Top SNP</v-card-title>
-    <div class="top-snps"></div>
-    <v-card-title>
-      SNPs associated
-      <download-csv :data="filterSnps" :name="getFilename">
-        <v-fab-transition>
-          <v-btn class="mx-2" color="secondary" small dark elevation="5" fab>
-            <v-icon>mdi-table-arrow-down</v-icon>
-          </v-btn>
-        </v-fab-transition>
-      </download-csv>
-      <v-spacer></v-spacer>
-      <v-text-field
-        v-model="search"
-        append-icon="mdi-magnify"
-        label="Search"
-        single-line
-        hide-details
-      ></v-text-field>
-    </v-card-title>
+    <v-card-title></v-card-title>
+    <v-toolbar flat>
+      <v-select
+        v-model="selectedTopSnps"
+        :items="topSnpOptions"
+        outlined
+        hide-details="auto"
+        label="Select top snp"
+      ></v-select
+    ></v-toolbar>
+    <top-snp
+      v-model="selectedPoints"
+      :top-snp="snpsWithId"
+      :color-map="colorMap"
+    ></top-snp>
+
     <v-card-text>
       <v-data-table
         dense
-        :headers="getHeader"
-        :items="filterSnps"
+        :headers="headers"
+        :items="snpsWithId"
         :items-per-page="10"
         :search="search"
         :sort-by="['genotype']"
@@ -33,75 +29,110 @@
         multi-sort
         item-key="id"
         show-group-by
-      ></v-data-table>
+      >
+        <template #top>
+          <v-toolbar flat>
+            <v-toolbar-title> Top SNPs data</v-toolbar-title>
+            <v-divider class="mx-4" inset vertical></v-divider>
+            <v-text-field
+              v-model="search"
+              append-icon="mdi-magnify"
+              label="Search"
+              single-line
+              hide-details
+              clearable
+            ></v-text-field>
+            <v-spacer></v-spacer>
+            <download-csv :data="snps" :name="getFilename">
+              <v-fab-transition>
+                <v-btn class="mx-2" color="secondary" small elevation="5" fab>
+                  <v-icon>mdi-table-arrow-down</v-icon>
+                </v-btn>
+              </v-fab-transition>
+            </download-csv>
+          </v-toolbar>
+        </template>
+      </v-data-table>
     </v-card-text>
   </div>
 </template>
 
 <script>
-import { Snp } from 'bioviz-js'
-import { select } from 'd3-selection'
-import { extent, group } from 'd3-array'
+import TopSnp from '@/components/charts/TopSnp'
 import JsonCSV from 'vue-json-csv'
 
 export default {
   components: {
     downloadCsv: JsonCSV,
+    TopSnp,
+  },
+  props: {
+    project: { type: Object, default: () => ({}) },
+    analysis: { type: Object, default: () => ({}) },
+    peak: { type: Object, default: () => ({}) },
   },
   async asyncData({ $axios, params, $auth }) {
     const { id: projectId, analysisId, peakId } = params
-    const { top_snps: rawSnps } = await $axios.$get(
-      `/api/projects/${projectId}/analysis/${analysisId}/peaks/${peakId}/top_snps`
-    )
-    const founders = await $axios.$get('/api/founders')
-    const project = await $axios.$get(`/api/projects/${projectId}`)
-    const analysis = await $axios.$get(
-      `/api/projects/${projectId}/analysis/${analysisId}`
+    const { top_snps: snps } = await $axios.$get(
+      `/api/projects/${projectId}/analysis/${analysisId}/peaks/${peakId}/top_snps/`
     )
-    const snps = Array.from(
-      group(rawSnps, (d) => d.genotype),
-      ([key, values]) => ({ key, values })
-    )
-
+    const founders = await $axios.$get('/api/founders/')
     return {
       founders,
       snps,
-      yAxisRange: extent(rawSnps, (d) => d.phenotype),
-      project,
-      analysis,
-      peakId,
     }
   },
   data() {
     return {
       search: '',
-      project: null,
-      analysis: null,
-      peakId: null,
+      selectedPoints: null,
       snps: [],
       founders: null,
-      yAxisRange: [],
+      selectedTopSnps: 'top_snp_1',
     }
   },
   computed: {
-    getColorMap() {
-      return new Map(this.founders.map((d) => [d.cc_designation, d.color]))
+    snpsWithId() {
+      return this.snps.map((snp, id) => ({
+        ccline: snp.ccline,
+        phenotype: snp.phenotype,
+        id,
+        genotype: snp[this.selectedTopSnps],
+      }))
+    },
+    snpsData() {
+      return this.selectedPoints === null
+        ? this.snpsWithId
+        : this.snpsWithId.filter(({ id }) => this.selectedPoints.has(id))
     },
-    filterSnps() {
-      return this.snps
-        .reduce((acc, snp) => {
-          return [...acc, ...snp.values]
-        }, [])
-        .filter(
-          (d) =>
-            d.phenotype >= this.yAxisRange[0] &&
-            d.phenotype <= this.yAxisRange[1]
-        )
+
+    topSnpOptions() {
+      if (this.snps.length > 0) {
+        return Object.keys(this.snps[0])
+          .filter((item) => item.startsWith('top_snp_'))
+          .map((item) => ({
+            text: 'Top snp ' + item.split('_').slice(-1)[0],
+            value: item,
+          }))
+      } else {
+        return []
+      }
+    },
+    colorMap() {
+      return new Map([
+        ...this.founders.map((d) => [d.cc_designation, d.color]),
+        ['NA', '#000000'],
+      ])
     },
-    getHeader() {
-      return this.snps.length > 0
-        ? Object.keys(this.snps[0].values[0])
-            .filter((d) => d !== 'id')
+    headers() {
+      return this.snpsWithId.length > 0
+        ? Object.keys(this.snpsWithId[0])
+            .filter(
+              (item) =>
+                !item.startsWith('top_snp_') ||
+                item === this.selectedTopSnps ||
+                item !== 'id'
+            )
             .map((d) => ({
               text: d,
               value: d,
@@ -109,27 +140,11 @@ export default {
         : []
     },
     getFilename() {
-      return `topsnps-${this.project.project_name}-${this.analysis.name}-${this.peakId}.csv`
-    },
-  },
-  mounted() {
-    this.draw()
-  },
-  methods: {
-    draw(snps) {
-      const self = this
-      const container = select('.top-snps')
-      container.datum(this.snps).call(Snp(), this.getColorMap)
-      container.node().on('plotly_relayout', function (eventdata) {
-        if ('yaxis.range[0]' in eventdata) {
-          self.yAxisRange = [eventdata['yaxis.range[0]'], self.yAxisRange[1]]
-        }
-        if ('yaxis.range[1]' in eventdata) {
-          self.yAxisRange = [self.yAxisRange[0], eventdata['yaxis.range[1]']]
-        }
-      })
+      return `topsnps-${this.project.project_name}-${this.analysis.name}-${this.peak.id}.csv`
     },
   },
+
+  methods: {},
 }
 </script>
 
diff --git a/client-nuxt/pages/projects/_id/analysis/_analysisId/results/peaks/index.vue b/client-nuxt/pages/projects/_id/analysis/_analysisId/results/peaks/index.vue
new file mode 100644
index 0000000000000000000000000000000000000000..08ede43f854d5f9b06791ba976f9a9772fc07385
--- /dev/null
+++ b/client-nuxt/pages/projects/_id/analysis/_analysisId/results/peaks/index.vue
@@ -0,0 +1,122 @@
+<template>
+  <v-card flat color="transparent" class="mt-3">
+    <v-card>
+      <error-alert v-if="error" :error-message="error"></error-alert>
+
+      <Peaks
+        v-if="sanitizedPeaks.length > 0"
+        :title="titleList"
+        :item-type="type"
+        :project-id="projectId"
+        :items="sanitizedPeaks"
+        :headers="headers"
+        :selected-item="selectedItem"
+      />
+      <v-card-actions
+        ><download-csv :data="exportPeak" :name="exportFileName">
+          <v-btn class="mx-2" color="secondary" small fab>
+            <v-icon>mdi-table-arrow-down</v-icon>
+          </v-btn>
+        </download-csv></v-card-actions
+      >
+    </v-card>
+    <nuxt-child />
+  </v-card>
+</template>
+<script>
+import JsonCSV from 'vue-json-csv'
+import ErrorAlert from '@/components/ErrorAlert'
+import Peaks from '~/components/DataTableActions.vue'
+
+export default {
+  components: {
+    Peaks,
+    ErrorAlert,
+    downloadCsv: JsonCSV,
+  },
+
+  async asyncData({ $axios, params, $auth, route }) {
+    const { id: projectId, analysisId } = params
+    let peaks = []
+    let error = null
+    try {
+      peaks = await $axios.$get(
+        `/api/projects/${projectId}/analysis/${analysisId}/peaks/`
+      )
+    } catch (e) {
+      if (e?.response?.data) {
+        error = e.response.data
+      } else {
+        error = e.message
+      }
+    }
+    return {
+      error,
+      peaks,
+      projectId: parseInt(route.params.id),
+      analysisId: parseInt(route.params.analysisId),
+    }
+  },
+  data() {
+    return {
+      error: null,
+      peaks: null,
+      type: 'peak',
+      projectId: null,
+      titleList: 'Significant peaks',
+      headers: [
+        { text: 'Id', align: 'start', value: 'id' },
+        {
+          text: 'Variable Name',
+
+          value: 'name',
+        },
+        { text: 'Chromosome', value: 'chromosome' },
+        { text: 'Position', value: 'position' },
+        { text: 'Lod Score', value: 'lod' },
+        { text: 'Lower bound', value: 'ci_lo' },
+        { text: 'Upper bound', value: 'ci_hi' },
+        { text: 'p-value', value: 'p_value' },
+      ],
+    }
+  },
+  computed: {
+    sanitizedPeaks() {
+      return this.peaks.map((peak) => ({
+        ...peak,
+        name: peak.variable_name,
+        itemRoute: this.getItemRoute(peak),
+      }))
+    },
+    exportPeak() {
+      return this.peaks.map(
+        // eslint-disable-next-line camelcase
+        ({ ci_hi, ci_lo, lod, p_value, position, variable_name }) => ({
+          ci_hi,
+          ci_lo,
+          lod,
+          p_value,
+          position,
+          variable_name,
+        })
+      )
+    },
+    selectedItem() {
+      return parseInt(this.$route.params?.peakId)
+    },
+    exportFileName() {
+      return `${this.projectId}-${this.analysisId}-significant-peaks.csv`
+    },
+  },
+  methods: {
+    getItemRoute({ id: peakId }) {
+      const routeName =
+        'projects-id-analysis-analysisId-results-peaks-peakId-coefficients'
+      return {
+        name: routeName,
+        params: { id: this.projectId, analysisId: this.analysisId, peakId },
+      }
+    },
+  },
+}
+</script>
diff --git a/client-nuxt/pages/projects/_id/analysis/add.vue b/client-nuxt/pages/projects/_id/analysis/add.vue
index 41e5bbc42bf4586f1f32a5ff6431feec9f9e90fa..81fcfea10ab2c19dc490fda7678a7eca7766b88e 100644
--- a/client-nuxt/pages/projects/_id/analysis/add.vue
+++ b/client-nuxt/pages/projects/_id/analysis/add.vue
@@ -1,66 +1,60 @@
 <template>
-  <v-card class="my-4">
-    <error-alert v-if="error" :error-message="error"></error-alert>
-
-    <v-card-title>Run Analysis</v-card-title>
-    <v-card-text>
-      <RunAnalysisForm
-        :project-id="projectId"
-        :experiments="experiments"
-        :wf-params="wfParams"
-        :tools-inputs="toolsInputs"
-      />
-    </v-card-text>
+  <v-card color="transparent">
+    <v-toolbar flat>
+      <v-btn class="mr-3" nuxt text x-small @click="goToAnalysisListRoute()">
+        <v-icon left>mdi-arrow-left</v-icon>Analysis</v-btn
+      >
+      <v-divider inset vertical></v-divider>
+      <v-toolbar-title class="text-uppercase ml-5 text-h5">
+        Run Analysis</v-toolbar-title
+      >
+    </v-toolbar>
+    <RunAnalysisForm
+      :workflows="workflows"
+      :experiments="sanitizedExperiments"
+      :project-id="projectId"
+      @update-analysis="$emit('update-analysis')"
+    />
   </v-card>
 </template>
 
 <script>
-import ErrorAlert from '@/components/ErrorAlert'
 import RunAnalysisForm from '~/components/RunAnalysisForm.vue'
 
 export default {
-  components: { RunAnalysisForm, ErrorAlert },
+  components: {
+    RunAnalysisForm,
+  },
   async asyncData({ params, $axios, route }) {
-    try {
-      const experiments = await $axios.$get(
-        `/api/projects/${route.params.id}/experiments`
-      )
-      const expWithVarTypes = experiments.map(async (exp) => {
-        const variables = await $axios.$get(
-          `/api/projects/${route.params.id}/experiments/${exp.id}/variable_types/`
-        )
-        return {
-          ...exp,
-          variables,
-          creation_date: new Date(exp.creation_date).toDateString(),
-        }
-      })
-      const workflowTools = await $axios.$get('/api/workflow-tools')
-      const wfParams = await $axios.$get('/api/workflow-default-parameters')
+    const experiments = await $axios.$get(
+      `/api/projects/${route.params.id}/experiments`
+    )
+    const workflows = await $axios.$get('/api/cc-qtl-workflows/')
 
-      const toolsInputs = Object.keys(workflowTools)
-        .filter((stepId) => stepId !== 'null')
-        .map((stepId) => {
-          workflowTools[stepId].stepId = stepId
-          return workflowTools[stepId]
-        })
-      return {
-        experiments: await Promise.all(expWithVarTypes),
-        toolsInputs,
-        wfParams: Object.keys(wfParams).reduce((acc, stepId) => {
-          if (Object.keys(wfParams[stepId]).length > 0) {
-            acc[stepId] = { ...wfParams[stepId] }
-          }
-          return acc
-        }, {}),
-        projectId: parseInt(params.id),
-      }
-    } catch (error) {
-      return { error: error.message }
+    return {
+      experiments,
+      projectId: parseInt(params.id),
+      workflows,
     }
   },
-  data() {
-    return { error: null }
+  computed: {
+    sanitizedExperiments() {
+      return this.experiments.map((experiment) => ({
+        ...experiment,
+        creation_date: new Date(experiment.creation_date).toDateString(),
+      }))
+    },
+  },
+  methods: {
+    analysisListRoute() {
+      return {
+        name: 'projects-id-analysis',
+        params: { id: this.projectId },
+      }
+    },
+    goToAnalysisListRoute() {
+      this.$router.push(this.analysisListRoute())
+    },
   },
 }
 </script>
diff --git a/client-nuxt/pages/projects/_id/analysis/index.vue b/client-nuxt/pages/projects/_id/analysis/index.vue
index d659280dbc8e76f1b85204f69e61d6e3625e46e3..b6bfef480775388f22345d527efef892436b2a5d 100644
--- a/client-nuxt/pages/projects/_id/analysis/index.vue
+++ b/client-nuxt/pages/projects/_id/analysis/index.vue
@@ -1,114 +1,146 @@
 <template>
-  <div>
-    <v-card flat>
+  <v-card flat color="transparent" class="my-10">
+    <v-card :id="`projects-${$route.params.id}-analysis`">
       <error-alert v-if="error" :error-message="error"></error-alert>
-
-      <Analysis
+      <data-table-actions
+        :item-type="itemType"
         :title="analysisListTitle"
-        :type="type"
-        :project-id="parseInt($route.params.id)"
-        :items="analysis"
-        :keys="analysisKeys"
-        :items-per-page-array="itemsPerPageArray"
-        :items-per-page="itemsPerPage"
+        :items="sanitizedAnalysis"
+        :headers="headers"
         :add-route="addAnalysisRoute"
-        :can-delete="true"
-        @show-detail="viewAnalysisDetail"
+        :selected-item="selectedItem"
+        :loading="$fetchState.pending"
         @delete="deleteAnalysis"
-      />
+      ></data-table-actions>
+      <ProgressBar :waiting="waiting" message="Deleting Analysis" />
     </v-card>
-    <ProgressBar :waiting="waiting" message="Deleting Analysis" />
-
-    <nuxt-child />
-  </div>
+  </v-card>
 </template>
 <script>
+import { mapActions } from 'vuex'
 import ProgressBar from '@/components/ProgressBar'
 import ErrorAlert from '@/components/ErrorAlert'
-import Analysis from '~/components/GenericDataIterator'
+import DataTableActions from '~/components/DataTableActions.vue'
 
 export default {
   components: {
-    Analysis,
     ErrorAlert,
     ProgressBar,
+    DataTableActions,
+  },
+  loading: {
+    continuous: true,
   },
   async fetch() {
     try {
-      const analysis = await this.$axios.$get(
-        `/api/projects/${this.$route.params.id}/analysis`
+      this.analysis = await this.$axios.$get(
+        `/api/projects/${this.$route.params.id}/analysis/`
       )
-      this.analysis = analysis.map((a) => ({
-        ...a,
-        creation_date: new Date(a.creation_date).toDateString(),
-      }))
     } catch (error) {
-      return { error: error.message }
+      if (error.response.status === 403) {
+        return []
+      } else {
+        throw error
+      }
     }
   },
   async asyncData({ params, $axios }) {
-    try {
-      const analysis = await $axios.$get(`/api/projects/${params.id}/analysis`)
-      return {
-        analysis: analysis.map((a) => ({
-          ...a,
-          creation_date: new Date(a.creation_date).toDateString(),
-        })),
-      }
-    } catch (error) {
-      return { error: error.message }
+    return {
+      permissions: await $axios.$get(
+        `/api/projects/${params.id}/analysis/permissions/`
+      ),
     }
   },
   data() {
     return {
-      type: 'analysis',
+      itemType: 'analysis',
+      search: '',
       waiting: false,
       analysis: [],
       error: null,
-      analysisKeys: [
-        'Id',
-        'Name',
-        'galaxy_history_id',
-        'galaxy_workflow_id',
-        'galaxy_workflow_invocation_id',
-        'creation_date',
-      ],
       analysisListTitle: 'Analysis',
       itemsPerPageArray: [9, 15, 24],
       itemsPerPage: 9,
+      headers: [
+        {
+          text: 'Name',
+          align: 'start',
+          value: 'name',
+        },
+        { text: 'Description', value: 'description' },
+        { text: 'Galaxy History', value: 'galaxy_history_id' },
+        { text: 'Galaxy Workflow', value: 'galaxy_workflow_id' },
+        { text: 'Creation Date', value: 'creation_date' },
+        {
+          text: 'Galaxy history state',
+          value: 'history_status',
+          sortable: false,
+        },
+        { text: 'Galaxy workflow State', value: 'workflow_invocation_status' },
+        { text: 'Actionw', value: 'actions', sortable: false },
+      ],
     }
   },
   computed: {
+    permissionsSet() {
+      return new Set(this.permissions)
+    },
     addAnalysisRoute() {
-      return {
-        name: 'projects-id-analysis-add',
-        params: this.$route.params,
+      if (this.permissionsSet.has('add')) {
+        return {
+          name: 'projects-id-analysis-add',
+          params: this.$route.params,
+        }
+      } else {
+        return null
       }
     },
+    sanitizedAnalysis() {
+      return this.analysis.map((a) => ({
+        ...a,
+        creation_date: new Date(a.creation_date),
+        itemRoute: this.getItemRoute(a),
+      }))
+    },
+    selectedItem() {
+      return parseInt(this.$route.params?.analysisId)
+    },
+  },
+  mounted() {
+    this.$fetch()
   },
+
   methods: {
-    viewAnalysisDetail(analysisId) {
-      this.$router.push({
+    getItemRoute({ id: analysisId }) {
+      return {
         name: 'projects-id-analysis-analysisId',
         params: {
           id: this.$route.params.id,
           analysisId,
         },
-      })
+        // hash: `#projects-${this.$route.params.id}-analysis-${analysisId}`,
+      }
     },
     async deleteAnalysis(analysisId) {
+      this.waiting = true
       try {
-        this.dialog = false
-        this.waiting = true
+        const params = this.$route.params
         await this.$axios.$delete(
-          `/api/projects/${this.$route.params.id}/analysis/${analysisId}`
+          `/api/projects/${params.id}/analysis/${analysisId}`
         )
-        this.waiting = false
         this.$fetch()
+        this.updateAnalysisCount()
+        this.$emit('update-analysis')
       } catch (error) {
         this.error = `Could not delete the analysis: ${error.message}`
+      } finally {
+        this.dialog = false
+        this.waiting = false
       }
     },
+    ...mapActions({
+      updateAnalysisCount: 'updateAnalysisCount',
+    }),
   },
 }
 </script>
diff --git a/client-nuxt/pages/projects/_id/experiments.vue b/client-nuxt/pages/projects/_id/experiments.vue
new file mode 100644
index 0000000000000000000000000000000000000000..71553b2860264bdfa31fb8bbe3f3fe5f88e9ed83
--- /dev/null
+++ b/client-nuxt/pages/projects/_id/experiments.vue
@@ -0,0 +1,15 @@
+<template>
+  <v-card flat color="transparent" class="my-10">
+    <nuxt-child
+      :project="project"
+      @update-experiments="$emit('update-experiments')"
+    />
+  </v-card>
+</template>
+<script>
+export default {
+  props: {
+    project: { type: Object, default: () => ({}) },
+  },
+}
+</script>
diff --git a/client-nuxt/pages/projects/_id/experiments/_experimentId.vue b/client-nuxt/pages/projects/_id/experiments/_experimentId.vue
index 8e901f45e3713fa51639a992380886002d7e0ffd..8a45c4362c8db8796332d02e413bb0c0df74e5bd 100644
--- a/client-nuxt/pages/projects/_id/experiments/_experimentId.vue
+++ b/client-nuxt/pages/projects/_id/experiments/_experimentId.vue
@@ -1,127 +1,572 @@
 <template>
   <v-card>
     <error-alert v-if="error" :error-message="error"></error-alert>
-    <v-toolbar flat>
-      <v-toolbar-title
-        >{{ experiment.name }}
-        <v-chip class="ma-2" color="primary">
-          {{ experiment.creation_date.toDateString() }}
+    <v-skeleton-loader
+      v-if="$fetchState.pending"
+      elevation="2"
+      type="card-heading, list-item-avatar-two-line@3, article, table-heading, table-thead, table-tfoot"
+    ></v-skeleton-loader>
+    <v-card v-else flat class="mt-3">
+      <v-toolbar v-if="sanitizedExperiment" flat>
+        <v-btn
+          nuxt
+          x-small
+          text
+          class="mr-3"
+          @click="goToExperimentsListRoute()"
+          ><v-icon left>mdi-arrow-left</v-icon> Experiments</v-btn
+        >
+        <v-divider vertical inset></v-divider>
+        <v-toolbar-title class="text-uppercase ml-3">
+          <v-btn text class="text-h5" @click="goToExperiment()">
+            <v-icon left>mdi-flask</v-icon>
+            {{ sanitizedExperiment.name }}</v-btn
+          >
+        </v-toolbar-title>
+        <v-spacer></v-spacer>
+
+        <v-spacer></v-spacer>
+        <v-chip class="ma-2" color="secondary" small>
+          {{ sanitizedExperiment.creation_date.toDateString() }}
         </v-chip>
-      </v-toolbar-title>
-    </v-toolbar>
-    <v-card-text> {{ experiment.description }}</v-card-text>
-    <v-card-text>
-      <v-data-table
-        dense
-        fixed-header
-        height="34rem"
-        :headers="getHeader"
-        :items="variables"
-        :items-per-page="15"
-        :search="search"
-        :sort-by="['mouseId']"
-        :sort-desc="[false]"
-        :footer-props="dataTableFooterProps"
-        multi-sort
-        item-key="mouseId"
-        ><template v-slot:top>
-          <v-toolbar flat dense>
-            <v-toolbar-title>experiment data</v-toolbar-title>
+        <v-chip small color="accent">Experiment</v-chip>
+      </v-toolbar>
+      <v-card-text v-if="sanitizedExperiment">
+        <v-card flat>
+          <v-toolbar dense flat
+            ><v-toolbar-title>Description</v-toolbar-title>
+          </v-toolbar>
+          <v-card-text>
+            {{ sanitizedExperiment.description }}
+          </v-card-text>
+        </v-card>
+      </v-card-text>
+
+      <v-card-text>
+        <v-card flat outlined>
+          <v-data-table
+            dense
+            height="34rem"
+            :headers="header"
+            :items="sanitizedPhenotypes"
+            :items-per-page="15"
+            :search="search"
+            :sort-by="['ccline_id']"
+            :sort-desc="[false]"
+            :footer-props="dataTableFooterProps"
+            multi-sort
+            item-key="ccline_id"
+          >
+            <template v-slot:top>
+              <v-toolbar flat class="mb-3">
+                <v-toolbar-title>Mice</v-toolbar-title>
+                <v-divider class="mx-4" inset vertical></v-divider>
+                <v-text-field
+                  v-model="search"
+                  append-icon="mdi-magnify"
+                  label="Search"
+                  single-line
+                  hide-details
+                ></v-text-field>
+                <v-spacer></v-spacer>
+                <download-csv
+                  :data="sanitizedPhenotypes"
+                  :name="exportFilename"
+                  :labels="labelsExport"
+                  :fields="fieldsToExport"
+                >
+                  <v-fab-transition>
+                    <v-btn
+                      class="mx-2"
+                      color="secondary"
+                      small
+                      elevation="5"
+                      fab
+                    >
+                      <v-icon>mdi-table-arrow-down</v-icon>
+                    </v-btn>
+                  </v-fab-transition>
+                </download-csv></v-toolbar
+              ></template
+            >
+          </v-data-table>
+        </v-card>
+      </v-card-text>
+      <v-card-text>
+        <v-card flat class="my-2" outlined>
+          <v-toolbar flat class="mb-3">
+            <v-toolbar-title>Plot phenotype data</v-toolbar-title>
+
             <v-divider class="mx-4" inset vertical></v-divider>
-            <v-text-field
-              v-model="search"
-              append-icon="mdi-magnify"
-              label="Search"
-              single-line
+            <v-spacer></v-spacer>
+            <v-select
+              v-model="selectedPhenotype"
+              dense
               hide-details
-            ></v-text-field></v-toolbar
-        ></template>
-      </v-data-table>
-    </v-card-text>
+              outlined
+              :items="numberPhenotypeNames"
+              label="Select phenotype"
+            ></v-select>
+            <v-spacer></v-spacer><v-chip small color="accent">Plot</v-chip>
+          </v-toolbar>
+          <v-card-title
+            >Raw Phenotype
+            <v-dialog :max-width="1000">
+              <template v-slot:activator="{ on, attrs }"
+                ><v-btn icon color="primary" v-bind="attrs" v-on="on"
+                  ><v-icon>mdi-help-circle</v-icon></v-btn
+                >
+              </template>
+              <template v-slot:default="dialog">
+                <v-card>
+                  <v-toolbar flat class="mb-2">
+                    <v-toolbar-title>
+                      Phenotype values distribution
+                    </v-toolbar-title>
+                    <v-spacer></v-spacer
+                    ><v-toolbar-items>
+                      <v-btn color="primary" text @click="dialog.value = false">
+                        Close
+                      </v-btn>
+                    </v-toolbar-items></v-toolbar
+                  ><v-card-text>
+                    To satisfy the statistics hypotheses underlying QTL mapping,
+                    phenotypic data must be pseudo-gaussian. It is advised that
+                    before running cc-qtl analysis, you check if the
+                    distribution grossly satisfies a gaussian. If it is not the
+                    case, several mathematicals transformations of your data can
+                    be considered.</v-card-text
+                  ></v-card
+                ></template
+              >
+            </v-dialog></v-card-title
+          >
+          <v-card-text>
+            <phenotype-distribution
+              :phenotype="rawPhenotype"
+              :phenotype-name="selectedPhenotype"
+            ></phenotype-distribution>
+          </v-card-text>
+          <v-card-title
+            >Transformed Phenotype
+            <v-dialog :max-width="1000">
+              <template v-slot:activator="{ on, attrs }"
+                ><v-btn icon color="primary" v-bind="attrs" v-on="on"
+                  ><v-icon>mdi-help-circle</v-icon></v-btn
+                >
+              </template>
+              <template v-slot:default="dialog">
+                <v-card>
+                  <v-toolbar flat class="mb-2">
+                    <v-toolbar-title>
+                      Phenotype values transformation
+                    </v-toolbar-title>
+                    <v-spacer></v-spacer
+                    ><v-toolbar-items>
+                      <v-btn color="primary" text @click="dialog.value = false">
+                        Close
+                      </v-btn>
+                    </v-toolbar-items></v-toolbar
+                  ><v-card-text>
+                    What type of transformation given the data ?
+                    <ul>
+                      <li v-for="item in transformationHelp" :key="item.type">
+                        {{ item.text }} :
+                        <span class="font-weight-bold">{{ item.type }}</span>
+                      </li>
+                    </ul>
+                  </v-card-text>
+                  <v-toolbar flat>
+                    <v-toolbar-title
+                      >generic reminder : pig shape transformation
+                    </v-toolbar-title></v-toolbar
+                  >
+
+                  <v-card-text>
+                    <v-card flat :outlined="imgLoading === false">
+                      <v-skeleton-loader
+                        v-if="imgLoading"
+                        class="mx-auto"
+                        max-width="300px"
+                        :loading="imgLoading"
+                        type="card"
+                      ></v-skeleton-loader>
+                      <v-img
+                        contain
+                        width="100%"
+                        src="https://www.davidzeleny.net/anadat-r/lib/exe/fetch.php/obrazky:trans.pig.png"
+                        @load="imgLoading = false"
+                        @loadstart="imgLoading = true"
+                      ></v-img>
+                      <v-card-subtitle
+                        >(https://www.davidzeleny.net/anadat-r/lib/exe/fetch.php/obrazky:trans.pig.png)</v-card-subtitle
+                      ></v-card
+                    ></v-card-text
+                  ></v-card
+                ></template
+              >
+            </v-dialog></v-card-title
+          >
+          <v-card-text>
+            <phenotype-distribution
+              :phenotype="rawPhenotype"
+              :phenotype-name="selectedPhenotype"
+              :phenotype-transform-types="phenotypeTransformTypes"
+            ></phenotype-distribution>
+          </v-card-text>
+          <v-card-text class="mt-4">
+            <phenotype-bar-plot
+              :phenotype-name="selectedPhenotype"
+              :grouped-phenotypes="phenotypeMeanPerGenotype"
+            ></phenotype-bar-plot>
+          </v-card-text>
+          <v-card-text>
+            <phenotype-box-plot
+              :phenotype-name="selectedPhenotype"
+              :phenotype-per-genotype="rawPhenotypeGroupedPerGenotype"
+            ></phenotype-box-plot>
+          </v-card-text>
+        </v-card>
+      </v-card-text>
+      <v-card v-if="sanitizedExperiment.analysis_set" flat>
+        <v-card-text>
+          <v-card outlined>
+            <generic-table
+              :items="sanitizedExperiment.analysis_set"
+              :headers="analysisHeaders"
+              title="Linked analysis"
+              :footer-props="analysisFooterProps"
+              :items-per-page="10"
+              @go-to-item="goToAnalysis"
+            ></generic-table>
+          </v-card>
+        </v-card-text>
+      </v-card>
+    </v-card>
   </v-card>
 </template>
 <script>
+import * as d3Array from 'd3-array'
+import JsonCSV from 'vue-json-csv'
+
 import ErrorAlert from '@/components/ErrorAlert'
+import GenericTable from '@/components/GenericTable.vue'
+import PhenotypeDistribution from '@/components/charts/PhenotypeDistribution'
+import PhenotypeBarPlot from '@/components/charts/PhenotypeBarPlot'
+import PhenotypeBoxPlot from '@/components/charts/PhenotypeBoxPlot.vue'
+
 import { group } from 'd3-array'
-export default {
-  components: { ErrorAlert },
 
-  async asyncData({ params, $axios, route }) {
-    const { id: projectId, experimentId } = params
+export default {
+  components: {
+    ErrorAlert,
+    GenericTable,
+    PhenotypeDistribution,
+    PhenotypeBarPlot,
+    downloadCsv: JsonCSV,
+    PhenotypeBoxPlot,
+  },
+  props: {
+    project: { type: Object, default: () => ({}) },
+  },
+  async fetch() {
+    const { id: projectId, experimentId } = this.$route.params
     try {
-      const experiment = await $axios.$get(
-        `/api/projects/${projectId}/experiments/${experimentId}`
+      this.experiment = await this.$axios.$get(
+        `/api/projects/${projectId}/experiments/${experimentId}/`
       )
-      const rawVariables = await $axios.$get(
-        `/api/projects/${projectId}/experiments/${experimentId}/variables/`
+      this.rawPhenotypes = await this.$axios.$get(
+        `/api/projects/${projectId}/experiments/${experimentId}/phenotypes/`
       )
 
-      const unwrap = ({
-        ccline_id: mouseId,
-        ccline_f_id: cclineFId,
-        ccline_m_id: cclineMId,
-        ccline_sex: cclineSex,
-        id_cc_f: idCcF,
-        id_cc_m: idCcM,
-      }) => ({
-        mouseId,
-        cclineFId,
-        cclineMId,
-        cclineSex,
-        idCcF,
-        idCcM,
-      })
-
-      // group variables on the ccline_id
-      const variablesMaps = group(rawVariables, (d) => d.ccline_id)
-
-      const variables = Array.from(variablesMaps).map((d) => {
-        const experimentCcline = unwrap(d[1][0])
-        for (const v of d[1]) {
-          experimentCcline[v.variable_type] = v.value
-        }
-        return experimentCcline
-      })
-
-      return {
-        variables,
-        experiment: {
-          ...experiment,
-          creation_date: new Date(experiment.creation_date),
-        },
-      }
+      this.error =
+        !this.rawPhenotypes && this.rawPhenotypes.length === 0
+          ? 'No phenotype found for this experiment.'
+          : null
     } catch (error) {
-      return { error: error.message }
+      this.error = error
     }
   },
   data() {
     return {
+      imgLoading: false,
       error: null,
+      selectedPhenotype: null,
       search: '',
+      analysisSearch: '',
       experiment: null,
-      variables: [],
-      headersValueToLabel: new Map([
-        ['mouseId', 'Mouse Id'],
-        ['idCcF', 'CC Mother'],
-        ['idCcM', 'CC Father'],
-        ['cclineSex', 'Sex'],
-      ]),
-      columnsToFilter: new Set(['cclineFId', 'cclineMId']),
+      rawPhenotypes: null,
+      phenotypes: [],
+      labelsExport: {
+        ccline_id: 'Individual_ID',
+        id_cc_f: 'Mother_Line',
+        id_cc_m: 'Father_Line',
+        ccline_sex: 'Sex',
+      },
+      labelsHeader: {
+        ccline_id: 'Individual ID',
+        id_cc_f: 'Mother Line',
+        id_cc_m: 'Father Line',
+        ccline_sex: 'Sex',
+      },
+      // fields: ['ccline_id', 'id_cc_f', 'id_cc_m', 'ccline_sex'],
+      analysisHeaders: [
+        { text: 'Id', value: 'id' },
+        { text: 'Name', value: 'name' },
+        { text: 'Creation Date', value: 'creation_date' },
+        { text: 'Status', value: 'history_status' },
+      ],
+      analysisFooterProps: { 'items-per-page-options': [10, 20, 30, -1] },
+      columnsToFilter: new Set(['ccline_f_id', 'ccline_m_id']),
       dataTableFooterProps: { 'items-per-page-options': [15, 25, 35, -1] },
+      phenotypeTransformTypes: [
+        // { label: 'None', value: 'identity', fn: (d) => d },
+        {
+          label: 'Log',
+          value: 'log',
+          fn: (d) => ({ ...d, y: Math.log(d.y) }),
+          help: { text: 'Strongly right-skewed' },
+        },
+        {
+          label: 'Log10',
+          value: 'log10',
+          fn: (d) => ({ ...d, y: Math.log10(d.y) }),
+        },
+        {
+          label: 'Square root',
+          value: 'square_root',
+          fn: (d) => ({ ...d, y: Math.sqrt(d.y) }),
+          help: { text: 'Slitghly right-skewed' },
+        },
+        {
+          label: 'Inverse',
+          value: 'inverse',
+          fn: (d) => ({ ...d, y: 1.0 / d.y }),
+        },
+        {
+          label: 'Power',
+          value: 'power',
+          fn: (d) => ({ ...d, y: Math.pow(d.y, 2) }),
+          help: { text: 'left-skewed' },
+        },
+      ],
     }
   },
   computed: {
-    getHeader() {
-      return Object.keys(this.variables[0])
-        .filter((d) => !this.columnsToFilter.has(d))
-        .map((d) => {
+    groupedPhenotypes() {
+      if (this.rawPhenotypes) {
+        return group(this.rawPhenotypes, (d) => d.ccline_id)
+      } else {
+        return []
+      }
+    },
+    header() {
+      const commonHeader = Object.entries(this.labelsHeader).map((d) => ({
+        text: d[1],
+        value: d[0],
+      }))
+      if (this.groupedPhenotypes && this.groupedPhenotypes.size > 0) {
+        const firstEntry = Array.from(this.groupedPhenotypes)[0]
+        return [
+          ...commonHeader,
+          ...firstEntry[1]
+            // eslint-disable-next-line camelcase
+            .map(({ phenotype_type, dataclass, datatype }) => ({
+              value: phenotype_type,
+              text: phenotype_type,
+              dataclass,
+              datatype,
+              class:
+                dataclass === 'Phenotype'
+                  ? this.$vuetify.theme.dark
+                    ? 'indigo darken-4'
+                    : 'indigo lighten-4'
+                  : this.$vuetify.theme.dark
+                  ? 'teal darken-4'
+                  : 'teal lighten-4',
+            }))
+            .sort((a, b) => {
+              return b.dataclass.localeCompare(a.dataclass)
+            }),
+        ]
+      } else {
+        return commonHeader
+      }
+    },
+    exportFilename() {
+      return `phenotype-from-${this.project.project_name}-${this.experiment.name}.csv`
+    },
+    phenotypeNames() {
+      return this.header.filter((d) => d?.dataclass === 'Phenotype')
+    },
+    numberPhenotypeNames() {
+      return this.phenotypeNames.filter(({ datatype }) => {
+        return datatype === 'Float' || datatype === 'Integer'
+      })
+    },
+    covariateNames() {
+      return this.header.filter((d) => d?.dataclass === 'Covariate')
+    },
+    fieldsToExport() {
+      return this.header.map((d) => d.value)
+    },
+    sanitizedExperiment() {
+      if (this.experiment) {
+        return {
+          ...this.experiment,
+          creation_date: new Date(this.experiment.creation_date),
+          analysis_set: this.experiment.analysis_set.map((a) => ({
+            ...a,
+            creation_date: new Date(a.creation_date),
+          })),
+        }
+      } else {
+        return null
+      }
+    },
+
+    sanitizedPhenotypes() {
+      return Array.from(this.groupedPhenotypes).map((d) => {
+        const experimentCcline = this.unwrapPhenotypes(d[1][0])
+        for (const v of d[1]) {
+          experimentCcline[v.phenotype_type] = this.parseDatatype(
+            v.datatype,
+            v.value
+          )
+        }
+        return experimentCcline
+      })
+    },
+    sanitizedPhenotypesNoCovar() {
+      if (this.rawPhenotypes) {
+        const phenotypesMaps = group(
+          this.rawPhenotypes.filter((d) => d.dataclass === 'Phenotype'),
+          (d) => d.ccline_id
+        )
+        return Array.from(phenotypesMaps).map((d) => {
+          const experimentCcline = this.unwrapPhenotypes(d[1][0])
+          for (const v of d[1]) {
+            experimentCcline[v.phenotype_type] = this.parseDatatype(
+              v.datatype,
+              v.value
+            )
+          }
+          return experimentCcline
+        })
+      } else {
+        return []
+      }
+    },
+    rawPhenotype() {
+      if (this.selectedPhenotype) {
+        return this.sanitizedPhenotypesNoCovar.map((d) => {
+          // eslint-disable-next-line camelcase
+          const { ccline_id, id_cc_f, id_cc_m, ccline_sex } = d
           return {
-            text: this.headersValueToLabel.has(d)
-              ? this.headersValueToLabel.get(d)
-              : d,
-            value: d,
+            ccline_id,
+            id_cc_f,
+            id_cc_m,
+            ccline_sex,
+            y: d[this.selectedPhenotype],
           }
         })
+      } else {
+        return []
+      }
+    },
+    rawPhenotypeGroupedPerGenotype() {
+      return group(this.rawPhenotype, (d) => d.id_cc_f)
+    },
+
+    phenotypeMeanPerGenotype() {
+      return Array.from(this.rawPhenotypeGroupedPerGenotype.entries())
+        .map(([k, v]) => {
+          // return [k, d3Array.mean(v.map((d) => d.y))]
+          return {
+            name: k,
+            // x: k,
+            y: d3Array.mean(v.map((d) => d.y)),
+            count: v.length,
+          }
+        })
+        .sort((a, b) => a.y - b.y)
+      // .sort((a, b) => a[1] - b[1])
+    },
+    transformationHelp() {
+      return this.phenotypeTransformTypes
+        .filter((pt) => pt?.help)
+        .map((pt) => ({ type: pt.value, text: pt.help.text }))
+    },
+  },
+  mounted() {
+    this.$fetch()
+  },
+  beforeUpdate() {
+    if (this.numberPhenotypeNames && this.numberPhenotypeNames.length > 0) {
+      this.selectedPhenotype = this.numberPhenotypeNames[0].value
+    } else {
+      this.selectedPhenotype = null
+    }
+  },
+  methods: {
+    unwrapPhenotypes({
+      // eslint-disable-next-line camelcase
+      ccline_id,
+      // eslint-disable-next-line camelcase
+      ccline_f_id,
+      // eslint-disable-next-line camelcase
+      ccline_m_id,
+      // eslint-disable-next-line camelcase
+      ccline_sex,
+      // eslint-disable-next-line camelcase
+      id_cc_f,
+      // eslint-disable-next-line camelcase
+      id_cc_m,
+    }) {
+      return {
+        ccline_id,
+        ccline_f_id,
+        ccline_m_id,
+        ccline_sex,
+        id_cc_f,
+        id_cc_m,
+      }
+    },
+    parseDatatype(datatype, value) {
+      switch (datatype) {
+        case 'Float':
+          return parseFloat(value)
+        case 'Integer':
+          return parseInt(value)
+        default:
+          return value
+      }
+    },
+    getExperimentsListRoute() {
+      return {
+        name: 'projects-id-experiments',
+        params: {
+          id: this.$route.params.id,
+        },
+      }
+    },
+    goToExperimentsListRoute() {
+      this.$router.push(this.getExperimentsListRoute())
+    },
+    goToExperiment() {
+      this.$router.push({
+        name: 'projects-id-experiments-experimentId',
+        params: {
+          id: this.$route.params.id,
+          experimentId: this.$route.params.experimentId,
+        },
+      })
+    },
+    goToAnalysis({ id: analysisId }) {
+      this.$router.push({
+        name: 'projects-id-analysis-analysisId',
+        params: { id: this.$route.params.id, analysisId },
+      })
     },
   },
 }
diff --git a/client-nuxt/pages/projects/_id/experiments/add.vue b/client-nuxt/pages/projects/_id/experiments/add.vue
new file mode 100644
index 0000000000000000000000000000000000000000..cadf59d8c0273992b9c26cd4d5085d87fa8f95d2
--- /dev/null
+++ b/client-nuxt/pages/projects/_id/experiments/add.vue
@@ -0,0 +1,109 @@
+<template>
+  <v-card flat class="mt-3">
+    <v-toolbar flat dense>
+      <v-btn nuxt x-small text class="mr-3" @click="goToExperimentsListRoute()"
+        ><v-icon left>mdi-arrow-left</v-icon> Experiments</v-btn
+      >
+      <v-divider vertical inset></v-divider>
+      <v-toolbar-title class="text-uppercase ml-3 text-h5">
+        Upload an experiment
+      </v-toolbar-title></v-toolbar
+    >
+    <add-experiment-form
+      :project-id="parseInt($route.params.id)"
+      :phenotype-categories="phenotypeCategories"
+      :phenotype-category-permissions="permissions"
+      :phenotype-category-options="phenotypeCategoryOptions"
+      :experiment-name.sync="experimentToAdd.experiment.name"
+      :experiment-description.sync="experimentToAdd.experiment.description"
+      :experiment-file.sync="experimentToAdd.experiment.file"
+      :experiment-metadata.sync="experimentToAdd.experimentMetadata"
+      @update-experiments="$emit('update-experiments')"
+      @update-phenotype-categories="$fetch()"
+    >
+    </add-experiment-form>
+  </v-card>
+</template>
+<script>
+import { mapMutations } from 'vuex'
+
+import AddExperimentForm from '@/components/AddExperimentForm.vue'
+export default {
+  components: { AddExperimentForm },
+  async fetch() {
+    try {
+      this.phenotypeCategories = await this.$axios.$get(
+        `/api/phenotype-categories/`
+      )
+    } catch (error) {
+      return { error: error.message }
+    }
+  },
+  async asyncData({ $axios }) {
+    const phenotypeCategories = await $axios.$get('/api/phenotype-categories/')
+    const permissions = await $axios.$get(
+      '/api/phenotype-categories/permissions/'
+    )
+    const endpointOptions = await $axios.$options('/api/phenotype-categories/')
+    let phenotypeCategoryOptions = null
+    if (endpointOptions?.actions?.POST) {
+      phenotypeCategoryOptions = endpointOptions.actions.POST
+    }
+    return {
+      phenotypeCategories,
+      permissions: new Set(permissions),
+      phenotypeCategoryOptions,
+    }
+  },
+  data() {
+    return {
+      experimentToAdd: {
+        experiment: {
+          name: '',
+          description: '',
+          file: null,
+        },
+        experimentMetadata: [],
+      },
+    }
+  },
+  created() {
+    if (this.$store.getters.getExperimentToAdd(this.$route.params.id)) {
+      const experimentToAdd = this.$store.getters.getExperimentToAdd(
+        this.$route.params.id
+      )
+      // eslint-disable-next-line no-undef
+      this.experimentToAdd = structuredClone(experimentToAdd)
+    }
+  },
+
+  methods: {
+    getExperimentsListRoute() {
+      return {
+        name: 'projects-id-experiments',
+        params: {
+          id: this.$route.params.id,
+        },
+      }
+    },
+    goToExperimentsListRoute() {
+      this.$router.push(this.getExperimentsListRoute())
+    },
+    ...mapMutations({
+      updateExperiment: 'updateExperiment',
+      // updateFromAddExperiment: 'updateFromAddExperiment',
+    }),
+  },
+  beforeRouteLeave(to, from, next) {
+    this.updateExperiment({
+      experiment: this.experimentToAdd,
+      projectId: parseInt(this.$route.params.id),
+    })
+    // console.log(to)
+    // if (to.name === 'phenotype-categories') {
+    //   this.updateFromAddExperiment(true)
+    // }
+    next()
+  },
+}
+</script>
diff --git a/client-nuxt/pages/projects/_id/experiments/index.vue b/client-nuxt/pages/projects/_id/experiments/index.vue
index 1869374a0ab51dc29081ff1585714af521c41aff..cf373e9de02bd0858e93f5c8b0e5b58871de22c5 100644
--- a/client-nuxt/pages/projects/_id/experiments/index.vue
+++ b/client-nuxt/pages/projects/_id/experiments/index.vue
@@ -1,101 +1,104 @@
 <template>
-  <div>
-    <Experiments
-      :title="experimentListTitle"
-      :type="type"
-      :project-id="projectId"
-      :items="experiments"
-      :keys="experimentsKeys"
-      can-delete="true"
-      @show-detail="goToExperiment"
-      @delete="deleteExperiment"
-    />
-    <v-card class="my-4">
-      <v-card-title>Add experiment</v-card-title>
-      <v-card-text>
-        <AddExperimentForm
-          :project-id="projectId"
-          :variable-categories="variableCategories"
-        />
-      </v-card-text>
+  <v-card flat color="transparent" class="my-10">
+    <v-card :id="`projects-${$route.params.id}-experiments`">
+      <data-table-actions
+        :item-type="itemType"
+        :title="experimentListTitle"
+        :items="sanitizedExperiments"
+        :headers="headers"
+        :add-route="addExperimentRoute"
+        :selected-item="selectedItem"
+        @delete="deleteExperiment"
+      >
+      </data-table-actions>
     </v-card>
-  </div>
+  </v-card>
 </template>
 <script>
-import Experiments from '~/components/GenericDataIterator'
-import AddExperimentForm from '~/components/AddExperimentForm'
+import { mapActions } from 'vuex'
 
-function createDateForExperiment(item) {
-  return { ...item, creation_date: new Date(item.creation_date).toDateString() }
+import DataTableActions from '~/components/DataTableActions.vue'
+
+function fetchExperiments($axios, params) {
+  return $axios.$get(`/api/projects/${params.id}/experiments/`)
 }
 
 export default {
   components: {
-    Experiments,
-    AddExperimentForm,
-  },
-  async fetch() {
-    try {
-      const experiments = await this.$axios.$get(
-        `/api/projects/${this.$route.params.id}/experiments`
-      )
-      const variableCategories = await this.$axios.$get(
-        '/api/variable-categories/'
-      )
-      this.variableCategories = variableCategories
-      this.experiments = experiments.map(createDateForExperiment)
-    } catch (error) {
-      return { error: error.message }
-    }
+    DataTableActions,
   },
-  async asyncData({ params, $axios, route }) {
-    try {
-      const experiments = await $axios.$get(
-        `/api/projects/${route.params.id}/experiments`
-      )
-      const variableCategories = await $axios.$get('/api/variable-categories/')
-
-      return {
-        variableCategories,
-        experiments: experiments.map(createDateForExperiment),
-        projectId: parseInt(params.id),
-      }
-    } catch (error) {
-      return { error: error.message }
+  async asyncData({ params, $axios }) {
+    return {
+      experiments: await fetchExperiments($axios, params),
+      projectId: parseInt(params.id),
     }
   },
   data() {
     // console.log(this.route.params)
     return {
-      type: 'experiment',
+      itemType: 'experiment',
       error: null,
-      variableCategories: [],
       experiments: [],
-      experimentsKeys: ['Id', 'Name', 'Description', 'Creation_date'],
       experimentListTitle: 'Experiments',
+      headers: [
+        {
+          text: 'Name',
+          align: 'start',
+          value: 'name',
+        },
+        { text: 'Description', value: 'description' },
+        { text: 'Creation Date', value: 'creation_date' },
+        { text: 'Mouse Count', value: 'cclines' },
+        { text: 'Actions', value: 'actions', sortable: false },
+      ],
     }
   },
+  computed: {
+    sanitizedExperiments() {
+      return this.experiments.map((exp) => ({
+        ...exp,
+        creation_date: new Date(exp.creation_date),
+        itemRoute: this.getItemRoute(exp),
+      }))
+    },
+    addExperimentRoute() {
+      return {
+        name: 'projects-id-experiments-add',
+        params: this.$route.params,
+      }
+    },
+    selectedItem() {
+      return parseInt(this.$route.params?.experimentId)
+    },
+  },
   methods: {
-    goToExperiment(experimentId) {
-      this.$router.push({
+    getItemRoute({ id: experimentId }) {
+      return {
         name: 'projects-id-experiments-experimentId',
         params: {
           id: this.$route.params.id,
           experimentId,
         },
-      })
+      }
     },
     async deleteExperiment(experimentId) {
       try {
-        this.dialog = false
+        const params = this.$route.params
         await this.$axios.$delete(
-          `/api/projects/${this.$route.params.id}/experiments/${experimentId}`
+          `/api/projects/${params.id}/experiments/${experimentId}/`
         )
-        this.$fetch()
+        this.experiments = await fetchExperiments(this.$axios, params)
+        this.updateExperimentsCount()
+        this.$emit('update-experiments')
       } catch (error) {
         this.error = `Could not delete the experiment: ${error.message}`
+      } finally {
+        this.dialog = false
       }
     },
+    ...mapActions({
+      updateExperimentsCount: 'updateExperimentsCount',
+    }),
   },
 }
 </script>
diff --git a/client-nuxt/pages/projects/_id/index.vue b/client-nuxt/pages/projects/_id/index.vue
index c61c1a982b228798ea19af4197e044743272322e..1cec3582becc89e4a773f79659671f2d423f1d72 100644
--- a/client-nuxt/pages/projects/_id/index.vue
+++ b/client-nuxt/pages/projects/_id/index.vue
@@ -1,30 +1,3 @@
 <template>
-  <v-card>
-    <v-card-text>
-      <div class="text--primary">{{ project.description }}</div>
-    </v-card-text>
-  </v-card>
+  <v-card> </v-card>
 </template>
-
-<script>
-export default {
-  async asyncData({ $axios, params, route }) {
-    const rawProject = await $axios.$get(`/api/projects/${route.params.id}`)
-
-    return { rawProject }
-  },
-  data() {
-    return {
-      rawProject: null,
-    }
-  },
-  computed: {
-    project() {
-      return {
-        ...this.rawProject,
-        creation_date: new Date(this.rawProject.creation_date),
-      }
-    },
-  },
-}
-</script>
diff --git a/client-nuxt/pages/projects/_id/member.vue b/client-nuxt/pages/projects/_id/member.vue
index b3180e1514308e57e1cba07b087acf0fbf3700c9..d017c4b897d686767f5ceb2be9aa621bd5aa04bb 100644
--- a/client-nuxt/pages/projects/_id/member.vue
+++ b/client-nuxt/pages/projects/_id/member.vue
@@ -1,36 +1,26 @@
 <template>
-  <v-card flat>
+  <v-card flat color="transparent" class="my-10">
     <error-alert v-if="error" :error-message="error"></error-alert>
-
-    <v-card-text v-if="hasChangeProjectGroupPermission()">
-      <v-form ref="form" @submit.prevent="addMembers">
-        <v-row>
-          <v-col cols="12" sm="6">
-            <v-select
-              v-model="usersToAdd"
-              :items="users"
-              item-text="label"
-              item-value="id"
-              multiple
-              small
-              label="Select users"
-            ></v-select>
-          </v-col>
-          <v-col cols="12" sm="6">
-            <v-select
-              v-model="projectGroupSelected"
-              :items="projectGroups"
-              item-text="role"
-              item-value="id"
-              label="Project role"
-            ></v-select> </v-col
-        ></v-row>
-
-        <v-btn class="mr-4" type="submit"> submit </v-btn>
-      </v-form>
-    </v-card-text>
-    <v-card-text>
-      <v-data-table :headers="headers" :items="members" :items-per-page="5">
+    <v-card class="my-10">
+      <v-data-table
+        :headers="headers"
+        :items="members"
+        :items-per-page="10"
+        :search="search"
+      >
+        <template #top>
+          <v-toolbar dense flat>
+            <v-toolbar-title> Members </v-toolbar-title>
+            <v-divider class="mx-4" inset vertical></v-divider>
+            <v-text-field
+              v-model="search"
+              append-icon="mdi-magnify"
+              label="Search"
+              single-line
+              hide-details
+            ></v-text-field>
+          </v-toolbar>
+        </template>
         <template
           v-if="hasChangeProjectGroupPermission()"
           v-slot:[`item.actions`]="{ item }"
@@ -52,16 +42,91 @@
             hide-details
             @change="changeMemberRole($event, item)"
           ></v-select>
-        </template> </v-data-table></v-card-text
-  ></v-card>
+        </template>
+      </v-data-table>
+    </v-card>
+    <v-card
+      v-if="hasChangeProjectGroupPermission()"
+      :id="`projects-${$route.params.id}-member`"
+      class="my-10"
+    >
+      <v-toolbar dense flat>
+        <v-toolbar-title> Add Members </v-toolbar-title>
+      </v-toolbar>
+      <v-card-text>
+        <ValidationObserver ref="observer" v-slot="{ invalid }">
+          <v-form ref="form" v-model="valid" @submit.prevent="addMembers">
+            <v-row>
+              <v-col cols="12" sm="6">
+                <ValidationProvider
+                  v-slot="{ errors }"
+                  name="users"
+                  rules="required"
+                >
+                  <v-select
+                    v-model="usersToAdd"
+                    :items="users"
+                    item-text="label"
+                    item-value="id"
+                    multiple
+                    small
+                    chips
+                    label="Select users"
+                    :error-messages="errors"
+                  ></v-select>
+                </ValidationProvider>
+              </v-col>
+              <v-col cols="12" sm="6">
+                <ValidationProvider
+                  v-slot="{ errors }"
+                  name="role"
+                  rules="required"
+                >
+                  <v-select
+                    v-model="projectGroupSelected"
+                    :items="projectGroups"
+                    item-text="role"
+                    item-value="id"
+                    label="Project role"
+                    chips
+                    :error-messages="errors"
+                  ></v-select
+                ></ValidationProvider> </v-col
+            ></v-row>
+            <v-row>
+              <v-col cols="12">
+                <v-btn
+                  class="mr-4"
+                  type="submit"
+                  color="primary"
+                  :disabled="invalid"
+                >
+                  submit
+                </v-btn>
+              </v-col>
+            </v-row>
+          </v-form>
+        </ValidationObserver>
+      </v-card-text>
+    </v-card>
+  </v-card>
 </template>
 
 <script>
 import ErrorAlert from '@/components/ErrorAlert'
+import { required } from 'vee-validate/dist/rules'
+import { extend, ValidationObserver, ValidationProvider } from 'vee-validate'
+
+extend('required', {
+  ...required,
+  message: 'The {_field_} can not be empty',
+})
 
 export default {
   components: {
     ErrorAlert,
+    ValidationProvider,
+    ValidationObserver,
   },
   async fetch() {
     const { id: projectId } = this.$route.params
@@ -97,6 +162,8 @@ export default {
 
   data() {
     return {
+      valid: false,
+      search: '',
       usersToAdd: [],
       projectGroupSelected: null,
       currentMemberPermissions: new Set([]),
@@ -116,6 +183,7 @@ export default {
       error: null,
     }
   },
+
   computed: {
     members() {
       return this.rawMembers.map((member) => {
@@ -124,7 +192,9 @@ export default {
     },
     users() {
       return this.rawUsers
-        .filter((user) => user.username !== 'admin')
+        .filter(
+          (user) => user.username !== 'admin' && user.id !== this.$auth.user.id
+        )
         .map((user) => {
           return {
             label: `${user.first_name} ${user.last_name} (${user.username})`,
@@ -133,12 +203,15 @@ export default {
         })
     },
     projectGroups() {
-      return this.rawProjectGroups.map((group) => ({
-        role: group.project_role.name,
-        id: group.id,
-      }))
+      return this.rawProjectGroups
+        .map((group) => ({
+          role: group.project_role.name,
+          id: group.id,
+        }))
+        .filter((g) => g.role !== 'reader')
     },
   },
+
   methods: {
     hasChangeProjectGroupPermission() {
       return this.currentMemberPermissions.has('change_projectgroup')
@@ -173,8 +246,13 @@ export default {
           }
         )
         this.projectGroupSelected = null
-        this.userToAdd = []
+        this.usersToAdd = []
+        this.$nextTick(() => {
+          console.log(this)
+          this.$refs?.observer?.reset()
+        })
         this.$fetch()
+        this.$emit('project-updated')
       } catch (err) {
         this.error = err.message
       }
@@ -192,6 +270,7 @@ export default {
           }
         )
         this.$fetch()
+        this.$emit('project-updated')
       } catch (err) {
         this.error = err.message
       }
diff --git a/client-nuxt/pages/projects/add.vue b/client-nuxt/pages/projects/add.vue
index 0204dbb1c541bfaf995cb57378ce3ea97c4b340a..49f48b5afbd55c4408bb5ab6b36121cbe81fe3d0 100644
--- a/client-nuxt/pages/projects/add.vue
+++ b/client-nuxt/pages/projects/add.vue
@@ -2,7 +2,7 @@
   <v-card class="my-4">
     <v-card-title> Add a project</v-card-title>
     <v-card-text>
-      <AddProjectForm></AddProjectForm>
+      <AddProjectForm @cancel="goToProjects"></AddProjectForm>
     </v-card-text>
   </v-card>
 </template>
@@ -10,5 +10,10 @@
 import AddProjectForm from '@/components/AddProjectForm.vue'
 export default {
   components: { AddProjectForm },
+  methods: {
+    goToProjects() {
+      this.$router.push({ name: 'projects' })
+    },
+  },
 }
 </script>
diff --git a/client-nuxt/pages/projects/index.vue b/client-nuxt/pages/projects/index.vue
index c86b8713b061a2cbb9f9a2ed931cd65af534f409..60ad9d2f902333935c06c87dcf072390b4bee47f 100644
--- a/client-nuxt/pages/projects/index.vue
+++ b/client-nuxt/pages/projects/index.vue
@@ -1,152 +1,117 @@
 <template>
-  <div class="projects">
-    <error-alert v-if="error" :error-message="error"></error-alert>
-    <v-row justify="center">
-      <v-btn
-        class="mx-2 mt-2"
-        small
-        fab
-        dark
-        color="primary"
-        nuxt
-        :to="$nuxt.$route.path + '/add'"
-      >
-        <v-icon dark>mdi-plus</v-icon>
-      </v-btn>
-    </v-row>
-    <v-timeline align-top :dense="$vuetify.breakpoint.smAndDown">
-      <v-timeline-item
-        v-for="(project, i) in projectsTimeline"
-        :key="i"
-        color="primary"
-        fill-dot
-      >
-        <template v-slot:opposite>
-          <span
-            :class="`headline font-weight-bold`"
-            v-text="project.year"
-          ></span>
-        </template>
-        <v-card :color="project.role === 'manager' ? 'teal darken-4' : ''">
-          <v-card-title class="title text-uppercase font-weight-bold">{{
-            project.project_name
-          }}</v-card-title>
-          <v-card-text class="pt-4">
-            <div class="mb-3">{{ project.description }}</div>
-          </v-card-text>
-          <v-card-text>
-            <v-badge>
-              <template v-slot:badge>{{ project.membersCount }}</template>
-              <v-icon large color="primary">mdi-account-circle</v-icon>
-            </v-badge>
-          </v-card-text>
-          <v-card-actions>
-            <v-btn
-              color="primary"
-              class="mx-2"
-              :to="getProjectLocation(project.id)"
-              nuxt
-              ><v-icon>mdi-eye</v-icon></v-btn
-            >
-            <delete-dialog
-              v-if="canDeleteProject(project.id)"
-              type="project"
-              :name="project.project_name"
-              @delete="deleteProject(project)"
-            ></delete-dialog>
-          </v-card-actions>
-        </v-card>
-      </v-timeline-item>
-    </v-timeline>
-  </div>
+  <v-card flat color="transparent">
+    <v-card flat class="projects" color="transparent">
+      <error-alert v-if="error" :error-message="error"></error-alert>
+      <projects-data-iterator
+        :title="projectListTitle"
+        :type="type"
+        :items="sanitizedProjects"
+        :keys="projectKeys"
+        :items-per-page-array="itemsPerPageArray"
+        :items-per-page="itemsPerPage"
+        :can-delete="canDeleteProject"
+        :add-route="addProjectRoute"
+        item-name-key="project_name"
+        :key-to-filter="keyToFilter"
+        @show-detail="viewProjectDetail"
+        @delete="deleteProject"
+        @project-updated="fetchProjects"
+      />
+    </v-card>
+  </v-card>
 </template>
-
 <script>
-import DeleteDialog from '@/components/DeleteDialog.vue'
+import { mapActions } from 'vuex'
 import ErrorAlert from '@/components/ErrorAlert'
+import ProjectsDataIterator from '@/components/ProjectsDataIterator.vue'
 
 async function fetchProjects($axios, authUser) {
-  let projects = await $axios.$get('/api/projects/')
+  let projects = null
+  try {
+    projects = await $axios.$get('/api/projects/')
+  } catch (error) {
+    if (error.response.status === 403) {
+      return []
+    } else {
+      throw error
+    }
+  }
 
   // get some informations for each projects
   projects = await Promise.all(
     projects.map(async (project) => {
       // Get the members of this particular project
       const members = await $axios.$get(`/api/projects/${project.id}/members/`)
-      // Get the permissions the auth-user has on this project
-      const member = members.find((member) => member.id === authUser.id)
-      const role = member ? member.role.name : ''
       return {
         ...project,
-        role,
-        membersCount: members.length,
-        permissions: member ? member.permissions : [],
         members,
       }
     })
   )
-  return (
-    projects
-      // creation date to a date
-      .map((project) => {
-        return {
-          ...project,
-          creation_date: new Date(project.creation_date),
-        }
-      })
-      // sort by date
-      .sort((a, b) => b.creation_date.getTime() - a.creation_date.getTime())
-  )
+  return projects
 }
 
 export default {
   // define components
-  components: { DeleteDialog, ErrorAlert },
+  components: {
+    ErrorAlert,
+    ProjectsDataIterator,
+  },
+
   // load data
   async asyncData({ params, $axios, $auth }) {
-    try {
-      const authUser = await $axios.$get(`/api/users/${$auth.user}`)
-      return {
-        projects: await fetchProjects($axios, authUser),
-        authUser,
-      }
-    } catch (error) {
-      return { error: error.message }
+    return {
+      projects: await fetchProjects($axios, $auth.user),
     }
   },
 
   data() {
     return {
+      type: 'project',
       error: null,
       projectToDelete: {},
       title: 'Projects Timeline',
-      projects: [],
-      authUser: null,
+      projectKeys: ['Id', 'description', 'project_name', 'creation_date'],
+      keyToFilter: ['project_name'],
+      projectListTitle: 'Projects',
+      itemsPerPageArray: [9, 15, 24],
+      itemsPerPage: 9,
     }
   },
   computed: {
-    projectsTimeline() {
-      return this.projects.map((proj, i) => ({
-        ...proj,
-        textRight: i % 2 === 0,
-        year: proj.creation_date.toDateString(),
-      }))
+    sanitizedProjects() {
+      return this.projects.map((proj) => {
+        const member = proj.members.find(
+          (member) => member.id === this.$auth.user.id
+        )
+
+        return {
+          ...proj,
+          creation_date: new Date(proj.creation_date),
+          membersCount: proj.members.length,
+          role: member ? member.role.name : null,
+          permissions: member ? new Set(member.permissions) : new Set(),
+        }
+      })
     },
-    projectsObject() {
-      return this.projects.reduce((acc, item) => {
-        acc[item.id] = item
-        return acc
-      }, {})
+    addProjectRoute() {
+      return {
+        name: 'projects-add',
+        params: {},
+      }
     },
   },
   methods: {
-    async deleteProject(projectToDelete) {
+    async deleteProject(projectId) {
       try {
-        this.dialog = false
-        await this.$axios.$delete(`/api/projects/${projectToDelete.id}`)
-        this.projects = await fetchProjects(this.$axios, this.authUser)
+        await this.$axios.$delete(`/api/projects/${projectId}`)
+        this.projects = await fetchProjects(this.$axios, this.$auth.user)
+        this.$router.push({ name: 'projects' })
+        this.updateProjectsCount()
       } catch (error) {
         this.error = `Could not delete the project: ${error.message}`
+      } finally {
+        this.dialog = false
       }
     },
     getProjectLocation(id) {
@@ -155,19 +120,30 @@ export default {
         params: { id },
       }
     },
-    canDeleteProject(projectId) {
-      const project = this.projectsObject[projectId]
-      const canDeleteProjectPerm = 'delete_project'
-      return project.permissions.some((perm) => {
-        return perm === canDeleteProjectPerm
+    viewProjectDetail(id) {
+      this.$router.push({
+        name: 'projects-id',
+        params: { id },
       })
     },
-    toGenericEntry({ project_name: name }) {
-      return {
-        name,
-        type: 'project',
+
+    canDeleteProject(project) {
+      if (this.$auth.user.is_superuser) {
+        return true
+      } else {
+        const canDeleteProjectPerm = 'delete_project'
+        return project.permissions.some((perm) => {
+          return perm === canDeleteProjectPerm
+        })
       }
     },
+    async fetchProjects() {
+      this.projects = await fetchProjects(this.$axios)
+    },
+
+    ...mapActions({
+      updateProjectsCount: 'updateProjectsCount',
+    }),
   },
   head() {
     return {
diff --git a/client-nuxt/pages/teams.vue b/client-nuxt/pages/teams.vue
index d63c422e349bb53ddf63ec2375b89c9f47b0cf18..86ffa69991d0486f8446487fe9e8d7a43cb1b265 100644
--- a/client-nuxt/pages/teams.vue
+++ b/client-nuxt/pages/teams.vue
@@ -1,6 +1,6 @@
 <template>
   <div>
-    <User :user="user" />
+    <User :user="$auth.user.id" />
     <nuxt-child />
   </div>
 </template>
@@ -12,16 +12,5 @@ export default {
   components: {
     User,
   },
-  async asyncData({ $axios, params, $auth }) {
-    const user = await $axios.$get(`/api/users/${$auth.user}`)
-    return {
-      user,
-    }
-  },
-  data() {
-    return {
-      user: {},
-    }
-  },
 }
 </script>
diff --git a/client-nuxt/pages/users/_userId.vue b/client-nuxt/pages/users/_userId.vue
new file mode 100644
index 0000000000000000000000000000000000000000..c144e2a96241ccf2ae53a79497bd642df5a91407
--- /dev/null
+++ b/client-nuxt/pages/users/_userId.vue
@@ -0,0 +1,18 @@
+<template>
+  <v-card flat>
+    <User :user="user" />
+    <nuxt-child />
+  </v-card>
+</template>
+<script>
+import User from '~/components/User'
+export default {
+  components: {
+    User,
+  },
+  async asyncData({ $axios, params }) {
+    const user = await $axios.$get(`/api/users/${params.userId}`)
+    return { user }
+  },
+}
+</script>
diff --git a/client-nuxt/pages/users/_userId/password-change.vue b/client-nuxt/pages/users/_userId/password-change.vue
new file mode 100644
index 0000000000000000000000000000000000000000..a95b8d87f241b39d7b42b57fc0bb539660199d2f
--- /dev/null
+++ b/client-nuxt/pages/users/_userId/password-change.vue
@@ -0,0 +1,121 @@
+<template>
+  <v-card>
+    <v-card-title> Password Change </v-card-title>
+    <ValidationObserver ref="observer" v-slot="{ invalid }">
+      <v-form v-model="valid" @submit.prevent="submit">
+        <v-card-text>
+          <error-alert v-if="error" :error-message="error"></error-alert>
+          <ValidationProvider
+            v-slot="{ errors }"
+            name="oldPassword"
+            rules="required"
+          >
+            <v-text-field
+              v-model="passwords.oldPassword"
+              :error-messages="errors"
+              type="password"
+              placeholder="Enter your password"
+              label="Old Password"
+              required
+            ></v-text-field>
+          </ValidationProvider>
+          <ValidationProvider
+            v-slot="{ errors }"
+            name="password"
+            rules="confirmed:confirmation"
+          >
+            <v-text-field
+              v-model="passwords.newPassword"
+              :error-messages="errors"
+              type="password"
+              placeholder="Enter your password"
+              label="New Password"
+              required
+            ></v-text-field>
+          </ValidationProvider>
+          <ValidationProvider v-slot="{ errors }" vid="confirmation">
+            <v-text-field
+              v-model="passwords.newPasswordConfirmation"
+              :error-messages="errors"
+              type="password"
+              placeholder="Enter your password"
+              label="New Password Confirmation"
+              required
+            ></v-text-field>
+          </ValidationProvider>
+        </v-card-text>
+        <v-card-actions>
+          <v-btn
+            type="submit"
+            color="primary"
+            class="submit-auth"
+            :disabled="invalid"
+            >Change</v-btn
+          >
+        </v-card-actions>
+      </v-form>
+    </ValidationObserver>
+  </v-card>
+</template>
+
+<script>
+import { required, confirmed } from 'vee-validate/dist/rules'
+import { extend, ValidationObserver, ValidationProvider } from 'vee-validate'
+import ErrorAlert from '@/components/ErrorAlert'
+
+extend('required', {
+  ...required,
+  message: '{_field_} can not be empty',
+})
+extend('confirmed', {
+  ...confirmed,
+  message: 'The {_field_} field confirmation does not match',
+})
+
+export default {
+  components: {
+    ValidationProvider,
+    ValidationObserver,
+    ErrorAlert,
+  },
+  data() {
+    return {
+      passwords: {
+        oldPassword: null,
+        newPassword: null,
+        newPasswordConfirmation: null,
+      },
+      error: null,
+      valid: false,
+    }
+  },
+  methods: {
+    submit() {
+      this.$refs.observer.validate().then((success) => {
+        this.passwordChange()
+      })
+    },
+    async passwordChange() {
+      try {
+        await this.$axios.$put(
+          `/api/users/${this.$auth.user.id}/password_change/`,
+          {
+            ...this.passwords,
+            old_password: this.passwords.oldPassword,
+            new_password: this.passwords.newPassword,
+            new_password_confirmation: this.passwords.newPasswordConfirmation,
+          }
+        )
+        this.$router.push({
+          name: 'users-userId',
+          params: { userId: this.$auth.user.id },
+        })
+      } catch (err) {
+        this.error = err.message
+      }
+    },
+  },
+}
+</script>
+
+<style></style>
diff --git a/client-nuxt/pages/users/add.vue b/client-nuxt/pages/users/add.vue
new file mode 100644
index 0000000000000000000000000000000000000000..1c507b935eadc742782148562b746b68b87cdf27
--- /dev/null
+++ b/client-nuxt/pages/users/add.vue
@@ -0,0 +1,241 @@
+<template>
+  <ValidationObserver ref="observer" v-slot="{ invalid }">
+    <v-form v-model="valid" @submit.prevent="submit">
+      <v-card>
+        <v-card-title>Add user</v-card-title>
+        <v-card-text>
+          <v-container>
+            <v-row :justify="justifyForm">
+              <v-col cols="12" md="6">
+                <validation-provider
+                  v-slot="{ errors }"
+                  name="Username"
+                  rules="required|alpha_dash|max:25"
+                >
+                  <v-text-field
+                    v-model="user.username"
+                    :counter="25"
+                    :error-count="5"
+                    :error-messages="errors"
+                    label="Username"
+                  ></v-text-field>
+                </validation-provider>
+              </v-col>
+            </v-row>
+            <v-row :justify="justifyForm">
+              <v-col cols="12" md="6">
+                <validation-provider
+                  v-slot="{ errors }"
+                  name="First Name"
+                  rules="required|max:50"
+                >
+                  <v-text-field
+                    v-model="user.first_name"
+                    :counter="50"
+                    :error-messages="errors"
+                    label="First Name"
+                  ></v-text-field
+                ></validation-provider> </v-col
+            ></v-row>
+            <v-row :justify="justifyForm">
+              <v-col cols="12" md="6">
+                <validation-provider
+                  v-slot="{ errors }"
+                  name="Last Name"
+                  rules="required|max:50"
+                >
+                  <v-text-field
+                    v-model="user.last_name"
+                    :counter="50"
+                    :error-messages="errors"
+                    label="Last Name"
+                  ></v-text-field
+                ></validation-provider>
+              </v-col>
+            </v-row>
+            <v-row :justify="justifyForm">
+              <v-col cols="12" md="6">
+                <validation-provider
+                  v-slot="{ errors }"
+                  name="email"
+                  rules="required|email"
+                >
+                  <v-text-field
+                    v-model="user.email"
+                    :error-messages="errors"
+                    label="E-mail"
+                  ></v-text-field
+                ></validation-provider>
+              </v-col>
+            </v-row>
+            <v-row :justify="justifyForm">
+              <v-col cols="12" md="2">
+                <v-switch v-model="user.is_active" label="is active"></v-switch>
+              </v-col>
+              <!-- <v-col cols="12" md="2">
+                <v-switch v-model="user.is_staff" label="is staff"></v-switch>
+              </v-col>
+
+              <v-col cols="12" md="2">
+                <v-switch
+                  v-model="user.is_superuser"
+                  label="is superuser"
+                ></v-switch>
+              </v-col> -->
+            </v-row>
+            <v-row :justify="justifyForm">
+              <v-col cols="12" md="6">
+                <v-select
+                  v-model="role"
+                  :items="roles"
+                  label="Role"
+                  dense
+                ></v-select> </v-col
+            ></v-row>
+            <v-row :justify="justifyForm">
+              <v-col cols="12" md="6">
+                <validation-provider
+                  v-slot="{ errors }"
+                  name="Password"
+                  rules="confirmed:confirmation"
+                >
+                  <v-text-field
+                    v-model="user.password"
+                    type="password"
+                    label="Password"
+                    :error-messages="errors"
+                  ></v-text-field>
+                </validation-provider>
+                <validation-provider v-slot="{ errors }" vid="confirmation">
+                  <v-text-field
+                    v-model="confirmation"
+                    type="password"
+                    label="Password confirmation"
+                    :error-messages="errors"
+                  ></v-text-field>
+                </validation-provider>
+              </v-col>
+            </v-row>
+          </v-container>
+        </v-card-text>
+        <v-card-actions>
+          <v-btn type="submit" color="primary" class="mr-4" :disabled="invalid"
+            >submit</v-btn
+          >
+        </v-card-actions>
+      </v-card>
+    </v-form>
+  </ValidationObserver>
+</template>
+<script>
+import {
+  required,
+  max,
+  email,
+  alpha_dash as alphaDash,
+  confirmed,
+} from 'vee-validate/dist/rules'
+
+import {
+  extend,
+  ValidationObserver,
+  ValidationProvider,
+  setInteractionMode,
+} from 'vee-validate'
+
+setInteractionMode('eager')
+extend('required', {
+  ...required,
+  message: '{_field_} can not be empty',
+})
+extend('email', {
+  ...email,
+  message: 'Email must be valid',
+})
+extend('max', {
+  ...max,
+  message: '{_field_} may not be greater than {length} characters',
+})
+
+extend('alpha_dash', {
+  ...alphaDash,
+  message:
+    'The {_field_} field may contain alpha-numeric characters as well as dashes and underscores',
+})
+extend('confirmed', {
+  ...confirmed,
+  message: 'The {_field_} field confirmation does not match',
+})
+export default {
+  components: {
+    ValidationProvider,
+    ValidationObserver,
+  },
+  async asyncData({ $axios }) {
+    const [{ data: appRoles }, { data: projectGroups }] = await Promise.all([
+      $axios.get('/api/app-roles'),
+      $axios.get('/api/project-groups/'),
+    ])
+    // const { data: appRoles } = await $axios.get('/api/app-roles')
+    return {
+      appRoles,
+      projectGroups,
+    }
+  },
+  data() {
+    return {
+      valid: false,
+      confirmation: null,
+      user: {
+        username: null,
+        first_name: null,
+        last_name: null,
+        email: null,
+        password: null,
+        is_active: true,
+        is_staff: false,
+        is_superuser: false,
+      },
+      role: null,
+      error: null,
+      justifyForm: 'start',
+    }
+  },
+  computed: {
+    roles() {
+      return this.appRoles.map((appRole) => ({
+        text: appRole.role.name,
+        value: appRole.group_ptr,
+        group_id: appRole.group_ptr.id,
+      }))
+    },
+  },
+  methods: {
+    submit() {
+      // setTimeout(() => {})
+      this.$refs.observer.validate().then((success) => {
+        if (success) {
+          this.addUser()
+        } else {
+          this.error = 'The form is invalid'
+        }
+      })
+    },
+
+    async addUser() {
+      try {
+        await this.$axios.$post('/api/users/', {
+          ...this.user,
+          appGroup: this.role,
+        })
+        this.$router.push({
+          name: 'users',
+          params: {},
+        })
+      } catch (err) {
+        this.error = err.message
+      }
+    },
+  },
+}
+</script>
diff --git a/client-nuxt/pages/users/index.vue b/client-nuxt/pages/users/index.vue
new file mode 100644
index 0000000000000000000000000000000000000000..906fc9000964a9aa27500d4b412e6704f30189bb
--- /dev/null
+++ b/client-nuxt/pages/users/index.vue
@@ -0,0 +1,209 @@
+<template>
+  <v-card flat>
+    <error-alert v-if="error" :error-message="error"></error-alert>
+    <v-card-text>
+      <v-data-table
+        :headers="headers"
+        :items="sanitizedUsers"
+        :items-per-page="15"
+        item-key="id"
+        :search="search"
+        :footer-props="{
+          'items-per-page-options': [15, 30, 50, -1],
+        }"
+        calculate-widths
+        class="elevation-1"
+      >
+        <template v-slot:top>
+          <v-toolbar flat>
+            <v-toolbar-title> Users </v-toolbar-title>
+            <v-divider class="mx-4" inset vertical></v-divider>
+            <v-text-field
+              v-model="search"
+              append-icon="mdi-magnify"
+              label="Search"
+              single-line
+              hide-details
+            ></v-text-field>
+            <v-spacer></v-spacer>
+            <v-btn
+              v-if="hasUserCreatePermission"
+              color="primary"
+              fab
+              small
+              to="/users/add"
+            >
+              <v-icon> mdi-plus </v-icon>
+            </v-btn>
+            <v-dialog v-model="dialogDelete" max-width="800px">
+              <v-card>
+                <v-card-title class="text-h5"
+                  >Are you sure you want to delete this user ?</v-card-title
+                >
+                <v-card-actions>
+                  <v-spacer></v-spacer>
+                  <v-btn color="blue darken-1" text @click="closeDelete"
+                    >Cancel</v-btn
+                  >
+                  <v-btn color="blue darken-1" text @click="deleteItemConfirm"
+                    >OK</v-btn
+                  >
+                  <v-spacer></v-spacer>
+                </v-card-actions>
+              </v-card>
+            </v-dialog>
+          </v-toolbar>
+        </template>
+        <template #[`item.is_active`]="{ item }">
+          <v-icon v-if="item.is_active">mdi-check</v-icon>
+          <v-icon v-else>mdi-close</v-icon>
+        </template>
+        <template #[`item.is_staff`]="{ item }">
+          <v-icon v-if="item.is_staff">mdi-check</v-icon>
+          <v-icon v-else>mdi-close</v-icon>
+        </template>
+        <template #[`item.is_superuser`]="{ item }">
+          <v-icon v-if="item.is_superuser">mdi-check</v-icon>
+          <v-icon v-else>mdi-close</v-icon>
+        </template>
+        <template #[`item.username`]="{ item }">
+          <v-chip color="primary">{{ item.username }}</v-chip>
+        </template>
+        <template #[`item.groups`]="{ item }">
+          <v-card
+            flat
+            color="transparent"
+            class="d-flex justify-start flex-wrap"
+          >
+            <template v-for="group in item.groups">
+              <v-card
+                :key="group.id"
+                flat
+                color="transparent"
+                class="align-center"
+              >
+                <v-chip
+                  v-if="group.projectgroup"
+                  :color="projectRoleColor[group.projectgroup.project_role]"
+                  small
+                  class="ma-1"
+                  >{{ group.projectgroup.project }}
+                </v-chip>
+              </v-card>
+            </template>
+          </v-card>
+        </template>
+        <template #[`item.actions`]="{ item }">
+          <v-icon
+            v-if="hasDeletePermissions(item.permissions)"
+            small
+            @click="deleteItem(item)"
+          >
+            mdi-delete
+          </v-icon>
+        </template>
+      </v-data-table>
+    </v-card-text>
+  </v-card>
+</template>
+<script>
+import ErrorAlert from '@/components/ErrorAlert'
+
+export default {
+  components: {
+    ErrorAlert,
+  },
+  async fetch() {
+    try {
+      this.users = await this.$axios.$get(`/api/users/`)
+    } catch (error) {
+      return { error: error.message }
+    }
+  },
+  async asyncData({ $axios }) {
+    const [users, userOptionsRequest] = await Promise.all([
+      $axios.$get('/api/users/'),
+      $axios.$options('/api/users/'),
+    ])
+    return { users, userOptionsRequest }
+  },
+  data() {
+    return {
+      search: '',
+      headers: [
+        {
+          text: 'Username',
+          align: 'start',
+          value: 'username',
+        },
+        { text: 'First Name', value: 'first_name' },
+        { text: 'Last Name', value: 'last_name' },
+        { text: 'E-Mail', value: 'email' },
+        // { text: 'Projects', value: 'groups' },
+        { text: 'Active', value: 'is_active' },
+        { text: 'Staff', value: 'is_staff' },
+        { text: 'Superuser', value: 'is_superuser' },
+        { text: 'Actions', value: 'actions', sortable: false },
+      ],
+      dialogDelete: false,
+      user: {},
+      error: null,
+      defaultRoleColor: {
+        get(obj, prop) {
+          return prop in obj ? obj[prop] : 'grey'
+        },
+      },
+      roleToColor: {
+        manager: 'error',
+        maintainer: 'accent',
+        reader: 'success',
+      },
+      deletePermissionName: 'delete_user',
+    }
+  },
+  computed: {
+    projectRoleColor() {
+      return new Proxy(this.roleToColor, this.defaultRoleColor)
+    },
+    sanitizedUsers() {
+      return this.users
+        .map((user) => {
+          return { ...user, permissions: new Set(user.permissions) }
+        })
+        .filter((user) => this.$auth.user.id !== user.id)
+    },
+    hasUserCreatePermission() {
+      return this?.userOptionsRequest?.actions?.POST
+    },
+  },
+  methods: {
+    deleteItem(item) {
+      this.user = { ...item }
+      this.dialogDelete = true
+    },
+    async deleteItemConfirm() {
+      try {
+        await this.$axios.$delete(`/api/users/${this.user.id}`)
+        this.$fetch()
+      } catch (err) {
+        this.error = err.message
+      } finally {
+        this.closeDelete()
+      }
+    },
+    closeDelete() {
+      this.dialogDelete = false
+      this.$nextTick(() => {
+        this.user = {}
+      })
+    },
+    hasDeletePermissions(permissionsSet) {
+      return permissionsSet.has(this.deletePermissionName)
+    },
+  },
+}
+</script>
+<style>
+.projects-chips-card {
+}
+</style>
diff --git a/client-nuxt/pages/variable-categories.vue b/client-nuxt/pages/variable-categories.vue
deleted file mode 100644
index 1f95804a71366d0d02d12171d556891451283218..0000000000000000000000000000000000000000
--- a/client-nuxt/pages/variable-categories.vue
+++ /dev/null
@@ -1,279 +0,0 @@
-<template>
-  <v-card>
-    <error-alert v-if="error" :error-message="error"></error-alert>
-    <v-data-table
-      :headers="headers"
-      :items="variableCategories"
-      :sort-by="['dataclass', 'name']"
-      :sort-desc="[true, false]"
-      :search="search"
-      multi-sort
-      class="elevation-1"
-    >
-      <template v-slot:top>
-        <v-toolbar flat>
-          <v-toolbar-title> Variable Categories </v-toolbar-title>
-          <v-divider class="mx-4" inset vertical></v-divider>
-          <v-text-field
-            v-model="search"
-            append-icon="mdi-magnify"
-            label="Search"
-            single-line
-            hide-details
-          ></v-text-field>
-          <v-spacer></v-spacer>
-          <v-dialog v-if="options" v-model="dialog" max-width="800px">
-            <template v-slot:activator="{ on, attrs }">
-              <v-btn
-                color="primary"
-                fab
-                v-bind="attrs"
-                v-on="on"
-                @click="newItem = true"
-              >
-                <v-icon> mdi-plus </v-icon>
-              </v-btn>
-            </template>
-            <v-card>
-              <v-card-title>
-                <span class="text-h5">{{ formTitle }}</span>
-              </v-card-title>
-
-              <v-card-text>
-                <v-container>
-                  <v-row>
-                    <v-col cols="12">
-                      <v-text-field
-                        v-model="variableCategory.name"
-                        label="Name"
-                      ></v-text-field>
-                    </v-col>
-                    <v-col cols="12">
-                      <v-textarea
-                        v-model="variableCategory.description"
-                        outlined
-                        name="input-7-4"
-                        label="Description"
-                      ></v-textarea>
-                    </v-col>
-                    <v-col cols="12">
-                      <v-select
-                        v-model="variableCategory.dataclass"
-                        :items="options.dataclass.choices"
-                        label="Class"
-                        item-text="display_name"
-                        item-value="value"
-                        outlined
-                      ></v-select>
-                    </v-col>
-                    <v-col cols="12">
-                      <v-select
-                        v-model="variableCategory.datatype"
-                        :items="options.datatype.choices"
-                        label="Type"
-                        item-text="display_name"
-                        item-value="value"
-                        outlined
-                      ></v-select>
-                    </v-col>
-                    <v-col cols="12">
-                      <v-select
-                        v-model="variableCategory.nature"
-                        :items="options.nature.choices"
-                        label="Nature"
-                        item-text="display_name"
-                        item-value="value"
-                        outlined
-                      ></v-select>
-                    </v-col>
-                    <v-col cols="12">
-                      <v-select
-                        v-model="variableCategory.location"
-                        :items="options.location.choices"
-                        label="Location"
-                        item-text="display_name"
-                        item-value="value"
-                        outlined
-                      ></v-select>
-                    </v-col>
-                  </v-row>
-                </v-container>
-              </v-card-text>
-
-              <v-card-actions>
-                <v-spacer></v-spacer>
-                <v-btn color="blue darken-1" text @click="close">
-                  Cancel
-                </v-btn>
-                <v-btn color="blue darken-1" text @click="save"> Save </v-btn>
-              </v-card-actions>
-            </v-card>
-          </v-dialog>
-          <v-dialog v-model="dialogDelete" max-width="800px">
-            <v-card>
-              <v-card-title class="text-h5"
-                >Are you sure you want to delete this variable
-                category?</v-card-title
-              >
-              <v-card-actions>
-                <v-spacer></v-spacer>
-                <v-btn color="blue darken-1" text @click="closeDelete"
-                  >Cancel</v-btn
-                >
-                <v-btn color="blue darken-1" text @click="deleteItemConfirm"
-                  >OK</v-btn
-                >
-                <v-spacer></v-spacer>
-              </v-card-actions>
-            </v-card>
-          </v-dialog>
-        </v-toolbar>
-      </template>
-      <template v-if="options" #[`item.actions`]="{ item }">
-        <v-icon small class="mr-2" @click="editItem(item)"> mdi-pencil </v-icon>
-        <v-icon small @click="deleteItem(item)"> mdi-delete </v-icon>
-      </template>
-      <template v-slot:no-data>
-        <v-btn color="primary" @click="initialize"> Reset </v-btn>
-      </template></v-data-table
-    ></v-card
-  >
-</template>
-
-<script>
-import ErrorAlert from '@/components/ErrorAlert'
-
-export default {
-  components: {
-    ErrorAlert,
-  },
-  async fetch() {
-    try {
-      this.variableCategories = await this.$axios.$get(
-        `/api/variable-categories/`
-      )
-    } catch (error) {
-      return { error: error.message }
-    }
-  },
-  async asyncData({ $axios }) {
-    const variableCategories = await $axios.$get(`/api/variable-categories/`)
-    const endpointOptions = await $axios.$options('/api/variable-categories/')
-    let options = null
-    if (endpointOptions.actions && endpointOptions.actions.POST) {
-      options = endpointOptions.actions.POST
-    }
-    return {
-      variableCategories,
-      options,
-    }
-  },
-  data() {
-    return {
-      search: '',
-      dialog: false,
-      dialogDelete: false,
-      newItem: true,
-      error: null,
-      variableCategory: {
-        name: '',
-        description: '',
-        datatype: '',
-        dataclass: '',
-        nature: '',
-        location: '',
-      },
-      defaultVariableCategory: {
-        name: '',
-        description: '',
-        datatype: '',
-        dataclass: '',
-        nature: '',
-        location: '',
-      },
-      allHeaders: [
-        {
-          text: 'Name',
-          align: 'start',
-          value: 'name',
-        },
-        { text: 'Description', value: 'description' },
-        { text: 'Data Class', value: 'dataclass' },
-        { text: 'Datatype', value: 'datatype' },
-        { text: 'Nature', value: 'nature' },
-        { text: 'Location', value: 'location' },
-        { text: 'Actions', value: 'actions', sortable: false },
-      ],
-    }
-  },
-  computed: {
-    formTitle() {
-      return this.newItem ? 'New Variable Category' : 'Edit Variable Category'
-    },
-    headers() {
-      return this.options ? this.allHeaders : this.allHeaders.slice(0, -1)
-    },
-  },
-
-  methods: {
-    editItem(item) {
-      this.variableCategory = { ...item }
-      this.dialog = true
-      this.newItem = false
-    },
-    deleteItem(item) {
-      this.variableCategory = { ...item }
-      this.dialogDelete = true
-    },
-
-    async deleteItemConfirm() {
-      try {
-        await this.$axios.$delete(
-          `/api/variable-categories/${this.variableCategory.id}`
-        )
-        this.$fetch()
-      } catch (err) {
-        this.error = err.message
-      } finally {
-        this.closeDelete()
-      }
-    },
-    closeDelete() {
-      this.dialogDelete = false
-      this.$nextTick(() => {
-        this.variableCategory = { ...this.defaultVariableCategory }
-        this.newItem = false
-      })
-    },
-    close() {
-      this.dialog = false
-      this.$nextTick(() => {
-        this.variableCategory = { ...this.defaultVariableCategory }
-        this.newItem = false
-      })
-    },
-    async save() {
-      try {
-        if (this.newItem) {
-          await this.$axios.$post(
-            '/api/variable-categories/',
-            this.variableCategory
-          )
-        } else {
-          await this.$axios.$patch(
-            `/api/variable-categories/${this.variableCategory.id}/`,
-            this.variableCategory
-          )
-        }
-        this.$fetch()
-      } catch (err) {
-        this.error = err.message
-      } finally {
-        this.close()
-      }
-    },
-  },
-}
-</script>
-
-<style></style>
diff --git a/client-nuxt/plugins/highcharts.js b/client-nuxt/plugins/highcharts.js
new file mode 100644
index 0000000000000000000000000000000000000000..82ccf830d9434567ba9a31734f532f8d744a36ab
--- /dev/null
+++ b/client-nuxt/plugins/highcharts.js
@@ -0,0 +1,17 @@
+import Vue from 'vue'
+import Highcharts from 'highcharts'
+import Histogram from 'highcharts/modules/histogram-bellcurve'
+import exportingInit from 'highcharts/modules/exporting'
+import offlineExportingInit from 'highcharts/modules/offline-exporting'
+import exportDataInit from 'highcharts/modules/export-data'
+import boostInit from 'highcharts/modules/boost'
+import More from 'highcharts/highcharts-more'
+import HighchartsVue from 'highcharts-vue'
+
+Histogram(Highcharts)
+exportingInit(Highcharts)
+offlineExportingInit(Highcharts)
+exportDataInit(Highcharts)
+boostInit(Highcharts)
+More(Highcharts)
+Vue.use(HighchartsVue)
diff --git a/client-nuxt/store/index.js b/client-nuxt/store/index.js
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..b0c09441e738644efc771a10e0c83279f771abe7 100644
--- a/client-nuxt/store/index.js
+++ b/client-nuxt/store/index.js
@@ -0,0 +1,74 @@
+function emptyExperimentToAdd() {
+  return {
+    projectId: null,
+    experiment: {
+      name: '',
+      description: '',
+      file: null,
+    },
+    experimentMetadata: [],
+  }
+}
+
+export const state = () => ({
+  theme: {
+    darkIcon: 'mdi-weather-night',
+    lightIcon: 'mdi-white-balance-sunny',
+  },
+  projects: { count: 0 },
+  analysis: { count: 0 },
+  experiments: { count: 0 },
+  emptyExperimentToAdd: {
+    projectId: null,
+    experiment: {
+      name: '',
+      description: '',
+      file: null,
+    },
+    experimentMetadata: [],
+  },
+  experimentToAdd: {},
+})
+
+export const getters = {
+  getExperimentToAdd: (state) => (id) => {
+    return state.experimentToAdd[id]
+  },
+}
+export const mutations = {
+  projectsCount(state, count) {
+    state.projects.count = count
+  },
+  analysisCount(state, count) {
+    state.analysis.count = count
+  },
+
+  // experiments
+  experimentsCount(state, count) {
+    state.experiments.count = count
+  },
+  initExperimentToAdd(state, projectId) {
+    state.experimentToAdd[projectId] = emptyExperimentToAdd()
+  },
+  updateExperiment(state, { experiment, projectId }) {
+    state.experimentToAdd[projectId] = experiment
+  },
+  clearExperiment(state, projectId) {
+    state.experimentToAdd[projectId] = emptyExperimentToAdd()
+  },
+}
+
+export const actions = {
+  async updateProjectsCount({ commit }) {
+    const { count } = await this.$axios.$get('/api/projects/count/')
+    commit('projectsCount', count)
+  },
+  async updateAnalysisCount({ commit }) {
+    const { count } = await this.$axios.$get('/api/analysis/count/')
+    commit('analysisCount', count)
+  },
+  async updateExperimentsCount({ commit }) {
+    const { count } = await this.$axios.$get('/api/experiments/count/')
+    commit('experimentsCount', count)
+  },
+}
diff --git a/client-nuxt/test/User.spec.js b/client-nuxt/test/User.spec.js
deleted file mode 100644
index 18a3512ea96eb62cd35b9d77a21e9cb4e1193b49..0000000000000000000000000000000000000000
--- a/client-nuxt/test/User.spec.js
+++ /dev/null
@@ -1,31 +0,0 @@
-import { mount, createLocalVue } from '@vue/test-utils'
-import User from '@/components/User.vue'
-import Vuetify from 'vuetify'
-
-const localVue = createLocalVue()
-describe('User', () => {
-  let vuetify
-  beforeEach(() => {
-    vuetify = new Vuetify()
-  })
-
-  test('is a Vue instance', () => {
-    const user = {
-      first_name: 'foo',
-      last_name: 'bar',
-      username: 'fbar',
-      email: 'fbar@example.com',
-    }
-    const wrapper = mount(User, {
-      localVue,
-      vuetify,
-      propsData: {
-        user,
-      },
-    })
-    expect(wrapper.isVueInstance()).toBeTruthy()
-
-    const title = wrapper.find('.v-card__title')
-    expect(title.text()).toBe(user.first_name + ' ' + user.last_name)
-  })
-})
diff --git a/client-nuxt/yarn.lock b/client-nuxt/yarn.lock
index 4c875390de531d405f8c69efc6e93263aed63306..8d4a490483da21180cd04321aa6318291dacbe7b 100644
--- a/client-nuxt/yarn.lock
+++ b/client-nuxt/yarn.lock
@@ -2,372 +2,423 @@
 # yarn lockfile v1
 
 
-"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.11":
+"@babel/code-frame@7.12.11":
   version "7.12.11"
   resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.11.tgz#f4ad435aa263db935b8f10f2c552d23fb716a63f"
   integrity sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==
   dependencies:
     "@babel/highlight" "^7.10.4"
 
-"@babel/compat-data@^7.12.5", "@babel/compat-data@^7.12.7":
-  version "7.12.7"
-  resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.12.7.tgz#9329b4782a7d6bbd7eef57e11addf91ee3ef1e41"
-  integrity sha512-YaxPMGs/XIWtYqrdEOZOCPsVWfEoriXopnsz3/i7apYPXQ3698UFhS6dVT1KN5qOsWmVgw/FOrmQgpRaZayGsw==
-
-"@babel/core@^7.1.0", "@babel/core@^7.12.9", "@babel/core@^7.4.4", "@babel/core@^7.7.5":
-  version "7.12.10"
-  resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.12.10.tgz#b79a2e1b9f70ed3d84bbfb6d8c4ef825f606bccd"
-  integrity sha512-eTAlQKq65zHfkHZV0sIVODCPGVgoo1HdBlbSLi9CqOzuZanMv2ihzY+4paiKr1mH+XmYESMAmJ/dpZ68eN6d8w==
-  dependencies:
-    "@babel/code-frame" "^7.10.4"
-    "@babel/generator" "^7.12.10"
-    "@babel/helper-module-transforms" "^7.12.1"
-    "@babel/helpers" "^7.12.5"
-    "@babel/parser" "^7.12.10"
-    "@babel/template" "^7.12.7"
-    "@babel/traverse" "^7.12.10"
-    "@babel/types" "^7.12.10"
+"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.14.5":
+  version "7.14.5"
+  resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.14.5.tgz#23b08d740e83f49c5e59945fbf1b43e80bbf4edb"
+  integrity sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==
+  dependencies:
+    "@babel/highlight" "^7.14.5"
+
+"@babel/compat-data@^7.13.11", "@babel/compat-data@^7.14.0", "@babel/compat-data@^7.14.7", "@babel/compat-data@^7.15.0":
+  version "7.15.0"
+  resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.15.0.tgz#2dbaf8b85334796cafbb0f5793a90a2fc010b176"
+  integrity sha512-0NqAC1IJE0S0+lL1SWFMxMkz1pKCNCjI4tr2Zx4LJSXxCLAdr6KyArnY+sno5m3yH9g737ygOyPABDsnXkpxiA==
+
+"@babel/core@^7.1.0", "@babel/core@^7.12.16", "@babel/core@^7.14.0", "@babel/core@^7.7.5":
+  version "7.15.5"
+  resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.15.5.tgz#f8ed9ace730722544609f90c9bb49162dc3bf5b9"
+  integrity sha512-pYgXxiwAgQpgM1bNkZsDEq85f0ggXMA5L7c+o3tskGMh2BunCI9QUwB9Z4jpvXUOuMdyGKiGKQiRe11VS6Jzvg==
+  dependencies:
+    "@babel/code-frame" "^7.14.5"
+    "@babel/generator" "^7.15.4"
+    "@babel/helper-compilation-targets" "^7.15.4"
+    "@babel/helper-module-transforms" "^7.15.4"
+    "@babel/helpers" "^7.15.4"
+    "@babel/parser" "^7.15.5"
+    "@babel/template" "^7.15.4"
+    "@babel/traverse" "^7.15.4"
+    "@babel/types" "^7.15.4"
     convert-source-map "^1.7.0"
     debug "^4.1.0"
-    gensync "^1.0.0-beta.1"
+    gensync "^1.0.0-beta.2"
     json5 "^2.1.2"
-    lodash "^4.17.19"
-    semver "^5.4.1"
+    semver "^6.3.0"
     source-map "^0.5.0"
 
-"@babel/generator@^7.12.10", "@babel/generator@^7.12.11", "@babel/generator@^7.4.4":
-  version "7.12.11"
-  resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.12.11.tgz#98a7df7b8c358c9a37ab07a24056853016aba3af"
-  integrity sha512-Ggg6WPOJtSi8yYQvLVjG8F/TlpWDlKx0OpS4Kt+xMQPs5OaGYWy+v1A+1TvxI6sAMGZpKWWoAQ1DaeQbImlItA==
+"@babel/eslint-parser@^7.12.16":
+  version "7.15.4"
+  resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.15.4.tgz#46385943726291fb3e8db99522c8099b15684387"
+  integrity sha512-hPMIAmGNbmQzXJIo2P43Zj9UhRmGev5f9nqdBFOWNGDGh6XKmjby79woBvg6y0Jur6yRfQBneDbUQ8ZVc1krFw==
+  dependencies:
+    eslint-scope "^5.1.1"
+    eslint-visitor-keys "^2.1.0"
+    semver "^6.3.0"
+
+"@babel/generator@^7.15.4":
+  version "7.15.4"
+  resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.15.4.tgz#85acb159a267ca6324f9793986991ee2022a05b0"
+  integrity sha512-d3itta0tu+UayjEORPNz6e1T3FtvWlP5N4V5M+lhp/CxT4oAA7/NcScnpRyspUMLK6tu9MNHmQHxRykuN2R7hw==
   dependencies:
-    "@babel/types" "^7.12.11"
+    "@babel/types" "^7.15.4"
     jsesc "^2.5.1"
     source-map "^0.5.0"
 
-"@babel/helper-annotate-as-pure@^7.10.4", "@babel/helper-annotate-as-pure@^7.12.10":
-  version "7.12.10"
-  resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.12.10.tgz#54ab9b000e60a93644ce17b3f37d313aaf1d115d"
-  integrity sha512-XplmVbC1n+KY6jL8/fgLVXXUauDIB+lD5+GsQEh6F6GBF1dq1qy4DP4yXWzDKcoqXB3X58t61e85Fitoww4JVQ==
+"@babel/helper-annotate-as-pure@^7.14.5", "@babel/helper-annotate-as-pure@^7.15.4":
+  version "7.15.4"
+  resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.15.4.tgz#3d0e43b00c5e49fdb6c57e421601a7a658d5f835"
+  integrity sha512-QwrtdNvUNsPCj2lfNQacsGSQvGX8ee1ttrBrcozUP2Sv/jylewBP/8QFe6ZkBsC8T/GYWonNAWJV4aRR9AL2DA==
   dependencies:
-    "@babel/types" "^7.12.10"
+    "@babel/types" "^7.15.4"
 
-"@babel/helper-builder-binary-assignment-operator-visitor@^7.10.4":
-  version "7.10.4"
-  resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.10.4.tgz#bb0b75f31bf98cbf9ff143c1ae578b87274ae1a3"
-  integrity sha512-L0zGlFrGWZK4PbT8AszSfLTM5sDU1+Az/En9VrdT8/LmEiJt4zXt+Jve9DCAnQcbqDhCI+29y/L93mrDzddCcg==
+"@babel/helper-builder-binary-assignment-operator-visitor@^7.14.5":
+  version "7.15.4"
+  resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.15.4.tgz#21ad815f609b84ee0e3058676c33cf6d1670525f"
+  integrity sha512-P8o7JP2Mzi0SdC6eWr1zF+AEYvrsZa7GSY1lTayjF5XJhVH0kjLYUZPvTMflP7tBgZoe9gIhTa60QwFpqh/E0Q==
   dependencies:
-    "@babel/helper-explode-assignable-expression" "^7.10.4"
-    "@babel/types" "^7.10.4"
+    "@babel/helper-explode-assignable-expression" "^7.15.4"
+    "@babel/types" "^7.15.4"
 
-"@babel/helper-compilation-targets@^7.12.5":
-  version "7.12.5"
-  resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.12.5.tgz#cb470c76198db6a24e9dbc8987275631e5d29831"
-  integrity sha512-+qH6NrscMolUlzOYngSBMIOQpKUGPPsc61Bu5W10mg84LxZ7cmvnBHzARKbDoFxVvqqAbj6Tg6N7bSrWSPXMyw==
+"@babel/helper-compilation-targets@^7.13.0", "@babel/helper-compilation-targets@^7.13.16", "@babel/helper-compilation-targets@^7.14.5", "@babel/helper-compilation-targets@^7.15.4":
+  version "7.15.4"
+  resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.15.4.tgz#cf6d94f30fbefc139123e27dd6b02f65aeedb7b9"
+  integrity sha512-rMWPCirulnPSe4d+gwdWXLfAXTTBj8M3guAf5xFQJ0nvFY7tfNAFnWdqaHegHlgDZOCT4qvhF3BYlSJag8yhqQ==
   dependencies:
-    "@babel/compat-data" "^7.12.5"
-    "@babel/helper-validator-option" "^7.12.1"
-    browserslist "^4.14.5"
-    semver "^5.5.0"
+    "@babel/compat-data" "^7.15.0"
+    "@babel/helper-validator-option" "^7.14.5"
+    browserslist "^4.16.6"
+    semver "^6.3.0"
 
-"@babel/helper-create-class-features-plugin@^7.12.1":
-  version "7.12.1"
-  resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.12.1.tgz#3c45998f431edd4a9214c5f1d3ad1448a6137f6e"
-  integrity sha512-hkL++rWeta/OVOBTRJc9a5Azh5mt5WgZUGAKMD8JM141YsE08K//bp1unBBieO6rUKkIPyUE0USQ30jAy3Sk1w==
+"@babel/helper-create-class-features-plugin@^7.14.5", "@babel/helper-create-class-features-plugin@^7.15.4":
+  version "7.15.4"
+  resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.15.4.tgz#7f977c17bd12a5fba363cb19bea090394bf37d2e"
+  integrity sha512-7ZmzFi+DwJx6A7mHRwbuucEYpyBwmh2Ca0RvI6z2+WLZYCqV0JOaLb+u0zbtmDicebgKBZgqbYfLaKNqSgv5Pw==
   dependencies:
-    "@babel/helper-function-name" "^7.10.4"
-    "@babel/helper-member-expression-to-functions" "^7.12.1"
-    "@babel/helper-optimise-call-expression" "^7.10.4"
-    "@babel/helper-replace-supers" "^7.12.1"
-    "@babel/helper-split-export-declaration" "^7.10.4"
+    "@babel/helper-annotate-as-pure" "^7.15.4"
+    "@babel/helper-function-name" "^7.15.4"
+    "@babel/helper-member-expression-to-functions" "^7.15.4"
+    "@babel/helper-optimise-call-expression" "^7.15.4"
+    "@babel/helper-replace-supers" "^7.15.4"
+    "@babel/helper-split-export-declaration" "^7.15.4"
 
-"@babel/helper-create-regexp-features-plugin@^7.12.1":
-  version "7.12.7"
-  resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.12.7.tgz#2084172e95443fa0a09214ba1bb328f9aea1278f"
-  integrity sha512-idnutvQPdpbduutvi3JVfEgcVIHooQnhvhx0Nk9isOINOIGYkZea1Pk2JlJRiUnMefrlvr0vkByATBY/mB4vjQ==
+"@babel/helper-create-regexp-features-plugin@^7.14.5":
+  version "7.14.5"
+  resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.14.5.tgz#c7d5ac5e9cf621c26057722fb7a8a4c5889358c4"
+  integrity sha512-TLawwqpOErY2HhWbGJ2nZT5wSkR192QpN+nBg1THfBfftrlvOh+WbhrxXCH4q4xJ9Gl16BGPR/48JA+Ryiho/A==
   dependencies:
-    "@babel/helper-annotate-as-pure" "^7.10.4"
+    "@babel/helper-annotate-as-pure" "^7.14.5"
     regexpu-core "^4.7.1"
 
-"@babel/helper-define-map@^7.10.4":
-  version "7.10.5"
-  resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.10.5.tgz#b53c10db78a640800152692b13393147acb9bb30"
-  integrity sha512-fMw4kgFB720aQFXSVaXr79pjjcW5puTCM16+rECJ/plGS+zByelE8l9nCpV1GibxTnFVmUuYG9U8wYfQHdzOEQ==
-  dependencies:
-    "@babel/helper-function-name" "^7.10.4"
-    "@babel/types" "^7.10.5"
-    lodash "^4.17.19"
-
-"@babel/helper-explode-assignable-expression@^7.10.4":
-  version "7.12.1"
-  resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.12.1.tgz#8006a466695c4ad86a2a5f2fb15b5f2c31ad5633"
-  integrity sha512-dmUwH8XmlrUpVqgtZ737tK88v07l840z9j3OEhCLwKTkjlvKpfqXVIZ0wpK3aeOxspwGrf/5AP5qLx4rO3w5rA==
-  dependencies:
-    "@babel/types" "^7.12.1"
-
-"@babel/helper-function-name@^7.10.4", "@babel/helper-function-name@^7.12.11":
-  version "7.12.11"
-  resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.12.11.tgz#1fd7738aee5dcf53c3ecff24f1da9c511ec47b42"
-  integrity sha512-AtQKjtYNolKNi6nNNVLQ27CP6D9oFR6bq/HPYSizlzbp7uC1M59XJe8L+0uXjbIaZaUJF99ruHqVGiKXU/7ybA==
-  dependencies:
-    "@babel/helper-get-function-arity" "^7.12.10"
-    "@babel/template" "^7.12.7"
-    "@babel/types" "^7.12.11"
-
-"@babel/helper-get-function-arity@^7.12.10":
-  version "7.12.10"
-  resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.10.tgz#b158817a3165b5faa2047825dfa61970ddcc16cf"
-  integrity sha512-mm0n5BPjR06wh9mPQaDdXWDoll/j5UpCAPl1x8fS71GHm7HA6Ua2V4ylG1Ju8lvcTOietbPNNPaSilKj+pj+Ag==
-  dependencies:
-    "@babel/types" "^7.12.10"
-
-"@babel/helper-hoist-variables@^7.10.4":
-  version "7.10.4"
-  resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.10.4.tgz#d49b001d1d5a68ca5e6604dda01a6297f7c9381e"
-  integrity sha512-wljroF5PgCk2juF69kanHVs6vrLwIPNp6DLD+Lrl3hoQ3PpPPikaDRNFA+0t81NOoMt2DL6WW/mdU8k4k6ZzuA==
-  dependencies:
-    "@babel/types" "^7.10.4"
-
-"@babel/helper-member-expression-to-functions@^7.12.1", "@babel/helper-member-expression-to-functions@^7.12.7":
-  version "7.12.7"
-  resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.12.7.tgz#aa77bd0396ec8114e5e30787efa78599d874a855"
-  integrity sha512-DCsuPyeWxeHgh1Dus7APn7iza42i/qXqiFPWyBDdOFtvS581JQePsc1F/nD+fHrcswhLlRc2UpYS1NwERxZhHw==
-  dependencies:
-    "@babel/types" "^7.12.7"
-
-"@babel/helper-module-imports@^7.0.0", "@babel/helper-module-imports@^7.12.1", "@babel/helper-module-imports@^7.12.5":
-  version "7.12.5"
-  resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.12.5.tgz#1bfc0229f794988f76ed0a4d4e90860850b54dfb"
-  integrity sha512-SR713Ogqg6++uexFRORf/+nPXMmWIn80TALu0uaFb+iQIUoR7bOC7zBWyzBs5b3tBBJXuyD0cRu1F15GyzjOWA==
-  dependencies:
-    "@babel/types" "^7.12.5"
-
-"@babel/helper-module-transforms@^7.12.1":
-  version "7.12.1"
-  resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.12.1.tgz#7954fec71f5b32c48e4b303b437c34453fd7247c"
-  integrity sha512-QQzehgFAZ2bbISiCpmVGfiGux8YVFXQ0abBic2Envhej22DVXV9nCFaS5hIQbkyo1AdGb+gNME2TSh3hYJVV/w==
-  dependencies:
-    "@babel/helper-module-imports" "^7.12.1"
-    "@babel/helper-replace-supers" "^7.12.1"
-    "@babel/helper-simple-access" "^7.12.1"
-    "@babel/helper-split-export-declaration" "^7.11.0"
-    "@babel/helper-validator-identifier" "^7.10.4"
-    "@babel/template" "^7.10.4"
-    "@babel/traverse" "^7.12.1"
-    "@babel/types" "^7.12.1"
-    lodash "^4.17.19"
-
-"@babel/helper-optimise-call-expression@^7.10.4", "@babel/helper-optimise-call-expression@^7.12.10":
-  version "7.12.10"
-  resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.12.10.tgz#94ca4e306ee11a7dd6e9f42823e2ac6b49881e2d"
-  integrity sha512-4tpbU0SrSTjjt65UMWSrUOPZTsgvPgGG4S8QSTNHacKzpS51IVWGDj0yCwyeZND/i+LSN2g/O63jEXEWm49sYQ==
-  dependencies:
-    "@babel/types" "^7.12.10"
-
-"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3":
-  version "7.10.4"
-  resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz#2f75a831269d4f677de49986dff59927533cf375"
-  integrity sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==
-
-"@babel/helper-remap-async-to-generator@^7.12.1":
-  version "7.12.1"
-  resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.12.1.tgz#8c4dbbf916314f6047dc05e6a2217074238347fd"
-  integrity sha512-9d0KQCRM8clMPcDwo8SevNs+/9a8yWVVmaE80FGJcEP8N1qToREmWEGnBn8BUlJhYRFz6fqxeRL1sl5Ogsed7A==
-  dependencies:
-    "@babel/helper-annotate-as-pure" "^7.10.4"
-    "@babel/helper-wrap-function" "^7.10.4"
-    "@babel/types" "^7.12.1"
-
-"@babel/helper-replace-supers@^7.12.1":
-  version "7.12.11"
-  resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.12.11.tgz#ea511658fc66c7908f923106dd88e08d1997d60d"
-  integrity sha512-q+w1cqmhL7R0FNzth/PLLp2N+scXEK/L2AHbXUyydxp828F4FEa5WcVoqui9vFRiHDQErj9Zof8azP32uGVTRA==
-  dependencies:
-    "@babel/helper-member-expression-to-functions" "^7.12.7"
-    "@babel/helper-optimise-call-expression" "^7.12.10"
-    "@babel/traverse" "^7.12.10"
-    "@babel/types" "^7.12.11"
-
-"@babel/helper-simple-access@^7.12.1":
-  version "7.12.1"
-  resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.12.1.tgz#32427e5aa61547d38eb1e6eaf5fd1426fdad9136"
-  integrity sha512-OxBp7pMrjVewSSC8fXDFrHrBcJATOOFssZwv16F3/6Xtc138GHybBfPbm9kfiqQHKhYQrlamWILwlDCeyMFEaA==
-  dependencies:
-    "@babel/types" "^7.12.1"
-
-"@babel/helper-skip-transparent-expression-wrappers@^7.12.1":
-  version "7.12.1"
-  resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.12.1.tgz#462dc63a7e435ade8468385c63d2b84cce4b3cbf"
-  integrity sha512-Mf5AUuhG1/OCChOJ/HcADmvcHM42WJockombn8ATJG3OnyiSxBK/Mm5x78BQWvmtXZKHgbjdGL2kin/HOLlZGA==
-  dependencies:
-    "@babel/types" "^7.12.1"
-
-"@babel/helper-split-export-declaration@^7.10.4", "@babel/helper-split-export-declaration@^7.11.0", "@babel/helper-split-export-declaration@^7.12.11":
-  version "7.12.11"
-  resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.11.tgz#1b4cc424458643c47d37022223da33d76ea4603a"
-  integrity sha512-LsIVN8j48gHgwzfocYUSkO/hjYAOJqlpJEc7tGXcIm4cubjVUf8LGW6eWRyxEu7gA25q02p0rQUWoCI33HNS5g==
+"@babel/helper-define-polyfill-provider@^0.2.2":
+  version "0.2.3"
+  resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.2.3.tgz#0525edec5094653a282688d34d846e4c75e9c0b6"
+  integrity sha512-RH3QDAfRMzj7+0Nqu5oqgO5q9mFtQEVvCRsi8qCEfzLR9p2BHfn5FzhSB2oj1fF7I2+DcTORkYaQ6aTR9Cofew==
   dependencies:
-    "@babel/types" "^7.12.11"
-
-"@babel/helper-validator-identifier@^7.10.4", "@babel/helper-validator-identifier@^7.12.11":
-  version "7.12.11"
-  resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz#c9a1f021917dcb5ccf0d4e453e399022981fc9ed"
-  integrity sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==
-
-"@babel/helper-validator-option@^7.12.1", "@babel/helper-validator-option@^7.12.11":
-  version "7.12.11"
-  resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.12.11.tgz#d66cb8b7a3e7fe4c6962b32020a131ecf0847f4f"
-  integrity sha512-TBFCyj939mFSdeX7U7DDj32WtzYY7fDcalgq8v3fBZMNOJQNn7nOYzMaUCiPxPYfCup69mtIpqlKgMZLvQ8Xhw==
+    "@babel/helper-compilation-targets" "^7.13.0"
+    "@babel/helper-module-imports" "^7.12.13"
+    "@babel/helper-plugin-utils" "^7.13.0"
+    "@babel/traverse" "^7.13.0"
+    debug "^4.1.1"
+    lodash.debounce "^4.0.8"
+    resolve "^1.14.2"
+    semver "^6.1.2"
+
+"@babel/helper-explode-assignable-expression@^7.15.4":
+  version "7.15.4"
+  resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.15.4.tgz#f9aec9d219f271eaf92b9f561598ca6b2682600c"
+  integrity sha512-J14f/vq8+hdC2KoWLIQSsGrC9EFBKE4NFts8pfMpymfApds+fPqR30AOUWc4tyr56h9l/GA1Sxv2q3dLZWbQ/g==
+  dependencies:
+    "@babel/types" "^7.15.4"
+
+"@babel/helper-function-name@^7.14.5", "@babel/helper-function-name@^7.15.4":
+  version "7.15.4"
+  resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.15.4.tgz#845744dafc4381a4a5fb6afa6c3d36f98a787ebc"
+  integrity sha512-Z91cOMM4DseLIGOnog+Z8OI6YseR9bua+HpvLAQ2XayUGU+neTtX+97caALaLdyu53I/fjhbeCnWnRH1O3jFOw==
+  dependencies:
+    "@babel/helper-get-function-arity" "^7.15.4"
+    "@babel/template" "^7.15.4"
+    "@babel/types" "^7.15.4"
+
+"@babel/helper-get-function-arity@^7.15.4":
+  version "7.15.4"
+  resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.15.4.tgz#098818934a137fce78b536a3e015864be1e2879b"
+  integrity sha512-1/AlxSF92CmGZzHnC515hm4SirTxtpDnLEJ0UyEMgTMZN+6bxXKg04dKhiRx5Enel+SUA1G1t5Ed/yQia0efrA==
+  dependencies:
+    "@babel/types" "^7.15.4"
+
+"@babel/helper-hoist-variables@^7.15.4":
+  version "7.15.4"
+  resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.15.4.tgz#09993a3259c0e918f99d104261dfdfc033f178df"
+  integrity sha512-VTy085egb3jUGVK9ycIxQiPbquesq0HUQ+tPO0uv5mPEBZipk+5FkRKiWq5apuyTE9FUrjENB0rCf8y+n+UuhA==
+  dependencies:
+    "@babel/types" "^7.15.4"
+
+"@babel/helper-member-expression-to-functions@^7.15.4":
+  version "7.15.4"
+  resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.15.4.tgz#bfd34dc9bba9824a4658b0317ec2fd571a51e6ef"
+  integrity sha512-cokOMkxC/BTyNP1AlY25HuBWM32iCEsLPI4BHDpJCHHm1FU2E7dKWWIXJgQgSFiu4lp8q3bL1BIKwqkSUviqtA==
+  dependencies:
+    "@babel/types" "^7.15.4"
+
+"@babel/helper-module-imports@^7.0.0", "@babel/helper-module-imports@^7.12.13", "@babel/helper-module-imports@^7.13.12", "@babel/helper-module-imports@^7.14.5", "@babel/helper-module-imports@^7.15.4":
+  version "7.15.4"
+  resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.15.4.tgz#e18007d230632dea19b47853b984476e7b4e103f"
+  integrity sha512-jeAHZbzUwdW/xHgHQ3QmWR4Jg6j15q4w/gCfwZvtqOxoo5DKtLHk8Bsf4c5RZRC7NmLEs+ohkdq8jFefuvIxAA==
+  dependencies:
+    "@babel/types" "^7.15.4"
+
+"@babel/helper-module-transforms@^7.14.5", "@babel/helper-module-transforms@^7.15.4":
+  version "7.15.4"
+  resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.15.4.tgz#962cc629a7f7f9a082dd62d0307fa75fe8788d7c"
+  integrity sha512-9fHHSGE9zTC++KuXLZcB5FKgvlV83Ox+NLUmQTawovwlJ85+QMhk1CnVk406CQVj97LaWod6KVjl2Sfgw9Aktw==
+  dependencies:
+    "@babel/helper-module-imports" "^7.15.4"
+    "@babel/helper-replace-supers" "^7.15.4"
+    "@babel/helper-simple-access" "^7.15.4"
+    "@babel/helper-split-export-declaration" "^7.15.4"
+    "@babel/helper-validator-identifier" "^7.14.9"
+    "@babel/template" "^7.15.4"
+    "@babel/traverse" "^7.15.4"
+    "@babel/types" "^7.15.4"
+
+"@babel/helper-optimise-call-expression@^7.15.4":
+  version "7.15.4"
+  resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.15.4.tgz#f310a5121a3b9cc52d9ab19122bd729822dee171"
+  integrity sha512-E/z9rfbAOt1vDW1DR7k4SzhzotVV5+qMciWV6LaG1g4jeFrkDlJedjtV4h0i4Q/ITnUu+Pk08M7fczsB9GXBDw==
+  dependencies:
+    "@babel/types" "^7.15.4"
+
+"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.13.0", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3":
+  version "7.14.5"
+  resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.14.5.tgz#5ac822ce97eec46741ab70a517971e443a70c5a9"
+  integrity sha512-/37qQCE3K0vvZKwoK4XU/irIJQdIfCJuhU5eKnNxpFDsOkgFaUAwbv+RYw6eYgsC0E4hS7r5KqGULUogqui0fQ==
+
+"@babel/helper-remap-async-to-generator@^7.14.5", "@babel/helper-remap-async-to-generator@^7.15.4":
+  version "7.15.4"
+  resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.15.4.tgz#2637c0731e4c90fbf58ac58b50b2b5a192fc970f"
+  integrity sha512-v53MxgvMK/HCwckJ1bZrq6dNKlmwlyRNYM6ypaRTdXWGOE2c1/SCa6dL/HimhPulGhZKw9W0QhREM583F/t0vQ==
+  dependencies:
+    "@babel/helper-annotate-as-pure" "^7.15.4"
+    "@babel/helper-wrap-function" "^7.15.4"
+    "@babel/types" "^7.15.4"
+
+"@babel/helper-replace-supers@^7.14.5", "@babel/helper-replace-supers@^7.15.4":
+  version "7.15.4"
+  resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.15.4.tgz#52a8ab26ba918c7f6dee28628b07071ac7b7347a"
+  integrity sha512-/ztT6khaXF37MS47fufrKvIsiQkx1LBRvSJNzRqmbyeZnTwU9qBxXYLaaT/6KaxfKhjs2Wy8kG8ZdsFUuWBjzw==
+  dependencies:
+    "@babel/helper-member-expression-to-functions" "^7.15.4"
+    "@babel/helper-optimise-call-expression" "^7.15.4"
+    "@babel/traverse" "^7.15.4"
+    "@babel/types" "^7.15.4"
+
+"@babel/helper-simple-access@^7.15.4":
+  version "7.15.4"
+  resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.15.4.tgz#ac368905abf1de8e9781434b635d8f8674bcc13b"
+  integrity sha512-UzazrDoIVOZZcTeHHEPYrr1MvTR/K+wgLg6MY6e1CJyaRhbibftF6fR2KU2sFRtI/nERUZR9fBd6aKgBlIBaPg==
+  dependencies:
+    "@babel/types" "^7.15.4"
+
+"@babel/helper-skip-transparent-expression-wrappers@^7.14.5", "@babel/helper-skip-transparent-expression-wrappers@^7.15.4":
+  version "7.15.4"
+  resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.15.4.tgz#707dbdba1f4ad0fa34f9114fc8197aec7d5da2eb"
+  integrity sha512-BMRLsdh+D1/aap19TycS4eD1qELGrCBJwzaY9IE8LrpJtJb+H7rQkPIdsfgnMtLBA6DJls7X9z93Z4U8h7xw0A==
+  dependencies:
+    "@babel/types" "^7.15.4"
+
+"@babel/helper-split-export-declaration@^7.15.4":
+  version "7.15.4"
+  resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.15.4.tgz#aecab92dcdbef6a10aa3b62ab204b085f776e257"
+  integrity sha512-HsFqhLDZ08DxCpBdEVtKmywj6PQbwnF6HHybur0MAnkAKnlS6uHkwnmRIkElB2Owpfb4xL4NwDmDLFubueDXsw==
+  dependencies:
+    "@babel/types" "^7.15.4"
+
+"@babel/helper-validator-identifier@^7.14.5", "@babel/helper-validator-identifier@^7.14.9":
+  version "7.14.9"
+  resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.9.tgz#6654d171b2024f6d8ee151bf2509699919131d48"
+  integrity sha512-pQYxPY0UP6IHISRitNe8bsijHex4TWZXi2HwKVsjPiltzlhse2znVcm9Ace510VT1kxIHjGJCZZQBX2gJDbo0g==
+
+"@babel/helper-validator-option@^7.14.5":
+  version "7.14.5"
+  resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.14.5.tgz#6e72a1fff18d5dfcb878e1e62f1a021c4b72d5a3"
+  integrity sha512-OX8D5eeX4XwcroVW45NMvoYaIuFI+GQpA2a8Gi+X/U/cDUIRsV37qQfF905F0htTRCREQIB4KqPeaveRJUl3Ow==
+
+"@babel/helper-wrap-function@^7.15.4":
+  version "7.15.4"
+  resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.15.4.tgz#6f754b2446cfaf3d612523e6ab8d79c27c3a3de7"
+  integrity sha512-Y2o+H/hRV5W8QhIfTpRIBwl57y8PrZt6JM3V8FOo5qarjshHItyH5lXlpMfBfmBefOqSCpKZs/6Dxqp0E/U+uw==
+  dependencies:
+    "@babel/helper-function-name" "^7.15.4"
+    "@babel/template" "^7.15.4"
+    "@babel/traverse" "^7.15.4"
+    "@babel/types" "^7.15.4"
+
+"@babel/helpers@^7.15.4":
+  version "7.15.4"
+  resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.15.4.tgz#5f40f02050a3027121a3cf48d497c05c555eaf43"
+  integrity sha512-V45u6dqEJ3w2rlryYYXf6i9rQ5YMNu4FLS6ngs8ikblhu2VdR1AqAd6aJjBzmf2Qzh6KOLqKHxEN9+TFbAkAVQ==
+  dependencies:
+    "@babel/template" "^7.15.4"
+    "@babel/traverse" "^7.15.4"
+    "@babel/types" "^7.15.4"
+
+"@babel/highlight@^7.10.4", "@babel/highlight@^7.14.5":
+  version "7.14.5"
+  resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.14.5.tgz#6861a52f03966405001f6aa534a01a24d99e8cd9"
+  integrity sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==
+  dependencies:
+    "@babel/helper-validator-identifier" "^7.14.5"
+    chalk "^2.0.0"
+    js-tokens "^4.0.0"
 
-"@babel/helper-wrap-function@^7.10.4":
-  version "7.12.3"
-  resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.12.3.tgz#3332339fc4d1fbbf1c27d7958c27d34708e990d9"
-  integrity sha512-Cvb8IuJDln3rs6tzjW3Y8UeelAOdnpB8xtQ4sme2MSZ9wOxrbThporC0y/EtE16VAtoyEfLM404Xr1e0OOp+ow==
-  dependencies:
-    "@babel/helper-function-name" "^7.10.4"
-    "@babel/template" "^7.10.4"
-    "@babel/traverse" "^7.10.4"
-    "@babel/types" "^7.10.4"
+"@babel/parser@^7.1.0", "@babel/parser@^7.15.4", "@babel/parser@^7.15.5", "@babel/parser@^7.7.0":
+  version "7.15.5"
+  resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.15.5.tgz#d33a58ca69facc05b26adfe4abebfed56c1c2dac"
+  integrity sha512-2hQstc6I7T6tQsWzlboMh3SgMRPaS4H6H7cPQsJkdzTzEGqQrpLDsE2BGASU5sBPoEQyHzeqU6C8uKbFeEk6sg==
 
-"@babel/helpers@^7.12.5":
-  version "7.12.5"
-  resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.12.5.tgz#1a1ba4a768d9b58310eda516c449913fe647116e"
-  integrity sha512-lgKGMQlKqA8meJqKsW6rUnc4MdUk35Ln0ATDqdM1a/UpARODdI4j5Y5lVfUScnSNkJcdCRAaWkspykNoFg9sJA==
+"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.15.4":
+  version "7.15.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.15.4.tgz#dbdeabb1e80f622d9f0b583efb2999605e0a567e"
+  integrity sha512-eBnpsl9tlhPhpI10kU06JHnrYXwg3+V6CaP2idsCXNef0aeslpqyITXQ74Vfk5uHgY7IG7XP0yIH8b42KSzHog==
   dependencies:
-    "@babel/template" "^7.10.4"
-    "@babel/traverse" "^7.12.5"
-    "@babel/types" "^7.12.5"
+    "@babel/helper-plugin-utils" "^7.14.5"
+    "@babel/helper-skip-transparent-expression-wrappers" "^7.15.4"
+    "@babel/plugin-proposal-optional-chaining" "^7.14.5"
 
-"@babel/highlight@^7.10.4":
-  version "7.10.4"
-  resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.10.4.tgz#7d1bdfd65753538fabe6c38596cdb76d9ac60143"
-  integrity sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==
+"@babel/plugin-proposal-async-generator-functions@^7.15.4":
+  version "7.15.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.15.4.tgz#f82aabe96c135d2ceaa917feb9f5fca31635277e"
+  integrity sha512-2zt2g5vTXpMC3OmK6uyjvdXptbhBXfA77XGrd3gh93zwG8lZYBLOBImiGBEG0RANu3JqKEACCz5CGk73OJROBw==
   dependencies:
-    "@babel/helper-validator-identifier" "^7.10.4"
-    chalk "^2.0.0"
-    js-tokens "^4.0.0"
-
-"@babel/parser@^7.1.0", "@babel/parser@^7.12.10", "@babel/parser@^7.12.11", "@babel/parser@^7.12.7", "@babel/parser@^7.4.4", "@babel/parser@^7.7.0":
-  version "7.12.11"
-  resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.12.11.tgz#9ce3595bcd74bc5c466905e86c535b8b25011e79"
-  integrity sha512-N3UxG+uuF4CMYoNj8AhnbAcJF0PiuJ9KHuy1lQmkYsxTer/MAH9UBNHsBoAX/4s6NvlDD047No8mYVGGzLL4hg==
+    "@babel/helper-plugin-utils" "^7.14.5"
+    "@babel/helper-remap-async-to-generator" "^7.15.4"
+    "@babel/plugin-syntax-async-generators" "^7.8.4"
 
-"@babel/plugin-proposal-async-generator-functions@^7.12.1":
-  version "7.12.12"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.12.12.tgz#04b8f24fd4532008ab4e79f788468fd5a8476566"
-  integrity sha512-nrz9y0a4xmUrRq51bYkWJIO5SBZyG2ys2qinHsN0zHDHVsUaModrkpyWWWXfGqYQmOL3x9sQIcTNN/pBGpo09A==
+"@babel/plugin-proposal-class-properties@^7.13.0", "@babel/plugin-proposal-class-properties@^7.14.5":
+  version "7.14.5"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.14.5.tgz#40d1ee140c5b1e31a350f4f5eed945096559b42e"
+  integrity sha512-q/PLpv5Ko4dVc1LYMpCY7RVAAO4uk55qPwrIuJ5QJ8c6cVuAmhu7I/49JOppXL6gXf7ZHzpRVEUZdYoPLM04Gg==
   dependencies:
-    "@babel/helper-plugin-utils" "^7.10.4"
-    "@babel/helper-remap-async-to-generator" "^7.12.1"
-    "@babel/plugin-syntax-async-generators" "^7.8.0"
+    "@babel/helper-create-class-features-plugin" "^7.14.5"
+    "@babel/helper-plugin-utils" "^7.14.5"
 
-"@babel/plugin-proposal-class-properties@^7.12.1":
-  version "7.12.1"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.12.1.tgz#a082ff541f2a29a4821065b8add9346c0c16e5de"
-  integrity sha512-cKp3dlQsFsEs5CWKnN7BnSHOd0EOW8EKpEjkoz1pO2E5KzIDNV9Ros1b0CnmbVgAGXJubOYVBOGCT1OmJwOI7w==
+"@babel/plugin-proposal-class-static-block@^7.15.4":
+  version "7.15.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.15.4.tgz#3e7ca6128453c089e8b477a99f970c63fc1cb8d7"
+  integrity sha512-M682XWrrLNk3chXCjoPUQWOyYsB93B9z3mRyjtqqYJWDf2mfCdIYgDrA11cgNVhAQieaq6F2fn2f3wI0U4aTjA==
   dependencies:
-    "@babel/helper-create-class-features-plugin" "^7.12.1"
-    "@babel/helper-plugin-utils" "^7.10.4"
+    "@babel/helper-create-class-features-plugin" "^7.15.4"
+    "@babel/helper-plugin-utils" "^7.14.5"
+    "@babel/plugin-syntax-class-static-block" "^7.14.5"
 
-"@babel/plugin-proposal-decorators@^7.12.1":
-  version "7.12.12"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.12.12.tgz#067a6d3d6ca86d54cf56bb183239199c20daeafe"
-  integrity sha512-fhkE9lJYpw2mjHelBpM2zCbaA11aov2GJs7q4cFaXNrWx0H3bW58H9Esy2rdtYOghFBEYUDRIpvlgi+ZD+AvvQ==
+"@babel/plugin-proposal-decorators@^7.13.15":
+  version "7.15.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.15.4.tgz#fb55442bc83ab4d45dda76b91949706bf22881d2"
+  integrity sha512-WNER+YLs7avvRukEddhu5PSfSaMMimX2xBFgLQS7Bw16yrUxJGWidO9nQp+yLy9MVybg5Ba3BlhAw+BkdhpDmg==
   dependencies:
-    "@babel/helper-create-class-features-plugin" "^7.12.1"
-    "@babel/helper-plugin-utils" "^7.10.4"
-    "@babel/plugin-syntax-decorators" "^7.12.1"
+    "@babel/helper-create-class-features-plugin" "^7.15.4"
+    "@babel/helper-plugin-utils" "^7.14.5"
+    "@babel/plugin-syntax-decorators" "^7.14.5"
 
-"@babel/plugin-proposal-dynamic-import@^7.12.1":
-  version "7.12.1"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.12.1.tgz#43eb5c2a3487ecd98c5c8ea8b5fdb69a2749b2dc"
-  integrity sha512-a4rhUSZFuq5W8/OO8H7BL5zspjnc1FLd9hlOxIK/f7qG4a0qsqk8uvF/ywgBA8/OmjsapjpvaEOYItfGG1qIvQ==
+"@babel/plugin-proposal-dynamic-import@^7.14.5":
+  version "7.14.5"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.14.5.tgz#0c6617df461c0c1f8fff3b47cd59772360101d2c"
+  integrity sha512-ExjiNYc3HDN5PXJx+bwC50GIx/KKanX2HiggnIUAYedbARdImiCU4RhhHfdf0Kd7JNXGpsBBBCOm+bBVy3Gb0g==
   dependencies:
-    "@babel/helper-plugin-utils" "^7.10.4"
-    "@babel/plugin-syntax-dynamic-import" "^7.8.0"
+    "@babel/helper-plugin-utils" "^7.14.5"
+    "@babel/plugin-syntax-dynamic-import" "^7.8.3"
 
-"@babel/plugin-proposal-export-namespace-from@^7.12.1":
-  version "7.12.1"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.12.1.tgz#8b9b8f376b2d88f5dd774e4d24a5cc2e3679b6d4"
-  integrity sha512-6CThGf0irEkzujYS5LQcjBx8j/4aQGiVv7J9+2f7pGfxqyKh3WnmVJYW3hdrQjyksErMGBPQrCnHfOtna+WLbw==
+"@babel/plugin-proposal-export-namespace-from@^7.14.5":
+  version "7.14.5"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.14.5.tgz#dbad244310ce6ccd083072167d8cea83a52faf76"
+  integrity sha512-g5POA32bXPMmSBu5Dx/iZGLGnKmKPc5AiY7qfZgurzrCYgIztDlHFbznSNCoQuv57YQLnQfaDi7dxCtLDIdXdA==
   dependencies:
-    "@babel/helper-plugin-utils" "^7.10.4"
+    "@babel/helper-plugin-utils" "^7.14.5"
     "@babel/plugin-syntax-export-namespace-from" "^7.8.3"
 
-"@babel/plugin-proposal-json-strings@^7.12.1":
-  version "7.12.1"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.12.1.tgz#d45423b517714eedd5621a9dfdc03fa9f4eb241c"
-  integrity sha512-GoLDUi6U9ZLzlSda2Df++VSqDJg3CG+dR0+iWsv6XRw1rEq+zwt4DirM9yrxW6XWaTpmai1cWJLMfM8qQJf+yw==
+"@babel/plugin-proposal-json-strings@^7.14.5":
+  version "7.14.5"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.14.5.tgz#38de60db362e83a3d8c944ac858ddf9f0c2239eb"
+  integrity sha512-NSq2fczJYKVRIsUJyNxrVUMhB27zb7N7pOFGQOhBKJrChbGcgEAqyZrmZswkPk18VMurEeJAaICbfm57vUeTbQ==
   dependencies:
-    "@babel/helper-plugin-utils" "^7.10.4"
-    "@babel/plugin-syntax-json-strings" "^7.8.0"
+    "@babel/helper-plugin-utils" "^7.14.5"
+    "@babel/plugin-syntax-json-strings" "^7.8.3"
 
-"@babel/plugin-proposal-logical-assignment-operators@^7.12.1":
-  version "7.12.1"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.12.1.tgz#f2c490d36e1b3c9659241034a5d2cd50263a2751"
-  integrity sha512-k8ZmVv0JU+4gcUGeCDZOGd0lCIamU/sMtIiX3UWnUc5yzgq6YUGyEolNYD+MLYKfSzgECPcqetVcJP9Afe/aCA==
+"@babel/plugin-proposal-logical-assignment-operators@^7.14.5":
+  version "7.14.5"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.14.5.tgz#6e6229c2a99b02ab2915f82571e0cc646a40c738"
+  integrity sha512-YGn2AvZAo9TwyhlLvCCWxD90Xq8xJ4aSgaX3G5D/8DW94L8aaT+dS5cSP+Z06+rCJERGSr9GxMBZ601xoc2taw==
   dependencies:
-    "@babel/helper-plugin-utils" "^7.10.4"
+    "@babel/helper-plugin-utils" "^7.14.5"
     "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4"
 
-"@babel/plugin-proposal-nullish-coalescing-operator@^7.12.1":
-  version "7.12.1"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.12.1.tgz#3ed4fff31c015e7f3f1467f190dbe545cd7b046c"
-  integrity sha512-nZY0ESiaQDI1y96+jk6VxMOaL4LPo/QDHBqL+SF3/vl6dHkTwHlOI8L4ZwuRBHgakRBw5zsVylel7QPbbGuYgg==
+"@babel/plugin-proposal-nullish-coalescing-operator@^7.13.8", "@babel/plugin-proposal-nullish-coalescing-operator@^7.14.5":
+  version "7.14.5"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.14.5.tgz#ee38589ce00e2cc59b299ec3ea406fcd3a0fdaf6"
+  integrity sha512-gun/SOnMqjSb98Nkaq2rTKMwervfdAoz6NphdY0vTfuzMfryj+tDGb2n6UkDKwez+Y8PZDhE3D143v6Gepp4Hg==
   dependencies:
-    "@babel/helper-plugin-utils" "^7.10.4"
-    "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0"
+    "@babel/helper-plugin-utils" "^7.14.5"
+    "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3"
 
-"@babel/plugin-proposal-numeric-separator@^7.12.7":
-  version "7.12.7"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.12.7.tgz#8bf253de8139099fea193b297d23a9d406ef056b"
-  integrity sha512-8c+uy0qmnRTeukiGsjLGy6uVs/TFjJchGXUeBqlG4VWYOdJWkhhVPdQ3uHwbmalfJwv2JsV0qffXP4asRfL2SQ==
+"@babel/plugin-proposal-numeric-separator@^7.14.5":
+  version "7.14.5"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.14.5.tgz#83631bf33d9a51df184c2102a069ac0c58c05f18"
+  integrity sha512-yiclALKe0vyZRZE0pS6RXgjUOt87GWv6FYa5zqj15PvhOGFO69R5DusPlgK/1K5dVnCtegTiWu9UaBSrLLJJBg==
   dependencies:
-    "@babel/helper-plugin-utils" "^7.10.4"
+    "@babel/helper-plugin-utils" "^7.14.5"
     "@babel/plugin-syntax-numeric-separator" "^7.10.4"
 
-"@babel/plugin-proposal-object-rest-spread@^7.12.1":
-  version "7.12.1"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.12.1.tgz#def9bd03cea0f9b72283dac0ec22d289c7691069"
-  integrity sha512-s6SowJIjzlhx8o7lsFx5zmY4At6CTtDvgNQDdPzkBQucle58A6b/TTeEBYtyDgmcXjUTM+vE8YOGHZzzbc/ioA==
+"@babel/plugin-proposal-object-rest-spread@^7.14.7":
+  version "7.14.7"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.14.7.tgz#5920a2b3df7f7901df0205974c0641b13fd9d363"
+  integrity sha512-082hsZz+sVabfmDWo1Oct1u1AgbKbUAyVgmX4otIc7bdsRgHBXwTwb3DpDmD4Eyyx6DNiuz5UAATT655k+kL5g==
   dependencies:
-    "@babel/helper-plugin-utils" "^7.10.4"
-    "@babel/plugin-syntax-object-rest-spread" "^7.8.0"
-    "@babel/plugin-transform-parameters" "^7.12.1"
+    "@babel/compat-data" "^7.14.7"
+    "@babel/helper-compilation-targets" "^7.14.5"
+    "@babel/helper-plugin-utils" "^7.14.5"
+    "@babel/plugin-syntax-object-rest-spread" "^7.8.3"
+    "@babel/plugin-transform-parameters" "^7.14.5"
 
-"@babel/plugin-proposal-optional-catch-binding@^7.12.1":
-  version "7.12.1"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.12.1.tgz#ccc2421af64d3aae50b558a71cede929a5ab2942"
-  integrity sha512-hFvIjgprh9mMw5v42sJWLI1lzU5L2sznP805zeT6rySVRA0Y18StRhDqhSxlap0oVgItRsB6WSROp4YnJTJz0g==
+"@babel/plugin-proposal-optional-catch-binding@^7.14.5":
+  version "7.14.5"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.14.5.tgz#939dd6eddeff3a67fdf7b3f044b5347262598c3c"
+  integrity sha512-3Oyiixm0ur7bzO5ybNcZFlmVsygSIQgdOa7cTfOYCMY+wEPAYhZAJxi3mixKFCTCKUhQXuCTtQ1MzrpL3WT8ZQ==
   dependencies:
-    "@babel/helper-plugin-utils" "^7.10.4"
-    "@babel/plugin-syntax-optional-catch-binding" "^7.8.0"
+    "@babel/helper-plugin-utils" "^7.14.5"
+    "@babel/plugin-syntax-optional-catch-binding" "^7.8.3"
 
-"@babel/plugin-proposal-optional-chaining@^7.12.7":
-  version "7.12.7"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.12.7.tgz#e02f0ea1b5dc59d401ec16fb824679f683d3303c"
-  integrity sha512-4ovylXZ0PWmwoOvhU2vhnzVNnm88/Sm9nx7V8BPgMvAzn5zDou3/Awy0EjglyubVHasJj+XCEkr/r1X3P5elCA==
+"@babel/plugin-proposal-optional-chaining@^7.13.12", "@babel/plugin-proposal-optional-chaining@^7.14.5":
+  version "7.14.5"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.14.5.tgz#fa83651e60a360e3f13797eef00b8d519695b603"
+  integrity sha512-ycz+VOzo2UbWNI1rQXxIuMOzrDdHGrI23fRiz/Si2R4kv2XZQ1BK8ccdHwehMKBlcH/joGW/tzrUmo67gbJHlQ==
   dependencies:
-    "@babel/helper-plugin-utils" "^7.10.4"
-    "@babel/helper-skip-transparent-expression-wrappers" "^7.12.1"
-    "@babel/plugin-syntax-optional-chaining" "^7.8.0"
+    "@babel/helper-plugin-utils" "^7.14.5"
+    "@babel/helper-skip-transparent-expression-wrappers" "^7.14.5"
+    "@babel/plugin-syntax-optional-chaining" "^7.8.3"
 
-"@babel/plugin-proposal-private-methods@^7.12.1":
-  version "7.12.1"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.12.1.tgz#86814f6e7a21374c980c10d38b4493e703f4a389"
-  integrity sha512-mwZ1phvH7/NHK6Kf8LP7MYDogGV+DKB1mryFOEwx5EBNQrosvIczzZFTUmWaeujd5xT6G1ELYWUz3CutMhjE1w==
+"@babel/plugin-proposal-private-methods@^7.13.0", "@babel/plugin-proposal-private-methods@^7.14.5":
+  version "7.14.5"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.14.5.tgz#37446495996b2945f30f5be5b60d5e2aa4f5792d"
+  integrity sha512-838DkdUA1u+QTCplatfq4B7+1lnDa/+QMI89x5WZHBcnNv+47N8QEj2k9I2MUU9xIv8XJ4XvPCviM/Dj7Uwt9g==
   dependencies:
-    "@babel/helper-create-class-features-plugin" "^7.12.1"
-    "@babel/helper-plugin-utils" "^7.10.4"
+    "@babel/helper-create-class-features-plugin" "^7.14.5"
+    "@babel/helper-plugin-utils" "^7.14.5"
 
-"@babel/plugin-proposal-unicode-property-regex@^7.12.1", "@babel/plugin-proposal-unicode-property-regex@^7.4.4":
-  version "7.12.1"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.12.1.tgz#2a183958d417765b9eae334f47758e5d6a82e072"
-  integrity sha512-MYq+l+PvHuw/rKUz1at/vb6nCnQ2gmJBNaM62z0OgH7B2W1D9pvkpYtlti9bGtizNIU1K3zm4bZF9F91efVY0w==
+"@babel/plugin-proposal-private-property-in-object@^7.15.4":
+  version "7.15.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.15.4.tgz#55c5e3b4d0261fd44fe637e3f624cfb0f484e3e5"
+  integrity sha512-X0UTixkLf0PCCffxgu5/1RQyGGbgZuKoI+vXP4iSbJSYwPb7hu06omsFGBvQ9lJEvwgrxHdS8B5nbfcd8GyUNA==
   dependencies:
-    "@babel/helper-create-regexp-features-plugin" "^7.12.1"
-    "@babel/helper-plugin-utils" "^7.10.4"
+    "@babel/helper-annotate-as-pure" "^7.15.4"
+    "@babel/helper-create-class-features-plugin" "^7.15.4"
+    "@babel/helper-plugin-utils" "^7.14.5"
+    "@babel/plugin-syntax-private-property-in-object" "^7.14.5"
+
+"@babel/plugin-proposal-unicode-property-regex@^7.14.5", "@babel/plugin-proposal-unicode-property-regex@^7.4.4":
+  version "7.14.5"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.14.5.tgz#0f95ee0e757a5d647f378daa0eca7e93faa8bbe8"
+  integrity sha512-6axIeOU5LnY471KenAB9vI8I5j7NQ2d652hIYwVyRfgaZT5UpiqFKCuVXCDMSrU+3VFafnu2c5m3lrWIlr6A5Q==
+  dependencies:
+    "@babel/helper-create-regexp-features-plugin" "^7.14.5"
+    "@babel/helper-plugin-utils" "^7.14.5"
 
-"@babel/plugin-syntax-async-generators@^7.8.0", "@babel/plugin-syntax-async-generators@^7.8.4":
+"@babel/plugin-syntax-async-generators@^7.8.4":
   version "7.8.4"
   resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d"
   integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==
@@ -381,21 +432,28 @@
   dependencies:
     "@babel/helper-plugin-utils" "^7.8.0"
 
-"@babel/plugin-syntax-class-properties@^7.12.1", "@babel/plugin-syntax-class-properties@^7.8.3":
-  version "7.12.1"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.1.tgz#bcb297c5366e79bebadef509549cd93b04f19978"
-  integrity sha512-U40A76x5gTwmESz+qiqssqmeEsKvcSyvtgktrm0uzcARAmM9I1jR221f6Oq+GmHrcD+LvZDag1UTOTe2fL3TeA==
+"@babel/plugin-syntax-class-properties@^7.12.13", "@babel/plugin-syntax-class-properties@^7.8.3":
+  version "7.12.13"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10"
+  integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==
   dependencies:
-    "@babel/helper-plugin-utils" "^7.10.4"
+    "@babel/helper-plugin-utils" "^7.12.13"
 
-"@babel/plugin-syntax-decorators@^7.12.1":
-  version "7.12.1"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.12.1.tgz#81a8b535b284476c41be6de06853a8802b98c5dd"
-  integrity sha512-ir9YW5daRrTYiy9UJ2TzdNIJEZu8KclVzDcfSt4iEmOtwQ4llPtWInNKJyKnVXp1vE4bbVd5S31M/im3mYMO1w==
+"@babel/plugin-syntax-class-static-block@^7.14.5":
+  version "7.14.5"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz#195df89b146b4b78b3bf897fd7a257c84659d406"
+  integrity sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==
   dependencies:
-    "@babel/helper-plugin-utils" "^7.10.4"
+    "@babel/helper-plugin-utils" "^7.14.5"
+
+"@babel/plugin-syntax-decorators@^7.14.5":
+  version "7.14.5"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.14.5.tgz#eafb9c0cbe09c8afeb964ba3a7bbd63945a72f20"
+  integrity sha512-c4sZMRWL4GSvP1EXy0woIP7m4jkVcEuG8R1TOZxPBPtp4FSM/kiPZub9UIs/Jrb5ZAOzvTUSGYrWsrSu1JvoPw==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.14.5"
 
-"@babel/plugin-syntax-dynamic-import@^7.8.0":
+"@babel/plugin-syntax-dynamic-import@^7.8.3":
   version "7.8.3"
   resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3"
   integrity sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==
@@ -409,13 +467,6 @@
   dependencies:
     "@babel/helper-plugin-utils" "^7.8.3"
 
-"@babel/plugin-syntax-flow@^7.12.1":
-  version "7.12.1"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.12.1.tgz#a77670d9abe6d63e8acadf4c31bb1eb5a506bbdd"
-  integrity sha512-1lBLLmtxrwpm4VKmtVFselI/P3pX+G63fAtUUt6b2Nzgao77KNDwyuRt90Mj2/9pKobtt68FdvjfqohZjg/FCA==
-  dependencies:
-    "@babel/helper-plugin-utils" "^7.10.4"
-
 "@babel/plugin-syntax-import-meta@^7.8.3":
   version "7.10.4"
   resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51"
@@ -423,19 +474,19 @@
   dependencies:
     "@babel/helper-plugin-utils" "^7.10.4"
 
-"@babel/plugin-syntax-json-strings@^7.8.0", "@babel/plugin-syntax-json-strings@^7.8.3":
+"@babel/plugin-syntax-json-strings@^7.8.3":
   version "7.8.3"
   resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a"
   integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==
   dependencies:
     "@babel/helper-plugin-utils" "^7.8.0"
 
-"@babel/plugin-syntax-jsx@^7.12.1", "@babel/plugin-syntax-jsx@^7.2.0":
-  version "7.12.1"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.12.1.tgz#9d9d357cc818aa7ae7935917c1257f67677a0926"
-  integrity sha512-1yRi7yAtB0ETgxdY9ti/p2TivUxJkTdhu/ZbF9MshVGqOx1TdB3b7xCXs49Fupgg50N45KcAsRP/ZqWjs9SRjg==
+"@babel/plugin-syntax-jsx@^7.2.0":
+  version "7.14.5"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.14.5.tgz#000e2e25d8673cce49300517a3eda44c263e4201"
+  integrity sha512-ohuFIsOMXJnbOMRfX7/w7LocdR6R7whhuRD4ax8IipLcLPlZGJKkBxgHp++U4N/vKyU16/YDQr2f5seajD3jIw==
   dependencies:
-    "@babel/helper-plugin-utils" "^7.10.4"
+    "@babel/helper-plugin-utils" "^7.14.5"
 
 "@babel/plugin-syntax-logical-assignment-operators@^7.10.4", "@babel/plugin-syntax-logical-assignment-operators@^7.8.3":
   version "7.10.4"
@@ -444,7 +495,7 @@
   dependencies:
     "@babel/helper-plugin-utils" "^7.10.4"
 
-"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.0", "@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3":
+"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3":
   version "7.8.3"
   resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9"
   integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==
@@ -458,384 +509,381 @@
   dependencies:
     "@babel/helper-plugin-utils" "^7.10.4"
 
-"@babel/plugin-syntax-object-rest-spread@^7.8.0", "@babel/plugin-syntax-object-rest-spread@^7.8.3":
+"@babel/plugin-syntax-object-rest-spread@^7.8.3":
   version "7.8.3"
   resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871"
   integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==
   dependencies:
     "@babel/helper-plugin-utils" "^7.8.0"
 
-"@babel/plugin-syntax-optional-catch-binding@^7.8.0", "@babel/plugin-syntax-optional-catch-binding@^7.8.3":
+"@babel/plugin-syntax-optional-catch-binding@^7.8.3":
   version "7.8.3"
   resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1"
   integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==
   dependencies:
     "@babel/helper-plugin-utils" "^7.8.0"
 
-"@babel/plugin-syntax-optional-chaining@^7.8.0", "@babel/plugin-syntax-optional-chaining@^7.8.3":
+"@babel/plugin-syntax-optional-chaining@^7.8.3":
   version "7.8.3"
   resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a"
   integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==
   dependencies:
     "@babel/helper-plugin-utils" "^7.8.0"
 
-"@babel/plugin-syntax-top-level-await@^7.12.1", "@babel/plugin-syntax-top-level-await@^7.8.3":
-  version "7.12.1"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.12.1.tgz#dd6c0b357ac1bb142d98537450a319625d13d2a0"
-  integrity sha512-i7ooMZFS+a/Om0crxZodrTzNEPJHZrlMVGMTEpFAj6rYY/bKCddB0Dk/YxfPuYXOopuhKk/e1jV6h+WUU9XN3A==
+"@babel/plugin-syntax-private-property-in-object@^7.14.5":
+  version "7.14.5"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz#0dc6671ec0ea22b6e94a1114f857970cd39de1ad"
+  integrity sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==
   dependencies:
-    "@babel/helper-plugin-utils" "^7.10.4"
+    "@babel/helper-plugin-utils" "^7.14.5"
 
-"@babel/plugin-transform-arrow-functions@^7.12.1":
-  version "7.12.1"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.12.1.tgz#8083ffc86ac8e777fbe24b5967c4b2521f3cb2b3"
-  integrity sha512-5QB50qyN44fzzz4/qxDPQMBCTHgxg3n0xRBLJUmBlLoU/sFvxVWGZF/ZUfMVDQuJUKXaBhbupxIzIfZ6Fwk/0A==
+"@babel/plugin-syntax-top-level-await@^7.14.5", "@babel/plugin-syntax-top-level-await@^7.8.3":
+  version "7.14.5"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c"
+  integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==
   dependencies:
-    "@babel/helper-plugin-utils" "^7.10.4"
+    "@babel/helper-plugin-utils" "^7.14.5"
 
-"@babel/plugin-transform-async-to-generator@^7.12.1":
-  version "7.12.1"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.12.1.tgz#3849a49cc2a22e9743cbd6b52926d30337229af1"
-  integrity sha512-SDtqoEcarK1DFlRJ1hHRY5HvJUj5kX4qmtpMAm2QnhOlyuMC4TMdCRgW6WXpv93rZeYNeLP22y8Aq2dbcDRM1A==
+"@babel/plugin-transform-arrow-functions@^7.14.5":
+  version "7.14.5"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.14.5.tgz#f7187d9588a768dd080bf4c9ffe117ea62f7862a"
+  integrity sha512-KOnO0l4+tD5IfOdi4x8C1XmEIRWUjNRV8wc6K2vz/3e8yAOoZZvsRXRRIF/yo/MAOFb4QjtAw9xSxMXbSMRy8A==
   dependencies:
-    "@babel/helper-module-imports" "^7.12.1"
-    "@babel/helper-plugin-utils" "^7.10.4"
-    "@babel/helper-remap-async-to-generator" "^7.12.1"
+    "@babel/helper-plugin-utils" "^7.14.5"
 
-"@babel/plugin-transform-block-scoped-functions@^7.12.1":
-  version "7.12.1"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.12.1.tgz#f2a1a365bde2b7112e0a6ded9067fdd7c07905d9"
-  integrity sha512-5OpxfuYnSgPalRpo8EWGPzIYf0lHBWORCkj5M0oLBwHdlux9Ri36QqGW3/LR13RSVOAoUUMzoPI/jpE4ABcHoA==
+"@babel/plugin-transform-async-to-generator@^7.14.5":
+  version "7.14.5"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.14.5.tgz#72c789084d8f2094acb945633943ef8443d39e67"
+  integrity sha512-szkbzQ0mNk0rpu76fzDdqSyPu0MuvpXgC+6rz5rpMb5OIRxdmHfQxrktL8CYolL2d8luMCZTR0DpIMIdL27IjA==
   dependencies:
-    "@babel/helper-plugin-utils" "^7.10.4"
+    "@babel/helper-module-imports" "^7.14.5"
+    "@babel/helper-plugin-utils" "^7.14.5"
+    "@babel/helper-remap-async-to-generator" "^7.14.5"
 
-"@babel/plugin-transform-block-scoping@^7.12.11":
-  version "7.12.12"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.12.12.tgz#d93a567a152c22aea3b1929bb118d1d0a175cdca"
-  integrity sha512-VOEPQ/ExOVqbukuP7BYJtI5ZxxsmegTwzZ04j1aF0dkSypGo9XpDHuOrABsJu+ie+penpSJheDJ11x1BEZNiyQ==
+"@babel/plugin-transform-block-scoped-functions@^7.14.5":
+  version "7.14.5"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.14.5.tgz#e48641d999d4bc157a67ef336aeb54bc44fd3ad4"
+  integrity sha512-dtqWqdWZ5NqBX3KzsVCWfQI3A53Ft5pWFCT2eCVUftWZgjc5DpDponbIF1+c+7cSGk2wN0YK7HGL/ezfRbpKBQ==
   dependencies:
-    "@babel/helper-plugin-utils" "^7.10.4"
+    "@babel/helper-plugin-utils" "^7.14.5"
 
-"@babel/plugin-transform-classes@^7.12.1":
-  version "7.12.1"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.12.1.tgz#65e650fcaddd3d88ddce67c0f834a3d436a32db6"
-  integrity sha512-/74xkA7bVdzQTBeSUhLLJgYIcxw/dpEpCdRDiHgPJ3Mv6uC11UhjpOhl72CgqbBCmt1qtssCyB2xnJm1+PFjog==
+"@babel/plugin-transform-block-scoping@^7.15.3":
+  version "7.15.3"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.15.3.tgz#94c81a6e2fc230bcce6ef537ac96a1e4d2b3afaf"
+  integrity sha512-nBAzfZwZb4DkaGtOes1Up1nOAp9TDRRFw4XBzBBSG9QK7KVFmYzgj9o9sbPv7TX5ofL4Auq4wZnxCoPnI/lz2Q==
   dependencies:
-    "@babel/helper-annotate-as-pure" "^7.10.4"
-    "@babel/helper-define-map" "^7.10.4"
-    "@babel/helper-function-name" "^7.10.4"
-    "@babel/helper-optimise-call-expression" "^7.10.4"
-    "@babel/helper-plugin-utils" "^7.10.4"
-    "@babel/helper-replace-supers" "^7.12.1"
-    "@babel/helper-split-export-declaration" "^7.10.4"
-    globals "^11.1.0"
+    "@babel/helper-plugin-utils" "^7.14.5"
 
-"@babel/plugin-transform-computed-properties@^7.12.1":
-  version "7.12.1"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.12.1.tgz#d68cf6c9b7f838a8a4144badbe97541ea0904852"
-  integrity sha512-vVUOYpPWB7BkgUWPo4C44mUQHpTZXakEqFjbv8rQMg7TC6S6ZhGZ3otQcRH6u7+adSlE5i0sp63eMC/XGffrzg==
+"@babel/plugin-transform-classes@^7.15.4":
+  version "7.15.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.15.4.tgz#50aee17aaf7f332ae44e3bce4c2e10534d5d3bf1"
+  integrity sha512-Yjvhex8GzBmmPQUvpXRPWQ9WnxXgAFuZSrqOK/eJlOGIXwvv8H3UEdUigl1gb/bnjTrln+e8bkZUYCBt/xYlBg==
   dependencies:
-    "@babel/helper-plugin-utils" "^7.10.4"
+    "@babel/helper-annotate-as-pure" "^7.15.4"
+    "@babel/helper-function-name" "^7.15.4"
+    "@babel/helper-optimise-call-expression" "^7.15.4"
+    "@babel/helper-plugin-utils" "^7.14.5"
+    "@babel/helper-replace-supers" "^7.15.4"
+    "@babel/helper-split-export-declaration" "^7.15.4"
+    globals "^11.1.0"
 
-"@babel/plugin-transform-destructuring@^7.12.1":
-  version "7.12.1"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.12.1.tgz#b9a570fe0d0a8d460116413cb4f97e8e08b2f847"
-  integrity sha512-fRMYFKuzi/rSiYb2uRLiUENJOKq4Gnl+6qOv5f8z0TZXg3llUwUhsNNwrwaT/6dUhJTzNpBr+CUvEWBtfNY1cw==
+"@babel/plugin-transform-computed-properties@^7.14.5":
+  version "7.14.5"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.14.5.tgz#1b9d78987420d11223d41195461cc43b974b204f"
+  integrity sha512-pWM+E4283UxaVzLb8UBXv4EIxMovU4zxT1OPnpHJcmnvyY9QbPPTKZfEj31EUvG3/EQRbYAGaYEUZ4yWOBC2xg==
   dependencies:
-    "@babel/helper-plugin-utils" "^7.10.4"
+    "@babel/helper-plugin-utils" "^7.14.5"
 
-"@babel/plugin-transform-dotall-regex@^7.12.1", "@babel/plugin-transform-dotall-regex@^7.4.4":
-  version "7.12.1"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.12.1.tgz#a1d16c14862817b6409c0a678d6f9373ca9cd975"
-  integrity sha512-B2pXeRKoLszfEW7J4Hg9LoFaWEbr/kzo3teWHmtFCszjRNa/b40f9mfeqZsIDLLt/FjwQ6pz/Gdlwy85xNckBA==
+"@babel/plugin-transform-destructuring@^7.14.7":
+  version "7.14.7"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.14.7.tgz#0ad58ed37e23e22084d109f185260835e5557576"
+  integrity sha512-0mDE99nK+kVh3xlc5vKwB6wnP9ecuSj+zQCa/n0voENtP/zymdT4HH6QEb65wjjcbqr1Jb/7z9Qp7TF5FtwYGw==
   dependencies:
-    "@babel/helper-create-regexp-features-plugin" "^7.12.1"
-    "@babel/helper-plugin-utils" "^7.10.4"
+    "@babel/helper-plugin-utils" "^7.14.5"
 
-"@babel/plugin-transform-duplicate-keys@^7.12.1":
-  version "7.12.1"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.12.1.tgz#745661baba295ac06e686822797a69fbaa2ca228"
-  integrity sha512-iRght0T0HztAb/CazveUpUQrZY+aGKKaWXMJ4uf9YJtqxSUe09j3wteztCUDRHs+SRAL7yMuFqUsLoAKKzgXjw==
+"@babel/plugin-transform-dotall-regex@^7.14.5", "@babel/plugin-transform-dotall-regex@^7.4.4":
+  version "7.14.5"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.14.5.tgz#2f6bf76e46bdf8043b4e7e16cf24532629ba0c7a"
+  integrity sha512-loGlnBdj02MDsFaHhAIJzh7euK89lBrGIdM9EAtHFo6xKygCUGuuWe07o1oZVk287amtW1n0808sQM99aZt3gw==
   dependencies:
-    "@babel/helper-plugin-utils" "^7.10.4"
+    "@babel/helper-create-regexp-features-plugin" "^7.14.5"
+    "@babel/helper-plugin-utils" "^7.14.5"
 
-"@babel/plugin-transform-exponentiation-operator@^7.12.1":
-  version "7.12.1"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.12.1.tgz#b0f2ed356ba1be1428ecaf128ff8a24f02830ae0"
-  integrity sha512-7tqwy2bv48q+c1EHbXK0Zx3KXd2RVQp6OC7PbwFNt/dPTAV3Lu5sWtWuAj8owr5wqtWnqHfl2/mJlUmqkChKug==
+"@babel/plugin-transform-duplicate-keys@^7.14.5":
+  version "7.14.5"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.14.5.tgz#365a4844881bdf1501e3a9f0270e7f0f91177954"
+  integrity sha512-iJjbI53huKbPDAsJ8EmVmvCKeeq21bAze4fu9GBQtSLqfvzj2oRuHVx4ZkDwEhg1htQ+5OBZh/Ab0XDf5iBZ7A==
   dependencies:
-    "@babel/helper-builder-binary-assignment-operator-visitor" "^7.10.4"
-    "@babel/helper-plugin-utils" "^7.10.4"
+    "@babel/helper-plugin-utils" "^7.14.5"
 
-"@babel/plugin-transform-flow-strip-types@^7.4.4":
-  version "7.12.10"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.12.10.tgz#d85e30ecfa68093825773b7b857e5085bbd32c95"
-  integrity sha512-0ti12wLTLeUIzu9U7kjqIn4MyOL7+Wibc7avsHhj4o1l5C0ATs8p2IMHrVYjm9t9wzhfEO6S3kxax0Rpdo8LTg==
+"@babel/plugin-transform-exponentiation-operator@^7.14.5":
+  version "7.14.5"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.14.5.tgz#5154b8dd6a3dfe6d90923d61724bd3deeb90b493"
+  integrity sha512-jFazJhMBc9D27o9jDnIE5ZErI0R0m7PbKXVq77FFvqFbzvTMuv8jaAwLZ5PviOLSFttqKIW0/wxNSDbjLk0tYA==
   dependencies:
-    "@babel/helper-plugin-utils" "^7.10.4"
-    "@babel/plugin-syntax-flow" "^7.12.1"
+    "@babel/helper-builder-binary-assignment-operator-visitor" "^7.14.5"
+    "@babel/helper-plugin-utils" "^7.14.5"
 
-"@babel/plugin-transform-for-of@^7.12.1":
-  version "7.12.1"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.12.1.tgz#07640f28867ed16f9511c99c888291f560921cfa"
-  integrity sha512-Zaeq10naAsuHo7heQvyV0ptj4dlZJwZgNAtBYBnu5nNKJoW62m0zKcIEyVECrUKErkUkg6ajMy4ZfnVZciSBhg==
+"@babel/plugin-transform-for-of@^7.15.4":
+  version "7.15.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.15.4.tgz#25c62cce2718cfb29715f416e75d5263fb36a8c2"
+  integrity sha512-DRTY9fA751AFBDh2oxydvVm4SYevs5ILTWLs6xKXps4Re/KG5nfUkr+TdHCrRWB8C69TlzVgA9b3RmGWmgN9LA==
   dependencies:
-    "@babel/helper-plugin-utils" "^7.10.4"
+    "@babel/helper-plugin-utils" "^7.14.5"
 
-"@babel/plugin-transform-function-name@^7.12.1":
-  version "7.12.1"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.12.1.tgz#2ec76258c70fe08c6d7da154003a480620eba667"
-  integrity sha512-JF3UgJUILoFrFMEnOJLJkRHSk6LUSXLmEFsA23aR2O5CSLUxbeUX1IZ1YQ7Sn0aXb601Ncwjx73a+FVqgcljVw==
+"@babel/plugin-transform-function-name@^7.14.5":
+  version "7.14.5"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.14.5.tgz#e81c65ecb900746d7f31802f6bed1f52d915d6f2"
+  integrity sha512-vbO6kv0fIzZ1GpmGQuvbwwm+O4Cbm2NrPzwlup9+/3fdkuzo1YqOZcXw26+YUJB84Ja7j9yURWposEHLYwxUfQ==
   dependencies:
-    "@babel/helper-function-name" "^7.10.4"
-    "@babel/helper-plugin-utils" "^7.10.4"
+    "@babel/helper-function-name" "^7.14.5"
+    "@babel/helper-plugin-utils" "^7.14.5"
 
-"@babel/plugin-transform-literals@^7.12.1":
-  version "7.12.1"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.12.1.tgz#d73b803a26b37017ddf9d3bb8f4dc58bfb806f57"
-  integrity sha512-+PxVGA+2Ag6uGgL0A5f+9rklOnnMccwEBzwYFL3EUaKuiyVnUipyXncFcfjSkbimLrODoqki1U9XxZzTvfN7IQ==
+"@babel/plugin-transform-literals@^7.14.5":
+  version "7.14.5"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.14.5.tgz#41d06c7ff5d4d09e3cf4587bd3ecf3930c730f78"
+  integrity sha512-ql33+epql2F49bi8aHXxvLURHkxJbSmMKl9J5yHqg4PLtdE6Uc48CH1GS6TQvZ86eoB/ApZXwm7jlA+B3kra7A==
   dependencies:
-    "@babel/helper-plugin-utils" "^7.10.4"
+    "@babel/helper-plugin-utils" "^7.14.5"
 
-"@babel/plugin-transform-member-expression-literals@^7.12.1":
-  version "7.12.1"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.12.1.tgz#496038602daf1514a64d43d8e17cbb2755e0c3ad"
-  integrity sha512-1sxePl6z9ad0gFMB9KqmYofk34flq62aqMt9NqliS/7hPEpURUCMbyHXrMPlo282iY7nAvUB1aQd5mg79UD9Jg==
+"@babel/plugin-transform-member-expression-literals@^7.14.5":
+  version "7.14.5"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.14.5.tgz#b39cd5212a2bf235a617d320ec2b48bcc091b8a7"
+  integrity sha512-WkNXxH1VXVTKarWFqmso83xl+2V3Eo28YY5utIkbsmXoItO8Q3aZxN4BTS2k0hz9dGUloHK26mJMyQEYfkn/+Q==
   dependencies:
-    "@babel/helper-plugin-utils" "^7.10.4"
+    "@babel/helper-plugin-utils" "^7.14.5"
 
-"@babel/plugin-transform-modules-amd@^7.12.1":
-  version "7.12.1"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.12.1.tgz#3154300b026185666eebb0c0ed7f8415fefcf6f9"
-  integrity sha512-tDW8hMkzad5oDtzsB70HIQQRBiTKrhfgwC/KkJeGsaNFTdWhKNt/BiE8c5yj19XiGyrxpbkOfH87qkNg1YGlOQ==
+"@babel/plugin-transform-modules-amd@^7.14.5":
+  version "7.14.5"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.14.5.tgz#4fd9ce7e3411cb8b83848480b7041d83004858f7"
+  integrity sha512-3lpOU8Vxmp3roC4vzFpSdEpGUWSMsHFreTWOMMLzel2gNGfHE5UWIh/LN6ghHs2xurUp4jRFYMUIZhuFbody1g==
   dependencies:
-    "@babel/helper-module-transforms" "^7.12.1"
-    "@babel/helper-plugin-utils" "^7.10.4"
+    "@babel/helper-module-transforms" "^7.14.5"
+    "@babel/helper-plugin-utils" "^7.14.5"
     babel-plugin-dynamic-import-node "^2.3.3"
 
-"@babel/plugin-transform-modules-commonjs@^7.12.1", "@babel/plugin-transform-modules-commonjs@^7.4.4":
-  version "7.12.1"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.12.1.tgz#fa403124542636c786cf9b460a0ffbb48a86e648"
-  integrity sha512-dY789wq6l0uLY8py9c1B48V8mVL5gZh/+PQ5ZPrylPYsnAvnEMjqsUXkuoDVPeVK+0VyGar+D08107LzDQ6pag==
+"@babel/plugin-transform-modules-commonjs@^7.15.4":
+  version "7.15.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.15.4.tgz#8201101240eabb5a76c08ef61b2954f767b6b4c1"
+  integrity sha512-qg4DPhwG8hKp4BbVDvX1s8cohM8a6Bvptu4l6Iingq5rW+yRUAhe/YRup/YcW2zCOlrysEWVhftIcKzrEZv3sA==
   dependencies:
-    "@babel/helper-module-transforms" "^7.12.1"
-    "@babel/helper-plugin-utils" "^7.10.4"
-    "@babel/helper-simple-access" "^7.12.1"
+    "@babel/helper-module-transforms" "^7.15.4"
+    "@babel/helper-plugin-utils" "^7.14.5"
+    "@babel/helper-simple-access" "^7.15.4"
     babel-plugin-dynamic-import-node "^2.3.3"
 
-"@babel/plugin-transform-modules-systemjs@^7.12.1":
-  version "7.12.1"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.12.1.tgz#663fea620d593c93f214a464cd399bf6dc683086"
-  integrity sha512-Hn7cVvOavVh8yvW6fLwveFqSnd7rbQN3zJvoPNyNaQSvgfKmDBO9U1YL9+PCXGRlZD9tNdWTy5ACKqMuzyn32Q==
+"@babel/plugin-transform-modules-systemjs@^7.15.4":
+  version "7.15.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.15.4.tgz#b42890c7349a78c827719f1d2d0cd38c7d268132"
+  integrity sha512-fJUnlQrl/mezMneR72CKCgtOoahqGJNVKpompKwzv3BrEXdlPspTcyxrZ1XmDTIr9PpULrgEQo3qNKp6dW7ssw==
   dependencies:
-    "@babel/helper-hoist-variables" "^7.10.4"
-    "@babel/helper-module-transforms" "^7.12.1"
-    "@babel/helper-plugin-utils" "^7.10.4"
-    "@babel/helper-validator-identifier" "^7.10.4"
+    "@babel/helper-hoist-variables" "^7.15.4"
+    "@babel/helper-module-transforms" "^7.15.4"
+    "@babel/helper-plugin-utils" "^7.14.5"
+    "@babel/helper-validator-identifier" "^7.14.9"
     babel-plugin-dynamic-import-node "^2.3.3"
 
-"@babel/plugin-transform-modules-umd@^7.12.1":
-  version "7.12.1"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.12.1.tgz#eb5a218d6b1c68f3d6217b8fa2cc82fec6547902"
-  integrity sha512-aEIubCS0KHKM0zUos5fIoQm+AZUMt1ZvMpqz0/H5qAQ7vWylr9+PLYurT+Ic7ID/bKLd4q8hDovaG3Zch2uz5Q==
-  dependencies:
-    "@babel/helper-module-transforms" "^7.12.1"
-    "@babel/helper-plugin-utils" "^7.10.4"
-
-"@babel/plugin-transform-named-capturing-groups-regex@^7.12.1":
-  version "7.12.1"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.12.1.tgz#b407f5c96be0d9f5f88467497fa82b30ac3e8753"
-  integrity sha512-tB43uQ62RHcoDp9v2Nsf+dSM8sbNodbEicbQNA53zHz8pWUhsgHSJCGpt7daXxRydjb0KnfmB+ChXOv3oADp1Q==
+"@babel/plugin-transform-modules-umd@^7.14.5":
+  version "7.14.5"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.14.5.tgz#fb662dfee697cce274a7cda525190a79096aa6e0"
+  integrity sha512-RfPGoagSngC06LsGUYyM9QWSXZ8MysEjDJTAea1lqRjNECE3y0qIJF/qbvJxc4oA4s99HumIMdXOrd+TdKaAAA==
   dependencies:
-    "@babel/helper-create-regexp-features-plugin" "^7.12.1"
+    "@babel/helper-module-transforms" "^7.14.5"
+    "@babel/helper-plugin-utils" "^7.14.5"
 
-"@babel/plugin-transform-new-target@^7.12.1":
-  version "7.12.1"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.12.1.tgz#80073f02ee1bb2d365c3416490e085c95759dec0"
-  integrity sha512-+eW/VLcUL5L9IvJH7rT1sT0CzkdUTvPrXC2PXTn/7z7tXLBuKvezYbGdxD5WMRoyvyaujOq2fWoKl869heKjhw==
+"@babel/plugin-transform-named-capturing-groups-regex@^7.14.9":
+  version "7.14.9"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.14.9.tgz#c68f5c5d12d2ebaba3762e57c2c4f6347a46e7b2"
+  integrity sha512-l666wCVYO75mlAtGFfyFwnWmIXQm3kSH0C3IRnJqWcZbWkoihyAdDhFm2ZWaxWTqvBvhVFfJjMRQ0ez4oN1yYA==
   dependencies:
-    "@babel/helper-plugin-utils" "^7.10.4"
+    "@babel/helper-create-regexp-features-plugin" "^7.14.5"
 
-"@babel/plugin-transform-object-super@^7.12.1":
-  version "7.12.1"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.12.1.tgz#4ea08696b8d2e65841d0c7706482b048bed1066e"
-  integrity sha512-AvypiGJH9hsquNUn+RXVcBdeE3KHPZexWRdimhuV59cSoOt5kFBmqlByorAeUlGG2CJWd0U+4ZtNKga/TB0cAw==
+"@babel/plugin-transform-new-target@^7.14.5":
+  version "7.14.5"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.14.5.tgz#31bdae8b925dc84076ebfcd2a9940143aed7dbf8"
+  integrity sha512-Nx054zovz6IIRWEB49RDRuXGI4Gy0GMgqG0cII9L3MxqgXz/+rgII+RU58qpo4g7tNEx1jG7rRVH4ihZoP4esQ==
   dependencies:
-    "@babel/helper-plugin-utils" "^7.10.4"
-    "@babel/helper-replace-supers" "^7.12.1"
+    "@babel/helper-plugin-utils" "^7.14.5"
 
-"@babel/plugin-transform-parameters@^7.12.1":
-  version "7.12.1"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.12.1.tgz#d2e963b038771650c922eff593799c96d853255d"
-  integrity sha512-xq9C5EQhdPK23ZeCdMxl8bbRnAgHFrw5EOC3KJUsSylZqdkCaFEXxGSBuTSObOpiiHHNyb82es8M1QYgfQGfNg==
+"@babel/plugin-transform-object-super@^7.14.5":
+  version "7.14.5"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.14.5.tgz#d0b5faeac9e98597a161a9cf78c527ed934cdc45"
+  integrity sha512-MKfOBWzK0pZIrav9z/hkRqIk/2bTv9qvxHzPQc12RcVkMOzpIKnFCNYJip00ssKWYkd8Sf5g0Wr7pqJ+cmtuFg==
   dependencies:
-    "@babel/helper-plugin-utils" "^7.10.4"
+    "@babel/helper-plugin-utils" "^7.14.5"
+    "@babel/helper-replace-supers" "^7.14.5"
 
-"@babel/plugin-transform-property-literals@^7.12.1":
-  version "7.12.1"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.12.1.tgz#41bc81200d730abb4456ab8b3fbd5537b59adecd"
-  integrity sha512-6MTCR/mZ1MQS+AwZLplX4cEySjCpnIF26ToWo942nqn8hXSm7McaHQNeGx/pt7suI1TWOWMfa/NgBhiqSnX0cQ==
+"@babel/plugin-transform-parameters@^7.14.5", "@babel/plugin-transform-parameters@^7.15.4":
+  version "7.15.4"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.15.4.tgz#5f2285cc3160bf48c8502432716b48504d29ed62"
+  integrity sha512-9WB/GUTO6lvJU3XQsSr6J/WKvBC2hcs4Pew8YxZagi6GkTdniyqp8On5kqdK8MN0LMeu0mGbhPN+O049NV/9FQ==
   dependencies:
-    "@babel/helper-plugin-utils" "^7.10.4"
+    "@babel/helper-plugin-utils" "^7.14.5"
 
-"@babel/plugin-transform-react-jsx@^7.0.0":
-  version "7.12.12"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.12.12.tgz#b0da51ffe5f34b9a900e9f1f5fb814f9e512d25e"
-  integrity sha512-JDWGuzGNWscYcq8oJVCtSE61a5+XAOos+V0HrxnDieUus4UMnBEosDnY1VJqU5iZ4pA04QY7l0+JvHL1hZEfsw==
+"@babel/plugin-transform-property-literals@^7.14.5":
+  version "7.14.5"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.14.5.tgz#0ddbaa1f83db3606f1cdf4846fa1dfb473458b34"
+  integrity sha512-r1uilDthkgXW8Z1vJz2dKYLV1tuw2xsbrp3MrZmD99Wh9vsfKoob+JTgri5VUb/JqyKRXotlOtwgu4stIYCmnw==
   dependencies:
-    "@babel/helper-annotate-as-pure" "^7.12.10"
-    "@babel/helper-module-imports" "^7.12.5"
-    "@babel/helper-plugin-utils" "^7.10.4"
-    "@babel/plugin-syntax-jsx" "^7.12.1"
-    "@babel/types" "^7.12.12"
+    "@babel/helper-plugin-utils" "^7.14.5"
 
-"@babel/plugin-transform-regenerator@^7.12.1":
-  version "7.12.1"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.12.1.tgz#5f0a28d842f6462281f06a964e88ba8d7ab49753"
-  integrity sha512-gYrHqs5itw6i4PflFX3OdBPMQdPbF4bj2REIUxlMRUFk0/ZOAIpDFuViuxPjUL7YC8UPnf+XG7/utJvqXdPKng==
+"@babel/plugin-transform-regenerator@^7.14.5":
+  version "7.14.5"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.14.5.tgz#9676fd5707ed28f522727c5b3c0aa8544440b04f"
+  integrity sha512-NVIY1W3ITDP5xQl50NgTKlZ0GrotKtLna08/uGY6ErQt6VEQZXla86x/CTddm5gZdcr+5GSsvMeTmWA5Ii6pkg==
   dependencies:
     regenerator-transform "^0.14.2"
 
-"@babel/plugin-transform-reserved-words@^7.12.1":
-  version "7.12.1"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.12.1.tgz#6fdfc8cc7edcc42b36a7c12188c6787c873adcd8"
-  integrity sha512-pOnUfhyPKvZpVyBHhSBoX8vfA09b7r00Pmm1sH+29ae2hMTKVmSp4Ztsr8KBKjLjx17H0eJqaRC3bR2iThM54A==
-  dependencies:
-    "@babel/helper-plugin-utils" "^7.10.4"
-
-"@babel/plugin-transform-runtime@^7.12.1":
-  version "7.12.10"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.12.10.tgz#af0fded4e846c4b37078e8e5d06deac6cd848562"
-  integrity sha512-xOrUfzPxw7+WDm9igMgQCbO3cJKymX7dFdsgRr1eu9n3KjjyU4pptIXbXPseQDquw+W+RuJEJMHKHNsPNNm3CA==
-  dependencies:
-    "@babel/helper-module-imports" "^7.12.5"
-    "@babel/helper-plugin-utils" "^7.10.4"
-    semver "^5.5.1"
-
-"@babel/plugin-transform-shorthand-properties@^7.12.1":
-  version "7.12.1"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.12.1.tgz#0bf9cac5550fce0cfdf043420f661d645fdc75e3"
-  integrity sha512-GFZS3c/MhX1OusqB1MZ1ct2xRzX5ppQh2JU1h2Pnfk88HtFTM+TWQqJNfwkmxtPQtb/s1tk87oENfXJlx7rSDw==
-  dependencies:
-    "@babel/helper-plugin-utils" "^7.10.4"
-
-"@babel/plugin-transform-spread@^7.12.1":
-  version "7.12.1"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.12.1.tgz#527f9f311be4ec7fdc2b79bb89f7bf884b3e1e1e"
-  integrity sha512-vuLp8CP0BE18zVYjsEBZ5xoCecMK6LBMMxYzJnh01rxQRvhNhH1csMMmBfNo5tGpGO+NhdSNW2mzIvBu3K1fng==
-  dependencies:
-    "@babel/helper-plugin-utils" "^7.10.4"
-    "@babel/helper-skip-transparent-expression-wrappers" "^7.12.1"
-
-"@babel/plugin-transform-sticky-regex@^7.12.7":
-  version "7.12.7"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.12.7.tgz#560224613ab23987453948ed21d0b0b193fa7fad"
-  integrity sha512-VEiqZL5N/QvDbdjfYQBhruN0HYjSPjC4XkeqW4ny/jNtH9gcbgaqBIXYEZCNnESMAGs0/K/R7oFGMhOyu/eIxg==
-  dependencies:
-    "@babel/helper-plugin-utils" "^7.10.4"
-
-"@babel/plugin-transform-template-literals@^7.12.1":
-  version "7.12.1"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.12.1.tgz#b43ece6ed9a79c0c71119f576d299ef09d942843"
-  integrity sha512-b4Zx3KHi+taXB1dVRBhVJtEPi9h1THCeKmae2qP0YdUHIFhVjtpqqNfxeVAa1xeHVhAy4SbHxEwx5cltAu5apw==
-  dependencies:
-    "@babel/helper-plugin-utils" "^7.10.4"
-
-"@babel/plugin-transform-typeof-symbol@^7.12.10":
-  version "7.12.10"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.12.10.tgz#de01c4c8f96580bd00f183072b0d0ecdcf0dec4b"
-  integrity sha512-JQ6H8Rnsogh//ijxspCjc21YPd3VLVoYtAwv3zQmqAt8YGYUtdo5usNhdl4b9/Vir2kPFZl6n1h0PfUz4hJhaA==
+"@babel/plugin-transform-reserved-words@^7.14.5":
+  version "7.14.5"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.14.5.tgz#c44589b661cfdbef8d4300dcc7469dffa92f8304"
+  integrity sha512-cv4F2rv1nD4qdexOGsRQXJrOcyb5CrgjUH9PKrrtyhSDBNWGxd0UIitjyJiWagS+EbUGjG++22mGH1Pub8D6Vg==
   dependencies:
-    "@babel/helper-plugin-utils" "^7.10.4"
+    "@babel/helper-plugin-utils" "^7.14.5"
 
-"@babel/plugin-transform-unicode-escapes@^7.12.1":
-  version "7.12.1"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.12.1.tgz#5232b9f81ccb07070b7c3c36c67a1b78f1845709"
-  integrity sha512-I8gNHJLIc7GdApm7wkVnStWssPNbSRMPtgHdmH3sRM1zopz09UWPS4x5V4n1yz/MIWTVnJ9sp6IkuXdWM4w+2Q==
+"@babel/plugin-transform-runtime@^7.13.15":
+  version "7.15.0"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.15.0.tgz#d3aa650d11678ca76ce294071fda53d7804183b3"
+  integrity sha512-sfHYkLGjhzWTq6xsuQ01oEsUYjkHRux9fW1iUA68dC7Qd8BS1Unq4aZ8itmQp95zUzIcyR2EbNMTzAicFj+guw==
   dependencies:
-    "@babel/helper-plugin-utils" "^7.10.4"
-
-"@babel/plugin-transform-unicode-regex@^7.12.1":
-  version "7.12.1"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.12.1.tgz#cc9661f61390db5c65e3febaccefd5c6ac3faecb"
-  integrity sha512-SqH4ClNngh/zGwHZOOQMTD+e8FGWexILV+ePMyiDJttAWRh5dhDL8rcl5lSgU3Huiq6Zn6pWTMvdPAb21Dwdyg==
-  dependencies:
-    "@babel/helper-create-regexp-features-plugin" "^7.12.1"
-    "@babel/helper-plugin-utils" "^7.10.4"
+    "@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"
+    semver "^6.3.0"
 
-"@babel/preset-env@^7.12.7", "@babel/preset-env@^7.4.4":
-  version "7.12.11"
-  resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.12.11.tgz#55d5f7981487365c93dbbc84507b1c7215e857f9"
-  integrity sha512-j8Tb+KKIXKYlDBQyIOy4BLxzv1NUOwlHfZ74rvW+Z0Gp4/cI2IMDPBWAgWceGcE7aep9oL/0K9mlzlMGxA8yNw==
-  dependencies:
-    "@babel/compat-data" "^7.12.7"
-    "@babel/helper-compilation-targets" "^7.12.5"
-    "@babel/helper-module-imports" "^7.12.5"
-    "@babel/helper-plugin-utils" "^7.10.4"
-    "@babel/helper-validator-option" "^7.12.11"
-    "@babel/plugin-proposal-async-generator-functions" "^7.12.1"
-    "@babel/plugin-proposal-class-properties" "^7.12.1"
-    "@babel/plugin-proposal-dynamic-import" "^7.12.1"
-    "@babel/plugin-proposal-export-namespace-from" "^7.12.1"
-    "@babel/plugin-proposal-json-strings" "^7.12.1"
-    "@babel/plugin-proposal-logical-assignment-operators" "^7.12.1"
-    "@babel/plugin-proposal-nullish-coalescing-operator" "^7.12.1"
-    "@babel/plugin-proposal-numeric-separator" "^7.12.7"
-    "@babel/plugin-proposal-object-rest-spread" "^7.12.1"
-    "@babel/plugin-proposal-optional-catch-binding" "^7.12.1"
-    "@babel/plugin-proposal-optional-chaining" "^7.12.7"
-    "@babel/plugin-proposal-private-methods" "^7.12.1"
-    "@babel/plugin-proposal-unicode-property-regex" "^7.12.1"
-    "@babel/plugin-syntax-async-generators" "^7.8.0"
-    "@babel/plugin-syntax-class-properties" "^7.12.1"
-    "@babel/plugin-syntax-dynamic-import" "^7.8.0"
+"@babel/plugin-transform-shorthand-properties@^7.14.5":
+  version "7.14.5"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.14.5.tgz#97f13855f1409338d8cadcbaca670ad79e091a58"
+  integrity sha512-xLucks6T1VmGsTB+GWK5Pl9Jl5+nRXD1uoFdA5TSO6xtiNjtXTjKkmPdFXVLGlK5A2/or/wQMKfmQ2Y0XJfn5g==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.14.5"
+
+"@babel/plugin-transform-spread@^7.14.6":
+  version "7.14.6"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.14.6.tgz#6bd40e57fe7de94aa904851963b5616652f73144"
+  integrity sha512-Zr0x0YroFJku7n7+/HH3A2eIrGMjbmAIbJSVv0IZ+t3U2WUQUA64S/oeied2e+MaGSjmt4alzBCsK9E8gh+fag==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.14.5"
+    "@babel/helper-skip-transparent-expression-wrappers" "^7.14.5"
+
+"@babel/plugin-transform-sticky-regex@^7.14.5":
+  version "7.14.5"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.14.5.tgz#5b617542675e8b7761294381f3c28c633f40aeb9"
+  integrity sha512-Z7F7GyvEMzIIbwnziAZmnSNpdijdr4dWt+FJNBnBLz5mwDFkqIXU9wmBcWWad3QeJF5hMTkRe4dAq2sUZiG+8A==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.14.5"
+
+"@babel/plugin-transform-template-literals@^7.14.5":
+  version "7.14.5"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.14.5.tgz#a5f2bc233937d8453885dc736bdd8d9ffabf3d93"
+  integrity sha512-22btZeURqiepOfuy/VkFr+zStqlujWaarpMErvay7goJS6BWwdd6BY9zQyDLDa4x2S3VugxFb162IZ4m/S/+Gg==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.14.5"
+
+"@babel/plugin-transform-typeof-symbol@^7.14.5":
+  version "7.14.5"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.14.5.tgz#39af2739e989a2bd291bf6b53f16981423d457d4"
+  integrity sha512-lXzLD30ffCWseTbMQzrvDWqljvZlHkXU+CnseMhkMNqU1sASnCsz3tSzAaH3vCUXb9PHeUb90ZT1BdFTm1xxJw==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.14.5"
+
+"@babel/plugin-transform-unicode-escapes@^7.14.5":
+  version "7.14.5"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.14.5.tgz#9d4bd2a681e3c5d7acf4f57fa9e51175d91d0c6b"
+  integrity sha512-crTo4jATEOjxj7bt9lbYXcBAM3LZaUrbP2uUdxb6WIorLmjNKSpHfIybgY4B8SRpbf8tEVIWH3Vtm7ayCrKocA==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.14.5"
+
+"@babel/plugin-transform-unicode-regex@^7.14.5":
+  version "7.14.5"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.14.5.tgz#4cd09b6c8425dd81255c7ceb3fb1836e7414382e"
+  integrity sha512-UygduJpC5kHeCiRw/xDVzC+wj8VaYSoKl5JNVmbP7MadpNinAm3SvZCxZ42H37KZBKztz46YC73i9yV34d0Tzw==
+  dependencies:
+    "@babel/helper-create-regexp-features-plugin" "^7.14.5"
+    "@babel/helper-plugin-utils" "^7.14.5"
+
+"@babel/preset-env@^7.14.1":
+  version "7.15.4"
+  resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.15.4.tgz#197e7f99a755c488f0af411af179cbd10de6e815"
+  integrity sha512-4f2nLw+q6ht8gl3sHCmNhmA5W6b1ItLzbH3UrKuJxACHr2eCpk96jwjrAfCAaXaaVwTQGnyUYHY2EWXJGt7TUQ==
+  dependencies:
+    "@babel/compat-data" "^7.15.0"
+    "@babel/helper-compilation-targets" "^7.15.4"
+    "@babel/helper-plugin-utils" "^7.14.5"
+    "@babel/helper-validator-option" "^7.14.5"
+    "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.15.4"
+    "@babel/plugin-proposal-async-generator-functions" "^7.15.4"
+    "@babel/plugin-proposal-class-properties" "^7.14.5"
+    "@babel/plugin-proposal-class-static-block" "^7.15.4"
+    "@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.15.4"
+    "@babel/plugin-proposal-unicode-property-regex" "^7.14.5"
+    "@babel/plugin-syntax-async-generators" "^7.8.4"
+    "@babel/plugin-syntax-class-properties" "^7.12.13"
+    "@babel/plugin-syntax-class-static-block" "^7.14.5"
+    "@babel/plugin-syntax-dynamic-import" "^7.8.3"
     "@babel/plugin-syntax-export-namespace-from" "^7.8.3"
-    "@babel/plugin-syntax-json-strings" "^7.8.0"
+    "@babel/plugin-syntax-json-strings" "^7.8.3"
     "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4"
-    "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0"
+    "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3"
     "@babel/plugin-syntax-numeric-separator" "^7.10.4"
-    "@babel/plugin-syntax-object-rest-spread" "^7.8.0"
-    "@babel/plugin-syntax-optional-catch-binding" "^7.8.0"
-    "@babel/plugin-syntax-optional-chaining" "^7.8.0"
-    "@babel/plugin-syntax-top-level-await" "^7.12.1"
-    "@babel/plugin-transform-arrow-functions" "^7.12.1"
-    "@babel/plugin-transform-async-to-generator" "^7.12.1"
-    "@babel/plugin-transform-block-scoped-functions" "^7.12.1"
-    "@babel/plugin-transform-block-scoping" "^7.12.11"
-    "@babel/plugin-transform-classes" "^7.12.1"
-    "@babel/plugin-transform-computed-properties" "^7.12.1"
-    "@babel/plugin-transform-destructuring" "^7.12.1"
-    "@babel/plugin-transform-dotall-regex" "^7.12.1"
-    "@babel/plugin-transform-duplicate-keys" "^7.12.1"
-    "@babel/plugin-transform-exponentiation-operator" "^7.12.1"
-    "@babel/plugin-transform-for-of" "^7.12.1"
-    "@babel/plugin-transform-function-name" "^7.12.1"
-    "@babel/plugin-transform-literals" "^7.12.1"
-    "@babel/plugin-transform-member-expression-literals" "^7.12.1"
-    "@babel/plugin-transform-modules-amd" "^7.12.1"
-    "@babel/plugin-transform-modules-commonjs" "^7.12.1"
-    "@babel/plugin-transform-modules-systemjs" "^7.12.1"
-    "@babel/plugin-transform-modules-umd" "^7.12.1"
-    "@babel/plugin-transform-named-capturing-groups-regex" "^7.12.1"
-    "@babel/plugin-transform-new-target" "^7.12.1"
-    "@babel/plugin-transform-object-super" "^7.12.1"
-    "@babel/plugin-transform-parameters" "^7.12.1"
-    "@babel/plugin-transform-property-literals" "^7.12.1"
-    "@babel/plugin-transform-regenerator" "^7.12.1"
-    "@babel/plugin-transform-reserved-words" "^7.12.1"
-    "@babel/plugin-transform-shorthand-properties" "^7.12.1"
-    "@babel/plugin-transform-spread" "^7.12.1"
-    "@babel/plugin-transform-sticky-regex" "^7.12.7"
-    "@babel/plugin-transform-template-literals" "^7.12.1"
-    "@babel/plugin-transform-typeof-symbol" "^7.12.10"
-    "@babel/plugin-transform-unicode-escapes" "^7.12.1"
-    "@babel/plugin-transform-unicode-regex" "^7.12.1"
-    "@babel/preset-modules" "^0.1.3"
-    "@babel/types" "^7.12.11"
-    core-js-compat "^3.8.0"
-    semver "^5.5.0"
+    "@babel/plugin-syntax-object-rest-spread" "^7.8.3"
+    "@babel/plugin-syntax-optional-catch-binding" "^7.8.3"
+    "@babel/plugin-syntax-optional-chaining" "^7.8.3"
+    "@babel/plugin-syntax-private-property-in-object" "^7.14.5"
+    "@babel/plugin-syntax-top-level-await" "^7.14.5"
+    "@babel/plugin-transform-arrow-functions" "^7.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.15.3"
+    "@babel/plugin-transform-classes" "^7.15.4"
+    "@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.15.4"
+    "@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.15.4"
+    "@babel/plugin-transform-modules-systemjs" "^7.15.4"
+    "@babel/plugin-transform-modules-umd" "^7.14.5"
+    "@babel/plugin-transform-named-capturing-groups-regex" "^7.14.9"
+    "@babel/plugin-transform-new-target" "^7.14.5"
+    "@babel/plugin-transform-object-super" "^7.14.5"
+    "@babel/plugin-transform-parameters" "^7.15.4"
+    "@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.15.4"
+    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.16.0"
+    semver "^6.3.0"
 
-"@babel/preset-modules@^0.1.3":
+"@babel/preset-modules@^0.1.4":
   version "0.1.4"
   resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.4.tgz#362f2b68c662842970fdb5e254ffc8fc1c2e415e"
   integrity sha512-J36NhwnfdzpmH41M1DrnkkgAqhZaqr/NBdPfQ677mLzlaXo+oDiv1deyCDtgAhz8p328otdob0Du7+xgHGZbKg==
@@ -846,44 +894,43 @@
     "@babel/types" "^7.4.4"
     esutils "^2.0.2"
 
-"@babel/runtime@^7.12.5", "@babel/runtime@^7.4.4", "@babel/runtime@^7.8.4":
-  version "7.12.5"
-  resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.12.5.tgz#410e7e487441e1b360c29be715d870d9b985882e"
-  integrity sha512-plcc+hbExy3McchJCEQG3knOsuh3HH+Prx1P6cLIkET/0dLuQDEnrT+s27Axgc9bqfsmNUNHfscgMUdBpC9xfg==
+"@babel/runtime@^7.14.0", "@babel/runtime@^7.8.4":
+  version "7.15.4"
+  resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.15.4.tgz#fd17d16bfdf878e6dd02d19753a39fa8a8d9c84a"
+  integrity sha512-99catp6bHCaxr4sJ/DbTGgHS4+Rs2RVd2g7iOap6SLGPDknRK9ztKNsE/Fg6QhSeh1FGE5f6gHGQmvvn3I3xhw==
   dependencies:
     regenerator-runtime "^0.13.4"
 
-"@babel/template@^7.10.4", "@babel/template@^7.12.7", "@babel/template@^7.3.3", "@babel/template@^7.4.4":
-  version "7.12.7"
-  resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.12.7.tgz#c817233696018e39fbb6c491d2fb684e05ed43bc"
-  integrity sha512-GkDzmHS6GV7ZeXfJZ0tLRBhZcMcY0/Lnb+eEbXDBfCAcZCjrZKe6p3J4we/D24O9Y8enxWAg1cWwof59yLh2ow==
-  dependencies:
-    "@babel/code-frame" "^7.10.4"
-    "@babel/parser" "^7.12.7"
-    "@babel/types" "^7.12.7"
-
-"@babel/traverse@^7.1.0", "@babel/traverse@^7.10.4", "@babel/traverse@^7.12.1", "@babel/traverse@^7.12.10", "@babel/traverse@^7.12.5", "@babel/traverse@^7.4.4", "@babel/traverse@^7.7.0":
-  version "7.12.12"
-  resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.12.12.tgz#d0cd87892704edd8da002d674bc811ce64743376"
-  integrity sha512-s88i0X0lPy45RrLM8b9mz8RPH5FqO9G9p7ti59cToE44xFm1Q+Pjh5Gq4SXBbtb88X7Uy7pexeqRIQDDMNkL0w==
-  dependencies:
-    "@babel/code-frame" "^7.12.11"
-    "@babel/generator" "^7.12.11"
-    "@babel/helper-function-name" "^7.12.11"
-    "@babel/helper-split-export-declaration" "^7.12.11"
-    "@babel/parser" "^7.12.11"
-    "@babel/types" "^7.12.12"
+"@babel/template@^7.15.4", "@babel/template@^7.3.3":
+  version "7.15.4"
+  resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.15.4.tgz#51898d35dcf3faa670c4ee6afcfd517ee139f194"
+  integrity sha512-UgBAfEa1oGuYgDIPM2G+aHa4Nlo9Lh6mGD2bDBGMTbYnc38vulXPuC1MGjYILIEmlwl6Rd+BPR9ee3gm20CBtg==
+  dependencies:
+    "@babel/code-frame" "^7.14.5"
+    "@babel/parser" "^7.15.4"
+    "@babel/types" "^7.15.4"
+
+"@babel/traverse@^7.1.0", "@babel/traverse@^7.13.0", "@babel/traverse@^7.15.4", "@babel/traverse@^7.7.0":
+  version "7.15.4"
+  resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.15.4.tgz#ff8510367a144bfbff552d9e18e28f3e2889c22d"
+  integrity sha512-W6lQD8l4rUbQR/vYgSuCAE75ADyyQvOpFVsvPPdkhf6lATXAsQIG9YdtOcu8BB1dZ0LKu+Zo3c1wEcbKeuhdlA==
+  dependencies:
+    "@babel/code-frame" "^7.14.5"
+    "@babel/generator" "^7.15.4"
+    "@babel/helper-function-name" "^7.15.4"
+    "@babel/helper-hoist-variables" "^7.15.4"
+    "@babel/helper-split-export-declaration" "^7.15.4"
+    "@babel/parser" "^7.15.4"
+    "@babel/types" "^7.15.4"
     debug "^4.1.0"
     globals "^11.1.0"
-    lodash "^4.17.19"
 
-"@babel/types@^7.0.0", "@babel/types@^7.10.4", "@babel/types@^7.10.5", "@babel/types@^7.12.1", "@babel/types@^7.12.10", "@babel/types@^7.12.11", "@babel/types@^7.12.12", "@babel/types@^7.12.5", "@babel/types@^7.12.7", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4", "@babel/types@^7.7.0":
-  version "7.12.12"
-  resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.12.12.tgz#4608a6ec313abbd87afa55004d373ad04a96c299"
-  integrity sha512-lnIX7piTxOH22xE7fDXDbSHg9MM1/6ORnafpJmov5rs0kX5g4BZxeXNJLXsMRiO0U5Rb8/FvMS6xlTnTHvxonQ==
+"@babel/types@^7.0.0", "@babel/types@^7.15.4", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4", "@babel/types@^7.7.0":
+  version "7.15.4"
+  resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.15.4.tgz#74eeb86dbd6748d2741396557b9860e57fce0a0d"
+  integrity sha512-0f1HJFuGmmbrKTCZtbm3cU+b/AqdEYk5toj5iQur58xkVMlS0JWaKxTBSmCXd47uiN7vbcozAupm6Mvs80GNhw==
   dependencies:
-    "@babel/helper-validator-identifier" "^7.12.11"
-    lodash "^4.17.19"
+    "@babel/helper-validator-identifier" "^7.14.9"
     to-fast-properties "^2.0.0"
 
 "@bcoe/v8-coverage@^0.2.3":
@@ -904,31 +951,44 @@
   resolved "https://registry.yarnpkg.com/@csstools/convert-colors/-/convert-colors-1.4.0.tgz#ad495dc41b12e75d588c6db8b9834f08fa131eb7"
   integrity sha512-5a6wqoJV/xEdbRNKVo6I4hO3VjyDq//8q2f9I6PBAvMesJHFauXDorcNCsr9RzvsZnaWi5NYCcfyqP1QeFHFbw==
 
-"@eslint/eslintrc@^0.2.2":
-  version "0.2.2"
-  resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.2.2.tgz#d01fc791e2fc33e88a29d6f3dc7e93d0cd784b76"
-  integrity sha512-EfB5OHNYp1F4px/LI/FEnGylop7nOqkQ1LRzCM0KccA2U8tvV8w01KBv37LbO7nW4H+YhKyo2LcJhRwjjV17QQ==
+"@eslint/eslintrc@^0.4.3":
+  version "0.4.3"
+  resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.4.3.tgz#9e42981ef035beb3dd49add17acb96e8ff6f394c"
+  integrity sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==
   dependencies:
     ajv "^6.12.4"
     debug "^4.1.1"
     espree "^7.3.0"
-    globals "^12.1.0"
+    globals "^13.9.0"
     ignore "^4.0.6"
     import-fresh "^3.2.1"
     js-yaml "^3.13.1"
-    lodash "^4.17.19"
     minimatch "^3.0.4"
     strip-json-comments "^3.1.1"
 
 "@fortawesome/fontawesome-free@^5.15.1":
-  version "5.15.1"
-  resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-free/-/fontawesome-free-5.15.1.tgz#ccfef6ddbe59f8fe8f694783e1d3eb88902dc5eb"
-  integrity sha512-OEdH7SyC1suTdhBGW91/zBfR6qaIhThbcN8PUXtXilY4GYnSBbVqOntdHbC1vXwsDnX0Qix2m2+DSU1J51ybOQ==
+  version "5.15.4"
+  resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-free/-/fontawesome-free-5.15.4.tgz#ecda5712b61ac852c760d8b3c79c96adca5554e5"
+  integrity sha512-eYm8vijH/hpzr/6/1CJ/V/Eb1xQFW2nnUKArb3z+yUWv7HTwj6M7SP957oMjfZjAHU6qpoNc2wQvIxBLWYa/Jg==
+
+"@gar/promisify@^1.0.1":
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/@gar/promisify/-/promisify-1.1.2.tgz#30aa825f11d438671d585bd44e7fd564535fc210"
+  integrity sha512-82cpyJyKRoQoRi+14ibCeGPu0CwypgtBAdBhq1WfvagpCZNKqwXbKwXllYSMG91DhmG4jt9gN8eP6lGOtozuaw==
+
+"@humanwhocodes/config-array@^0.5.0":
+  version "0.5.0"
+  resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.5.0.tgz#1407967d4c6eecd7388f83acf1eaf4d0c6e58ef9"
+  integrity sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==
+  dependencies:
+    "@humanwhocodes/object-schema" "^1.2.0"
+    debug "^4.1.1"
+    minimatch "^3.0.4"
 
-"@iarna/toml@^2.2.0":
-  version "2.2.5"
-  resolved "https://registry.yarnpkg.com/@iarna/toml/-/toml-2.2.5.tgz#b32366c89b43c6f8cefbdefac778b9c828e3ba8c"
-  integrity sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg==
+"@humanwhocodes/object-schema@^1.2.0":
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.0.tgz#87de7af9c231826fdd68ac7258f77c429e0e5fcf"
+  integrity sha512-wdppn25U8z/2yiaT6YGquE6X8sSv7hNMWSXYSSU1jGv/yd6XqjXgTDJ8KP4NgjTXfJ3GbRjeeb8RTV7a/VpM+w==
 
 "@istanbuljs/load-nyc-config@^1.0.0":
   version "1.1.0"
@@ -942,9 +1002,9 @@
     resolve-from "^5.0.0"
 
 "@istanbuljs/schema@^0.1.2":
-  version "0.1.2"
-  resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.2.tgz#26520bf09abe4a5644cd5414e37125a8954241dd"
-  integrity sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw==
+  version "0.1.3"
+  resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98"
+  integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==
 
 "@jest/console@^26.6.2":
   version "26.6.2"
@@ -1117,193 +1177,199 @@
     "@types/yargs" "^15.0.0"
     chalk "^4.0.0"
 
-"@mrmlnc/readdir-enhanced@^2.2.1":
-  version "2.2.1"
-  resolved "https://registry.yarnpkg.com/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz#524af240d1a360527b730475ecfa1344aa540dde"
-  integrity sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==
-  dependencies:
-    call-me-maybe "^1.0.1"
-    glob-to-regexp "^0.3.0"
-
-"@nodelib/fs.scandir@2.1.4":
-  version "2.1.4"
-  resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz#d4b3549a5db5de2683e0c1071ab4f140904bbf69"
-  integrity sha512-33g3pMJk3bg5nXbL/+CY6I2eJDzZAni49PfJnL5fghPTggPvBd/pFNSgJsdAgWptuFu7qq/ERvOYFlhvsLTCKA==
+"@nodelib/fs.scandir@2.1.5":
+  version "2.1.5"
+  resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5"
+  integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==
   dependencies:
-    "@nodelib/fs.stat" "2.0.4"
+    "@nodelib/fs.stat" "2.0.5"
     run-parallel "^1.1.9"
 
-"@nodelib/fs.stat@2.0.4", "@nodelib/fs.stat@^2.0.2":
-  version "2.0.4"
-  resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.4.tgz#a3f2dd61bab43b8db8fa108a121cfffe4c676655"
-  integrity sha512-IYlHJA0clt2+Vg7bccq+TzRdJvv19c2INqBSsoOLp1je7xjtr7J26+WXR72MCdvU9q1qTzIWDfhMf+DRvQJK4Q==
-
-"@nodelib/fs.stat@^1.1.2":
-  version "1.1.3"
-  resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b"
-  integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==
+"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2":
+  version "2.0.5"
+  resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b"
+  integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==
 
 "@nodelib/fs.walk@^1.2.3":
-  version "1.2.6"
-  resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.6.tgz#cce9396b30aa5afe9e3756608f5831adcb53d063"
-  integrity sha512-8Broas6vTtW4GIXTAHDoE32hnN2M5ykgCpWGbuXHQ15vEMqr23pB76e/GZcYsZCHALv50ktd24qhEyKr6wBtow==
+  version "1.2.8"
+  resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a"
+  integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==
   dependencies:
-    "@nodelib/fs.scandir" "2.1.4"
+    "@nodelib/fs.scandir" "2.1.5"
     fastq "^1.6.0"
 
-"@nuxt/babel-preset-app@2.14.12":
-  version "2.14.12"
-  resolved "https://registry.yarnpkg.com/@nuxt/babel-preset-app/-/babel-preset-app-2.14.12.tgz#503380ec97bb5178d16163b572cc9c0fea5b7f9a"
-  integrity sha512-6qAW5i4F+nCRWyGBytJAEJ/P0yH9RpYmIqWwkzQd1GQ1EuO1Fuc9QoOmmzbs+3MrwW7HzpQ5jJtLDuzhQ+e5/w==
-  dependencies:
-    "@babel/core" "^7.12.9"
-    "@babel/helper-compilation-targets" "^7.12.5"
-    "@babel/plugin-proposal-class-properties" "^7.12.1"
-    "@babel/plugin-proposal-decorators" "^7.12.1"
-    "@babel/plugin-proposal-nullish-coalescing-operator" "^7.12.1"
-    "@babel/plugin-proposal-optional-chaining" "^7.12.7"
-    "@babel/plugin-transform-runtime" "^7.12.1"
-    "@babel/preset-env" "^7.12.7"
-    "@babel/runtime" "^7.12.5"
+"@npmcli/fs@^1.0.0":
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/@npmcli/fs/-/fs-1.0.0.tgz#589612cfad3a6ea0feafcb901d29c63fd52db09f"
+  integrity sha512-8ltnOpRR/oJbOp8vaGUnipOi3bqkcW+sLHFlyXIr08OGHmVJLB1Hn7QtGXbYcpVtH1gAYZTlmDXtE4YV0+AMMQ==
+  dependencies:
+    "@gar/promisify" "^1.0.1"
+    semver "^7.3.5"
+
+"@npmcli/move-file@^1.0.1":
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/@npmcli/move-file/-/move-file-1.1.2.tgz#1a82c3e372f7cae9253eb66d72543d6b8685c674"
+  integrity sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==
+  dependencies:
+    mkdirp "^1.0.4"
+    rimraf "^3.0.2"
+
+"@nuxt/babel-preset-app@2.15.8":
+  version "2.15.8"
+  resolved "https://registry.yarnpkg.com/@nuxt/babel-preset-app/-/babel-preset-app-2.15.8.tgz#c78eb8c47c1cafec1c5aba6a52385a3ce877b968"
+  integrity sha512-z23bY5P7dLTmIbk0ZZ95mcEXIEER/mQCOqEp2vxnzG2nurks+vq6tNcUAXqME1Wl6aXWTXlqky5plBe7RQHzhQ==
+  dependencies:
+    "@babel/compat-data" "^7.14.0"
+    "@babel/core" "^7.14.0"
+    "@babel/helper-compilation-targets" "^7.13.16"
+    "@babel/helper-module-imports" "^7.13.12"
+    "@babel/plugin-proposal-class-properties" "^7.13.0"
+    "@babel/plugin-proposal-decorators" "^7.13.15"
+    "@babel/plugin-proposal-nullish-coalescing-operator" "^7.13.8"
+    "@babel/plugin-proposal-optional-chaining" "^7.13.12"
+    "@babel/plugin-proposal-private-methods" "^7.13.0"
+    "@babel/plugin-transform-runtime" "^7.13.15"
+    "@babel/preset-env" "^7.14.1"
+    "@babel/runtime" "^7.14.0"
     "@vue/babel-preset-jsx" "^1.2.4"
     core-js "^2.6.5"
-
-"@nuxt/builder@2.14.12":
-  version "2.14.12"
-  resolved "https://registry.yarnpkg.com/@nuxt/builder/-/builder-2.14.12.tgz#c8c9deecaf88e59db4be1e1f7f296bb9212f93b7"
-  integrity sha512-I25K6BEZVJv7p2bAJfNFAXXEaSF41DGV/QZBAXVb/gFjmhZABNYfvIkwHGnAv5n1JPHHi2Y1R3gsFM4fFXkxxw==
-  dependencies:
-    "@nuxt/devalue" "^1.2.4"
-    "@nuxt/utils" "2.14.12"
-    "@nuxt/vue-app" "2.14.12"
-    "@nuxt/webpack" "2.14.12"
-    chalk "^3.0.0"
-    chokidar "^3.4.3"
-    consola "^2.15.0"
-    fs-extra "^8.1.0"
-    glob "^7.1.6"
+    core-js-compat "^3.12.1"
+    regenerator-runtime "^0.13.7"
+
+"@nuxt/builder@2.15.8":
+  version "2.15.8"
+  resolved "https://registry.yarnpkg.com/@nuxt/builder/-/builder-2.15.8.tgz#66ead4be0a2ce6932a2b7e521cfe1621e49290e7"
+  integrity sha512-WVhN874LFMdgRiJqpxmeKI+vh5lhCUBVOyR9PhL1m1V/GV3fb+Dqc1BKS6XgayrWAWavPLveCJmQ/FID0puOfQ==
+  dependencies:
+    "@nuxt/devalue" "^1.2.5"
+    "@nuxt/utils" "2.15.8"
+    "@nuxt/vue-app" "2.15.8"
+    "@nuxt/webpack" "2.15.8"
+    chalk "^4.1.1"
+    chokidar "^3.5.1"
+    consola "^2.15.3"
+    fs-extra "^9.1.0"
+    glob "^7.1.7"
     hash-sum "^2.0.0"
     ignore "^5.1.8"
-    lodash "^4.17.20"
-    pify "^4.0.1"
-    semver "^7.3.2"
+    lodash "^4.17.21"
+    pify "^5.0.0"
     serialize-javascript "^5.0.1"
     upath "^2.0.1"
 
-"@nuxt/cli@2.14.12":
-  version "2.14.12"
-  resolved "https://registry.yarnpkg.com/@nuxt/cli/-/cli-2.14.12.tgz#1298ecbe4f2b44cd5c52cec58f01d9dfe4e16f47"
-  integrity sha512-YRWY1Gg0c3kcO9vg9/Ig9ZMzih5mhxsBTm5b7DCLAEIALBVcJJLamLDnY2C52YLUeMIcY5XCi0HkizvPIv9r2w==
+"@nuxt/cli@2.15.8":
+  version "2.15.8"
+  resolved "https://registry.yarnpkg.com/@nuxt/cli/-/cli-2.15.8.tgz#3b946ee08c7b5b3223c8952873c65727e775ec30"
+  integrity sha512-KcGIILW/dAjBKea1DHsuLCG1sNzhzETShwT23DhXWO304qL8ljf4ndYKzn2RenzauGRGz7MREta80CbJCkLSHw==
   dependencies:
-    "@nuxt/config" "2.14.12"
-    "@nuxt/utils" "2.14.12"
-    boxen "^4.2.0"
-    chalk "^3.0.0"
+    "@nuxt/config" "2.15.8"
+    "@nuxt/utils" "2.15.8"
+    boxen "^5.0.1"
+    chalk "^4.1.1"
     compression "^1.7.4"
     connect "^3.7.0"
-    consola "^2.15.0"
+    consola "^2.15.3"
     crc "^3.8.0"
-    destr "^1.0.1"
-    esm "^3.2.25"
-    execa "^3.4.0"
+    defu "^4.0.1"
+    destr "^1.1.0"
+    execa "^5.0.0"
     exit "^0.1.2"
-    fs-extra "^8.1.0"
-    globby "^11.0.1"
+    fs-extra "^9.1.0"
+    globby "^11.0.3"
     hable "^3.0.0"
+    lodash "^4.17.21"
     minimist "^1.2.5"
     opener "1.5.2"
-    pretty-bytes "^5.4.1"
+    pretty-bytes "^5.6.0"
+    semver "^7.3.5"
     serve-static "^1.14.1"
-    std-env "^2.2.1"
+    std-env "^2.3.0"
     upath "^2.0.1"
-    wrap-ansi "^6.2.0"
-
-"@nuxt/components@^1.2.2":
-  version "1.2.2"
-  resolved "https://registry.yarnpkg.com/@nuxt/components/-/components-1.2.2.tgz#675975758f77d3cbd33f9561867d71ba9e54d0e9"
-  integrity sha512-AByrBPnV4mWwwf1tPaKLmtg6JBsNJACLuSnpJOpWGV6KjS5S8i6BTf8dqiPN0uGg6YeSQaeDWtnfILcoLp2GSw==
-  dependencies:
-    chalk "^4.1.0"
-    chokidar "^3.4.3"
-    glob "^7.1.6"
-    globby "^11.0.1"
-    lodash "^4.17.20"
-    semver "^7.3.4"
-    vue-template-compiler "^2.6.12"
+    wrap-ansi "^7.0.0"
 
-"@nuxt/config@2.14.12":
-  version "2.14.12"
-  resolved "https://registry.yarnpkg.com/@nuxt/config/-/config-2.14.12.tgz#077267c94ac4d30ed38f7642236f3523ee5280f2"
-  integrity sha512-Ob861w1BjgI1IcpXRC14TKMpUSogGYX/BFn7q/0HkntYxSOQAkMaaUZ0/YEx6IR1fuZV2v+NB8M4IkyUrgW1YA==
-  dependencies:
-    "@nuxt/ufo" "^0.5.0"
-    "@nuxt/utils" "2.14.12"
-    consola "^2.15.0"
-    create-require "^1.1.1"
-    defu "^2.0.4"
-    destr "^1.0.1"
-    dotenv "^8.2.0"
-    esm "^3.2.25"
-    jiti "^0.1.17"
+"@nuxt/components@^2.1.8":
+  version "2.2.1"
+  resolved "https://registry.yarnpkg.com/@nuxt/components/-/components-2.2.1.tgz#49c4442ac5a0ef49f49ef7d9960f4376fc3e7c78"
+  integrity sha512-r1LHUzifvheTnJtYrMuA+apgsrEJbxcgFKIimeXKb+jl8TnPWdV3egmrxBCaDJchrtY/wmHyP47tunsft7AWwg==
+  dependencies:
+    chalk "^4.1.2"
+    chokidar "^3.5.2"
+    glob "^7.1.7"
+    globby "^11.0.4"
+    scule "^0.2.1"
+    semver "^7.3.5"
+    upath "^2.0.1"
+    vue-template-compiler "^2.6.14"
+
+"@nuxt/config@2.15.8":
+  version "2.15.8"
+  resolved "https://registry.yarnpkg.com/@nuxt/config/-/config-2.15.8.tgz#56cc1b052871072a26f76c6d3b69d9b53808ce52"
+  integrity sha512-KMQbjmUf9RVHeTZEf7zcuFnh03XKZioYhok6GOCY+leu3g5n/UhyPvLnTsgTfsLWohqoRoOm94u4A+tNYwn9VQ==
+  dependencies:
+    "@nuxt/utils" "2.15.8"
+    consola "^2.15.3"
+    defu "^4.0.1"
+    destr "^1.1.0"
+    dotenv "^9.0.2"
+    lodash "^4.17.21"
     rc9 "^1.2.0"
-    std-env "^2.2.1"
-
-"@nuxt/core@2.14.12":
-  version "2.14.12"
-  resolved "https://registry.yarnpkg.com/@nuxt/core/-/core-2.14.12.tgz#8f35142bcff0b1bacde2516d5e04d69e34047a95"
-  integrity sha512-J+ej2KYzB05jpGkEH5y+dHdOLEa/GKSJvJBWf5Zq0wgneOHUaxB+dnBNxIRO75eXHslHxE++y/PRIQ9ZlEdtOw==
-  dependencies:
-    "@nuxt/config" "2.14.12"
-    "@nuxt/devalue" "^1.2.4"
-    "@nuxt/server" "2.14.12"
-    "@nuxt/utils" "2.14.12"
-    "@nuxt/vue-renderer" "2.14.12"
-    consola "^2.15.0"
-    debug "^4.2.0"
-    esm "^3.2.25"
-    fs-extra "^8.1.0"
+    std-env "^2.3.0"
+    ufo "^0.7.4"
+
+"@nuxt/core@2.15.8":
+  version "2.15.8"
+  resolved "https://registry.yarnpkg.com/@nuxt/core/-/core-2.15.8.tgz#443d13da9edc5c4ae47d7902f1d6504a8cce27a2"
+  integrity sha512-31pipWRvwHiyB5VDqffgSO7JtmHxyzgshIzuZzSinxMbVmK3BKsOwacD/51oEyELgrPlUgLqcY9dg+RURgmHGQ==
+  dependencies:
+    "@nuxt/config" "2.15.8"
+    "@nuxt/server" "2.15.8"
+    "@nuxt/utils" "2.15.8"
+    consola "^2.15.3"
+    fs-extra "^9.1.0"
     hable "^3.0.0"
     hash-sum "^2.0.0"
-    std-env "^2.2.1"
+    lodash "^4.17.21"
 
-"@nuxt/devalue@^1.2.4":
-  version "1.2.4"
-  resolved "https://registry.yarnpkg.com/@nuxt/devalue/-/devalue-1.2.4.tgz#69eca032b7481fd3c019a78ade65d642da3f2f35"
-  integrity sha512-hS87c2HdSfTk1d+2KQx7mQpebyd2HjguvZu/UBy9LB+kUgT1qz2+Sj38FH32yJALK6Fv49ZfOZEwgcZ4rcNLjg==
+"@nuxt/devalue@^1.2.5":
+  version "1.2.5"
+  resolved "https://registry.yarnpkg.com/@nuxt/devalue/-/devalue-1.2.5.tgz#8d95e3e74b3332d3eb713342c5c4d18096047d66"
+  integrity sha512-Tg86C7tqzvZtZli2BQVqgzZN136mZDTgauvJXagglKkP2xt5Kw3NUIiJyjX0Ww/IZy2xVmD0LN+CEPpij4dB2g==
   dependencies:
     consola "^2.9.0"
 
-"@nuxt/friendly-errors-webpack-plugin@^2.5.0":
-  version "2.5.0"
-  resolved "https://registry.yarnpkg.com/@nuxt/friendly-errors-webpack-plugin/-/friendly-errors-webpack-plugin-2.5.0.tgz#5374665bc72d34b7dbadcc361a4777e3f0f5d46b"
-  integrity sha512-pUgPFmRL56/xuTCGN5rqgTfxvs1N/AYJw7q7tUHiZaBm3UyPgbIVPkadS9njwbFbPD2XcebVy7npQMMVwQJWfA==
+"@nuxt/friendly-errors-webpack-plugin@^2.5.1":
+  version "2.5.1"
+  resolved "https://registry.yarnpkg.com/@nuxt/friendly-errors-webpack-plugin/-/friendly-errors-webpack-plugin-2.5.1.tgz#3ab815c31eb43859a239848a85481157aaf7b07e"
+  integrity sha512-mKN0Mbb1PjJYBzrswsyWvSEZw5Jxi0fQZPMA0ssrTmkz9lvtxtXq4luhX31OpULUvbc0jLaBu/SL0ExlxIbTlw==
   dependencies:
     chalk "^2.3.2"
     consola "^2.6.0"
     error-stack-parser "^2.0.0"
     string-width "^2.0.0"
 
-"@nuxt/generator@2.14.12":
-  version "2.14.12"
-  resolved "https://registry.yarnpkg.com/@nuxt/generator/-/generator-2.14.12.tgz#6db8ac0b2954e4b99c36a13c40b2e4d8043d7854"
-  integrity sha512-r7+QW3gk0nUGaaHW8zCQ9DaBAmr+LvEI7YOLFeTQdJUjwHBdw65ga36KpL3aC1HIRkb7LgWD6lbyGKJiASkpWQ==
+"@nuxt/generator@2.15.8":
+  version "2.15.8"
+  resolved "https://registry.yarnpkg.com/@nuxt/generator/-/generator-2.15.8.tgz#d6bd4a677edf14f34d516e13bcb70d62cdd4c5b4"
+  integrity sha512-hreLdYbBIe3SWcP8LsMG7OlDTx2ZVucX8+f8Vrjft3Q4r8iCwLMYC1s1N5etxeHAZfS2kZiLmF92iscOdfbgMQ==
   dependencies:
-    "@nuxt/utils" "2.14.12"
-    chalk "^3.0.0"
-    consola "^2.15.0"
+    "@nuxt/utils" "2.15.8"
+    chalk "^4.1.1"
+    consola "^2.15.3"
+    defu "^4.0.1"
     devalue "^2.0.1"
-    fs-extra "^8.1.0"
+    fs-extra "^9.1.0"
     html-minifier "^4.0.0"
-    node-html-parser "^2.0.0"
+    node-html-parser "^3.2.0"
+    ufo "^0.7.4"
 
 "@nuxt/loading-screen@^2.0.3":
-  version "2.0.3"
-  resolved "https://registry.yarnpkg.com/@nuxt/loading-screen/-/loading-screen-2.0.3.tgz#1d6b1f976bb143c6592231af0bf7fa6245f6ebd2"
-  integrity sha512-ThvxxUpfTZezzz0gAgyG4vHCM7KDeA692EL7lKrZ/fU8JvXlG6LYngVLWAobexBsydtGkuZyKCwCVDnEGNL4jw==
+  version "2.0.4"
+  resolved "https://registry.yarnpkg.com/@nuxt/loading-screen/-/loading-screen-2.0.4.tgz#756abd861f77c57001be4d21d47534723afb4f3a"
+  integrity sha512-xpEDAoRu75tLUYCkUJCIvJkWJSuwr8pqomvQ+fkXpSrkxZ/9OzlBFjAbVdOAWTMj4aV/LVQso4vcEdircKeFIQ==
   dependencies:
     connect "^3.7.0"
-    defu "^2.0.4"
-    get-port-please "^1.0.0"
+    defu "^5.0.0"
+    get-port-please "^2.2.0"
     node-res "^5.0.1"
     serve-static "^1.14.1"
 
@@ -1316,178 +1382,180 @@
     consola "^2.15.0"
     node-fetch "^2.6.1"
 
-"@nuxt/server@2.14.12":
-  version "2.14.12"
-  resolved "https://registry.yarnpkg.com/@nuxt/server/-/server-2.14.12.tgz#919ebe76d608a38cc9358c57ae0b76c1bd039ecb"
-  integrity sha512-HDOYgjv01zRSmLxPutrXb/F7kwisR+Vur0b2MEyxqBTTy7OcxiyQn1CcXozl/Q21iqZdcGpu/tRpCHO7B8bKOQ==
+"@nuxt/server@2.15.8":
+  version "2.15.8"
+  resolved "https://registry.yarnpkg.com/@nuxt/server/-/server-2.15.8.tgz#ec733897de78f858ae0eebd174e8549f247c4e99"
+  integrity sha512-E4EtXudxtWQBUHMHOxFwm5DlPOkJbW+iF1+zc0dGmXLscep1KWPrlP+4nrpZj8/UKzpupamE8ZTS9I4IbnExVA==
   dependencies:
-    "@nuxt/config" "2.14.12"
-    "@nuxt/utils" "2.14.12"
-    "@nuxt/vue-renderer" "2.14.12"
+    "@nuxt/utils" "2.15.8"
+    "@nuxt/vue-renderer" "2.15.8"
     "@nuxtjs/youch" "^4.2.3"
-    chalk "^3.0.0"
     compression "^1.7.4"
     connect "^3.7.0"
-    consola "^2.15.0"
+    consola "^2.15.3"
     etag "^1.8.1"
     fresh "^0.5.2"
-    fs-extra "^8.1.0"
+    fs-extra "^9.1.0"
     ip "^1.1.5"
     launch-editor-middleware "^2.2.1"
     on-headers "^1.0.2"
-    pify "^4.0.1"
-    serve-placeholder "^1.2.2"
+    pify "^5.0.0"
+    serve-placeholder "^1.2.3"
     serve-static "^1.14.1"
     server-destroy "^1.0.1"
+    ufo "^0.7.4"
 
-"@nuxt/telemetry@^1.3.0":
-  version "1.3.0"
-  resolved "https://registry.yarnpkg.com/@nuxt/telemetry/-/telemetry-1.3.0.tgz#0c6595c786c4fcb060ea8508aaf6285dce8201e0"
-  integrity sha512-anAhyccoVyy/RetkqVsIxpJKdAu/GHyLl79ZtH0oOCbYcC85k8d+LC1S10WcqXyeqyUKifLxGR6yPqSPmQCCtg==
+"@nuxt/telemetry@^1.3.3":
+  version "1.3.6"
+  resolved "https://registry.yarnpkg.com/@nuxt/telemetry/-/telemetry-1.3.6.tgz#a27a27b2f56a2ad4ef2c1bef82e12f0bc0dc40ac"
+  integrity sha512-sZpLf/rU3cvN8/alR1HpJIl3mHPA1GOg41GKdOOrtw7Gi/lCEVk4hK+lpXgYInZ2n6i1JyknpKhM9YzX2RU33w==
   dependencies:
     arg "^5.0.0"
-    chalk "^4.1.0"
-    ci-info "^2.0.0"
-    consola "^2.15.0"
-    create-require "^1.1.0"
-    defu "^3.2.2"
-    destr "^1.0.1"
-    dotenv "^8.2.0"
+    chalk "^4.1.1"
+    ci-info "^3.1.1"
+    consola "^2.15.3"
+    create-require "^1.1.1"
+    defu "^5.0.0"
+    destr "^1.1.0"
+    dotenv "^9.0.2"
     fs-extra "^8.1.0"
-    git-url-parse "^11.4.0"
+    git-url-parse "^11.4.4"
     inquirer "^7.3.3"
-    is-docker "^2.1.1"
-    jiti "^0.1.16"
-    nanoid "^3.1.18"
+    is-docker "^2.2.1"
+    jiti "^1.9.2"
+    nanoid "^3.1.23"
     node-fetch "^2.6.1"
     parse-git-config "^3.0.0"
     rc9 "^1.2.0"
-    std-env "^2.2.1"
+    std-env "^2.3.0"
 
-"@nuxt/ufo@^0.5.0":
-  version "0.5.2"
-  resolved "https://registry.yarnpkg.com/@nuxt/ufo/-/ufo-0.5.2.tgz#cb40e4b3001739baebddfd65d0f03d6070e2c0e5"
-  integrity sha512-nnKFQ4NA5id5ekyQWHTdOfirIZRQzfEHMB9T0T6NZdWy4+3Nrw0GTBQ3J9Am0gg8kvqR0mMQTn1wK6ya3i/XmA==
-
-"@nuxt/utils@2.14.12":
-  version "2.14.12"
-  resolved "https://registry.yarnpkg.com/@nuxt/utils/-/utils-2.14.12.tgz#7684ef732fba65608baff02bc4cce2b3ced891ac"
-  integrity sha512-XAy18aT2JOuyGnCuGImelOMwheLRo/qBkjqufa/TLIqnBtywdv2y7WP7c9uGTZrwh+O6KHYFeeZjnLqFI0r/xQ==
+"@nuxt/utils@2.15.8":
+  version "2.15.8"
+  resolved "https://registry.yarnpkg.com/@nuxt/utils/-/utils-2.15.8.tgz#0c3594f01be63ab521583904cafd32215b719d4c"
+  integrity sha512-e0VBarUbPiQ4ZO1T58puoFIuXme7L5gk1QfwyxOONlp2ryE7aRyZ8X/mryuOiIeyP64c4nwSUtN7q9EUWRb7Lg==
   dependencies:
-    "@nuxt/ufo" "^0.5.0"
-    consola "^2.15.0"
-    fs-extra "^8.1.0"
+    consola "^2.15.3"
+    create-require "^1.1.1"
+    fs-extra "^9.1.0"
     hash-sum "^2.0.0"
-    proper-lockfile "^4.1.1"
-    semver "^7.3.2"
+    jiti "^1.9.2"
+    lodash "^4.17.21"
+    proper-lockfile "^4.1.2"
+    semver "^7.3.5"
     serialize-javascript "^5.0.1"
     signal-exit "^3.0.3"
-    ua-parser-js "^0.7.22"
+    ua-parser-js "^0.7.28"
+    ufo "^0.7.4"
 
-"@nuxt/vue-app@2.14.12":
-  version "2.14.12"
-  resolved "https://registry.yarnpkg.com/@nuxt/vue-app/-/vue-app-2.14.12.tgz#1e41d64a8b18277d5db15158ca2a5d7fbcdf23dc"
-  integrity sha512-DwkXh8Djn2wi2qLetupDKpRIFmBDNZKrdT94xFieI5qY32EhLj9d/T80wZoZNZkPVqAKcwq24WktCSVRQ/uiOw==
+"@nuxt/vue-app@2.15.8":
+  version "2.15.8"
+  resolved "https://registry.yarnpkg.com/@nuxt/vue-app/-/vue-app-2.15.8.tgz#46b7ec8fc93f8d1f4cdf4f6b04134cb40ceb7c4a"
+  integrity sha512-FJf9FSMPsWT3BqkS37zEuPTxLKzSg2EIwp1sP8Eou25eE08qxRfe2PwTVA8HnXUPNdpz2uk/T9DlNw+JraiFRQ==
   dependencies:
-    "@nuxt/ufo" "^0.5.0"
     node-fetch "^2.6.1"
+    ufo "^0.7.4"
     unfetch "^4.2.0"
     vue "^2.6.12"
     vue-client-only "^2.0.0"
     vue-meta "^2.4.0"
     vue-no-ssr "^1.1.1"
-    vue-router "^3.4.9"
+    vue-router "^3.5.1"
     vue-template-compiler "^2.6.12"
-    vuex "^3.6.0"
-
-"@nuxt/vue-renderer@2.14.12":
-  version "2.14.12"
-  resolved "https://registry.yarnpkg.com/@nuxt/vue-renderer/-/vue-renderer-2.14.12.tgz#17343f8698037e6a24ca12bc5908301b8018f151"
-  integrity sha512-bYqN1SIumi4EKWDaay6+V2NxcWS/IygOQekfuvNKYhQk97pzkBuXrBGgI6WRdSGLcEBFV0DpHxx66XWVXghL/g==
-  dependencies:
-    "@nuxt/devalue" "^1.2.4"
-    "@nuxt/ufo" "^0.5.0"
-    "@nuxt/utils" "2.14.12"
-    consola "^2.15.0"
-    fs-extra "^8.1.0"
+    vuex "^3.6.2"
+
+"@nuxt/vue-renderer@2.15.8":
+  version "2.15.8"
+  resolved "https://registry.yarnpkg.com/@nuxt/vue-renderer/-/vue-renderer-2.15.8.tgz#1cd781de18724a98e27655e89bfe64cd5521491e"
+  integrity sha512-54I/k+4G6axP9XVYYdtH6M1S6T49OIkarpF6/yIJj0yi3S/2tdJ9eUyfoLZ9EbquZFDDRHBxSswTtr2l/eakPw==
+  dependencies:
+    "@nuxt/devalue" "^1.2.5"
+    "@nuxt/utils" "2.15.8"
+    consola "^2.15.3"
+    defu "^4.0.1"
+    fs-extra "^9.1.0"
+    lodash "^4.17.21"
     lru-cache "^5.1.1"
+    ufo "^0.7.4"
     vue "^2.6.12"
     vue-meta "^2.4.0"
     vue-server-renderer "^2.6.12"
 
-"@nuxt/webpack@2.14.12":
-  version "2.14.12"
-  resolved "https://registry.yarnpkg.com/@nuxt/webpack/-/webpack-2.14.12.tgz#e1c394615056d7fc398f91d719b3937fe25935f2"
-  integrity sha512-fZjs000HVkZ4zvVY5KVnRVBpOxAB4o+cx90rte9GZlU/GaJPZ5Go7KQmxnws0SaAqeN3MorURuu0JU05n3ko9g==
+"@nuxt/webpack@2.15.8":
+  version "2.15.8"
+  resolved "https://registry.yarnpkg.com/@nuxt/webpack/-/webpack-2.15.8.tgz#6169b4b8a13ee2cdb4987df6c5a401e18c412ef1"
+  integrity sha512-CzJYFed23Ow/UK0+cI1FVthDre1p2qc8Q97oizG39d3/SIh3aUHjgj8c60wcR+RSxVO0FzZMXkmq02NmA7vWJg==
   dependencies:
-    "@babel/core" "^7.12.9"
-    "@nuxt/babel-preset-app" "2.14.12"
-    "@nuxt/friendly-errors-webpack-plugin" "^2.5.0"
-    "@nuxt/utils" "2.14.12"
+    "@babel/core" "^7.14.0"
+    "@nuxt/babel-preset-app" "2.15.8"
+    "@nuxt/friendly-errors-webpack-plugin" "^2.5.1"
+    "@nuxt/utils" "2.15.8"
     babel-loader "^8.2.2"
     cache-loader "^4.1.0"
-    caniuse-lite "^1.0.30001164"
-    chalk "^3.0.0"
-    consola "^2.15.0"
-    create-require "^1.1.1"
-    css-loader "^3.6.0"
-    cssnano "^4.1.10"
+    caniuse-lite "^1.0.30001228"
+    consola "^2.15.3"
+    css-loader "^4.3.0"
+    cssnano "^4.1.11"
     eventsource-polyfill "^0.9.6"
-    extract-css-chunks-webpack-plugin "^4.8.0"
-    file-loader "^4.3.0"
-    glob "^7.1.6"
+    extract-css-chunks-webpack-plugin "^4.9.0"
+    file-loader "^6.2.0"
+    glob "^7.1.7"
     hard-source-webpack-plugin "^0.13.1"
     hash-sum "^2.0.0"
-    html-webpack-plugin "^4.5.0"
-    memory-fs "^0.4.1"
+    html-webpack-plugin "^4.5.1"
+    lodash "^4.17.21"
+    memory-fs "^0.5.0"
     optimize-css-assets-webpack-plugin "^5.0.4"
-    pify "^4.0.1"
+    pify "^5.0.0"
+    pnp-webpack-plugin "^1.6.4"
     postcss "^7.0.32"
     postcss-import "^12.0.1"
     postcss-import-resolver "^2.0.0"
     postcss-loader "^3.0.0"
     postcss-preset-env "^6.7.0"
     postcss-url "^8.0.0"
-    semver "^7.3.2"
-    std-env "^2.2.1"
+    semver "^7.3.5"
+    std-env "^2.3.0"
     style-resources-loader "^1.4.1"
-    terser-webpack-plugin "^2.3.5"
-    thread-loader "^2.1.3"
+    terser-webpack-plugin "^4.2.3"
+    thread-loader "^3.0.4"
     time-fix-plugin "^2.0.7"
-    url-loader "^2.3.0"
-    vue-loader "^15.9.5"
-    webpack "^4.44.2"
-    webpack-bundle-analyzer "^3.9.0"
-    webpack-dev-middleware "^3.7.2"
+    ufo "^0.7.4"
+    url-loader "^4.1.1"
+    vue-loader "^15.9.7"
+    vue-style-loader "^4.1.3"
+    vue-template-compiler "^2.6.12"
+    webpack "^4.46.0"
+    webpack-bundle-analyzer "^4.4.1"
+    webpack-dev-middleware "^4.2.0"
     webpack-hot-middleware "^2.25.0"
-    webpack-node-externals "^2.5.2"
+    webpack-node-externals "^3.0.0"
     webpackbar "^4.0.0"
 
 "@nuxtjs/auth-next@^5.0.0-1588866376.2380814":
-  version "5.0.0-1608568767.2fe2217"
-  resolved "https://registry.yarnpkg.com/@nuxtjs/auth-next/-/auth-next-5.0.0-1608568767.2fe2217.tgz#2e87df29cedab5037ef1fe63df151aad1a628dae"
-  integrity sha512-e75XSLqCXwOshi4uRPai8YKUGlJa3NUqJRVk2jhHXFmIzF7IZH9VJoS5HrT8R7vFPsfAvlAXIQeDlj1P5bfXxw==
+  version "5.0.0-1624817847.21691f1"
+  resolved "https://registry.yarnpkg.com/@nuxtjs/auth-next/-/auth-next-5.0.0-1624817847.21691f1.tgz#28b92625ac5817d8083f8b42dd184a88caefbe96"
+  integrity sha512-PsHhLtzglMnwM2o16mgM7zQ3KwTI7AIg2ja3IFYujbs9s1w8HvnRD3byMRj1WZo0vXEBRh3u3nHxKEBIbFe1Xg==
   dependencies:
-    "@nuxtjs/axios" "^5.12.4"
-    axios "^0.21.0"
+    "@nuxtjs/axios" "^5.13.0"
+    axios "^0.21.1"
     body-parser "^1.19.0"
-    consola "^2.15.0"
+    consola "^2.15.3"
     cookie "^0.4.1"
     defu "^3.2.2"
     hasha "^5.2.2"
     jwt-decode "^3.1.2"
     requrl "^3.0.2"
 
-"@nuxtjs/axios@^5.12.0", "@nuxtjs/axios@^5.12.4":
-  version "5.12.5"
-  resolved "https://registry.yarnpkg.com/@nuxtjs/axios/-/axios-5.12.5.tgz#d4a1003052d21e54d93d97a895ca84f58e4bc8d9"
-  integrity sha512-KCZMLRZFYOKcGt9mKxJMH6UJMB6H6g+BF/YxXEYz3Urrf2U2XiNkj6rmBqgw0XLRY5XD9Wm8knTGp6955512fQ==
+"@nuxtjs/axios@^5.12.0", "@nuxtjs/axios@^5.13.0":
+  version "5.13.6"
+  resolved "https://registry.yarnpkg.com/@nuxtjs/axios/-/axios-5.13.6.tgz#6f4bbd98a3a7799a5d2c0726c6ad2a98aa111881"
+  integrity sha512-XS+pOE0xsDODs1zAIbo95A0LKlilvJi8YW0NoXYuq3/jjxGgWDxizZ6Yx0AIIjZOoGsXJOPc0/BcnSEUQ2mFBA==
   dependencies:
     "@nuxtjs/proxy" "^2.1.0"
     axios "^0.21.1"
     axios-retry "^3.1.9"
-    consola "^2.15.0"
-    defu "^3.2.2"
+    consola "^2.15.3"
+    defu "^5.0.0"
 
 "@nuxtjs/eslint-config@^3.1.0":
   version "3.1.0"
@@ -1527,16 +1595,15 @@
     http-proxy-middleware "^1.0.6"
 
 "@nuxtjs/vuetify@^1.11.2":
-  version "1.11.2"
-  resolved "https://registry.yarnpkg.com/@nuxtjs/vuetify/-/vuetify-1.11.2.tgz#fefa861d98c021e10dd579a5b91b34b3fb49dc99"
-  integrity sha512-8+k/PQG37OAoXvXgKE+BkBQXaoBCz9odK8oPYA4lwmxQ0ekHnh4PFrU/6Fr+OeVHbQbynbuMZnkF9aWxDsTqug==
+  version "1.12.1"
+  resolved "https://registry.yarnpkg.com/@nuxtjs/vuetify/-/vuetify-1.12.1.tgz#87dd1e1517b0120c660f4a43a22627c9fe124189"
+  integrity sha512-oNwNhR6LY7l9ETsNyPkmCxgzbOYuAf27m+6E9mjQzHSu8PPI0vJ3xnGLgo87XnTcnWr9nYxqjwRN8xqMuuyoxQ==
   dependencies:
     deepmerge "^4.2.2"
-    fibers "^4.0.3"
-    sass "^1.26.5"
-    sass-loader "^8.0.2"
-    vuetify "^2"
-    vuetify-loader "^1.4.3"
+    sass "~1.32.13"
+    sass-loader "^10.2.0"
+    vuetify "^2.5.3"
+    vuetify-loader "^1.7.2"
 
 "@nuxtjs/youch@^4.2.3":
   version "4.2.3"
@@ -1547,51 +1614,15 @@
     mustache "^2.3.0"
     stack-trace "0.0.10"
 
-"@parcel/fs@^1.11.0":
-  version "1.11.0"
-  resolved "https://registry.yarnpkg.com/@parcel/fs/-/fs-1.11.0.tgz#fb8a2be038c454ad46a50dc0554c1805f13535cd"
-  integrity sha512-86RyEqULbbVoeo8OLcv+LQ1Vq2PKBAvWTU9fCgALxuCTbbs5Ppcvll4Vr+Ko1AnmMzja/k++SzNAwJfeQXVlpA==
-  dependencies:
-    "@parcel/utils" "^1.11.0"
-    mkdirp "^0.5.1"
-    rimraf "^2.6.2"
-
-"@parcel/logger@^1.11.1":
-  version "1.11.1"
-  resolved "https://registry.yarnpkg.com/@parcel/logger/-/logger-1.11.1.tgz#c55b0744bcbe84ebc291155627f0ec406a23e2e6"
-  integrity sha512-9NF3M6UVeP2udOBDILuoEHd8VrF4vQqoWHEafymO1pfSoOMfxrSJZw1MfyAAIUN/IFp9qjcpDCUbDZB+ioVevA==
-  dependencies:
-    "@parcel/workers" "^1.11.0"
-    chalk "^2.1.0"
-    grapheme-breaker "^0.3.2"
-    ora "^2.1.0"
-    strip-ansi "^4.0.0"
-
-"@parcel/utils@^1.11.0":
-  version "1.11.0"
-  resolved "https://registry.yarnpkg.com/@parcel/utils/-/utils-1.11.0.tgz#539e08fff8af3b26eca11302be80b522674b51ea"
-  integrity sha512-cA3p4jTlaMeOtAKR/6AadanOPvKeg8VwgnHhOyfi0yClD0TZS/hi9xu12w4EzA/8NtHu0g6o4RDfcNjqN8l1AQ==
-
-"@parcel/watcher@^1.12.1":
-  version "1.12.1"
-  resolved "https://registry.yarnpkg.com/@parcel/watcher/-/watcher-1.12.1.tgz#b98b3df309fcab93451b5583fc38e40826696dad"
-  integrity sha512-od+uCtCxC/KoNQAIE1vWx1YTyKYY+7CTrxBJPRh3cDWw/C0tCtlBMVlrbplscGoEpt6B27KhJDCv82PBxOERNA==
-  dependencies:
-    "@parcel/utils" "^1.11.0"
-    chokidar "^2.1.5"
-
-"@parcel/workers@^1.11.0":
-  version "1.11.0"
-  resolved "https://registry.yarnpkg.com/@parcel/workers/-/workers-1.11.0.tgz#7b8dcf992806f4ad2b6cecf629839c41c2336c59"
-  integrity sha512-USSjRAAQYsZFlv43FUPdD+jEGML5/8oLF0rUzPQTtK4q9kvaXr49F5ZplyLz5lox78cLZ0TxN2bIDQ1xhOkulQ==
-  dependencies:
-    "@parcel/utils" "^1.11.0"
-    physical-cpu-count "^2.0.0"
+"@polka/url@^1.0.0-next.20":
+  version "1.0.0-next.20"
+  resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.20.tgz#111b5db0f501aa89b05076fa31f0ea0e0c292cd3"
+  integrity sha512-88p7+M0QGxKpmnkfXjS4V26AnoC/eiqZutE8GLdaI5X12NY75bXSdTY9NkmYb2Xyk1O+MmkuO6Frmsj84V6I8Q==
 
 "@sinonjs/commons@^1.7.0":
-  version "1.8.1"
-  resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.1.tgz#e7df00f98a203324f6dc7cc606cad9d4a8ab2217"
-  integrity sha512-892K+kWUUi3cl+LlqEWIDrhvLgdL79tECi8JZUyq6IviKy/DNhuzCRlbHUjxK89f4ypPMMaFnFuR9Ie6DoIMsw==
+  version "1.8.3"
+  resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.3.tgz#3802ddd21a50a949b6721ddd72da36e67e7f1b2d"
+  integrity sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==
   dependencies:
     type-detect "4.0.8"
 
@@ -1602,15 +1633,15 @@
   dependencies:
     "@sinonjs/commons" "^1.7.0"
 
-"@types/anymatch@*":
-  version "1.3.1"
-  resolved "https://registry.yarnpkg.com/@types/anymatch/-/anymatch-1.3.1.tgz#336badc1beecb9dacc38bea2cf32adf627a8421a"
-  integrity sha512-/+CRPXpBDpo2RK9C68N3b2cOvO0Cf5B9aPijHsoDQTHivnGSObdOF2BRQOYjojWTDy6nQvMjmqRXIxH55VjxxA==
+"@tootallnate/once@1":
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82"
+  integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==
 
 "@types/babel__core@^7.0.0", "@types/babel__core@^7.1.7":
-  version "7.1.12"
-  resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.12.tgz#4d8e9e51eb265552a7e4f1ff2219ab6133bdfb2d"
-  integrity sha512-wMTHiiTiBAAPebqaPiPDLFA4LYPKr6Ph0Xq/6rq1Ur3v66HXyG+clfR9CNETkD7MQS8ZHvpQOtA53DLws5WAEQ==
+  version "7.1.15"
+  resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.15.tgz#2ccfb1ad55a02c83f8e0ad327cbc332f55eb1024"
+  integrity sha512-bxlMKPDbY8x5h6HBwVzEOk2C8fb6SLfYQ5Jw3uBYuYF1lfWk/kbLd81la82vrIkBb0l+JdmrZaDikPrNxpS/Ew==
   dependencies:
     "@babel/parser" "^7.1.0"
     "@babel/types" "^7.0.0"
@@ -1619,268 +1650,43 @@
     "@types/babel__traverse" "*"
 
 "@types/babel__generator@*":
-  version "7.6.2"
-  resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.2.tgz#f3d71178e187858f7c45e30380f8f1b7415a12d8"
-  integrity sha512-MdSJnBjl+bdwkLskZ3NGFp9YcXGx5ggLpQQPqtgakVhsWK0hTtNYhjpZLlWQTviGTvF8at+Bvli3jV7faPdgeQ==
+  version "7.6.3"
+  resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.3.tgz#f456b4b2ce79137f768aa130d2423d2f0ccfaba5"
+  integrity sha512-/GWCmzJWqV7diQW54smJZzWbSFf4QYtF71WCKhcx6Ru/tFyQIY2eiiITcCAeuPbNSvT9YCGkVMqqvSk2Z0mXiA==
   dependencies:
     "@babel/types" "^7.0.0"
 
 "@types/babel__template@*":
-  version "7.4.0"
-  resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.4.0.tgz#0c888dd70b3ee9eebb6e4f200e809da0076262be"
-  integrity sha512-NTPErx4/FiPCGScH7foPyr+/1Dkzkni+rHiYHHoTjvwou7AQzJkNeD60A9CXRy+ZEN2B1bggmkTMCDb+Mv5k+A==
+  version "7.4.1"
+  resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.4.1.tgz#3d1a48fd9d6c0edfd56f2ff578daed48f36c8969"
+  integrity sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==
   dependencies:
     "@babel/parser" "^7.1.0"
     "@babel/types" "^7.0.0"
 
 "@types/babel__traverse@*", "@types/babel__traverse@^7.0.4", "@types/babel__traverse@^7.0.6":
-  version "7.11.0"
-  resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.11.0.tgz#b9a1efa635201ba9bc850323a8793ee2d36c04a0"
-  integrity sha512-kSjgDMZONiIfSH1Nxcr5JIRMwUetDki63FSQfpTCz8ogF3Ulqm8+mr5f78dUYs6vMiB6gBusQqfQmBvHZj/lwg==
+  version "7.14.2"
+  resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.14.2.tgz#ffcd470bbb3f8bf30481678fb5502278ca833a43"
+  integrity sha512-K2waXdXBi2302XUdcHcR1jCeU0LL4TD9HRs/gk0N2Xvrht+G/BfJa4QObBQZfhMdxiCpV3COl5Nfq4uKTeTnJA==
   dependencies:
     "@babel/types" "^7.3.0"
 
-"@types/d3-array@*":
-  version "2.8.0"
-  resolved "https://registry.yarnpkg.com/@types/d3-array/-/d3-array-2.8.0.tgz#4b70ccb0c6d2ef28dac1e7e653b3ecd1f4b1d1ee"
-  integrity sha512-Q0ubcGHAmCRPh90/hoYB4eKWhxYKUxphwSeQrlz2tiabQ8S9zqhaE2CZJtCaLH2cjqKcjr52WPvmOA7ha0O4ZA==
-
-"@types/d3-axis@*":
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/@types/d3-axis/-/d3-axis-2.0.0.tgz#a3e7534d3c399c20ba42ec3093dd2a385659366e"
-  integrity sha512-gUdlEwGBLl3tXGiBnBNmNzph9W3bCfa4tBgWZD60Z1eDQKTY4zyCAcZ3LksignGfKawYatmDYcBdjJ5h/54sqA==
-  dependencies:
-    "@types/d3-selection" "*"
-
-"@types/d3-brush@*":
-  version "2.1.0"
-  resolved "https://registry.yarnpkg.com/@types/d3-brush/-/d3-brush-2.1.0.tgz#c51ad1ab93887b23be7637d2100540f1df0dac00"
-  integrity sha512-rLQqxQeXWF4ArXi81GlV8HBNwJw9EDpz0jcWvvzv548EDE4tXrayBTOHYi/8Q4FZ/Df8PGXFzxpAVQmJMjOtvQ==
-  dependencies:
-    "@types/d3-selection" "*"
-
-"@types/d3-chord@*":
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/@types/d3-chord/-/d3-chord-2.0.0.tgz#8d7085e2828418f2c5087e512f276559499bacfd"
-  integrity sha512-3nHsLY7lImpZlM/hrPeDqqW2a+lRXXoHsG54QSurDGihZAIE/doQlohs0evoHrWOJqXyn4A4xbSVEtXnMEZZiw==
-
-"@types/d3-color@*":
-  version "2.0.1"
-  resolved "https://registry.yarnpkg.com/@types/d3-color/-/d3-color-2.0.1.tgz#570ea7f8b853461301804efa52bd790a640a26db"
-  integrity sha512-u7LTCL7RnaavFSmob2rIAJLNwu50i6gFwY9cHFr80BrQURYQBRkJ+Yv47nA3Fm7FeRhdWTiVTeqvSeOuMAOzBQ==
-
-"@types/d3-contour@*":
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/@types/d3-contour/-/d3-contour-2.0.0.tgz#6e079f281b29a8df3fcbd3ec193f2cf1d0b4a584"
-  integrity sha512-PS9UO6zBQqwHXsocbpdzZFONgK1oRUgWtjjh/iz2vM06KaXLInLiKZ9e3OLBRerc1cU2uJYpO+8zOnb6frvCGQ==
-  dependencies:
-    "@types/d3-array" "*"
-    "@types/geojson" "*"
-
-"@types/d3-delaunay@*":
-  version "5.3.0"
-  resolved "https://registry.yarnpkg.com/@types/d3-delaunay/-/d3-delaunay-5.3.0.tgz#416169bb5c67a510c87b55d092a404fcab49def3"
-  integrity sha512-gJYcGxLu0xDZPccbUe32OUpeaNtd1Lz0NYJtko6ZLMyG2euF4pBzrsQXms67LHZCDFzzszw+dMhSL/QAML3bXw==
-
-"@types/d3-dispatch@*":
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/@types/d3-dispatch/-/d3-dispatch-2.0.0.tgz#1f8803041b73b81f2c751e026b7bb63dd5f24ce0"
-  integrity sha512-Sh0KW6z/d7uxssD7K4s4uCSzlEG/+SP+U47q098NVdOfFvUKNTvKAIV4XqjxsUuhE/854ARAREHOxkr9gQOCyg==
-
-"@types/d3-drag@*":
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/@types/d3-drag/-/d3-drag-2.0.0.tgz#ef66acc422576fbe10b8bd66af45a9fb8525199a"
-  integrity sha512-VaUJPjbMnDn02tcRqsHLRAX5VjcRIzCjBfeXTLGe6QjMn5JccB5Cz4ztMRXMJfkbC45ovgJFWuj6DHvWMX1thA==
-  dependencies:
-    "@types/d3-selection" "*"
-
-"@types/d3-dsv@*":
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/@types/d3-dsv/-/d3-dsv-2.0.0.tgz#c9fb8b2f0f7168d21a6bbd29492141bfd1b8db16"
-  integrity sha512-wYqy7T8tQ/DmocwxmlPujllLI5fg3lb6/FrVVWkLUD+NsRV+kcE4nbRZg10G9yjJ8pK2ZXqu+VP5jQbN13uNRQ==
-
-"@types/d3-ease@*":
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/@types/d3-ease/-/d3-ease-2.0.0.tgz#798cbd9908d26cfe9f1a295a3a75164da9a3666e"
-  integrity sha512-6aZrTyX5LG+ptofVHf+gTsThLRY1nhLotJjgY4drYqk1OkJMu2UvuoZRlPw2fffjRHeYepue3/fxTufqKKmvsA==
-
-"@types/d3-fetch@*":
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/@types/d3-fetch/-/d3-fetch-2.0.0.tgz#580846256ed0011b36a08ebb36924e0dff70e27e"
-  integrity sha512-WnLepGtxepFfXRdPI8I5FTgNiHn9p4vMTTqaNCzJJfAswXx0rOY2jjeolzEU063em3iJmGZ+U79InnEeFOrCRw==
-  dependencies:
-    "@types/d3-dsv" "*"
-
-"@types/d3-force@*":
-  version "2.1.0"
-  resolved "https://registry.yarnpkg.com/@types/d3-force/-/d3-force-2.1.0.tgz#6a2210f04d02a0862c6b069de91bad904143e7b5"
-  integrity sha512-LGDtC2YADu8OBniq9EBx/MOsXsMcJbEkmfSpXuz6oVdRamB+3CLCiq5EKFPEILGZQckkilGFq1ZTJ7kc289k+Q==
-
-"@types/d3-format@*":
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/@types/d3-format/-/d3-format-2.0.0.tgz#607d261cb268f0a027f100575491031539a40ee6"
-  integrity sha512-uagdkftxnGkO4pZw5jEYOM5ZnZOEsh7z8j11Qxk85UkB2RzfUUxRl7R9VvvJZHwKn8l+x+rpS77Nusq7FkFmIg==
-
-"@types/d3-geo@*":
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/@types/d3-geo/-/d3-geo-2.0.0.tgz#6f179512343c2d30e06acde190abfacf44b2d264"
-  integrity sha512-DHHgYXW36lnAEQMYU2udKVOxxljHrn2EdOINeSC9jWCAXwOnGn7A19B8sNsHqgpu4F7O2bSD7//cqBXD3W0Deg==
-  dependencies:
-    "@types/geojson" "*"
-
-"@types/d3-hierarchy@*":
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/@types/d3-hierarchy/-/d3-hierarchy-2.0.0.tgz#92079d9dbcec1dfe2736fb050a8bf916e5850a1c"
-  integrity sha512-YxdskUvwzqggpnSnDQj4KVkicgjpkgXn/g/9M9iGsiToLS3nG6Ytjo1FoYhYVAAElV/fJBGVL3cQ9Hb7tcv+lw==
-
-"@types/d3-interpolate@*":
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/@types/d3-interpolate/-/d3-interpolate-2.0.0.tgz#325029216dc722c1c68c33ccda759f1209d35823"
-  integrity sha512-Wt1v2zTlEN8dSx8hhx6MoOhWQgTkz0Ukj7owAEIOF2QtI0e219paFX9rf/SLOr/UExWb1TcUzatU8zWwFby6gg==
-  dependencies:
-    "@types/d3-color" "*"
-
-"@types/d3-path@*":
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/@types/d3-path/-/d3-path-2.0.0.tgz#dcc7f5ecadf52b0c0c39f6c1def3733195e4b199"
-  integrity sha512-tXcR/9OtDdeCIsyl6eTNHC3XOAOdyc6ceF3QGBXOd9jTcK+ex/ecr00p9L9362e/op3UEPpxrToi1FHrtTSj7Q==
-
-"@types/d3-path@^1":
-  version "1.0.9"
-  resolved "https://registry.yarnpkg.com/@types/d3-path/-/d3-path-1.0.9.tgz#73526b150d14cd96e701597cbf346cfd1fd4a58c"
-  integrity sha512-NaIeSIBiFgSC6IGUBjZWcscUJEq7vpVu7KthHN8eieTV9d9MqkSOZLH4chq1PmcKy06PNe3axLeKmRIyxJ+PZQ==
-
-"@types/d3-polygon@*":
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/@types/d3-polygon/-/d3-polygon-2.0.0.tgz#8b1df0a1358016e62c4961b01e8dc8e5ab4c64e5"
-  integrity sha512-fISnMd8ePED1G4aa4V974Jmt+ajHSgPoxMa2D0ULxMybpx0Vw4WEzhQEaMIrL3hM8HVRcKTx669I+dTy/4PhAw==
-
-"@types/d3-quadtree@*":
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/@types/d3-quadtree/-/d3-quadtree-2.0.0.tgz#b17e953dc061e083966075bba0d3a9a259812150"
-  integrity sha512-YZuJuGBnijD0H+98xMJD4oZXgv/umPXy5deu3IimYTPGH3Kr8Th6iQUff0/6S80oNBD7KtOuIHwHUCymUiRoeQ==
-
-"@types/d3-random@*":
-  version "2.2.0"
-  resolved "https://registry.yarnpkg.com/@types/d3-random/-/d3-random-2.2.0.tgz#fc44cabb966917459490b758f31f5359adeabe5b"
-  integrity sha512-Hjfj9m68NmYZzushzEG7etPvKH/nj9b9s9+qtkNG3/dbRBjQZQg1XS6nRuHJcCASTjxXlyXZnKu2gDxyQIIu9A==
-
-"@types/d3-scale-chromatic@*":
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/@types/d3-scale-chromatic/-/d3-scale-chromatic-2.0.0.tgz#8d4a6f07cbbf2a9f2a4bec9c9476c27ed76a96ea"
-  integrity sha512-Y62+2clOwZoKua84Ha0xU77w7lePiaBoTjXugT4l8Rd5LAk+Mn/ZDtrgs087a+B5uJ3jYUHHtKw5nuEzp0WBHw==
-
-"@types/d3-scale@*":
-  version "3.2.2"
-  resolved "https://registry.yarnpkg.com/@types/d3-scale/-/d3-scale-3.2.2.tgz#5e28d0b1c599328aaec6094219f10a2570be6d74"
-  integrity sha512-qpQe8G02tzUwt9sdWX1h8A/W0Q1+N48wMnYXVOkrzeLUkCfvzJYV9Ee3aORCS4dN4ONRLFmMvaXdziQ29XGLjQ==
-  dependencies:
-    "@types/d3-time" "*"
-
-"@types/d3-selection@*":
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/@types/d3-selection/-/d3-selection-2.0.0.tgz#59df94a8e47ed1050a337d4ffb4d4d213aa590a8"
-  integrity sha512-EF0lWZ4tg7oDFg4YQFlbOU3936e3a9UmoQ2IXlBy1+cv2c2Pv7knhKUzGlH5Hq2sF/KeDTH1amiRPey2rrLMQA==
-
-"@types/d3-shape@*":
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/@types/d3-shape/-/d3-shape-2.0.0.tgz#61aa065726f3c2641aedc59c3603475ab11aeb2f"
-  integrity sha512-NLzD02m5PiD1KLEDjLN+MtqEcFYn4ZL9+Rqc9ZwARK1cpKZXd91zBETbe6wpBB6Ia0D0VZbpmbW3+BsGPGnCpA==
-  dependencies:
-    "@types/d3-path" "^1"
-
-"@types/d3-time-format@*":
-  version "3.0.0"
-  resolved "https://registry.yarnpkg.com/@types/d3-time-format/-/d3-time-format-3.0.0.tgz#913e984362a59792dc8d8b122dd17625991eade2"
-  integrity sha512-UpLg1mn/8PLyjr+J/JwdQJM/GzysMvv2CS8y+WYAL5K0+wbvXv/pPSLEfdNaprCZsGcXTxPsFMy8QtkYv9ueew==
-
-"@types/d3-time@*":
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/@types/d3-time/-/d3-time-2.0.0.tgz#831dd093db91f16b83ba980e194bb8e4bcef44d6"
-  integrity sha512-Abz8bTzy8UWDeYs9pCa3D37i29EWDjNTjemdk0ei1ApYVNqulYlGUKip/jLOpogkPSsPz/GvZCYiC7MFlEk0iQ==
-
-"@types/d3-timer@*":
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/@types/d3-timer/-/d3-timer-2.0.0.tgz#9901bb02af38798764674df17d66b07329705632"
-  integrity sha512-l6stHr1VD1BWlW6u3pxrjLtJfpPZq9I3XmKIQtq7zHM/s6fwEtI1Yn6Sr5/jQTrUDCC5jkS6gWqlFGCDArDqNg==
-
-"@types/d3-transition@*":
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/@types/d3-transition/-/d3-transition-2.0.0.tgz#6f073f0b567c13b7a3dcd1d54214c89f48c5a873"
-  integrity sha512-UJDzI98utcZQUJt3uIit/Ho0/eBIANzrWJrTmi4+TaKIyWL2iCu7ShP0o4QajCskhyjOA7C8+4CE3b1YirTzEQ==
-  dependencies:
-    "@types/d3-selection" "*"
-
-"@types/d3-zoom@*":
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/@types/d3-zoom/-/d3-zoom-2.0.0.tgz#ef8b87464e8ebc7c66b70f6383d1ae841e78e7fc"
-  integrity sha512-daL0PJm4yT0ISTGa7p2lHX0kvv9FO/IR1ooWbHR/7H4jpbaKiLux5FslyS/OvISPiJ5SXb4sOqYhO6fMB6hKRw==
-  dependencies:
-    "@types/d3-interpolate" "*"
-    "@types/d3-selection" "*"
-
-"@types/d3@^3":
-  version "3.5.44"
-  resolved "https://registry.yarnpkg.com/@types/d3/-/d3-3.5.44.tgz#28635f8bb9adf1cef5bbef2b06778174a9d34383"
-  integrity sha512-hFEcf03YGJ2uQoDYEp3nFD5mXWxly5kf6KOstuOQFEs9sUCN7kNlKhcYkpZ3gK6PiHz4XRLkoHa80NVCJNeLBw==
-
-"@types/d3@^6.2.0":
-  version "6.2.0"
-  resolved "https://registry.yarnpkg.com/@types/d3/-/d3-6.2.0.tgz#db3c70ad6479cf79b15840a3d15338a9754384e7"
-  integrity sha512-XhQ6sCTu+CrFLqJMsg/uRPZQrt5FlCPjPE/wvsSBYoaOZ9C1chdJSS9+2oR8+Xtk6DKGewa7/UP5icJRwAryEA==
-  dependencies:
-    "@types/d3-array" "*"
-    "@types/d3-axis" "*"
-    "@types/d3-brush" "*"
-    "@types/d3-chord" "*"
-    "@types/d3-color" "*"
-    "@types/d3-contour" "*"
-    "@types/d3-delaunay" "*"
-    "@types/d3-dispatch" "*"
-    "@types/d3-drag" "*"
-    "@types/d3-dsv" "*"
-    "@types/d3-ease" "*"
-    "@types/d3-fetch" "*"
-    "@types/d3-force" "*"
-    "@types/d3-format" "*"
-    "@types/d3-geo" "*"
-    "@types/d3-hierarchy" "*"
-    "@types/d3-interpolate" "*"
-    "@types/d3-path" "*"
-    "@types/d3-polygon" "*"
-    "@types/d3-quadtree" "*"
-    "@types/d3-random" "*"
-    "@types/d3-scale" "*"
-    "@types/d3-scale-chromatic" "*"
-    "@types/d3-selection" "*"
-    "@types/d3-shape" "*"
-    "@types/d3-time" "*"
-    "@types/d3-time-format" "*"
-    "@types/d3-timer" "*"
-    "@types/d3-transition" "*"
-    "@types/d3-zoom" "*"
-
-"@types/geojson@*":
-  version "7946.0.7"
-  resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-7946.0.7.tgz#c8fa532b60a0042219cdf173ca21a975ef0666ad"
-  integrity sha512-wE2v81i4C4Ol09RtsWFAqg3BUitWbHSpSlIo+bNdsCJijO9sjme+zm+73ZMCa/qMC8UEERxzGbvmr1cffo2SiQ==
-
 "@types/graceful-fs@^4.1.2":
-  version "4.1.4"
-  resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.4.tgz#4ff9f641a7c6d1a3508ff88bc3141b152772e753"
-  integrity sha512-mWA/4zFQhfvOA8zWkXobwJvBD7vzcxgrOQ0J5CH1votGqdq9m7+FwtGaqyCZqC3NyyBkc9z4m+iry4LlqcMWJg==
+  version "4.1.5"
+  resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.5.tgz#21ffba0d98da4350db64891f92a9e5db3cdb4e15"
+  integrity sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw==
   dependencies:
     "@types/node" "*"
 
 "@types/html-minifier-terser@^5.0.0":
-  version "5.1.1"
-  resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-5.1.1.tgz#3c9ee980f1a10d6021ae6632ca3e79ca2ec4fb50"
-  integrity sha512-giAlZwstKbmvMk1OO7WXSj4OZ0keXAcl2TQq4LWHiiPH2ByaH7WeUzng+Qej8UPxxv+8lRTuouo0iaNDBuzIBA==
+  version "5.1.2"
+  resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-5.1.2.tgz#693b316ad323ea97eed6b38ed1a3cc02b1672b57"
+  integrity sha512-h4lTMgMJctJybDp8CQrxTUiiYmedihHWkjnF/8Pxseu2S6Nlfcy8kwboQ8yejh456rP2yWoEVm1sS/FVsfM48w==
 
-"@types/http-proxy@^1.17.4":
-  version "1.17.4"
-  resolved "https://registry.yarnpkg.com/@types/http-proxy/-/http-proxy-1.17.4.tgz#e7c92e3dbe3e13aa799440ff42e6d3a17a9d045b"
-  integrity sha512-IrSHl2u6AWXduUaDLqYpt45tLVCtYv7o4Z0s1KghBCDgIIS9oW5K1H8mZG/A2CfeLdEa7rTd1ACOiHBc1EMT2Q==
+"@types/http-proxy@^1.17.5":
+  version "1.17.7"
+  resolved "https://registry.yarnpkg.com/@types/http-proxy/-/http-proxy-1.17.7.tgz#30ea85cc2c868368352a37f0d0d3581e24834c6f"
+  integrity sha512-9hdj6iXH64tHSLTY+Vt2eYOGzSogC+JQ2H7bdPWkuh7KXP5qLllWx++t+K9Wk556c3dkDdPws/SpMRi0sdCT1w==
   dependencies:
     "@types/node" "*"
 
@@ -1897,16 +1703,16 @@
     "@types/istanbul-lib-coverage" "*"
 
 "@types/istanbul-reports@^3.0.0":
-  version "3.0.0"
-  resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.0.tgz#508b13aa344fa4976234e75dddcc34925737d821"
-  integrity sha512-nwKNbvnwJ2/mndE9ItP/zc2TCzw6uuodnF4EHYWD+gCQDVBuRQL5UzbZD0/ezy1iKsFU2ZQiDqg4M9dN4+wZgA==
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz#9153fe98bba2bd565a63add9436d6f0d7f8468ff"
+  integrity sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==
   dependencies:
     "@types/istanbul-lib-report" "*"
 
-"@types/json-schema@^7.0.3", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.6":
-  version "7.0.6"
-  resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.6.tgz#f4c7ec43e81b319a9815115031709f26987891f0"
-  integrity sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw==
+"@types/json-schema@^7.0.3", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8":
+  version "7.0.9"
+  resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d"
+  integrity sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==
 
 "@types/json5@^0.0.29":
   version "0.0.29"
@@ -1914,132 +1720,24 @@
   integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4=
 
 "@types/node@*":
-  version "14.14.20"
-  resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.20.tgz#f7974863edd21d1f8a494a73e8e2b3658615c340"
-  integrity sha512-Y93R97Ouif9JEOWPIUyU+eyIdyRqQR0I8Ez1dzku4hDx34NWh4HbtIc3WNzwB1Y9ULvNGeu5B8h8bVL5cAk4/A==
+  version "16.7.10"
+  resolved "https://registry.yarnpkg.com/@types/node/-/node-16.7.10.tgz#7aa732cc47341c12a16b7d562f519c2383b6d4fc"
+  integrity sha512-S63Dlv4zIPb8x6MMTgDq5WWRJQe56iBEY0O3SOFA9JrRienkOVDXSXBjjJw6HTNQYSE2JI6GMCR6LVbIMHJVvA==
 
 "@types/normalize-package-data@^2.4.0":
-  version "2.4.0"
-  resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz#e486d0d97396d79beedd0a6e33f4534ff6b4973e"
-  integrity sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA==
-
-"@types/plotly.js@^1.54.2":
-  version "1.54.7"
-  resolved "https://registry.yarnpkg.com/@types/plotly.js/-/plotly.js-1.54.7.tgz#db784d781e17d66482cee91ea5e72d61589ab043"
-  integrity sha512-4oNu0FHeMnL7ZB45MOs+MEstw0GvCVBRg2YvABrIPbN/hy65wg0Cy8Z0pyGwAXaXL9BeXjJJhQqFawjwZgobbQ==
-  dependencies:
-    "@types/d3" "^3"
+  version "2.4.1"
+  resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz#d3357479a0fdfdd5907fe67e17e0a85c906e1301"
+  integrity sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==
 
 "@types/prettier@^2.0.0":
-  version "2.1.6"
-  resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.1.6.tgz#f4b1efa784e8db479cdb8b14403e2144b1e9ff03"
-  integrity sha512-6gOkRe7OIioWAXfnO/2lFiv+SJichKVSys1mSsgyrYHSEjk8Ctv4tSR/Odvnu+HWlH2C8j53dahU03XmQdd5fA==
+  version "2.3.2"
+  resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.3.2.tgz#fc8c2825e4ed2142473b4a81064e6e081463d1b3"
+  integrity sha512-eI5Yrz3Qv4KPUa/nSIAi0h+qX0XyewOliug5F2QAtuRg6Kjg6jfmxe1GIwoIRhZspD1A0RP8ANrPwvEXXtRFog==
 
 "@types/q@^1.5.1":
-  version "1.5.4"
-  resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.4.tgz#15925414e0ad2cd765bfef58842f7e26a7accb24"
-  integrity sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug==
-
-"@types/rx-core-binding@*":
-  version "4.0.4"
-  resolved "https://registry.yarnpkg.com/@types/rx-core-binding/-/rx-core-binding-4.0.4.tgz#d969d32f15a62b89e2862c17b3ee78fe329818d3"
-  integrity sha512-5pkfxnC4w810LqBPUwP5bg7SFR/USwhMSaAeZQQbEHeBp57pjKXRlXmqpMrLJB4y1oglR/c2502853uN0I+DAQ==
-  dependencies:
-    "@types/rx-core" "*"
-
-"@types/rx-core@*":
-  version "4.0.3"
-  resolved "https://registry.yarnpkg.com/@types/rx-core/-/rx-core-4.0.3.tgz#0b3354b1238cedbe2b74f6326f139dbc7a591d60"
-  integrity sha1-CzNUsSOM7b4rdPYybxOdvHpZHWA=
-
-"@types/rx-lite-aggregates@*":
-  version "4.0.3"
-  resolved "https://registry.yarnpkg.com/@types/rx-lite-aggregates/-/rx-lite-aggregates-4.0.3.tgz#6efb2b7f3d5f07183a1cb2bd4b1371d7073384c2"
-  integrity sha512-MAGDAHy8cRatm94FDduhJF+iNS5//jrZ/PIfm+QYw9OCeDgbymFHChM8YVIvN2zArwsRftKgE33QfRWvQk4DPg==
-  dependencies:
-    "@types/rx-lite" "*"
-
-"@types/rx-lite-async@*":
-  version "4.0.2"
-  resolved "https://registry.yarnpkg.com/@types/rx-lite-async/-/rx-lite-async-4.0.2.tgz#27fbf0caeff029f41e2d2aae638b05e91ceb600c"
-  integrity sha512-vTEv5o8l6702ZwfAM5aOeVDfUwBSDOs+ARoGmWAKQ6LOInQ8J4/zjM7ov12fuTpktUKdMQjkeCp07Vd73mPkxw==
-  dependencies:
-    "@types/rx-lite" "*"
-
-"@types/rx-lite-backpressure@*":
-  version "4.0.3"
-  resolved "https://registry.yarnpkg.com/@types/rx-lite-backpressure/-/rx-lite-backpressure-4.0.3.tgz#05abb19bdf87cc740196c355e5d0b37bb50b5d56"
-  integrity sha512-Y6aIeQCtNban5XSAF4B8dffhIKu6aAy/TXFlScHzSxh6ivfQBQw6UjxyEJxIOt3IT49YkS+siuayM2H/Q0cmgA==
-  dependencies:
-    "@types/rx-lite" "*"
-
-"@types/rx-lite-coincidence@*":
-  version "4.0.3"
-  resolved "https://registry.yarnpkg.com/@types/rx-lite-coincidence/-/rx-lite-coincidence-4.0.3.tgz#80bd69acc4054a15cdc1638e2dc8843498cd85c0"
-  integrity sha512-1VNJqzE9gALUyMGypDXZZXzR0Tt7LC9DdAZQ3Ou/Q0MubNU35agVUNXKGHKpNTba+fr8GdIdkC26bRDqtCQBeQ==
-  dependencies:
-    "@types/rx-lite" "*"
-
-"@types/rx-lite-experimental@*":
-  version "4.0.1"
-  resolved "https://registry.yarnpkg.com/@types/rx-lite-experimental/-/rx-lite-experimental-4.0.1.tgz#c532f5cbdf3f2c15da16ded8930d1b2984023cbd"
-  integrity sha1-xTL1y98/LBXaFt7Ykw0bKYQCPL0=
-  dependencies:
-    "@types/rx-lite" "*"
-
-"@types/rx-lite-joinpatterns@*":
-  version "4.0.1"
-  resolved "https://registry.yarnpkg.com/@types/rx-lite-joinpatterns/-/rx-lite-joinpatterns-4.0.1.tgz#f70fe370518a8432f29158cc92ffb56b4e4afc3e"
-  integrity sha1-9w/jcFGKhDLykVjMkv+1a05K/D4=
-  dependencies:
-    "@types/rx-lite" "*"
-
-"@types/rx-lite-testing@*":
-  version "4.0.1"
-  resolved "https://registry.yarnpkg.com/@types/rx-lite-testing/-/rx-lite-testing-4.0.1.tgz#21b19d11f4dfd6ffef5a9d1648e9c8879bfe21e9"
-  integrity sha1-IbGdEfTf1v/vWp0WSOnIh5v+Iek=
-  dependencies:
-    "@types/rx-lite-virtualtime" "*"
-
-"@types/rx-lite-time@*":
-  version "4.0.3"
-  resolved "https://registry.yarnpkg.com/@types/rx-lite-time/-/rx-lite-time-4.0.3.tgz#0eda65474570237598f3448b845d2696f2dbb1c4"
-  integrity sha512-ukO5sPKDRwCGWRZRqPlaAU0SKVxmWwSjiOrLhoQDoWxZWg6vyB9XLEZViKOzIO6LnTIQBlk4UylYV0rnhJLxQw==
-  dependencies:
-    "@types/rx-lite" "*"
-
-"@types/rx-lite-virtualtime@*":
-  version "4.0.3"
-  resolved "https://registry.yarnpkg.com/@types/rx-lite-virtualtime/-/rx-lite-virtualtime-4.0.3.tgz#4b30cacd0fe2e53af29f04f7438584c7d3959537"
-  integrity sha512-3uC6sGmjpOKatZSVHI2xB1+dedgml669ZRvqxy+WqmGJDVusOdyxcKfyzjW0P3/GrCiN4nmRkLVMhPwHCc5QLg==
-  dependencies:
-    "@types/rx-lite" "*"
-
-"@types/rx-lite@*":
-  version "4.0.6"
-  resolved "https://registry.yarnpkg.com/@types/rx-lite/-/rx-lite-4.0.6.tgz#3c02921c4244074234f26b772241bcc20c18c253"
-  integrity sha512-oYiDrFIcor9zDm0VDUca1UbROiMYBxMLMaM6qzz4ADAfOmA9r1dYEcAFH+2fsPI5BCCjPvV9pWC3X3flbrvs7w==
-  dependencies:
-    "@types/rx-core" "*"
-    "@types/rx-core-binding" "*"
-
-"@types/rx@^4.1.1":
-  version "4.1.2"
-  resolved "https://registry.yarnpkg.com/@types/rx/-/rx-4.1.2.tgz#a4061b3d72b03cf11a38d69e2022a17334c54dc0"
-  integrity sha512-1r8ZaT26Nigq7o4UBGl+aXB2UMFUIdLPP/8bLIP0x3d0pZL46ybKKjhWKaJQWIkLl5QCLD0nK3qTOO1QkwdFaA==
-  dependencies:
-    "@types/rx-core" "*"
-    "@types/rx-core-binding" "*"
-    "@types/rx-lite" "*"
-    "@types/rx-lite-aggregates" "*"
-    "@types/rx-lite-async" "*"
-    "@types/rx-lite-backpressure" "*"
-    "@types/rx-lite-coincidence" "*"
-    "@types/rx-lite-experimental" "*"
-    "@types/rx-lite-joinpatterns" "*"
-    "@types/rx-lite-testing" "*"
-    "@types/rx-lite-time" "*"
-    "@types/rx-lite-virtualtime" "*"
+  version "1.5.5"
+  resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.5.tgz#75a2a8e7d8ab4b230414505d92335d1dcb53a6df"
+  integrity sha512-L28j2FcJfSZOnL1WBjDYp2vUHCeIFlyYI/53EwD/rKUBQ7MtUUfbQWiyKJGpcnv4/WgrhWsFKrcPstcAt/J0tQ==
 
 "@types/source-list-map@*":
   version "0.1.2"
@@ -2047,9 +1745,9 @@
   integrity sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA==
 
 "@types/stack-utils@^2.0.0":
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.0.tgz#7036640b4e21cc2f259ae826ce843d277dad8cff"
-  integrity sha512-RJJrrySY7A8havqpGObOB4W92QXKJo63/jFLLgpvOtsGUqbQZ9Sbgl35KMm1DjC6j7AvmmU2bIno+3IyEaemaw==
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.1.tgz#20f18294f797f2209b5f65c8e3b5c8e8261d127c"
+  integrity sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==
 
 "@types/strip-bom@^3.0.0":
   version "3.0.0"
@@ -2061,48 +1759,48 @@
   resolved "https://registry.yarnpkg.com/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz#9aa30c04db212a9a0649d6ae6fd50accc40748a1"
   integrity sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==
 
-"@types/tapable@*", "@types/tapable@^1.0.5":
-  version "1.0.6"
-  resolved "https://registry.yarnpkg.com/@types/tapable/-/tapable-1.0.6.tgz#a9ca4b70a18b270ccb2bc0aaafefd1d486b7ea74"
-  integrity sha512-W+bw9ds02rAQaMvaLYxAbJ6cvguW/iJXNT6lTssS1ps6QdrMKttqEAMEG/b5CR8TZl3/L7/lH0ZV5nNR1LXikA==
+"@types/tapable@^1", "@types/tapable@^1.0.5":
+  version "1.0.8"
+  resolved "https://registry.yarnpkg.com/@types/tapable/-/tapable-1.0.8.tgz#b94a4391c85666c7b73299fd3ad79d4faa435310"
+  integrity sha512-ipixuVrh2OdNmauvtT51o3d8z12p6LtFW9in7U79der/kwejjdNchQC5UMn5u/KxNoM7VHHOs/l8KS8uHxhODQ==
 
 "@types/uglify-js@*":
-  version "3.11.1"
-  resolved "https://registry.yarnpkg.com/@types/uglify-js/-/uglify-js-3.11.1.tgz#97ff30e61a0aa6876c270b5f538737e2d6ab8ceb"
-  integrity sha512-7npvPKV+jINLu1SpSYVWG8KvyJBhBa8tmzMMdDoVc2pWUYHN8KIXlPJhjJ4LT97c4dXJA2SHL/q6ADbDriZN+Q==
+  version "3.13.1"
+  resolved "https://registry.yarnpkg.com/@types/uglify-js/-/uglify-js-3.13.1.tgz#5e889e9e81e94245c75b6450600e1c5ea2878aea"
+  integrity sha512-O3MmRAk6ZuAKa9CHgg0Pr0+lUOqoMLpc9AS4R8ano2auvsg7IE8syF3Xh/NPr26TWklxYcqoEEFdzLLs1fV9PQ==
   dependencies:
     source-map "^0.6.1"
 
 "@types/webpack-sources@*":
-  version "2.1.0"
-  resolved "https://registry.yarnpkg.com/@types/webpack-sources/-/webpack-sources-2.1.0.tgz#8882b0bd62d1e0ce62f183d0d01b72e6e82e8c10"
-  integrity sha512-LXn/oYIpBeucgP1EIJbKQ2/4ZmpvRl+dlrFdX7+94SKRUV3Evy3FsfMZY318vGhkWUS5MPhtOM3w1/hCOAOXcg==
+  version "3.2.0"
+  resolved "https://registry.yarnpkg.com/@types/webpack-sources/-/webpack-sources-3.2.0.tgz#16d759ba096c289034b26553d2df1bf45248d38b"
+  integrity sha512-Ft7YH3lEVRQ6ls8k4Ff1oB4jN6oy/XmU6tQISKdhfh+1mR+viZFphS6WL0IrtDOzvefmJg5a0s7ZQoRXwqTEFg==
   dependencies:
     "@types/node" "*"
     "@types/source-list-map" "*"
     source-map "^0.7.3"
 
 "@types/webpack@^4.41.8":
-  version "4.41.25"
-  resolved "https://registry.yarnpkg.com/@types/webpack/-/webpack-4.41.25.tgz#4d3b5aecc4e44117b376280fbfd2dc36697968c4"
-  integrity sha512-cr6kZ+4m9lp86ytQc1jPOJXgINQyz3kLLunZ57jznW+WIAL0JqZbGubQk4GlD42MuQL5JGOABrxdpqqWeovlVQ==
+  version "4.41.30"
+  resolved "https://registry.yarnpkg.com/@types/webpack/-/webpack-4.41.30.tgz#fd3db6d0d41e145a8eeeafcd3c4a7ccde9068ddc"
+  integrity sha512-GUHyY+pfuQ6haAfzu4S14F+R5iGRwN6b2FRNJY7U0NilmFAqbsOfK6j1HwuLBAqwRIT+pVdNDJGJ6e8rpp0KHA==
   dependencies:
-    "@types/anymatch" "*"
     "@types/node" "*"
-    "@types/tapable" "*"
+    "@types/tapable" "^1"
     "@types/uglify-js" "*"
     "@types/webpack-sources" "*"
+    anymatch "^3.0.0"
     source-map "^0.6.0"
 
 "@types/yargs-parser@*":
-  version "20.2.0"
-  resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-20.2.0.tgz#dd3e6699ba3237f0348cd085e4698780204842f9"
-  integrity sha512-37RSHht+gzzgYeobbG+KWryeAW8J33Nhr69cjTqSYymXVZEN9NbRYWoYlRtDhHKPVT1FyNKwaTPC1NynKZpzRA==
+  version "20.2.1"
+  resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-20.2.1.tgz#3b9ce2489919d9e4fea439b76916abc34b2df129"
+  integrity sha512-7tFImggNeNBVMsn0vLrpn1H1uPrUBdnARPTpZoitY37ZrdJREzf7I16tMrlK3hen349gr1NYh8CmZQa7CTG6Aw==
 
 "@types/yargs@^15.0.0":
-  version "15.0.12"
-  resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-15.0.12.tgz#6234ce3e3e3fa32c5db301a170f96a599c960d74"
-  integrity sha512-f+fD/fQAo3BCbCDlrUpznF1A5Zp9rB0noS5vnoormHSIPFKL0Z2DcUJ3Gxp5ytH4uLRNxy7AwYUC9exZzqGMAw==
+  version "15.0.14"
+  resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-15.0.14.tgz#26d821ddb89e70492160b66d10a0eb6df8f6fb06"
+  integrity sha512-yEJzHoxf6SyQGhBhIYGXQDSCkJjB6HohDShto7m8vaKg9Yp0Yn8+71J9eakh2bnPg6BfsH9PRMhiRTZnd4eXGQ==
   dependencies:
     "@types/yargs-parser" "*"
 
@@ -2210,25 +1908,54 @@
     camelcase "^5.0.0"
 
 "@vue/component-compiler-utils@^3.1.0":
-  version "3.2.0"
-  resolved "https://registry.yarnpkg.com/@vue/component-compiler-utils/-/component-compiler-utils-3.2.0.tgz#8f85182ceed28e9b3c75313de669f83166d11e5d"
-  integrity sha512-lejBLa7xAMsfiZfNp7Kv51zOzifnb29FwdnMLa96z26kXErPFioSf9BMcePVIQ6/Gc6/mC0UrPpxAWIHyae0vw==
+  version "3.2.2"
+  resolved "https://registry.yarnpkg.com/@vue/component-compiler-utils/-/component-compiler-utils-3.2.2.tgz#2f7ed5feed82ff7f0284acc11d525ee7eff22460"
+  integrity sha512-rAYMLmgMuqJFWAOb3Awjqqv5X3Q3hVr4jH/kgrFJpiU0j3a90tnNBplqbj+snzrgZhC9W128z+dtgMifOiMfJg==
   dependencies:
     consolidate "^0.15.1"
     hash-sum "^1.0.2"
     lru-cache "^4.1.2"
     merge-source-map "^1.1.0"
-    postcss "^7.0.14"
+    postcss "^7.0.36"
     postcss-selector-parser "^6.0.2"
     source-map "~0.6.1"
     vue-template-es2015-compiler "^1.9.0"
   optionalDependencies:
     prettier "^1.18.2"
 
+"@vue/reactivity@3.2.32":
+  version "3.2.32"
+  resolved "https://registry.yarnpkg.com/@vue/reactivity/-/reactivity-3.2.32.tgz#a859c8ab28a297d14a46cbd450bf70b3f6f87fac"
+  integrity sha512-4zaDumuyDqkuhbb63hRd+YHFGopW7srFIWesLUQ2su/rJfWrSq3YUvoKAJE8Eu1EhZ2Q4c1NuwnEreKj1FkDxA==
+  dependencies:
+    "@vue/shared" "3.2.32"
+
+"@vue/runtime-core@3.2.32":
+  version "3.2.32"
+  resolved "https://registry.yarnpkg.com/@vue/runtime-core/-/runtime-core-3.2.32.tgz#8f8875dc032f99991bafb72070327ae5584a08dd"
+  integrity sha512-uKKzK6LaCnbCJ7rcHvsK0azHLGpqs+Vi9B28CV1mfWVq1F3Bj8Okk3cX+5DtD06aUh4V2bYhS2UjjWiUUKUF0w==
+  dependencies:
+    "@vue/reactivity" "3.2.32"
+    "@vue/shared" "3.2.32"
+
+"@vue/runtime-dom@^3.2.32":
+  version "3.2.32"
+  resolved "https://registry.yarnpkg.com/@vue/runtime-dom/-/runtime-dom-3.2.32.tgz#53a8be5c9d72105faf4d11d10202063e9a29c39c"
+  integrity sha512-AmlIg+GPqjkNoADLjHojEX5RGcAg+TsgXOOcUrtDHwKvA8mO26EnLQLB8nylDjU6AMJh2CIYn8NEgyOV5ZIScQ==
+  dependencies:
+    "@vue/runtime-core" "3.2.32"
+    "@vue/shared" "3.2.32"
+    csstype "^2.6.8"
+
+"@vue/shared@3.2.32":
+  version "3.2.32"
+  resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.2.32.tgz#1ca0c3b8c03a5e24129156e171df736b2c1d645f"
+  integrity sha512-bjcixPErUsAnTQRQX4Z5IQnICYjIfNCyCl8p29v1M6kfVzvwOICPw+dz48nNuWlTOOx2RHhzHdazJibE8GSnsw==
+
 "@vue/test-utils@^1.0.3":
-  version "1.1.2"
-  resolved "https://registry.yarnpkg.com/@vue/test-utils/-/test-utils-1.1.2.tgz#fdb487448dceefeaf3d01d465f7c836a3d666dbc"
-  integrity sha512-utbIL7zn9c+SjhybPwh48lpWCiluFCbP1yyRNAy1fQsw/6hiNFioaWy05FoVAFIZXC5WwBf+5r4ypfM1j/nI4A==
+  version "1.2.2"
+  resolved "https://registry.yarnpkg.com/@vue/test-utils/-/test-utils-1.2.2.tgz#0242ea4e202d4853541bb167fead3f2249140ab7"
+  integrity sha512-P+yiAsszoy8z1TqXiVUnAZaJj0WGGz5fCxm4bOSI6Cpwy1+PNYwYxDv0ROAA/SUtOPppV+aD8tp/QWwxf8ROJw==
   dependencies:
     dom-event-types "^1.0.0"
     lodash "^4.17.15"
@@ -2389,7 +2116,7 @@
   resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d"
   integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==
 
-abab@^2.0.0, abab@^2.0.3:
+abab@^2.0.3, abab@^2.0.5:
   version "2.0.5"
   resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.5.tgz#c0b678fb32d60fc1219c784d6a826fe385aeb79a"
   integrity sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q==
@@ -2399,7 +2126,7 @@ abbrev@1:
   resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8"
   integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==
 
-accepts@~1.3.5, accepts@~1.3.7:
+accepts@~1.3.5:
   version "1.3.7"
   resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd"
   integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==
@@ -2407,14 +2134,6 @@ accepts@~1.3.5, accepts@~1.3.7:
     mime-types "~2.1.24"
     negotiator "0.6.2"
 
-acorn-globals@^4.3.0:
-  version "4.3.4"
-  resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-4.3.4.tgz#9fa1926addc11c97308c4e66d7add0d40c3272e7"
-  integrity sha512-clfQEh21R+D0leSbUdWf3OcfqyaCSAQ8Ryq00bofSekfr9W8u1jyYZo6ir0xu9Gtcf7BjcHJpnbZH7JOCpP60A==
-  dependencies:
-    acorn "^6.0.1"
-    acorn-walk "^6.0.1"
-
 acorn-globals@^6.0.0:
   version "6.0.0"
   resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-6.0.0.tgz#46cdd39f0f8ff08a876619b55f5ac8a6dc770b45"
@@ -2424,21 +2143,21 @@ acorn-globals@^6.0.0:
     acorn-walk "^7.1.1"
 
 acorn-jsx@^5.2.0, acorn-jsx@^5.3.1:
-  version "5.3.1"
-  resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.1.tgz#fc8661e11b7ac1539c47dbfea2e72b3af34d267b"
-  integrity sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==
-
-acorn-walk@^6.0.1:
-  version "6.2.0"
-  resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-6.2.0.tgz#123cb8f3b84c2171f1f7fb252615b1c78a6b1a8c"
-  integrity sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==
+  version "5.3.2"
+  resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937"
+  integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==
 
 acorn-walk@^7.1.1:
   version "7.2.0"
   resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc"
   integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==
 
-acorn@^6.0.1, acorn@^6.0.4, acorn@^6.4.1:
+acorn-walk@^8.0.0:
+  version "8.2.0"
+  resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1"
+  integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==
+
+acorn@^6.4.1:
   version "6.4.2"
   resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.2.tgz#35866fd710528e92de10cf06016498e47e39e1e6"
   integrity sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==
@@ -2448,6 +2167,18 @@ acorn@^7.1.1, acorn@^7.4.0:
   resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa"
   integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==
 
+acorn@^8.0.4, acorn@^8.2.4:
+  version "8.5.0"
+  resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.5.0.tgz#4512ccb99b3698c752591e9bb4472e38ad43cee2"
+  integrity sha512-yXbYeFy+jUuYd3/CDcg2NkIYE991XYX/bje7LmjJigUciaeO1JR4XxXgCIV1/Zc/dRuFEyw1L0pbA+qynJkW5Q==
+
+agent-base@6:
+  version "6.0.2"
+  resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77"
+  integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==
+  dependencies:
+    debug "4"
+
 aggregate-error@^3.0.0:
   version "3.1.0"
   resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a"
@@ -2466,7 +2197,7 @@ ajv-keywords@^3.1.0, ajv-keywords@^3.4.1, ajv-keywords@^3.5.2:
   resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d"
   integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==
 
-ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.3, ajv@^6.12.4, ajv@^6.12.5:
+ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.4, ajv@^6.12.5:
   version "6.12.6"
   resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4"
   integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==
@@ -2476,10 +2207,10 @@ ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.3, ajv@^6.12.4, ajv@^6.12.5:
     json-schema-traverse "^0.4.1"
     uri-js "^4.2.2"
 
-ajv@^7.0.2:
-  version "7.0.3"
-  resolved "https://registry.yarnpkg.com/ajv/-/ajv-7.0.3.tgz#13ae747eff125cafb230ac504b2406cf371eece2"
-  integrity sha512-R50QRlXSxqXcQP5SvKUrw8VZeypvo12i2IX0EeR5PiZ7bEKeHWgzgo264LDadUsCU42lTJVhFikTqJwNeH34gQ==
+ajv@^8.0.1:
+  version "8.6.2"
+  resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.6.2.tgz#2fb45e0e5fcbc0813326c1c3da535d1881bb0571"
+  integrity sha512-9807RlWAgT564wT+DjeyU5OFMPjmzxVobvDFmNAhY+5zD6A2ly3jDp6sgnfyDtlIQ+7H97oc/DGCzzfu9rjw9w==
   dependencies:
     fast-deep-equal "^3.1.1"
     json-schema-traverse "^1.0.0"
@@ -2498,22 +2229,17 @@ ansi-align@^3.0.0:
   dependencies:
     string-width "^3.0.0"
 
-ansi-colors@^3.0.0:
-  version "3.2.4"
-  resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.4.tgz#e3a3da4bfbae6c86a9c285625de124a234026fbf"
-  integrity sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==
-
 ansi-colors@^4.1.1:
   version "4.1.1"
   resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348"
   integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==
 
 ansi-escapes@^4.2.1:
-  version "4.3.1"
-  resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.1.tgz#a5c47cc43181f1f38ffd7076837700d395522a61"
-  integrity sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA==
+  version "4.3.2"
+  resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e"
+  integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==
   dependencies:
-    type-fest "^0.11.0"
+    type-fest "^0.21.3"
 
 ansi-html@0.0.7:
   version "0.0.7"
@@ -2559,13 +2285,6 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0:
   dependencies:
     color-convert "^2.0.1"
 
-ansi-to-html@^0.6.4:
-  version "0.6.14"
-  resolved "https://registry.yarnpkg.com/ansi-to-html/-/ansi-to-html-0.6.14.tgz#65fe6d08bba5dd9db33f44a20aec331e0010dad8"
-  integrity sha512-7ZslfB1+EnFSDO5Ju+ue5Y6It19DRnZXWv8jrGHgIlPna5Mh4jz7BV5jCbQneXNFurQcKoolaaAjHtgSBfOIuA==
-  dependencies:
-    entities "^1.1.2"
-
 anymatch@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb"
@@ -2574,10 +2293,10 @@ anymatch@^2.0.0:
     micromatch "^3.1.4"
     normalize-path "^2.1.1"
 
-anymatch@^3.0.3, anymatch@~3.1.1:
-  version "3.1.1"
-  resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.1.tgz#c55ecf02185e2469259399310c173ce31233b142"
-  integrity sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==
+anymatch@^3.0.0, anymatch@^3.0.3, anymatch@~3.1.2:
+  version "3.1.2"
+  resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716"
+  integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==
   dependencies:
     normalize-path "^3.0.0"
     picomatch "^2.0.4"
@@ -2588,9 +2307,9 @@ aproba@^1.1.1:
   integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==
 
 arg@^5.0.0:
-  version "5.0.0"
-  resolved "https://registry.yarnpkg.com/arg/-/arg-5.0.0.tgz#a20e2bb5710e82950a516b3f933fee5ed478be90"
-  integrity sha512-4P8Zm2H+BRS+c/xX1LrHw0qKpEhdlZjLCgWy+d78T9vqa2Z2SiD2wMrYuWIAFy5IZUD7nnNXroRttz+0RzlrzQ==
+  version "5.0.1"
+  resolved "https://registry.yarnpkg.com/arg/-/arg-5.0.1.tgz#eb0c9a8f77786cad2af8ff2b862899842d7b6adb"
+  integrity sha512-e0hDa9H2Z9AwFkk2qDlwhoMYE4eToKarchkQHovNdLTCYMHZHeRjI71crOh+dio4K6u1IcwubQqo79Ga4CyAQA==
 
 argparse@^1.0.7:
   version "1.0.10"
@@ -2614,25 +2333,15 @@ arr-union@^3.1.0:
   resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4"
   integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=
 
-array-equal@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/array-equal/-/array-equal-1.0.0.tgz#8c2a5ef2472fd9ea742b04c77a75093ba2757c93"
-  integrity sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=
-
-array-flatten@1.1.1:
-  version "1.1.1"
-  resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2"
-  integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=
-
 array-includes@^3.1.1:
-  version "3.1.2"
-  resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.2.tgz#a8db03e0b88c8c6aeddc49cb132f9bcab4ebf9c8"
-  integrity sha512-w2GspexNQpx+PutG3QpT437/BenZBj0M/MZGn5mzv/MofYqo0xmRHzn4lFsoDlWJ+THYsGJmFlW68WlDFx7VRw==
+  version "3.1.3"
+  resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.3.tgz#c7f619b382ad2afaf5326cddfdc0afc61af7690a"
+  integrity sha512-gcem1KlBU7c9rB+Rq8/3PPKsK2kjqeEBa3bD5kkQo4nYlOHQCJqIJFqBXDEfwaRuYTT4E+FxA9xez7Gf/e3Q7A==
   dependencies:
-    call-bind "^1.0.0"
+    call-bind "^1.0.2"
     define-properties "^1.1.3"
-    es-abstract "^1.18.0-next.1"
-    get-intrinsic "^1.0.1"
+    es-abstract "^1.18.0-next.2"
+    get-intrinsic "^1.1.1"
     is-string "^1.0.5"
 
 array-union@^2.1.0:
@@ -2661,20 +2370,8 @@ asn1.js@^5.2.0:
   dependencies:
     bn.js "^4.0.0"
     inherits "^2.0.1"
-    minimalistic-assert "^1.0.0"
-    safer-buffer "^2.1.0"
-
-asn1@~0.2.3:
-  version "0.2.4"
-  resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136"
-  integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==
-  dependencies:
-    safer-buffer "~2.1.0"
-
-assert-plus@1.0.0, assert-plus@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525"
-  integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=
+    minimalistic-assert "^1.0.0"
+    safer-buffer "^2.1.0"
 
 assert@^1.1.1:
   version "1.5.0"
@@ -2699,16 +2396,16 @@ async-each@^1.0.1:
   resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf"
   integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==
 
-async-limiter@~1.0.0:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd"
-  integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==
-
 asynckit@^0.4.0:
   version "0.4.0"
   resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
   integrity sha1-x57Zf380y48robyXkLzDZkdLS3k=
 
+at-least-node@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2"
+  integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==
+
 atob@^2.1.2:
   version "2.1.2"
   resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9"
@@ -2727,16 +2424,6 @@ autoprefixer@^9.6.1:
     postcss "^7.0.32"
     postcss-value-parser "^4.1.0"
 
-aws-sign2@~0.7.0:
-  version "0.7.0"
-  resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8"
-  integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=
-
-aws4@^1.8.0:
-  version "1.11.0"
-  resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59"
-  integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==
-
 axios-retry@^3.1.9:
   version "3.1.9"
   resolved "https://registry.yarnpkg.com/axios-retry/-/axios-retry-3.1.9.tgz#6c30fc9aeb4519aebaec758b90ef56fa03fe72e8"
@@ -2744,12 +2431,12 @@ axios-retry@^3.1.9:
   dependencies:
     is-retry-allowed "^1.1.0"
 
-axios@^0.21.0, axios@^0.21.1:
-  version "0.21.1"
-  resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.1.tgz#22563481962f4d6bde9a76d516ef0e5d3c09b2b8"
-  integrity sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==
+axios@^0.21.1:
+  version "0.21.3"
+  resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.3.tgz#f85d9b747f9b66d59ca463605cedf1844872b82e"
+  integrity sha512-JtoZ3Ndke/+Iwt5n+BgSli/3idTvpt5OjKyoCmz4LX5+lPiY5l7C1colYezhlxThjNa/NhngCUWZSZFypIFuaA==
   dependencies:
-    follow-redirects "^1.10.0"
+    follow-redirects "^1.14.0"
 
 babel-code-frame@^6.26.0:
   version "6.26.0"
@@ -2836,6 +2523,30 @@ babel-plugin-jest-hoist@^26.6.2:
     "@types/babel__core" "^7.0.0"
     "@types/babel__traverse" "^7.0.6"
 
+babel-plugin-polyfill-corejs2@^0.2.2:
+  version "0.2.2"
+  resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.2.2.tgz#e9124785e6fd94f94b618a7954e5693053bf5327"
+  integrity sha512-kISrENsJ0z5dNPq5eRvcctITNHYXWOA4DUZRFYCz3jYCcvTb/A546LIddmoGNMVYg2U38OyFeNosQwI9ENTqIQ==
+  dependencies:
+    "@babel/compat-data" "^7.13.11"
+    "@babel/helper-define-polyfill-provider" "^0.2.2"
+    semver "^6.1.1"
+
+babel-plugin-polyfill-corejs3@^0.2.2:
+  version "0.2.4"
+  resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.2.4.tgz#68cb81316b0e8d9d721a92e0009ec6ecd4cd2ca9"
+  integrity sha512-z3HnJE5TY/j4EFEa/qpQMSbcUJZ5JQi+3UFjXzn6pQCmIKc5Ug5j98SuYyH+m4xQnvKlMDIW4plLfgyVnd0IcQ==
+  dependencies:
+    "@babel/helper-define-polyfill-provider" "^0.2.2"
+    core-js-compat "^3.14.0"
+
+babel-plugin-polyfill-regenerator@^0.2.2:
+  version "0.2.2"
+  resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.2.2.tgz#b310c8d642acada348c1fa3b3e6ce0e851bee077"
+  integrity sha512-Goy5ghsc21HgPDFtzRkSirpZVW35meGoTmTOb2bxqdl60ghub4xOidgNTHaZfQ2FaxQsKmwvXtOAkcIS4SMBWg==
+  dependencies:
+    "@babel/helper-define-polyfill-provider" "^0.2.2"
+
 babel-plugin-transform-es2015-modules-commonjs@^6.26.0:
   version "6.26.2"
   resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz#58a793863a9e7ca870bdc5a881117ffac27db6f3"
@@ -2880,7 +2591,7 @@ babel-preset-jest@^26.6.2:
     babel-plugin-jest-hoist "^26.6.2"
     babel-preset-current-node-syntax "^1.0.0"
 
-babel-runtime@^6.11.6, babel-runtime@^6.22.0, babel-runtime@^6.26.0:
+babel-runtime@^6.22.0, babel-runtime@^6.26.0:
   version "6.26.0"
   resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe"
   integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4=
@@ -2914,7 +2625,7 @@ babel-traverse@^6.26.0:
     invariant "^2.2.2"
     lodash "^4.17.4"
 
-babel-types@^6.15.0, babel-types@^6.24.1, babel-types@^6.26.0:
+babel-types@^6.24.1, babel-types@^6.26.0:
   version "6.26.0"
   resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497"
   integrity sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=
@@ -2924,24 +2635,15 @@ babel-types@^6.15.0, babel-types@^6.24.1, babel-types@^6.26.0:
     lodash "^4.17.4"
     to-fast-properties "^1.0.3"
 
-babylon-walk@^1.0.2:
-  version "1.0.2"
-  resolved "https://registry.yarnpkg.com/babylon-walk/-/babylon-walk-1.0.2.tgz#3b15a5ddbb482a78b4ce9c01c8ba181702d9d6ce"
-  integrity sha1-OxWl3btIKni0zpwByLoYFwLZ1s4=
-  dependencies:
-    babel-runtime "^6.11.6"
-    babel-types "^6.15.0"
-    lodash.clone "^4.5.0"
-
 babylon@^6.18.0:
   version "6.18.0"
   resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3"
   integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==
 
 balanced-match@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
-  integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c=
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
+  integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
 
 base64-js@^1.0.2, base64-js@^1.3.1:
   version "1.5.1"
@@ -2961,23 +2663,6 @@ base@^0.11.1:
     mixin-deep "^1.2.0"
     pascalcase "^0.1.1"
 
-bcrypt-pbkdf@^1.0.0:
-  version "1.0.2"
-  resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e"
-  integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=
-  dependencies:
-    tweetnacl "^0.14.3"
-
-bfj@^6.1.1:
-  version "6.1.2"
-  resolved "https://registry.yarnpkg.com/bfj/-/bfj-6.1.2.tgz#325c861a822bcb358a41c78a33b8e6e2086dde7f"
-  integrity sha512-BmBJa4Lip6BPRINSZ0BPEIfB1wUY/9rwbwvIHQA1KjX9om29B6id0wnWXq7m3bn5JrUVjeOTnVuhPT1FiHwPGw==
-  dependencies:
-    bluebird "^3.5.5"
-    check-types "^8.0.3"
-    hoopy "^0.1.4"
-    tryer "^1.0.1"
-
 big.js@^5.2.2:
   version "5.2.2"
   resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328"
@@ -2989,9 +2674,9 @@ binary-extensions@^1.0.0:
   integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==
 
 binary-extensions@^2.0.0:
-  version "2.1.0"
-  resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.1.0.tgz#30fa40c9e7fe07dbc895678cd287024dea241dd9"
-  integrity sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==
+  version "2.2.0"
+  resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d"
+  integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==
 
 bindings@^1.5.0:
   version "1.5.0"
@@ -3000,41 +2685,22 @@ bindings@^1.5.0:
   dependencies:
     file-uri-to-path "1.0.0"
 
-"bioviz-js@git+https://gitlab.pasteur.fr/rplanel/bioviz-js#cc-qtl":
-  version "0.1.3"
-  resolved "git+https://gitlab.pasteur.fr/rplanel/bioviz-js#3eabfcad845bc33a1b56881bdc8a7863b9f0ab48"
-  dependencies:
-    "@types/d3" "^6.2.0"
-    "@types/plotly.js" "^1.54.2"
-    "@types/rx" "^4.1.1"
-    d3 "^6.2.0"
-    d3-axis "^2.0.0"
-    d3-brush "^2.1.0"
-    d3-drag "^2.0.0"
-    d3-path "^2.0.0"
-    d3-scale "^3.2.3"
-    d3-selection "^2.0.0"
-    parcel-bundler "^1.12.4"
-    plotly.js-dist "^1.57.1"
-    rxjs "^6.5.4"
-    tslint "^5.20.1"
-
 bluebird@^3.1.1, bluebird@^3.5.5:
   version "3.7.2"
   resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f"
   integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==
 
-bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.4.0:
-  version "4.11.9"
-  resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.9.tgz#26d556829458f9d1e81fc48952493d0ba3507828"
-  integrity sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==
+bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.9:
+  version "4.12.0"
+  resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88"
+  integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==
 
 bn.js@^5.0.0, bn.js@^5.1.1:
-  version "5.1.3"
-  resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.1.3.tgz#beca005408f642ebebea80b042b4d18d2ac0ee6b"
-  integrity sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==
+  version "5.2.0"
+  resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.0.tgz#358860674396c6997771a9d051fcc1b57d4ae002"
+  integrity sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==
 
-body-parser@1.19.0, body-parser@^1.19.0:
+body-parser@^1.19.0:
   version "1.19.0"
   resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a"
   integrity sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==
@@ -3055,19 +2721,19 @@ boolbase@^1.0.0, boolbase@~1.0.0:
   resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e"
   integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24=
 
-boxen@^4.2.0:
-  version "4.2.0"
-  resolved "https://registry.yarnpkg.com/boxen/-/boxen-4.2.0.tgz#e411b62357d6d6d36587c8ac3d5d974daa070e64"
-  integrity sha512-eB4uT9RGzg2odpER62bBwSLvUeGC+WbRjjyyFhGsKnc8wp/m0+hQsMUvUe3H2V0D5vw0nBdO1hCJoZo5mKeuIQ==
+boxen@^5.0.1:
+  version "5.0.1"
+  resolved "https://registry.yarnpkg.com/boxen/-/boxen-5.0.1.tgz#657528bdd3f59a772b8279b831f27ec2c744664b"
+  integrity sha512-49VBlw+PrWEF51aCmy7QIteYPIFZxSpvqBdP/2itCPPlJ49kj9zg/XPRFrdkne2W+CfwXUls8exMvu1RysZpKA==
   dependencies:
     ansi-align "^3.0.0"
-    camelcase "^5.3.1"
-    chalk "^3.0.0"
-    cli-boxes "^2.2.0"
-    string-width "^4.1.0"
-    term-size "^2.1.0"
-    type-fest "^0.8.1"
+    camelcase "^6.2.0"
+    chalk "^4.1.0"
+    cli-boxes "^2.2.1"
+    string-width "^4.2.0"
+    type-fest "^0.20.2"
     widest-line "^3.1.0"
+    wrap-ansi "^7.0.0"
 
 brace-expansion@^1.1.7:
   version "1.1.11"
@@ -3100,17 +2766,7 @@ braces@^3.0.1, braces@~3.0.2:
   dependencies:
     fill-range "^7.0.1"
 
-brfs@^1.2.0:
-  version "1.6.1"
-  resolved "https://registry.yarnpkg.com/brfs/-/brfs-1.6.1.tgz#b78ce2336d818e25eea04a0947cba6d4fb8849c3"
-  integrity sha512-OfZpABRQQf+Xsmju8XE9bDjs+uU4vLREGolP7bDgcpsI17QREyZ4Bl+2KLxxx1kCgA0fAIhKQBaBYh+PEcCqYQ==
-  dependencies:
-    quote-stream "^1.0.1"
-    resolve "^1.1.5"
-    static-module "^2.2.0"
-    through2 "^2.0.0"
-
-brorand@^1.0.1:
+brorand@^1.0.1, brorand@^1.1.0:
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f"
   integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=
@@ -3181,16 +2837,16 @@ browserify-zlib@^0.2.0:
   dependencies:
     pako "~1.0.5"
 
-browserslist@^4.0.0, browserslist@^4.1.0, browserslist@^4.12.0, browserslist@^4.14.5, browserslist@^4.16.0, browserslist@^4.6.4:
-  version "4.16.0"
-  resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.16.0.tgz#410277627500be3cb28a1bfe037586fbedf9488b"
-  integrity sha512-/j6k8R0p3nxOC6kx5JGAxsnhc9ixaWJfYc+TNTzxg6+ARaESAvQGV7h0uNOB4t+pLQJZWzcrMxXOxjgsCj3dqQ==
+browserslist@^4.0.0, browserslist@^4.12.0, browserslist@^4.16.6, browserslist@^4.16.8, browserslist@^4.6.4:
+  version "4.17.0"
+  resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.17.0.tgz#1fcd81ec75b41d6d4994fb0831b92ac18c01649c"
+  integrity sha512-g2BJ2a0nEYvEFQC208q8mVAhfNwpZ5Mu8BwgtCdZKO3qx98HChmeg448fPdUzld8aFmfLgVh7yymqV+q1lJZ5g==
   dependencies:
-    caniuse-lite "^1.0.30001165"
-    colorette "^1.2.1"
-    electron-to-chromium "^1.3.621"
+    caniuse-lite "^1.0.30001254"
+    colorette "^1.3.0"
+    electron-to-chromium "^1.3.830"
     escalade "^3.1.1"
-    node-releases "^1.1.67"
+    node-releases "^1.1.75"
 
 bser@2.1.1:
   version "2.1.1"
@@ -3199,15 +2855,10 @@ bser@2.1.1:
   dependencies:
     node-int64 "^0.4.0"
 
-buffer-equal@0.0.1:
-  version "0.0.1"
-  resolved "https://registry.yarnpkg.com/buffer-equal/-/buffer-equal-0.0.1.tgz#91bc74b11ea405bc916bc6aa908faafa5b4aac4b"
-  integrity sha1-kbx0sR6kBbyRa8aqkI+q+ltKrEs=
-
 buffer-from@^1.0.0:
-  version "1.1.1"
-  resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
-  integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5"
+  integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==
 
 buffer-json@^2.0.0:
   version "2.0.0"
@@ -3236,11 +2887,6 @@ buffer@^5.1.0:
     base64-js "^1.3.1"
     ieee754 "^1.1.13"
 
-builtin-modules@^1.1.1:
-  version "1.1.1"
-  resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f"
-  integrity sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=
-
 builtin-status-codes@^3.0.0:
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8"
@@ -3277,28 +2923,28 @@ cacache@^12.0.2:
     unique-filename "^1.1.1"
     y18n "^4.0.0"
 
-cacache@^13.0.1:
-  version "13.0.1"
-  resolved "https://registry.yarnpkg.com/cacache/-/cacache-13.0.1.tgz#a8000c21697089082f85287a1aec6e382024a71c"
-  integrity sha512-5ZvAxd05HDDU+y9BVvcqYu2LLXmPnQ0hW62h32g4xBTgL/MppR4/04NHfj/ycM2y6lmTnbw6HVi+1eN0Psba6w==
+cacache@^15.0.5:
+  version "15.3.0"
+  resolved "https://registry.yarnpkg.com/cacache/-/cacache-15.3.0.tgz#dc85380fb2f556fe3dda4c719bfa0ec875a7f1eb"
+  integrity sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==
   dependencies:
-    chownr "^1.1.2"
-    figgy-pudding "^3.5.1"
+    "@npmcli/fs" "^1.0.0"
+    "@npmcli/move-file" "^1.0.1"
+    chownr "^2.0.0"
     fs-minipass "^2.0.0"
     glob "^7.1.4"
-    graceful-fs "^4.2.2"
     infer-owner "^1.0.4"
-    lru-cache "^5.1.1"
-    minipass "^3.0.0"
+    lru-cache "^6.0.0"
+    minipass "^3.1.1"
     minipass-collect "^1.0.2"
     minipass-flush "^1.0.5"
     minipass-pipeline "^1.2.2"
-    mkdirp "^0.5.1"
-    move-concurrently "^1.0.1"
-    p-map "^3.0.0"
+    mkdirp "^1.0.3"
+    p-map "^4.0.0"
     promise-inflight "^1.0.1"
-    rimraf "^2.7.1"
-    ssri "^7.0.0"
+    rimraf "^3.0.2"
+    ssri "^8.0.1"
+    tar "^6.0.2"
     unique-filename "^1.1.1"
 
 cache-base@^1.0.1:
@@ -3328,18 +2974,13 @@ cache-loader@^4.1.0:
     neo-async "^2.6.1"
     schema-utils "^2.0.0"
 
-call-bind@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.0.tgz#24127054bb3f9bdcb4b1fb82418186072f77b8ce"
-  integrity sha512-AEXsYIyyDY3MCzbwdhzG3Jx1R0J2wetQyUynn6dYHAO+bg8l1k7jwZtRv4ryryFs7EP+NDlikJlVe59jr0cM2w==
+call-bind@^1.0.0, call-bind@^1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c"
+  integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==
   dependencies:
     function-bind "^1.1.1"
-    get-intrinsic "^1.0.0"
-
-call-me-maybe@^1.0.1:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b"
-  integrity sha1-JtII6onje1y95gJQoV8DHBak1ms=
+    get-intrinsic "^1.0.2"
 
 caller-callsite@^2.0.0:
   version "2.0.0"
@@ -3355,6 +2996,11 @@ caller-path@^2.0.0:
   dependencies:
     caller-callsite "^2.0.0"
 
+callsite@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/callsite/-/callsite-1.0.0.tgz#280398e5d664bd74038b6f0905153e6e8af1bc20"
+  integrity sha1-KAOY5dZkvXQDi28JBRU+borxvCA=
+
 callsites@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50"
@@ -3386,7 +3032,7 @@ camelcase@^5.0.0, camelcase@^5.3.1:
   resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
   integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
 
-camelcase@^6.0.0:
+camelcase@^6.0.0, camelcase@^6.2.0:
   version "6.2.0"
   resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.2.0.tgz#924af881c9d525ac9d87f40d964e5cea982a1809"
   integrity sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==
@@ -3401,10 +3047,10 @@ caniuse-api@^3.0.0:
     lodash.memoize "^4.1.2"
     lodash.uniq "^4.5.0"
 
-caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001164, caniuse-lite@^1.0.30001165:
-  version "1.0.30001173"
-  resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001173.tgz#3c47bbe3cd6d7a9eda7f50ac016d158005569f56"
-  integrity sha512-R3aqmjrICdGCTAnSXtNyvWYMK3YtV5jwudbq0T7nN9k4kmE4CBuwPqyJ+KBzepSTh0huivV2gLbSMEzTTmfeYw==
+caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001228, caniuse-lite@^1.0.30001254:
+  version "1.0.30001255"
+  resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001255.tgz#f3b09b59ab52e39e751a569523618f47c4298ca0"
+  integrity sha512-F+A3N9jTZL882f/fg/WWVnKSu6IOo3ueLz4zwaOPbPYHNmM/ZaDUyzyJwS1mZhX7Ex5jqTyW599Gdelh5PDYLQ==
 
 capture-exit@^2.0.0:
   version "2.0.0"
@@ -3413,11 +3059,6 @@ capture-exit@^2.0.0:
   dependencies:
     rsvp "^4.8.4"
 
-caseless@~0.12.0:
-  version "0.12.0"
-  resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
-  integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=
-
 chalk@^1.1.3:
   version "1.1.3"
   resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
@@ -3429,7 +3070,7 @@ chalk@^1.1.3:
     strip-ansi "^3.0.0"
     supports-color "^2.0.0"
 
-chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.3.1, chalk@^2.3.2, chalk@^2.4.1, chalk@^2.4.2:
+chalk@^2.0.0, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.3.2, chalk@^2.4.1, chalk@^2.4.2:
   version "2.4.2"
   resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
   integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
@@ -3438,18 +3079,10 @@ chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.3.1, chalk@^2.3
     escape-string-regexp "^1.0.5"
     supports-color "^5.3.0"
 
-chalk@^3.0.0:
-  version "3.0.0"
-  resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4"
-  integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==
-  dependencies:
-    ansi-styles "^4.1.0"
-    supports-color "^7.1.0"
-
-chalk@^4.0.0, chalk@^4.1.0:
-  version "4.1.0"
-  resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a"
-  integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==
+chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.1, chalk@^4.1.2:
+  version "4.1.2"
+  resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
+  integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
   dependencies:
     ansi-styles "^4.1.0"
     supports-color "^7.1.0"
@@ -3464,27 +3097,22 @@ chardet@^0.7.0:
   resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e"
   integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==
 
-check-types@^8.0.3:
-  version "8.0.3"
-  resolved "https://registry.yarnpkg.com/check-types/-/check-types-8.0.3.tgz#3356cca19c889544f2d7a95ed49ce508a0ecf552"
-  integrity sha512-YpeKZngUmG65rLudJ4taU7VLkOCTMhNl/u4ctNC56LQS/zJTyNH0Lrtwm1tfTsbLlwvlfsA2d1c8vCf/Kh2KwQ==
-
-"chokidar@>=2.0.0 <4.0.0", chokidar@^3.4.1, chokidar@^3.4.3:
-  version "3.4.3"
-  resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.4.3.tgz#c1df38231448e45ca4ac588e6c79573ba6a57d5b"
-  integrity sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ==
+"chokidar@>=3.0.0 <4.0.0", chokidar@^3.4.1, chokidar@^3.5.1, chokidar@^3.5.2:
+  version "3.5.2"
+  resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.2.tgz#dba3976fcadb016f66fd365021d91600d01c1e75"
+  integrity sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==
   dependencies:
-    anymatch "~3.1.1"
+    anymatch "~3.1.2"
     braces "~3.0.2"
-    glob-parent "~5.1.0"
+    glob-parent "~5.1.2"
     is-binary-path "~2.1.0"
     is-glob "~4.0.1"
     normalize-path "~3.0.0"
-    readdirp "~3.5.0"
+    readdirp "~3.6.0"
   optionalDependencies:
-    fsevents "~2.1.2"
+    fsevents "~2.3.2"
 
-chokidar@^2.1.5, chokidar@^2.1.8:
+chokidar@^2.1.8:
   version "2.1.8"
   resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917"
   integrity sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==
@@ -3503,28 +3131,31 @@ chokidar@^2.1.5, chokidar@^2.1.8:
   optionalDependencies:
     fsevents "^1.2.7"
 
-chownr@^1.1.1, chownr@^1.1.2:
+chownr@^1.1.1:
   version "1.1.4"
   resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b"
   integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==
 
-chrome-trace-event@^1.0.2:
-  version "1.0.2"
-  resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz#234090ee97c7d4ad1a2c4beae27505deffc608a4"
-  integrity sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ==
-  dependencies:
-    tslib "^1.9.0"
+chownr@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece"
+  integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==
 
-ci-info@^1.6.0:
-  version "1.6.0"
-  resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.6.0.tgz#2ca20dbb9ceb32d4524a683303313f0304b1e497"
-  integrity sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==
+chrome-trace-event@^1.0.2:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac"
+  integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==
 
 ci-info@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46"
   integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==
 
+ci-info@^3.0.0, ci-info@^3.1.1:
+  version "3.2.0"
+  resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.2.0.tgz#2876cb948a498797b5236f0095bc057d0dca38b6"
+  integrity sha512-dVqRX7fLUm8J6FgHJ418XuIgDLZDkYcDFTeL6TA2gt5WlIZUQrrH6EZrNClwT/H0FateUsZkGIOPRrLbP+PR9A==
+
 cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3:
   version "1.0.4"
   resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de"
@@ -3567,18 +3198,11 @@ clean-stack@^2.0.0:
   resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b"
   integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==
 
-cli-boxes@^2.2.0:
+cli-boxes@^2.2.1:
   version "2.2.1"
   resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.1.tgz#ddd5035d25094fce220e9cab40a45840a440318f"
   integrity sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==
 
-cli-cursor@^2.1.0:
-  version "2.1.0"
-  resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5"
-  integrity sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=
-  dependencies:
-    restore-cursor "^2.0.0"
-
 cli-cursor@^3.1.0:
   version "3.1.0"
   resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307"
@@ -3586,11 +3210,6 @@ cli-cursor@^3.1.0:
   dependencies:
     restore-cursor "^3.1.0"
 
-cli-spinners@^1.1.0:
-  version "1.3.1"
-  resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-1.3.1.tgz#002c1990912d0d59580c93bd36c056de99e4259a"
-  integrity sha512-1QL4544moEsDVH9T/l6Cemov/37iv1RtoKf7NJ04A60+4MREXNfx/QvavbH6QoGdsD4N4Mwy49cmaINR/o2mdg==
-
 cli-width@^3.0.0:
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6"
@@ -3605,25 +3224,11 @@ cliui@^6.0.0:
     strip-ansi "^6.0.0"
     wrap-ansi "^6.2.0"
 
-clone-deep@^4.0.1:
-  version "4.0.1"
-  resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387"
-  integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==
-  dependencies:
-    is-plain-object "^2.0.4"
-    kind-of "^6.0.2"
-    shallow-clone "^3.0.0"
-
-clone@2.x, clone@^2.1.1:
+clone@2.x:
   version "2.1.2"
   resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f"
   integrity sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=
 
-clone@^1.0.2:
-  version "1.0.4"
-  resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e"
-  integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4=
-
 co@^4.6.0:
   version "4.6.0"
   resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184"
@@ -3651,7 +3256,7 @@ collection-visit@^1.0.0:
     map-visit "^1.0.0"
     object-visit "^1.0.0"
 
-color-convert@^1.9.0, color-convert@^1.9.1:
+color-convert@^1.9.0, color-convert@^1.9.3:
   version "1.9.3"
   resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
   integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==
@@ -3675,40 +3280,35 @@ color-name@^1.0.0, color-name@~1.1.4:
   resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
   integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
 
-color-string@^1.5.4:
-  version "1.5.4"
-  resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.5.4.tgz#dd51cd25cfee953d138fe4002372cc3d0e504cb6"
-  integrity sha512-57yF5yt8Xa3czSEW1jfQDE79Idk0+AkN/4KWad6tbdxUmAs3MvjxlWSWD4deYytcRfoZ9nhKyFl1kj5tBvidbw==
+color-string@^1.6.0:
+  version "1.6.0"
+  resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.6.0.tgz#c3915f61fe267672cb7e1e064c9d692219f6c312"
+  integrity sha512-c/hGS+kRWJutUBEngKKmk4iH3sD59MBkoxVapS/0wgpCz2u7XsNloxknyvBhzwEs1IbV36D9PwqLPJ2DTu3vMA==
   dependencies:
     color-name "^1.0.0"
     simple-swizzle "^0.2.2"
 
 color@^3.0.0:
-  version "3.1.3"
-  resolved "https://registry.yarnpkg.com/color/-/color-3.1.3.tgz#ca67fb4e7b97d611dcde39eceed422067d91596e"
-  integrity sha512-xgXAcTHa2HeFCGLE9Xs/R82hujGtu9Jd9x4NW3T34+OMs7VoPsjwzRczKHvTAHeJwWFwX5j15+MgAppE8ztObQ==
+  version "3.2.1"
+  resolved "https://registry.yarnpkg.com/color/-/color-3.2.1.tgz#3544dc198caf4490c3ecc9a790b54fe9ff45e164"
+  integrity sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==
   dependencies:
-    color-convert "^1.9.1"
-    color-string "^1.5.4"
+    color-convert "^1.9.3"
+    color-string "^1.6.0"
 
-colorette@^1.2.1:
-  version "1.2.1"
-  resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.2.1.tgz#4d0b921325c14faf92633086a536db6e89564b1b"
-  integrity sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw==
+colorette@^1.2.1, colorette@^1.2.2, colorette@^1.3.0:
+  version "1.3.0"
+  resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.3.0.tgz#ff45d2f0edb244069d3b772adeb04fed38d0a0af"
+  integrity sha512-ecORCqbSFP7Wm8Y6lyqMJjexBQqXSF7SSeaTyGGphogUjBlFP9m9o08wy86HL2uB7fMTxtOUzLMk7ogKcxMg1w==
 
-combined-stream@^1.0.6, combined-stream@~1.0.6:
+combined-stream@^1.0.8:
   version "1.0.8"
   resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
   integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
   dependencies:
     delayed-stream "~1.0.0"
 
-command-exists@^1.2.6:
-  version "1.2.9"
-  resolved "https://registry.yarnpkg.com/command-exists/-/command-exists-1.2.9.tgz#c50725af3808c8ab0260fd60b01fbfa25b954f69"
-  integrity sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==
-
-commander@2, commander@^2.11.0, commander@^2.12.1, commander@^2.18.0, commander@^2.19.0, commander@^2.20.0:
+commander@^2.19.0, commander@^2.20.0:
   version "2.20.3"
   resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
   integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
@@ -3718,10 +3318,10 @@ commander@^4.1.1:
   resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068"
   integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==
 
-commander@^5.0.0:
-  version "5.1.0"
-  resolved "https://registry.yarnpkg.com/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae"
-  integrity sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==
+commander@^6.2.0:
+  version "6.2.1"
+  resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.1.tgz#0792eb682dfbc325999bb2b84fddddba110ac73c"
+  integrity sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==
 
 commondir@^1.0.1:
   version "1.0.1"
@@ -3758,7 +3358,7 @@ concat-map@0.0.1:
   resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
   integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
 
-concat-stream@^1.5.0, concat-stream@~1.6.0:
+concat-stream@^1.5.0:
   version "1.6.2"
   resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34"
   integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==
@@ -3778,9 +3378,9 @@ condense-newlines@^0.2.1:
     kind-of "^3.0.2"
 
 config-chain@^1.1.12:
-  version "1.1.12"
-  resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.12.tgz#0fde8d091200eb5e808caf25fe618c02f48e4efa"
-  integrity sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA==
+  version "1.1.13"
+  resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.13.tgz#fad0795aa6a6cdaff9ed1b68e9dff94372c232f4"
+  integrity sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==
   dependencies:
     ini "^1.3.4"
     proto-list "~1.2.1"
@@ -3795,10 +3395,10 @@ connect@^3.7.0:
     parseurl "~1.3.3"
     utils-merge "1.0.1"
 
-consola@^2.10.0, consola@^2.11.3, consola@^2.15.0, consola@^2.5.6, consola@^2.6.0, consola@^2.9.0:
-  version "2.15.0"
-  resolved "https://registry.yarnpkg.com/consola/-/consola-2.15.0.tgz#40fc4eefa4d2f8ef2e2806147f056ea207fcc0e9"
-  integrity sha512-vlcSGgdYS26mPf7qNi+dCisbhiyDnrN1zaRbw3CSuc2wGOMEGGPsp46PdRG5gqXwgtJfjxDkxRNAgRPr1B77vQ==
+consola@^2.10.0, consola@^2.11.3, consola@^2.15.0, consola@^2.15.3, consola@^2.5.6, consola@^2.6.0, consola@^2.9.0:
+  version "2.15.3"
+  resolved "https://registry.yarnpkg.com/consola/-/consola-2.15.3.tgz#2e11f98d6a4be71ff72e0bdf07bd23e12cb61550"
+  integrity sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==
 
 console-browserify@^1.1.0:
   version "1.2.0"
@@ -3822,35 +3422,18 @@ contains-path@^0.1.0:
   resolved "https://registry.yarnpkg.com/contains-path/-/contains-path-0.1.0.tgz#fe8cf184ff6670b6baef01a9d4861a5cbec4120a"
   integrity sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=
 
-content-disposition@0.5.3:
-  version "0.5.3"
-  resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd"
-  integrity sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==
-  dependencies:
-    safe-buffer "5.1.2"
-
 content-type@~1.0.4:
   version "1.0.4"
   resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
   integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==
 
-convert-source-map@^1.4.0, convert-source-map@^1.5.1, convert-source-map@^1.6.0, convert-source-map@^1.7.0:
-  version "1.7.0"
-  resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442"
-  integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==
+convert-source-map@^1.4.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0:
+  version "1.8.0"
+  resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.8.0.tgz#f3373c32d21b4d780dd8004514684fb791ca4369"
+  integrity sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==
   dependencies:
     safe-buffer "~5.1.1"
 
-cookie-signature@1.0.6:
-  version "1.0.6"
-  resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c"
-  integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw=
-
-cookie@0.4.0:
-  version "0.4.0"
-  resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba"
-  integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==
-
 cookie@^0.3.1:
   version "0.3.1"
   resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb"
@@ -3878,12 +3461,12 @@ copy-descriptor@^0.1.0:
   resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d"
   integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=
 
-core-js-compat@^3.8.0:
-  version "3.8.2"
-  resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.8.2.tgz#3717f51f6c3d2ebba8cbf27619b57160029d1d4c"
-  integrity sha512-LO8uL9lOIyRRrQmZxHZFl1RV+ZbcsAkFWTktn5SmH40WgLtSNYN4m4W2v9ONT147PxBY/XrRhrWq8TlvObyUjQ==
+core-js-compat@^3.12.1, core-js-compat@^3.14.0, core-js-compat@^3.16.0:
+  version "3.17.2"
+  resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.17.2.tgz#f461ab950c0a0ffedfc327debf28b7e518950936"
+  integrity sha512-lHnt7A1Oqplebl5i0MrQyFv/yyEzr9p29OjlkcsFRDDgHwwQyVckfRGJ790qzXhkwM8ba4SFHHa2sO+T5f1zGg==
   dependencies:
-    browserslist "^4.16.0"
+    browserslist "^4.16.8"
     semver "7.0.0"
 
 core-js@^2.4.0, core-js@^2.6.5:
@@ -3891,10 +3474,10 @@ core-js@^2.4.0, core-js@^2.6.5:
   resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec"
   integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==
 
-core-util-is@1.0.2, core-util-is@~1.0.0:
-  version "1.0.2"
-  resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
-  integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
+core-util-is@~1.0.0:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85"
+  integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==
 
 cosmiconfig@^5.0.0:
   version "5.2.1"
@@ -3944,12 +3527,12 @@ create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7:
     safe-buffer "^5.0.1"
     sha.js "^2.4.8"
 
-create-require@^1.1.0, create-require@^1.1.1:
+create-require@^1.1.1:
   version "1.1.1"
   resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333"
   integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==
 
-cross-spawn@^6.0.0, cross-spawn@^6.0.4:
+cross-spawn@^6.0.0:
   version "6.0.5"
   resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
   integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==
@@ -3960,7 +3543,7 @@ cross-spawn@^6.0.0, cross-spawn@^6.0.4:
     shebang-command "^1.2.0"
     which "^1.2.9"
 
-cross-spawn@^7.0.0, cross-spawn@^7.0.2:
+cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3:
   version "7.0.3"
   resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
   integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==
@@ -4014,36 +3597,23 @@ css-has-pseudo@^0.10.0:
     postcss "^7.0.6"
     postcss-selector-parser "^5.0.0-rc.4"
 
-css-loader@^3.6.0:
-  version "3.6.0"
-  resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-3.6.0.tgz#2e4b2c7e6e2d27f8c8f28f61bffcd2e6c91ef645"
-  integrity sha512-M5lSukoWi1If8dhQAUCvj4H8vUt3vOnwbQBH9DdTm/s4Ym2B/3dPMtYZeJmq7Q3S3Pa+I94DcZ7pc9bP14cWIQ==
+css-loader@^4.3.0:
+  version "4.3.0"
+  resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-4.3.0.tgz#c888af64b2a5b2e85462c72c0f4a85c7e2e0821e"
+  integrity sha512-rdezjCjScIrsL8BSYszgT4s476IcNKt6yX69t0pHjJVnPUTDpn4WfIpDQTN3wCJvUvfsz/mFjuGOekf3PY3NUg==
   dependencies:
-    camelcase "^5.3.1"
+    camelcase "^6.0.0"
     cssesc "^3.0.0"
     icss-utils "^4.1.1"
-    loader-utils "^1.2.3"
-    normalize-path "^3.0.0"
+    loader-utils "^2.0.0"
     postcss "^7.0.32"
     postcss-modules-extract-imports "^2.0.0"
-    postcss-modules-local-by-default "^3.0.2"
+    postcss-modules-local-by-default "^3.0.3"
     postcss-modules-scope "^2.2.0"
     postcss-modules-values "^3.0.0"
     postcss-value-parser "^4.1.0"
-    schema-utils "^2.7.0"
-    semver "^6.3.0"
-
-css-modules-loader-core@^1.1.0:
-  version "1.1.0"
-  resolved "https://registry.yarnpkg.com/css-modules-loader-core/-/css-modules-loader-core-1.1.0.tgz#5908668294a1becd261ae0a4ce21b0b551f21d16"
-  integrity sha1-WQhmgpShvs0mGuCkziGwtVHyHRY=
-  dependencies:
-    icss-replace-symbols "1.1.0"
-    postcss "6.0.1"
-    postcss-modules-extract-imports "1.1.0"
-    postcss-modules-local-by-default "1.2.0"
-    postcss-modules-scope "1.1.0"
-    postcss-modules-values "1.3.0"
+    schema-utils "^2.7.1"
+    semver "^7.3.2"
 
 css-prefers-color-scheme@^3.1.1:
   version "3.1.1"
@@ -4057,7 +3627,7 @@ css-select-base-adapter@^0.1.1:
   resolved "https://registry.yarnpkg.com/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz#3b2ff4972cc362ab88561507a95408a1432135d7"
   integrity sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w==
 
-css-select@^2.0.0, css-select@^2.0.2:
+css-select@^2.0.0:
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/css-select/-/css-select-2.1.0.tgz#6a34653356635934a81baca68d0255432105dbef"
   integrity sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ==
@@ -4067,13 +3637,16 @@ css-select@^2.0.0, css-select@^2.0.2:
     domutils "^1.7.0"
     nth-check "^1.0.2"
 
-css-selector-tokenizer@^0.7.0:
-  version "0.7.3"
-  resolved "https://registry.yarnpkg.com/css-selector-tokenizer/-/css-selector-tokenizer-0.7.3.tgz#735f26186e67c749aaf275783405cf0661fae8f1"
-  integrity sha512-jWQv3oCEL5kMErj4wRnK/OPoBi0D+P1FR2cDCKYPaMeD2eW3/mttav8HT4hT1CKopiJI/psEULjkClhvJo4Lvg==
+css-select@^4.1.3:
+  version "4.1.3"
+  resolved "https://registry.yarnpkg.com/css-select/-/css-select-4.1.3.tgz#a70440f70317f2669118ad74ff105e65849c7067"
+  integrity sha512-gT3wBNd9Nj49rAbmtFHj1cljIAOLYSX1nZ8CB7TBO3INYckygm5B7LISU/szY//YmdiSLbJvDLOx9VnMVpMBxA==
   dependencies:
-    cssesc "^3.0.0"
-    fastparse "^1.1.2"
+    boolbase "^1.0.0"
+    css-what "^5.0.0"
+    domhandler "^4.2.0"
+    domutils "^2.6.0"
+    nth-check "^2.0.0"
 
 css-tree@1.0.0-alpha.37:
   version "1.0.0-alpha.37"
@@ -4084,9 +3657,9 @@ css-tree@1.0.0-alpha.37:
     source-map "^0.6.1"
 
 css-tree@^1.1.2:
-  version "1.1.2"
-  resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.1.2.tgz#9ae393b5dafd7dae8a622475caec78d3d8fbd7b5"
-  integrity sha512-wCoWush5Aeo48GLhfHPbmvZs59Z+M7k5+B1xDnXbdWNcEF423DoFdqSWE0PM5aNk5nI5cp1q7ms36zGApY/sKQ==
+  version "1.1.3"
+  resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.1.3.tgz#eb4870fb6fd7707327ec95c2ff2ab09b5e8db91d"
+  integrity sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==
   dependencies:
     mdn-data "2.0.14"
     source-map "^0.6.1"
@@ -4096,6 +3669,11 @@ css-what@^3.2.1:
   resolved "https://registry.yarnpkg.com/css-what/-/css-what-3.4.2.tgz#ea7026fcb01777edbde52124e21f327e7ae950e4"
   integrity sha512-ACUm3L0/jiZTqfzRM3Hi9Q8eZqd6IK37mMWPLz9PJxkLWllYeRf+EHUSHYEtFop2Eqytaq1FizFVh7XfBnXCDQ==
 
+css-what@^5.0.0:
+  version "5.0.1"
+  resolved "https://registry.yarnpkg.com/css-what/-/css-what-5.0.1.tgz#3efa820131f4669a8ac2408f9c32e7c7de9f4cad"
+  integrity sha512-FYDTSHb/7KXsWICVsxdmiExPjCfRC4qRFBdVwv7Ax9hMnvMmEjP9RfxTEZ3qPZGmADDn2vAKSo9UcN1jKVYscg==
+
 css@^2.1.0:
   version "2.2.4"
   resolved "https://registry.yarnpkg.com/css/-/css-2.2.4.tgz#c646755c73971f2bba6a601e2cf2fd71b1298929"
@@ -4121,10 +3699,10 @@ cssesc@^3.0.0:
   resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee"
   integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==
 
-cssnano-preset-default@^4.0.7:
-  version "4.0.7"
-  resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-4.0.7.tgz#51ec662ccfca0f88b396dcd9679cdb931be17f76"
-  integrity sha512-x0YHHx2h6p0fCl1zY9L9roD7rnlltugGu7zXSKQx6k2rYw0Hi3IqxcoAGF7u9Q5w1nt7vK0ulxV8Lo+EvllGsA==
+cssnano-preset-default@^4.0.8:
+  version "4.0.8"
+  resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-4.0.8.tgz#920622b1fc1e95a34e8838203f1397a504f2d3ff"
+  integrity sha512-LdAyHuq+VRyeVREFmuxUZR1TXjQm8QQU/ktoo/x7bz+SdOge1YKc5eMN6pRW7YWBmyq59CqYba1dJ5cUukEjLQ==
   dependencies:
     css-declaration-sorter "^4.0.1"
     cssnano-util-raw-cache "^4.0.1"
@@ -4154,7 +3732,7 @@ cssnano-preset-default@^4.0.7:
     postcss-ordered-values "^4.1.2"
     postcss-reduce-initial "^4.0.3"
     postcss-reduce-transforms "^4.0.2"
-    postcss-svgo "^4.0.2"
+    postcss-svgo "^4.0.3"
     postcss-unique-selectors "^4.0.1"
 
 cssnano-util-get-arguments@^4.0.0:
@@ -4179,13 +3757,13 @@ cssnano-util-same-parent@^4.0.0:
   resolved "https://registry.yarnpkg.com/cssnano-util-same-parent/-/cssnano-util-same-parent-4.0.1.tgz#574082fb2859d2db433855835d9a8456ea18bbf3"
   integrity sha512-WcKx5OY+KoSIAxBW6UBBRay1U6vkYheCdjyVNDm85zt5K9mHoGOfsOsqIszfAqrQQFIIKgjh2+FDgIj/zsl21Q==
 
-cssnano@^4.0.0, cssnano@^4.1.10:
-  version "4.1.10"
-  resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-4.1.10.tgz#0ac41f0b13d13d465487e111b778d42da631b8b2"
-  integrity sha512-5wny+F6H4/8RgNlaqab4ktc3e0/blKutmq8yNlBFXA//nSFFAqAngjNVRzUvCgYROULmZZUoosL/KSoZo5aUaQ==
+cssnano@^4.1.10, cssnano@^4.1.11:
+  version "4.1.11"
+  resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-4.1.11.tgz#c7b5f5b81da269cb1fd982cb960c1200910c9a99"
+  integrity sha512-6gZm2htn7xIPJOHY824ERgj8cNPgPxyCSnkXc4v7YvNW+TdVfzgngHcEhy/8D11kUWRUMbke+tC+AUcUsnMz2g==
   dependencies:
     cosmiconfig "^5.0.0"
-    cssnano-preset-default "^4.0.7"
+    cssnano-preset-default "^4.0.8"
     is-resolvable "^1.0.0"
     postcss "^7.0.0"
 
@@ -4196,30 +3774,28 @@ csso@^4.0.2:
   dependencies:
     css-tree "^1.1.2"
 
-cssom@0.3.x, cssom@^0.3.4, cssom@~0.3.6:
-  version "0.3.8"
-  resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.8.tgz#9f1276f5b2b463f2114d3f2c75250af8c1a36f4a"
-  integrity sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==
-
 cssom@^0.4.4:
   version "0.4.4"
   resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.4.4.tgz#5a66cf93d2d0b661d80bf6a44fb65f5c2e4e0a10"
   integrity sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==
 
-cssstyle@^1.1.1:
-  version "1.4.0"
-  resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-1.4.0.tgz#9d31328229d3c565c61e586b02041a28fccdccf1"
-  integrity sha512-GBrLZYZ4X4x6/QEoBnIrqb8B/f5l4+8me2dkom/j1Gtbxy0kBv6OGzKuAsGM75bkGwGAFkt56Iwg28S3XTZgSA==
-  dependencies:
-    cssom "0.3.x"
+cssom@~0.3.6:
+  version "0.3.8"
+  resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.8.tgz#9f1276f5b2b463f2114d3f2c75250af8c1a36f4a"
+  integrity sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==
 
-cssstyle@^2.2.0:
+cssstyle@^2.3.0:
   version "2.3.0"
   resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-2.3.0.tgz#ff665a0ddbdc31864b09647f34163443d90b0852"
   integrity sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==
   dependencies:
     cssom "~0.3.6"
 
+csstype@^2.6.8:
+  version "2.6.20"
+  resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.20.tgz#9229c65ea0b260cf4d3d997cb06288e36a8d6dda"
+  integrity sha512-/WwNkdXfckNgw6S5R125rrW8ez139lBHWouiBvX8dfMFtcn6V81REDqnH7+CRpRipfYlyU1CmOnOxrmGcFOjeA==
+
 cuint@^0.2.2:
   version "0.2.2"
   resolved "https://registry.yarnpkg.com/cuint/-/cuint-0.2.2.tgz#408086d409550c2631155619e9fa7bcadc3b991b"
@@ -4230,261 +3806,67 @@ cyclist@^1.0.1:
   resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9"
   integrity sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=
 
-d3-array@2, d3-array@>=2.5, d3-array@^2.3.0, d3-array@^2.8.0:
-  version "2.9.1"
-  resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-2.9.1.tgz#f355cc72b46c8649b3f9212029e2d681cb5b9643"
-  integrity sha512-Ob7RdOtkqsjx1NWyQHMFLtCSk6/aKTxDdC4ZIolX+O+mDD2RzrsYgAyc0WGAlfYFVELLSilS7w8BtE3PKM8bHg==
-
-d3-axis@2, d3-axis@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/d3-axis/-/d3-axis-2.0.0.tgz#40aebb65626ffe6d95e9441fbf9194274b328a8b"
-  integrity sha512-9nzB0uePtb+u9+dWir+HTuEAKJOEUYJoEwbJPsZ1B4K3iZUgzJcSENQ05Nj7S4CIfbZZ8/jQGoUzGKFznBhiiQ==
-
-d3-brush@2, d3-brush@^2.1.0:
-  version "2.1.0"
-  resolved "https://registry.yarnpkg.com/d3-brush/-/d3-brush-2.1.0.tgz#adadfbb104e8937af142e9a6e2028326f0471065"
-  integrity sha512-cHLLAFatBATyIKqZOkk/mDHUbzne2B3ZwxkzMHvFTCZCmLaXDpZRihQSn8UNXTkGD/3lb/W2sQz0etAftmHMJQ==
-  dependencies:
-    d3-dispatch "1 - 2"
-    d3-drag "2"
-    d3-interpolate "1 - 2"
-    d3-selection "2"
-    d3-transition "2"
-
-d3-chord@2:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/d3-chord/-/d3-chord-2.0.0.tgz#32491b5665391180560f738e5c1ccd1e3c47ebae"
-  integrity sha512-D5PZb7EDsRNdGU4SsjQyKhja8Zgu+SHZfUSO5Ls8Wsn+jsAKUUGkcshLxMg9HDFxG3KqavGWaWkJ8EpU8ojuig==
-  dependencies:
-    d3-path "1 - 2"
-
-"d3-color@1 - 2", d3-color@2:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/d3-color/-/d3-color-2.0.0.tgz#8d625cab42ed9b8f601a1760a389f7ea9189d62e"
-  integrity sha512-SPXi0TSKPD4g9tw0NMZFnR95XVgUZiBH+uUTqQuDu1OsE2zomHU7ho0FISciaPvosimixwHFl3WHLGabv6dDgQ==
-
-d3-contour@2:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/d3-contour/-/d3-contour-2.0.0.tgz#80ee834988563e3bea9d99ddde72c0f8c089ea40"
-  integrity sha512-9unAtvIaNk06UwqBmvsdHX7CZ+NPDZnn8TtNH1myW93pWJkhsV25JcgnYAu0Ck5Veb1DHiCv++Ic5uvJ+h50JA==
-  dependencies:
-    d3-array "2"
-
-d3-delaunay@5:
-  version "5.3.0"
-  resolved "https://registry.yarnpkg.com/d3-delaunay/-/d3-delaunay-5.3.0.tgz#b47f05c38f854a4e7b3cea80e0bb12e57398772d"
-  integrity sha512-amALSrOllWVLaHTnDLHwMIiz0d1bBu9gZXd1FiLfXf8sHcX9jrcj81TVZOqD4UX7MgBZZ07c8GxzEgBpJqc74w==
-  dependencies:
-    delaunator "4"
-
-"d3-dispatch@1 - 2", d3-dispatch@2:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/d3-dispatch/-/d3-dispatch-2.0.0.tgz#8a18e16f76dd3fcaef42163c97b926aa9b55e7cf"
-  integrity sha512-S/m2VsXI7gAti2pBoLClFFTMOO1HTtT0j99AuXLoGFKO6deHDdnv6ZGTxSTTUTgO1zVcv82fCOtDjYK4EECmWA==
-
-d3-drag@2, d3-drag@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/d3-drag/-/d3-drag-2.0.0.tgz#9eaf046ce9ed1c25c88661911c1d5a4d8eb7ea6d"
-  integrity sha512-g9y9WbMnF5uqB9qKqwIIa/921RYWzlUDv9Jl1/yONQwxbOfszAWTCm8u7HOTgJgRDXiRZN56cHT9pd24dmXs8w==
-  dependencies:
-    d3-dispatch "1 - 2"
-    d3-selection "2"
-
-"d3-dsv@1 - 2", d3-dsv@2:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/d3-dsv/-/d3-dsv-2.0.0.tgz#b37b194b6df42da513a120d913ad1be22b5fe7c5"
-  integrity sha512-E+Pn8UJYx9mViuIUkoc93gJGGYut6mSDKy2+XaPwccwkRGlR+LO97L2VCCRjQivTwLHkSnAJG7yo00BWY6QM+w==
-  dependencies:
-    commander "2"
-    iconv-lite "0.4"
-    rw "1"
-
-"d3-ease@1 - 2", d3-ease@2:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/d3-ease/-/d3-ease-2.0.0.tgz#fd1762bfca00dae4bacea504b1d628ff290ac563"
-  integrity sha512-68/n9JWarxXkOWMshcT5IcjbB+agblQUaIsbnXmrzejn2O82n3p2A9R2zEB9HIEFWKFwPAEDDN8gR0VdSAyyAQ==
-
-d3-fetch@2:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/d3-fetch/-/d3-fetch-2.0.0.tgz#ecd7ef2128d9847a3b41b548fec80918d645c064"
-  integrity sha512-TkYv/hjXgCryBeNKiclrwqZH7Nb+GaOwo3Neg24ZVWA3MKB+Rd+BY84Nh6tmNEMcjUik1CSUWjXYndmeO6F7sw==
-  dependencies:
-    d3-dsv "1 - 2"
-
-d3-force@2:
-  version "2.1.1"
-  resolved "https://registry.yarnpkg.com/d3-force/-/d3-force-2.1.1.tgz#f20ccbf1e6c9e80add1926f09b51f686a8bc0937"
-  integrity sha512-nAuHEzBqMvpFVMf9OX75d00OxvOXdxY+xECIXjW6Gv8BRrXu6gAWbv/9XKrvfJ5i5DCokDW7RYE50LRoK092ew==
+"d3-array@2 - 3", "d3-array@2.10.0 - 3", d3-array@^3.0.2:
+  version "3.0.2"
+  resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-3.0.2.tgz#7a65593784cfc0150eee1aba8d3e69a6fe73be7b"
+  integrity sha512-nTN4OC6ufZueotlexbxBd2z8xmG1eIfhvP2m1auH2ONps0L+AZn1r0JWuzMXZ6XgOj1VBOp7GGZmEs9NUFEBbA==
   dependencies:
-    d3-dispatch "1 - 2"
-    d3-quadtree "1 - 2"
-    d3-timer "1 - 2"
+    internmap "1 - 2"
 
-"d3-format@1 - 2", d3-format@2:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/d3-format/-/d3-format-2.0.0.tgz#a10bcc0f986c372b729ba447382413aabf5b0767"
-  integrity sha512-Ab3S6XuE/Q+flY96HXT0jOXcM4EAClYFnRGY5zsjRGNy6qCYrQsMffs7cV5Q9xejb35zxW5hf/guKw34kvIKsA==
-
-d3-geo@2:
-  version "2.0.1"
-  resolved "https://registry.yarnpkg.com/d3-geo/-/d3-geo-2.0.1.tgz#2437fdfed3fe3aba2812bd8f30609cac83a7ee39"
-  integrity sha512-M6yzGbFRfxzNrVhxDJXzJqSLQ90q1cCyb3EWFZ1LF4eWOBYxFypw7I/NFVBNXKNqxv1bqLathhYvdJ6DC+th3A==
-  dependencies:
-    d3-array ">=2.5"
+"d3-color@1 - 3", d3-color@^3.0.1:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/d3-color/-/d3-color-3.0.1.tgz#03316e595955d1fcd39d9f3610ad41bb90194d0a"
+  integrity sha512-6/SlHkDOBLyQSJ1j1Ghs82OIUXpKWlR0hCsw0XrLSQhuUPuCSmLQ1QPH98vpnQxMUQM2/gfAkUEWsupVpd9JGw==
 
-d3-hierarchy@2:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/d3-hierarchy/-/d3-hierarchy-2.0.0.tgz#dab88a58ca3e7a1bc6cab390e89667fcc6d20218"
-  integrity sha512-SwIdqM3HxQX2214EG9GTjgmCc/mbSx4mQBn+DuEETubhOw6/U3fmnji4uCVrmzOydMHSO1nZle5gh6HB/wdOzw==
+"d3-format@1 - 3":
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/d3-format/-/d3-format-3.0.1.tgz#e41b81b2ab79277141ec1404aa5d05001da64084"
+  integrity sha512-hdL7+HBIohpgfolhBxr1KX47VMD6+vVD/oEFrxk5yhmzV2prk99EkFKYpXuhVkFpTgHdJ6/4bYcjdLPPXV4tIA==
 
-"d3-interpolate@1 - 2", "d3-interpolate@1.2.0 - 2", d3-interpolate@2:
-  version "2.0.1"
-  resolved "https://registry.yarnpkg.com/d3-interpolate/-/d3-interpolate-2.0.1.tgz#98be499cfb8a3b94d4ff616900501a64abc91163"
-  integrity sha512-c5UhwwTs/yybcmTpAVqwSFl6vrQ8JZJoT5F7xNFK9pymv5C0Ymcc9/LIJHtYIggg/yS9YHw8i8O8tgb9pupjeQ==
+"d3-interpolate@1 - 3", "d3-interpolate@1.2.0 - 3":
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/d3-interpolate/-/d3-interpolate-3.0.1.tgz#3c47aa5b32c5b3dfb56ef3fd4342078a632b400d"
+  integrity sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==
   dependencies:
-    d3-color "1 - 2"
-
-"d3-path@1 - 2", d3-path@2, d3-path@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/d3-path/-/d3-path-2.0.0.tgz#55d86ac131a0548adae241eebfb56b4582dd09d8"
-  integrity sha512-ZwZQxKhBnv9yHaiWd6ZU4x5BtCQ7pXszEV9CU6kRgwIQVQGLMv1oiL4M+MK/n79sYzsj+gcgpPQSctJUsLN7fA==
-
-d3-polygon@2:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/d3-polygon/-/d3-polygon-2.0.0.tgz#13608ef042fbec625ba1598327564f03c0396d8e"
-  integrity sha512-MsexrCK38cTGermELs0cO1d79DcTsQRN7IWMJKczD/2kBjzNXxLUWP33qRF6VDpiLV/4EI4r6Gs0DAWQkE8pSQ==
-
-"d3-quadtree@1 - 2", d3-quadtree@2:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/d3-quadtree/-/d3-quadtree-2.0.0.tgz#edbad045cef88701f6fee3aee8e93fb332d30f9d"
-  integrity sha512-b0Ed2t1UUalJpc3qXzKi+cPGxeXRr4KU9YSlocN74aTzp6R/Ud43t79yLLqxHRWZfsvWXmbDWPpoENK1K539xw==
-
-d3-random@2:
-  version "2.2.2"
-  resolved "https://registry.yarnpkg.com/d3-random/-/d3-random-2.2.2.tgz#5eebd209ef4e45a2b362b019c1fb21c2c98cbb6e"
-  integrity sha512-0D9P8TRj6qDAtHhRQn6EfdOtHMfsUWanl3yb/84C4DqpZ+VsgfI5iTVRNRbELCfNvRfpMr8OrqqUTQ6ANGCijw==
+    d3-color "1 - 3"
 
-d3-scale-chromatic@2:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/d3-scale-chromatic/-/d3-scale-chromatic-2.0.0.tgz#c13f3af86685ff91323dc2f0ebd2dabbd72d8bab"
-  integrity sha512-LLqy7dJSL8yDy7NRmf6xSlsFZ6zYvJ4BcWFE4zBrOPnQERv9zj24ohnXKRbyi9YHnYV+HN1oEO3iFK971/gkzA==
+d3-scale-chromatic@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/d3-scale-chromatic/-/d3-scale-chromatic-3.0.0.tgz#15b4ceb8ca2bb0dcb6d1a641ee03d59c3b62376a"
+  integrity sha512-Lx9thtxAKrO2Pq6OO2Ua474opeziKr279P/TKZsMAhYyNDD3EnCffdbgeSYN5O7m2ByQsxtuP2CSDczNUIZ22g==
   dependencies:
-    d3-color "1 - 2"
-    d3-interpolate "1 - 2"
+    d3-color "1 - 3"
+    d3-interpolate "1 - 3"
 
-d3-scale@3, d3-scale@^3.2.3:
-  version "3.2.3"
-  resolved "https://registry.yarnpkg.com/d3-scale/-/d3-scale-3.2.3.tgz#be380f57f1f61d4ff2e6cbb65a40593a51649cfd"
-  integrity sha512-8E37oWEmEzj57bHcnjPVOBS3n4jqakOeuv1EDdQSiSrYnMCBdMd3nc4HtKk7uia8DUHcY/CGuJ42xxgtEYrX0g==
+d3-scale@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/d3-scale/-/d3-scale-4.0.0.tgz#294377ea1d7e5a31509ee648b98d7916ac0b34e3"
+  integrity sha512-foHQYKpWQcyndH1CGoHdUC4PECxTxonzwwBXGT8qu+Drb1FIc6ON6dG2P5f4hRRMkLiIKeWK7iFtdznDUrnuPQ==
   dependencies:
-    d3-array "^2.3.0"
-    d3-format "1 - 2"
-    d3-interpolate "1.2.0 - 2"
-    d3-time "1 - 2"
-    d3-time-format "2 - 3"
+    d3-array "2.10.0 - 3"
+    d3-format "1 - 3"
+    d3-interpolate "1.2.0 - 3"
+    d3-time "2.1.1 - 3"
+    d3-time-format "2 - 4"
 
-d3-selection@2, d3-selection@^2.0.0:
+d3-selection@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/d3-selection/-/d3-selection-2.0.0.tgz#94a11638ea2141b7565f883780dabc7ef6a61066"
   integrity sha512-XoGGqhLUN/W14NmaqcO/bb1nqjDAw5WtSYb2X8wiuQWvSZUsUVYsOSkOybUrNvcBjaywBdYPy03eXHMXjk9nZA==
 
-d3-shape@2:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/d3-shape/-/d3-shape-2.0.0.tgz#2331b62fa784a2a1daac47a7233cfd69301381fd"
-  integrity sha512-djpGlA779ua+rImicYyyjnOjeubyhql1Jyn1HK0bTyawuH76UQRWXd+pftr67H6Fa8hSwetkgb/0id3agKWykw==
+"d3-time-format@2 - 4":
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/d3-time-format/-/d3-time-format-4.0.0.tgz#930ded86a9de761702344760d8a25753467f28b7"
+  integrity sha512-nzaCwlj+ZVBIlFuVOT1RmU+6xb/7D5IcnhHzHQcBgS/aTa5K9fWZNN5LCXA27LgF5WxoSNJqKBbLcGMtM6Ca6A==
   dependencies:
-    d3-path "1 - 2"
+    d3-time "1 - 3"
 
-"d3-time-format@2 - 3", d3-time-format@3:
+"d3-time@1 - 3", "d3-time@2.1.1 - 3":
   version "3.0.0"
-  resolved "https://registry.yarnpkg.com/d3-time-format/-/d3-time-format-3.0.0.tgz#df8056c83659e01f20ac5da5fdeae7c08d5f1bb6"
-  integrity sha512-UXJh6EKsHBTjopVqZBhFysQcoXSv/5yLONZvkQ5Kk3qbwiUYkdX17Xa1PT6U1ZWXGGfB1ey5L8dKMlFq2DO0Ag==
-  dependencies:
-    d3-time "1 - 2"
-
-"d3-time@1 - 2", d3-time@2:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/d3-time/-/d3-time-2.0.0.tgz#ad7c127d17c67bd57a4c61f3eaecb81108b1e0ab"
-  integrity sha512-2mvhstTFcMvwStWd9Tj3e6CEqtOivtD8AUiHT8ido/xmzrI9ijrUUihZ6nHuf/vsScRBonagOdj0Vv+SEL5G3Q==
-
-"d3-timer@1 - 2", d3-timer@2:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/d3-timer/-/d3-timer-2.0.0.tgz#055edb1d170cfe31ab2da8968deee940b56623e6"
-  integrity sha512-TO4VLh0/420Y/9dO3+f9abDEFYeCUr2WZRlxJvbp4HPTQcSylXNiL6yZa9FIUvV1yRiFufl1bszTCLDqv9PWNA==
-
-d3-transition@2:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/d3-transition/-/d3-transition-2.0.0.tgz#366ef70c22ef88d1e34105f507516991a291c94c"
-  integrity sha512-42ltAGgJesfQE3u9LuuBHNbGrI/AJjNL2OAUdclE70UE6Vy239GCBEYD38uBPoLeNsOhFStGpPI0BAOV+HMxog==
-  dependencies:
-    d3-color "1 - 2"
-    d3-dispatch "1 - 2"
-    d3-ease "1 - 2"
-    d3-interpolate "1 - 2"
-    d3-timer "1 - 2"
-
-d3-zoom@2:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/d3-zoom/-/d3-zoom-2.0.0.tgz#f04d0afd05518becce879d04709c47ecd93fba54"
-  integrity sha512-fFg7aoaEm9/jf+qfstak0IYpnesZLiMX6GZvXtUSdv8RH2o4E2qeelgdU09eKS6wGuiGMfcnMI0nTIqWzRHGpw==
-  dependencies:
-    d3-dispatch "1 - 2"
-    d3-drag "2"
-    d3-interpolate "1 - 2"
-    d3-selection "2"
-    d3-transition "2"
-
-d3@^6.2.0:
-  version "6.3.1"
-  resolved "https://registry.yarnpkg.com/d3/-/d3-6.3.1.tgz#c5fe6c7abff432826775a9e04db80b5f2e22eb1c"
-  integrity sha512-rbaoA67o2N4lO1TCuvrTGQdowNb3zT0z2ygg6TLmJZAd7TRPg+lhbfDOVwQUAgdbRD+73kg2FrEQ9HLiap5H2w==
-  dependencies:
-    d3-array "2"
-    d3-axis "2"
-    d3-brush "2"
-    d3-chord "2"
-    d3-color "2"
-    d3-contour "2"
-    d3-delaunay "5"
-    d3-dispatch "2"
-    d3-drag "2"
-    d3-dsv "2"
-    d3-ease "2"
-    d3-fetch "2"
-    d3-force "2"
-    d3-format "2"
-    d3-geo "2"
-    d3-hierarchy "2"
-    d3-interpolate "2"
-    d3-path "2"
-    d3-polygon "2"
-    d3-quadtree "2"
-    d3-random "2"
-    d3-scale "3"
-    d3-scale-chromatic "2"
-    d3-selection "2"
-    d3-shape "2"
-    d3-time "2"
-    d3-time-format "3"
-    d3-timer "2"
-    d3-transition "2"
-    d3-zoom "2"
-
-dashdash@^1.12.0:
-  version "1.14.1"
-  resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0"
-  integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=
+  resolved "https://registry.yarnpkg.com/d3-time/-/d3-time-3.0.0.tgz#65972cb98ae2d4954ef5c932e8704061335d4975"
+  integrity sha512-zmV3lRnlaLI08y9IMRXSDshQb5Nj77smnfpnd2LrBa/2K281Jijactokeak14QacHs/kKq0AQ121nidNYlarbQ==
   dependencies:
-    assert-plus "^1.0.0"
-
-data-urls@^1.1.0:
-  version "1.1.0"
-  resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-1.1.0.tgz#15ee0582baa5e22bb59c77140da8f9c76963bbfe"
-  integrity sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ==
-  dependencies:
-    abab "^2.0.0"
-    whatwg-mimetype "^2.2.0"
-    whatwg-url "^7.0.0"
+    d3-array "2 - 3"
 
 data-urls@^2.0.0:
   version "2.0.0"
@@ -4500,10 +3882,10 @@ de-indent@^1.0.2:
   resolved "https://registry.yarnpkg.com/de-indent/-/de-indent-1.0.2.tgz#b2038e846dc33baa5796128d0804b455b8c1e21d"
   integrity sha1-sgOOhG3DO6pXlhKNCAS0VbjB4h0=
 
-deasync@^0.1.14, deasync@^0.1.15:
-  version "0.1.21"
-  resolved "https://registry.yarnpkg.com/deasync/-/deasync-0.1.21.tgz#bb11eabd4466c0d8776f0d82deb8a6126460d30f"
-  integrity sha512-kUmM8Y+PZpMpQ+B4AuOW9k2Pfx/mSupJtxOsLzmnHY2WqZUYRFccFn2RhzPAqt3Xb+sorK/badW2D4zNzqZz5w==
+deasync@^0.1.15:
+  version "0.1.23"
+  resolved "https://registry.yarnpkg.com/deasync/-/deasync-0.1.23.tgz#d52bb1f9cebb511933bb977f2820af1af5d1ec08"
+  integrity sha512-CGZSokFwidI50GOAmkz/7z3QdMzTQqAiUOzt95PuhKgi6VVztn9D03ZCzzi93uUWlp/v6A9osvNWpIvqHvKjTA==
   dependencies:
     bindings "^1.5.0"
     node-addon-api "^1.7.1"
@@ -4515,22 +3897,36 @@ debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9:
   dependencies:
     ms "2.0.0"
 
-debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.2.0:
-  version "4.3.1"
-  resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee"
-  integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==
+debug@4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1:
+  version "4.3.2"
+  resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b"
+  integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==
   dependencies:
     ms "2.1.2"
 
+debug@^3.2.7:
+  version "3.2.7"
+  resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a"
+  integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==
+  dependencies:
+    ms "^2.1.1"
+
+decache@^4.6.0:
+  version "4.6.0"
+  resolved "https://registry.yarnpkg.com/decache/-/decache-4.6.0.tgz#87026bc6e696759e82d57a3841c4e251a30356e8"
+  integrity sha512-PppOuLiz+DFeaUvFXEYZjLxAkKiMYH/do/b/MxpDe/8AgKBi5GhZxridoVIbBq72GDbL36e4p0Ce2jTGUwwU+w==
+  dependencies:
+    callsite "^1.0.0"
+
 decamelize@^1.2.0:
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
   integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=
 
-decimal.js@^10.2.0:
-  version "10.2.1"
-  resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.2.1.tgz#238ae7b0f0c793d3e3cea410108b35a2c01426a3"
-  integrity sha512-KaL7+6Fw6i5A2XSnsbhm/6B+NuEA7TZ4vqxnd5tXz9sbKtrN9Srj8ab4vKVdK8YAqZO9P1kg45Y6YLoduPf+kw==
+decimal.js@^10.2.1:
+  version "10.3.1"
+  resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.3.1.tgz#d8c3a444a9c6774ba60ca6ad7261c3a94fd5e783"
+  integrity sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ==
 
 decode-uri-component@^0.2.0:
   version "0.2.0"
@@ -4538,22 +3934,15 @@ decode-uri-component@^0.2.0:
   integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=
 
 deep-is@^0.1.3, deep-is@~0.1.3:
-  version "0.1.3"
-  resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
-  integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=
+  version "0.1.4"
+  resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831"
+  integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==
 
 deepmerge@^4.2.2:
   version "4.2.2"
   resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955"
   integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==
 
-defaults@^1.0.3:
-  version "1.0.3"
-  resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d"
-  integrity sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=
-  dependencies:
-    clone "^1.0.2"
-
 define-properties@^1.1.2, define-properties@^1.1.3:
   version "1.1.3"
   resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1"
@@ -4593,10 +3982,15 @@ defu@^3.2.2:
   resolved "https://registry.yarnpkg.com/defu/-/defu-3.2.2.tgz#be20f4cc49b9805d54ee6b610658d53894942e97"
   integrity sha512-8UWj5lNv7HD+kB0e9w77Z7TdQlbUYDVWqITLHNqFIn6khrNHv5WQo38Dcm1f6HeNyZf0U7UbPf6WeZDSdCzGDQ==
 
-delaunator@4:
+defu@^4.0.1:
   version "4.0.1"
-  resolved "https://registry.yarnpkg.com/delaunator/-/delaunator-4.0.1.tgz#3d779687f57919a7a418f8ab947d3bddb6846957"
-  integrity sha512-WNPWi1IRKZfCt/qIDMfERkDp93+iZEmOxN2yy4Jg+Xhv8SLk2UTqqbe1sfiipn0and9QrE914/ihdx82Y/Giag==
+  resolved "https://registry.yarnpkg.com/defu/-/defu-4.0.1.tgz#9d7d7a48f9295f08285d153dcff174c89b9bcb22"
+  integrity sha512-lC+G0KvvWRbisQa50+iFelm3/eMmwo4IlBmfASOVlw9MZpHHyQeVsZxc5j23+TQy5ydgEoTVSrWl7ptou1kzJQ==
+
+defu@^5.0.0:
+  version "5.0.0"
+  resolved "https://registry.yarnpkg.com/defu/-/defu-5.0.0.tgz#5768f0d402a555bfc4c267246b20f82ce8b5a10b"
+  integrity sha512-VHg73EDeRXlu7oYWRmmrNp/nl7QkdXUxkQQKig0Zk8daNmm84AbGoC8Be6/VVLJEKxn12hR0UBmz8O+xQiAPKQ==
 
 delayed-stream@~1.0.0:
   version "1.0.0"
@@ -4616,10 +4010,10 @@ des.js@^1.0.0:
     inherits "^2.0.1"
     minimalistic-assert "^1.0.0"
 
-destr@^1.0.0, destr@^1.0.1:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/destr/-/destr-1.0.1.tgz#d13db7f9d9c9ca4fcf24e86343d601217136ddc3"
-  integrity sha512-LnEdINrd1ydSqRiAGjMBVrG/G8hNruwE+fEKlkJA14MGPEoI9T7zJDwGpkMTyXT2ASE0ycnN2SYn4k6Q7j7lHg==
+destr@^1.0.0, destr@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/destr/-/destr-1.1.0.tgz#2da6add6ba71e04fd0abfb1e642d4f6763235095"
+  integrity sha512-Ev/sqS5AzzDwlpor/5wFCDu0dYMQu/0x2D6XfAsQ0E7uQmamIgYJ6Dppo2T2EOFVkeVYWjc+PCLKaqZZ57qmLg==
 
 destroy@^1.0.4, destroy@~1.0.4:
   version "1.0.4"
@@ -4631,11 +4025,6 @@ detect-indent@^5.0.0:
   resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-5.0.0.tgz#3871cc0a6a002e8c3e5b3cf7f336264675f06b9d"
   integrity sha1-OHHMCmoALow+Wzz38zYmRnXwa50=
 
-detect-libc@^1.0.3:
-  version "1.0.3"
-  resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b"
-  integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=
-
 detect-newline@^3.0.0:
   version "3.1.0"
   resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651"
@@ -4651,11 +4040,6 @@ diff-sequences@^26.6.2:
   resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-26.6.2.tgz#48ba99157de1923412eed41db6b6d4aa9ca7c0b1"
   integrity sha512-Mv/TDa3nZ9sbc5soK+OoA74BsS3mL37yixCvUAQkiuA4Wz6YtwP/K47n2rv2ovzHZvoiQeA5FTQOschKkEwB0Q==
 
-diff@^4.0.1:
-  version "4.0.2"
-  resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d"
-  integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==
-
 diffie-hellman@^5.0.0:
   version "5.0.3"
   resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875"
@@ -4687,7 +4071,7 @@ doctrine@^3.0.0:
   dependencies:
     esutils "^2.0.2"
 
-dom-converter@^0.2:
+dom-converter@^0.2.0:
   version "0.2.0"
   resolved "https://registry.yarnpkg.com/dom-converter/-/dom-converter-0.2.0.tgz#6721a9daee2e293682955b6afe416771627bb768"
   integrity sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==
@@ -4707,27 +4091,29 @@ dom-serializer@0:
     domelementtype "^2.0.1"
     entities "^2.0.0"
 
+dom-serializer@^1.0.1:
+  version "1.3.2"
+  resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.3.2.tgz#6206437d32ceefaec7161803230c7a20bc1b4d91"
+  integrity sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==
+  dependencies:
+    domelementtype "^2.0.1"
+    domhandler "^4.2.0"
+    entities "^2.0.0"
+
 domain-browser@^1.1.1:
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda"
   integrity sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==
 
-domelementtype@1, domelementtype@^1.3.1:
+domelementtype@1:
   version "1.3.1"
   resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f"
   integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==
 
-domelementtype@^2.0.1:
-  version "2.1.0"
-  resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.1.0.tgz#a851c080a6d1c3d94344aed151d99f669edf585e"
-  integrity sha512-LsTgx/L5VpD+Q8lmsXSHW2WpA+eBlZ9HPf3erD1IoPF00/3JKHZ3BknUVA2QGDNu69ZNmyFmCWBSO45XjYKC5w==
-
-domexception@^1.0.1:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/domexception/-/domexception-1.0.1.tgz#937442644ca6a31261ef36e3ec677fe805582c90"
-  integrity sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug==
-  dependencies:
-    webidl-conversions "^4.0.2"
+domelementtype@^2.0.1, domelementtype@^2.2.0:
+  version "2.2.0"
+  resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.2.0.tgz#9a0b6c2782ed6a1c7323d42267183df9bd8b1d57"
+  integrity sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==
 
 domexception@^2.0.1:
   version "2.0.1"
@@ -4736,20 +4122,29 @@ domexception@^2.0.1:
   dependencies:
     webidl-conversions "^5.0.0"
 
-domhandler@^2.3.0:
-  version "2.4.2"
-  resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.2.tgz#8805097e933d65e85546f726d60f5eb88b44f803"
-  integrity sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==
+domhandler@^4.0.0, domhandler@^4.2.0:
+  version "4.2.2"
+  resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.2.2.tgz#e825d721d19a86b8c201a35264e226c678ee755f"
+  integrity sha512-PzE9aBMsdZO8TK4BnuJwH0QT41wgMbRzuZrHUcpYncEjmQazq8QEaBWgLG7ZyC/DAZKEgglpIA6j4Qn/HmxS3w==
   dependencies:
-    domelementtype "1"
+    domelementtype "^2.2.0"
 
-domutils@^1.5.1, domutils@^1.7.0:
+domutils@^1.7.0:
   version "1.7.0"
   resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a"
   integrity sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==
   dependencies:
-    dom-serializer "0"
-    domelementtype "1"
+    dom-serializer "0"
+    domelementtype "1"
+
+domutils@^2.5.2, domutils@^2.6.0:
+  version "2.8.0"
+  resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.8.0.tgz#4437def5db6e2d1f5d6ee859bd95ca7d02048135"
+  integrity sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==
+  dependencies:
+    dom-serializer "^1.0.1"
+    domelementtype "^2.2.0"
+    domhandler "^4.2.0"
 
 dot-case@^3.0.4:
   version "3.0.4"
@@ -4766,29 +4161,12 @@ dot-prop@^5.2.0:
   dependencies:
     is-obj "^2.0.0"
 
-dotenv-expand@^5.1.0:
-  version "5.1.0"
-  resolved "https://registry.yarnpkg.com/dotenv-expand/-/dotenv-expand-5.1.0.tgz#3fbaf020bfd794884072ea26b1e9791d45a629f0"
-  integrity sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==
-
-dotenv@^5.0.0:
-  version "5.0.1"
-  resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-5.0.1.tgz#a5317459bd3d79ab88cff6e44057a6a3fbb1fcef"
-  integrity sha512-4As8uPrjfwb7VXC+WnLCbXK7y+Ueb2B3zgNCePYfhxS1PYeaO1YTeplffTEcbfLhvFNGLAz90VvJs9yomG7bow==
-
-dotenv@^8.2.0:
-  version "8.2.0"
-  resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.2.0.tgz#97e619259ada750eea3e4ea3e26bceea5424b16a"
-  integrity sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==
-
-duplexer2@~0.1.4:
-  version "0.1.4"
-  resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.1.4.tgz#8b12dab878c0d69e3e7891051662a32fc6bddcc1"
-  integrity sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=
-  dependencies:
-    readable-stream "^2.0.2"
+dotenv@^9.0.2:
+  version "9.0.2"
+  resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-9.0.2.tgz#dacc20160935a37dea6364aa1bef819fb9b6ab05"
+  integrity sha512-I9OvvrHp4pIARv4+x9iuewrWycX6CcZtoAu1XrzPxc5UygMJXJZYmBsynku8IkrJwgypE5DGNjDPmPRhDCptUg==
 
-duplexer@^0.1.1:
+duplexer@^0.1.2:
   version "0.1.2"
   resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6"
   integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==
@@ -4803,14 +4181,6 @@ duplexify@^3.4.2, duplexify@^3.6.0:
     readable-stream "^2.0.0"
     stream-shift "^1.0.0"
 
-ecc-jsbn@~0.1.1:
-  version "0.1.2"
-  resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9"
-  integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=
-  dependencies:
-    jsbn "~0.1.0"
-    safer-buffer "^2.1.0"
-
 editorconfig@^0.15.3:
   version "0.15.3"
   resolved "https://registry.yarnpkg.com/editorconfig/-/editorconfig-0.15.3.tgz#bef84c4e75fb8dcb0ce5cee8efd51c15999befc5"
@@ -4826,28 +4196,23 @@ ee-first@1.1.1:
   resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
   integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=
 
-ejs@^2.6.1:
-  version "2.7.4"
-  resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.7.4.tgz#48661287573dcc53e366c7a1ae52c3a120eec9ba"
-  integrity sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA==
-
-electron-to-chromium@^1.3.621:
-  version "1.3.634"
-  resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.634.tgz#82ea400f520f739c4f6ff00c1f7524827a917d25"
-  integrity sha512-QPrWNYeE/A0xRvl/QP3E0nkaEvYUvH3gM04ZWYtIa6QlSpEetRlRI1xvQ7hiMIySHHEV+mwDSX8Kj4YZY6ZQAw==
+electron-to-chromium@^1.3.830:
+  version "1.3.830"
+  resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.830.tgz#40e3144204f8ca11b2cebec83cf14c20d3499236"
+  integrity sha512-gBN7wNAxV5vl1430dG+XRcQhD4pIeYeak6p6rjdCtlz5wWNwDad8jwvphe5oi1chL5MV6RNRikfffBBiFuj+rQ==
 
 elliptic@^6.5.3:
-  version "6.5.3"
-  resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.3.tgz#cb59eb2efdaf73a0bd78ccd7015a62ad6e0f93d6"
-  integrity sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw==
+  version "6.5.4"
+  resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb"
+  integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==
   dependencies:
-    bn.js "^4.4.0"
-    brorand "^1.0.1"
+    bn.js "^4.11.9"
+    brorand "^1.1.0"
     hash.js "^1.0.0"
-    hmac-drbg "^1.0.0"
-    inherits "^2.0.1"
-    minimalistic-assert "^1.0.0"
-    minimalistic-crypto-utils "^1.0.0"
+    hmac-drbg "^1.0.1"
+    inherits "^2.0.4"
+    minimalistic-assert "^1.0.1"
+    minimalistic-crypto-utils "^1.0.1"
 
 emittery@^0.7.1:
   version "0.7.2"
@@ -4881,10 +4246,10 @@ end-of-stream@^1.0.0, end-of-stream@^1.1.0:
   dependencies:
     once "^1.4.0"
 
-enhanced-resolve@^4.1.1, enhanced-resolve@^4.3.0:
-  version "4.3.0"
-  resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.3.0.tgz#3b806f3bfafc1ec7de69551ef93cca46c1704126"
-  integrity sha512-3e87LvavsdxyoCfGusJnrZ5G8SLPOFeHSNpZI/ATL9a5leXo2k0w6MKnbqhdBad9qTobSfB20Ld7UmgoNbAZkQ==
+enhanced-resolve@^4.1.1, enhanced-resolve@^4.5.0:
+  version "4.5.0"
+  resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz#2f3cfd84dbe3b487f18f2db2ef1e064a571ca5ec"
+  integrity sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg==
   dependencies:
     graceful-fs "^4.1.2"
     memory-fs "^0.5.0"
@@ -4897,20 +4262,10 @@ enquirer@^2.3.5:
   dependencies:
     ansi-colors "^4.1.1"
 
-entities@^1.1.1, entities@^1.1.2:
-  version "1.1.2"
-  resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56"
-  integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==
-
 entities@^2.0.0:
-  version "2.1.0"
-  resolved "https://registry.yarnpkg.com/entities/-/entities-2.1.0.tgz#992d3129cf7df6870b96c57858c249a120f8b8b5"
-  integrity sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==
-
-envinfo@^7.3.1:
-  version "7.7.3"
-  resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.7.3.tgz#4b2d8622e3e7366afb8091b23ed95569ea0208cc"
-  integrity sha512-46+j5QxbPWza0PB1i15nZx0xQ4I/EfQxg9J8Had3b408SV63nEtor2e+oiY63amTo9KTuh2a3XLObNwduxYwwA==
+  version "2.2.0"
+  resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55"
+  integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==
 
 errno@^0.1.3, errno@~0.1.7:
   version "0.1.8"
@@ -4933,40 +4288,28 @@ error-stack-parser@^2.0.0:
   dependencies:
     stackframe "^1.1.1"
 
-es-abstract@^1.17.2:
-  version "1.17.7"
-  resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.7.tgz#a4de61b2f66989fc7421676c1cb9787573ace54c"
-  integrity sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==
-  dependencies:
-    es-to-primitive "^1.2.1"
-    function-bind "^1.1.1"
-    has "^1.0.3"
-    has-symbols "^1.0.1"
-    is-callable "^1.2.2"
-    is-regex "^1.1.1"
-    object-inspect "^1.8.0"
-    object-keys "^1.1.1"
-    object.assign "^4.1.1"
-    string.prototype.trimend "^1.0.1"
-    string.prototype.trimstart "^1.0.1"
-
-es-abstract@^1.18.0-next.1:
-  version "1.18.0-next.1"
-  resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.0-next.1.tgz#6e3a0a4bda717e5023ab3b8e90bec36108d22c68"
-  integrity sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==
+es-abstract@^1.17.2, es-abstract@^1.18.0-next.1, es-abstract@^1.18.0-next.2, es-abstract@^1.18.2:
+  version "1.18.5"
+  resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.5.tgz#9b10de7d4c206a3581fd5b2124233e04db49ae19"
+  integrity sha512-DDggyJLoS91CkJjgauM5c0yZMjiD1uK3KcaCeAmffGwZ+ODWzOkPN4QwRbsK5DOFf06fywmyLci3ZD8jLGhVYA==
   dependencies:
+    call-bind "^1.0.2"
     es-to-primitive "^1.2.1"
     function-bind "^1.1.1"
+    get-intrinsic "^1.1.1"
     has "^1.0.3"
-    has-symbols "^1.0.1"
-    is-callable "^1.2.2"
-    is-negative-zero "^2.0.0"
-    is-regex "^1.1.1"
-    object-inspect "^1.8.0"
+    has-symbols "^1.0.2"
+    internal-slot "^1.0.3"
+    is-callable "^1.2.3"
+    is-negative-zero "^2.0.1"
+    is-regex "^1.1.3"
+    is-string "^1.0.6"
+    object-inspect "^1.11.0"
     object-keys "^1.1.1"
-    object.assign "^4.1.1"
-    string.prototype.trimend "^1.0.1"
-    string.prototype.trimstart "^1.0.1"
+    object.assign "^4.1.2"
+    string.prototype.trimend "^1.0.4"
+    string.prototype.trimstart "^1.0.4"
+    unbox-primitive "^1.0.1"
 
 es-to-primitive@^1.2.1:
   version "1.2.1"
@@ -4997,25 +4340,18 @@ escape-string-regexp@^2.0.0:
   resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344"
   integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==
 
-escodegen@^1.11.0, escodegen@^1.11.1, escodegen@^1.14.1:
-  version "1.14.3"
-  resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.14.3.tgz#4e7b81fba61581dc97582ed78cab7f0e8d63f503"
-  integrity sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==
-  dependencies:
-    esprima "^4.0.1"
-    estraverse "^4.2.0"
-    esutils "^2.0.2"
-    optionator "^0.8.1"
-  optionalDependencies:
-    source-map "~0.6.1"
+escape-string-regexp@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34"
+  integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==
 
-escodegen@~1.9.0:
-  version "1.9.1"
-  resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.9.1.tgz#dbae17ef96c8e4bedb1356f4504fa4cc2f7cb7e2"
-  integrity sha512-6hTjO1NAWkHnDk3OqQ4YrCuwwmGHL9S3nPlzBOUG/R44rda3wLNrfvQ5fkSGjyhHFKM7ALPKcKGrwvCLe0lC7Q==
+escodegen@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-2.0.0.tgz#5e32b12833e8aa8fa35e1bf0befa89380484c7dd"
+  integrity sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==
   dependencies:
-    esprima "^3.1.3"
-    estraverse "^4.2.0"
+    esprima "^4.0.1"
+    estraverse "^5.2.0"
     esutils "^2.0.2"
     optionator "^0.8.1"
   optionalDependencies:
@@ -5042,12 +4378,12 @@ eslint-config-standard@^14.1.1:
   integrity sha512-Z9B+VR+JIXRxz21udPTL9HpFMyoMUEeX1G251EQ6e05WD9aPVtVBn09XUmZ259wCMlCDmYDSZG62Hhm+ZTJcUg==
 
 eslint-import-resolver-node@^0.3.3:
-  version "0.3.4"
-  resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz#85ffa81942c25012d8231096ddf679c03042c717"
-  integrity sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA==
+  version "0.3.6"
+  resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz#4048b958395da89668252001dbd9eca6b83bacbd"
+  integrity sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw==
   dependencies:
-    debug "^2.6.9"
-    resolve "^1.13.1"
+    debug "^3.2.7"
+    resolve "^1.20.0"
 
 eslint-loader@^4.0.2:
   version "4.0.2"
@@ -5061,11 +4397,11 @@ eslint-loader@^4.0.2:
     schema-utils "^2.6.5"
 
 eslint-module-utils@^2.6.0:
-  version "2.6.0"
-  resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.6.0.tgz#579ebd094f56af7797d19c9866c9c9486629bfa6"
-  integrity sha512-6j9xxegbqe8/kZY8cYpcp0xhbK0EgJlg3g9mib3/miLaExuuwc3n5UEfSnU6hWMbT0FAYVvDbL9RrRgpUeQIvA==
+  version "2.6.2"
+  resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.6.2.tgz#94e5540dd15fe1522e8ffa3ec8db3b7fa7e7a534"
+  integrity sha512-QG8pcgThYOuqxupd06oYTZoNOGaUdTY1PqK+oS6ElF6vs4pBdk/aYxFVQQXzcrAqp9m7cl7lb2ubazX+g16k2Q==
   dependencies:
-    debug "^2.6.9"
+    debug "^3.2.7"
     pkg-dir "^2.0.0"
 
 eslint-plugin-es@^3.0.0:
@@ -5124,16 +4460,16 @@ eslint-plugin-nuxt@1.0.0:
     vue-eslint-parser "^7.0.0"
 
 eslint-plugin-prettier@^3.1.4:
-  version "3.3.1"
-  resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.3.1.tgz#7079cfa2497078905011e6f82e8dd8453d1371b7"
-  integrity sha512-Rq3jkcFY8RYeQLgk2cCwuc0P7SEFwDravPhsJZOQ5N4YI4DSg50NyqJ/9gdZHzQlHf8MvafSesbNJCcP/FF6pQ==
+  version "3.4.1"
+  resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.4.1.tgz#e9ddb200efb6f3d05ffe83b1665a716af4a387e5"
+  integrity sha512-htg25EUYUeIhKHXjOinK4BgCcDwtLHjqaxCDsMy5nbnUMkKFvIhMVCp+5GFUXQ4Nr8lBsPqtGAqBenbpFqAA2g==
   dependencies:
     prettier-linter-helpers "^1.0.0"
 
 eslint-plugin-promise@^4.2.1:
-  version "4.2.1"
-  resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-4.2.1.tgz#845fd8b2260ad8f82564c1222fce44ad71d9418a"
-  integrity sha512-VoM09vT7bfA7D+upt+FjeBO5eHIJQBUWki1aPvB+vbNiHS3+oGIJGIeyBtKQTME6UPXXy3vV07OL1tHd3ANuDw==
+  version "4.3.1"
+  resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-4.3.1.tgz#61485df2a359e03149fdafc0a68b0e030ad2ac45"
+  integrity sha512-bY2sGqyptzFBDLh/GMbAxfdJC+b0f23ME63FOE4+Jao0oZ3E1LEwFtWJX/1pGMJLiTtrSSern2CRM/g+dfc0eQ==
 
 eslint-plugin-standard@^4.0.1:
   version "4.1.0"
@@ -5185,11 +4521,12 @@ eslint-scope@^5.0.0, eslint-scope@^5.1.1:
     estraverse "^4.1.1"
 
 eslint-template-visitor@^2.0.0:
-  version "2.2.2"
-  resolved "https://registry.yarnpkg.com/eslint-template-visitor/-/eslint-template-visitor-2.2.2.tgz#46cd2b06eca5c1d97369aadd96e131df88fdd59c"
-  integrity sha512-SkcLjzKw3JjKTWHacRDeLBa2gxb600zbCKTkXj/V97QnZ9yxkknoPL8vc8PFueqbFXP7mYNTQzjCjcMpTRdRaA==
+  version "2.3.2"
+  resolved "https://registry.yarnpkg.com/eslint-template-visitor/-/eslint-template-visitor-2.3.2.tgz#b52f96ff311e773a345d79053ccc78275bbc463d"
+  integrity sha512-3ydhqFpuV7x1M9EK52BPNj6V0Kwu0KKkcIAfpUhwHbR8ocRln/oUHgfxQupY8O1h4Qv/POHDumb/BwwNfxbtnA==
   dependencies:
-    babel-eslint "^10.1.0"
+    "@babel/core" "^7.12.16"
+    "@babel/eslint-parser" "^7.12.16"
     eslint-visitor-keys "^2.0.0"
     esquery "^1.3.1"
     multimap "^1.1.0"
@@ -5206,34 +4543,37 @@ eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3
   resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e"
   integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==
 
-eslint-visitor-keys@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz#21fdc8fbcd9c795cc0321f0563702095751511a8"
-  integrity sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==
+eslint-visitor-keys@^2.0.0, eslint-visitor-keys@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303"
+  integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==
 
 eslint@^7.5.0:
-  version "7.17.0"
-  resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.17.0.tgz#4ccda5bf12572ad3bf760e6f195886f50569adb0"
-  integrity sha512-zJk08MiBgwuGoxes5sSQhOtibZ75pz0J35XTRlZOk9xMffhpA9BTbQZxoXZzOl5zMbleShbGwtw+1kGferfFwQ==
+  version "7.32.0"
+  resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.32.0.tgz#c6d328a14be3fb08c8d1d21e12c02fdb7a2a812d"
+  integrity sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==
   dependencies:
-    "@babel/code-frame" "^7.0.0"
-    "@eslint/eslintrc" "^0.2.2"
+    "@babel/code-frame" "7.12.11"
+    "@eslint/eslintrc" "^0.4.3"
+    "@humanwhocodes/config-array" "^0.5.0"
     ajv "^6.10.0"
     chalk "^4.0.0"
     cross-spawn "^7.0.2"
     debug "^4.0.1"
     doctrine "^3.0.0"
     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.2.0"
+    esquery "^1.4.0"
     esutils "^2.0.2"
-    file-entry-cache "^6.0.0"
+    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"
@@ -5241,7 +4581,7 @@ eslint@^7.5.0:
     js-yaml "^3.13.1"
     json-stable-stringify-without-jsonify "^1.0.1"
     levn "^0.4.1"
-    lodash "^4.17.19"
+    lodash.merge "^4.6.2"
     minimatch "^3.0.4"
     natural-compare "^1.4.0"
     optionator "^0.9.1"
@@ -5250,15 +4590,10 @@ eslint@^7.5.0:
     semver "^7.2.1"
     strip-ansi "^6.0.0"
     strip-json-comments "^3.1.0"
-    table "^6.0.4"
+    table "^6.0.9"
     text-table "^0.2.0"
     v8-compile-cache "^2.0.3"
 
-esm@^3.2.25:
-  version "3.2.25"
-  resolved "https://registry.yarnpkg.com/esm/-/esm-3.2.25.tgz#342c18c29d56157688ba5ce31f8431fbb795cc10"
-  integrity sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==
-
 espree@^6.2.1:
   version "6.2.1"
   resolved "https://registry.yarnpkg.com/espree/-/espree-6.2.1.tgz#77fc72e1fd744a2052c20f38a5b575832e82734a"
@@ -5277,20 +4612,15 @@ espree@^7.3.0, espree@^7.3.1:
     acorn-jsx "^5.3.1"
     eslint-visitor-keys "^1.3.0"
 
-esprima@^3.1.3:
-  version "3.1.3"
-  resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633"
-  integrity sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=
-
 esprima@^4.0.0, esprima@^4.0.1:
   version "4.0.1"
   resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71"
   integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==
 
-esquery@^1.0.1, esquery@^1.2.0, esquery@^1.3.1:
-  version "1.3.1"
-  resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.3.1.tgz#b78b5828aa8e214e29fb74c4d5b752e1c033da57"
-  integrity sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==
+esquery@^1.3.1, esquery@^1.4.0:
+  version "1.4.0"
+  resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5"
+  integrity sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==
   dependencies:
     estraverse "^5.1.0"
 
@@ -5301,7 +4631,7 @@ esrecurse@^4.1.0, esrecurse@^4.3.0:
   dependencies:
     estraverse "^5.2.0"
 
-estraverse@^4.1.1, estraverse@^4.2.0:
+estraverse@^4.1.1:
   version "4.3.0"
   resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d"
   integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==
@@ -5327,9 +4657,9 @@ eventemitter3@^4.0.0:
   integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==
 
 events@^3.0.0:
-  version "3.2.0"
-  resolved "https://registry.yarnpkg.com/events/-/events-3.2.0.tgz#93b87c18f8efcd4202a461aec4dfc0556b639379"
-  integrity sha512-/46HWwbfCX2xTawVfkKLGxMifJYQBWMwY1mjywRtb4c9x8l5NP3KoJtnIOiL1hfdRkIuYhETxQlo62IF8tcnlg==
+  version "3.3.0"
+  resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400"
+  integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==
 
 eventsource-polyfill@^0.9.6:
   version "0.9.6"
@@ -5345,9 +4675,9 @@ evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3:
     safe-buffer "^5.1.1"
 
 exec-sh@^0.3.2:
-  version "0.3.4"
-  resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.3.4.tgz#3a018ceb526cc6f6df2bb504b2bfe8e3a4934ec5"
-  integrity sha512-sEFIkc61v75sWeOe72qyrqg2Qg0OuLESziUDk/O/z2qgS15y2gWVFrI6f2Qn/qw/0/NCfCEsmNA4zOjkwEZT1A==
+  version "0.3.6"
+  resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.3.6.tgz#ff264f9e325519a60cb5e273692943483cca63bc"
+  integrity sha512-nQn+hI3yp+oD0huYhKwvYI32+JFeq+XkNcD1GAo3Y/MjxsfVGmrrzrnzjWiNY6f+pUCP440fThsFh5gZrRAU/w==
 
 execa@^1.0.0:
   version "1.0.0"
@@ -5362,10 +4692,10 @@ execa@^1.0.0:
     signal-exit "^3.0.0"
     strip-eof "^1.0.0"
 
-execa@^3.4.0:
-  version "3.4.0"
-  resolved "https://registry.yarnpkg.com/execa/-/execa-3.4.0.tgz#c08ed4550ef65d858fac269ffc8572446f37eb89"
-  integrity sha512-r9vdGQk4bmCuK1yKQu1KTwcT2zwfWdbdaXfCtAh+5nU/4fSX+JAb7vZGvI5naJrQlvONrEB20jeruESI69530g==
+execa@^4.0.0:
+  version "4.1.0"
+  resolved "https://registry.yarnpkg.com/execa/-/execa-4.1.0.tgz#4e5491ad1572f2f17a77d388c6c857135b22847a"
+  integrity sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==
   dependencies:
     cross-spawn "^7.0.0"
     get-stream "^5.0.0"
@@ -5374,23 +4704,22 @@ execa@^3.4.0:
     merge-stream "^2.0.0"
     npm-run-path "^4.0.0"
     onetime "^5.1.0"
-    p-finally "^2.0.0"
     signal-exit "^3.0.2"
     strip-final-newline "^2.0.0"
 
-execa@^4.0.0:
-  version "4.1.0"
-  resolved "https://registry.yarnpkg.com/execa/-/execa-4.1.0.tgz#4e5491ad1572f2f17a77d388c6c857135b22847a"
-  integrity sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==
+execa@^5.0.0:
+  version "5.1.1"
+  resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd"
+  integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==
   dependencies:
-    cross-spawn "^7.0.0"
-    get-stream "^5.0.0"
-    human-signals "^1.1.1"
+    cross-spawn "^7.0.3"
+    get-stream "^6.0.0"
+    human-signals "^2.1.0"
     is-stream "^2.0.0"
     merge-stream "^2.0.0"
-    npm-run-path "^4.0.0"
-    onetime "^5.1.0"
-    signal-exit "^3.0.2"
+    npm-run-path "^4.0.1"
+    onetime "^5.1.2"
+    signal-exit "^3.0.3"
     strip-final-newline "^2.0.0"
 
 exit@^0.1.2:
@@ -5423,42 +4752,6 @@ expect@^26.6.2:
     jest-message-util "^26.6.2"
     jest-regex-util "^26.0.0"
 
-express@^4.16.3:
-  version "4.17.1"
-  resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134"
-  integrity sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==
-  dependencies:
-    accepts "~1.3.7"
-    array-flatten "1.1.1"
-    body-parser "1.19.0"
-    content-disposition "0.5.3"
-    content-type "~1.0.4"
-    cookie "0.4.0"
-    cookie-signature "1.0.6"
-    debug "2.6.9"
-    depd "~1.1.2"
-    encodeurl "~1.0.2"
-    escape-html "~1.0.3"
-    etag "~1.8.1"
-    finalhandler "~1.1.2"
-    fresh "0.5.2"
-    merge-descriptors "1.0.1"
-    methods "~1.1.2"
-    on-finished "~2.3.0"
-    parseurl "~1.3.3"
-    path-to-regexp "0.1.7"
-    proxy-addr "~2.0.5"
-    qs "6.7.0"
-    range-parser "~1.2.1"
-    safe-buffer "5.1.2"
-    send "0.17.1"
-    serve-static "1.14.1"
-    setprototypeof "1.1.1"
-    statuses "~1.5.0"
-    type-is "~1.6.18"
-    utils-merge "1.0.1"
-    vary "~1.1.2"
-
 extend-shallow@^2.0.1:
   version "2.0.1"
   resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f"
@@ -5474,11 +4767,6 @@ extend-shallow@^3.0.0, extend-shallow@^3.0.2:
     assign-symbols "^1.0.0"
     is-extendable "^1.0.1"
 
-extend@~3.0.2:
-  version "3.0.2"
-  resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
-  integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==
-
 external-editor@^3.0.3:
   version "3.1.0"
   resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495"
@@ -5502,7 +4790,7 @@ extglob@^2.0.4:
     snapdragon "^0.8.1"
     to-regex "^3.0.1"
 
-extract-css-chunks-webpack-plugin@^4.8.0:
+extract-css-chunks-webpack-plugin@^4.9.0:
   version "4.9.0"
   resolved "https://registry.yarnpkg.com/extract-css-chunks-webpack-plugin/-/extract-css-chunks-webpack-plugin-4.9.0.tgz#da5e6b1d8b39a398c817ffc98550f4ccb6d795e1"
   integrity sha512-HNuNPCXRMqJDQ1OHAUehoY+0JVCnw9Y/H22FQzYVwo8Ulgew98AGDu0grnY5c7xwiXHjQa6yJ/1dxLCI/xqTyQ==
@@ -5519,27 +4807,7 @@ extract-from-css@^0.4.4:
   dependencies:
     css "^2.1.0"
 
-extsprintf@1.3.0:
-  version "1.3.0"
-  resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05"
-  integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=
-
-extsprintf@^1.2.0:
-  version "1.4.0"
-  resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f"
-  integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8=
-
-falafel@^2.1.0:
-  version "2.2.4"
-  resolved "https://registry.yarnpkg.com/falafel/-/falafel-2.2.4.tgz#b5d86c060c2412a43166243cb1bce44d1abd2819"
-  integrity sha512-0HXjo8XASWRmsS0X1EkhwEMZaD3Qvp7FfURwjLKjG1ghfRm/MGZl2r4cWUTv41KdNghTw4OUMmVtdGQp3+H+uQ==
-  dependencies:
-    acorn "^7.1.1"
-    foreach "^2.0.5"
-    isarray "^2.0.1"
-    object-keys "^1.0.6"
-
-fast-deep-equal@^3.1.1:
+fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3:
   version "3.1.3"
   resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
   integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
@@ -5549,29 +4817,16 @@ fast-diff@^1.1.2:
   resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03"
   integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==
 
-fast-glob@^2.2.2:
-  version "2.2.7"
-  resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-2.2.7.tgz#6953857c3afa475fff92ee6015d52da70a4cd39d"
-  integrity sha512-g1KuQwHOZAmOZMuBtHdxDtju+T2RT8jgCC9aANsbpdiDDTSnjgfuVsIBNKbUeJI3oKMRExcfNDtJl4OhbffMsw==
-  dependencies:
-    "@mrmlnc/readdir-enhanced" "^2.2.1"
-    "@nodelib/fs.stat" "^1.1.2"
-    glob-parent "^3.1.0"
-    is-glob "^4.0.0"
-    merge2 "^1.2.3"
-    micromatch "^3.1.10"
-
 fast-glob@^3.1.1:
-  version "3.2.4"
-  resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.4.tgz#d20aefbf99579383e7f3cc66529158c9b98554d3"
-  integrity sha512-kr/Oo6PX51265qeuCYsyGypiO5uJFgBS0jksyG7FUeCyQzNwYnzrNIMR1NXfkZXsMYXYLRAHgISHBz8gQcxKHQ==
+  version "3.2.7"
+  resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.7.tgz#fd6cb7a2d7e9aa7a7846111e85a196d6b2f766a1"
+  integrity sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==
   dependencies:
     "@nodelib/fs.stat" "^2.0.2"
     "@nodelib/fs.walk" "^1.2.3"
-    glob-parent "^5.1.0"
+    glob-parent "^5.1.2"
     merge2 "^1.3.0"
-    micromatch "^4.0.2"
-    picomatch "^2.2.1"
+    micromatch "^4.0.4"
 
 fast-json-stable-stringify@^2.0.0:
   version "2.1.0"
@@ -5583,15 +4838,10 @@ fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6:
   resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
   integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=
 
-fastparse@^1.1.2:
-  version "1.1.2"
-  resolved "https://registry.yarnpkg.com/fastparse/-/fastparse-1.1.2.tgz#91728c5a5942eced8531283c79441ee4122c35a9"
-  integrity sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==
-
 fastq@^1.6.0:
-  version "1.10.0"
-  resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.10.0.tgz#74dbefccade964932cdf500473ef302719c652bb"
-  integrity sha512-NL2Qc5L3iQEsyYzweq7qfgy5OtXCmGzGvhElGEd/SoFWEMOEczNh5s5ocaF01HDetxz+p8ecjNPA6cZxxIHmzA==
+  version "1.12.0"
+  resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.12.0.tgz#ed7b6ab5d62393fb2cc591c853652a5c318bf794"
+  integrity sha512-VNX0QkHK3RsXVKr9KrlUv/FoTa0NdbYoHHl7uXHv2rzyHSlxjdNAKug2twd9luJxpcyNeAgf5iPPMutJO67Dfg==
   dependencies:
     reusify "^1.0.4"
 
@@ -5602,13 +4852,6 @@ fb-watchman@^2.0.0:
   dependencies:
     bser "2.1.1"
 
-fibers@^4.0.3:
-  version "4.0.3"
-  resolved "https://registry.yarnpkg.com/fibers/-/fibers-4.0.3.tgz#dda5918280a48507f5d8a96dd9a525e8f4a532e2"
-  integrity sha512-MW5VrDtTOLpKK7lzw4qD7Z9tXaAhdOmOED5RHzg3+HjUk+ibkjVW0Py2ERtdqgTXaerLkVkBy2AEmJiT6RMyzg==
-  dependencies:
-    detect-libc "^1.0.3"
-
 figgy-pudding@^3.5.1:
   version "3.5.2"
   resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.2.tgz#b4eee8148abb01dcf1d1ac34367d59e12fa61d6e"
@@ -5621,20 +4864,20 @@ figures@^3.0.0:
   dependencies:
     escape-string-regexp "^1.0.5"
 
-file-entry-cache@^6.0.0:
-  version "6.0.0"
-  resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.0.tgz#7921a89c391c6d93efec2169ac6bf300c527ea0a"
-  integrity sha512-fqoO76jZ3ZnYrXLDRxBR1YvOvc0k844kcOg40bgsPrE25LAb/PDqTY+ho64Xh2c8ZXgIKldchCFHczG2UVRcWA==
+file-entry-cache@^6.0.1:
+  version "6.0.1"
+  resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027"
+  integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==
   dependencies:
     flat-cache "^3.0.4"
 
-file-loader@^4.0.0, file-loader@^4.3.0:
-  version "4.3.0"
-  resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-4.3.0.tgz#780f040f729b3d18019f20605f723e844b8a58af"
-  integrity sha512-aKrYPYjF1yG3oX0kWRrqrSMfgftm7oJW5M+m4owoldH5C51C0RkIwB++JbRvEW3IU6/ZG5n8UvEcdgwOt2UOWA==
+file-loader@^6.2.0:
+  version "6.2.0"
+  resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-6.2.0.tgz#baef7cf8e1840df325e4390b4484879480eebe4d"
+  integrity sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==
   dependencies:
-    loader-utils "^1.2.3"
-    schema-utils "^2.5.0"
+    loader-utils "^2.0.0"
+    schema-utils "^3.0.0"
 
 file-saver@^2.0.5:
   version "2.0.5"
@@ -5646,11 +4889,6 @@ file-uri-to-path@1.0.0:
   resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd"
   integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==
 
-filesize@^3.6.0, filesize@^3.6.1:
-  version "3.6.1"
-  resolved "https://registry.yarnpkg.com/filesize/-/filesize-3.6.1.tgz#090bb3ee01b6f801a8a8be99d31710b3422bb317"
-  integrity sha512-7KjR1vv6qnicaPMi1iiTcI85CyYwRO/PSFCu6SvqL8jN2Wjt/NIYQTFtFs7fSDCYOstUkEWIQGFUg5YZQfjlcg==
-
 fill-range@^4.0.0:
   version "4.0.0"
   resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7"
@@ -5668,7 +4906,12 @@ fill-range@^7.0.1:
   dependencies:
     to-regex-range "^5.0.1"
 
-finalhandler@1.1.2, finalhandler@~1.1.2:
+filter-obj@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/filter-obj/-/filter-obj-1.1.0.tgz#9b311112bc6c6127a16e016c6c5d7f19e0805c5b"
+  integrity sha1-mzERErxsYSehbgFsbF1/GeCAXFs=
+
+finalhandler@1.1.2:
   version "1.1.2"
   resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d"
   integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==
@@ -5699,9 +4942,9 @@ find-cache-dir@^2.0.0, find-cache-dir@^2.1.0:
     pkg-dir "^3.0.0"
 
 find-cache-dir@^3.0.0, find-cache-dir@^3.3.1:
-  version "3.3.1"
-  resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.1.tgz#89b33fad4a4670daa94f855f7fbe31d6d84fe880"
-  integrity sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==
+  version "3.3.2"
+  resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.2.tgz#b30c5b6eff0730731aea9bbd9dbecbd80256d64b"
+  integrity sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==
   dependencies:
     commondir "^1.0.1"
     make-dir "^3.0.2"
@@ -5743,9 +4986,9 @@ flat@^5.0.0:
   integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==
 
 flatted@^3.1.0:
-  version "3.1.0"
-  resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.1.0.tgz#a5d06b4a8b01e3a63771daa5cb7a1903e2e57067"
-  integrity sha512-tW+UkmtNg/jv9CSofAKvgVcO7c2URjhTdW1ZTkcAritblu8tajiYy7YisnIflEwtKssCtOxpnBRoCB7iap0/TA==
+  version "3.2.2"
+  resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.2.tgz#64bfed5cb68fe3ca78b3eb214ad97b63bedce561"
+  integrity sha512-JaTY/wtrcSyvXJl4IMFHPKyFur1sE9AUqc0QnhOaJ0CxHtAoIV8pYDzeEfAaNEtGkOfq4gr3LBFmdXW5mOQFnA==
 
 flatten@^1.0.2:
   version "1.0.3"
@@ -5760,40 +5003,25 @@ flush-write-stream@^1.0.0:
     inherits "^2.0.3"
     readable-stream "^2.3.6"
 
-follow-redirects@^1.0.0, follow-redirects@^1.10.0:
-  version "1.13.1"
-  resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.13.1.tgz#5f69b813376cee4fd0474a3aba835df04ab763b7"
-  integrity sha512-SSG5xmZh1mkPGyKzjZP8zLjltIfpW32Y5QpdNJyjcfGxK3qo3NDDkZOZSFiGn1A6SclQxY9GzEwAHQ3dmYRWpg==
+follow-redirects@^1.0.0, follow-redirects@^1.14.0:
+  version "1.14.3"
+  resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.3.tgz#6ada78118d8d24caee595595accdc0ac6abd022e"
+  integrity sha512-3MkHxknWMUtb23apkgz/83fDoe+y+qr0TdgacGIA7bew+QLBo3vdgEN2xEsuXNivpFy4CyDhBBZnNZOtalmenw==
 
 for-in@^1.0.2:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80"
   integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=
 
-foreach@^2.0.5:
-  version "2.0.5"
-  resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99"
-  integrity sha1-C+4AUBiusmDQo6865ljdATbsG5k=
-
-forever-agent@~0.6.1:
-  version "0.6.1"
-  resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
-  integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=
-
-form-data@~2.3.2:
-  version "2.3.3"
-  resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6"
-  integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==
+form-data@^3.0.0:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f"
+  integrity sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==
   dependencies:
     asynckit "^0.4.0"
-    combined-stream "^1.0.6"
+    combined-stream "^1.0.8"
     mime-types "^2.1.12"
 
-forwarded@~0.1.2:
-  version "0.1.2"
-  resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84"
-  integrity sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=
-
 fragment-cache@^0.2.1:
   version "0.2.1"
   resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19"
@@ -5823,6 +5051,16 @@ fs-extra@^8.1.0:
     jsonfile "^4.0.0"
     universalify "^0.1.0"
 
+fs-extra@^9.1.0:
+  version "9.1.0"
+  resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d"
+  integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==
+  dependencies:
+    at-least-node "^1.0.0"
+    graceful-fs "^4.2.0"
+    jsonfile "^6.0.1"
+    universalify "^2.0.0"
+
 fs-memo@^1.2.0:
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/fs-memo/-/fs-memo-1.2.0.tgz#a2ec3be606b902077adbb37ec529c5ec5fb2e037"
@@ -5835,6 +5073,11 @@ fs-minipass@^2.0.0:
   dependencies:
     minipass "^3.0.0"
 
+fs-monkey@1.0.3:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/fs-monkey/-/fs-monkey-1.0.3.tgz#ae3ac92d53bb328efe0e9a1d9541f6ad8d48e2d3"
+  integrity sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q==
+
 fs-write-stream-atomic@^1.0.8:
   version "1.0.10"
   resolved "https://registry.yarnpkg.com/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz#b47df53493ef911df75731e70a9ded0189db40c9"
@@ -5858,15 +5101,10 @@ fsevents@^1.2.7:
     bindings "^1.5.0"
     nan "^2.12.1"
 
-fsevents@^2.1.2:
-  version "2.3.1"
-  resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.1.tgz#b209ab14c61012636c8863507edf7fb68cc54e9f"
-  integrity sha512-YR47Eg4hChJGAB1O3yEAOkGO+rlzutoICGqGo9EZ4lKWokzZRSyIW1QmTzqjtw8MJdj9srP869CuWw/hyzSiBw==
-
-fsevents@~2.1.2:
-  version "2.1.3"
-  resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.3.tgz#fb738703ae8d2f9fe900c33836ddebee8b97f23e"
-  integrity sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==
+fsevents@^2.1.2, fsevents@~2.3.2:
+  version "2.3.2"
+  resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
+  integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
 
 function-bind@^1.1.1:
   version "1.1.1"
@@ -5878,7 +5116,7 @@ functional-red-black-tree@^1.0.1:
   resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327"
   integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=
 
-gensync@^1.0.0-beta.1:
+gensync@^1.0.0-beta.2:
   version "1.0.0-beta.2"
   resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0"
   integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==
@@ -5888,10 +5126,10 @@ get-caller-file@^2.0.1:
   resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
   integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
 
-get-intrinsic@^1.0.0, get-intrinsic@^1.0.1:
-  version "1.0.2"
-  resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.0.2.tgz#6820da226e50b24894e08859469dc68361545d49"
-  integrity sha512-aeX0vrFm21ILl3+JpFFRNe9aUvp6VFZb2/CTbgLb8j75kOhvoNYjt9d8KA/tJG4gSo8nzEDedRl0h7vDmBYRVg==
+get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6"
+  integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==
   dependencies:
     function-bind "^1.1.1"
     has "^1.0.3"
@@ -5902,18 +5140,13 @@ get-package-type@^0.1.0:
   resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a"
   integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==
 
-get-port-please@^1.0.0:
-  version "1.1.0"
-  resolved "https://registry.yarnpkg.com/get-port-please/-/get-port-please-1.1.0.tgz#7a60007578df6c4570c233803b48854c44db41f7"
-  integrity sha512-C9adQpQ9uyboxURlYAVcqvKdnrZ0uIad6lAZzIr51G5shhUFcZUwl8rxY0B0hB6OJytBNzPB1Uj/S1CpP9aFzQ==
+get-port-please@^2.2.0:
+  version "2.2.0"
+  resolved "https://registry.yarnpkg.com/get-port-please/-/get-port-please-2.2.0.tgz#3fabbbe2f9d8e6b7c47e1cddd71fc4c593f1deac"
+  integrity sha512-1c7Np/cpA7XCB6IrPAdaBaJjlGHTqg4P82h/ZqyBL6dCdwRzZBOFGZO7FL2KaZ2uNvD6v8QilA7LZwMpmIggDQ==
   dependencies:
     fs-memo "^1.2.0"
 
-get-port@^3.2.0:
-  version "3.2.0"
-  resolved "https://registry.yarnpkg.com/get-port/-/get-port-3.2.0.tgz#dd7ce7de187c06c8bf353796ac71e099f0980ebc"
-  integrity sha1-3Xzn3hh8Bsi/NTeWrHHgmfCYDrw=
-
 get-stdin@^6.0.0:
   version "6.0.0"
   resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-6.0.0.tgz#9e09bf712b360ab9225e812048f71fde9c89657b"
@@ -5933,35 +5166,33 @@ get-stream@^5.0.0:
   dependencies:
     pump "^3.0.0"
 
+get-stream@^6.0.0:
+  version "6.0.1"
+  resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7"
+  integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==
+
 get-value@^2.0.3, get-value@^2.0.6:
   version "2.0.6"
   resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28"
   integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=
 
-getpass@^0.1.1:
-  version "0.1.7"
-  resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa"
-  integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=
-  dependencies:
-    assert-plus "^1.0.0"
-
 git-config-path@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/git-config-path/-/git-config-path-2.0.0.tgz#62633d61af63af4405a5024efd325762f58a181b"
   integrity sha512-qc8h1KIQbJpp+241id3GuAtkdyJ+IK+LIVtkiFTRKRrmddDzs3SI9CvP1QYmWBFvm1I/PWRwj//of8bgAc0ltA==
 
 git-up@^4.0.0:
-  version "4.0.2"
-  resolved "https://registry.yarnpkg.com/git-up/-/git-up-4.0.2.tgz#10c3d731051b366dc19d3df454bfca3f77913a7c"
-  integrity sha512-kbuvus1dWQB2sSW4cbfTeGpCMd8ge9jx9RKnhXhuJ7tnvT+NIrTVfYZxjtflZddQYcmdOTlkAcjmx7bor+15AQ==
+  version "4.0.5"
+  resolved "https://registry.yarnpkg.com/git-up/-/git-up-4.0.5.tgz#e7bb70981a37ea2fb8fe049669800a1f9a01d759"
+  integrity sha512-YUvVDg/vX3d0syBsk/CKUTib0srcQME0JyHkL5BaYdwLsiCslPWmDSi8PUMo9pXYjrryMcmsCoCgsTpSCJEQaA==
   dependencies:
     is-ssh "^1.3.0"
-    parse-url "^5.0.0"
+    parse-url "^6.0.0"
 
-git-url-parse@^11.4.0:
-  version "11.4.3"
-  resolved "https://registry.yarnpkg.com/git-url-parse/-/git-url-parse-11.4.3.tgz#1610284edf1f14964180f5b3399ec68b692cfd87"
-  integrity sha512-LZTTk0nqJnKN48YRtOpR8H5SEfp1oM2tls90NuZmBxN95PnCvmuXGzqQ4QmVirBgKx2KPYfPGteX3/raWjKenQ==
+git-url-parse@^11.4.4:
+  version "11.6.0"
+  resolved "https://registry.yarnpkg.com/git-url-parse/-/git-url-parse-11.6.0.tgz#c634b8de7faa66498a2b88932df31702c67df605"
+  integrity sha512-WWUxvJs5HsyHL6L08wOusa/IXYtMuCAhrMmnTjQPpBU0TTHyDhnOATNH3xNQz7YOQUsqIIPTGr4xiVti1Hsk5g==
   dependencies:
     git-up "^4.0.0"
 
@@ -5973,22 +5204,17 @@ glob-parent@^3.1.0:
     is-glob "^3.1.0"
     path-dirname "^1.0.0"
 
-glob-parent@^5.0.0, glob-parent@^5.1.0, glob-parent@~5.1.0:
-  version "5.1.1"
-  resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229"
-  integrity sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==
+glob-parent@^5.1.2, glob-parent@~5.1.2:
+  version "5.1.2"
+  resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
+  integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
   dependencies:
     is-glob "^4.0.1"
 
-glob-to-regexp@^0.3.0:
-  version "0.3.0"
-  resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab"
-  integrity sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs=
-
-glob@^7.0.0, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6:
-  version "7.1.6"
-  resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6"
-  integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==
+glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@^7.1.7:
+  version "7.1.7"
+  resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90"
+  integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==
   dependencies:
     fs.realpath "^1.0.0"
     inflight "^1.0.4"
@@ -6002,22 +5228,22 @@ globals@^11.1.0:
   resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e"
   integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==
 
-globals@^12.1.0:
-  version "12.4.0"
-  resolved "https://registry.yarnpkg.com/globals/-/globals-12.4.0.tgz#a18813576a41b00a24a97e7f815918c2e19925f8"
-  integrity sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==
+globals@^13.6.0, globals@^13.9.0:
+  version "13.11.0"
+  resolved "https://registry.yarnpkg.com/globals/-/globals-13.11.0.tgz#40ef678da117fe7bd2e28f1fab24951bd0255be7"
+  integrity sha512-08/xrJ7wQjK9kkkRoI3OFUBbLx4f+6x3SGwcPvQ0QH6goFDrOU2oyAWrmh3dJezu65buo+HBMzAMQy6rovVC3g==
   dependencies:
-    type-fest "^0.8.1"
+    type-fest "^0.20.2"
 
 globals@^9.18.0:
   version "9.18.0"
   resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a"
   integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==
 
-globby@^11.0.1:
-  version "11.0.1"
-  resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.1.tgz#9a2bf107a068f3ffeabc49ad702c79ede8cfd357"
-  integrity sha512-iH9RmgwCmUJHi2z5o2l3eTtGBtXek1OYlHrbcxOYugyHLmAsZrPj43OtHThd62Buh/Vv6VyCBD2bdyWcGNQqoQ==
+globby@^11.0.3, globby@^11.0.4:
+  version "11.0.4"
+  resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.4.tgz#2cbaff77c2f2a62e71e9b2813a67b97a3a3001a5"
+  integrity sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==
   dependencies:
     array-union "^2.1.0"
     dir-glob "^3.0.1"
@@ -6026,50 +5252,28 @@ globby@^11.0.1:
     merge2 "^1.3.0"
     slash "^3.0.0"
 
-graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.2, graceful-fs@^4.2.4:
-  version "4.2.4"
-  resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb"
-  integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==
-
-grapheme-breaker@^0.3.2:
-  version "0.3.2"
-  resolved "https://registry.yarnpkg.com/grapheme-breaker/-/grapheme-breaker-0.3.2.tgz#5b9e6b78c3832452d2ba2bb1cb830f96276410ac"
-  integrity sha1-W55reMODJFLSuiuxy4MPlidkEKw=
-  dependencies:
-    brfs "^1.2.0"
-    unicode-trie "^0.3.1"
+graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4:
+  version "4.2.8"
+  resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.8.tgz#e412b8d33f5e006593cbd3cee6df9f2cebbe802a"
+  integrity sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==
 
 growly@^1.3.0:
   version "1.3.0"
   resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081"
   integrity sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=
 
-gzip-size@^5.0.0:
-  version "5.1.1"
-  resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-5.1.1.tgz#cb9bee692f87c0612b232840a873904e4c135274"
-  integrity sha512-FNHi6mmoHvs1mxZAds4PpdCS6QG8B4C1krxJsMutgxl5t3+GlRTzzI3NEkifXx2pVsOvJdOGSmIgDhQ55FwdPA==
+gzip-size@^6.0.0:
+  version "6.0.0"
+  resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-6.0.0.tgz#065367fd50c239c0671cbcbad5be3e2eeb10e462"
+  integrity sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==
   dependencies:
-    duplexer "^0.1.1"
-    pify "^4.0.1"
+    duplexer "^0.1.2"
 
 hable@^3.0.0:
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/hable/-/hable-3.0.0.tgz#6de089b2df946635cf8134b9e4859f1b62de255f"
   integrity sha512-7+G0/2/COR8pwteYFqHIVYfQpuEiO2HXwJrhCBJVgrNrl9O5eaUoJVDGXUJX+0RpGncNVTuestexjk1afj01wQ==
 
-har-schema@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92"
-  integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=
-
-har-validator@~5.1.3:
-  version "5.1.5"
-  resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd"
-  integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==
-  dependencies:
-    ajv "^6.12.3"
-    har-schema "^2.0.0"
-
 hard-source-webpack-plugin@^0.13.1:
   version "0.13.1"
   resolved "https://registry.yarnpkg.com/hard-source-webpack-plugin/-/hard-source-webpack-plugin-0.13.1.tgz#a99071e25b232f1438a5bc3c99f10a3869e4428e"
@@ -6096,10 +5300,10 @@ has-ansi@^2.0.0:
   dependencies:
     ansi-regex "^2.0.0"
 
-has-flag@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa"
-  integrity sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=
+has-bigints@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.1.tgz#64fe6acb020673e3b78db035a5af69aa9d07b113"
+  integrity sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==
 
 has-flag@^3.0.0:
   version "3.0.0"
@@ -6111,10 +5315,17 @@ has-flag@^4.0.0:
   resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
   integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
 
-has-symbols@^1.0.1:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8"
-  integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==
+has-symbols@^1.0.1, has-symbols@^1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.2.tgz#165d3070c00309752a1236a479331e3ac56f1423"
+  integrity sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==
+
+has-tostringtag@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25"
+  integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==
+  dependencies:
+    has-symbols "^1.0.2"
 
 has-value@^0.3.1:
   version "0.3.1"
@@ -6147,7 +5358,7 @@ has-values@^1.0.0:
     is-number "^3.0.0"
     kind-of "^4.0.0"
 
-has@^1.0.0, has@^1.0.1, has@^1.0.3:
+has@^1.0.0, has@^1.0.3:
   version "1.0.3"
   resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
   integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==
@@ -6199,7 +5410,17 @@ hex-color-regex@^1.1.0:
   resolved "https://registry.yarnpkg.com/hex-color-regex/-/hex-color-regex-1.1.0.tgz#4c06fccb4602fe2602b3c93df82d7e7dbf1a8a8e"
   integrity sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ==
 
-hmac-drbg@^1.0.0:
+highcharts-vue@^1.4.0:
+  version "1.4.0"
+  resolved "https://registry.yarnpkg.com/highcharts-vue/-/highcharts-vue-1.4.0.tgz#4bdaaddc6b9a3eea0df70d29a22ae713d28e4a0c"
+  integrity sha512-fTPqJmU/wR/nUEtofbC/iJqcgULGcP3C0Hd4YYCKH2FiiteNs7UidjSM4eYj5Y4ldpOVhwPtNj/m6XwC3ajp6g==
+
+highcharts@^9.2.2:
+  version "9.2.2"
+  resolved "https://registry.yarnpkg.com/highcharts/-/highcharts-9.2.2.tgz#4ace4aa7c4d2b4051115d9be70bfd2038559d656"
+  integrity sha512-OMEdFCaG626ES1JEcKAvJTpxAOMuchy0XuAplmnOs0Yu7NMd2RMfTLFQ2fCJOxo3ubSdm/RVQwKAWC+5HYThnw==
+
+hmac-drbg@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1"
   integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=
@@ -6208,15 +5429,10 @@ hmac-drbg@^1.0.0:
     minimalistic-assert "^1.0.0"
     minimalistic-crypto-utils "^1.0.1"
 
-hoopy@^0.1.4:
-  version "0.1.4"
-  resolved "https://registry.yarnpkg.com/hoopy/-/hoopy-0.1.4.tgz#609207d661100033a9a9402ad3dea677381c1b1d"
-  integrity sha512-HRcs+2mr52W0K+x8RzcLzuPPmVIKMSv97RGHy0Ea9y/mpcaK+xTrjICA04KAHi4GRzxliNqNJEFYWHghy3rSfQ==
-
 hosted-git-info@^2.1.4:
-  version "2.8.8"
-  resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488"
-  integrity sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==
+  version "2.8.9"
+  resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9"
+  integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==
 
 hsl-regex@^1.0.0:
   version "1.0.0"
@@ -6228,18 +5444,6 @@ hsla-regex@^1.0.0:
   resolved "https://registry.yarnpkg.com/hsla-regex/-/hsla-regex-1.0.0.tgz#c1ce7a3168c8c6614033a4b5f7877f3b225f9c38"
   integrity sha1-wc56MWjIxmFAM6S194d/OyJfnDg=
 
-html-comment-regex@^1.1.0:
-  version "1.1.2"
-  resolved "https://registry.yarnpkg.com/html-comment-regex/-/html-comment-regex-1.1.2.tgz#97d4688aeb5c81886a364faa0cad1dda14d433a7"
-  integrity sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ==
-
-html-encoding-sniffer@^1.0.2:
-  version "1.0.2"
-  resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz#e70d84b94da53aa375e11fe3a351be6642ca46f8"
-  integrity sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw==
-  dependencies:
-    whatwg-encoding "^1.0.1"
-
 html-encoding-sniffer@^2.0.1:
   version "2.0.1"
   resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz#42a6dc4fd33f00281176e8b23759ca4e4fa185f3"
@@ -6283,20 +5487,15 @@ html-minifier@^4.0.0:
     relateurl "^0.2.7"
     uglify-js "^3.5.1"
 
-html-tags@^1.0.0:
-  version "1.2.0"
-  resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-1.2.0.tgz#c78de65b5663aa597989dd2b7ab49200d7e4db98"
-  integrity sha1-x43mW1Zjqll5id0rerSSANfk25g=
-
 html-tags@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-2.0.0.tgz#10b30a386085f43cede353cc8fa7cb0deeea668b"
   integrity sha1-ELMKOGCF9Dzt41PMj6fLDe7qZos=
 
-html-webpack-plugin@^4.5.0:
-  version "4.5.1"
-  resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-4.5.1.tgz#40aaf1b5cb78f2f23a83333999625c20929cda65"
-  integrity sha512-yzK7RQZwv9xB+pcdHNTjcqbaaDZ+5L0zJHXfi89iWIZmb/FtzxhLk0635rmJihcQbs3ZUF27Xp4oWGx6EK56zg==
+html-webpack-plugin@^4.5.1:
+  version "4.5.2"
+  resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-4.5.2.tgz#76fc83fa1a0f12dd5f7da0404a54e2699666bc12"
+  integrity sha512-q5oYdzjKUIPQVjOosjgvCHQOv9Ett9CYYHlgvJeXG0qQvdSojnBq4vAdQBwn1+yGveAwHCoe/rMR86ozX3+c2A==
   dependencies:
     "@types/html-minifier-terser" "^5.0.0"
     "@types/tapable" "^1.0.5"
@@ -6308,33 +5507,15 @@ html-webpack-plugin@^4.5.0:
     tapable "^1.1.3"
     util.promisify "1.0.0"
 
-htmlnano@^0.2.2:
-  version "0.2.8"
-  resolved "https://registry.yarnpkg.com/htmlnano/-/htmlnano-0.2.8.tgz#d9c22daa18c8ea7675a0bf07cc904793ccaeb56f"
-  integrity sha512-q5gbo4SIDAE5sfJ5V0UD6uu+n1dcO/Mpr0B6SlDlJBoV7xKPne4uG4UwrT8vUWjdjIPJl95TY8EDuEbBW2TG0A==
-  dependencies:
-    cssnano "^4.1.10"
-    posthtml "^0.13.4"
-    posthtml-render "^1.3.0"
-    purgecss "^2.3.0"
-    relateurl "^0.2.7"
-    srcset "^3.0.0"
-    svgo "^1.3.2"
-    terser "^4.8.0"
-    timsort "^0.3.0"
-    uncss "^0.17.3"
-
-htmlparser2@^3.10.1, htmlparser2@^3.9.2:
-  version "3.10.1"
-  resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.10.1.tgz#bd679dc3f59897b6a34bb10749c855bb53a9392f"
-  integrity sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==
+htmlparser2@^6.1.0:
+  version "6.1.0"
+  resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-6.1.0.tgz#c4d762b6c3371a05dbe65e94ae43a9f845fb8fb7"
+  integrity sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==
   dependencies:
-    domelementtype "^1.3.1"
-    domhandler "^2.3.0"
-    domutils "^1.5.1"
-    entities "^1.1.1"
-    inherits "^2.0.1"
-    readable-stream "^3.1.1"
+    domelementtype "^2.0.1"
+    domhandler "^4.0.0"
+    domutils "^2.5.2"
+    entities "^2.0.0"
 
 http-errors@1.7.2:
   version "1.7.2"
@@ -6358,6 +5539,15 @@ http-errors@~1.7.2:
     statuses ">= 1.5.0 < 2"
     toidentifier "1.0.0"
 
+http-proxy-agent@^4.0.1:
+  version "4.0.1"
+  resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz#8a8c8ef7f5932ccf953c296ca8291b95aa74aa3a"
+  integrity sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==
+  dependencies:
+    "@tootallnate/once" "1"
+    agent-base "6"
+    debug "4"
+
 http-proxy-middleware@^0.19.1:
   version "0.19.2"
   resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-0.19.2.tgz#ee73dcc8348165afefe8de2ff717751d181608ee"
@@ -6369,14 +5559,14 @@ http-proxy-middleware@^0.19.1:
     micromatch "^3.1.10"
 
 http-proxy-middleware@^1.0.6:
-  version "1.0.6"
-  resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-1.0.6.tgz#0618557722f450375d3796d701a8ac5407b3b94e"
-  integrity sha512-NyL6ZB6cVni7pl+/IT2W0ni5ME00xR0sN27AQZZrpKn1b+qRh+mLbBxIq9Cq1oGfmTc7BUq4HB77mxwCaxAYNg==
+  version "1.3.1"
+  resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-1.3.1.tgz#43700d6d9eecb7419bf086a128d0f7205d9eb665"
+  integrity sha512-13eVVDYS4z79w7f1+NPllJtOQFx/FdUW4btIvVRMaRlUY9VGstAbo5MOhLEuUgZFRHn3x50ufn25zkj/boZnEg==
   dependencies:
-    "@types/http-proxy" "^1.17.4"
+    "@types/http-proxy" "^1.17.5"
     http-proxy "^1.18.1"
     is-glob "^4.0.1"
-    lodash "^4.17.20"
+    is-plain-obj "^3.0.0"
     micromatch "^4.0.2"
 
 http-proxy@^1.18.1:
@@ -6388,37 +5578,36 @@ http-proxy@^1.18.1:
     follow-redirects "^1.0.0"
     requires-port "^1.0.0"
 
-http-signature@~1.2.0:
-  version "1.2.0"
-  resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1"
-  integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=
-  dependencies:
-    assert-plus "^1.0.0"
-    jsprim "^1.2.2"
-    sshpk "^1.7.0"
-
 https-browserify@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73"
   integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=
 
+https-proxy-agent@^5.0.0:
+  version "5.0.0"
+  resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2"
+  integrity sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==
+  dependencies:
+    agent-base "6"
+    debug "4"
+
 human-signals@^1.1.1:
   version "1.1.1"
   resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3"
   integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==
 
-iconv-lite@0.4, iconv-lite@0.4.24, iconv-lite@^0.4.24:
+human-signals@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0"
+  integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==
+
+iconv-lite@0.4.24, iconv-lite@^0.4.24:
   version "0.4.24"
   resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
   integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
   dependencies:
     safer-buffer ">= 2.1.2 < 3"
 
-icss-replace-symbols@1.1.0, icss-replace-symbols@^1.1.0:
-  version "1.1.0"
-  resolved "https://registry.yarnpkg.com/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz#06ea6f83679a7749e386cfe1fe812ae5db223ded"
-  integrity sha1-Bupvg2ead0njhs/h/oEq5dsiPe0=
-
 icss-utils@^4.0.0, icss-utils@^4.1.1:
   version "4.1.1"
   resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-4.1.1.tgz#21170b53789ee27447c2f47dd683081403f9a467"
@@ -6556,6 +5745,20 @@ inquirer@^7.3.3:
     strip-ansi "^6.0.0"
     through "^2.3.6"
 
+internal-slot@^1.0.3:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c"
+  integrity sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==
+  dependencies:
+    get-intrinsic "^1.1.0"
+    has "^1.0.3"
+    side-channel "^1.0.4"
+
+"internmap@1 - 2":
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/internmap/-/internmap-2.0.1.tgz#33d0fa016185397549fb1a14ea3dbe5a2949d1cd"
+  integrity sha512-Ujwccrj9FkGqjbY3iVoxD1VV+KdZZeENx0rphrtzmRXbFvkFO88L80BL/zeSIguX/7T+y8k04xqtgWgS5vxwxw==
+
 invariant@^2.2.2:
   version "2.2.4"
   resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6"
@@ -6563,31 +5766,16 @@ invariant@^2.2.2:
   dependencies:
     loose-envify "^1.0.0"
 
-ip-regex@^2.1.0:
-  version "2.1.0"
-  resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9"
-  integrity sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=
-
 ip@^1.1.5:
   version "1.1.5"
   resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a"
   integrity sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=
 
-ipaddr.js@1.9.1:
-  version "1.9.1"
-  resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3"
-  integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==
-
 is-absolute-url@^2.0.0:
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-2.1.0.tgz#50530dfb84fcc9aa7dbe7852e83a37b93b9f2aa6"
   integrity sha1-UFMN+4T8yap9vnhS6Do3uTufKqY=
 
-is-absolute-url@^3.0.1:
-  version "3.0.3"
-  resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-3.0.3.tgz#96c6a22b6a23929b11ea0afb1836c36ad4a5d698"
-  integrity sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q==
-
 is-accessor-descriptor@^0.1.6:
   version "0.1.6"
   resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6"
@@ -6612,6 +5800,13 @@ is-arrayish@^0.3.1:
   resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03"
   integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==
 
+is-bigint@^1.0.1:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3"
+  integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==
+  dependencies:
+    has-bigints "^1.0.1"
+
 is-binary-path@^1.0.0:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898"
@@ -6626,15 +5821,23 @@ is-binary-path@~2.1.0:
   dependencies:
     binary-extensions "^2.0.0"
 
+is-boolean-object@^1.1.0:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719"
+  integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==
+  dependencies:
+    call-bind "^1.0.2"
+    has-tostringtag "^1.0.0"
+
 is-buffer@^1.1.5:
   version "1.1.6"
   resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
   integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==
 
-is-callable@^1.1.4, is-callable@^1.2.2:
-  version "1.2.2"
-  resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.2.tgz#c7c6715cd22d4ddb48d3e19970223aceabb080d9"
-  integrity sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==
+is-callable@^1.1.4, is-callable@^1.2.3:
+  version "1.2.4"
+  resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.4.tgz#47301d58dd0259407865547853df6d61fe471945"
+  integrity sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==
 
 is-ci@^2.0.0:
   version "2.0.0"
@@ -6655,10 +5858,10 @@ is-color-stop@^1.0.0:
     rgb-regex "^1.0.1"
     rgba-regex "^1.0.0"
 
-is-core-module@^2.1.0:
-  version "2.2.0"
-  resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.2.0.tgz#97037ef3d52224d85163f5597b2b63d9afed981a"
-  integrity sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==
+is-core-module@^2.2.0:
+  version "2.6.0"
+  resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.6.0.tgz#d7553b2526fe59b92ba3e40c8df757ec8a709e19"
+  integrity sha512-wShG8vs60jKfPWpF2KZRaAtvt3a20OAn7+IJ6hLPECpSABLcKtFKTTI4ZtH5QcBruBHlq+WsdHWyz0BCZW7svQ==
   dependencies:
     has "^1.0.3"
 
@@ -6677,9 +5880,11 @@ is-data-descriptor@^1.0.0:
     kind-of "^6.0.0"
 
 is-date-object@^1.0.1:
-  version "1.0.2"
-  resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.2.tgz#bda736f2cd8fd06d32844e7743bfa7494c3bfd7e"
-  integrity sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==
+  version "1.0.5"
+  resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f"
+  integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==
+  dependencies:
+    has-tostringtag "^1.0.0"
 
 is-descriptor@^0.1.0:
   version "0.1.6"
@@ -6704,10 +5909,10 @@ is-directory@^0.3.1:
   resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1"
   integrity sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=
 
-is-docker@^2.0.0, is-docker@^2.1.1:
-  version "2.1.1"
-  resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.1.1.tgz#4125a88e44e450d384e09047ede71adc2d144156"
-  integrity sha512-ZOoqiXfEwtGknTiuDEy8pN2CfE3TxMHprvNer1mXiqwkOT77Rw3YVrUQ52EqAOU3QAWDQ+bQdx7HJzrv7LS2Hw==
+is-docker@^2.0.0, is-docker@^2.2.1:
+  version "2.2.1"
+  resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa"
+  integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==
 
 is-extendable@^0.1.0, is-extendable@^0.1.1:
   version "0.1.1"
@@ -6755,18 +5960,18 @@ is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1:
   dependencies:
     is-extglob "^2.1.1"
 
-is-html@^1.1.0:
-  version "1.1.0"
-  resolved "https://registry.yarnpkg.com/is-html/-/is-html-1.1.0.tgz#e04f1c18d39485111396f9a0273eab51af218464"
-  integrity sha1-4E8cGNOUhRETlvmgJz6rUa8hhGQ=
-  dependencies:
-    html-tags "^1.0.0"
-
-is-negative-zero@^2.0.0:
+is-negative-zero@^2.0.1:
   version "2.0.1"
   resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.1.tgz#3de746c18dda2319241a53675908d8f766f11c24"
   integrity sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==
 
+is-number-object@^1.0.4:
+  version "1.0.6"
+  resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.6.tgz#6a7aaf838c7f0686a50b4553f7e54a96494e89f0"
+  integrity sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==
+  dependencies:
+    has-tostringtag "^1.0.0"
+
 is-number@^3.0.0:
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195"
@@ -6789,6 +5994,11 @@ is-plain-obj@^1.0.0:
   resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e"
   integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4=
 
+is-plain-obj@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-3.0.0.tgz#af6f2ea14ac5a646183a5bbdb5baabbc156ad9d7"
+  integrity sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==
+
 is-plain-object@^2.0.3, is-plain-object@^2.0.4:
   version "2.0.4"
   resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677"
@@ -6796,17 +6006,18 @@ is-plain-object@^2.0.3, is-plain-object@^2.0.4:
   dependencies:
     isobject "^3.0.1"
 
-is-potential-custom-element-name@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.0.tgz#0c52e54bcca391bb2c494b21e8626d7336c6e397"
-  integrity sha1-DFLlS8yjkbssSUsh6GJtczbG45c=
+is-potential-custom-element-name@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5"
+  integrity sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==
 
-is-regex@^1.1.1:
-  version "1.1.1"
-  resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.1.tgz#c6f98aacc546f6cec5468a07b7b153ab564a57b9"
-  integrity sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==
+is-regex@^1.1.3:
+  version "1.1.4"
+  resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958"
+  integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==
   dependencies:
-    has-symbols "^1.0.1"
+    call-bind "^1.0.2"
+    has-tostringtag "^1.0.0"
 
 is-resolvable@^1.0.0:
   version "1.1.0"
@@ -6819,9 +6030,9 @@ is-retry-allowed@^1.1.0:
   integrity sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg==
 
 is-ssh@^1.3.0:
-  version "1.3.2"
-  resolved "https://registry.yarnpkg.com/is-ssh/-/is-ssh-1.3.2.tgz#a4b82ab63d73976fd8263cceee27f99a88bdae2b"
-  integrity sha512-elEw0/0c2UscLrNG+OAorbP539E3rhliKPg+hDMWN9VwrDXfYK+4PBEykDPfxlYYtQvl84TascnQyobfQLHEhQ==
+  version "1.3.3"
+  resolved "https://registry.yarnpkg.com/is-ssh/-/is-ssh-1.3.3.tgz#7f133285ccd7f2c2c7fc897b771b53d95a2b2c7e"
+  integrity sha512-NKzJmQzJfEEma3w5cJNcUMxoXfDjz0Zj0eyCalHn2E6VOwlzjZo0yuO2fcBSf8zhFuVCL/82/r5gRcoi6aEPVQ==
   dependencies:
     protocols "^1.1.0"
 
@@ -6831,39 +6042,29 @@ is-stream@^1.1.0:
   integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ=
 
 is-stream@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3"
-  integrity sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==
-
-is-string@^1.0.5:
-  version "1.0.5"
-  resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.5.tgz#40493ed198ef3ff477b8c7f92f644ec82a5cd3a6"
-  integrity sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077"
+  integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==
 
-is-svg@^3.0.0:
-  version "3.0.0"
-  resolved "https://registry.yarnpkg.com/is-svg/-/is-svg-3.0.0.tgz#9321dbd29c212e5ca99c4fa9794c714bcafa2f75"
-  integrity sha512-gi4iHK53LR2ujhLVVj+37Ykh9GLqYHX6JOVXbLAucaG/Cqw9xwdFOjDM2qeifLs1sF1npXXFvDu0r5HNgCMrzQ==
+is-string@^1.0.5, is-string@^1.0.6:
+  version "1.0.7"
+  resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd"
+  integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==
   dependencies:
-    html-comment-regex "^1.1.0"
+    has-tostringtag "^1.0.0"
 
-is-symbol@^1.0.2:
-  version "1.0.3"
-  resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.3.tgz#38e1014b9e6329be0de9d24a414fd7441ec61937"
-  integrity sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==
+is-symbol@^1.0.2, is-symbol@^1.0.3:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c"
+  integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==
   dependencies:
-    has-symbols "^1.0.1"
+    has-symbols "^1.0.2"
 
-is-typedarray@^1.0.0, is-typedarray@~1.0.0:
+is-typedarray@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
   integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=
 
-is-url@^1.2.2:
-  version "1.2.4"
-  resolved "https://registry.yarnpkg.com/is-url/-/is-url-1.2.4.tgz#04a4df46d28c4cff3d73d01ff06abeb318a1aa52"
-  integrity sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==
-
 is-whitespace@^0.3.0:
   version "0.3.0"
   resolved "https://registry.yarnpkg.com/is-whitespace/-/is-whitespace-0.3.0.tgz#1639ecb1be036aec69a54cbb401cfbed7114ab7f"
@@ -6891,11 +6092,6 @@ isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0:
   resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
   integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=
 
-isarray@^2.0.1:
-  version "2.0.5"
-  resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723"
-  integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==
-
 isexe@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
@@ -6913,11 +6109,6 @@ isobject@^3.0.0, isobject@^3.0.1:
   resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df"
   integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8=
 
-isstream@~0.1.2:
-  version "0.1.2"
-  resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
-  integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=
-
 istanbul-lib-coverage@^3.0.0:
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz#f5944a37c70b550b02a78a5c3b2055b280cec8ec"
@@ -7314,15 +6505,7 @@ jest-watcher@^26.6.2:
     jest-util "^26.6.2"
     string-length "^4.0.1"
 
-jest-worker@^25.4.0:
-  version "25.5.0"
-  resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-25.5.0.tgz#2611d071b79cea0f43ee57a3d118593ac1547db1"
-  integrity sha512-/dsSmUkIy5EBGfv/IjjqmFxrNAUpBERfGs1oHROyD7yxjG/w+t0GOJDX8O1k32ySmd7+a5IhnJU2qQFcJ4n1vw==
-  dependencies:
-    merge-stream "^2.0.0"
-    supports-color "^7.0.0"
-
-jest-worker@^26.6.2:
+jest-worker@^26.5.0, jest-worker@^26.6.2:
   version "26.6.2"
   resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.6.2.tgz#7f72cbc4d643c365e27b9fd775f9d0eaa9c7a8ed"
   integrity sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==
@@ -7340,20 +6523,19 @@ jest@^26.1.0:
     import-local "^3.0.2"
     jest-cli "^26.6.3"
 
-jiti@^0.1.16, jiti@^0.1.17:
-  version "0.1.19"
-  resolved "https://registry.yarnpkg.com/jiti/-/jiti-0.1.19.tgz#455f93e0c92f26c9cea0af48def3eb4f567bbbe3"
-  integrity sha512-ElDW0w/0ATX6IQwReNYMVrYkHu8PqIOO5t3lluceP/saq4SYz4D3uSMpU8pbn/RX3H6VYVPc0PnKn2WfQ5kiwg==
+jiti@^1.9.2:
+  version "1.11.0"
+  resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.11.0.tgz#64120a30d97b9bf37b8b032cf4564dfadc28984c"
+  integrity sha512-/2c7e61hxxTIN34UeHBB0LCJ5Tq64kgJDV7GR+++e8XRxCKRIKmB8tH6ww1W+Z6Kgd6By+C3RSCu1lXjbPT68A==
 
 js-beautify@^1.6.12, js-beautify@^1.6.14:
-  version "1.13.0"
-  resolved "https://registry.yarnpkg.com/js-beautify/-/js-beautify-1.13.0.tgz#a056d5d3acfd4918549aae3ab039f9f3c51eebb2"
-  integrity sha512-/Tbp1OVzZjbwzwJQFIlYLm9eWQ+3aYbBXLSaqb1mEJzhcQAfrqMMQYtjb6io+U6KpD0ID4F+Id3/xcjH3l/sqA==
+  version "1.14.0"
+  resolved "https://registry.yarnpkg.com/js-beautify/-/js-beautify-1.14.0.tgz#2ce790c555d53ce1e3d7363227acf5dc69024c2d"
+  integrity sha512-yuck9KirNSCAwyNJbqW+BxJqJ0NLJ4PwBUzQQACl5O3qHMBXVkXb/rD0ilh/Lat/tn88zSZ+CAHOlk0DsY7GuQ==
   dependencies:
     config-chain "^1.1.12"
     editorconfig "^0.15.3"
     glob "^7.1.3"
-    mkdirp "^1.0.4"
     nopt "^5.0.0"
 
 "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0:
@@ -7366,7 +6548,7 @@ js-tokens@^3.0.2:
   resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b"
   integrity sha1-mGbfOVECEw449/mWvOtlRDIJwls=
 
-js-yaml@^3.10.0, js-yaml@^3.13.1:
+js-yaml@^3.13.1:
   version "3.14.1"
   resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537"
   integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==
@@ -7374,73 +6556,37 @@ js-yaml@^3.10.0, js-yaml@^3.13.1:
     argparse "^1.0.7"
     esprima "^4.0.0"
 
-jsbn@~0.1.0:
-  version "0.1.1"
-  resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
-  integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM=
-
-jsdom@^14.1.0:
-  version "14.1.0"
-  resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-14.1.0.tgz#916463b6094956b0a6c1782c94e380cd30e1981b"
-  integrity sha512-O901mfJSuTdwU2w3Sn+74T+RnDVP+FuV5fH8tcPWyqrseRAb0s5xOtPgCFiPOtLcyK7CLIJwPyD83ZqQWvA5ng==
-  dependencies:
-    abab "^2.0.0"
-    acorn "^6.0.4"
-    acorn-globals "^4.3.0"
-    array-equal "^1.0.0"
-    cssom "^0.3.4"
-    cssstyle "^1.1.1"
-    data-urls "^1.1.0"
-    domexception "^1.0.1"
-    escodegen "^1.11.0"
-    html-encoding-sniffer "^1.0.2"
-    nwsapi "^2.1.3"
-    parse5 "5.1.0"
-    pn "^1.1.0"
-    request "^2.88.0"
-    request-promise-native "^1.0.5"
-    saxes "^3.1.9"
-    symbol-tree "^3.2.2"
-    tough-cookie "^2.5.0"
-    w3c-hr-time "^1.0.1"
-    w3c-xmlserializer "^1.1.2"
-    webidl-conversions "^4.0.2"
-    whatwg-encoding "^1.0.5"
-    whatwg-mimetype "^2.3.0"
-    whatwg-url "^7.0.0"
-    ws "^6.1.2"
-    xml-name-validator "^3.0.0"
-
 jsdom@^16.4.0:
-  version "16.4.0"
-  resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-16.4.0.tgz#36005bde2d136f73eee1a830c6d45e55408edddb"
-  integrity sha512-lYMm3wYdgPhrl7pDcRmvzPhhrGVBeVhPIqeHjzeiHN3DFmD1RBpbExbi8vU7BJdH8VAZYovR8DMt0PNNDM7k8w==
+  version "16.7.0"
+  resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-16.7.0.tgz#918ae71965424b197c819f8183a754e18977b710"
+  integrity sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==
   dependencies:
-    abab "^2.0.3"
-    acorn "^7.1.1"
+    abab "^2.0.5"
+    acorn "^8.2.4"
     acorn-globals "^6.0.0"
     cssom "^0.4.4"
-    cssstyle "^2.2.0"
+    cssstyle "^2.3.0"
     data-urls "^2.0.0"
-    decimal.js "^10.2.0"
+    decimal.js "^10.2.1"
     domexception "^2.0.1"
-    escodegen "^1.14.1"
+    escodegen "^2.0.0"
+    form-data "^3.0.0"
     html-encoding-sniffer "^2.0.1"
-    is-potential-custom-element-name "^1.0.0"
+    http-proxy-agent "^4.0.1"
+    https-proxy-agent "^5.0.0"
+    is-potential-custom-element-name "^1.0.1"
     nwsapi "^2.2.0"
-    parse5 "5.1.1"
-    request "^2.88.2"
-    request-promise-native "^1.0.8"
-    saxes "^5.0.0"
+    parse5 "6.0.1"
+    saxes "^5.0.1"
     symbol-tree "^3.2.4"
-    tough-cookie "^3.0.1"
+    tough-cookie "^4.0.0"
     w3c-hr-time "^1.0.2"
     w3c-xmlserializer "^2.0.0"
     webidl-conversions "^6.1.0"
     whatwg-encoding "^1.0.5"
     whatwg-mimetype "^2.3.0"
-    whatwg-url "^8.0.0"
-    ws "^7.2.3"
+    whatwg-url "^8.5.0"
+    ws "^7.4.6"
     xml-name-validator "^3.0.0"
 
 jsesc@^2.5.1:
@@ -7473,21 +6619,11 @@ json-schema-traverse@^1.0.0:
   resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2"
   integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==
 
-json-schema@0.2.3:
-  version "0.2.3"
-  resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13"
-  integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=
-
 json-stable-stringify-without-jsonify@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651"
   integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=
 
-json-stringify-safe@~5.0.1:
-  version "5.0.1"
-  resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
-  integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=
-
 json5@^0.5.1:
   version "0.5.1"
   resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821"
@@ -7501,9 +6637,9 @@ json5@^1.0.1:
     minimist "^1.2.0"
 
 json5@^2.1.2:
-  version "2.1.3"
-  resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.3.tgz#c9b0f7fa9233bfe5807fe66fcf3a5617ed597d43"
-  integrity sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==
+  version "2.2.0"
+  resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.0.tgz#2dfefe720c6ba525d9ebd909950f0515316c89a3"
+  integrity sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==
   dependencies:
     minimist "^1.2.5"
 
@@ -7514,15 +6650,14 @@ jsonfile@^4.0.0:
   optionalDependencies:
     graceful-fs "^4.1.6"
 
-jsprim@^1.2.2:
-  version "1.4.1"
-  resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2"
-  integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=
+jsonfile@^6.0.1:
+  version "6.1.0"
+  resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae"
+  integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==
   dependencies:
-    assert-plus "1.0.0"
-    extsprintf "1.3.0"
-    json-schema "0.2.3"
-    verror "1.10.0"
+    universalify "^2.0.0"
+  optionalDependencies:
+    graceful-fs "^4.1.6"
 
 jwt-decode@^3.1.2:
   version "3.1.2"
@@ -7558,6 +6693,11 @@ kleur@^3.0.3:
   resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e"
   integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==
 
+klona@^2.0.4:
+  version "2.0.4"
+  resolved "https://registry.yarnpkg.com/klona/-/klona-2.0.4.tgz#7bb1e3affb0cb8624547ef7e8f6708ea2e39dfc0"
+  integrity sha512-ZRbnvdg/NxqzC7L9Uyqzf4psi1OM4Cuc+sJAkQPjO6XkQIJTNbfK2Rsmbw8fx1p2mkZdp2FZYo2+LwXYY/uwIA==
+
 last-call-webpack-plugin@^3.0.0:
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/last-call-webpack-plugin/-/last-call-webpack-plugin-3.0.0.tgz#9742df0e10e3cf46e5c0381c2de90d3a7a2d7555"
@@ -7617,12 +6757,17 @@ load-json-file@^2.0.0:
     pify "^2.0.0"
     strip-bom "^3.0.0"
 
-loader-runner@^2.3.1, loader-runner@^2.4.0:
+loader-runner@^2.4.0:
   version "2.4.0"
   resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357"
   integrity sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==
 
-loader-utils@^1.0.2, loader-utils@^1.1.0, loader-utils@^1.2.0, loader-utils@^1.2.3, loader-utils@^1.4.0:
+loader-runner@^4.1.0:
+  version "4.2.0"
+  resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.2.0.tgz#d7022380d66d14c5fb1d496b89864ebcfd478384"
+  integrity sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw==
+
+loader-utils@^1.0.2, loader-utils@^1.1.0, loader-utils@^1.2.3, loader-utils@^1.4.0:
   version "1.4.0"
   resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613"
   integrity sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==
@@ -7668,10 +6813,15 @@ lodash._reinterpolate@^3.0.0:
   resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d"
   integrity sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=
 
-lodash.clone@^4.5.0:
+lodash.clonedeep@^4.5.0:
   version "4.5.0"
-  resolved "https://registry.yarnpkg.com/lodash.clone/-/lodash.clone-4.5.0.tgz#195870450f5a13192478df4bc3d23d2dea1907b6"
-  integrity sha1-GVhwRQ9aExkkeN9Lw9I9LeoZB7Y=
+  resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef"
+  integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=
+
+lodash.debounce@^4.0.8:
+  version "4.0.8"
+  resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
+  integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168=
 
 lodash.get@^4.4.2:
   version "4.4.2"
@@ -7693,6 +6843,11 @@ lodash.memoize@^4.1.2:
   resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe"
   integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=
 
+lodash.merge@^4.6.2:
+  version "4.6.2"
+  resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
+  integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==
+
 lodash.pick@^4.4.0:
   version "4.4.0"
   resolved "https://registry.yarnpkg.com/lodash.pick/-/lodash.pick-4.4.0.tgz#52f05610fff9ded422611441ed1fc123a03001b3"
@@ -7703,11 +6858,6 @@ lodash.pickby@^4.6.0:
   resolved "https://registry.yarnpkg.com/lodash.pickby/-/lodash.pickby-4.6.0.tgz#7dea21d8c18d7703a27c704c15d3b84a67e33aff"
   integrity sha1-feoh2MGNdwOifHBMFdO4SmfjOv8=
 
-lodash.sortby@^4.7.0:
-  version "4.7.0"
-  resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438"
-  integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=
-
 lodash.template@^4.5.0:
   version "4.5.0"
   resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-4.5.0.tgz#f976195cf3f347d0d5f52483569fe8031ccce8ab"
@@ -7723,6 +6873,11 @@ lodash.templatesettings@^4.0.0:
   dependencies:
     lodash._reinterpolate "^3.0.0"
 
+lodash.truncate@^4.4.2:
+  version "4.4.2"
+  resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193"
+  integrity sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=
+
 lodash.uniq@^4.5.0:
   version "4.5.0"
   resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
@@ -7733,17 +6888,10 @@ lodash.zip@^4.2.0:
   resolved "https://registry.yarnpkg.com/lodash.zip/-/lodash.zip-4.2.0.tgz#ec6662e4896408ed4ab6c542a3990b72cc080020"
   integrity sha1-7GZi5IlkCO1KtsVCo5kLcswIACA=
 
-lodash@^4.15.0, lodash@^4.17.11, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.4, lodash@^4.17.5:
-  version "4.17.20"
-  resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52"
-  integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==
-
-log-symbols@^2.2.0:
-  version "2.2.0"
-  resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a"
-  integrity sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==
-  dependencies:
-    chalk "^2.0.1"
+lodash@^4.15.0, lodash@^4.17.11, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.7.0:
+  version "4.17.21"
+  resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
+  integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
 
 loose-envify@^1.0.0:
   version "1.4.0"
@@ -7786,13 +6934,6 @@ lru-cache@^6.0.0:
   dependencies:
     yallist "^4.0.0"
 
-magic-string@^0.22.4:
-  version "0.22.5"
-  resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.22.5.tgz#8e9cf5afddf44385c1da5bc2a6a0dbd10b03657e"
-  integrity sha512-oreip9rJZkzvA8Qzk9HFs8fZGF/u7H/gtrE8EN6RjKJ9kh2HlC+yQ2QezifqTZfGyiuAV0dRv5a+y/8gBb1m9w==
-  dependencies:
-    vlq "^0.2.2"
-
 make-dir@^1.0.0:
   version "1.3.0"
   resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c"
@@ -7822,6 +6963,13 @@ makeerror@1.0.x:
   dependencies:
     tmpl "1.0.x"
 
+map-age-cleaner@^0.1.3:
+  version "0.1.3"
+  resolved "https://registry.yarnpkg.com/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz#7d583a7306434c055fe474b0f45078e6e1b4b92a"
+  integrity sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==
+  dependencies:
+    p-defer "^1.0.0"
+
 map-cache@^0.2.2:
   version "0.2.2"
   resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf"
@@ -7858,6 +7006,21 @@ media-typer@0.3.0:
   resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
   integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=
 
+mem@^8.1.1:
+  version "8.1.1"
+  resolved "https://registry.yarnpkg.com/mem/-/mem-8.1.1.tgz#cf118b357c65ab7b7e0817bdf00c8062297c0122"
+  integrity sha512-qFCFUDs7U3b8mBDPyz5EToEKoAkgCzqquIgi9nkkR9bixxOVOre+09lbuH7+9Kn2NFpm56M3GUWVbU2hQgdACA==
+  dependencies:
+    map-age-cleaner "^0.1.3"
+    mimic-fn "^3.1.0"
+
+memfs@^3.2.2:
+  version "3.2.4"
+  resolved "https://registry.yarnpkg.com/memfs/-/memfs-3.2.4.tgz#1108c28d2e9137daf5a5586af856c3e18c1c64b2"
+  integrity sha512-2mDCPhuduRPOxlfgsXF9V+uqC6Jgz8zt/bNe4d4W7d5f6pCzHrWkxLNr17jKGXd4+j2kQNsAG2HARPnt74sqVQ==
+  dependencies:
+    fs-monkey "1.0.3"
+
 memory-fs@^0.4.1:
   version "0.4.1"
   resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552"
@@ -7874,18 +7037,6 @@ memory-fs@^0.5.0:
     errno "^0.1.3"
     readable-stream "^2.0.1"
 
-merge-descriptors@1.0.1:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61"
-  integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=
-
-merge-source-map@1.0.4:
-  version "1.0.4"
-  resolved "https://registry.yarnpkg.com/merge-source-map/-/merge-source-map-1.0.4.tgz#a5de46538dae84d4114cc5ea02b4772a6346701f"
-  integrity sha1-pd5GU42uhNQRTMXqArR3KmNGcB8=
-  dependencies:
-    source-map "^0.5.6"
-
 merge-source-map@^1.1.0:
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/merge-source-map/-/merge-source-map-1.1.0.tgz#2fdde7e6020939f70906a68f2d7ae685e4c8c646"
@@ -7898,17 +7049,12 @@ merge-stream@^2.0.0:
   resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60"
   integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==
 
-merge2@^1.2.3, merge2@^1.3.0:
+merge2@^1.3.0:
   version "1.4.1"
   resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae"
   integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==
 
-methods@~1.1.2:
-  version "1.1.2"
-  resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
-  integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=
-
-micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4:
+micromatch@^3.1.10, micromatch@^3.1.4:
   version "3.1.10"
   resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23"
   integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==
@@ -7927,13 +7073,13 @@ micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4:
     snapdragon "^0.8.1"
     to-regex "^3.0.2"
 
-micromatch@^4.0.2:
-  version "4.0.2"
-  resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.2.tgz#4fcb0999bf9fbc2fcbdd212f6d629b9a56c39259"
-  integrity sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==
+micromatch@^4.0.2, micromatch@^4.0.4:
+  version "4.0.4"
+  resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.4.tgz#896d519dfe9db25fce94ceb7a500919bf881ebf9"
+  integrity sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==
   dependencies:
     braces "^3.0.1"
-    picomatch "^2.0.5"
+    picomatch "^2.2.3"
 
 miller-rabin@^4.0.0:
   version "4.0.1"
@@ -7943,44 +7089,44 @@ miller-rabin@^4.0.0:
     bn.js "^4.0.0"
     brorand "^1.0.1"
 
-mime-db@1.45.0, "mime-db@>= 1.43.0 < 2":
-  version "1.45.0"
-  resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.45.0.tgz#cceeda21ccd7c3a745eba2decd55d4b73e7879ea"
-  integrity sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w==
+mime-db@1.49.0, "mime-db@>= 1.43.0 < 2":
+  version "1.49.0"
+  resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.49.0.tgz#f3dfde60c99e9cf3bc9701d687778f537001cbed"
+  integrity sha512-CIc8j9URtOVApSFCQIF+VBkX1RwXp/oMMOrqdyXSBXq5RWNEsRfyj1kiRnQgmNXmHxPoFIxOroKA3zcU9P+nAA==
 
-mime-types@^2.1.12, mime-types@^2.1.19, mime-types@~2.1.19, mime-types@~2.1.24:
-  version "2.1.28"
-  resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.28.tgz#1160c4757eab2c5363888e005273ecf79d2a0ecd"
-  integrity sha512-0TO2yJ5YHYr7M2zzT7gDU1tbwHxEUWBCLt0lscSNpcdAfFyJOVEpRYNS7EXVcTLNj/25QO8gulHC5JtTzSE2UQ==
+mime-types@^2.1.12, mime-types@^2.1.19, mime-types@^2.1.27, mime-types@^2.1.30, mime-types@~2.1.24:
+  version "2.1.32"
+  resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.32.tgz#1d00e89e7de7fe02008db61001d9e02852670fd5"
+  integrity sha512-hJGaVS4G4c9TSMYh2n6SQAGrC4RnfU+daP8G7cSCmaqNjiOoUY0VHCMS42pxnQmVF1GWwFhbHWn3RIxCqTmZ9A==
   dependencies:
-    mime-db "1.45.0"
+    mime-db "1.49.0"
 
 mime@1.6.0:
   version "1.6.0"
   resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
   integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==
 
-mime@^2.3.1, mime@^2.4.4:
-  version "2.4.7"
-  resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.7.tgz#962aed9be0ed19c91fd7dc2ece5d7f4e89a90d74"
-  integrity sha512-dhNd1uA2u397uQk3Nv5LM4lm93WYDUXFn3Fu291FJerns4jyTudqhIWe4W04YLy7Uk1tm1Ore04NpjRvQp/NPA==
-
-mimic-fn@^1.0.0:
-  version "1.2.0"
-  resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022"
-  integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==
+mime@^2.3.1:
+  version "2.5.2"
+  resolved "https://registry.yarnpkg.com/mime/-/mime-2.5.2.tgz#6e3dc6cc2b9510643830e5f19d5cb753da5eeabe"
+  integrity sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==
 
 mimic-fn@^2.1.0:
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
   integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
 
+mimic-fn@^3.1.0:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-3.1.0.tgz#65755145bbf3e36954b949c16450427451d5ca74"
+  integrity sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ==
+
 minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7"
   integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==
 
-minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1:
+minimalistic-crypto-utils@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a"
   integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=
@@ -7992,7 +7138,7 @@ minimatch@^3.0.4:
   dependencies:
     brace-expansion "^1.1.7"
 
-minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0, minimist@^1.2.5:
+minimist@^1.1.1, minimist@^1.2.0, minimist@^1.2.5:
   version "1.2.5"
   resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
   integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
@@ -8025,6 +7171,14 @@ minipass@^3.0.0, minipass@^3.1.1:
   dependencies:
     yallist "^4.0.0"
 
+minizlib@^2.1.1:
+  version "2.1.2"
+  resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931"
+  integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==
+  dependencies:
+    minipass "^3.0.0"
+    yallist "^4.0.0"
+
 mississippi@^3.0.0:
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-3.0.0.tgz#ea0a3291f97e0b5e8776b363d5f0a12d94c67022"
@@ -8056,7 +7210,7 @@ mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@~0.5.1:
   dependencies:
     minimist "^1.2.5"
 
-mkdirp@^1.0.4:
+mkdirp@^1.0.3, mkdirp@^1.0.4:
   version "1.0.4"
   resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
   integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
@@ -8088,6 +7242,11 @@ ms@2.1.2:
   resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
   integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
 
+ms@^2.1.1:
+  version "2.1.3"
+  resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
+  integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
+
 multimap@^1.1.0:
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/multimap/-/multimap-1.1.0.tgz#5263febc085a1791c33b59bb3afc6a76a2a10ca8"
@@ -8104,14 +7263,14 @@ mute-stream@0.0.8:
   integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==
 
 nan@^2.12.1:
-  version "2.14.2"
-  resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.2.tgz#f5376400695168f4cc694ac9393d0c9585eeea19"
-  integrity sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==
+  version "2.15.0"
+  resolved "https://registry.yarnpkg.com/nan/-/nan-2.15.0.tgz#3f34a473ff18e15c1b5626b62903b5ad6e665fee"
+  integrity sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==
 
-nanoid@^3.1.18:
-  version "3.1.20"
-  resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.20.tgz#badc263c6b1dcf14b71efaa85f6ab4c1d6cfc788"
-  integrity sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw==
+nanoid@^3.1.23:
+  version "3.1.25"
+  resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.25.tgz#09ca32747c0e543f0e1814b7d3793477f9c8e152"
+  integrity sha512-rdwtIXaXCLFAQbnfqDRnI6jaRHp9fTcYBjtFKE8eezcZ7LuLjhUaQGNeMXf1HmRoCH32CLz6XwX0TtxEOS/A3Q==
 
 nanomatch@^1.2.9:
   version "1.2.13"
@@ -8140,7 +7299,7 @@ negotiator@0.6.2:
   resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb"
   integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==
 
-neo-async@^2.5.0, neo-async@^2.6.0, neo-async@^2.6.1:
+neo-async@^2.5.0, neo-async@^2.6.1, neo-async@^2.6.2:
   version "2.6.2"
   resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f"
   integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==
@@ -8183,16 +7342,12 @@ node-fetch@^2.6.1:
   resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052"
   integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==
 
-node-forge@^0.7.1:
-  version "0.7.6"
-  resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.7.6.tgz#fdf3b418aee1f94f0ef642cd63486c77ca9724ac"
-  integrity sha512-sol30LUpz1jQFBjOKwbjxijiE3b6pjd74YwfD0fJOKPjF+fONKb2Yg8rYgS6+bK6VDl+/wfr4IYpC7jDzLUIfw==
-
-node-html-parser@^2.0.0:
-  version "2.0.1"
-  resolved "https://registry.yarnpkg.com/node-html-parser/-/node-html-parser-2.0.1.tgz#66e3a6178f5fbf345f5e0e7522d36af7625a3346"
-  integrity sha512-CE0K6zALs+pS+SsQd8oKKF51cNrpwZ6gj/8OSzjhQ2vTfCOnlNtZakgv0MKuEOAZ4kBiKRgJBUicvjAxaFM4Hw==
+node-html-parser@^3.2.0:
+  version "3.3.6"
+  resolved "https://registry.yarnpkg.com/node-html-parser/-/node-html-parser-3.3.6.tgz#fdbb3ba16d1252d7197ec39f0260d9c10ef33590"
+  integrity sha512-VkWDHvNgFGB3mbQGMyzqRE1i/BG7TKX9wRXC8e/v8kL0kZR/Oy6RjYxXH91K6/+m3g8iQ8dTqRy75lTYoA2Cjg==
   dependencies:
+    css-select "^4.1.3"
     he "1.2.0"
 
 node-int64@^0.4.0:
@@ -8200,7 +7355,7 @@ node-int64@^0.4.0:
   resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b"
   integrity sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=
 
-node-libs-browser@^2.0.0, node-libs-browser@^2.2.1:
+node-libs-browser@^2.2.1:
   version "2.2.1"
   resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.2.1.tgz#b64f513d18338625f90346d27b0d235e631f6425"
   integrity sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==
@@ -8235,9 +7390,9 @@ node-modules-regexp@^1.0.0:
   integrity sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA=
 
 node-notifier@^8.0.0:
-  version "8.0.1"
-  resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-8.0.1.tgz#f86e89bbc925f2b068784b31f382afdc6ca56be1"
-  integrity sha512-BvEXF+UmsnAfYfoapKM9nGxnP+Wn7P91YfXmrKnfcYCx6VBeoN5Ez5Ogck6I8Bi5k4RlpqRYaw75pAwzX9OphA==
+  version "8.0.2"
+  resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-8.0.2.tgz#f3167a38ef0d2c8a866a83e318c1ba0efeb702c5"
+  integrity sha512-oJP/9NAdd9+x2Q+rfphB2RJCHjod70RcRLjosiPMMu5gjIfwVnOUGq2nbTjTUbmy0DJ/tFIVT30+Qe3nzl4TJg==
   dependencies:
     growly "^1.3.0"
     is-wsl "^2.2.0"
@@ -8251,10 +7406,10 @@ node-object-hash@^1.2.0:
   resolved "https://registry.yarnpkg.com/node-object-hash/-/node-object-hash-1.4.2.tgz#385833d85b229902b75826224f6077be969a9e94"
   integrity sha512-UdS4swXs85fCGWWf6t6DMGgpN/vnlKeSGEQ7hJcrs7PBFoxoKLmibc3QRb7fwiYsjdL7PX8iI/TMSlZ90dgHhQ==
 
-node-releases@^1.1.67:
-  version "1.1.69"
-  resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.69.tgz#3149dbde53b781610cd8b486d62d86e26c3725f6"
-  integrity sha512-DGIjo79VDEyAnRlfSqYTsy+yoHd2IOjJiKUozD2MV2D85Vso6Bug56mb9tT/fY5Urt0iqk01H7x+llAruDR2zA==
+node-releases@^1.1.75:
+  version "1.1.75"
+  resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.75.tgz#6dd8c876b9897a1b8e5a02de26afa79bb54ebbfe"
+  integrity sha512-Qe5OUajvqrqDSy6wrWFmMwfJ0jVgwiw4T3KqmbTcZ62qW0gQkheXYhcFM1+lOVcGUoRxcEcfyvFMAnDgaF1VWw==
 
 node-res@^5.0.1:
   version "5.0.1"
@@ -8311,11 +7466,16 @@ normalize-url@1.9.1:
     query-string "^4.1.0"
     sort-keys "^1.0.0"
 
-normalize-url@^3.0.0, normalize-url@^3.3.0:
+normalize-url@^3.0.0:
   version "3.3.0"
   resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-3.3.0.tgz#b2e1c4dc4f7c6d57743df733a4f5978d18650559"
   integrity sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg==
 
+normalize-url@^6.1.0:
+  version "6.1.0"
+  resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-6.1.0.tgz#40d0885b535deffe3f3147bec877d05fe4c5668a"
+  integrity sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==
+
 npm-run-path@^2.0.0:
   version "2.0.2"
   resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f"
@@ -8323,7 +7483,7 @@ npm-run-path@^2.0.0:
   dependencies:
     path-key "^2.0.0"
 
-npm-run-path@^4.0.0:
+npm-run-path@^4.0.0, npm-run-path@^4.0.1:
   version "4.0.1"
   resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea"
   integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==
@@ -8337,36 +7497,44 @@ nth-check@^1.0.2:
   dependencies:
     boolbase "~1.0.0"
 
+nth-check@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.0.0.tgz#1bb4f6dac70072fc313e8c9cd1417b5074c0a125"
+  integrity sha512-i4sc/Kj8htBrAiH1viZ0TgU8Y5XqCaV/FziYK6TBczxmeKm3AEFWqqF3195yKudrarqy7Zu80Ra5dobFjn9X/Q==
+  dependencies:
+    boolbase "^1.0.0"
+
 num2fraction@^1.2.2:
   version "1.2.2"
   resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede"
   integrity sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=
 
 nuxt@^2.14.0:
-  version "2.14.12"
-  resolved "https://registry.yarnpkg.com/nuxt/-/nuxt-2.14.12.tgz#836096ff62ba72554b73744d94f5547109e563f7"
-  integrity sha512-tfGz7s0ahL6mCGzzVEWpHgv+/hekNXgY1fX0SBB0dvJKjVHKAdoMxaoHBYhoCYdNL2GNiNQncHRipxiEtuCtOQ==
-  dependencies:
-    "@nuxt/builder" "2.14.12"
-    "@nuxt/cli" "2.14.12"
-    "@nuxt/components" "^1.2.2"
-    "@nuxt/core" "2.14.12"
-    "@nuxt/generator" "2.14.12"
+  version "2.15.8"
+  resolved "https://registry.yarnpkg.com/nuxt/-/nuxt-2.15.8.tgz#946cba46bdaaf0e3918aa27fd9ea0fed8ed303b0"
+  integrity sha512-ceK3qLg/Baj7J8mK9bIxqw9AavrF+LXqwYEreBdY/a4Sj8YV4mIvhqea/6E7VTCNNGvKT2sJ/TTJjtfQ597lTA==
+  dependencies:
+    "@nuxt/babel-preset-app" "2.15.8"
+    "@nuxt/builder" "2.15.8"
+    "@nuxt/cli" "2.15.8"
+    "@nuxt/components" "^2.1.8"
+    "@nuxt/config" "2.15.8"
+    "@nuxt/core" "2.15.8"
+    "@nuxt/generator" "2.15.8"
     "@nuxt/loading-screen" "^2.0.3"
     "@nuxt/opencollective" "^0.3.2"
-    "@nuxt/telemetry" "^1.3.0"
-    "@nuxt/webpack" "2.14.12"
-
-nwsapi@^2.1.3, nwsapi@^2.2.0:
+    "@nuxt/server" "2.15.8"
+    "@nuxt/telemetry" "^1.3.3"
+    "@nuxt/utils" "2.15.8"
+    "@nuxt/vue-app" "2.15.8"
+    "@nuxt/vue-renderer" "2.15.8"
+    "@nuxt/webpack" "2.15.8"
+
+nwsapi@^2.2.0:
   version "2.2.0"
   resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.0.tgz#204879a9e3d068ff2a55139c2c772780681a38b7"
   integrity sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==
 
-oauth-sign@~0.9.0:
-  version "0.9.0"
-  resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455"
-  integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==
-
 object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1:
   version "4.1.1"
   resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
@@ -8382,21 +7550,16 @@ object-copy@^0.1.0:
     kind-of "^3.0.3"
 
 object-hash@^2.0.3:
-  version "2.1.1"
-  resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-2.1.1.tgz#9447d0279b4fcf80cff3259bf66a1dc73afabe09"
-  integrity sha512-VOJmgmS+7wvXf8CjbQmimtCnEx3IAoLxI3fp2fbWehxrWBcAQFbk+vcwb6vzR0VZv/eNCJ/27j151ZTwqW/JeQ==
-
-object-inspect@^1.8.0:
-  version "1.9.0"
-  resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.9.0.tgz#c90521d74e1127b67266ded3394ad6116986533a"
-  integrity sha512-i3Bp9iTqwhaLZBxGkRfo5ZbE07BQRT7MGu8+nNgwW9ItGp1TzCTw2DLEoWwjClxBjOFI/hWljTAmYGCEwmtnOw==
+  version "2.2.0"
+  resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-2.2.0.tgz#5ad518581eefc443bd763472b8ff2e9c2c0d54a5"
+  integrity sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==
 
-object-inspect@~1.4.0:
-  version "1.4.1"
-  resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.4.1.tgz#37ffb10e71adaf3748d05f713b4c9452f402cbc4"
-  integrity sha512-wqdhLpfCUbEsoEwl3FXwGyv8ief1k/1aUdIPCqVnupM6e8l63BEJdiF/0swtn04/8p05tG/T0FrpTlfwvljOdw==
+object-inspect@^1.11.0, object-inspect@^1.9.0:
+  version "1.11.0"
+  resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.11.0.tgz#9dceb146cedd4148a0d9e51ab88d34cf509922b1"
+  integrity sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg==
 
-object-keys@^1.0.12, object-keys@^1.0.6, object-keys@^1.1.1:
+object-keys@^1.0.12, object-keys@^1.1.1:
   version "1.1.1"
   resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e"
   integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==
@@ -8408,7 +7571,7 @@ object-visit@^1.0.0:
   dependencies:
     isobject "^3.0.0"
 
-object.assign@^4.1.0, object.assign@^4.1.1:
+object.assign@^4.1.0, object.assign@^4.1.2:
   version "4.1.2"
   resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940"
   integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==
@@ -8419,13 +7582,13 @@ object.assign@^4.1.0, object.assign@^4.1.1:
     object-keys "^1.1.1"
 
 object.getownpropertydescriptors@^2.0.3, object.getownpropertydescriptors@^2.1.0:
-  version "2.1.1"
-  resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.1.tgz#0dfda8d108074d9c563e80490c883b6661091544"
-  integrity sha512-6DtXgZ/lIZ9hqx4GtZETobXLR/ZLaa0aqV0kzbn80Rf8Z2e/XFnhA0I7p07N2wH8bBBltr2xQPi6sbKWAY2Eng==
+  version "2.1.2"
+  resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.2.tgz#1bd63aeacf0d5d2d2f31b5e393b03a7c601a23f7"
+  integrity sha512-WtxeKSzfBjlzL+F9b7M7hewDzMwy+C8NRssHd1YrNlzHzIDrXcXiNOMrezdAEM4UXixgV+vvnyBeN7Rygl2ttQ==
   dependencies:
-    call-bind "^1.0.0"
+    call-bind "^1.0.2"
     define-properties "^1.1.3"
-    es-abstract "^1.18.0-next.1"
+    es-abstract "^1.18.0-next.2"
 
 object.pick@^1.3.0:
   version "1.3.0"
@@ -8435,14 +7598,13 @@ object.pick@^1.3.0:
     isobject "^3.0.1"
 
 object.values@^1.1.0, object.values@^1.1.1:
-  version "1.1.2"
-  resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.2.tgz#7a2015e06fcb0f546bd652486ce8583a4731c731"
-  integrity sha512-MYC0jvJopr8EK6dPBiO8Nb9mvjdypOachO5REGk6MXzujbBrAisKo3HmdEI6kZDL6fC31Mwee/5YbtMebixeag==
+  version "1.1.4"
+  resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.4.tgz#0d273762833e816b693a637d30073e7051535b30"
+  integrity sha512-TnGo7j4XSnKQoK3MfvkzqKCi0nVe/D9I9IjwTNYdb/fxYHpjrluHVOgw0AF6jrRFGMPHdfuidR09tIDiIvnaSg==
   dependencies:
-    call-bind "^1.0.0"
+    call-bind "^1.0.2"
     define-properties "^1.1.3"
-    es-abstract "^1.18.0-next.1"
-    has "^1.0.3"
+    es-abstract "^1.18.2"
 
 on-finished@^2.3.0, on-finished@~2.3.0:
   version "2.3.0"
@@ -8463,36 +7625,22 @@ once@^1.3.0, once@^1.3.1, once@^1.4.0:
   dependencies:
     wrappy "1"
 
-onetime@^2.0.0:
-  version "2.0.1"
-  resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4"
-  integrity sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=
-  dependencies:
-    mimic-fn "^1.0.0"
-
-onetime@^5.1.0:
+onetime@^5.1.0, onetime@^5.1.2:
   version "5.1.2"
   resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e"
   integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==
   dependencies:
     mimic-fn "^2.1.0"
 
-opener@1.5.2, opener@^1.5.1:
+opener@1.5.2, opener@^1.5.2:
   version "1.5.2"
   resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.2.tgz#5d37e1f35077b9dcac4301372271afdeb2a13598"
   integrity sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==
 
-opn@^5.1.0:
-  version "5.5.0"
-  resolved "https://registry.yarnpkg.com/opn/-/opn-5.5.0.tgz#fc7164fab56d235904c51c3b27da6758ca3b9bfc"
-  integrity sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA==
-  dependencies:
-    is-wsl "^1.1.0"
-
 optimize-css-assets-webpack-plugin@^5.0.4:
-  version "5.0.4"
-  resolved "https://registry.yarnpkg.com/optimize-css-assets-webpack-plugin/-/optimize-css-assets-webpack-plugin-5.0.4.tgz#85883c6528aaa02e30bbad9908c92926bb52dc90"
-  integrity sha512-wqd6FdI2a5/FdoiCNNkEvLeA//lHHfG24Ln2Xm2qqdIk4aOlsR18jwpyOihqQ8849W3qu2DX8fOYxpvTMj+93A==
+  version "5.0.8"
+  resolved "https://registry.yarnpkg.com/optimize-css-assets-webpack-plugin/-/optimize-css-assets-webpack-plugin-5.0.8.tgz#cbccdcf5a6ef61d4f8cc78cf083a67446e5f402a"
+  integrity sha512-mgFS1JdOtEGzD8l+EuISqL57cKO+We9GcoiQEmdCWRqqck+FGNmYJtx9qfAPzEz+lRrlThWMuGDaRkI/yWNx/Q==
   dependencies:
     cssnano "^4.1.10"
     last-call-webpack-plugin "^3.0.0"
@@ -8521,18 +7669,6 @@ optionator@^0.9.1:
     type-check "^0.4.0"
     word-wrap "^1.2.3"
 
-ora@^2.1.0:
-  version "2.1.0"
-  resolved "https://registry.yarnpkg.com/ora/-/ora-2.1.0.tgz#6caf2830eb924941861ec53a173799e008b51e5b"
-  integrity sha512-hNNlAd3gfv/iPmsNxYoAPLvxg7HuPozww7fFonMZvL84tP6Ox5igfk5j/+a9rtJJwqMgKK+JgWsAQik5o0HTLA==
-  dependencies:
-    chalk "^2.3.1"
-    cli-cursor "^2.1.0"
-    cli-spinners "^1.1.0"
-    log-symbols "^2.2.0"
-    strip-ansi "^4.0.0"
-    wcwidth "^1.0.1"
-
 os-browserify@^0.3.0:
   version "0.3.0"
   resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27"
@@ -8543,6 +7679,11 @@ os-tmpdir@~1.0.2:
   resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
   integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=
 
+p-defer@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c"
+  integrity sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=
+
 p-each-series@^2.1.0:
   version "2.2.0"
   resolved "https://registry.yarnpkg.com/p-each-series/-/p-each-series-2.2.0.tgz#105ab0357ce72b202a8a8b94933672657b5e2a9a"
@@ -8553,11 +7694,6 @@ p-finally@^1.0.0:
   resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae"
   integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=
 
-p-finally@^2.0.0:
-  version "2.0.1"
-  resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-2.0.1.tgz#bd6fcaa9c559a096b680806f4d657b3f0f240561"
-  integrity sha512-vpm09aKwq6H9phqRQzecoDpD8TmVyGw70qmWlyq5onxY7tqyTTFVvxMykxQSQKILBSFlbXpypIw2T1Ml7+DDtw==
-
 p-limit@^1.1.0:
   version "1.3.0"
   resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8"
@@ -8565,13 +7701,20 @@ p-limit@^1.1.0:
   dependencies:
     p-try "^1.0.0"
 
-p-limit@^2.0.0, p-limit@^2.2.0, p-limit@^2.3.0:
+p-limit@^2.0.0, p-limit@^2.2.0:
   version "2.3.0"
   resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1"
   integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==
   dependencies:
     p-try "^2.0.0"
 
+p-limit@^3.0.2:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b"
+  integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==
+  dependencies:
+    yocto-queue "^0.1.0"
+
 p-locate@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43"
@@ -8593,10 +7736,10 @@ p-locate@^4.1.0:
   dependencies:
     p-limit "^2.2.0"
 
-p-map@^3.0.0:
-  version "3.0.0"
-  resolved "https://registry.yarnpkg.com/p-map/-/p-map-3.0.0.tgz#d704d9af8a2ba684e2600d9a215983d4141a979d"
-  integrity sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==
+p-map@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b"
+  integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==
   dependencies:
     aggregate-error "^3.0.0"
 
@@ -8610,20 +7753,15 @@ p-try@^2.0.0:
   resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6"
   integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==
 
-pako@^0.2.5:
-  version "0.2.9"
-  resolved "https://registry.yarnpkg.com/pako/-/pako-0.2.9.tgz#f3f7522f4ef782348da8161bad9ecfd51bf83a75"
-  integrity sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=
-
 pako@~1.0.5:
   version "1.0.11"
   resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf"
   integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==
 
 papaparse@^5.3.0:
-  version "5.3.0"
-  resolved "https://registry.yarnpkg.com/papaparse/-/papaparse-5.3.0.tgz#ab1702feb96e79ab4309652f36db9536563ad05a"
-  integrity sha512-Lb7jN/4bTpiuGPrYy4tkKoUS8sTki8zacB5ke1p5zolhcSE4TlWgrlsxjrDTbG/dFVh07ck7X36hUf/b5V68pg==
+  version "5.3.1"
+  resolved "https://registry.yarnpkg.com/papaparse/-/papaparse-5.3.1.tgz#770b7a9124d821d4b2132132b7bd7dce7194b5b1"
+  integrity sha512-Dbt2yjLJrCwH2sRqKFFJaN5XgIASO9YOFeFP8rIBRG2Ain8mqk5r1M6DkfvqEVozVcz3r3HaUGw253hA1nLIcA==
 
 parallel-transform@^1.1.0:
   version "1.2.0"
@@ -8649,71 +7787,6 @@ param-case@^3.0.3:
     dot-case "^3.0.4"
     tslib "^2.0.3"
 
-parcel-bundler@^1.12.4:
-  version "1.12.4"
-  resolved "https://registry.yarnpkg.com/parcel-bundler/-/parcel-bundler-1.12.4.tgz#31223f4ab4d00323a109fce28d5e46775409a9ee"
-  integrity sha512-G+iZGGiPEXcRzw0fiRxWYCKxdt/F7l9a0xkiU4XbcVRJCSlBnioWEwJMutOCCpoQmaQtjB4RBHDGIHN85AIhLQ==
-  dependencies:
-    "@babel/code-frame" "^7.0.0"
-    "@babel/core" "^7.4.4"
-    "@babel/generator" "^7.4.4"
-    "@babel/parser" "^7.4.4"
-    "@babel/plugin-transform-flow-strip-types" "^7.4.4"
-    "@babel/plugin-transform-modules-commonjs" "^7.4.4"
-    "@babel/plugin-transform-react-jsx" "^7.0.0"
-    "@babel/preset-env" "^7.4.4"
-    "@babel/runtime" "^7.4.4"
-    "@babel/template" "^7.4.4"
-    "@babel/traverse" "^7.4.4"
-    "@babel/types" "^7.4.4"
-    "@iarna/toml" "^2.2.0"
-    "@parcel/fs" "^1.11.0"
-    "@parcel/logger" "^1.11.1"
-    "@parcel/utils" "^1.11.0"
-    "@parcel/watcher" "^1.12.1"
-    "@parcel/workers" "^1.11.0"
-    ansi-to-html "^0.6.4"
-    babylon-walk "^1.0.2"
-    browserslist "^4.1.0"
-    chalk "^2.1.0"
-    clone "^2.1.1"
-    command-exists "^1.2.6"
-    commander "^2.11.0"
-    core-js "^2.6.5"
-    cross-spawn "^6.0.4"
-    css-modules-loader-core "^1.1.0"
-    cssnano "^4.0.0"
-    deasync "^0.1.14"
-    dotenv "^5.0.0"
-    dotenv-expand "^5.1.0"
-    envinfo "^7.3.1"
-    fast-glob "^2.2.2"
-    filesize "^3.6.0"
-    get-port "^3.2.0"
-    htmlnano "^0.2.2"
-    is-glob "^4.0.0"
-    is-url "^1.2.2"
-    js-yaml "^3.10.0"
-    json5 "^1.0.1"
-    micromatch "^3.0.4"
-    mkdirp "^0.5.1"
-    node-forge "^0.7.1"
-    node-libs-browser "^2.0.0"
-    opn "^5.1.0"
-    postcss "^7.0.11"
-    postcss-value-parser "^3.3.1"
-    posthtml "^0.11.2"
-    posthtml-parser "^0.4.0"
-    posthtml-render "^1.1.3"
-    resolve "^1.4.0"
-    semver "^5.4.1"
-    serialize-to-js "^3.0.0"
-    serve-static "^1.12.4"
-    source-map "0.6.1"
-    terser "^3.7.3"
-    v8-compile-cache "^2.0.0"
-    ws "^5.1.1"
-
 parent-module@^1.0.0:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2"
@@ -8756,9 +7829,9 @@ parse-json@^4.0.0:
     json-parse-better-errors "^1.0.1"
 
 parse-json@^5.0.0:
-  version "5.1.0"
-  resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.1.0.tgz#f96088cdf24a8faa9aea9a009f2d9d942c999646"
-  integrity sha512-+mi/lmVVNKFNVyLXV31ERiy2CY5E1/F6QtJFEzoChPRwwngMNXRDQ9GJ5WdE2Z2P4AujsOi0/+2qHID68KwfIQ==
+  version "5.2.0"
+  resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd"
+  integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==
   dependencies:
     "@babel/code-frame" "^7.0.0"
     error-ex "^1.3.1"
@@ -8766,32 +7839,29 @@ parse-json@^5.0.0:
     lines-and-columns "^1.1.6"
 
 parse-path@^4.0.0:
-  version "4.0.2"
-  resolved "https://registry.yarnpkg.com/parse-path/-/parse-path-4.0.2.tgz#ef14f0d3d77bae8dd4bc66563a4c151aac9e65aa"
-  integrity sha512-HSqVz6iuXSiL8C1ku5Gl1Z5cwDd9Wo0q8CoffdAghP6bz8pJa1tcMC+m4N+z6VAS8QdksnIGq1TB6EgR4vPR6w==
+  version "4.0.3"
+  resolved "https://registry.yarnpkg.com/parse-path/-/parse-path-4.0.3.tgz#82d81ec3e071dcc4ab49aa9f2c9c0b8966bb22bf"
+  integrity sha512-9Cepbp2asKnWTJ9x2kpw6Fe8y9JDbqwahGCTvklzd/cEq5C5JC59x2Xb0Kx+x0QZ8bvNquGO8/BWP0cwBHzSAA==
   dependencies:
     is-ssh "^1.3.0"
     protocols "^1.4.0"
+    qs "^6.9.4"
+    query-string "^6.13.8"
 
-parse-url@^5.0.0:
-  version "5.0.2"
-  resolved "https://registry.yarnpkg.com/parse-url/-/parse-url-5.0.2.tgz#856a3be1fcdf78dc93fc8b3791f169072d898b59"
-  integrity sha512-Czj+GIit4cdWtxo3ISZCvLiUjErSo0iI3wJ+q9Oi3QuMYTI6OZu+7cewMWZ+C1YAnKhYTk6/TLuhIgCypLthPA==
+parse-url@^6.0.0:
+  version "6.0.0"
+  resolved "https://registry.yarnpkg.com/parse-url/-/parse-url-6.0.0.tgz#f5dd262a7de9ec00914939220410b66cff09107d"
+  integrity sha512-cYyojeX7yIIwuJzledIHeLUBVJ6COVLeT4eF+2P6aKVzwvgKQPndCBv3+yQ7pcWjqToYwaligxzSYNNmGoMAvw==
   dependencies:
     is-ssh "^1.3.0"
-    normalize-url "^3.3.0"
+    normalize-url "^6.1.0"
     parse-path "^4.0.0"
     protocols "^1.4.0"
 
-parse5@5.1.0:
-  version "5.1.0"
-  resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.0.tgz#c59341c9723f414c452975564c7c00a68d58acd2"
-  integrity sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ==
-
-parse5@5.1.1:
-  version "5.1.1"
-  resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.1.tgz#f68e4e5ba1852ac2cadc00f4555fff6c2abb6178"
-  integrity sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==
+parse5@6.0.1:
+  version "6.0.1"
+  resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b"
+  integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==
 
 parseurl@~1.3.3:
   version "1.3.3"
@@ -8847,14 +7917,9 @@ path-key@^3.0.0, path-key@^3.1.0:
   integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==
 
 path-parse@^1.0.6:
-  version "1.0.6"
-  resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c"
-  integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==
-
-path-to-regexp@0.1.7:
-  version "0.1.7"
-  resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
-  integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=
+  version "1.0.7"
+  resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
+  integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
 
 path-type@^2.0.0:
   version "2.0.0"
@@ -8869,9 +7934,9 @@ path-type@^4.0.0:
   integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==
 
 pbkdf2@^3.0.3:
-  version "3.1.1"
-  resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.1.tgz#cb8724b0fada984596856d1a6ebafd3584654b94"
-  integrity sha512-4Ejy1OPxi9f2tt1rRV7Go7zmfDQ+ZectEQz3VGUQhgq62HtIRPDyG/JtnwIxs6x3uNMwo2V7q1fMvKjb+Tnpqg==
+  version "3.1.2"
+  resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.2.tgz#dd822aa0887580e52f1a039dc3eda108efae3075"
+  integrity sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==
   dependencies:
     create-hash "^1.1.2"
     create-hmac "^1.1.4"
@@ -8879,20 +7944,10 @@ pbkdf2@^3.0.3:
     safe-buffer "^5.0.1"
     sha.js "^2.4.8"
 
-performance-now@^2.1.0:
-  version "2.1.0"
-  resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
-  integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=
-
-physical-cpu-count@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/physical-cpu-count/-/physical-cpu-count-2.0.0.tgz#18de2f97e4bf7a9551ad7511942b5496f7aba660"
-  integrity sha1-GN4vl+S/epVRrXURlCtUlverpmA=
-
-picomatch@^2.0.4, picomatch@^2.0.5, picomatch@^2.2.1:
-  version "2.2.2"
-  resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad"
-  integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==
+picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3:
+  version "2.3.0"
+  resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972"
+  integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==
 
 pify@^2.0.0, pify@^2.3.0:
   version "2.3.0"
@@ -8909,6 +7964,11 @@ pify@^4.0.1:
   resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231"
   integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==
 
+pify@^5.0.0:
+  version "5.0.0"
+  resolved "https://registry.yarnpkg.com/pify/-/pify-5.0.0.tgz#1f5eca3f5e87ebec28cc6d54a0e4aaf00acc127f"
+  integrity sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA==
+
 pirates@^4.0.1:
   version "4.0.1"
   resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.1.tgz#643a92caf894566f91b2b986d2c66950a8e2fb87"
@@ -8937,20 +7997,17 @@ pkg-dir@^4.1.0, pkg-dir@^4.2.0:
   dependencies:
     find-up "^4.0.0"
 
-plotly.js-dist@^1.57.1:
-  version "1.58.4"
-  resolved "https://registry.yarnpkg.com/plotly.js-dist/-/plotly.js-dist-1.58.4.tgz#d57b73d27af57a0d6cd2cf9428a001962889cf5b"
-  integrity sha512-oXCTRJFN8FBsHZSQPYoM3LuJQchPUrf6sOXFC0EFdvcr5lmJmLcAsW74jDy9PkRpm3PB+A+2oY1hsUMmk2eZbw==
-
 pluralize@^8.0.0:
   version "8.0.0"
   resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-8.0.0.tgz#1a6fa16a38d12a1901e0320fa017051c539ce3b1"
   integrity sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==
 
-pn@^1.1.0:
-  version "1.1.0"
-  resolved "https://registry.yarnpkg.com/pn/-/pn-1.1.0.tgz#e2f4cef0e219f463c179ab37463e4e1ecdccbafb"
-  integrity sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==
+pnp-webpack-plugin@^1.6.4:
+  version "1.7.0"
+  resolved "https://registry.yarnpkg.com/pnp-webpack-plugin/-/pnp-webpack-plugin-1.7.0.tgz#65741384f6d8056f36e2255a8d67ffc20866f5c9"
+  integrity sha512-2Rb3vm+EXble/sMXNSu6eoBx8e79gKqhNq9F5ZWW6ERNCTE/Q0wQNne5541tE5vKjfM8hpNCYL+LGc1YTfI0dg==
+  dependencies:
+    ts-pnp "^1.1.6"
 
 posix-character-classes@^0.1.0:
   version "0.1.1"
@@ -9164,11 +8221,10 @@ postcss-import@^12.0.1:
     resolve "^1.1.7"
 
 postcss-initial@^3.0.0:
-  version "3.0.2"
-  resolved "https://registry.yarnpkg.com/postcss-initial/-/postcss-initial-3.0.2.tgz#f018563694b3c16ae8eaabe3c585ac6319637b2d"
-  integrity sha512-ugA2wKonC0xeNHgirR4D3VWHs2JcU08WAi1KFLVcnb7IN89phID6Qtg2RIctWbnvp1TM2BOmDtX8GGLCKdR8YA==
+  version "3.0.4"
+  resolved "https://registry.yarnpkg.com/postcss-initial/-/postcss-initial-3.0.4.tgz#9d32069a10531fe2ecafa0b6ac750ee0bc7efc53"
+  integrity sha512-3RLn6DIpMsK1l5UUy9jxQvoDeUN4gP939tDcKUHD/kM8SGSKbFAnvkpFpj3Bhtz3HGk1jWY5ZNWX6mPta5M9fg==
   dependencies:
-    lodash.template "^4.5.0"
     postcss "^7.0.2"
 
 postcss-lab-function@^2.0.1:
@@ -9274,13 +8330,6 @@ postcss-minify-selectors@^4.0.2:
     postcss "^7.0.0"
     postcss-selector-parser "^3.0.0"
 
-postcss-modules-extract-imports@1.1.0:
-  version "1.1.0"
-  resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.1.0.tgz#b614c9720be6816eaee35fb3a5faa1dba6a05ddb"
-  integrity sha1-thTJcgvmgW6u41+zpfqh26agXds=
-  dependencies:
-    postcss "^6.0.1"
-
 postcss-modules-extract-imports@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz#818719a1ae1da325f9832446b01136eeb493cd7e"
@@ -9288,15 +8337,7 @@ postcss-modules-extract-imports@^2.0.0:
   dependencies:
     postcss "^7.0.5"
 
-postcss-modules-local-by-default@1.2.0:
-  version "1.2.0"
-  resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-1.2.0.tgz#f7d80c398c5a393fa7964466bd19500a7d61c069"
-  integrity sha1-99gMOYxaOT+nlkRmvRlQCn1hwGk=
-  dependencies:
-    css-selector-tokenizer "^0.7.0"
-    postcss "^6.0.1"
-
-postcss-modules-local-by-default@^3.0.2:
+postcss-modules-local-by-default@^3.0.3:
   version "3.0.3"
   resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-3.0.3.tgz#bb14e0cc78279d504dbdcbfd7e0ca28993ffbbb0"
   integrity sha512-e3xDq+LotiGesympRlKNgaJ0PCzoUIdpH0dj47iWAui/kyTgh3CiAr1qP54uodmJhl6p9rN6BoNcdEDVJx9RDw==
@@ -9306,14 +8347,6 @@ postcss-modules-local-by-default@^3.0.2:
     postcss-selector-parser "^6.0.2"
     postcss-value-parser "^4.1.0"
 
-postcss-modules-scope@1.1.0:
-  version "1.1.0"
-  resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-1.1.0.tgz#d6ea64994c79f97b62a72b426fbe6056a194bb90"
-  integrity sha1-1upkmUx5+XtipytCb75gVqGUu5A=
-  dependencies:
-    css-selector-tokenizer "^0.7.0"
-    postcss "^6.0.1"
-
 postcss-modules-scope@^2.2.0:
   version "2.2.0"
   resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-2.2.0.tgz#385cae013cc7743f5a7d7602d1073a89eaae62ee"
@@ -9322,14 +8355,6 @@ postcss-modules-scope@^2.2.0:
     postcss "^7.0.6"
     postcss-selector-parser "^6.0.0"
 
-postcss-modules-values@1.3.0:
-  version "1.3.0"
-  resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-1.3.0.tgz#ecffa9d7e192518389f42ad0e83f72aec456ea20"
-  integrity sha1-7P+p1+GSUYOJ9CrQ6D9yrsRW6iA=
-  dependencies:
-    icss-replace-symbols "^1.1.0"
-    postcss "^6.0.1"
-
 postcss-modules-values@^3.0.0:
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-3.0.0.tgz#5b5000d6ebae29b4255301b4a3a54574423e7f10"
@@ -9551,15 +8576,6 @@ postcss-selector-not@^4.0.0:
     balanced-match "^1.0.0"
     postcss "^7.0.2"
 
-postcss-selector-parser@6.0.2:
-  version "6.0.2"
-  resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.2.tgz#934cf799d016c83411859e09dcecade01286ec5c"
-  integrity sha512-36P2QR59jDTOAiIkqEprfJDsoNrvwFei3eCqKd1Y0tUsBimsq39BLp7RD+JWny3WgB1zGhJX8XVePwm9k4wdBg==
-  dependencies:
-    cssesc "^3.0.0"
-    indexes-of "^1.0.1"
-    uniq "^1.0.1"
-
 postcss-selector-parser@^3.0.0:
   version "3.1.2"
   resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz#b310f5c4c0fdaf76f94902bbaa30db6aa84f5270"
@@ -9579,21 +8595,18 @@ postcss-selector-parser@^5.0.0-rc.3, postcss-selector-parser@^5.0.0-rc.4:
     uniq "^1.0.1"
 
 postcss-selector-parser@^6.0.0, postcss-selector-parser@^6.0.2:
-  version "6.0.4"
-  resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.4.tgz#56075a1380a04604c38b063ea7767a129af5c2b3"
-  integrity sha512-gjMeXBempyInaBqpp8gODmwZ52WaYsVOsfr4L4lDQ7n3ncD6mEyySiDtgzCT+NYC0mmeOLvtsF8iaEf0YT6dBw==
+  version "6.0.6"
+  resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.6.tgz#2c5bba8174ac2f6981ab631a42ab0ee54af332ea"
+  integrity sha512-9LXrvaaX3+mcv5xkg5kFwqSzSH1JIObIx51PrndZwlmznwXRfxMddDvo9gve3gVR8ZTKgoFDdWkbRFmEhT4PMg==
   dependencies:
     cssesc "^3.0.0"
-    indexes-of "^1.0.1"
-    uniq "^1.0.1"
     util-deprecate "^1.0.2"
 
-postcss-svgo@^4.0.2:
-  version "4.0.2"
-  resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-4.0.2.tgz#17b997bc711b333bab143aaed3b8d3d6e3d38258"
-  integrity sha512-C6wyjo3VwFm0QgBy+Fu7gCYOkCmgmClghO+pjcxvrcBKtiKt0uCF+hvbMO1fyv5BMImRK90SMb+dwUnfbGd+jw==
+postcss-svgo@^4.0.3:
+  version "4.0.3"
+  resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-4.0.3.tgz#343a2cdbac9505d416243d496f724f38894c941e"
+  integrity sha512-NoRbrcMWTtUghzuKSoIm6XV+sJdvZ7GZSc3wdBN0W19FTtp2ko8NqLsgoh/m9CzNhU3KLPvQmjIwtaNFkaFTvw==
   dependencies:
-    is-svg "^3.0.0"
     postcss "^7.0.0"
     postcss-value-parser "^3.0.0"
     svgo "^1.0.0"
@@ -9618,7 +8631,7 @@ postcss-url@^8.0.0:
     postcss "^7.0.2"
     xxhashjs "^0.2.1"
 
-postcss-value-parser@^3.0.0, postcss-value-parser@^3.2.3, postcss-value-parser@^3.3.1:
+postcss-value-parser@^3.0.0, postcss-value-parser@^3.2.3:
   version "3.3.1"
   resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281"
   integrity sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==
@@ -9637,77 +8650,15 @@ postcss-values-parser@^2.0.0, postcss-values-parser@^2.0.1:
     indexes-of "^1.0.1"
     uniq "^1.0.1"
 
-postcss@6.0.1:
-  version "6.0.1"
-  resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.1.tgz#000dbd1f8eef217aa368b9a212c5fc40b2a8f3f2"
-  integrity sha1-AA29H47vIXqjaLmiEsX8QLKo8/I=
-  dependencies:
-    chalk "^1.1.3"
-    source-map "^0.5.6"
-    supports-color "^3.2.3"
-
-postcss@7.0.32:
-  version "7.0.32"
-  resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.32.tgz#4310d6ee347053da3433db2be492883d62cec59d"
-  integrity sha512-03eXong5NLnNCD05xscnGKGDZ98CyzoqPSMjOe6SuoQY7Z2hIj0Ld1g/O/UQRuOle2aRtiIRDg9tDcTGAkLfKw==
-  dependencies:
-    chalk "^2.4.2"
-    source-map "^0.6.1"
-    supports-color "^6.1.0"
-
-postcss@^6.0.1:
-  version "6.0.23"
-  resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.23.tgz#61c82cc328ac60e677645f979054eb98bc0e3324"
-  integrity sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==
-  dependencies:
-    chalk "^2.4.1"
-    source-map "^0.6.1"
-    supports-color "^5.4.0"
-
-postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.11, postcss@^7.0.14, postcss@^7.0.17, postcss@^7.0.2, postcss@^7.0.27, postcss@^7.0.32, postcss@^7.0.5, postcss@^7.0.6:
-  version "7.0.35"
-  resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.35.tgz#d2be00b998f7f211d8a276974079f2e92b970e24"
-  integrity sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==
+postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.17, postcss@^7.0.2, postcss@^7.0.27, postcss@^7.0.32, postcss@^7.0.36, postcss@^7.0.5, postcss@^7.0.6:
+  version "7.0.36"
+  resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.36.tgz#056f8cffa939662a8f5905950c07d5285644dfcb"
+  integrity sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==
   dependencies:
     chalk "^2.4.2"
     source-map "^0.6.1"
     supports-color "^6.1.0"
 
-posthtml-parser@^0.4.0, posthtml-parser@^0.4.1:
-  version "0.4.2"
-  resolved "https://registry.yarnpkg.com/posthtml-parser/-/posthtml-parser-0.4.2.tgz#a132bbdf0cd4bc199d34f322f5c1599385d7c6c1"
-  integrity sha512-BUIorsYJTvS9UhXxPTzupIztOMVNPa/HtAm9KHni9z6qEfiJ1bpOBL5DfUOL9XAc3XkLIEzBzpph+Zbm4AdRAg==
-  dependencies:
-    htmlparser2 "^3.9.2"
-
-posthtml-parser@^0.5.0:
-  version "0.5.3"
-  resolved "https://registry.yarnpkg.com/posthtml-parser/-/posthtml-parser-0.5.3.tgz#e95b92e57d98da50b443e116fcee39466cd9012e"
-  integrity sha512-uHosRn0y+1wbnlYKrqMjBPoo/kK5LPYImLtiETszNFYfFwAD3cQdD1R2E13Mh5icBxkHj+yKtlIHozCsmVWD/Q==
-  dependencies:
-    htmlparser2 "^3.9.2"
-
-posthtml-render@^1.1.3, posthtml-render@^1.1.5, posthtml-render@^1.2.3, posthtml-render@^1.3.0:
-  version "1.4.0"
-  resolved "https://registry.yarnpkg.com/posthtml-render/-/posthtml-render-1.4.0.tgz#40114070c45881cacb93347dae3eff53afbcff13"
-  integrity sha512-W1779iVHGfq0Fvh2PROhCe2QhB8mEErgqzo1wpIt36tCgChafP+hbXIhLDOM8ePJrZcFs0vkNEtdibEWVqChqw==
-
-posthtml@^0.11.2:
-  version "0.11.6"
-  resolved "https://registry.yarnpkg.com/posthtml/-/posthtml-0.11.6.tgz#e349d51af7929d0683b9d8c3abd8166beecc90a8"
-  integrity sha512-C2hrAPzmRdpuL3iH0TDdQ6XCc9M7Dcc3zEW5BLerY65G4tWWszwv6nG/ksi6ul5i2mx22ubdljgktXCtNkydkw==
-  dependencies:
-    posthtml-parser "^0.4.1"
-    posthtml-render "^1.1.5"
-
-posthtml@^0.13.4:
-  version "0.13.4"
-  resolved "https://registry.yarnpkg.com/posthtml/-/posthtml-0.13.4.tgz#ad81b3fa62b85f81ccdb5710f4ec375a4ed94934"
-  integrity sha512-i2oTo/+dwXGC6zaAQSF6WZEQSbEqu10hsvg01DWzGAfZmy31Iiy9ktPh9nnXDfZiYytjxTIvxoK4TI0uk4QWpw==
-  dependencies:
-    posthtml-parser "^0.5.0"
-    posthtml-render "^1.2.3"
-
 prelude-ls@^1.2.1:
   version "1.2.1"
   resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396"
@@ -9736,14 +8687,14 @@ prettier@^1.18.2:
   integrity sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew==
 
 prettier@^2.0.5:
-  version "2.2.1"
-  resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.2.1.tgz#795a1a78dd52f073da0cd42b21f9c91381923ff5"
-  integrity sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q==
+  version "2.3.2"
+  resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.3.2.tgz#ef280a05ec253712e486233db5c6f23441e7342d"
+  integrity sha512-lnJzDfJ66zkMy58OL5/NY5zp70S7Nz6KqcKkXYzn2tMVrNxvbqaBpg7H3qHaLxCJ5lNMsGuM8+ohS7cZrthdLQ==
 
-pretty-bytes@^5.4.1:
-  version "5.5.0"
-  resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.5.0.tgz#0cecda50a74a941589498011cf23275aa82b339e"
-  integrity sha512-p+T744ZyjjiaFlMUZZv6YPC5JrkNj8maRmPaQCWFJFplUAzpIUTRaTcS+7wmZtUoFXHtESJb23ISliaWyz3SHA==
+pretty-bytes@^5.6.0:
+  version "5.6.0"
+  resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.6.0.tgz#356256f643804773c82f64723fe78c92c62beaeb"
+  integrity sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==
 
 pretty-error@^2.1.1:
   version "2.1.2"
@@ -9798,19 +8749,19 @@ promise-inflight@^1.0.1:
   integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM=
 
 prompts@^2.0.1:
-  version "2.4.0"
-  resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.0.tgz#4aa5de0723a231d1ee9121c40fdf663df73f61d7"
-  integrity sha512-awZAKrk3vN6CroQukBL+R9051a4R3zCZBlJm/HBfrSZ8iTpYix3VX1vU4mveiLpiwmOJT4wokTF9m6HUk4KqWQ==
+  version "2.4.1"
+  resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.1.tgz#befd3b1195ba052f9fd2fde8a486c4e82ee77f61"
+  integrity sha512-EQyfIuO2hPDsX1L/blblV+H7I0knhgAd82cVneCwcdND9B8AuCDuRcBH6yIcG4dFzlOUqbazQqwGjx5xmsNLuQ==
   dependencies:
     kleur "^3.0.3"
     sisteransi "^1.0.5"
 
-proper-lockfile@^4.1.1:
-  version "4.1.1"
-  resolved "https://registry.yarnpkg.com/proper-lockfile/-/proper-lockfile-4.1.1.tgz#284cf9db9e30a90e647afad69deb7cb06881262c"
-  integrity sha512-1w6rxXodisVpn7QYvLk706mzprPTAPCYAqxMvctmPN3ekuRk/kuGkGc82pangZiAt4R3lwSuUzheTTn0/Yb7Zg==
+proper-lockfile@^4.1.2:
+  version "4.1.2"
+  resolved "https://registry.yarnpkg.com/proper-lockfile/-/proper-lockfile-4.1.2.tgz#c8b9de2af6b2f1601067f98e01ac66baa223141f"
+  integrity sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==
   dependencies:
-    graceful-fs "^4.1.11"
+    graceful-fs "^4.2.4"
     retry "^0.12.0"
     signal-exit "^3.0.2"
 
@@ -9824,14 +8775,6 @@ protocols@^1.1.0, protocols@^1.4.0:
   resolved "https://registry.yarnpkg.com/protocols/-/protocols-1.4.8.tgz#48eea2d8f58d9644a4a32caae5d5db290a075ce8"
   integrity sha512-IgjKyaUSjsROSO8/D49Ab7hP8mJgTYcqApOqdPhLoPxAplXmkp+zRvsrSQjFn5by0rhm4VH0GAUELIPpx7B1yg==
 
-proxy-addr@~2.0.5:
-  version "2.0.6"
-  resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.6.tgz#fdc2336505447d3f2f2c638ed272caf614bbb2bf"
-  integrity sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==
-  dependencies:
-    forwarded "~0.1.2"
-    ipaddr.js "1.9.1"
-
 prr@~1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476"
@@ -9842,7 +8785,7 @@ pseudomap@^1.0.2:
   resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3"
   integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM=
 
-psl@^1.1.28:
+psl@^1.1.33:
   version "1.8.0"
   resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24"
   integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==
@@ -9899,16 +8842,6 @@ punycode@^2.1.0, punycode@^2.1.1:
   resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
   integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
 
-purgecss@^2.3.0:
-  version "2.3.0"
-  resolved "https://registry.yarnpkg.com/purgecss/-/purgecss-2.3.0.tgz#5327587abf5795e6541517af8b190a6fb5488bb3"
-  integrity sha512-BE5CROfVGsx2XIhxGuZAT7rTH9lLeQx/6M0P7DTXQH4IUc3BBzs9JUzt4yzGf3JrH9enkeq6YJBe9CTtkm1WmQ==
-  dependencies:
-    commander "^5.0.0"
-    glob "^7.0.0"
-    postcss "7.0.32"
-    postcss-selector-parser "^6.0.2"
-
 q@^1.1.2:
   version "1.5.1"
   resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7"
@@ -9919,10 +8852,12 @@ qs@6.7.0:
   resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc"
   integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==
 
-qs@~6.5.2:
-  version "6.5.2"
-  resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36"
-  integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==
+qs@^6.9.4:
+  version "6.10.1"
+  resolved "https://registry.yarnpkg.com/qs/-/qs-6.10.1.tgz#4931482fa8d647a5aab799c5271d2133b981fb6a"
+  integrity sha512-M528Hph6wsSVOBiYUnGf+K/7w0hNshs/duGsNXPUCLH5XAqjEtiPGwNONLV0tBH8NoGb0mvD5JubnUTrujKDTg==
+  dependencies:
+    side-channel "^1.0.4"
 
 query-string@^4.1.0:
   version "4.3.4"
@@ -9932,24 +8867,35 @@ query-string@^4.1.0:
     object-assign "^4.1.0"
     strict-uri-encode "^1.0.0"
 
+query-string@^6.13.8:
+  version "6.14.1"
+  resolved "https://registry.yarnpkg.com/query-string/-/query-string-6.14.1.tgz#7ac2dca46da7f309449ba0f86b1fd28255b0c86a"
+  integrity sha512-XDxAeVmpfu1/6IjyT/gXHOl+S0vQ9owggJ30hhWKdHAsNPOcasn5o9BW0eejZqL2e4vMjhAxoW3jVHcD6mbcYw==
+  dependencies:
+    decode-uri-component "^0.2.0"
+    filter-obj "^1.1.0"
+    split-on-first "^1.0.0"
+    strict-uri-encode "^2.0.0"
+
 querystring-es3@^0.2.0:
   version "0.2.1"
   resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73"
   integrity sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=
 
-querystring@0.2.0, querystring@^0.2.0:
+querystring@0.2.0:
   version "0.2.0"
   resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620"
   integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=
 
-quote-stream@^1.0.1, quote-stream@~1.0.2:
-  version "1.0.2"
-  resolved "https://registry.yarnpkg.com/quote-stream/-/quote-stream-1.0.2.tgz#84963f8c9c26b942e153feeb53aae74652b7e0b2"
-  integrity sha1-hJY/jJwmuULhU/7rU6rnRlK34LI=
-  dependencies:
-    buffer-equal "0.0.1"
-    minimist "^1.1.3"
-    through2 "^2.0.0"
+querystring@^0.2.0:
+  version "0.2.1"
+  resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.1.tgz#40d77615bb09d16902a85c3e38aa8b5ed761c2dd"
+  integrity sha512-wkvS7mL/JMugcup3/rMitHmd9ecIGd2lhFhK9N3UUQ450h66d1r3Y9nvXzQAW1Lq+wyx61k/1pfKS5KuKiyEbg==
+
+queue-microtask@^1.2.2:
+  version "1.2.3"
+  resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243"
+  integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==
 
 randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.1.0:
   version "2.1.0"
@@ -9991,9 +8937,9 @@ rc9@^1.2.0:
     flat "^5.0.0"
 
 react-is@^17.0.1:
-  version "17.0.1"
-  resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.1.tgz#5b3531bd76a645a4c9fb6e693ed36419e3301339"
-  integrity sha512-NAnt2iGDXohE5LI7uBnLnqvLQMtzhkiAOLXTmv+qnF9Ky7xAPcX8Up/xWIhxvLVGJvuLiNc4xQLtuqDRzb4fSA==
+  version "17.0.2"
+  resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0"
+  integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==
 
 read-cache@^1.0.0:
   version "1.0.0"
@@ -10038,7 +8984,7 @@ read-pkg@^5.2.0:
     parse-json "^5.0.0"
     type-fest "^0.6.0"
 
-"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.3, readable-stream@~2.3.6:
+"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.6:
   version "2.3.7"
   resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57"
   integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==
@@ -10051,7 +8997,7 @@ read-pkg@^5.2.0:
     string_decoder "~1.1.1"
     util-deprecate "~1.0.1"
 
-readable-stream@^3.1.1, readable-stream@^3.6.0:
+readable-stream@^3.6.0:
   version "3.6.0"
   resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198"
   integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==
@@ -10069,10 +9015,10 @@ readdirp@^2.2.1:
     micromatch "^3.1.10"
     readable-stream "^2.0.2"
 
-readdirp@~3.5.0:
-  version "3.5.0"
-  resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.5.0.tgz#9ba74c019b15d365278d2e91bb8c48d7b4d42c9e"
-  integrity sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==
+readdirp@~3.6.0:
+  version "3.6.0"
+  resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7"
+  integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==
   dependencies:
     picomatch "^2.2.1"
 
@@ -10093,10 +9039,10 @@ regenerator-runtime@^0.11.0:
   resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9"
   integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==
 
-regenerator-runtime@^0.13.4:
-  version "0.13.7"
-  resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz#cac2dacc8a1ea675feaabaeb8ae833898ae46f55"
-  integrity sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==
+regenerator-runtime@^0.13.4, regenerator-runtime@^0.13.7:
+  version "0.13.9"
+  resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52"
+  integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==
 
 regenerator-transform@^0.14.2:
   version "0.14.5"
@@ -10114,14 +9060,14 @@ regex-not@^1.0.0, regex-not@^1.0.2:
     safe-regex "^1.1.0"
 
 regexp-tree@^0.1.21, regexp-tree@~0.1.1:
-  version "0.1.21"
-  resolved "https://registry.yarnpkg.com/regexp-tree/-/regexp-tree-0.1.21.tgz#55e2246b7f7d36f1b461490942fa780299c400d7"
-  integrity sha512-kUUXjX4AnqnR8KRTCrayAo9PzYMRKmVoGgaz2tBuz0MF3g1ZbGebmtW0yFHfFK9CmBjQKeYIgoL22pFLBJY7sw==
+  version "0.1.23"
+  resolved "https://registry.yarnpkg.com/regexp-tree/-/regexp-tree-0.1.23.tgz#8a8ce1cc5e971acef62213a7ecdb1f6e18a1f1b2"
+  integrity sha512-+7HWfb4Bvu8Rs2eQTUIpX9I/PlQkYOuTNbRpKLJlQpSgwSkzFYh+pUj0gtvglnOZLKB6YgnIgRuJ2/IlpL48qw==
 
 regexpp@^3.0.0, regexpp@^3.1.0:
-  version "3.1.0"
-  resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.1.0.tgz#206d0ad0a5648cffbdb8ae46438f3dc51c9f78e2"
-  integrity sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==
+  version "3.2.0"
+  resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2"
+  integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==
 
 regexpu-core@^4.7.1:
   version "4.7.1"
@@ -10141,9 +9087,9 @@ regjsgen@^0.5.1:
   integrity sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A==
 
 regjsparser@^0.6.4:
-  version "0.6.4"
-  resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.6.4.tgz#a769f8684308401a66e9b529d2436ff4d0666272"
-  integrity sha512-64O87/dPDgfk8/RQqC4gkZoGyyWFIEUTTh80CU6CWuK5vkCGyekIx+oKcEIYtP/RAxSQltCZHCNu/mdd7fqlJw==
+  version "0.6.9"
+  resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.6.9.tgz#b489eef7c9a2ce43727627011429cf833a7183e6"
+  integrity sha512-ZqbNRz1SNjLAiYuwY0zoXW8Ne675IX5q+YHioAGbCw4X96Mjl2+dcX9B2ciaeyYjViDAfvIjFpQjJgLttTEERQ==
   dependencies:
     jsesc "~0.5.0"
 
@@ -10158,68 +9104,26 @@ remove-trailing-separator@^1.0.1:
   integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8=
 
 renderkid@^2.0.4:
-  version "2.0.5"
-  resolved "https://registry.yarnpkg.com/renderkid/-/renderkid-2.0.5.tgz#483b1ac59c6601ab30a7a596a5965cabccfdd0a5"
-  integrity sha512-ccqoLg+HLOHq1vdfYNm4TBeaCDIi1FLt3wGojTDSvdewUv65oTmI3cnT2E4hRjl1gzKZIPK+KZrXzlUYKnR+vQ==
+  version "2.0.7"
+  resolved "https://registry.yarnpkg.com/renderkid/-/renderkid-2.0.7.tgz#464f276a6bdcee606f4a15993f9b29fc74ca8609"
+  integrity sha512-oCcFyxaMrKsKcTY59qnCAtmDVSLfPbrv6A3tVbPdFMMrv5jaK10V6m40cKsoPNhAqN6rmHW9sswW4o3ruSrwUQ==
   dependencies:
-    css-select "^2.0.2"
-    dom-converter "^0.2"
-    htmlparser2 "^3.10.1"
-    lodash "^4.17.20"
-    strip-ansi "^3.0.0"
+    css-select "^4.1.3"
+    dom-converter "^0.2.0"
+    htmlparser2 "^6.1.0"
+    lodash "^4.17.21"
+    strip-ansi "^3.0.1"
 
 repeat-element@^1.1.2:
-  version "1.1.3"
-  resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce"
-  integrity sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==
+  version "1.1.4"
+  resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.4.tgz#be681520847ab58c7568ac75fbfad28ed42d39e9"
+  integrity sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==
 
 repeat-string@^1.6.1:
   version "1.6.1"
   resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637"
   integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc=
 
-request-promise-core@1.1.4:
-  version "1.1.4"
-  resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.4.tgz#3eedd4223208d419867b78ce815167d10593a22f"
-  integrity sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==
-  dependencies:
-    lodash "^4.17.19"
-
-request-promise-native@^1.0.5, request-promise-native@^1.0.8:
-  version "1.0.9"
-  resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.9.tgz#e407120526a5efdc9a39b28a5679bf47b9d9dc28"
-  integrity sha512-wcW+sIUiWnKgNY0dqCpOZkUbF/I+YPi+f09JZIDa39Ec+q82CpSYniDp+ISgTTbKmnpJWASeJBPZmoxH84wt3g==
-  dependencies:
-    request-promise-core "1.1.4"
-    stealthy-require "^1.1.1"
-    tough-cookie "^2.3.3"
-
-request@^2.88.0, request@^2.88.2:
-  version "2.88.2"
-  resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3"
-  integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==
-  dependencies:
-    aws-sign2 "~0.7.0"
-    aws4 "^1.8.0"
-    caseless "~0.12.0"
-    combined-stream "~1.0.6"
-    extend "~3.0.2"
-    forever-agent "~0.6.1"
-    form-data "~2.3.2"
-    har-validator "~5.1.3"
-    http-signature "~1.2.0"
-    is-typedarray "~1.0.0"
-    isstream "~0.1.2"
-    json-stringify-safe "~5.0.1"
-    mime-types "~2.1.19"
-    oauth-sign "~0.9.0"
-    performance-now "^2.1.0"
-    qs "~6.5.2"
-    safe-buffer "^5.1.2"
-    tough-cookie "~2.5.0"
-    tunnel-agent "^0.6.0"
-    uuid "^3.3.2"
-
 require-directory@^2.1.1:
   version "2.1.1"
   resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
@@ -10277,22 +9181,14 @@ resolve-url@^0.2.1:
   resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a"
   integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=
 
-resolve@^1.1.5, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.10.1, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.17.0, resolve@^1.18.1, resolve@^1.2.0, resolve@^1.3.2, resolve@^1.4.0:
-  version "1.19.0"
-  resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.19.0.tgz#1af5bf630409734a067cae29318aac7fa29a267c"
-  integrity sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==
+resolve@^1.1.7, resolve@^1.10.0, resolve@^1.10.1, resolve@^1.12.0, resolve@^1.14.2, resolve@^1.17.0, resolve@^1.18.1, resolve@^1.2.0, resolve@^1.20.0:
+  version "1.20.0"
+  resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975"
+  integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==
   dependencies:
-    is-core-module "^2.1.0"
+    is-core-module "^2.2.0"
     path-parse "^1.0.6"
 
-restore-cursor@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf"
-  integrity sha1-n37ih/gv0ybU/RYpI9YhKe7g368=
-  dependencies:
-    onetime "^2.0.0"
-    signal-exit "^3.0.2"
-
 restore-cursor@^3.1.0:
   version "3.1.0"
   resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e"
@@ -10326,7 +9222,7 @@ rgba-regex@^1.0.0:
   resolved "https://registry.yarnpkg.com/rgba-regex/-/rgba-regex-1.0.0.tgz#43374e2e2ca0968b0ef1523460b7d730ff22eeb3"
   integrity sha1-QzdOLiyglosO8VI0YLfXMP8i7rM=
 
-rimraf@^2.5.4, rimraf@^2.6.2, rimraf@^2.6.3, rimraf@^2.7.1:
+rimraf@^2.5.4, rimraf@^2.6.2, rimraf@^2.6.3:
   version "2.7.1"
   resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec"
   integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==
@@ -10359,9 +9255,11 @@ run-async@^2.4.0:
   integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==
 
 run-parallel@^1.1.9:
-  version "1.1.10"
-  resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.1.10.tgz#60a51b2ae836636c81377df16cb107351bcd13ef"
-  integrity sha512-zb/1OuZ6flOlH6tQyMPUrE3x3Ulxjlo9WIVXR4yVYi4H9UXQaeIsPbLn2R3O3vQCnDKkAl2qHiuocKKX4Tz/Sw==
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee"
+  integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==
+  dependencies:
+    queue-microtask "^1.2.2"
 
 run-queue@^1.0.0, run-queue@^1.0.3:
   version "1.0.3"
@@ -10370,15 +9268,10 @@ run-queue@^1.0.0, run-queue@^1.0.3:
   dependencies:
     aproba "^1.1.1"
 
-rw@1:
-  version "1.3.3"
-  resolved "https://registry.yarnpkg.com/rw/-/rw-1.3.3.tgz#3f862dfa91ab766b14885ef4d01124bfda074fb4"
-  integrity sha1-P4Yt+pGrdmsUiF700BEkv9oHT7Q=
-
-rxjs@^6.5.4, rxjs@^6.6.0:
-  version "6.6.3"
-  resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.3.tgz#8ca84635c4daa900c0d3967a6ee7ac60271ee552"
-  integrity sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ==
+rxjs@^6.6.0:
+  version "6.6.7"
+  resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9"
+  integrity sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==
   dependencies:
     tslib "^1.9.0"
 
@@ -10406,7 +9299,7 @@ safe-regex@^2.1.1:
   dependencies:
     regexp-tree "~0.1.1"
 
-"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0:
+"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.1.0:
   version "2.1.2"
   resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
   integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
@@ -10426,37 +9319,30 @@ sane@^4.0.3:
     minimist "^1.1.1"
     walker "~1.0.5"
 
-sass-loader@^8.0.2:
-  version "8.0.2"
-  resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-8.0.2.tgz#debecd8c3ce243c76454f2e8290482150380090d"
-  integrity sha512-7o4dbSK8/Ol2KflEmSco4jTjQoV988bM82P9CZdmo9hR3RLnvNc0ufMNdMrB0caq38JQ/FgF4/7RcbcfKzxoFQ==
+sass-loader@^10.2.0:
+  version "10.2.0"
+  resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-10.2.0.tgz#3d64c1590f911013b3fa48a0b22a83d5e1494716"
+  integrity sha512-kUceLzC1gIHz0zNJPpqRsJyisWatGYNFRmv2CKZK2/ngMJgLqxTbXwe/hJ85luyvZkgqU3VlJ33UVF2T/0g6mw==
   dependencies:
-    clone-deep "^4.0.1"
-    loader-utils "^1.2.3"
-    neo-async "^2.6.1"
-    schema-utils "^2.6.1"
-    semver "^6.3.0"
+    klona "^2.0.4"
+    loader-utils "^2.0.0"
+    neo-async "^2.6.2"
+    schema-utils "^3.0.0"
+    semver "^7.3.2"
 
-sass@^1.26.5:
-  version "1.32.0"
-  resolved "https://registry.yarnpkg.com/sass/-/sass-1.32.0.tgz#10101a026c13080b14e2b374d4e15ee24400a4d3"
-  integrity sha512-fhyqEbMIycQA4blrz/C0pYhv2o4x2y6FYYAH0CshBw3DXh5D5wyERgxw0ptdau1orc/GhNrhF7DFN2etyOCEng==
+sass@~1.32.13:
+  version "1.32.13"
+  resolved "https://registry.yarnpkg.com/sass/-/sass-1.32.13.tgz#8d29c849e625a415bce71609c7cf95e15f74ed00"
+  integrity sha512-dEgI9nShraqP7cXQH+lEXVf73WOPCse0QlFzSD8k+1TcOxCMwVXfQlr0jtoluZysQOyJGnfr21dLvYKDJq8HkA==
   dependencies:
-    chokidar ">=2.0.0 <4.0.0"
+    chokidar ">=3.0.0 <4.0.0"
 
 sax@~1.2.4:
   version "1.2.4"
   resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
   integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==
 
-saxes@^3.1.9:
-  version "3.1.11"
-  resolved "https://registry.yarnpkg.com/saxes/-/saxes-3.1.11.tgz#d59d1fd332ec92ad98a2e0b2ee644702384b1c5b"
-  integrity sha512-Ydydq3zC+WYDJK1+gRxRapLIED9PWeSuuS41wqyoRmzvhhh9nc+QQrVMKJYzJFULazeGhzSV0QleN2wD3boh2g==
-  dependencies:
-    xmlchars "^2.1.1"
-
-saxes@^5.0.0:
+saxes@^5.0.1:
   version "5.0.1"
   resolved "https://registry.yarnpkg.com/saxes/-/saxes-5.0.1.tgz#eebab953fa3b7608dbe94e5dadb15c888fa6696d"
   integrity sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==
@@ -10472,7 +9358,7 @@ schema-utils@^1.0.0:
     ajv-errors "^1.0.0"
     ajv-keywords "^3.1.0"
 
-schema-utils@^2.0.0, schema-utils@^2.5.0, schema-utils@^2.6.1, schema-utils@^2.6.5, schema-utils@^2.6.6, schema-utils@^2.7.0:
+schema-utils@^2.0.0, schema-utils@^2.6.5, schema-utils@^2.7.1:
   version "2.7.1"
   resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.1.tgz#1ca4f32d1b24c590c203b8e7a50bf0ea4cd394d7"
   integrity sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==
@@ -10482,15 +9368,20 @@ schema-utils@^2.0.0, schema-utils@^2.5.0, schema-utils@^2.6.1, schema-utils@^2.6
     ajv-keywords "^3.5.2"
 
 schema-utils@^3.0.0:
-  version "3.0.0"
-  resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.0.0.tgz#67502f6aa2b66a2d4032b4279a2944978a0913ef"
-  integrity sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==
+  version "3.1.1"
+  resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.1.1.tgz#bc74c4b6b6995c1d88f76a8b77bea7219e0c8281"
+  integrity sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==
   dependencies:
-    "@types/json-schema" "^7.0.6"
+    "@types/json-schema" "^7.0.8"
     ajv "^6.12.5"
     ajv-keywords "^3.5.2"
 
-"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0:
+scule@^0.2.1:
+  version "0.2.1"
+  resolved "https://registry.yarnpkg.com/scule/-/scule-0.2.1.tgz#0c1dc847b18e07219ae9a3832f2f83224e2079dc"
+  integrity sha512-M9gnWtn3J0W+UhJOHmBxBTwv8mZCan5i1Himp60t6vvZcor0wr+IM0URKmIglsWJ7bRujNAVVN77fp+uZaWoKg==
+
+"semver@2 || 3 || 4 || 5", semver@^5.5.0, semver@^5.6.0:
   version "5.7.1"
   resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
   integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
@@ -10500,15 +9391,15 @@ semver@7.0.0:
   resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e"
   integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==
 
-semver@^6.0.0, semver@^6.1.0, semver@^6.3.0:
+semver@^6.0.0, semver@^6.1.0, semver@^6.1.1, semver@^6.1.2, semver@^6.3.0:
   version "6.3.0"
   resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
   integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
 
-semver@^7.2.1, semver@^7.3.2, semver@^7.3.4:
-  version "7.3.4"
-  resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.4.tgz#27aaa7d2e4ca76452f98d3add093a72c943edc97"
-  integrity sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==
+semver@^7.2.1, semver@^7.3.2, semver@^7.3.5:
+  version "7.3.5"
+  resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7"
+  integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==
   dependencies:
     lru-cache "^6.0.0"
 
@@ -10552,19 +9443,14 @@ serialize-javascript@^5.0.1:
   dependencies:
     randombytes "^2.1.0"
 
-serialize-to-js@^3.0.0:
-  version "3.1.1"
-  resolved "https://registry.yarnpkg.com/serialize-to-js/-/serialize-to-js-3.1.1.tgz#b3e77d0568ee4a60bfe66287f991e104d3a1a4ac"
-  integrity sha512-F+NGU0UHMBO4Q965tjw7rvieNVjlH6Lqi2emq/Lc9LUURYJbiCzmpi4Cy1OOjjVPtxu0c+NE85LU6968Wko5ZA==
-
-serve-placeholder@^1.2.2:
-  version "1.2.3"
-  resolved "https://registry.yarnpkg.com/serve-placeholder/-/serve-placeholder-1.2.3.tgz#d2e778c6fedfe6e6ca48aff0b4627bbe2c4aa2ca"
-  integrity sha512-DC7t66WeIrlVzVMzickfHIn1zHu7eMsVNiH0nkD/wCrijFQdvgyfH2zc5lkFf79EApUgRhZntkpKjfgLkn2i/Q==
+serve-placeholder@^1.2.3:
+  version "1.2.4"
+  resolved "https://registry.yarnpkg.com/serve-placeholder/-/serve-placeholder-1.2.4.tgz#513eac9c435272c7fe9a86612c852ae9b1467fd4"
+  integrity sha512-jWD9cZXLcr4vHTTL5KEPIUBUYyOWN/z6v/tn0l6XxFhi9iqV3Fc5Y1aFeduUyz+cx8sALzGCUczkPfeOlrq9jg==
   dependencies:
-    defu "^3.2.2"
+    defu "^5.0.0"
 
-serve-static@1.14.1, serve-static@^1.12.4, serve-static@^1.14.1:
+serve-static@^1.14.1:
   version "1.14.1"
   resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.1.tgz#666e636dc4f010f7ef29970a88a674320898b2f9"
   integrity sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==
@@ -10612,18 +9498,6 @@ sha.js@^2.4.0, sha.js@^2.4.8:
     inherits "^2.0.1"
     safe-buffer "^5.0.1"
 
-shallow-clone@^3.0.0:
-  version "3.0.1"
-  resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3"
-  integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==
-  dependencies:
-    kind-of "^6.0.2"
-
-shallow-copy@~0.0.1:
-  version "0.0.1"
-  resolved "https://registry.yarnpkg.com/shallow-copy/-/shallow-copy-0.0.1.tgz#415f42702d73d810330292cc5ee86eae1a11a170"
-  integrity sha1-QV9CcC1z2BAzApLMXuhurhoRoXA=
-
 shebang-command@^1.2.0:
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
@@ -10658,6 +9532,15 @@ shellwords@^0.1.1:
   resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b"
   integrity sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==
 
+side-channel@^1.0.4:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf"
+  integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==
+  dependencies:
+    call-bind "^1.0.0"
+    get-intrinsic "^1.0.2"
+    object-inspect "^1.9.0"
+
 sigmund@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590"
@@ -10675,6 +9558,15 @@ simple-swizzle@^0.2.2:
   dependencies:
     is-arrayish "^0.3.1"
 
+sirv@^1.0.7:
+  version "1.0.17"
+  resolved "https://registry.yarnpkg.com/sirv/-/sirv-1.0.17.tgz#86e2c63c612da5a1dace1c16c46f524aaa26ac45"
+  integrity sha512-qx9go5yraB7ekT7bCMqUHJ5jEaOC/GXBxUWv+jeWnb7WzHUFdcQPGWk7YmAwFBaQBrogpuSqd/azbC2lZRqqmw==
+  dependencies:
+    "@polka/url" "^1.0.0-next.20"
+    mime "^2.3.1"
+    totalist "^1.0.0"
+
 sisteransi@^1.0.5:
   version "1.0.5"
   resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed"
@@ -10754,7 +9646,7 @@ source-map-resolve@^0.5.0, source-map-resolve@^0.5.2:
     source-map-url "^0.4.0"
     urix "^0.1.0"
 
-source-map-support@^0.5.6, source-map-support@~0.5.10, source-map-support@~0.5.12:
+source-map-support@^0.5.6, source-map-support@~0.5.12, source-map-support@~0.5.19:
   version "0.5.19"
   resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61"
   integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==
@@ -10763,26 +9655,26 @@ source-map-support@^0.5.6, source-map-support@~0.5.10, source-map-support@~0.5.1
     source-map "^0.6.0"
 
 source-map-url@^0.4.0:
-  version "0.4.0"
-  resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3"
-  integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=
+  version "0.4.1"
+  resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.1.tgz#0af66605a745a5a2f91cf1bbf8a7afbc283dec56"
+  integrity sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==
 
 source-map@0.5.6:
   version "0.5.6"
   resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412"
   integrity sha1-dc449SvwczxafwwRjYEzSiu19BI=
 
-source-map@0.6.1, source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1:
-  version "0.6.1"
-  resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
-  integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
-
 source-map@^0.5.0, source-map@^0.5.6:
   version "0.5.7"
   resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
   integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=
 
-source-map@^0.7.3:
+source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1:
+  version "0.6.1"
+  resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
+  integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
+
+source-map@^0.7.3, source-map@~0.7.2:
   version "0.7.3"
   resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383"
   integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==
@@ -10809,9 +9701,14 @@ spdx-expression-parse@^3.0.0:
     spdx-license-ids "^3.0.0"
 
 spdx-license-ids@^3.0.0:
-  version "3.0.7"
-  resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.7.tgz#e9c18a410e5ed7e12442a549fbd8afa767038d65"
-  integrity sha512-U+MTEOO0AiDzxwFvoa4JVnMV6mZlJKk2sBLt90s7G0Gd0Mlknc7kxEn3nuDPNZRta7O2uy8oLcZLVT+4sqNZHQ==
+  version "3.0.10"
+  resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.10.tgz#0d9becccde7003d6c658d487dd48a32f0bf3014b"
+  integrity sha512-oie3/+gKf7QtpitB0LYLETe+k8SifzsX4KixvpOsbI6S0kRiRQ5MKOio8eMSAKQ17N06+wdEOXRiId+zOxo0hA==
+
+split-on-first@^1.0.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/split-on-first/-/split-on-first-1.1.0.tgz#f610afeee3b12bce1d0c30425e76398b78249a5f"
+  integrity sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==
 
 split-string@^3.0.1, split-string@^3.0.2:
   version "3.1.0"
@@ -10825,39 +9722,18 @@ sprintf-js@~1.0.2:
   resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
   integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=
 
-srcset@^3.0.0:
-  version "3.0.0"
-  resolved "https://registry.yarnpkg.com/srcset/-/srcset-3.0.0.tgz#8afd8b971362dfc129ae9c1a99b3897301ce6441"
-  integrity sha512-D59vF08Qzu/C4GAOXVgMTLfgryt5fyWo93FZyhEWANo0PokFz/iWdDe13mX3O5TRf6l8vMTqckAfR4zPiaH0yQ==
-
-sshpk@^1.7.0:
-  version "1.16.1"
-  resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877"
-  integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==
-  dependencies:
-    asn1 "~0.2.3"
-    assert-plus "^1.0.0"
-    bcrypt-pbkdf "^1.0.0"
-    dashdash "^1.12.0"
-    ecc-jsbn "~0.1.1"
-    getpass "^0.1.1"
-    jsbn "~0.1.0"
-    safer-buffer "^2.0.2"
-    tweetnacl "~0.14.0"
-
 ssri@^6.0.1:
-  version "6.0.1"
-  resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.1.tgz#2a3c41b28dd45b62b63676ecb74001265ae9edd8"
-  integrity sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==
+  version "6.0.2"
+  resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.2.tgz#157939134f20464e7301ddba3e90ffa8f7728ac5"
+  integrity sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q==
   dependencies:
     figgy-pudding "^3.5.1"
 
-ssri@^7.0.0:
-  version "7.1.0"
-  resolved "https://registry.yarnpkg.com/ssri/-/ssri-7.1.0.tgz#92c241bf6de82365b5c7fb4bd76e975522e1294d"
-  integrity sha512-77/WrDZUWocK0mvA5NTRQyveUf+wsrIc6vyrxpS8tVvYBcX215QbafrJR3KtkpskIzoFLqqNuuYQvxaMjXJ/0g==
+ssri@^8.0.1:
+  version "8.0.1"
+  resolved "https://registry.yarnpkg.com/ssri/-/ssri-8.0.1.tgz#638e4e439e2ffbd2cd289776d5ca457c4f51a2af"
+  integrity sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==
   dependencies:
-    figgy-pudding "^3.5.1"
     minipass "^3.1.1"
 
 stable@^0.1.8:
@@ -10882,13 +9758,6 @@ stackframe@^1.1.1:
   resolved "https://registry.yarnpkg.com/stackframe/-/stackframe-1.2.0.tgz#52429492d63c62eb989804c11552e3d22e779303"
   integrity sha512-GrdeshiRmS1YLMYgzF16olf2jJ/IzxXY9lhKOskuVziubpTYcYqyOwYeJKzQkwy7uN0fYSsbsC4RQaXf9LCrYA==
 
-static-eval@^2.0.0:
-  version "2.1.0"
-  resolved "https://registry.yarnpkg.com/static-eval/-/static-eval-2.1.0.tgz#a16dbe54522d7fa5ef1389129d813fd47b148014"
-  integrity sha512-agtxZ/kWSsCkI5E4QifRwsaPs0P0JmZV6dkLz6ILYfFYQGn+5plctanRN+IC8dJRiFkyXHrwEE3W9Wmx67uDbw==
-  dependencies:
-    escodegen "^1.11.1"
-
 static-extend@^0.1.1:
   version "0.1.2"
   resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6"
@@ -10897,42 +9766,17 @@ static-extend@^0.1.1:
     define-property "^0.2.5"
     object-copy "^0.1.0"
 
-static-module@^2.2.0:
-  version "2.2.5"
-  resolved "https://registry.yarnpkg.com/static-module/-/static-module-2.2.5.tgz#bd40abceae33da6b7afb84a0e4329ff8852bfbbf"
-  integrity sha512-D8vv82E/Kpmz3TXHKG8PPsCPg+RAX6cbCOyvjM6x04qZtQ47EtJFVwRsdov3n5d6/6ynrOY9XB4JkaZwB2xoRQ==
-  dependencies:
-    concat-stream "~1.6.0"
-    convert-source-map "^1.5.1"
-    duplexer2 "~0.1.4"
-    escodegen "~1.9.0"
-    falafel "^2.1.0"
-    has "^1.0.1"
-    magic-string "^0.22.4"
-    merge-source-map "1.0.4"
-    object-inspect "~1.4.0"
-    quote-stream "~1.0.2"
-    readable-stream "~2.3.3"
-    shallow-copy "~0.0.1"
-    static-eval "^2.0.0"
-    through2 "~2.0.3"
-
 "statuses@>= 1.5.0 < 2", statuses@~1.5.0:
   version "1.5.0"
   resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
   integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=
 
-std-env@^2.2.1:
-  version "2.2.1"
-  resolved "https://registry.yarnpkg.com/std-env/-/std-env-2.2.1.tgz#2ffa0fdc9e2263e0004c1211966e960948a40f6b"
-  integrity sha512-IjYQUinA3lg5re/YMlwlfhqNRTzMZMqE+pezevdcTaHceqx8ngEi1alX9nNCk9Sc81fy1fLDeQoaCzeiW1yBOQ==
+std-env@^2.2.1, std-env@^2.3.0:
+  version "2.3.0"
+  resolved "https://registry.yarnpkg.com/std-env/-/std-env-2.3.0.tgz#66d4a4a4d5224242ed8e43f5d65cfa9095216eee"
+  integrity sha512-4qT5B45+Kjef2Z6pE0BkskzsH0GO7GrND0wGlTM1ioUe3v0dGYx9ZJH0Aro/YyA8fqQ5EyIKDRjZojJYMFTflw==
   dependencies:
-    ci-info "^1.6.0"
-
-stealthy-require@^1.1.1:
-  version "1.1.1"
-  resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b"
-  integrity sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=
+    ci-info "^3.0.0"
 
 stream-browserify@^2.0.1:
   version "2.0.2"
@@ -10971,10 +9815,15 @@ strict-uri-encode@^1.0.0:
   resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713"
   integrity sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=
 
+strict-uri-encode@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546"
+  integrity sha1-ucczDHBChi9rFC3CdLvMWGbONUY=
+
 string-length@^4.0.1:
-  version "4.0.1"
-  resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.1.tgz#4a973bf31ef77c4edbceadd6af2611996985f8a1"
-  integrity sha512-PKyXUd0LK0ePjSOnWn34V2uD6acUWev9uy0Ft05k0E8xRW+SKcA0F7eMr7h5xlzfn+4O3N+55rduYyet3Jk+jw==
+  version "4.0.2"
+  resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a"
+  integrity sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==
   dependencies:
     char-regex "^1.0.2"
     strip-ansi "^6.0.0"
@@ -10997,28 +9846,28 @@ string-width@^3.0.0:
     strip-ansi "^5.1.0"
 
 string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0:
-  version "4.2.0"
-  resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5"
-  integrity sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==
+  version "4.2.2"
+  resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.2.tgz#dafd4f9559a7585cfba529c6a0a4f73488ebd4c5"
+  integrity sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==
   dependencies:
     emoji-regex "^8.0.0"
     is-fullwidth-code-point "^3.0.0"
     strip-ansi "^6.0.0"
 
-string.prototype.trimend@^1.0.1:
-  version "1.0.3"
-  resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.3.tgz#a22bd53cca5c7cf44d7c9d5c732118873d6cd18b"
-  integrity sha512-ayH0pB+uf0U28CtjlLvL7NaohvR1amUvVZk+y3DYb0Ey2PUV5zPkkKy9+U1ndVEIXO8hNg18eIv9Jntbii+dKw==
+string.prototype.trimend@^1.0.4:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz#e75ae90c2942c63504686c18b287b4a0b1a45f80"
+  integrity sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==
   dependencies:
-    call-bind "^1.0.0"
+    call-bind "^1.0.2"
     define-properties "^1.1.3"
 
-string.prototype.trimstart@^1.0.1:
-  version "1.0.3"
-  resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.3.tgz#9b4cb590e123bb36564401d59824298de50fd5aa"
-  integrity sha512-oBIBUy5lea5tt0ovtOFiEQaBkoBBkyJhZXzJYrSmDo5IUUqbOPvVezuRs/agBIdZ2p2Eo1FD6bD9USyBLfl3xg==
+string.prototype.trimstart@^1.0.4:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz#b36399af4ab2999b4c9c648bd7a3fb2bb26feeed"
+  integrity sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==
   dependencies:
-    call-bind "^1.0.0"
+    call-bind "^1.0.2"
     define-properties "^1.1.3"
 
 string_decoder@^1.0.0, string_decoder@^1.1.1:
@@ -11035,7 +9884,7 @@ string_decoder@~1.1.1:
   dependencies:
     safe-buffer "~5.1.0"
 
-strip-ansi@^3.0.0:
+strip-ansi@^3.0.0, strip-ansi@^3.0.1:
   version "3.0.1"
   resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf"
   integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=
@@ -11116,14 +9965,7 @@ supports-color@^2.0.0:
   resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
   integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=
 
-supports-color@^3.2.3:
-  version "3.2.3"
-  resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6"
-  integrity sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=
-  dependencies:
-    has-flag "^1.0.0"
-
-supports-color@^5.3.0, supports-color@^5.4.0:
+supports-color@^5.3.0:
   version "5.5.0"
   resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
   integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==
@@ -11145,9 +9987,9 @@ supports-color@^7.0.0, supports-color@^7.1.0:
     has-flag "^4.0.0"
 
 supports-hyperlinks@^2.0.0:
-  version "2.1.0"
-  resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-2.1.0.tgz#f663df252af5f37c5d49bbd7eeefa9e0b9e59e47"
-  integrity sha512-zoE5/e+dnEijk6ASB6/qrK+oYdm2do1hjoLWrqUC/8WEIW1gbxFcKuBof7sW8ArN6e+AYvsE8HBGiVRWL/F5CA==
+  version "2.2.0"
+  resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-2.2.0.tgz#4f77b42488765891774b70c79babd87f9bd594bb"
+  integrity sha512-6sXEzV5+I5j8Bmq9/vUphGRM/RJNT9SCURJLjwfOg51heRtguGWDzcaBlgAzKhQa0EVNpPEKzQuBwZ8S8WaCeQ==
   dependencies:
     has-flag "^4.0.0"
     supports-color "^7.0.0"
@@ -11157,7 +9999,7 @@ svg-tags@^1.0.0:
   resolved "https://registry.yarnpkg.com/svg-tags/-/svg-tags-1.0.0.tgz#58f71cee3bd519b59d4b2a843b6c7de64ac04764"
   integrity sha1-WPcc7jvVGbWdSyqEO2x95krAR2Q=
 
-svgo@^1.0.0, svgo@^1.3.2:
+svgo@^1.0.0:
   version "1.3.2"
   resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.3.2.tgz#b6dc511c063346c9e415b81e43401145b96d4167"
   integrity sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw==
@@ -11176,30 +10018,39 @@ svgo@^1.0.0, svgo@^1.3.2:
     unquote "~1.1.1"
     util.promisify "~1.0.0"
 
-symbol-tree@^3.2.2, symbol-tree@^3.2.4:
+symbol-tree@^3.2.4:
   version "3.2.4"
   resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2"
   integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==
 
-table@^6.0.4:
-  version "6.0.7"
-  resolved "https://registry.yarnpkg.com/table/-/table-6.0.7.tgz#e45897ffbcc1bcf9e8a87bf420f2c9e5a7a52a34"
-  integrity sha512-rxZevLGTUzWna/qBLObOe16kB2RTnnbhciwgPbMMlazz1yZGVEgnZK762xyVdVznhqxrfCeBMmMkgOOaPwjH7g==
+table@^6.0.9:
+  version "6.7.1"
+  resolved "https://registry.yarnpkg.com/table/-/table-6.7.1.tgz#ee05592b7143831a8c94f3cee6aae4c1ccef33e2"
+  integrity sha512-ZGum47Yi6KOOFDE8m223td53ath2enHcYLgOCjGr5ngu8bdIARQk6mN/wRMv4yMRcHnCSnHbCEha4sobQx5yWg==
   dependencies:
-    ajv "^7.0.2"
-    lodash "^4.17.20"
+    ajv "^8.0.1"
+    lodash.clonedeep "^4.5.0"
+    lodash.truncate "^4.4.2"
     slice-ansi "^4.0.0"
     string-width "^4.2.0"
+    strip-ansi "^6.0.0"
 
 tapable@^1.0.0, tapable@^1.0.0-beta.5, tapable@^1.1.3:
   version "1.1.3"
   resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2"
   integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==
 
-term-size@^2.1.0:
-  version "2.2.1"
-  resolved "https://registry.yarnpkg.com/term-size/-/term-size-2.2.1.tgz#2a6a54840432c2fb6320fea0f415531e90189f54"
-  integrity sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==
+tar@^6.0.2:
+  version "6.1.11"
+  resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.11.tgz#6760a38f003afa1b2ffd0ffe9e9abbd0eab3d621"
+  integrity sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==
+  dependencies:
+    chownr "^2.0.0"
+    fs-minipass "^2.0.0"
+    minipass "^3.0.0"
+    minizlib "^2.1.1"
+    mkdirp "^1.0.3"
+    yallist "^4.0.0"
 
 terminal-link@^2.0.0:
   version "2.1.1"
@@ -11224,31 +10075,22 @@ terser-webpack-plugin@^1.4.3:
     webpack-sources "^1.4.0"
     worker-farm "^1.7.0"
 
-terser-webpack-plugin@^2.3.5:
-  version "2.3.8"
-  resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-2.3.8.tgz#894764a19b0743f2f704e7c2a848c5283a696724"
-  integrity sha512-/fKw3R+hWyHfYx7Bv6oPqmk4HGQcrWLtV3X6ggvPuwPNHSnzvVV51z6OaaCOus4YLjutYGOz3pEpbhe6Up2s1w==
+terser-webpack-plugin@^4.2.3:
+  version "4.2.3"
+  resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-4.2.3.tgz#28daef4a83bd17c1db0297070adc07fc8cfc6a9a"
+  integrity sha512-jTgXh40RnvOrLQNgIkwEKnQ8rmHjHK4u+6UBEi+W+FPmvb+uo+chJXntKe7/3lW5mNysgSWD60KyesnhW8D6MQ==
   dependencies:
-    cacache "^13.0.1"
+    cacache "^15.0.5"
     find-cache-dir "^3.3.1"
-    jest-worker "^25.4.0"
-    p-limit "^2.3.0"
-    schema-utils "^2.6.6"
-    serialize-javascript "^4.0.0"
+    jest-worker "^26.5.0"
+    p-limit "^3.0.2"
+    schema-utils "^3.0.0"
+    serialize-javascript "^5.0.1"
     source-map "^0.6.1"
-    terser "^4.6.12"
+    terser "^5.3.4"
     webpack-sources "^1.4.3"
 
-terser@^3.7.3:
-  version "3.17.0"
-  resolved "https://registry.yarnpkg.com/terser/-/terser-3.17.0.tgz#f88ffbeda0deb5637f9d24b0da66f4e15ab10cb2"
-  integrity sha512-/FQzzPJmCpjAH9Xvk2paiWrFq+5M6aVOf+2KRbwhByISDX/EujxsK+BAvrhb6H+2rtrLCHK9N01wO014vrIwVQ==
-  dependencies:
-    commander "^2.19.0"
-    source-map "~0.6.1"
-    source-map-support "~0.5.10"
-
-terser@^4.1.2, terser@^4.6.12, terser@^4.6.3, terser@^4.8.0:
+terser@^4.1.2, terser@^4.6.3:
   version "4.8.0"
   resolved "https://registry.yarnpkg.com/terser/-/terser-4.8.0.tgz#63056343d7c70bb29f3af665865a46fe03a0df17"
   integrity sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==
@@ -11257,6 +10099,15 @@ terser@^4.1.2, terser@^4.6.12, terser@^4.6.3, terser@^4.8.0:
     source-map "~0.6.1"
     source-map-support "~0.5.12"
 
+terser@^5.3.4:
+  version "5.7.2"
+  resolved "https://registry.yarnpkg.com/terser/-/terser-5.7.2.tgz#d4d95ed4f8bf735cb933e802f2a1829abf545e3f"
+  integrity sha512-0Omye+RD4X7X69O0eql3lC4Heh/5iLj3ggxR/B5ketZLOtLiOqukUgjw3q4PDnNQbsrkKr3UMypqStQG3XKRvw==
+  dependencies:
+    commander "^2.20.0"
+    source-map "~0.7.2"
+    source-map-support "~0.5.19"
+
 test-exclude@^6.0.0:
   version "6.0.0"
   resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e"
@@ -11271,21 +10122,23 @@ text-table@^0.2.0:
   resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
   integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=
 
-thread-loader@^2.1.3:
-  version "2.1.3"
-  resolved "https://registry.yarnpkg.com/thread-loader/-/thread-loader-2.1.3.tgz#cbd2c139fc2b2de6e9d28f62286ab770c1acbdda"
-  integrity sha512-wNrVKH2Lcf8ZrWxDF/khdlLlsTMczdcwPA9VEK4c2exlEPynYWxi9op3nPTo5lAnDIkE0rQEB3VBP+4Zncc9Hg==
+thread-loader@^3.0.4:
+  version "3.0.4"
+  resolved "https://registry.yarnpkg.com/thread-loader/-/thread-loader-3.0.4.tgz#c392e4c0241fbc80430eb680e4886819b504a31b"
+  integrity sha512-ByaL2TPb+m6yArpqQUZvP+5S1mZtXsEP7nWKKlAUTm7fCml8kB5s1uI3+eHRP2bk5mVYfRSBI7FFf+tWEyLZwA==
   dependencies:
-    loader-runner "^2.3.1"
-    loader-utils "^1.1.0"
-    neo-async "^2.6.0"
+    json-parse-better-errors "^1.0.2"
+    loader-runner "^4.1.0"
+    loader-utils "^2.0.0"
+    neo-async "^2.6.2"
+    schema-utils "^3.0.0"
 
 throat@^5.0.0:
   version "5.0.0"
   resolved "https://registry.yarnpkg.com/throat/-/throat-5.0.0.tgz#c5199235803aad18754a667d659b5e72ce16764b"
   integrity sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==
 
-through2@^2.0.0, through2@~2.0.3:
+through2@^2.0.0:
   version "2.0.5"
   resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd"
   integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==
@@ -11315,11 +10168,6 @@ timsort@^0.3.0:
   resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4"
   integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=
 
-tiny-inflate@^1.0.0:
-  version "1.0.3"
-  resolved "https://registry.yarnpkg.com/tiny-inflate/-/tiny-inflate-1.0.3.tgz#122715494913a1805166aaf7c93467933eea26c4"
-  integrity sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==
-
 tmp@^0.0.33:
   version "0.0.33"
   resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
@@ -11384,46 +10232,36 @@ toidentifier@1.0.0:
   resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553"
   integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==
 
-tough-cookie@^2.3.3, tough-cookie@^2.5.0, tough-cookie@~2.5.0:
-  version "2.5.0"
-  resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2"
-  integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==
-  dependencies:
-    psl "^1.1.28"
-    punycode "^2.1.1"
+totalist@^1.0.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/totalist/-/totalist-1.1.0.tgz#a4d65a3e546517701e3e5c37a47a70ac97fe56df"
+  integrity sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g==
 
-tough-cookie@^3.0.1:
-  version "3.0.1"
-  resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-3.0.1.tgz#9df4f57e739c26930a018184887f4adb7dca73b2"
-  integrity sha512-yQyJ0u4pZsv9D4clxO69OEjLWYw+jbgspjTue4lTQZLfV0c5l1VmK2y1JK8E9ahdpltPOaAThPcp5nKPUgSnsg==
+tough-cookie@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.0.0.tgz#d822234eeca882f991f0f908824ad2622ddbece4"
+  integrity sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg==
   dependencies:
-    ip-regex "^2.1.0"
-    psl "^1.1.28"
+    psl "^1.1.33"
     punycode "^2.1.1"
+    universalify "^0.1.2"
 
-tr46@^1.0.1:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/tr46/-/tr46-1.0.1.tgz#a8b13fd6bfd2489519674ccde55ba3693b706d09"
-  integrity sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=
-  dependencies:
-    punycode "^2.1.0"
-
-tr46@^2.0.2:
-  version "2.0.2"
-  resolved "https://registry.yarnpkg.com/tr46/-/tr46-2.0.2.tgz#03273586def1595ae08fedb38d7733cee91d2479"
-  integrity sha512-3n1qG+/5kg+jrbTzwAykB5yRYtQCTqOGKq5U5PE3b0a1/mzo6snDhjGS0zJVJunO0NrT3Dg1MLy5TjWP/UJppg==
+tr46@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/tr46/-/tr46-2.1.0.tgz#fa87aa81ca5d5941da8cbf1f9b749dc969a4e240"
+  integrity sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==
   dependencies:
     punycode "^2.1.1"
 
-tryer@^1.0.1:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/tryer/-/tryer-1.0.1.tgz#f2c85406800b9b0f74c9f7465b81eaad241252f8"
-  integrity sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA==
+ts-pnp@^1.1.6:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/ts-pnp/-/ts-pnp-1.2.0.tgz#a500ad084b0798f1c3071af391e65912c86bca92"
+  integrity sha512-csd+vJOb/gkzvcCHgTGSChYpy5f1/XKNsmvBGO4JXS+z1v2HobugDz4s1IeFXM3wZB44uczs+eazB5Q/ccdhQw==
 
 tsconfig-paths@^3.9.0:
-  version "3.9.0"
-  resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz#098547a6c4448807e8fcb8eae081064ee9a3c90b"
-  integrity sha512-dRcuzokWhajtZWkQsDVKbWyY+jgcLC5sqJhg2PSgf4ZkH2aHPvaOY8YWGhmjb68b5qqTfasSsDO9k7RUiEmZAw==
+  version "3.11.0"
+  resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.11.0.tgz#954c1fe973da6339c78e06b03ce2e48810b65f36"
+  integrity sha512-7ecdYDnIdmv639mmDwslG6KQg1Z9STTz1j7Gcz0xa+nshh/gKDAHcPxRbWOsA3SPp0tXP2leTcY9Kw+NAkfZzA==
   dependencies:
     "@types/json5" "^0.0.29"
     json5 "^1.0.1"
@@ -11440,46 +10278,20 @@ tsconfig@^7.0.0:
     strip-bom "^3.0.0"
     strip-json-comments "^2.0.0"
 
-tslib@^1.8.0, tslib@^1.8.1, tslib@^1.9.0:
+tslib@^1.8.1, tslib@^1.9.0:
   version "1.14.1"
   resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
   integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
 
 tslib@^2.0.3:
-  version "2.0.3"
-  resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.0.3.tgz#8e0741ac45fc0c226e58a17bfc3e64b9bc6ca61c"
-  integrity sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==
-
-tslint@^5.20.1:
-  version "5.20.1"
-  resolved "https://registry.yarnpkg.com/tslint/-/tslint-5.20.1.tgz#e401e8aeda0152bc44dd07e614034f3f80c67b7d"
-  integrity sha512-EcMxhzCFt8k+/UP5r8waCf/lzmeSyVlqxqMEDQE7rWYiQky8KpIBz1JAoYXfROHrPZ1XXd43q8yQnULOLiBRQg==
-  dependencies:
-    "@babel/code-frame" "^7.0.0"
-    builtin-modules "^1.1.1"
-    chalk "^2.3.0"
-    commander "^2.12.1"
-    diff "^4.0.1"
-    glob "^7.1.1"
-    js-yaml "^3.13.1"
-    minimatch "^3.0.4"
-    mkdirp "^0.5.1"
-    resolve "^1.3.2"
-    semver "^5.3.0"
-    tslib "^1.8.0"
-    tsutils "^2.29.0"
-
-tsutils@^2.29.0:
-  version "2.29.0"
-  resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-2.29.0.tgz#32b488501467acbedd4b85498673a0812aca0b99"
-  integrity sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==
-  dependencies:
-    tslib "^1.8.1"
+  version "2.3.1"
+  resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01"
+  integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==
 
 tsutils@^3.17.1:
-  version "3.18.0"
-  resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.18.0.tgz#38add50a28ec97e988cb43c5b32e55d1ff4a222a"
-  integrity sha512-D9Tu8nE3E7D1Bsf/V29oMHceMf+gnVO+pDguk/A5YRo1cLpkiQ48ZnbbS57pvvHeY+OIeNQx1vf4ASPlEtRpcA==
+  version "3.21.0"
+  resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623"
+  integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==
   dependencies:
     tslib "^1.8.1"
 
@@ -11488,18 +10300,6 @@ tty-browserify@0.0.0:
   resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6"
   integrity sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=
 
-tunnel-agent@^0.6.0:
-  version "0.6.0"
-  resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd"
-  integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=
-  dependencies:
-    safe-buffer "^5.0.1"
-
-tweetnacl@^0.14.3, tweetnacl@~0.14.0:
-  version "0.14.5"
-  resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
-  integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=
-
 type-check@^0.4.0, type-check@~0.4.0:
   version "0.4.0"
   resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1"
@@ -11519,10 +10319,15 @@ type-detect@4.0.8:
   resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c"
   integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==
 
-type-fest@^0.11.0:
-  version "0.11.0"
-  resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.11.0.tgz#97abf0872310fed88a5c466b25681576145e33f1"
-  integrity sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==
+type-fest@^0.20.2:
+  version "0.20.2"
+  resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4"
+  integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==
+
+type-fest@^0.21.3:
+  version "0.21.3"
+  resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37"
+  integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==
 
 type-fest@^0.6.0:
   version "0.6.0"
@@ -11534,7 +10339,7 @@ type-fest@^0.8.0, type-fest@^0.8.1:
   resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d"
   integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==
 
-type-is@~1.6.17, type-is@~1.6.18:
+type-is@~1.6.17:
   version "1.6.18"
   resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131"
   integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==
@@ -11554,30 +10359,30 @@ typedarray@^0.0.6:
   resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
   integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
 
-ua-parser-js@^0.7.22:
-  version "0.7.23"
-  resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.23.tgz#704d67f951e13195fbcd3d78818577f5bc1d547b"
-  integrity sha512-m4hvMLxgGHXG3O3fQVAyyAQpZzDOvwnhOTjYz5Xmr7r/+LpkNy3vJXdVRWgd1TkAb7NGROZuSy96CrlNVjA7KA==
+ua-parser-js@^0.7.28:
+  version "0.7.28"
+  resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.28.tgz#8ba04e653f35ce210239c64661685bf9121dec31"
+  integrity sha512-6Gurc1n//gjp9eQNXjD9O3M/sMwVtN5S8Lv9bvOYBfKfDNiIIhqiyi01vMBO45u4zkDE420w/e0se7Vs+sIg+g==
+
+ufo@^0.7.4:
+  version "0.7.9"
+  resolved "https://registry.yarnpkg.com/ufo/-/ufo-0.7.9.tgz#0268e3734b413c9ed6f3510201f42372821b875c"
+  integrity sha512-6t9LrLk3FhqTS+GW3IqlITtfRB5JAVr5MMNjpBECfK827W+Vh5Ilw/LhTcHWrt6b3hkeBvcbjx4Ti7QVFzmcww==
 
 uglify-js@^3.5.1:
-  version "3.12.4"
-  resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.12.4.tgz#93de48bb76bb3ec0fc36563f871ba46e2ee5c7ee"
-  integrity sha512-L5i5jg/SHkEqzN18gQMTWsZk3KelRsfD1wUVNqtq0kzqWQqcJjyL8yc1o8hJgRrWqrAl2mUFbhfznEIoi7zi2A==
+  version "3.14.1"
+  resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.14.1.tgz#e2cb9fe34db9cb4cf7e35d1d26dfea28e09a7d06"
+  integrity sha512-JhS3hmcVaXlp/xSo3PKY5R0JqKs5M3IV+exdLHW99qKvKivPO4Z8qbej6mte17SOPqAOVMjt/XGgWacnFSzM3g==
 
-uncss@^0.17.3:
-  version "0.17.3"
-  resolved "https://registry.yarnpkg.com/uncss/-/uncss-0.17.3.tgz#50fc1eb4ed573ffff763458d801cd86e4d69ea11"
-  integrity sha512-ksdDWl81YWvF/X14fOSw4iu8tESDHFIeyKIeDrK6GEVTQvqJc1WlOEXqostNwOCi3qAj++4EaLsdAgPmUbEyog==
+unbox-primitive@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.1.tgz#085e215625ec3162574dc8859abee78a59b14471"
+  integrity sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==
   dependencies:
-    commander "^2.20.0"
-    glob "^7.1.4"
-    is-absolute-url "^3.0.1"
-    is-html "^1.1.0"
-    jsdom "^14.1.0"
-    lodash "^4.17.15"
-    postcss "^7.0.17"
-    postcss-selector-parser "6.0.2"
-    request "^2.88.0"
+    function-bind "^1.1.1"
+    has-bigints "^1.0.1"
+    has-symbols "^1.0.2"
+    which-boxed-primitive "^1.0.2"
 
 unfetch@^4.2.0:
   version "4.2.0"
@@ -11607,14 +10412,6 @@ unicode-property-aliases-ecmascript@^1.0.4:
   resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz#dd57a99f6207bedff4628abefb94c50db941c8f4"
   integrity sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg==
 
-unicode-trie@^0.3.1:
-  version "0.3.1"
-  resolved "https://registry.yarnpkg.com/unicode-trie/-/unicode-trie-0.3.1.tgz#d671dddd89101a08bac37b6a5161010602052085"
-  integrity sha1-1nHd3YkQGgi6w3tqUWEBBgIFIIU=
-  dependencies:
-    pako "^0.2.5"
-    tiny-inflate "^1.0.0"
-
 union-value@^1.0.0:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847"
@@ -11649,11 +10446,16 @@ unique-slug@^2.0.0:
   dependencies:
     imurmurhash "^0.1.4"
 
-universalify@^0.1.0:
+universalify@^0.1.0, universalify@^0.1.2:
   version "0.1.2"
   resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66"
   integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==
 
+universalify@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717"
+  integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==
+
 unpipe@1.0.0, unpipe@~1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
@@ -11688,9 +10490,9 @@ upper-case@^1.1.1:
   integrity sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=
 
 uri-js@^4.2.2:
-  version "4.4.0"
-  resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.0.tgz#aa714261de793e8a82347a7bcc9ce74e86f28602"
-  integrity sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g==
+  version "4.4.1"
+  resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e"
+  integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==
   dependencies:
     punycode "^2.1.0"
 
@@ -11699,14 +10501,14 @@ urix@^0.1.0:
   resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72"
   integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=
 
-url-loader@^2.3.0:
-  version "2.3.0"
-  resolved "https://registry.yarnpkg.com/url-loader/-/url-loader-2.3.0.tgz#e0e2ef658f003efb8ca41b0f3ffbf76bab88658b"
-  integrity sha512-goSdg8VY+7nPZKUEChZSEtW5gjbS66USIGCeSJ1OVOJ7Yfuh/36YxCwMi5HVEJh6mqUYOoy3NJ0vlOMrWsSHog==
+url-loader@^4.1.1:
+  version "4.1.1"
+  resolved "https://registry.yarnpkg.com/url-loader/-/url-loader-4.1.1.tgz#28505e905cae158cf07c92ca622d7f237e70a4e2"
+  integrity sha512-3BTV812+AVHHOJQO8O5MkWgZ5aosP7GnROJwvzLS9hWDj00lZ6Z0wNak423Lp9PBZN05N+Jk/N5Si8jRAlGyWA==
   dependencies:
-    loader-utils "^1.2.3"
-    mime "^2.4.4"
-    schema-utils "^2.5.0"
+    loader-utils "^2.0.0"
+    mime-types "^2.1.27"
+    schema-utils "^3.0.0"
 
 url@^0.11.0:
   version "0.11.0"
@@ -11768,25 +10570,20 @@ utils-merge@1.0.1:
   resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
   integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=
 
-uuid@^3.3.2:
-  version "3.4.0"
-  resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee"
-  integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==
-
 uuid@^8.3.0:
   version "8.3.2"
   resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2"
   integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==
 
-v8-compile-cache@^2.0.0, v8-compile-cache@^2.0.3:
-  version "2.2.0"
-  resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.2.0.tgz#9471efa3ef9128d2f7c6a7ca39c4dd6b5055b132"
-  integrity sha512-gTpR5XQNKFwOd4clxfnhaqvfqMpqEwr4tOtCyz4MtYZX2JYhfr1JvBFKdS+7K/9rfpZR3VLX+YWBbKoxCgS43Q==
+v8-compile-cache@^2.0.3:
+  version "2.3.0"
+  resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee"
+  integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==
 
 v8-to-istanbul@^7.0.0:
-  version "7.1.0"
-  resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-7.1.0.tgz#5b95cef45c0f83217ec79f8fc7ee1c8b486aee07"
-  integrity sha512-uXUVqNUCLa0AH1vuVxzi+MI4RfxEOKt9pBgKwHbgH7st8Kv2P1m+jvWNnektzBh5QShF3ODgKmUFCf38LnVz1g==
+  version "7.1.2"
+  resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-7.1.2.tgz#30898d1a7fa0c84d225a2c1434fb958f290883c1"
+  integrity sha512-TxNb7YEUwkLXCQYeudi6lgQ/SZrzNO4kMdlqVxaZPUIUjCv6iSSypUQX70kNBSERpQ8fk48+d61FXk+tgqcWow==
   dependencies:
     "@types/istanbul-lib-coverage" "^2.0.1"
     convert-source-map "^1.6.0"
@@ -11806,50 +10603,37 @@ vary@^1.1.2, vary@~1.1.2:
   integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=
 
 vee-validate@^3.3.0:
-  version "3.4.5"
-  resolved "https://registry.yarnpkg.com/vee-validate/-/vee-validate-3.4.5.tgz#96a456c309f7bdb2cce62c3b554f96d893e9f6ae"
-  integrity sha512-ZEcLqOAZzSkMhDvPcTx0xcwVOijFnMW9J+BA20j+rDmo24T8RCCqVQyRwwrDrcWJZV2dRYl/yYNa2GB6UCoBvg==
+  version "3.4.12"
+  resolved "https://registry.yarnpkg.com/vee-validate/-/vee-validate-3.4.12.tgz#a268f34b712ac8a2f951544ff4cc14d9808212f0"
+  integrity sha512-mKYlbLmnKVj6zQ4pWBpOEQhc4rcee+wYy2IuMJEuH4Omx31g62YRVnjO3DMeWz7kAQN8z11UwHTY5s75gAGzRw==
 
 vendors@^1.0.0:
   version "1.0.4"
   resolved "https://registry.yarnpkg.com/vendors/-/vendors-1.0.4.tgz#e2b800a53e7a29b93506c3cf41100d16c4c4ad8e"
   integrity sha512-/juG65kTL4Cy2su4P8HjtkTxk6VmJDiOPBufWniqQ6wknac6jNiXS9vU+hO3wgusiyqWlzTbVHi0dyJqRONg3w==
 
-verror@1.10.0:
-  version "1.10.0"
-  resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400"
-  integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=
-  dependencies:
-    assert-plus "^1.0.0"
-    core-util-is "1.0.2"
-    extsprintf "^1.2.0"
-
-vlq@^0.2.2:
-  version "0.2.3"
-  resolved "https://registry.yarnpkg.com/vlq/-/vlq-0.2.3.tgz#8f3e4328cf63b1540c0d67e1b2778386f8975b26"
-  integrity sha512-DRibZL6DsNhIgYQ+wNdWDL2SL3bKPlVrRiBqV5yuMm++op8W4kGFtaQfCs4KEJn0wBZcHVHJ3eoywX8983k1ow==
-
 vm-browserify@^1.0.1:
   version "1.1.2"
   resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0"
   integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==
 
 vue-client-only@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/vue-client-only/-/vue-client-only-2.0.0.tgz#ddad8d675ee02c761a14229f0e440e219de1da1c"
-  integrity sha512-arhk1wtWAfLsJyxGMoEYhoBowM87/i6HLSG2LH/03Yog6i2d9JEN1peMP0Ceis+/n9DxdenGYZZTxbPPJyHciA==
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/vue-client-only/-/vue-client-only-2.1.0.tgz#1a67a47b8ecacfa86d75830173fffee3bf8a4ee3"
+  integrity sha512-vKl1skEKn8EK9f8P2ZzhRnuaRHLHrlt1sbRmazlvsx6EiC3A8oWF8YCBrMJzoN+W3OnElwIGbVjsx6/xelY1AA==
 
 vue-eslint-parser@^7.0.0:
-  version "7.3.0"
-  resolved "https://registry.yarnpkg.com/vue-eslint-parser/-/vue-eslint-parser-7.3.0.tgz#894085839d99d81296fa081d19643733f23d7559"
-  integrity sha512-n5PJKZbyspD0+8LnaZgpEvNCrjQx1DyDHw8JdWwoxhhC+yRip4TAvSDpXGf9SWX6b0umeB5aR61gwUo6NVvFxw==
+  version "7.11.0"
+  resolved "https://registry.yarnpkg.com/vue-eslint-parser/-/vue-eslint-parser-7.11.0.tgz#214b5dea961007fcffb2ee65b8912307628d0daf"
+  integrity sha512-qh3VhDLeh773wjgNTl7ss0VejY9bMMa0GoDG2fQVyDzRFdiU3L7fw74tWZDHNQXdZqxO3EveQroa9ct39D2nqg==
   dependencies:
     debug "^4.1.1"
-    eslint-scope "^5.0.0"
+    eslint-scope "^5.1.1"
     eslint-visitor-keys "^1.1.0"
     espree "^6.2.1"
-    esquery "^1.0.1"
-    lodash "^4.17.15"
+    esquery "^1.4.0"
+    lodash "^4.17.21"
+    semver "^6.3.0"
 
 vue-hot-reload-api@^2.3.0:
   version "2.3.4"
@@ -11885,10 +10669,10 @@ vue-json-csv@^1.2.12:
     papaparse "^5.3.0"
     vue "^2.6.12"
 
-vue-loader@^15.9.5:
-  version "15.9.6"
-  resolved "https://registry.yarnpkg.com/vue-loader/-/vue-loader-15.9.6.tgz#f4bb9ae20c3a8370af3ecf09b8126d38ffdb6b8b"
-  integrity sha512-j0cqiLzwbeImIC6nVIby2o/ABAWhlppyL/m5oJ67R5MloP0hj/DtFgb0Zmq3J9CG7AJ+AXIvHVnJAPBvrLyuDg==
+vue-loader@^15.9.7:
+  version "15.9.8"
+  resolved "https://registry.yarnpkg.com/vue-loader/-/vue-loader-15.9.8.tgz#4b0f602afaf66a996be1e534fb9609dc4ab10e61"
+  integrity sha512-GwSkxPrihfLR69/dSV3+5CdMQ0D+jXg8Ma1S4nQXKJAznYFX14vHdc/NetQc34Dw+rBbIJyP7JOuVb9Fhprvog==
   dependencies:
     "@vue/component-compiler-utils" "^3.1.0"
     hash-sum "^1.0.2"
@@ -11908,15 +10692,15 @@ vue-no-ssr@^1.1.1:
   resolved "https://registry.yarnpkg.com/vue-no-ssr/-/vue-no-ssr-1.1.1.tgz#875f3be6fb0ae41568a837f3ac1a80eaa137b998"
   integrity sha512-ZMjqRpWabMPqPc7gIrG0Nw6vRf1+itwf0Itft7LbMXs2g3Zs/NFmevjZGN1x7K3Q95GmIjWbQZTVerxiBxI+0g==
 
-vue-router@^3.4.9:
-  version "3.4.9"
-  resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-3.4.9.tgz#c016f42030ae2932f14e4748b39a1d9a0e250e66"
-  integrity sha512-CGAKWN44RqXW06oC+u4mPgHLQQi2t6vLD/JbGRDAXm0YpMv0bgpKuU5bBd7AvMgfTz9kXVRIWKHqRwGEb8xFkA==
+vue-router@^3.5.1:
+  version "3.5.2"
+  resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-3.5.2.tgz#5f55e3f251970e36c3e8d88a7cd2d67a350ade5c"
+  integrity sha512-807gn82hTnjCYGrnF3eNmIw/dk7/GE4B5h69BlyCK9KHASwSloD1Sjcn06zg9fVG4fYH2DrsNBZkpLtb25WtaQ==
 
 vue-server-renderer@^2.6.12:
-  version "2.6.12"
-  resolved "https://registry.yarnpkg.com/vue-server-renderer/-/vue-server-renderer-2.6.12.tgz#a8cb9c49439ef205293cb41c35d0d2b0541653a5"
-  integrity sha512-3LODaOsnQx7iMFTBLjki8xSyOxhCtbZ+nQie0wWY4iOVeEtTg1a3YQAjd82WvKxrWHHTshjvLb7OXMc2/dYuxw==
+  version "2.6.14"
+  resolved "https://registry.yarnpkg.com/vue-server-renderer/-/vue-server-renderer-2.6.14.tgz#c8bffff152df6b47b858818ef8d524d2fc351654"
+  integrity sha512-HifYRa/LW7cKywg9gd4ZtvtRuBlstQBao5ZCWlg40fyB4OPoGfEXAzxb0emSLv4pBDOHYx0UjpqvxpiQFEuoLA==
   dependencies:
     chalk "^1.1.3"
     hash-sum "^1.0.2"
@@ -11927,18 +10711,18 @@ vue-server-renderer@^2.6.12:
     serialize-javascript "^3.1.0"
     source-map "0.5.6"
 
-vue-style-loader@^4.1.0:
-  version "4.1.2"
-  resolved "https://registry.yarnpkg.com/vue-style-loader/-/vue-style-loader-4.1.2.tgz#dedf349806f25ceb4e64f3ad7c0a44fba735fcf8"
-  integrity sha512-0ip8ge6Gzz/Bk0iHovU9XAUQaFt/G2B61bnWa2tCcqqdgfHs1lF9xXorFbE55Gmy92okFT+8bfmySuUOu13vxQ==
+vue-style-loader@^4.1.0, vue-style-loader@^4.1.3:
+  version "4.1.3"
+  resolved "https://registry.yarnpkg.com/vue-style-loader/-/vue-style-loader-4.1.3.tgz#6d55863a51fa757ab24e89d9371465072aa7bc35"
+  integrity sha512-sFuh0xfbtpRlKfm39ss/ikqs9AbKCoXZBpHeVZ8Tx650o0k0q/YCM7FRvigtxpACezfq6af+a7JeqVTWvncqDg==
   dependencies:
     hash-sum "^1.0.2"
     loader-utils "^1.0.2"
 
-vue-template-compiler@^2.6.12:
-  version "2.6.12"
-  resolved "https://registry.yarnpkg.com/vue-template-compiler/-/vue-template-compiler-2.6.12.tgz#947ed7196744c8a5285ebe1233fe960437fcc57e"
-  integrity sha512-OzzZ52zS41YUbkCBfdXShQTe69j1gQDZ9HIX8miuC9C3rBCk9wIRjLiZZLrmX9V+Ftq/YEyv1JaVr5Y/hNtByg==
+vue-template-compiler@^2.6.12, vue-template-compiler@^2.6.14:
+  version "2.6.14"
+  resolved "https://registry.yarnpkg.com/vue-template-compiler/-/vue-template-compiler-2.6.14.tgz#a2f0e7d985670d42c9c9ee0d044fed7690f4f763"
+  integrity sha512-ODQS1SyMbjKoO1JBJZojSw6FE4qnh9rIpUZn2EUT86FKizx9uH5z6uXiIrm4/Nb/gwxTi/o17ZDEGWAXHvtC7g==
   dependencies:
     de-indent "^1.0.2"
     he "^1.1.0"
@@ -11949,44 +10733,36 @@ vue-template-es2015-compiler@^1.6.0, vue-template-es2015-compiler@^1.9.0:
   integrity sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==
 
 vue@^2.6.12:
-  version "2.6.12"
-  resolved "https://registry.yarnpkg.com/vue/-/vue-2.6.12.tgz#f5ebd4fa6bd2869403e29a896aed4904456c9123"
-  integrity sha512-uhmLFETqPPNyuLLbsKz6ioJ4q7AZHzD8ZVFNATNyICSZouqP2Sz0rotWQC8UNBF6VGSCs5abnKJoStA6JbCbfg==
+  version "2.6.14"
+  resolved "https://registry.yarnpkg.com/vue/-/vue-2.6.14.tgz#e51aa5250250d569a3fbad3a8a5a687d6036e235"
+  integrity sha512-x2284lgYvjOMj3Za7kqzRcUSxBboHqtgRE2zlos1qWaOye5yUmHn42LB1250NJBLRwEcdrB0JRwyPTEPhfQjiQ==
 
-vuetify-loader@^1.4.3:
-  version "1.6.0"
-  resolved "https://registry.yarnpkg.com/vuetify-loader/-/vuetify-loader-1.6.0.tgz#05df0805b3ab2ff0de198109d34f9da3f69da667"
-  integrity sha512-1bx3YeZ712dT1+QMX+XSFlP0O5k5O5Ui9ysBBmUZ9bWkAEHWZJQI9soI+qG5qmeFxUC0L9QYMCIKP0hOL/pf3Q==
+vuetify-loader@^1.7.2:
+  version "1.7.3"
+  resolved "https://registry.yarnpkg.com/vuetify-loader/-/vuetify-loader-1.7.3.tgz#404657f4925c828f400fe3269003421d586835c6"
+  integrity sha512-1Kt6Rfvuw3i9BBlxC9WTMnU3WEU7IBWQmDX+fYGAVGpzWCX7oHythUIwPCZGShHSYcPMKSDbXTPP8UvT5RNw8Q==
   dependencies:
-    file-loader "^4.0.0"
-    loader-utils "^1.2.0"
+    decache "^4.6.0"
+    file-loader "^6.2.0"
+    loader-utils "^2.0.0"
 
-vuetify@^2:
-  version "2.4.0"
-  resolved "https://registry.yarnpkg.com/vuetify/-/vuetify-2.4.0.tgz#6aa2616b0fecb0614cf85052b0ffbb5cad80bf92"
-  integrity sha512-FBFAtg1ZnNwDBhMzENCzgh0hBV+HMjXejrxeRQqTfKPojKQSQFswtdHatUPmlkArDulZC73GRs2F/IwdF48o5g==
+vuetify@^2.5.3:
+  version "2.5.8"
+  resolved "https://registry.yarnpkg.com/vuetify/-/vuetify-2.5.8.tgz#a23e6a7e77b77de0744b53cf1e7c9d40efac0635"
+  integrity sha512-paLmNhKTYFD41+14rIHnCo+P1jHbUzwBiMowxs5qXVq8RdRMqRmcy05Sfse1WUu90amPGK2fIFQq5rL2N8zqZg==
 
-vuex@^3.6.0:
-  version "3.6.0"
-  resolved "https://registry.yarnpkg.com/vuex/-/vuex-3.6.0.tgz#95efa56a58f7607c135b053350833a09e01aa813"
-  integrity sha512-W74OO2vCJPs9/YjNjW8lLbj+jzT24waTo2KShI8jLvJW8OaIkgb3wuAMA7D+ZiUxDOx3ubwSZTaJBip9G8a3aQ==
+vuex@^3.6.2:
+  version "3.6.2"
+  resolved "https://registry.yarnpkg.com/vuex/-/vuex-3.6.2.tgz#236bc086a870c3ae79946f107f16de59d5895e71"
+  integrity sha512-ETW44IqCgBpVomy520DT5jf8n0zoCac+sxWnn+hMe/CzaSejb/eVw2YToiXYX+Ex/AuHHia28vWTq4goAexFbw==
 
-w3c-hr-time@^1.0.1, w3c-hr-time@^1.0.2:
+w3c-hr-time@^1.0.2:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz#0a89cdf5cc15822df9c360543676963e0cc308cd"
   integrity sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==
   dependencies:
     browser-process-hrtime "^1.0.0"
 
-w3c-xmlserializer@^1.1.2:
-  version "1.1.2"
-  resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-1.1.2.tgz#30485ca7d70a6fd052420a3d12fd90e6339ce794"
-  integrity sha512-p10l/ayESzrBMYWRID6xbuCKh2Fp77+sA0doRuGn4tTIMrrZVeqfpKjXHY+oDh3K4nLdPgNwMTVP6Vp4pvqbNg==
-  dependencies:
-    domexception "^1.0.1"
-    webidl-conversions "^4.0.2"
-    xml-name-validator "^3.0.0"
-
 w3c-xmlserializer@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz#3e7104a05b75146cc60f564380b7f683acf1020a"
@@ -12019,18 +10795,6 @@ watchpack@^1.7.4:
     chokidar "^3.4.1"
     watchpack-chokidar2 "^2.0.1"
 
-wcwidth@^1.0.1:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8"
-  integrity sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=
-  dependencies:
-    defaults "^1.0.3"
-
-webidl-conversions@^4.0.2:
-  version "4.0.2"
-  resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad"
-  integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==
-
 webidl-conversions@^5.0.0:
   version "5.0.0"
   resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-5.0.0.tgz#ae59c8a00b121543a2acc65c0434f57b0fc11aff"
@@ -12041,35 +10805,32 @@ webidl-conversions@^6.1.0:
   resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-6.1.0.tgz#9111b4d7ea80acd40f5270d666621afa78b69514"
   integrity sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==
 
-webpack-bundle-analyzer@^3.9.0:
-  version "3.9.0"
-  resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.9.0.tgz#f6f94db108fb574e415ad313de41a2707d33ef3c"
-  integrity sha512-Ob8amZfCm3rMB1ScjQVlbYYUEJyEjdEtQ92jqiFUYt5VkEeO2v5UMbv49P/gnmCZm3A6yaFQzCBvpZqN4MUsdA==
+webpack-bundle-analyzer@^4.4.1:
+  version "4.4.2"
+  resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.4.2.tgz#39898cf6200178240910d629705f0f3493f7d666"
+  integrity sha512-PIagMYhlEzFfhMYOzs5gFT55DkUdkyrJi/SxJp8EF3YMWhS+T9vvs2EoTetpk5qb6VsCq02eXTlRDOydRhDFAQ==
   dependencies:
-    acorn "^7.1.1"
-    acorn-walk "^7.1.1"
-    bfj "^6.1.1"
-    chalk "^2.4.1"
-    commander "^2.18.0"
-    ejs "^2.6.1"
-    express "^4.16.3"
-    filesize "^3.6.1"
-    gzip-size "^5.0.0"
-    lodash "^4.17.19"
-    mkdirp "^0.5.1"
-    opener "^1.5.1"
-    ws "^6.0.0"
+    acorn "^8.0.4"
+    acorn-walk "^8.0.0"
+    chalk "^4.1.0"
+    commander "^6.2.0"
+    gzip-size "^6.0.0"
+    lodash "^4.17.20"
+    opener "^1.5.2"
+    sirv "^1.0.7"
+    ws "^7.3.1"
 
-webpack-dev-middleware@^3.7.2:
-  version "3.7.3"
-  resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-3.7.3.tgz#0639372b143262e2b84ab95d3b91a7597061c2c5"
-  integrity sha512-djelc/zGiz9nZj/U7PTBi2ViorGJXEWo/3ltkPbDyxCXhhEXkW0ce99falaok4TPj+AsxLiXJR0EBOb0zh9fKQ==
+webpack-dev-middleware@^4.2.0:
+  version "4.3.0"
+  resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-4.3.0.tgz#179cc40795882cae510b1aa7f3710cbe93c9333e"
+  integrity sha512-PjwyVY95/bhBh6VUqt6z4THplYcsvQ8YNNBTBM873xLVmw8FLeALn0qurHbs9EmcfhzQis/eoqypSnZeuUz26w==
   dependencies:
-    memory-fs "^0.4.1"
-    mime "^2.4.4"
-    mkdirp "^0.5.1"
+    colorette "^1.2.2"
+    mem "^8.1.1"
+    memfs "^3.2.2"
+    mime-types "^2.1.30"
     range-parser "^1.2.1"
-    webpack-log "^2.0.0"
+    schema-utils "^3.0.0"
 
 webpack-hot-middleware@^2.25.0:
   version "2.25.0"
@@ -12081,18 +10842,10 @@ webpack-hot-middleware@^2.25.0:
     querystring "^0.2.0"
     strip-ansi "^3.0.0"
 
-webpack-log@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/webpack-log/-/webpack-log-2.0.0.tgz#5b7928e0637593f119d32f6227c1e0ac31e1b47f"
-  integrity sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg==
-  dependencies:
-    ansi-colors "^3.0.0"
-    uuid "^3.3.2"
-
-webpack-node-externals@^2.5.2:
-  version "2.5.2"
-  resolved "https://registry.yarnpkg.com/webpack-node-externals/-/webpack-node-externals-2.5.2.tgz#178e017a24fec6015bc9e672c77958a6afac861d"
-  integrity sha512-aHdl/y2N7PW2Sx7K+r3AxpJO+aDMcYzMQd60Qxefq3+EwhewSbTBqNumOsCE1JsCUNoyfGj5465N0sSf6hc/5w==
+webpack-node-externals@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/webpack-node-externals/-/webpack-node-externals-3.0.0.tgz#1a3407c158d547a9feb4229a9e3385b7b60c9917"
+  integrity sha512-LnL6Z3GGDPht/AigwRh2dvL9PQPFQ8skEpVrWZXLWBYmqcaojHNN0onvHzie6rq7EWKrrBfPYqNEzTJgiwEQDQ==
 
 webpack-sources@^1.0.1, webpack-sources@^1.1.0, webpack-sources@^1.4.0, webpack-sources@^1.4.1, webpack-sources@^1.4.3:
   version "1.4.3"
@@ -12102,10 +10855,10 @@ webpack-sources@^1.0.1, webpack-sources@^1.1.0, webpack-sources@^1.4.0, webpack-
     source-list-map "^2.0.0"
     source-map "~0.6.1"
 
-webpack@^4.44.2:
-  version "4.44.2"
-  resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.44.2.tgz#6bfe2b0af055c8b2d1e90ed2cd9363f841266b72"
-  integrity sha512-6KJVGlCxYdISyurpQ0IPTklv+DULv05rs2hseIXer6D7KrUicRDLFb4IUM1S6LUAKypPM/nSiVSuv8jHu1m3/Q==
+webpack@^4.46.0:
+  version "4.46.0"
+  resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.46.0.tgz#bf9b4404ea20a073605e0a011d188d77cb6ad542"
+  integrity sha512-6jJuJjg8znb/xRItk7bkT0+Q7AHCYjjFnvKIWQPkNIOyRqoCGvkOs0ipeQzrqz4l5FtN5ZI/ukEHroeX/o1/5Q==
   dependencies:
     "@webassemblyjs/ast" "1.9.0"
     "@webassemblyjs/helper-module-context" "1.9.0"
@@ -12115,7 +10868,7 @@ webpack@^4.44.2:
     ajv "^6.10.2"
     ajv-keywords "^3.4.1"
     chrome-trace-event "^1.0.2"
-    enhanced-resolve "^4.3.0"
+    enhanced-resolve "^4.5.0"
     eslint-scope "^4.0.3"
     json-parse-better-errors "^1.0.2"
     loader-runner "^2.4.0"
@@ -12145,35 +10898,37 @@ webpackbar@^4.0.0:
     text-table "^0.2.0"
     wrap-ansi "^6.0.0"
 
-whatwg-encoding@^1.0.1, whatwg-encoding@^1.0.5:
+whatwg-encoding@^1.0.5:
   version "1.0.5"
   resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz#5abacf777c32166a51d085d6b4f3e7d27113ddb0"
   integrity sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==
   dependencies:
     iconv-lite "0.4.24"
 
-whatwg-mimetype@^2.2.0, whatwg-mimetype@^2.3.0:
+whatwg-mimetype@^2.3.0:
   version "2.3.0"
   resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf"
   integrity sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==
 
-whatwg-url@^7.0.0:
-  version "7.1.0"
-  resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-7.1.0.tgz#c2c492f1eca612988efd3d2266be1b9fc6170d06"
-  integrity sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==
+whatwg-url@^8.0.0, whatwg-url@^8.5.0:
+  version "8.7.0"
+  resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-8.7.0.tgz#656a78e510ff8f3937bc0bcbe9f5c0ac35941b77"
+  integrity sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==
   dependencies:
-    lodash.sortby "^4.7.0"
-    tr46 "^1.0.1"
-    webidl-conversions "^4.0.2"
+    lodash "^4.7.0"
+    tr46 "^2.1.0"
+    webidl-conversions "^6.1.0"
 
-whatwg-url@^8.0.0:
-  version "8.4.0"
-  resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-8.4.0.tgz#50fb9615b05469591d2b2bd6dfaed2942ed72837"
-  integrity sha512-vwTUFf6V4zhcPkWp/4CQPr1TW9Ml6SF4lVyaIMBdJw5i6qUUJ1QWM4Z6YYVkfka0OUIzVo/0aNtGVGk256IKWw==
+which-boxed-primitive@^1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6"
+  integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==
   dependencies:
-    lodash.sortby "^4.7.0"
-    tr46 "^2.0.2"
-    webidl-conversions "^6.1.0"
+    is-bigint "^1.0.1"
+    is-boolean-object "^1.1.0"
+    is-number-object "^1.0.4"
+    is-string "^1.0.5"
+    is-symbol "^1.0.3"
 
 which-module@^2.0.0:
   version "2.0.0"
@@ -12222,6 +10977,15 @@ wrap-ansi@^6.0.0, wrap-ansi@^6.2.0:
     string-width "^4.1.0"
     strip-ansi "^6.0.0"
 
+wrap-ansi@^7.0.0:
+  version "7.0.0"
+  resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
+  integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
+  dependencies:
+    ansi-styles "^4.0.0"
+    string-width "^4.1.0"
+    strip-ansi "^6.0.0"
+
 wrappy@1:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
@@ -12258,31 +11022,17 @@ write-json-file@^2.3.0:
     sort-keys "^2.0.0"
     write-file-atomic "^2.0.0"
 
-ws@^5.1.1:
-  version "5.2.2"
-  resolved "https://registry.yarnpkg.com/ws/-/ws-5.2.2.tgz#dffef14866b8e8dc9133582514d1befaf96e980f"
-  integrity sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==
-  dependencies:
-    async-limiter "~1.0.0"
-
-ws@^6.0.0, ws@^6.1.2:
-  version "6.2.1"
-  resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.1.tgz#442fdf0a47ed64f59b6a5d8ff130f4748ed524fb"
-  integrity sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==
-  dependencies:
-    async-limiter "~1.0.0"
-
-ws@^7.2.3:
-  version "7.4.2"
-  resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.2.tgz#782100048e54eb36fe9843363ab1c68672b261dd"
-  integrity sha512-T4tewALS3+qsrpGI/8dqNMLIVdq/g/85U98HPMa6F0m6xTbvhXU6RCQLqPH3+SlomNV/LdY6RXEbBpMH6EOJnA==
+ws@^7.3.1, ws@^7.4.6:
+  version "7.5.4"
+  resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.4.tgz#56bfa20b167427e138a7795de68d134fe92e21f9"
+  integrity sha512-zP9z6GXm6zC27YtspwH99T3qTG7bBFv2VIkeHstMLrLlDJuzA7tQ5ls3OJ1hOGGCzTQPniNJoHXIAOS0Jljohg==
 
 xml-name-validator@^3.0.0:
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a"
   integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==
 
-xmlchars@^2.1.1, xmlchars@^2.2.0:
+xmlchars@^2.2.0:
   version "2.2.0"
   resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb"
   integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==
@@ -12300,9 +11050,9 @@ xxhashjs@^0.2.1:
     cuint "^0.2.2"
 
 y18n@^4.0.0:
-  version "4.0.1"
-  resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.1.tgz#8db2b83c31c5d75099bb890b23f3094891e247d4"
-  integrity sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==
+  version "4.0.3"
+  resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf"
+  integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==
 
 yallist@^2.1.2:
   version "2.1.2"
@@ -12343,3 +11093,8 @@ yargs@^15.4.1:
     which-module "^2.0.0"
     y18n "^4.0.0"
     yargs-parser "^18.1.2"
+
+yocto-queue@^0.1.0:
+  version "0.1.0"
+  resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
+  integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==
diff --git a/docker-compose.yml b/docker-compose.yml
index c7b8a4beb42f4f306a50720c615ae904bbf2de31..484d7e13bd11a288be023b579747ae05a402127f 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -99,6 +99,7 @@ services:
     environment:
       HOST: 0.0.0.0
       NODE_ENV: development
+      HOSTLABEL: local
     networks:
       - main
     depends_on:
@@ -154,7 +155,6 @@ services:
 volumes:
   cc-qtl-postgresql-data:
   cc-qtl-django-static:
-  planemo-dir:
   cc-qtl-node-modules:
   cc-qtl-nuxt:
 
diff --git a/package.json b/package.json
deleted file mode 100644
index 8ae5ef9072822b3b68aa0888c69debc2756cdb7a..0000000000000000000000000000000000000000
--- a/package.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
-  "dependencies": {
-    "bioviz-js": "git+https://gitlab.pasteur.fr/rplanel/bioviz-js#cc-qtl"
-  }
-}
diff --git a/server/Dockerfile.cronJob b/server/Dockerfile.cronJob
new file mode 100644
index 0000000000000000000000000000000000000000..bdd0dcf6abd1ffc1469eebb0fc99e799654eca7d
--- /dev/null
+++ b/server/Dockerfile.cronJob
@@ -0,0 +1,11 @@
+FROM alpine:3.15
+
+
+WORKDIR /app
+
+RUN adduser -D -u 1001 -g 1001 -s /bin/bash user
+
+USER user
+
+CMD ["/bin/sh", "-c", "find /app/static/ -maxdepth 1 -name tmp* -mmin +20 -type f -exec rm {} \\; && find /app/static/ -maxdepth 1 -name tmp* -mmin +20 -type d -exec rm -rf {} \\;"]
+
diff --git a/server/api/admin.py b/server/api/admin.py
index a045cbce0473bc7eb27a6828fe253494727edd95..43e6f0d8e68ecab643456e84c2468e1307a20e07 100644
--- a/server/api/admin.py
+++ b/server/api/admin.py
@@ -1,6 +1,6 @@
 from django.contrib import admin
 from django.contrib.auth.admin import UserAdmin
-from .models import Analysis, User, Project, VariableCategory
+from .models import Analysis, User, Project, PhenotypeCategory
 from guardian.admin import GuardedModelAdmin
 
 # Register your models here.
@@ -14,7 +14,7 @@ class AnalysisAdmin(GuardedModelAdmin):
     list_display = ("name", "creation_date")
 
 
-class VariableCategoryAdmin(GuardedModelAdmin):
+class PhenotypeCategoryAdmin(GuardedModelAdmin):
     list_display = (
         "name",
         "description",
@@ -28,4 +28,4 @@ class VariableCategoryAdmin(GuardedModelAdmin):
 admin.site.register(User, UserAdmin)
 admin.site.register(Project, ProjectAdmin)
 admin.site.register(Analysis, AnalysisAdmin)
-admin.site.register(VariableCategory, VariableCategoryAdmin)
+admin.site.register(PhenotypeCategory, PhenotypeCategoryAdmin)
diff --git a/server/api/exceptions.py b/server/api/exceptions.py
index 83548de7d9f0f9f7db934b66cf8b3fbe1c087315..e13791aedfca67cab61f89ed0db68ac36c2e9972 100644
--- a/server/api/exceptions.py
+++ b/server/api/exceptions.py
@@ -6,6 +6,6 @@ class RessourceAlreadyExists(APIException):
     default_detail = "The ressource already exists."
 
 
-class VariableDoesNotExist(APIException):
+class PhenotypeDoesNotExist(APIException):
     status_code = 409
     default_detail = "The ressource already exists."
diff --git a/server/api/factories.py b/server/api/factories.py
index c667bf0555256982a45d0407555032605c60e924..fb84099070de435375a5891f9c6a5d99cc20b863 100644
--- a/server/api/factories.py
+++ b/server/api/factories.py
@@ -14,6 +14,7 @@ from .models import (
     Analysis,
     Experiment,
     Peak,
+    PhenotypeCategory,
     Project,
     Role,
     Team,
@@ -22,7 +23,7 @@ from .models import (
 )
 
 User = get_user_model()
-Faker._DEFAULT_LOCALE = 'fr_FR'
+Faker._DEFAULT_LOCALE = "fr_FR"
 
 USER_PASSWORD = "password"
 
@@ -61,7 +62,7 @@ class UserStaffFactory(DjangoModelFactory):
 class UserFactory(DjangoModelFactory):
     class Meta:
         model = User
-        django_get_or_create = ("username",)
+        django_get_or_create = ("username", "first_name", "last_name")
 
     username = Faker("user_name")
     first_name = Faker("first_name")
@@ -70,7 +71,7 @@ class UserFactory(DjangoModelFactory):
     password = PostGenerationMethodCall("set_password", USER_PASSWORD)
     is_active = True
     is_staff = False
-    email = Faker("email")
+    email = LazyAttribute(lambda obj: '%s@pasteur.fr' % obj.username)
 
 
 class ProjectFactory(DjangoModelFactory):
@@ -98,6 +99,7 @@ class AnalysisFactory(DjangoModelFactory):
 
     name = Faker("word")
     creation_date = Faker("date_time")
+    description = Faker("sentence", nb_words=15)
 
 
 class PeakFactory(DjangoModelFactory):
@@ -157,7 +159,14 @@ class TeamSampleFactory(TeamFactory):
     name = Sequence(lambda n: "Team %d" % n)
 
 
-# class RoleGroupFactory(DjangoModelFactory):
-#     class Meta:
-#         model = RoleGroup
-#         django_get_or_create = ("name", "priority")
+class PhenotypeCategoryFactory(DjangoModelFactory):
+    class Meta:
+        model = PhenotypeCategory
+        django_get_or_create = ("name",)
+
+    name = Faker("word")
+    description = Faker("sentence", nb_words=15)
+    datatype = "Integer"
+    dataclass = "Phenotype"
+    nature = "Quantitative"
+    location = "Organ"
diff --git a/server/api/fixtures/analysis-category.json b/server/api/fixtures/analysis-category.json
new file mode 100644
index 0000000000000000000000000000000000000000..53cd154eec7600ec138f5d89271295e65f50069c
--- /dev/null
+++ b/server/api/fixtures/analysis-category.json
@@ -0,0 +1,9 @@
+[
+  {
+    "model": "api.analysiscategory",
+    "fields": {
+      "name": "cc-qtl",
+      "description": "cc-qtl analysis"
+    }
+  }
+]
diff --git a/server/api/fixtures/galaxy.json b/server/api/fixtures/galaxy.json
new file mode 100644
index 0000000000000000000000000000000000000000..8d1de7a9482630dd393f88f5a769b7ea55110d1d
--- /dev/null
+++ b/server/api/fixtures/galaxy.json
@@ -0,0 +1,37 @@
+[
+  {
+    "model": "api.galaxyinstance",
+    "fields": {
+      "name": "Pasteur",
+      "url": "https://galaxy.pasteur.fr",
+      "description": "Pasteur Galaxy instance"
+    }
+  },
+  {
+    "model": "api.galaxyuser",
+    "fields": {
+      "galaxy_instance": ["Pasteur"],
+      "username": "cc-qtl-galaxy@pasteur.fr"
+    }
+  },
+  {
+    "model": "api.galaxyworkflow",
+    "fields": {
+      "name": "cc-qtl",
+      "galaxy_workflow_id": "657f009ad32a3f27",
+      "version": "0.22_11",
+      "analysis_category": ["cc-qtl"],
+      "galaxy_user": ["cc-qtl-galaxy@pasteur.fr"]
+    }
+  },
+  {
+    "model": "api.galaxyworkflow",
+    "fields": {
+      "name": "cc-qtl",
+      "galaxy_workflow_id": "bd6cadfea4e7afba",
+      "version": "0.24",
+      "analysis_category": ["cc-qtl"],
+      "galaxy_user": ["cc-qtl-galaxy@pasteur.fr"]
+    }
+  }
+]
diff --git a/server/api/fixtures/role-permissions.json b/server/api/fixtures/role-permissions.json
index ea13f69f7d1a244e1ca0e9f542b943555d8e9748..a2c6b953f264bd461f3f8b9e17fb4bb076bc0194 100644
--- a/server/api/fixtures/role-permissions.json
+++ b/server/api/fixtures/role-permissions.json
@@ -27,6 +27,34 @@
       "permission": ["add_project", "api", "project"]
     }
   },
+  {
+    "model": "api.role_permissions",
+    "fields": {
+      "role": ["manager"],
+      "permission": ["add_phenotypecategory", "api", "phenotypecategory"]
+    }
+  },
+  {
+    "model": "api.role_permissions",
+    "fields": {
+      "role": ["manager"],
+      "permission": ["delete_phenotypecategory", "api", "phenotypecategory"]
+    }
+  },
+  {
+    "model": "api.role_permissions",
+    "fields": {
+      "role": ["manager"],
+      "permission": ["view_phenotypecategory", "api", "phenotypecategory"]
+    }
+  },
+  {
+    "model": "api.role_permissions",
+    "fields": {
+      "role": ["manager"],
+      "permission": ["change_phenotypecategory", "api", "phenotypecategory"]
+    }
+  },
   {
     "model": "api.role_permissions",
     "fields": {
@@ -54,5 +82,19 @@
       "role": ["user"],
       "permission": ["add_project", "api", "project"]
     }
+  },
+  {
+    "model": "api.role_permissions",
+    "fields": {
+      "role": ["user"],
+      "permission": ["view_phenotypecategory", "api", "phenotypecategory"]
+    }
+  },
+  {
+    "model": "api.role_permissions",
+    "fields": {
+      "role": ["user"],
+      "permission": ["add_phenotypecategory", "api", "phenotypecategory"]
+    }
   }
 ]
diff --git a/server/api/fixtures/variable-data-type.json b/server/api/fixtures/variable-data-type.json
index 3ab746341ed123251fa5e00a5b2edc354793593b..d6a9bb3af516bb1f5bb026db1ecbb3bfe4357aba 100644
--- a/server/api/fixtures/variable-data-type.json
+++ b/server/api/fixtures/variable-data-type.json
@@ -1,44 +1,44 @@
 [
   {
-    "model": "api.variablecategory",
+    "model": "api.phenotypecategory",
     "fields": {
       "name": "logNKnb.lungs",
       "description": "blabla",
       "nature": "Count",
       "location": "Organ",
-      "dataclass": "Variable",
+      "dataclass": "Phenotype",
       "datatype": "Float"
     }
   },
   {
-    "model": "api.variablecategory",
+    "model": "api.phenotypecategory",
     "fields": {
       "name": "logNKnb.spleen",
       "description": "blabla",
       "nature": "Count",
       "location": "Organ",
-      "dataclass": "Variable",
+      "dataclass": "Phenotype",
       "datatype": "Float"
     }
   },
   {
-    "model": "api.variablecategory",
+    "model": "api.phenotypecategory",
     "fields": {
       "name": "logNKnb.liver",
       "description": "blabla",
       "nature": "Count",
       "location": "Organ",
       "datatype": "Float",
-      "dataclass": "Variable"
+      "dataclass": "Phenotype"
     }
   },
   {
-    "model": "api.variablecategory",
+    "model": "api.phenotypecategory",
     "fields": {
       "name": "age",
       "description": "blabla",
       "nature": "Count",
-      "location": "Other",
+      "location": "Unassigned",
       "datatype": "Integer",
       "dataclass": "Covariate"
     }
diff --git a/server/api/galaxy.py b/server/api/galaxy.py
index afec72d910cad193a5bade8f7878ee3d5d2d8253..52f0e852720736ca22e93f42b3cbb18d704fb673 100644
--- a/server/api/galaxy.py
+++ b/server/api/galaxy.py
@@ -1,5 +1,17 @@
+from pathlib import Path
+from tempfile import mkdtemp
 from bioblend.galaxy import GalaxyInstance
+from bioblend.galaxy.datasets import DatasetStateException
 from django.conf import settings
+from requests.exceptions import HTTPError
+import logging
+import time
+from bioblend import TimeoutException
+
+log = logging.getLogger(__name__)
+
+INVOCATION_TERMINAL_STATES = {"cancelled", "failed", "scheduled"}
+# Invocation non-terminal states are: 'new', 'ready'
 
 
 class GalaxyRunner:
@@ -8,13 +20,89 @@ class GalaxyRunner:
             url=settings.GALAXY_BASE_URL, key=settings.GALAXY_API_KEY, verify=False
         )
         self.galaxy_instance.nocache = True
+        self.galaxy_url = settings.GALAXY_BASE_URL
+
+    def get_datasets_endswith(self, history_id, pattern):
+        try:
+            datasets = self.galaxy_instance.histories.show_history(
+                history_id, contents=True
+            )
+        except HTTPError:
+            raise Exception(f"Do not find history : {history_id}")
+        try:
+            filtered_datasets = (ds for ds in datasets if ds["name"].endswith(pattern))
+        except StopIteration:
+            raise Exception(f"Do not find the dataset : {pattern}")
+        else:
+            return filtered_datasets
+
+    def download_dataset_in_tmp(self, dataset, history_id):
+        history = self.show_history(history_id)
+        try:
+            dirpath = mkdtemp(prefix="cc-qtl-")
+            file_path = Path(dirpath) / Path(dataset["name"])
+            self.galaxy_instance.datasets.download_dataset(
+                dataset["id"], file_path=file_path, use_default_filename=False
+            )
+        except HTTPError:
+            raise Exception(f"Could not get the dataset : {dataset['name']}")
+        except DatasetStateException as e:
+            raise DatasetStateException(
+                f"{str(e)}. The dataset name: {dataset['name']}. "
+                + f"The history name : {history['name']}."
+            )
+        else:
+            return file_path
+
+    def show_history(self, history_id):
+        try:
+            history = self.galaxy_instance.histories.show_history(
+                history_id, contents=False
+            )
+        except HTTPError:
+            raise Exception(f"Do not find history : {history_id}")
+        else:
+            return history
+
+    # get this from a new version of bioblend not supported per our Galaxy version
+    # gi.invocations.show_invocation not working with 18.05
+    # but gi.workflows.show_invocation
+    def wait_for_invocation(
+        self, workflow_id, invocation_id, maxwait=12000, interval=3, check=True
+    ):
+
+        assert maxwait >= 0
+        assert interval > 0
+
+        time_left = maxwait
+        while True:
+            invocation = self.galaxy_instance.workflows.show_invocation(
+                workflow_id, invocation_id
+            )
+            state = invocation["state"]
+            if state in INVOCATION_TERMINAL_STATES:
+                if check and state != "scheduled":
+                    raise Exception(
+                        f"Invocation {invocation_id} is in terminal state {state}"
+                    )
+                return invocation
+            if time_left > 0:
+                log.info(
+                    f"Invocation {invocation_id} is in non-terminal state {state}. Will wait {time_left} more s"
+                )
+                time.sleep(min(time_left, interval))
+                time_left -= interval
+            else:
+                raise TimeoutException(
+                    f"Invocation {invocation_id} is still in non-terminal state {state} after {maxwait} s"
+                )
 
+    def get_workflow_invocation_status(self, wf_id, invoc_id):
+        return self.galaxy_instance.workflows.show_invocation(wf_id, invoc_id)["state"]
 
-def get_history_status(history_id):
-    runner = GalaxyRunner()
-    return runner.galaxy_instance.histories.get_status(history_id)
+    def delete_history(self, history_id):
+        return self.galaxy_instance.histories.delete_history(history_id, purge=True)
 
+    def get_history_status(self, history_id):
+        return self.galaxy_instance.histories.get_status(history_id)
 
-def delete_history(history_id):
-    runner = GalaxyRunner()
-    return runner.galaxy_instance.histories.delete_history(history_id, purge=True)
diff --git a/server/api/management/commands/create-account-workshop.py b/server/api/management/commands/create-account-workshop.py
new file mode 100644
index 0000000000000000000000000000000000000000..b0765feea67e5b947bde70f16436abae8243529b
--- /dev/null
+++ b/server/api/management/commands/create-account-workshop.py
@@ -0,0 +1,83 @@
+import unidecode
+from django.core.management.base import BaseCommand
+from django.contrib.auth import get_user_model
+from api.factories import (
+    USER_PASSWORD,
+    UserFactory,
+)
+from rest_framework.test import APIClient
+
+from api.tests.utils import authenticate
+from api.models import RoleGroup
+
+# from api.models import Project
+
+
+User = get_user_model()
+
+
+class Command(BaseCommand):
+    help = "create useraccount for workshop user"
+
+    def handle(self, *args, **options):
+        users = [
+            {"fn": "Xavier", "ln": "Montagutelli"},
+            {"fn": "Axelle", "ln": "Brulport"},
+            {"fn": "Christian", "ln": "Vosshenrich"},
+            {"fn": "Etienne", "ln": "Simon-Loriere"},
+            {"fn": "Franck", "ln": "Bourgade"},
+            {"fn": "Françoise", "ln": "Dromer"},
+            {"fn": "Gérard", "ln": "Eberl"},
+            {"fn": "James", "ln": "Di Santo"},
+            {"fn": "Jean", "ln": "Jaubert"},
+            {"fn": "Lucie", "ln": "Dupuis"},
+            {"fn": "Marie", "ln": "Bourdon"},
+            {"fn": "Marion", "ln": "Rincel"},
+            {"fn": "Pascal", "ln": "Campagne"},
+            {"fn": "Rachel", "ln": "Torchet"},
+            {"fn": "Sylvie", "ln": "Van Der Werf"},
+            {"fn": "Thomas", "ln": "Bourgeron"},
+        ]
+        users_with_username = [
+            UserFactory.build(
+                username=u["username"], first_name=u["fn"], last_name=u["ln"]
+            )
+            for u in [
+                dict(
+                    u,
+                    username=f"{unidecode.unidecode(u['fn'][0].lower())}"
+                    + f"{unidecode.unidecode(u['ln'].lower().replace(' ', ''))}",
+                )
+                for u in users
+            ]
+        ]
+        client = APIClient()
+        superuser = User.objects.get(username="admin")
+        authenticate(client, superuser, USER_PASSWORD)
+        for build_user in users_with_username:
+            db_user = User.objects.filter(username=build_user.username)
+            appGroup = RoleGroup.objects.get(name="app-manager")
+            # db_user.set_password(user.username)
+            # db_user.save()
+            if not db_user.exists():
+                response = client.post(
+                    "/api/users/",
+                    data={
+                        "username": build_user.username,
+                        "first_name": build_user.first_name,
+                        "last_name": build_user.last_name,
+                        "is_staff": build_user.is_staff,
+                        "is_active": build_user.is_active,
+                        "email": build_user.email,
+                        "password": USER_PASSWORD,
+                        "appGroup": {"id": appGroup.id, "name": appGroup.name},
+                    },
+                    format="json",
+                )
+                user = response.data
+                user = User.objects.get(pk=user["id"])
+                user.set_password(build_user.username)
+                user.save()
+                print(f"User {build_user.username} has been created")
+            else:
+                print(f"User {build_user.username} already exists")
diff --git a/server/api/management/commands/initdb.py b/server/api/management/commands/initdb.py
index 249befb31656b31753e1d5d46200d6482f199fc2..13c1f1c4c2d614eddc3883cc594c7902c928a905 100644
--- a/server/api/management/commands/initdb.py
+++ b/server/api/management/commands/initdb.py
@@ -1,24 +1,25 @@
-from celery import VERSION
 from django.core.management.base import BaseCommand
 from django.core.management import call_command
 
-from api.views import update_rolegroup_permissions
-from api.models import Role, ProjectRole
+from api.models import Role, ProjectRole, RoleGroup
 
 
 class Command(BaseCommand):
     help = "Fill the database with default data"
 
     def handle(self, *args, **options):
+
+        # call_command
+
         # load the permissions
         call_command("loaddata", "api/fixtures/roles", verbosity=2)
         call_command("loaddata", "api/fixtures/groups", verbosity=2)
         # Clear permissions for role
-        for role in Role.objects.all():
-            role.permissions.clear()
+        Role.objects.clear_permissions()
+
         # Clear permissions for project role
-        for project_role in ProjectRole.objects.all():
-            project_role.permissions.clear()
+        ProjectRole.objects.clear_permissions()
+
         # ProjectRole.objects.permissions.all().delete()
 
         call_command("loaddata", "api/fixtures/role-permissions", verbosity=2)
@@ -35,5 +36,7 @@ class Command(BaseCommand):
 
         # load markers
         # call_command("loaddata", "api/fixtures/markers", verbosity=2)
+        call_command("loaddata", "api/fixtures/analysis-category", verbosity=2)
 
-        update_rolegroup_permissions()
+        call_command("loaddata", "api/fixtures/galaxy", verbosity=2)
+        RoleGroup.objects.update_permissions()
diff --git a/server/api/management/commands/update-group-permissions.py b/server/api/management/commands/update-group-permissions.py
new file mode 100644
index 0000000000000000000000000000000000000000..ba857ecaf7da0c6074d5f408035e9c536b0060dc
--- /dev/null
+++ b/server/api/management/commands/update-group-permissions.py
@@ -0,0 +1,24 @@
+from django.core.management.base import BaseCommand
+from django.core.management import call_command
+
+from api.models import Project, ProjectGroup, Role, RoleGroup
+
+
+class Command(BaseCommand):
+    help = "Fill the database with default data"
+
+    def handle(self, *args, **options):
+        print("test")
+
+        # this will remove all role permissions
+        # and load the new ones
+        call_command("initdb", verbosity=2)
+
+        # get all the Role Group and update the permissions
+        # RoleGroup.objects.update_permissions()
+        # for pg in ProjectGroup.objects.all():
+        #     pg.clear_permissions()
+        #     pg.add_permissions()
+        # # if remove, remove function as well
+        # ProjectGroup.objects.update_projectgroup_permissions()
+        Project.objects.update_permissions()
diff --git a/server/api/managers.py b/server/api/managers.py
index 6242d260b9752ca91cab19a2e4d3964fc9c9713d..488e54ca3566ac97c6fda3048b99178f880e5e6b 100644
--- a/server/api/managers.py
+++ b/server/api/managers.py
@@ -10,11 +10,19 @@ class ProjectRoleManager(models.Manager):
     def get_by_natural_key(self, name):
         return self.get(name=name)
 
+    def clear_permissions(self):
+        for project_role in self.all():
+            project_role.permissions.clear()
+
 
 class RoleManager(models.Manager):
     def get_by_natural_key(self, name):
         return self.get(name=name)
 
+    def clear_permissions(self):
+        for role in self.all():
+            role.permissions.clear()
+
 
 class MarkerManager(models.Manager):
     def get_by_natural_key(self, id_marker):
@@ -31,6 +39,57 @@ class CCLineManager(models.Manager):
         return self.get(id_cc=id_cc)
 
 
-class VariableCategoryManager(models.Manager):
+class PhenotypeCategoryManager(models.Manager):
+    def get_by_natural_key(self, name):
+        return self.get(name=name)
+
+
+class PeakManager(models.Manager):
+    def peak_from_dataset_name(self, dataset_name, analysis_id):
+        # analysis = Analysis.objects.get(pk=analysis_id)
+        peak_info_it = iter(dataset_name.split("--"))
+        peak_info = dict(zip(peak_info_it, peak_info_it))
+        return self.model.objects.get(
+            analysis=analysis_id,
+            variable_name=peak_info["var"],
+            chromosome=peak_info["chr"],
+            position=peak_info["pos"],
+        )
+
+
+class RoleGroupManager(models.Manager):
+    def clear_permissions(self):
+        for role_group in self.all():
+            # clear the permissions
+            role_group.permissions.clear()
+
+    def add_permissions(self):
+        for role_group in self.all():
+            # Add permissions from role
+            for perm in role_group.role.permissions.all():
+                role_group.permissions.add(perm)
+
+    def update_permissions(self):
+        # Clear the permissions
+        self.clear_permissions()
+        self.add_permissions()
+
+
+class GalaxyInstanceManager(models.Manager):
+    def get_by_natural_key(self, name):
+        return self.get(name=name)
+
+
+class GalaxyUserManager(models.Manager):
+    def get_by_natural_key(self, username):
+        return self.get(username=username)
+
+
+class AnalysisCategoryManager(models.Manager):
     def get_by_natural_key(self, name):
         return self.get(name=name)
+
+
+class GalaxyWorkflowManager(models.Manager):
+    def get_by_natural_key(self, galaxy_workflow_id, galaxy_user):
+        return self.get(galaxy_workflow_id=galaxy_workflow_id, galaxy_user=galaxy_user)
diff --git a/server/api/migrations/0019_auto_20210817_1405.py b/server/api/migrations/0019_auto_20210817_1405.py
new file mode 100644
index 0000000000000000000000000000000000000000..16e940be2c9773e9745b34c555c0987833fe2fb3
--- /dev/null
+++ b/server/api/migrations/0019_auto_20210817_1405.py
@@ -0,0 +1,19 @@
+# Generated by Django 3.1.3 on 2021-08-17 12:05
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('api', '0018_auto_20210625_1449'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='projectgroup',
+            name='project',
+            field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='project', to='api.project'),
+        ),
+    ]
diff --git a/server/api/migrations/0020_auto_20210817_1407.py b/server/api/migrations/0020_auto_20210817_1407.py
new file mode 100644
index 0000000000000000000000000000000000000000..8b6989c04fdec7aafb81f0f70fc793e892828858
--- /dev/null
+++ b/server/api/migrations/0020_auto_20210817_1407.py
@@ -0,0 +1,19 @@
+# Generated by Django 3.1.3 on 2021-08-17 12:07
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('api', '0019_auto_20210817_1405'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='projectgroup',
+            name='project',
+            field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='project_set', to='api.project'),
+        ),
+    ]
diff --git a/server/api/migrations/0021_auto_20210817_1409.py b/server/api/migrations/0021_auto_20210817_1409.py
new file mode 100644
index 0000000000000000000000000000000000000000..3c586ec4989e086bfa7935a328f313aaddabda6a
--- /dev/null
+++ b/server/api/migrations/0021_auto_20210817_1409.py
@@ -0,0 +1,19 @@
+# Generated by Django 3.1.3 on 2021-08-17 12:09
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('api', '0020_auto_20210817_1407'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='projectgroup',
+            name='project',
+            field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='project_group_set', to='api.project'),
+        ),
+    ]
diff --git a/server/api/migrations/0022_auto_20210902_1102.py b/server/api/migrations/0022_auto_20210902_1102.py
new file mode 100644
index 0000000000000000000000000000000000000000..f05dc3588d918c206fd801cb22b433dc1a0dec82
--- /dev/null
+++ b/server/api/migrations/0022_auto_20210902_1102.py
@@ -0,0 +1,173 @@
+# Generated by Django 3.2.7 on 2021-09-02 09:02
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('api', '0021_auto_20210817_1409'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='analysis',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
+        ),
+        migrations.AlterField(
+            model_name='analysisgroupobjectpermission',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
+        ),
+        migrations.AlterField(
+            model_name='analysisuserobjectpermission',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
+        ),
+        migrations.AlterField(
+            model_name='ccline',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
+        ),
+        migrations.AlterField(
+            model_name='cclinemarker',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
+        ),
+        migrations.AlterField(
+            model_name='coefficient',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
+        ),
+        migrations.AlterField(
+            model_name='department',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
+        ),
+        migrations.AlterField(
+            model_name='experiment',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
+        ),
+        migrations.AlterField(
+            model_name='experimentccline',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
+        ),
+        migrations.AlterField(
+            model_name='experimentgroupobjectpermission',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
+        ),
+        migrations.AlterField(
+            model_name='experimentuserobjectpermission',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
+        ),
+        migrations.AlterField(
+            model_name='founder',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
+        ),
+        migrations.AlterField(
+            model_name='haplotypes',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
+        ),
+        migrations.AlterField(
+            model_name='lodscore',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
+        ),
+        migrations.AlterField(
+            model_name='lodscoregroupobjectpermission',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
+        ),
+        migrations.AlterField(
+            model_name='lodscoresignificancethreshold',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
+        ),
+        migrations.AlterField(
+            model_name='lodscoreuserobjectpermission',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
+        ),
+        migrations.AlterField(
+            model_name='marker',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
+        ),
+        migrations.AlterField(
+            model_name='peak',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
+        ),
+        migrations.AlterField(
+            model_name='peakgroupobjectpermission',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
+        ),
+        migrations.AlterField(
+            model_name='peakuserobjectpermission',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
+        ),
+        migrations.AlterField(
+            model_name='project',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
+        ),
+        migrations.AlterField(
+            model_name='projectgroupobjectpermission',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
+        ),
+        migrations.AlterField(
+            model_name='projectrole',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
+        ),
+        migrations.AlterField(
+            model_name='projectuserobjectpermission',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
+        ),
+        migrations.AlterField(
+            model_name='result',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
+        ),
+        migrations.AlterField(
+            model_name='role',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
+        ),
+        migrations.AlterField(
+            model_name='snpsassociation',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
+        ),
+        migrations.AlterField(
+            model_name='topsnps',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
+        ),
+        migrations.AlterField(
+            model_name='user',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
+        ),
+        migrations.AlterField(
+            model_name='variable',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
+        ),
+        migrations.AlterField(
+            model_name='variablecategory',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
+        ),
+    ]
diff --git a/server/api/migrations/0023_auto_20210916_1456.py b/server/api/migrations/0023_auto_20210916_1456.py
new file mode 100644
index 0000000000000000000000000000000000000000..9764dcd94b02a3ad2102f9cadadf1ad4e648c0e9
--- /dev/null
+++ b/server/api/migrations/0023_auto_20210916_1456.py
@@ -0,0 +1,59 @@
+# Generated by Django 3.2.7 on 2021-09-16 12:56
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('api', '0022_auto_20210902_1102'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='Phenotype',
+            fields=[
+                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('value', models.CharField(max_length=100)),
+            ],
+            options={
+                'ordering': ['experiment_cc_line'],
+            },
+        ),
+        migrations.CreateModel(
+            name='PhenotypeCategory',
+            fields=[
+                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('name', models.CharField(max_length=200)),
+                ('description', models.CharField(max_length=400)),
+                ('nature', models.CharField(choices=[('Quantitative', 'Quantitative'), ('Categorical', 'Categorical'), ('Measurement', 'Measurement'), ('Count', 'Count'), ('Semi_Quantitative', 'Semi Quantitative')], max_length=200)),
+                ('location', models.CharField(choices=[('Organ', 'Organ'), ('Whole_Organism', 'Whole Organism'), ('Other', 'Other')], max_length=200)),
+                ('datatype', models.CharField(choices=[('Float', 'Float'), ('Integer', 'Integer'), ('Char', 'Char')], max_length=50)),
+                ('dataclass', models.CharField(choices=[('Phenotype', 'Phenotype'), ('Covariate', 'Covariate')], max_length=20)),
+            ],
+            options={
+                'ordering': ['name'],
+            },
+        ),
+        migrations.DeleteModel(
+            name='Variable',
+        ),
+        migrations.DeleteModel(
+            name='VariableCategory',
+        ),
+        migrations.AddConstraint(
+            model_name='phenotypecategory',
+            constraint=models.UniqueConstraint(fields=('name', 'nature', 'datatype', 'location', 'dataclass'), name='phenotype_type_unique'),
+        ),
+        migrations.AddField(
+            model_name='phenotype',
+            name='category',
+            field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='api.phenotypecategory'),
+        ),
+        migrations.AddField(
+            model_name='phenotype',
+            name='experiment_cc_line',
+            field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='phenotypes', to='api.experimentccline'),
+        ),
+    ]
diff --git a/server/api/migrations/0024_auto_20211007_1549.py b/server/api/migrations/0024_auto_20211007_1549.py
new file mode 100644
index 0000000000000000000000000000000000000000..c4df2c5c13c9c7fcf0a79436d6280ba0861de251
--- /dev/null
+++ b/server/api/migrations/0024_auto_20211007_1549.py
@@ -0,0 +1,32 @@
+# Generated by Django 3.2.7 on 2021-10-07 13:49
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('api', '0023_auto_20210916_1456'),
+    ]
+
+    operations = [
+        migrations.RemoveConstraint(
+            model_name='phenotypecategory',
+            name='phenotype_type_unique',
+        ),
+        migrations.AddField(
+            model_name='analysis',
+            name='phenotype_category',
+            field=models.ManyToManyField(to='api.PhenotypeCategory'),
+        ),
+        migrations.AlterField(
+            model_name='phenotype',
+            name='category',
+            field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='api.phenotypecategory'),
+        ),
+        migrations.AddConstraint(
+            model_name='phenotypecategory',
+            constraint=models.UniqueConstraint(fields=('name',), name='phenotype_type_unique'),
+        ),
+    ]
diff --git a/server/api/migrations/0025_experiment_phenotype_category.py b/server/api/migrations/0025_experiment_phenotype_category.py
new file mode 100644
index 0000000000000000000000000000000000000000..c19d31bacc28d28999529e8a400873d688dbb4c8
--- /dev/null
+++ b/server/api/migrations/0025_experiment_phenotype_category.py
@@ -0,0 +1,18 @@
+# Generated by Django 3.2.7 on 2021-10-07 14:14
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('api', '0024_auto_20211007_1549'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='experiment',
+            name='phenotype_category',
+            field=models.ManyToManyField(to='api.PhenotypeCategory'),
+        ),
+    ]
diff --git a/server/api/migrations/0026_analysis_description.py b/server/api/migrations/0026_analysis_description.py
new file mode 100644
index 0000000000000000000000000000000000000000..96e21c247445652399961ac0f473b3ef637df6ea
--- /dev/null
+++ b/server/api/migrations/0026_analysis_description.py
@@ -0,0 +1,18 @@
+# Generated by Django 3.2.7 on 2021-10-08 12:24
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('api', '0025_experiment_phenotype_category'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='analysis',
+            name='description',
+            field=models.TextField(blank=True),
+        ),
+    ]
diff --git a/server/api/migrations/0027_rename_phenotype_category_analysis_phenotype_categories.py b/server/api/migrations/0027_rename_phenotype_category_analysis_phenotype_categories.py
new file mode 100644
index 0000000000000000000000000000000000000000..1a4dec612caba3300d5fbd9a368c1aff7e09a970
--- /dev/null
+++ b/server/api/migrations/0027_rename_phenotype_category_analysis_phenotype_categories.py
@@ -0,0 +1,18 @@
+# Generated by Django 3.2.7 on 2021-10-20 10:06
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('api', '0026_analysis_description'),
+    ]
+
+    operations = [
+        migrations.RenameField(
+            model_name='analysis',
+            old_name='phenotype_category',
+            new_name='phenotype_categories',
+        ),
+    ]
diff --git a/server/api/migrations/0028_rename_phenotype_category_experiment_phenotype_categories.py b/server/api/migrations/0028_rename_phenotype_category_experiment_phenotype_categories.py
new file mode 100644
index 0000000000000000000000000000000000000000..7ee0d0df0a5513958aa8b3ed42725d6f79a43ce9
--- /dev/null
+++ b/server/api/migrations/0028_rename_phenotype_category_experiment_phenotype_categories.py
@@ -0,0 +1,18 @@
+# Generated by Django 3.2.7 on 2021-10-20 10:12
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('api', '0027_rename_phenotype_category_analysis_phenotype_categories'),
+    ]
+
+    operations = [
+        migrations.RenameField(
+            model_name='experiment',
+            old_name='phenotype_category',
+            new_name='phenotype_categories',
+        ),
+    ]
diff --git a/server/api/migrations/0029_peakgenes.py b/server/api/migrations/0029_peakgenes.py
new file mode 100644
index 0000000000000000000000000000000000000000..0872e7fec89314d12210e9d0a251ad45495213b4
--- /dev/null
+++ b/server/api/migrations/0029_peakgenes.py
@@ -0,0 +1,22 @@
+# Generated by Django 3.2.7 on 2022-02-11 07:52
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('api', '0028_rename_phenotype_category_experiment_phenotype_categories'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='PeakGenes',
+            fields=[
+                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('genes', models.JSONField()),
+                ('peak', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='genes', to='api.peak')),
+            ],
+        ),
+    ]
diff --git a/server/api/migrations/0030_lodscoresignificancethreshold_significant_threshold_unique.py b/server/api/migrations/0030_lodscoresignificancethreshold_significant_threshold_unique.py
new file mode 100644
index 0000000000000000000000000000000000000000..8e010696177240604bc82d896892a20c08fadda2
--- /dev/null
+++ b/server/api/migrations/0030_lodscoresignificancethreshold_significant_threshold_unique.py
@@ -0,0 +1,17 @@
+# Generated by Django 3.2.7 on 2022-02-11 15:42
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('api', '0029_peakgenes'),
+    ]
+
+    operations = [
+        migrations.AddConstraint(
+            model_name='lodscoresignificancethreshold',
+            constraint=models.UniqueConstraint(fields=('analysis', 'threshold'), name='significant_threshold_unique'),
+        ),
+    ]
diff --git a/server/api/migrations/0031_lodscore_significance_thresholds.py b/server/api/migrations/0031_lodscore_significance_thresholds.py
new file mode 100644
index 0000000000000000000000000000000000000000..22b3767249d7f02d9575a8491d41e1f747b3d525
--- /dev/null
+++ b/server/api/migrations/0031_lodscore_significance_thresholds.py
@@ -0,0 +1,19 @@
+# Generated by Django 3.2.7 on 2022-02-18 12:43
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('api', '0030_lodscoresignificancethreshold_significant_threshold_unique'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='lodscore',
+            name='significance_thresholds',
+            field=models.JSONField(blank=True, default=[]),
+            preserve_default=False,
+        ),
+    ]
diff --git a/server/api/migrations/0032_alter_lodscore_significance_thresholds.py b/server/api/migrations/0032_alter_lodscore_significance_thresholds.py
new file mode 100644
index 0000000000000000000000000000000000000000..30ee3b968be8f6715b933950c5b1918b1c87dfb7
--- /dev/null
+++ b/server/api/migrations/0032_alter_lodscore_significance_thresholds.py
@@ -0,0 +1,18 @@
+# Generated by Django 3.2.7 on 2022-02-18 12:48
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('api', '0031_lodscore_significance_thresholds'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='lodscore',
+            name='significance_thresholds',
+            field=models.JSONField(blank=True, default=[]),
+        ),
+    ]
diff --git a/server/api/migrations/0033_alter_lodscore_significance_thresholds.py b/server/api/migrations/0033_alter_lodscore_significance_thresholds.py
new file mode 100644
index 0000000000000000000000000000000000000000..71d4bd2bed99ea34120b0ada08a960d7648d4865
--- /dev/null
+++ b/server/api/migrations/0033_alter_lodscore_significance_thresholds.py
@@ -0,0 +1,18 @@
+# Generated by Django 3.2.7 on 2022-02-18 12:50
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('api', '0032_alter_lodscore_significance_thresholds'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='lodscore',
+            name='significance_thresholds',
+            field=models.JSONField(blank=True, default=list),
+        ),
+    ]
diff --git a/server/api/migrations/0034_delete_lodscoresignificancethreshold.py b/server/api/migrations/0034_delete_lodscoresignificancethreshold.py
new file mode 100644
index 0000000000000000000000000000000000000000..203bf977d1e8209a6f3f2a9d9d9263c26d93c7a0
--- /dev/null
+++ b/server/api/migrations/0034_delete_lodscoresignificancethreshold.py
@@ -0,0 +1,16 @@
+# Generated by Django 3.2.7 on 2022-02-18 13:18
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('api', '0033_alter_lodscore_significance_thresholds'),
+    ]
+
+    operations = [
+        migrations.DeleteModel(
+            name='LodScoreSignificanceThreshold',
+        ),
+    ]
diff --git a/server/api/migrations/0035_auto_20220307_1044.py b/server/api/migrations/0035_auto_20220307_1044.py
new file mode 100644
index 0000000000000000000000000000000000000000..868578a5f80903c0f36f474ae5d6a28aaa2e897d
--- /dev/null
+++ b/server/api/migrations/0035_auto_20220307_1044.py
@@ -0,0 +1,165 @@
+# Generated by Django 3.2.7 on 2022-03-07 09:44
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('api', '0034_delete_lodscoresignificancethreshold'),
+    ]
+
+    operations = [
+        migrations.RemoveConstraint(
+            model_name='analysis',
+            name='analysis_unique',
+        ),
+        migrations.RemoveConstraint(
+            model_name='ccline',
+            name='id_cc_unique',
+        ),
+        migrations.RemoveConstraint(
+            model_name='department',
+            name='department_name_unique',
+        ),
+        migrations.RemoveConstraint(
+            model_name='experiment',
+            name='experiment_name_unique',
+        ),
+        migrations.RemoveConstraint(
+            model_name='experimentccline',
+            name='experiement_cc_line_unique',
+        ),
+        migrations.RemoveConstraint(
+            model_name='founder',
+            name='founder_name_unique',
+        ),
+        migrations.RemoveConstraint(
+            model_name='founder',
+            name='founder_cc_designation_unique',
+        ),
+        migrations.RemoveConstraint(
+            model_name='lodscore',
+            name='lod_unique',
+        ),
+        migrations.RemoveConstraint(
+            model_name='marker',
+            name='id_marker_unique',
+        ),
+        migrations.RemoveConstraint(
+            model_name='peak',
+            name='peak_unique',
+        ),
+        migrations.RemoveConstraint(
+            model_name='phenotypecategory',
+            name='phenotype_type_unique',
+        ),
+        migrations.RemoveConstraint(
+            model_name='project',
+            name='project_name_unique',
+        ),
+        migrations.RemoveConstraint(
+            model_name='projectgroup',
+            name='project_role_unique',
+        ),
+        migrations.RemoveConstraint(
+            model_name='projectrole',
+            name='projectrole_name_unique',
+        ),
+        migrations.RemoveConstraint(
+            model_name='role',
+            name='role_name_unique',
+        ),
+        migrations.RemoveConstraint(
+            model_name='team',
+            name='team_department_unique',
+        ),
+        migrations.AddConstraint(
+            model_name='analysis',
+            constraint=models.UniqueConstraint(fields=('name', 'galaxy_history_id'), name='api_analysis_unique'),
+        ),
+        migrations.AddConstraint(
+            model_name='ccline',
+            constraint=models.UniqueConstraint(fields=('id_cc',), name='api_ccline_id_cc_unique'),
+        ),
+        migrations.AddConstraint(
+            model_name='cclinemarker',
+            constraint=models.CheckConstraint(check=models.Q(('base__in', ['A', 'C', 'G', 'T', 'W', 'S', 'M', 'K', 'P', 'Y', 'B', 'D', 'H', 'V', 'N', 'Z'])), name='api_cclinemarker_base_valid'),
+        ),
+        migrations.AddConstraint(
+            model_name='department',
+            constraint=models.UniqueConstraint(fields=('name',), name='api_department_unique'),
+        ),
+        migrations.AddConstraint(
+            model_name='experiment',
+            constraint=models.UniqueConstraint(fields=('name', 'project'), name='api_experiment_unique'),
+        ),
+        migrations.AddConstraint(
+            model_name='experimentccline',
+            constraint=models.UniqueConstraint(fields=('experiment', 'cc_line_id'), name='api_experimentccline_unique'),
+        ),
+        migrations.AddConstraint(
+            model_name='experimentccline',
+            constraint=models.CheckConstraint(check=models.Q(('sex__in', ['F', 'M'])), name='api_experimentccline_sex_valid'),
+        ),
+        migrations.AddConstraint(
+            model_name='founder',
+            constraint=models.UniqueConstraint(fields=('name',), name='api_founder_name_unique'),
+        ),
+        migrations.AddConstraint(
+            model_name='founder',
+            constraint=models.UniqueConstraint(fields=('cc_designation',), name='api_founder_cc_designation_unique'),
+        ),
+        migrations.AddConstraint(
+            model_name='lodscore',
+            constraint=models.UniqueConstraint(fields=('analysis',), name='api_lodscore_unique'),
+        ),
+        migrations.AddConstraint(
+            model_name='marker',
+            constraint=models.UniqueConstraint(fields=('id_marker',), name='api_marker_idmarker_unique'),
+        ),
+        migrations.AddConstraint(
+            model_name='peak',
+            constraint=models.UniqueConstraint(fields=('analysis', 'variable_name', 'chromosome', 'position'), name='api_peak_unique'),
+        ),
+        migrations.AddConstraint(
+            model_name='phenotypecategory',
+            constraint=models.UniqueConstraint(fields=('name',), name='api_phenotypecategory_name_unique'),
+        ),
+        migrations.AddConstraint(
+            model_name='phenotypecategory',
+            constraint=models.CheckConstraint(check=models.Q(('nature__in', ['Quantitative', 'Categorical', 'Measurement', 'Count', 'Semi_Quantitative'])), name='api_phenotypecategory_nature_valid'),
+        ),
+        migrations.AddConstraint(
+            model_name='phenotypecategory',
+            constraint=models.CheckConstraint(check=models.Q(('location__in', ['Organ', 'Whole_Organism', 'Other'])), name='api_phenotypecategory_location_valid'),
+        ),
+        migrations.AddConstraint(
+            model_name='phenotypecategory',
+            constraint=models.CheckConstraint(check=models.Q(('datatype__in', ['Float', 'Integer', 'Char'])), name='api_phenotypecategory_datatype_valid'),
+        ),
+        migrations.AddConstraint(
+            model_name='phenotypecategory',
+            constraint=models.CheckConstraint(check=models.Q(('dataclass__in', ['Phenotype', 'Covariate'])), name='api_phenotypecategory_dataclass_valid'),
+        ),
+        migrations.AddConstraint(
+            model_name='project',
+            constraint=models.UniqueConstraint(fields=('project_name',), name='api_project_unique'),
+        ),
+        migrations.AddConstraint(
+            model_name='projectgroup',
+            constraint=models.UniqueConstraint(fields=('project', 'project_role'), name='api_projectgroup_unique'),
+        ),
+        migrations.AddConstraint(
+            model_name='projectrole',
+            constraint=models.UniqueConstraint(fields=('name',), name='api_projectrole_unique'),
+        ),
+        migrations.AddConstraint(
+            model_name='role',
+            constraint=models.UniqueConstraint(fields=('name',), name='api_role_unique'),
+        ),
+        migrations.AddConstraint(
+            model_name='team',
+            constraint=models.UniqueConstraint(fields=('group_ptr', 'department'), name='api_team_unique'),
+        ),
+    ]
diff --git a/server/api/migrations/0036_alter_experimentccline_cc_line_id.py b/server/api/migrations/0036_alter_experimentccline_cc_line_id.py
new file mode 100644
index 0000000000000000000000000000000000000000..9b8b1c11f0ddc1caf2bd7452068eff237d8c4386
--- /dev/null
+++ b/server/api/migrations/0036_alter_experimentccline_cc_line_id.py
@@ -0,0 +1,18 @@
+# Generated by Django 3.2.7 on 2022-03-07 09:58
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('api', '0035_auto_20220307_1044'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='experimentccline',
+            name='cc_line_id',
+            field=models.CharField(max_length=50),
+        ),
+    ]
diff --git a/server/api/migrations/0037_analysiscategory_galaxyinstance_galaxyuser_galaxyworkflow.py b/server/api/migrations/0037_analysiscategory_galaxyinstance_galaxyuser_galaxyworkflow.py
new file mode 100644
index 0000000000000000000000000000000000000000..5eeab283995e16c0128a22825ab9962ee26f9dcc
--- /dev/null
+++ b/server/api/migrations/0037_analysiscategory_galaxyinstance_galaxyuser_galaxyworkflow.py
@@ -0,0 +1,50 @@
+# Generated by Django 3.2.7 on 2022-03-10 14:58
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('api', '0036_alter_experimentccline_cc_line_id'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='AnalysisCategory',
+            fields=[
+                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('name', models.CharField(max_length=50)),
+                ('description', models.TextField(blank=True)),
+            ],
+        ),
+        migrations.CreateModel(
+            name='GalaxyInstance',
+            fields=[
+                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('name', models.CharField(max_length=200)),
+                ('url', models.URLField()),
+                ('description', models.TextField(blank=True)),
+            ],
+        ),
+        migrations.CreateModel(
+            name='GalaxyUser',
+            fields=[
+                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('username', models.EmailField(max_length=254)),
+                ('api_key', models.CharField(max_length=254)),
+                ('galaxy_instance', models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, to='api.galaxyinstance')),
+            ],
+        ),
+        migrations.CreateModel(
+            name='GalaxyWorkflow',
+            fields=[
+                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('name', models.CharField(max_length=200)),
+                ('galaxy_workflow_id', models.CharField(blank=True, max_length=200)),
+                ('analysis_category', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='api.analysiscategory')),
+                ('galaxy_user', models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, to='api.galaxyuser')),
+            ],
+        ),
+    ]
diff --git a/server/api/migrations/0038_alter_galaxyuser_api_key.py b/server/api/migrations/0038_alter_galaxyuser_api_key.py
new file mode 100644
index 0000000000000000000000000000000000000000..63ed63580c94fee7f1d8318e833cff5d708898e9
--- /dev/null
+++ b/server/api/migrations/0038_alter_galaxyuser_api_key.py
@@ -0,0 +1,18 @@
+# Generated by Django 3.2.7 on 2022-03-10 15:00
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('api', '0037_analysiscategory_galaxyinstance_galaxyuser_galaxyworkflow'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='galaxyuser',
+            name='api_key',
+            field=models.CharField(blank=True, max_length=254),
+        ),
+    ]
diff --git a/server/api/migrations/0039_auto_20220310_1611.py b/server/api/migrations/0039_auto_20220310_1611.py
new file mode 100644
index 0000000000000000000000000000000000000000..7e8491d2c018f9b7f63ef7af8800b062284471c3
--- /dev/null
+++ b/server/api/migrations/0039_auto_20220310_1611.py
@@ -0,0 +1,51 @@
+# Generated by Django 3.2.7 on 2022-03-10 15:11
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('api', '0038_alter_galaxyuser_api_key'),
+    ]
+
+    operations = [
+        migrations.AlterModelOptions(
+            name='analysiscategory',
+            options={'ordering': ['name']},
+        ),
+        migrations.AlterModelOptions(
+            name='galaxyinstance',
+            options={'ordering': ['name']},
+        ),
+        migrations.AlterModelOptions(
+            name='galaxyuser',
+            options={'ordering': ['galaxy_instance', 'username']},
+        ),
+        migrations.AlterModelOptions(
+            name='galaxyworkflow',
+            options={'ordering': ['analysis_category', 'name']},
+        ),
+        migrations.AlterField(
+            model_name='galaxyworkflow',
+            name='analysis_category',
+            field=models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, to='api.analysiscategory'),
+        ),
+        migrations.AddConstraint(
+            model_name='analysiscategory',
+            constraint=models.UniqueConstraint(fields=('name',), name='api_analysiscategory_unique'),
+        ),
+        migrations.AddConstraint(
+            model_name='galaxyinstance',
+            constraint=models.UniqueConstraint(fields=('url',), name='api_galaxyinstance_unique'),
+        ),
+        migrations.AddConstraint(
+            model_name='galaxyuser',
+            constraint=models.UniqueConstraint(fields=('galaxy_instance', 'username'), name='api_galaxyuser_unique'),
+        ),
+        migrations.AddConstraint(
+            model_name='galaxyworkflow',
+            constraint=models.UniqueConstraint(fields=('galaxy_workflow_id', 'galaxy_user'), name='api_galaxyworkflow_unique'),
+        ),
+    ]
diff --git a/server/api/migrations/0040_auto_20220310_1615.py b/server/api/migrations/0040_auto_20220310_1615.py
new file mode 100644
index 0000000000000000000000000000000000000000..319569cb2331bd4871071d652428e4bc8a509e93
--- /dev/null
+++ b/server/api/migrations/0040_auto_20220310_1615.py
@@ -0,0 +1,25 @@
+# Generated by Django 3.2.7 on 2022-03-10 15:15
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('api', '0039_auto_20220310_1611'),
+    ]
+
+    operations = [
+        migrations.RemoveConstraint(
+            model_name='galaxyinstance',
+            name='api_galaxyinstance_unique',
+        ),
+        migrations.AddConstraint(
+            model_name='galaxyinstance',
+            constraint=models.UniqueConstraint(fields=('url',), name='api_galaxyinstance_url_unique'),
+        ),
+        migrations.AddConstraint(
+            model_name='galaxyinstance',
+            constraint=models.UniqueConstraint(fields=('name',), name='api_galaxyinstance_name_unique'),
+        ),
+    ]
diff --git a/server/api/migrations/0041_alter_galaxyuser_unique_together.py b/server/api/migrations/0041_alter_galaxyuser_unique_together.py
new file mode 100644
index 0000000000000000000000000000000000000000..8836474b84d575be7078dc7bf8018edbfbe434aa
--- /dev/null
+++ b/server/api/migrations/0041_alter_galaxyuser_unique_together.py
@@ -0,0 +1,17 @@
+# Generated by Django 3.2.7 on 2022-03-11 08:46
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('api', '0040_auto_20220310_1615'),
+    ]
+
+    operations = [
+        migrations.AlterUniqueTogether(
+            name='galaxyuser',
+            unique_together={('galaxy_instance', 'username')},
+        ),
+    ]
diff --git a/server/api/migrations/0042_alter_galaxyuser_unique_together.py b/server/api/migrations/0042_alter_galaxyuser_unique_together.py
new file mode 100644
index 0000000000000000000000000000000000000000..e8051b784a98d140f82e168f263300a871eee89d
--- /dev/null
+++ b/server/api/migrations/0042_alter_galaxyuser_unique_together.py
@@ -0,0 +1,17 @@
+# Generated by Django 3.2.7 on 2022-03-11 08:49
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('api', '0041_alter_galaxyuser_unique_together'),
+    ]
+
+    operations = [
+        migrations.AlterUniqueTogether(
+            name='galaxyuser',
+            unique_together=set(),
+        ),
+    ]
diff --git a/server/api/migrations/0043_auto_20220311_0956.py b/server/api/migrations/0043_auto_20220311_0956.py
new file mode 100644
index 0000000000000000000000000000000000000000..825fce23c886c0242c4d27e421c1edcb861412da
--- /dev/null
+++ b/server/api/migrations/0043_auto_20220311_0956.py
@@ -0,0 +1,21 @@
+# Generated by Django 3.2.7 on 2022-03-11 08:56
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('api', '0042_alter_galaxyuser_unique_together'),
+    ]
+
+    operations = [
+        migrations.RemoveConstraint(
+            model_name='galaxyuser',
+            name='api_galaxyuser_unique',
+        ),
+        migrations.AddConstraint(
+            model_name='galaxyuser',
+            constraint=models.UniqueConstraint(fields=('username', 'galaxy_instance'), name='api_galaxyuser_unique'),
+        ),
+    ]
diff --git a/server/api/migrations/0044_auto_20220311_1024.py b/server/api/migrations/0044_auto_20220311_1024.py
new file mode 100644
index 0000000000000000000000000000000000000000..1322d29df4d87d1ec199846a2b0e30fa4e61b29f
--- /dev/null
+++ b/server/api/migrations/0044_auto_20220311_1024.py
@@ -0,0 +1,35 @@
+# Generated by Django 3.2.7 on 2022-03-11 09:24
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('api', '0043_auto_20220311_0956'),
+    ]
+
+    operations = [
+        migrations.AlterModelOptions(
+            name='galaxyuser',
+            options={'ordering': ['username', 'galaxy_instance']},
+        ),
+        migrations.RemoveConstraint(
+            model_name='galaxyinstance',
+            name='api_galaxyinstance_url_unique',
+        ),
+        migrations.RemoveConstraint(
+            model_name='galaxyinstance',
+            name='api_galaxyinstance_name_unique',
+        ),
+        migrations.AlterField(
+            model_name='galaxyinstance',
+            name='name',
+            field=models.CharField(max_length=200, unique=True),
+        ),
+        migrations.AlterField(
+            model_name='galaxyinstance',
+            name='url',
+            field=models.URLField(unique=True),
+        ),
+    ]
diff --git a/server/api/migrations/0045_auto_20220311_1029.py b/server/api/migrations/0045_auto_20220311_1029.py
new file mode 100644
index 0000000000000000000000000000000000000000..1833636b42b4e98c205b7c982dec1bb31f86dd49
--- /dev/null
+++ b/server/api/migrations/0045_auto_20220311_1029.py
@@ -0,0 +1,48 @@
+# Generated by Django 3.2.7 on 2022-03-11 09:29
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('api', '0044_auto_20220311_1024'),
+    ]
+
+    operations = [
+        migrations.RemoveConstraint(
+            model_name='analysiscategory',
+            name='api_analysiscategory_unique',
+        ),
+        migrations.RemoveConstraint(
+            model_name='experiment',
+            name='api_experiment_unique',
+        ),
+        migrations.RemoveConstraint(
+            model_name='phenotypecategory',
+            name='api_phenotypecategory_name_unique',
+        ),
+        migrations.RemoveConstraint(
+            model_name='project',
+            name='api_project_unique',
+        ),
+        migrations.AlterField(
+            model_name='analysiscategory',
+            name='name',
+            field=models.CharField(max_length=50, unique=True),
+        ),
+        migrations.AlterField(
+            model_name='phenotypecategory',
+            name='name',
+            field=models.CharField(max_length=200, unique=True),
+        ),
+        migrations.AlterField(
+            model_name='project',
+            name='project_name',
+            field=models.CharField(max_length=200, unique=True),
+        ),
+        migrations.AlterUniqueTogether(
+            name='experiment',
+            unique_together={('name', 'project')},
+        ),
+    ]
diff --git a/server/api/migrations/0046_auto_20220311_1030.py b/server/api/migrations/0046_auto_20220311_1030.py
new file mode 100644
index 0000000000000000000000000000000000000000..b87c71965192b326cbdc92401f7bd81a99b8fb05
--- /dev/null
+++ b/server/api/migrations/0046_auto_20220311_1030.py
@@ -0,0 +1,31 @@
+# Generated by Django 3.2.7 on 2022-03-11 09:30
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('api', '0045_auto_20220311_1029'),
+    ]
+
+    operations = [
+        migrations.RemoveConstraint(
+            model_name='projectrole',
+            name='api_projectrole_unique',
+        ),
+        migrations.RemoveConstraint(
+            model_name='role',
+            name='api_role_unique',
+        ),
+        migrations.AlterField(
+            model_name='projectrole',
+            name='name',
+            field=models.CharField(max_length=128, unique=True),
+        ),
+        migrations.AlterField(
+            model_name='role',
+            name='name',
+            field=models.CharField(max_length=128, unique=True),
+        ),
+    ]
diff --git a/server/api/migrations/0047_auto_20220311_1032.py b/server/api/migrations/0047_auto_20220311_1032.py
new file mode 100644
index 0000000000000000000000000000000000000000..6b99ac091b772670189eba724a4771576b640f2f
--- /dev/null
+++ b/server/api/migrations/0047_auto_20220311_1032.py
@@ -0,0 +1,31 @@
+# Generated by Django 3.2.7 on 2022-03-11 09:32
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('auth', '0012_alter_user_first_name_max_length'),
+        ('api', '0046_auto_20220311_1030'),
+    ]
+
+    operations = [
+        migrations.RemoveConstraint(
+            model_name='department',
+            name='api_department_unique',
+        ),
+        migrations.RemoveConstraint(
+            model_name='team',
+            name='api_team_unique',
+        ),
+        migrations.AlterField(
+            model_name='department',
+            name='name',
+            field=models.CharField(max_length=128, unique=True),
+        ),
+        migrations.AlterUniqueTogether(
+            name='team',
+            unique_together={('group_ptr', 'department')},
+        ),
+    ]
diff --git a/server/api/migrations/0048_auto_20220311_1033.py b/server/api/migrations/0048_auto_20220311_1033.py
new file mode 100644
index 0000000000000000000000000000000000000000..43041aefd91179bc4934682aed00d5c06ad4a990
--- /dev/null
+++ b/server/api/migrations/0048_auto_20220311_1033.py
@@ -0,0 +1,39 @@
+# Generated by Django 3.2.7 on 2022-03-11 09:33
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('api', '0047_auto_20220311_1032'),
+    ]
+
+    operations = [
+        migrations.RemoveConstraint(
+            model_name='founder',
+            name='api_founder_name_unique',
+        ),
+        migrations.RemoveConstraint(
+            model_name='founder',
+            name='api_founder_cc_designation_unique',
+        ),
+        migrations.RemoveConstraint(
+            model_name='projectgroup',
+            name='api_projectgroup_unique',
+        ),
+        migrations.AlterField(
+            model_name='founder',
+            name='cc_designation',
+            field=models.CharField(blank=True, max_length=10, unique=True),
+        ),
+        migrations.AlterField(
+            model_name='founder',
+            name='name',
+            field=models.CharField(max_length=200, unique=True),
+        ),
+        migrations.AlterUniqueTogether(
+            name='projectgroup',
+            unique_together={('project', 'project_role')},
+        ),
+    ]
diff --git a/server/api/migrations/0049_auto_20220311_1035.py b/server/api/migrations/0049_auto_20220311_1035.py
new file mode 100644
index 0000000000000000000000000000000000000000..71543ad03f72ad979abb32f1e0ca8c9173e38e58
--- /dev/null
+++ b/server/api/migrations/0049_auto_20220311_1035.py
@@ -0,0 +1,39 @@
+# Generated by Django 3.2.7 on 2022-03-11 09:35
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('api', '0048_auto_20220311_1033'),
+    ]
+
+    operations = [
+        migrations.RemoveConstraint(
+            model_name='ccline',
+            name='api_ccline_id_cc_unique',
+        ),
+        migrations.RemoveConstraint(
+            model_name='experimentccline',
+            name='api_experimentccline_unique',
+        ),
+        migrations.RemoveConstraint(
+            model_name='marker',
+            name='api_marker_idmarker_unique',
+        ),
+        migrations.AlterField(
+            model_name='ccline',
+            name='id_cc',
+            field=models.CharField(max_length=200, unique=True),
+        ),
+        migrations.AlterField(
+            model_name='marker',
+            name='id_marker',
+            field=models.CharField(max_length=200, unique=True),
+        ),
+        migrations.AlterUniqueTogether(
+            name='experimentccline',
+            unique_together={('experiment', 'cc_line_id')},
+        ),
+    ]
diff --git a/server/api/migrations/0050_alter_phenotype_unique_together.py b/server/api/migrations/0050_alter_phenotype_unique_together.py
new file mode 100644
index 0000000000000000000000000000000000000000..ef596b5e45781cb4ad97114ae29db721a762f90b
--- /dev/null
+++ b/server/api/migrations/0050_alter_phenotype_unique_together.py
@@ -0,0 +1,17 @@
+# Generated by Django 3.2.7 on 2022-03-11 09:37
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('api', '0049_auto_20220311_1035'),
+    ]
+
+    operations = [
+        migrations.AlterUniqueTogether(
+            name='phenotype',
+            unique_together={('experiment_cc_line', 'category')},
+        ),
+    ]
diff --git a/server/api/migrations/0051_auto_20220311_1044.py b/server/api/migrations/0051_auto_20220311_1044.py
new file mode 100644
index 0000000000000000000000000000000000000000..cf19a8006203d50918d91cd68511d5d057dea0e7
--- /dev/null
+++ b/server/api/migrations/0051_auto_20220311_1044.py
@@ -0,0 +1,55 @@
+# Generated by Django 3.2.7 on 2022-03-11 09:44
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('api', '0050_alter_phenotype_unique_together'),
+    ]
+
+    operations = [
+        migrations.RemoveConstraint(
+            model_name='analysis',
+            name='api_analysis_unique',
+        ),
+        migrations.RemoveConstraint(
+            model_name='galaxyuser',
+            name='api_galaxyuser_unique',
+        ),
+        migrations.RemoveConstraint(
+            model_name='galaxyworkflow',
+            name='api_galaxyworkflow_unique',
+        ),
+        migrations.RemoveConstraint(
+            model_name='lodscore',
+            name='api_lodscore_unique',
+        ),
+        migrations.RemoveConstraint(
+            model_name='peak',
+            name='api_peak_unique',
+        ),
+        migrations.AlterField(
+            model_name='lodscore',
+            name='analysis',
+            field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='api.analysis', unique=True),
+        ),
+        migrations.AlterUniqueTogether(
+            name='analysis',
+            unique_together={('name', 'galaxy_history_id')},
+        ),
+        migrations.AlterUniqueTogether(
+            name='galaxyuser',
+            unique_together={('username', 'galaxy_instance')},
+        ),
+        migrations.AlterUniqueTogether(
+            name='galaxyworkflow',
+            unique_together={('galaxy_workflow_id', 'galaxy_user')},
+        ),
+        migrations.AlterUniqueTogether(
+            name='peak',
+            unique_together={('analysis', 'variable_name', 'chromosome', 'position')},
+        ),
+    ]
diff --git a/server/api/migrations/0052_alter_lodscore_analysis.py b/server/api/migrations/0052_alter_lodscore_analysis.py
new file mode 100644
index 0000000000000000000000000000000000000000..94bcc5716c17a162001e2a2115b42003338e223c
--- /dev/null
+++ b/server/api/migrations/0052_alter_lodscore_analysis.py
@@ -0,0 +1,19 @@
+# Generated by Django 3.2.7 on 2022-03-11 09:46
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('api', '0051_auto_20220311_1044'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='lodscore',
+            name='analysis',
+            field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='api.analysis'),
+        ),
+    ]
diff --git a/server/api/migrations/0053_alter_galaxyinstance_url.py b/server/api/migrations/0053_alter_galaxyinstance_url.py
new file mode 100644
index 0000000000000000000000000000000000000000..a616aebdd2a95e95f9bab76d592a1eab6a81153d
--- /dev/null
+++ b/server/api/migrations/0053_alter_galaxyinstance_url.py
@@ -0,0 +1,18 @@
+# Generated by Django 3.2.7 on 2022-03-11 09:53
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('api', '0052_alter_lodscore_analysis'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='galaxyinstance',
+            name='url',
+            field=models.URLField(),
+        ),
+    ]
diff --git a/server/api/migrations/0054_alter_galaxyinstance_url.py b/server/api/migrations/0054_alter_galaxyinstance_url.py
new file mode 100644
index 0000000000000000000000000000000000000000..53dbfcc2911ca5e487d53e0583de19434b3c7f1d
--- /dev/null
+++ b/server/api/migrations/0054_alter_galaxyinstance_url.py
@@ -0,0 +1,18 @@
+# Generated by Django 3.2.7 on 2022-03-11 09:54
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('api', '0053_alter_galaxyinstance_url'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='galaxyinstance',
+            name='url',
+            field=models.URLField(unique=True),
+        ),
+    ]
diff --git a/server/api/migrations/0055_auto_20220311_1104.py b/server/api/migrations/0055_auto_20220311_1104.py
new file mode 100644
index 0000000000000000000000000000000000000000..4295bfedbc6ff78b32efcd6e3333b6b7f8463915
--- /dev/null
+++ b/server/api/migrations/0055_auto_20220311_1104.py
@@ -0,0 +1,24 @@
+# Generated by Django 3.2.7 on 2022-03-11 10:04
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('api', '0054_alter_galaxyinstance_url'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='galaxyworkflow',
+            name='galaxy_instance',
+            field=models.ForeignKey(default=9, on_delete=django.db.models.deletion.DO_NOTHING, to='api.galaxyinstance'),
+            preserve_default=False,
+        ),
+        migrations.AlterUniqueTogether(
+            name='galaxyworkflow',
+            unique_together={('galaxy_workflow_id', 'galaxy_instance')},
+        ),
+    ]
diff --git a/server/api/migrations/0056_auto_20220311_1158.py b/server/api/migrations/0056_auto_20220311_1158.py
new file mode 100644
index 0000000000000000000000000000000000000000..42135abaa3b236f0abd20fecf8ffd2e5234ecba1
--- /dev/null
+++ b/server/api/migrations/0056_auto_20220311_1158.py
@@ -0,0 +1,30 @@
+# Generated by Django 3.2.7 on 2022-03-11 10:58
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('api', '0055_auto_20220311_1104'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='galaxyuser',
+            name='username',
+            field=models.EmailField(max_length=254, unique=True),
+        ),
+        migrations.AlterUniqueTogether(
+            name='galaxyuser',
+            unique_together=set(),
+        ),
+        migrations.AlterUniqueTogether(
+            name='galaxyworkflow',
+            unique_together={('galaxy_workflow_id', 'galaxy_user')},
+        ),
+        migrations.RemoveField(
+            model_name='galaxyworkflow',
+            name='galaxy_instance',
+        ),
+    ]
diff --git a/server/api/migrations/0057_galaxyworkflow_version.py b/server/api/migrations/0057_galaxyworkflow_version.py
new file mode 100644
index 0000000000000000000000000000000000000000..a1c97399b56d552e2228efd162456c0c31f4b209
--- /dev/null
+++ b/server/api/migrations/0057_galaxyworkflow_version.py
@@ -0,0 +1,18 @@
+# Generated by Django 3.2.7 on 2022-03-12 02:28
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('api', '0056_auto_20220311_1158'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='galaxyworkflow',
+            name='version',
+            field=models.FloatField(null=True),
+        ),
+    ]
diff --git a/server/api/migrations/0058_alter_galaxyworkflow_version.py b/server/api/migrations/0058_alter_galaxyworkflow_version.py
new file mode 100644
index 0000000000000000000000000000000000000000..b2c6f1843cb2c0f896a3146209338d0650962a33
--- /dev/null
+++ b/server/api/migrations/0058_alter_galaxyworkflow_version.py
@@ -0,0 +1,18 @@
+# Generated by Django 3.2.7 on 2022-03-12 02:29
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('api', '0057_galaxyworkflow_version'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='galaxyworkflow',
+            name='version',
+            field=models.CharField(max_length=50, null=True),
+        ),
+    ]
diff --git a/server/api/migrations/0059_alter_galaxyworkflow_version.py b/server/api/migrations/0059_alter_galaxyworkflow_version.py
new file mode 100644
index 0000000000000000000000000000000000000000..672039e5e80a70907c19e6161ddeb2315bd6b202
--- /dev/null
+++ b/server/api/migrations/0059_alter_galaxyworkflow_version.py
@@ -0,0 +1,18 @@
+# Generated by Django 3.2.7 on 2022-03-12 02:32
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('api', '0058_alter_galaxyworkflow_version'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='galaxyworkflow',
+            name='version',
+            field=models.CharField(max_length=50),
+        ),
+    ]
diff --git a/server/api/migrations/0060_peak_p_value.py b/server/api/migrations/0060_peak_p_value.py
new file mode 100644
index 0000000000000000000000000000000000000000..c4ea20274c83fdc2012d0be44f3e0147c4dd07b9
--- /dev/null
+++ b/server/api/migrations/0060_peak_p_value.py
@@ -0,0 +1,18 @@
+# Generated by Django 3.2.7 on 2022-03-14 12:21
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('api', '0059_alter_galaxyworkflow_version'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='peak',
+            name='p_value',
+            field=models.FloatField(null=True),
+        ),
+    ]
diff --git a/server/api/migrations/0061_auto_20220316_1318.py b/server/api/migrations/0061_auto_20220316_1318.py
new file mode 100644
index 0000000000000000000000000000000000000000..22be5039e0902f3b76085410acf37bde3bab38a1
--- /dev/null
+++ b/server/api/migrations/0061_auto_20220316_1318.py
@@ -0,0 +1,52 @@
+# Generated by Django 3.2.7 on 2022-03-16 12:18
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('api', '0060_peak_p_value'),
+    ]
+
+    operations = [
+        migrations.RemoveConstraint(
+            model_name='phenotypecategory',
+            name='api_phenotypecategory_nature_valid',
+        ),
+        migrations.RemoveConstraint(
+            model_name='phenotypecategory',
+            name='api_phenotypecategory_location_valid',
+        ),
+        migrations.RemoveConstraint(
+            model_name='phenotypecategory',
+            name='api_phenotypecategory_datatype_valid',
+        ),
+        migrations.AlterField(
+            model_name='phenotypecategory',
+            name='datatype',
+            field=models.CharField(choices=[('Float', 'Float'), ('Integer', 'Integer'), ('Char', 'Char'), ('Unassigned', 'Unassigned')], max_length=50),
+        ),
+        migrations.AlterField(
+            model_name='phenotypecategory',
+            name='location',
+            field=models.CharField(choices=[('Organ', 'Organ'), ('Whole_Organism', 'Whole Organism'), ('Unassigned', 'Unassigned')], max_length=200),
+        ),
+        migrations.AlterField(
+            model_name='phenotypecategory',
+            name='nature',
+            field=models.CharField(choices=[('Quantitative', 'Quantitative'), ('Categorical', 'Categorical'), ('Measurement', 'Measurement'), ('Count', 'Count'), ('Semi_Quantitative', 'Semi Quantitative'), ('Unassigned', 'Unassigned')], max_length=200),
+        ),
+        migrations.AddConstraint(
+            model_name='phenotypecategory',
+            constraint=models.CheckConstraint(check=models.Q(('nature__in', ['Quantitative', 'Categorical', 'Measurement', 'Count', 'Semi_Quantitative', 'Unassigned'])), name='api_phenotypecategory_nature_valid'),
+        ),
+        migrations.AddConstraint(
+            model_name='phenotypecategory',
+            constraint=models.CheckConstraint(check=models.Q(('location__in', ['Organ', 'Whole_Organism', 'Unassigned'])), name='api_phenotypecategory_location_valid'),
+        ),
+        migrations.AddConstraint(
+            model_name='phenotypecategory',
+            constraint=models.CheckConstraint(check=models.Q(('datatype__in', ['Float', 'Integer', 'Char', 'Unassigned'])), name='api_phenotypecategory_datatype_valid'),
+        ),
+    ]
diff --git a/server/api/migrations/0062_alter_experimentccline_unique_together.py b/server/api/migrations/0062_alter_experimentccline_unique_together.py
new file mode 100644
index 0000000000000000000000000000000000000000..1c4e8100a74c5f759c4e90cb0f08b3ae6d4ddcea
--- /dev/null
+++ b/server/api/migrations/0062_alter_experimentccline_unique_together.py
@@ -0,0 +1,17 @@
+# Generated by Django 3.2.7 on 2022-03-17 20:57
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('api', '0061_auto_20220316_1318'),
+    ]
+
+    operations = [
+        migrations.AlterUniqueTogether(
+            name='experimentccline',
+            unique_together={('experiment', 'cc_line_id', 'cc_line_f')},
+        ),
+    ]
diff --git a/server/api/migrations/0063_alter_experimentccline_unique_together.py b/server/api/migrations/0063_alter_experimentccline_unique_together.py
new file mode 100644
index 0000000000000000000000000000000000000000..f5b1db8627acb57343dbd93e1fac29a8d724fed4
--- /dev/null
+++ b/server/api/migrations/0063_alter_experimentccline_unique_together.py
@@ -0,0 +1,17 @@
+# Generated by Django 3.2.7 on 2022-03-17 20:57
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('api', '0062_alter_experimentccline_unique_together'),
+    ]
+
+    operations = [
+        migrations.AlterUniqueTogether(
+            name='experimentccline',
+            unique_together={('experiment', 'cc_line_id')},
+        ),
+    ]
diff --git a/server/api/models.py b/server/api/models.py
index 72af7f291e90e1fd9c71dbdcc075454115689649..96c24d0ffe4a0f71cf0b032795a16a4fc1e1b554 100644
--- a/server/api/models.py
+++ b/server/api/models.py
@@ -17,47 +17,78 @@ from django.db.utils import IntegrityError
 # Guardian
 from guardian.models import UserObjectPermissionBase
 from guardian.models import GroupObjectPermissionBase
-from guardian.shortcuts import assign_perm
+from guardian.shortcuts import assign_perm, remove_perm
+
+# bioblend
+from bioblend import ConnectionError
 
 
 from .managers import (
+    AnalysisCategoryManager,
     DepartmentManager,
     FounderManager,
+    GalaxyInstanceManager,
+    GalaxyUserManager,
+    GalaxyWorkflowManager,
+    PeakManager,
     ProjectRoleManager,
+    RoleGroupManager,
     RoleManager,
     MarkerManager,
     CCLineManager,
-    VariableCategoryManager,
+    PhenotypeCategoryManager,
 )
 
 from .galaxy import GalaxyRunner
 from .exceptions import RessourceAlreadyExists
 
 # Create your models here.
+runner = GalaxyRunner()
 
 
 class User(AbstractUser):
-    def save(self, *args, **kwargs):
-        super().save(*args, **kwargs)  # Call the "real" save() method.
-
-        if self.username != "AnonymousUser":
-            # By default, new user have app-user role
-            generic_user_group = RoleGroup.objects.get(name__exact="app-user")
-            # get userperm
+    pass
 
-            # permission user on object
-            all_user_permissions = Permission.objects.filter(content_type__model="user")
-            for perm in all_user_permissions:
-                assign_perm(perm, self, self)
 
-            # permission group on object
-            role_user_permissions = generic_user_group.role.permissions.filter(
-                content_type__model="user"
+class ProjectManager(models.Manager):
+    @transaction.atomic
+    def create(self, *args, **kwargs):
+        creator = kwargs.pop("creator")
+        project = super().create(*args, **kwargs)
+        project_roles = ProjectRole.objects.all()
+        for project_role in project_roles:
+            project_group = ProjectGroup(
+                project=project,
+                project_role=project_role,
+                name=project.project_name + "_" + str(project_role),
             )
-            for perm in role_user_permissions:
-                assign_perm(perm, generic_user_group, self)
+            project_group.save()
+
+            # assign group permissions to this instance
+            # project_group.add_permissions()
 
-            generic_user_group.user_set.add(self)
+            # add the user to a this group
+            if str(project_role) == "manager":
+                project_group.user_set.add(creator)
+
+        # Add project group permissions
+        # (How a role can add/remove/change project role)
+        # ProjectGroup.objects.add_projectgroup_permissions_per_project(project)
+        # ProjectGroup.objects.add_permissions_per_project(project)
+        project.add_permissions()
+        return project
+
+    def add_permissions(self):
+        for project in self.all():
+            project.add_permissions()
+
+    def clear_permissions(self):
+        for project in self.all():
+            project.clear_permissions()
+
+    def update_permissions(self):
+        self.clear_permissions()
+        self.add_permissions()
 
 
 class Project(models.Model):
@@ -67,19 +98,27 @@ class Project(models.Model):
 
     # A project belongs to one group
     # group = models.OneToOneField(Group, on_delete=models.CASCADE)
-    project_name = models.CharField(max_length=200)
+    project_name = models.CharField(max_length=200, unique=True)
     description = models.TextField(blank=True)
     creation_date = models.DateTimeField(default=timezone.now)
-    objects = models.Manager()
+    # objects = models.Manager()
+    objects = ProjectManager()
 
     def __str__(self):
         return self.project_name
 
     class Meta:
         ordering = ["creation_date"]
-        constraints = [
-            models.UniqueConstraint(fields=["project_name"], name="project_name_unique")
-        ]
+
+    def add_permissions(self):
+        ProjectGroup.objects.add_permissions_per_project(self)
+
+    def clear_permissions(self):
+        ProjectGroup.objects.clear_permissions_per_project(self)
+
+    def update_permissions(self):
+        self.clear_permissions()
+        self.add_permissions()
 
 
 # Add foreign keys to handle permission deletion when object is deleted
@@ -91,6 +130,70 @@ class ProjectGroupObjectPermission(GroupObjectPermissionBase):
     content_object = models.ForeignKey(Project, on_delete=models.CASCADE)
 
 
+class PhenotypeNature(models.TextChoices):
+    Quantitative = ("Quantitative",)
+    Categorical = ("Categorical",)
+    Measurement = ("Measurement",)
+    Count = ("Count",)
+    Semi_Quantitative = ("Semi_Quantitative",)
+    Unassigned = ("Unassigned",)
+
+
+class PhenotypeLocation(models.TextChoices):
+    Organ = ("Organ",)
+    Whole_Organism = ("Whole_Organism",)
+    Unassigned = ("Unassigned",)
+
+
+class Datatype(models.TextChoices):
+    Float = ("Float",)
+    Integer = ("Integer",)
+    Char = ("Char",)
+    Unassigned = ("Unassigned",)
+
+
+class Dataclass(models.TextChoices):
+    Phenotype = ("Phenotype",)
+    Covariate = ("Covariate",)
+
+
+class PhenotypeCategory(models.Model):
+    name = models.CharField(max_length=200, unique=True)
+    description = models.CharField(max_length=400)
+    nature = models.CharField(max_length=200, choices=PhenotypeNature.choices)
+    location = models.CharField(max_length=200, choices=PhenotypeLocation.choices)
+    datatype = models.CharField(max_length=50, choices=Datatype.choices)
+    dataclass = models.CharField(max_length=20, choices=Dataclass.choices)
+    objects = PhenotypeCategoryManager()
+
+    class Meta:
+        ordering = ["name"]
+        constraints = [
+            models.CheckConstraint(
+                name="%(app_label)s_%(class)s_nature_valid",
+                check=models.Q(nature__in=PhenotypeNature.values),
+            ),
+            models.CheckConstraint(
+                name="%(app_label)s_%(class)s_location_valid",
+                check=models.Q(location__in=PhenotypeLocation.values),
+            ),
+            models.CheckConstraint(
+                name="%(app_label)s_%(class)s_datatype_valid",
+                check=models.Q(datatype__in=Datatype.values),
+            ),
+            models.CheckConstraint(
+                name="%(app_label)s_%(class)s_dataclass_valid",
+                check=models.Q(dataclass__in=Dataclass.values),
+            ),
+        ]
+
+    def __str__(self):
+        return self.name
+
+    def natural_key(self):
+        return (self.name,)
+
+
 class Experiment(models.Model):
     """
     Store experiments
@@ -102,16 +205,13 @@ class Experiment(models.Model):
     project = models.ForeignKey(
         Project, on_delete=models.CASCADE, related_name="experiments"
     )
+    phenotype_categories = models.ManyToManyField(PhenotypeCategory)
 
     objects = models.Manager()
 
     class Meta:
         ordering = ["creation_date"]
-        constraints = [
-            models.UniqueConstraint(
-                fields=["name", "project"], name="experiment_name_unique"
-            )
-        ]
+        unique_together = [["name", "project"]]
 
     def __str__(self):
         return self.name
@@ -141,9 +241,10 @@ class Experiment(models.Model):
                 raise RessourceAlreadyExists()
                 # Add reader role to the team the current user belongs
 
-    def generate_experiment_file(self, name):
-        variables = (
-            Variable.objects.filter(experiment_cc_line__experiment=self)
+    def generate_experiment_file(self, name, phenotype_type_name, galaxy_workflow_id):
+        galaxy_workflow_excel = {"657f009ad32a3f27", "bd6cadfea4e7afba"}
+        phenotypes = (
+            Phenotype.objects.filter(experiment_cc_line__experiment=self)
             .values(
                 "value",
                 "category__name",
@@ -155,37 +256,56 @@ class Experiment(models.Model):
             )
             .annotate(
                 id=models.F("experiment_cc_line__id"),
-                CC_ID=models.F("experiment_cc_line__cc_line_id"),
-                variable_type=models.F("category__name"),
-                Line_M=models.F("experiment_cc_line__cc_line_m__id_cc"),
-                Line_F=models.F("experiment_cc_line__cc_line_f__id_cc"),
+                Individual_ID=models.F("experiment_cc_line__cc_line_id"),
+                phenotype_type=models.F("category__name"),
+                Mother_Line=models.F("experiment_cc_line__cc_line_m__id_cc"),
+                Father_Line=models.F("experiment_cc_line__cc_line_f__id_cc"),
                 Sex=models.F("experiment_cc_line__sex"),
             )
-            .values("id", "CC_ID", "value", "variable_type", "Line_M", "Line_F", "Sex",)
+            .values(
+                "id",
+                "Individual_ID",
+                "value",
+                "phenotype_type",
+                "Mother_Line",
+                "Father_Line",
+                "Sex",
+            )
         )
 
-        df_variables = pd.DataFrame(data=variables)
-        variables = df_variables.variable_type.unique()
-
-        df = df_variables
-        pivoted = df.pivot_table(
-            values="value",
-            index=["id", "CC_ID", "Line_M", "Line_F", "Sex"],
-            columns="variable_type",
-            aggfunc="first",
-        )
-        columns = ["CC_ID", "Line_M", "Line_F", "Sex"] + variables.tolist()
-        pivoted.reset_index(inplace=True)
-        dirpath = tempfile.mkdtemp(prefix="cc-qtl-", dir="/tmp-exp-files")
-        experiment_file_path = f"{dirpath}/{name}.xls"
-        pivoted.to_excel(
-            experiment_file_path, index=False, columns=columns,
-        )
-        return experiment_file_path
+        df_phenotypes = pd.DataFrame(data=phenotypes)
+        phenotypes = df_phenotypes.phenotype_type.unique()
+        if phenotype_type_name in phenotypes:
+            # df = df_phenotypes
+            pivoted = df_phenotypes.pivot_table(
+                values="value",
+                index=["id", "Individual_ID", "Mother_Line", "Father_Line", "Sex"],
+                columns="phenotype_type",
+                aggfunc="first",
+            )
+            # phenotypes
+            columns = ["Individual_ID", "Mother_Line", "Father_Line", "Sex"] + [
+                phenotype_type_name
+            ]
+            pivoted.reset_index(inplace=True)
+            dirpath = tempfile.mkdtemp(prefix="cc-qtl-", dir="/tmp-exp-files")
+            if galaxy_workflow_id in galaxy_workflow_excel:
+                experiment_file_path = f"{dirpath}/{name}.xls"
+                pivoted.to_excel(
+                    experiment_file_path, index=False, columns=columns,
+                )
+            else:
+                experiment_file_path = f"{dirpath}/{name}.csv"
+                pivoted.to_csv(
+                    experiment_file_path, index=False, columns=columns,
+                )
+            return experiment_file_path
+        else:
+            raise NameError(f"No phenotype type defined for {phenotype_type_name}")
 
     def get_experiment_data(self):
         return (
-            Variable.objects.filter(experiment_cc_line__experiment=self)
+            Phenotype.objects.filter(experiment_cc_line__experiment=self)
             .values(
                 "id",
                 "value",
@@ -201,7 +321,7 @@ class Experiment(models.Model):
             )
             .annotate(
                 ccline_id=models.F("experiment_cc_line__cc_line_id"),
-                variable_type=models.F("category__name"),
+                phenotype_type=models.F("category__name"),
                 ccline_m_id=models.F("experiment_cc_line__cc_line_m__id"),
                 id_cc_m=models.F("experiment_cc_line__cc_line_m__id_cc"),
                 ccline_f_id=models.F("experiment_cc_line__cc_line_f__id"),
@@ -213,7 +333,7 @@ class Experiment(models.Model):
             .values(
                 "id",
                 "value",
-                "variable_type",
+                "phenotype_type",
                 "ccline_id",
                 "ccline_m_id",
                 "id_cc_m",
@@ -227,9 +347,9 @@ class Experiment(models.Model):
 
         # rename the keys
 
-    def get_experiment_variable_types(self):
+    def get_experiment_phenotype_types(self):
         return (
-            Variable.objects.filter(experiment_cc_line__experiment=self)
+            Phenotype.objects.filter(experiment_cc_line__experiment=self)
             .values(
                 "category__id",
                 "category__name",
@@ -267,7 +387,7 @@ class Role(models.Model):
     objects = RoleManager()
 
     permissions = models.ManyToManyField(Permission)
-    name = models.CharField(max_length=128)
+    name = models.CharField(max_length=128, unique=True)
     priority = models.PositiveIntegerField()
 
     def __str__(self):
@@ -276,11 +396,6 @@ class Role(models.Model):
     def natural_key(self):
         return (self.name,)
 
-    class Meta:
-        constraints = [
-            models.UniqueConstraint(fields=["name"], name="role_name_unique")
-        ]
-
 
 class ProjectRole(models.Model):
     """
@@ -288,7 +403,7 @@ class ProjectRole(models.Model):
     """
 
     permissions = models.ManyToManyField(Permission)
-    name = models.CharField(max_length=128)
+    name = models.CharField(max_length=128, unique=True)
     priority = models.PositiveIntegerField()
 
     objects = ProjectRoleManager()
@@ -296,23 +411,13 @@ class ProjectRole(models.Model):
     def __str__(self):
         return self.name
 
-    class Meta:
-        constraints = [
-            models.UniqueConstraint(fields=["name"], name="projectrole_name_unique")
-        ]
-
     def natural_key(self):
         return (self.name,)
 
 
 class Department(models.Model):
     objects = DepartmentManager()
-    name = models.CharField(max_length=128, null=False)
-
-    class Meta:
-        constraints = [
-            models.UniqueConstraint(fields=["name"], name="department_name_unique"),
-        ]
+    name = models.CharField(max_length=128, null=False, unique=True)
 
     def __str__(self):
         return self.name
@@ -332,11 +437,7 @@ class Team(Group):
     )
 
     class Meta:
-        constraints = [
-            models.UniqueConstraint(
-                fields=["group_ptr", "department"], name="team_department_unique"
-            ),
-        ]
+        unique_together = [["group_ptr", "department"]]
 
     def __str__(self):
         return self.name
@@ -358,19 +459,80 @@ class Team(Group):
             raise RessourceAlreadyExists()
 
 
+class ProjectGroupManager(models.Manager):
+    def check_has_projectgroup_per_role(self, project):
+        project_groups = self.filter(project=project)
+        project_roles = ProjectRole.objects.all()
+        # check if each role has a project_group associated
+        project_group_role_names = set([pg.project_role.name for pg in project_groups])
+        role_names = set([pr.name for pr in project_roles])
+        if project_group_role_names != role_names:
+            raise Exception(f"No group for each role in project {project}")
+
+    def add_permissions_per_project(self, project):
+        # get the project group associated to a projec
+        self.check_has_projectgroup_per_role(project)
+        project_groups = self.filter(project=project)
+        for pg in project_groups:
+            pg.add_permissions()
+        self.add_projectgroup_permissions_per_project(project)
+
+    def clear_permissions_per_project(self, project):
+        project_groups = self.filter(project=project)
+        for pg in project_groups:
+            pg.clear_permissions()
+        self.clear_projectgroup_permissions_per_project(project)
+
+    def update_permissions_per_project(self, project):
+        self.clear_permissions_per_project(project)
+        self.add_permissions_per_project(project)
+
+    # Permissions for projectgroup themselves
+    def add_projectgroup_permissions(self):
+        for project in Project.objects.all():
+            self.add_projectgroup_permissions_per_project(project)
+
+    def clear_projectgroup_permissions(self):
+        # Get all projectgroup permissions
+        for project in Project.objects.all():
+            self.clear_projectgroup_permissions_per_project(project)
+
+    def update_projectgroup_permissions(self):
+        self.clear_projectgroup_permissions()
+        self.add_projectgroup_permissions()
+
+    def add_projectgroup_permissions_per_project(self, project):
+        project_groups = self.filter(project=project)
+        self.check_has_projectgroup_per_role(project)
+        for pg_set_perm in project_groups:
+            projectgroup_permissions = pg_set_perm.project_role.permissions.filter(
+                content_type__model="projectgroup"
+            )
+            for perm in projectgroup_permissions:
+                for pg_object in project_groups:
+                    assign_perm(perm, pg_set_perm, pg_object)
+
+    def clear_projectgroup_permissions_per_project(self, project):
+        all_permissions = Permission.objects.filter(content_type__model="projectgroup")
+        project_groups = self.filter(project=project)
+        for pg_remove_perms in project_groups:
+            for obj in project_groups:
+                for perm in all_permissions:
+                    remove_perm(perm, pg_remove_perms, obj)
+
+
 class ProjectGroup(Group):
-    project = models.ForeignKey(Project, on_delete=models.CASCADE)
+    project = models.ForeignKey(
+        Project, on_delete=models.CASCADE, related_name="project_group_set"
+    )
+
     project_role = models.ForeignKey(
         ProjectRole, on_delete=models.CASCADE, related_name="project_group_set"
     )
-    objects = models.Manager()
+    objects = ProjectGroupManager()
 
     class Meta:
-        constraints = [
-            models.UniqueConstraint(
-                fields=["project", "project_role"], name="project_role_unique"
-            ),
-        ]
+        unique_together = [["project", "project_role"]]
 
     def __str__(self):
         return self.name
@@ -378,6 +540,57 @@ class ProjectGroup(Group):
     def natural_key(self):
         return (self.name, self.project, self.project_role)
 
+    def add_permissions(self):
+        permissions = self.project_role.permissions.filter(
+            content_type__model="project"
+        )
+
+        for project_perm in permissions:
+            assign_perm(project_perm, self, self.project)
+            assign_perm(project_perm, self)
+
+        # experiment permissions
+        experiment_permissions = self.project_role.permissions.filter(
+            content_type__model="experiment"
+        )
+        for experiment_perm in experiment_permissions:
+            assign_perm(experiment_perm, self)
+
+        # assign analysis permissions
+        analysis_permissions = self.project_role.permissions.filter(
+            content_type__model="analysis"
+        )
+        for perm in analysis_permissions:
+            assign_perm(perm, self)
+
+        # assign peak permissions
+        peak_permissions = self.project_role.permissions.filter(
+            content_type__model="peak"
+        )
+        for perm in peak_permissions:
+            assign_perm(perm, self)
+
+        # assign project group permissions
+        projectgroup_permissions = self.project_role.permissions.filter(
+            content_type__model="projectgroup"
+        )
+        # assign model project group permissions
+        for perm in projectgroup_permissions:
+            assign_perm(perm, self)
+
+    def clear_permissions(self):
+        # delete all permission for this group
+        self.permissions.clear()
+
+        # Delete specific permissions for linked project
+        ProjectGroupObjectPermission.objects.filter(
+            content_object=self.project, group=self
+        ).delete()
+
+    def update_permission(self):
+        self.clear_permissions()
+        self.add_permissions()
+
 
 # Add foreign keys to handle permission deletion when object is deleted
 # class ProjectGroupUserObjectPermission(UserObjectPermissionBase):
@@ -390,7 +603,7 @@ class ProjectGroup(Group):
 
 class RoleGroup(Group):
     role = models.ForeignKey(Role, on_delete=models.CASCADE)
-    objects = models.Manager()
+    objects = RoleGroupManager()
 
     def __str__(self):
         return self.name
@@ -401,9 +614,9 @@ class RoleGroup(Group):
 
 class Founder(models.Model):
 
-    name = models.CharField(max_length=200)
+    name = models.CharField(max_length=200, unique=True)
     short_name = models.CharField(max_length=20, blank=True)
-    cc_designation = models.CharField(max_length=10, blank=True)
+    cc_designation = models.CharField(max_length=10, blank=True, unique=True)
     color = models.CharField(max_length=10, blank=True)
     objects = FounderManager()
 
@@ -415,17 +628,11 @@ class Founder(models.Model):
 
     class Meta:
         ordering = ["name"]
-        constraints = [
-            models.UniqueConstraint(fields=["name"], name="founder_name_unique"),
-            models.UniqueConstraint(
-                fields=["cc_designation"], name="founder_cc_designation_unique"
-            ),
-        ]
 
 
 class Marker(models.Model):
 
-    id_marker = models.CharField(max_length=200)
+    id_marker = models.CharField(max_length=200, unique=True)
     chromosome = models.CharField(max_length=200)
     position = models.PositiveIntegerField()
     objects = MarkerManager()
@@ -438,20 +645,16 @@ class Marker(models.Model):
 
     class Meta:
         ordering = ["chromosome"]
-        constraints = [
-            models.UniqueConstraint(fields=["id_marker"], name="id_marker_unique")
-        ]
 
 
 class Ccline(models.Model):
-    id_cc = models.CharField(max_length=200)
+    id_cc = models.CharField(max_length=200, unique=True)
     markers = models.ManyToManyField(Marker, through="CclineMarker")
     funnel_code = models.CharField(max_length=8)
     objects = CCLineManager()
 
     class Meta:
         ordering = ["id_cc"]
-        constraints = [models.UniqueConstraint(fields=["id_cc"], name="id_cc_unique")]
 
     def __str__(self):
         return self.id_cc
@@ -479,72 +682,31 @@ class IUPAC(models.TextChoices):
     ZERO = "Z", _("Zero")
 
 
-class Sex(models.TextChoices):
-    Female = "F", _("Female")
-    Male = "M", _("Male")
-
-
-class VariableNature(models.TextChoices):
-    Quantitative = ("Quantitative",)
-    Categorical = ("Categorical",)
-    Measurement = ("Measurement",)
-    Count = ("Count",)
-    Semi_Quantitative = ("Semi_Quantitative",)
-
-
-class VariableLocation(models.TextChoices):
-    Organ = ("Organ",)
-    Whole_Organism = ("Whole_Organism",)
-    other = ("Other",)
-
-
-class Datatype(models.TextChoices):
-    Float = ("Float",)
-    Integer = ("Integer",)
-    Char = ("Char",)
-
-
-class Dataclass(models.TextChoices):
-    Variable = ("Variable",)
-    Covariate = ("Covariate",)
-
-
 class CclineMarker(models.Model):
     cc_line = models.ForeignKey(Ccline, on_delete=models.CASCADE)
     marker = models.ForeignKey(Marker, on_delete=models.CASCADE)
     base = models.CharField(max_length=1, choices=IUPAC.choices)
 
-
-class VariableCategory(models.Model):
-    name = models.CharField(max_length=200)
-    description = models.CharField(max_length=400)
-    nature = models.CharField(max_length=200, choices=VariableNature.choices)
-    location = models.CharField(max_length=200, choices=VariableLocation.choices)
-    datatype = models.CharField(max_length=50, choices=Datatype.choices)
-    dataclass = models.CharField(max_length=20, choices=Dataclass.choices)
-    objects = VariableCategoryManager()
-
     class Meta:
-        ordering = ["name"]
         constraints = [
-            models.UniqueConstraint(
-                fields=["name", "nature", "datatype", "location", "dataclass"],
-                name="variable_type_unique",
-            )
+            models.CheckConstraint(
+                name="%(app_label)s_%(class)s_base_valid",
+                check=models.Q(base__in=IUPAC.values),
+            ),
         ]
 
-    def __str__(self):
-        return self.name
 
-    def natural_key(self):
-        return (self.name,)
+class Sex(models.TextChoices):
+    Female = "F", _("Female")
+    Male = "M", _("Male")
 
 
 class ExperimentCcline(models.Model):
+
     experiment = models.ForeignKey(
         Experiment, on_delete=models.CASCADE, related_name="cclines"
     )
-    cc_line_id = models.IntegerField()
+    cc_line_id = models.CharField(max_length=50)
     cc_line_m = models.ForeignKey(
         Ccline, on_delete=models.CASCADE, related_name="ccline_m"
     )
@@ -555,25 +717,28 @@ class ExperimentCcline(models.Model):
 
     class Meta:
         ordering = ["experiment", "cc_line_id"]
+        unique_together = [["experiment", "cc_line_id"]]
         constraints = [
-            models.UniqueConstraint(
-                fields=["experiment", "cc_line_id"], name="experiement_cc_line_unique"
-            )
+            models.CheckConstraint(
+                name="%(app_label)s_%(class)s_sex_valid",
+                check=models.Q(sex__in=Sex.values),
+            ),
         ]
 
     def __str__(self):
-        return f"{self.cc_line_m} x {self.cc_line_f} -> {self.sex}"
+        return f"{self.cc_line_m} x {self.cc_line_f} -> {Sex(self.sex).label}"
 
 
-class Variable(models.Model):
-    category = models.ForeignKey(VariableCategory, on_delete=models.CASCADE)
+class Phenotype(models.Model):
+    category = models.ForeignKey(PhenotypeCategory, on_delete=models.PROTECT)
     experiment_cc_line = models.ForeignKey(
-        ExperimentCcline, on_delete=models.CASCADE, related_name="variables"
+        ExperimentCcline, on_delete=models.CASCADE, related_name="phenotypes"
     )
     value = models.CharField(max_length=100)
 
     class Meta:
         ordering = ["experiment_cc_line"]
+        unique_together = [["experiment_cc_line", "category"]]
 
     def __str__(self):
         return f"{self.category} {self.experiment_cc_line} {self.value}"
@@ -582,8 +747,72 @@ class Variable(models.Model):
         return (self.name,)
 
 
+class AnalysisCategory(models.Model):
+    name = models.CharField(max_length=50, unique=True)
+    description = models.TextField(blank=True)
+
+    objects = AnalysisCategoryManager()
+
+    class Meta:
+        ordering = ["name"]
+
+    def natural_key(self):
+        return (self.name,)
+
+
+class GalaxyInstance(models.Model):
+    name = models.CharField(max_length=200, unique=True)
+    url = models.URLField(unique=True)
+    description = models.TextField(blank=True)
+
+    objects = GalaxyInstanceManager()
+
+    class Meta:
+        ordering = ["name"]
+
+    def natural_key(self):
+        return (self.name,)
+
+    def __str__(self):
+        return self.name
+
+
+class GalaxyUser(models.Model):
+    username = models.EmailField(max_length=254, unique=True)
+    api_key = models.CharField(max_length=254, blank=True)
+    galaxy_instance = models.ForeignKey(GalaxyInstance, on_delete=models.DO_NOTHING)
+
+    objects = GalaxyUserManager()
+
+    class Meta:
+        ordering = ["username", "galaxy_instance"]
+        # unique_together = [["username", "galaxy_instance"]]
+
+    def natural_key(self):
+        # print("dan natural key galaxy user model")
+        return (self.username,)
+
+
+class GalaxyWorkflow(models.Model):
+    name = models.CharField(max_length=200)
+    galaxy_workflow_id = models.CharField(max_length=200, blank=True)
+    analysis_category = models.ForeignKey(AnalysisCategory, on_delete=models.DO_NOTHING)
+    galaxy_user = models.ForeignKey(GalaxyUser, on_delete=models.DO_NOTHING,)
+    version = models.CharField(max_length=50)
+
+    objects = GalaxyWorkflowManager()
+
+    class Meta:
+        ordering = ["analysis_category", "name"]
+        unique_together = [["galaxy_workflow_id", "galaxy_user"]]
+
+    def natural_key(self):
+        return (self.galaxy_workflow_id, self.galaxy_user)
+
+
 class Analysis(models.Model):
     name = models.CharField(max_length=200)
+    description = models.TextField(blank=True)
     galaxy_history_id = models.CharField(max_length=200, blank=True)
     galaxy_workflow_id = models.CharField(max_length=200, blank=True)
     galaxy_workflow_invocation_id = models.CharField(max_length=200, blank=True)
@@ -592,15 +821,12 @@ class Analysis(models.Model):
         Project, on_delete=models.CASCADE, related_name="analysis"
     )
     creation_date = models.DateTimeField(default=timezone.now)
+    phenotype_categories = models.ManyToManyField(PhenotypeCategory)
 
     objects = models.Manager()
 
     class Meta:
-        constraints = [
-            models.UniqueConstraint(
-                fields=["name", "galaxy_history_id"], name="analysis_unique",
-            )
-        ]
+        unique_together = [["name", "galaxy_history_id"]]
         verbose_name_plural = "analyzes"
 
     def __str__(self):
@@ -634,9 +860,31 @@ class Analysis(models.Model):
                 raise RessourceAlreadyExists()
                 # Add reader role to the team the current user belongs
 
-    def get_workflow_job_params(self):
-
-        runner = GalaxyRunner()
+    @property
+    def history_status(self):
+        if self.galaxy_history_id:
+            try:
+                history_status = runner.get_history_status(self.galaxy_history_id)
+                return history_status
+            except ConnectionError:
+                return None
+        else:
+            return None
+
+    @property
+    def workflow_invocation_status(self):
+        if self.galaxy_workflow_invocation_id:
+            try:
+                status = runner.get_workflow_invocation_status(
+                    self.galaxy_workflow_id, self.galaxy_workflow_invocation_id
+                )
+                return status
+            except ConnectionError:
+                return None
+        else:
+            return None
+
+    def get_workflow_job_parameters(self):
         gi = runner.galaxy_instance
         invocation = gi.workflows.show_invocation(
             workflow_id=self.galaxy_workflow_id,
@@ -666,7 +914,6 @@ class Analysis(models.Model):
         return dict(job_detail(invocation["steps"]))
 
     def get_workflow_invocation(self):
-        runner = GalaxyRunner()
         gi = runner.galaxy_instance
         invocation = gi.workflows.show_invocation(
             workflow_id=self.galaxy_workflow_id,
@@ -682,7 +929,8 @@ class Analysis(models.Model):
             for step in invocation["steps"]:
                 if step["job_id"] is not None:
                     job = gi.jobs.show_job(step["job_id"], full_details=True)
-                    tool = gi.tools.show_tool(job["tool_id"])
+                    tool = gi.tools.show_tool(job["tool_id"], io_details=True)
+                    metrics = job["job_metrics"] if "job_metrics" in job else []
                     yield (
                         {
                             "step_id": step["order_index"],
@@ -690,7 +938,7 @@ class Analysis(models.Model):
                             "job": {
                                 "create_time": job["create_time"],
                                 "update_time": job["update_time"],
-                                "metrics": job["job_metrics"],
+                                "metrics": metrics,
                                 "state": job["state"],
                                 "params": dict(
                                     [
@@ -723,12 +971,12 @@ class Result(models.Model):
 
 
 class LodScore(models.Model):
-    analysis = models.ForeignKey(Analysis, on_delete=models.CASCADE)
+    analysis = models.OneToOneField(Analysis, on_delete=models.CASCADE)
     lod_scores = models.JSONField()
+    significance_thresholds = models.JSONField(blank=True, default=list)
 
     class Meta:
         ordering = ["analysis"]
-        constraints = [models.UniqueConstraint(fields=["analysis"], name="lod_unique",)]
 
     def __str__(self):
         return f"{self.analysis}"
@@ -743,12 +991,6 @@ class LodScoreGroupObjectPermission(GroupObjectPermissionBase):
     content_object = models.ForeignKey(LodScore, on_delete=models.CASCADE)
 
 
-class LodScoreSignificanceThreshold(models.Model):
-    analysis = models.ForeignKey(Analysis, on_delete=models.CASCADE)
-    significance = models.FloatField()
-    threshold = models.FloatField()
-
-
 class Peak(models.Model):
     analysis = models.ForeignKey(
         Analysis, on_delete=models.CASCADE, related_name="peaks"
@@ -759,15 +1001,13 @@ class Peak(models.Model):
     lod = models.FloatField()
     ci_lo = models.FloatField()
     ci_hi = models.FloatField()
+    p_value = models.FloatField(null=True)
+
+    objects = PeakManager()
 
     class Meta:
         ordering = ["analysis", "variable_name", "chromosome", "position"]
-        constraints = [
-            models.UniqueConstraint(
-                fields=["analysis", "variable_name", "chromosome", "position"],
-                name="peak_unique",
-            )
-        ]
+        unique_together = [["analysis", "variable_name", "chromosome", "position"]]
 
     def __str__(self):
         return f"{self.variable_name} {self.chromosome} {self.position}"
@@ -810,6 +1050,14 @@ class TopSnps(models.Model):
         return f"{self.peak}"
 
 
+class PeakGenes(models.Model):
+    peak = models.ForeignKey(Peak, on_delete=models.CASCADE, related_name="genes")
+    genes = models.JSONField()
+
+    def __str__(self):
+        return f"{self.peak}"
+
+
 class Haplotypes(models.Model):
     peak = models.ForeignKey(Peak, on_delete=models.CASCADE, related_name="haplotypes")
     haplotypes = models.JSONField()
diff --git a/server/api/permissions.py b/server/api/permissions.py
index efa7b801740d74dcdd19ce53d281ac21c950f932..b038e56757e6a845cdc5d9423afc079135182621 100644
--- a/server/api/permissions.py
+++ b/server/api/permissions.py
@@ -15,3 +15,38 @@ class CustomObjectPermissions(permissions.DjangoObjectPermissions):
         "PATCH": ["%(app_label)s.change_%(model_name)s"],
         "DELETE": ["%(app_label)s.delete_%(model_name)s"],
     }
+
+
+class CustomPermissions(permissions.DjangoModelPermissions):
+    """
+    Similar to `DjangoObjectPermissions`, but adding 'view' permissions.
+    """
+
+    perms_map = {
+        "GET": ["%(app_label)s.view_%(model_name)s"],
+        "OPTIONS": ["%(app_label)s.view_%(model_name)s"],
+        "HEAD": ["%(app_label)s.view_%(model_name)s"],
+        "POST": ["%(app_label)s.add_%(model_name)s"],
+        "PUT": ["%(app_label)s.change_%(model_name)s"],
+        "PATCH": ["%(app_label)s.change_%(model_name)s"],
+        "DELETE": ["%(app_label)s.delete_%(model_name)s"],
+    }
+
+
+class IsAdminOrIsSelf(permissions.BasePermission):
+    """Allow unsafe methods for admin users only."""
+
+    def has_permission(self, request, view):
+        user = view.get_object()
+        print(user)
+        # print(dir(request.user))
+        # print(bool(request.user))
+        # print(bool(request.user.is_authenticated))
+        if bool(not request.user or not request.user.is_authenticated):
+            return False
+        if request.user.is_superuser:
+            return True
+
+        if request.user.id is user.id:
+            return True
+        return False
diff --git a/server/api/serializers.py b/server/api/serializers.py
index 9164a8e2931ed517ee774ec5cc901fa5218e40ba..1c5e7e240a2c5fbe21eb49d7cc65c2cb2fb5cf61 100644
--- a/server/api/serializers.py
+++ b/server/api/serializers.py
@@ -1,29 +1,19 @@
-import json
 import pprint
-from pathlib import Path
-import shutil
 
 # Django
 from django.contrib.auth import get_user_model
 from django.contrib.auth.models import Group, Permission
+from django.db import IntegrityError
 
-from django.db.utils import IntegrityError
-from django.db import transaction
-from django.core.exceptions import ObjectDoesNotExist
 
 # Django Rest Framework
 from rest_framework import serializers
 
-from rest_framework.exceptions import NotFound
 
 from guardian.shortcuts import assign_perm
-from rest_framework.relations import PrimaryKeyRelatedField
 
 from rest_framework_nested.serializers import NestedHyperlinkedModelSerializer
 
-# Pandas
-import pandas as pd
-
 #
 # , File
 from .models import (
@@ -36,21 +26,22 @@ from .models import (
     Founder,
     Haplotypes,
     LodScore,
-    LodScoreSignificanceThreshold,
     Peak,
+    PeakGenes,
     Project,
     ProjectGroup,
     ProjectRole,
     Role,
+    RoleGroup,
     SnpsAssociation,
     Team,
     TopSnps,
-    VariableCategory,
-    Variable,
+    PhenotypeCategory,
+    Phenotype,
 )
 from .exceptions import RessourceAlreadyExists
 
-from .tasks import run_analyis, load_results
+from .tasks import run_analyis
 
 pp = pprint.PrettyPrinter(indent=4)
 
@@ -58,8 +49,31 @@ pp = pprint.PrettyPrinter(indent=4)
 User = get_user_model()
 
 
+class ProjectGroupMembershipSerializer(serializers.ModelSerializer):
+    project = serializers.SlugRelatedField(read_only=True, slug_field="project_name")
+    project_role = serializers.SlugRelatedField(read_only=True, slug_field="name")
+
+    class Meta:
+        model = ProjectGroup
+        fields = ("id", "project", "project_role")
+
+
+class GroupMembershipSerializer(serializers.ModelSerializer):
+    projectgroup = ProjectGroupMembershipSerializer(read_only=True)
+
+    class Meta:
+        model = Group
+        fields = ("id", "name", "projectgroup")
+
+
+class GroupSerializer(serializers.ModelSerializer):
+    class Meta:
+        model = Group
+        fields = ("id", "name")
+
+
 class UserSerializer(serializers.ModelSerializer):
-    groups = serializers.SlugRelatedField(many=True, read_only=True, slug_field="name")
+    groups = GroupMembershipSerializer(many=True, read_only=True)
 
     class Meta:
         model = User
@@ -74,18 +88,89 @@ class UserSerializer(serializers.ModelSerializer):
             "groups",
             "is_staff",
             "is_active",
+            "is_superuser",
         )
         extra_kwargs = {"password": {"write_only": True}}
+        read_only_fields = ("is_superuser", "is_staff")
 
     def create(self, validated_data, **kwargs):
-        # current_user = self.context["request"].user
         password = validated_data.pop("password")
         user = super().create(validated_data, **kwargs)
         user.set_password(password)
         user.save()
+
+        if "appGroup" in self.initial_data and self.initial_data["appGroup"]:
+            app_group = self.initial_data.pop("appGroup")
+            try:
+                role_group = RoleGroup.objects.get(pk=app_group["id"])
+            except RoleGroup.DoesNotExist:
+                role_group = RoleGroup.objects.get(name__exact="app-user")
+        else:
+            role_group = RoleGroup.objects.get(name__exact="app-user")
+        role_group.user_set.add(user)
+        # permission user on object
+        # this is necessary for current-user
+        all_user_permissions = Permission.objects.filter(content_type__model="user")
+        for perm in all_user_permissions:
+            assign_perm(perm, user, user)
+
+        # Assign permissions corresponding to the group to this new user
+        # role_user_permissions = role_group.role.permissions.filter(
+        #     content_type__model="user"
+        # )
+        # for perm in role_user_permissions:
+        #     assign_perm(perm, role_group, user)
+
         return user
 
 
+class ChangePasswordSerializer(serializers.Serializer):
+    model = User
+
+    """
+    Serializer for password change endpoint.
+    """
+    old_password = serializers.CharField(
+        write_only=True,
+        required=True,
+        style={"input_type": "password", "placeholder": "Password"},
+    )
+    new_password = serializers.CharField(
+        write_only=True,
+        required=True,
+        style={"input_type": "password", "placeholder": "Password"},
+    )
+    new_password_confirmation = serializers.CharField(
+        write_only=True,
+        required=True,
+        style={"input_type": "password", "placeholder": "Password"},
+    )
+
+    class Meta:
+        model = User
+        fields = ("old_password", "new_password", "new_password_confirmation")
+
+    def validate(self, attrs):
+        if attrs["new_password"] != attrs["new_password_confirmation"]:
+            raise serializers.ValidationError(
+                {"password": "New passwords fields didn't match."}
+            )
+        return attrs
+
+    def validate_old_password(self, value):
+        user = self.context["request"].user
+        if not user.check_password(value):
+            raise serializers.ValidationError(
+                {"old_password": "Old password is not correct"}
+            )
+        return value
+
+    def update(self, instance, validated_data):
+        instance.set_password(validated_data["new_password"])
+        instance.save()
+        return instance
+
+
 class PermissionSerializer(serializers.ModelSerializer):
     class Meta:
         model = Permission
@@ -107,9 +192,9 @@ class ProjectExperimentSerializer(NestedHyperlinkedModelSerializer):
         )
 
 
-class VariableCategorySerializer(serializers.HyperlinkedModelSerializer):
+class PhenotypeCategorySerializer(serializers.HyperlinkedModelSerializer):
     class Meta:
-        model = VariableCategory
+        model = PhenotypeCategory
         fields = (
             "id",
             "name",
@@ -121,15 +206,15 @@ class VariableCategorySerializer(serializers.HyperlinkedModelSerializer):
         )
 
 
-class ExperimentCclineVariableSerializer(NestedHyperlinkedModelSerializer):
+class ExperimentCclinePhenotypeSerializer(NestedHyperlinkedModelSerializer):
     parent_lookup_kwargs = {
         "experiment_cc_line_pk": "experiment_cc_line__pk",
         "project_pk": "experiment__project__pk",
     }
-    category = VariableCategorySerializer(read_only=True,)
+    category = PhenotypeCategorySerializer(read_only=True,)
 
     class Meta:
-        model = Variable
+        model = Phenotype
         fields = ("id", "value", "category")
 
 
@@ -163,24 +248,6 @@ class ProjectAnalysisSerializer(NestedHyperlinkedModelSerializer):
         fields = ("url", "name")
 
 
-class ExperimentSerializer(NestedHyperlinkedModelSerializer):
-
-    parent_lookup_kwargs = {"project_pk": "project__pk"}
-    cclines = ExperimentExperimentCclineSerializer(many=True, read_only=True,)
-
-    class Meta:
-        model = Experiment
-        fields = (
-            "url",
-            "id",
-            "name",
-            "project",
-            "description",
-            "creation_date",
-            "cclines",
-        )
-
-
 class ExperimentCclineSerializer(NestedHyperlinkedModelSerializer):
     # class ExperimentCclineSerializer(serializers.HyperlinkedModelSerializer):
 
@@ -189,7 +256,7 @@ class ExperimentCclineSerializer(NestedHyperlinkedModelSerializer):
         "experiment_pk": "experiment__pk",
     }
 
-    variables = ExperimentCclineVariableSerializer(many=True, read_only=True,)
+    phenotypes = ExperimentCclinePhenotypeSerializer(many=True, read_only=True,)
 
     class Meta:
         model = ExperimentCcline
@@ -199,7 +266,7 @@ class ExperimentCclineSerializer(NestedHyperlinkedModelSerializer):
             "cc_line_m",
             "cc_line_f",
             "sex",
-            "variables",
+            "phenotypes",
         )
 
 
@@ -320,96 +387,53 @@ class ProjectSerializer(serializers.HyperlinkedModelSerializer):
 
     def create(self, validated_data, **kwargs):
         current_user = self.context["request"].user
-        project_name = validated_data["project_name"]
-        project = super().create(validated_data, **kwargs)
-
-        project_roles = ProjectRole.objects.all()
-        project_groups_and_permissions = []
-        # create a group foreach roles
-        for project_role in project_roles:
-            try:
-                with transaction.atomic():
-
-                    # Create a group project role entry
-                    project_group = ProjectGroup(
-                        project=project,
-                        project_role=project_role,
-                        name=project_name + "_" + str(project_role),
-                    )
-                    project_group.save()
-                    # add the user to a this group
-                    if str(project_role) == "manager":
-                        project_group.user_set.add(current_user)
-
-                    # assign group permissions to this instance
-                    # Get the permissions for a role
-                    permissions = project_role.permissions.filter(
-                        content_type__model="project"
-                    )
-
-                    for project_perm in permissions:
-                        assign_perm(project_perm, project_group, project)
-                        assign_perm(project_perm, project_group)
-
-                    # assign experiement permissions
-                    experiment_permissions = project_role.permissions.filter(
-                        content_type__model="experiment"
-                    )
-                    for exp_perm in experiment_permissions:
-                        assign_perm(exp_perm, project_group)
-
-                    # assign analysis permissions
-                    analysis_permissions = project_role.permissions.filter(
-                        content_type__model="analysis"
-                    )
-                    for perm in analysis_permissions:
-                        assign_perm(perm, project_group)
-
-                    # assign peak permissions
-                    peak_permissions = project_role.permissions.filter(
-                        content_type__model="peak"
-                    )
-                    for perm in peak_permissions:
-                        assign_perm(perm, project_group)
-
-                    # assign project group permissions
-                    projectgroup_permissions = project_role.permissions.filter(
-                        content_type__model="projectgroup"
-                    )
-
-                    project_groups_and_permissions.append(
-                        {
-                            "projectgroup": project_group,
-                            "permissions": projectgroup_permissions,
-                        }
-                    )
-                    # print(f"projectgroup perm assign : {perm} - {project_group}")
-                    # assign_perm(perm, project_group, project_group)
-                    # assign_perm(perm, project_group)
-
-            except IntegrityError:
-                raise RessourceAlreadyExists()
-                # Add reader role to the team the current user belongs
-
-        # add group permissions on projectgroup
-        for pgp in project_groups_and_permissions:
-            permissions = pgp["permissions"]
-            for perm in permissions:
-                assign_perm(perm, pgp["projectgroup"])
-                for pg in project_groups_and_permissions:
-                    assign_perm(perm, pgp["projectgroup"], pg["projectgroup"])
-
-        # Add team permissions
-        teams = Team.objects.filter(user__id=current_user.id)
-        for team in teams:
-            permissions = team.project_role.permissions.filter(
-                content_type__model="project"
-            )
-            team.projects.add(project)
-            for project_perm in permissions:
-                assign_perm(project_perm, team, project)
-
-        return project
+        try:
+            project = Project.objects.create(**validated_data, creator=current_user)
+        except IntegrityError as e:
+            msg = e.args[0]
+            if "" in msg:
+                raise serializers.ValidationError(
+                    f"The project name \"{validated_data['project_name']}\" already exists. "
+                    + "Please choose another one."
+                )
+            else:
+                raise serializers.ValidationError(e)
+        else:  # Add team permissions
+            teams = Team.objects.filter(user__id=current_user.id)
+            for team in teams:
+                permissions = team.project_role.permissions.filter(
+                    content_type__model="project"
+                )
+                team.projects.add(project)
+                for project_perm in permissions:
+                    assign_perm(project_perm, team, project)
+
+            return project
+
+    def update(self, instance, validated_data):
+        instance.project_name = validated_data.get(
+            "project_name", instance.project_name
+        )
+        instance.description = validated_data.get("description", instance.description)
+        try:
+            instance.save()
+            # Update project groups name
+            project_groups = ProjectGroup.objects.filter(project=instance)
+            for project_group in project_groups:
+                project_group.name = (
+                    instance.project_name + "_" + str(project_group.project_role)
+                )
+                project_group.save()
+            return instance
+        except IntegrityError as e:
+            msg = e.args[0]
+            if "" in msg:
+                raise serializers.ValidationError(
+                    f"The project name \"{validated_data['project_name']}\" already exists. "
+                    + "Please choose another one."
+                )
+            else:
+                raise serializers.ValidationError(e)
 
     @classmethod
     def assign_user_role_permissions(cls, user, role, project):
@@ -434,7 +458,32 @@ class ProjectSerializer(serializers.HyperlinkedModelSerializer):
         )
 
 
-class VariableSerializer(NestedHyperlinkedModelSerializer):
+class ProjectGroupRoleSerializer(serializers.ModelSerializer):
+    project = serializers.StringRelatedField(read_only=True)
+    project_role = serializers.StringRelatedField(read_only=True)
+
+    class Meta:
+        model = ProjectGroup
+        fields = ("id", "project", "project_role")
+
+
+class ExperimentLightSerializer(NestedHyperlinkedModelSerializer):
+
+    parent_lookup_kwargs = {"project_pk": "project__pk"}
+    project = ProjectSerializer(read_only=True)
+
+    class Meta:
+        model = Experiment
+        fields = (
+            "id",
+            "name",
+            "description",
+            "creation_date",
+            "project",
+        )
+
+
+class PhenotypeSerializer(NestedHyperlinkedModelSerializer):
     parent_lookup_kwargs = {
         "project_pk": "experiment_cc_line__experiment__project__pk",
         # "experiment_pk": "experiment_cc_line__experiment__pk",
@@ -442,7 +491,7 @@ class VariableSerializer(NestedHyperlinkedModelSerializer):
     }
 
     class Meta:
-        model = Variable
+        model = Phenotype
         fields = ("id", "value", "category")
 
 
@@ -455,7 +504,7 @@ class DepartmentSerializer(serializers.HyperlinkedModelSerializer):
 class RoleSerializer(serializers.HyperlinkedModelSerializer):
     class Meta:
         model = Role
-        fields = ("name", "priority")
+        fields = ("id", "name", "priority")
 
     @staticmethod
     def getPermissionsCodename(role_name, content_type):
@@ -466,6 +515,15 @@ class RoleSerializer(serializers.HyperlinkedModelSerializer):
         )
 
 
+class RoleGroupSerializer(serializers.ModelSerializer):
+    group_ptr = GroupSerializer(read_only=True)
+    role = RoleSerializer(read_only=True)
+
+    class Meta:
+        model = RoleGroup
+        fields = ("id", "role", "group_ptr")
+
+
 class AnalysisPeakSerializer(NestedHyperlinkedModelSerializer):
     parent_lookup_kwargs = {
         "project_pk": "analysis__project__pk",
@@ -474,23 +532,15 @@ class AnalysisPeakSerializer(NestedHyperlinkedModelSerializer):
 
     class Meta:
         model = Peak
-        fields = (
-            "url",
-            "id",
-            "variable_name",
-            "chromosome",
-            "position",
-        )
+        fields = ("url", "id", "variable_name", "chromosome", "position", "p_value")
 
 
 class AnalysisSerializer(NestedHyperlinkedModelSerializer):
-
     parent_lookup_kwargs = {"project_pk": "project__pk"}
     peaks = AnalysisPeakSerializer(many=True, read_only=True,)
-    experiments = serializers.PrimaryKeyRelatedField(
-        many=True, queryset=Experiment.objects.all()
-    )
+    experiments = ExperimentLightSerializer(many=True, read_only=True)
     project = ProjectSerializer(read_only=True)
+    phenotype_categories = PhenotypeCategorySerializer(many=True, read_only=True)
 
     class Meta:
         model = Analysis
@@ -498,6 +548,7 @@ class AnalysisSerializer(NestedHyperlinkedModelSerializer):
             "url",
             "id",
             "name",
+            "description",
             "galaxy_history_id",
             "galaxy_workflow_id",
             "galaxy_workflow_invocation_id",
@@ -505,29 +556,63 @@ class AnalysisSerializer(NestedHyperlinkedModelSerializer):
             "peaks",
             "experiments",
             "project",
+            "history_status",
+            "workflow_invocation_status",
+            "phenotype_categories",
         )
 
     def create(self, validated_data):
         project = Project.objects.get(pk=self.context["view"].kwargs["project_pk"])
         validated_data["project"] = project
-        experiments = validated_data.pop("experiments")
+        experiments = self.initial_data.pop("experiments")
         tools_params = self.initial_data["toolsParams"]
-        exp_file_path = experiments[0].generate_experiment_file(validated_data["name"])
-        workflow_invocation = run_analyis(
-            project.project_name, validated_data["name"], exp_file_path, tools_params,
+        phenotype_type_name = tools_params["1"]["column_pheno"]
+        experiment_db = Experiment.objects.get(pk=experiments[0])
+        exp_file_path = experiment_db.generate_experiment_file(
+            validated_data["name"],
+            phenotype_type_name,
+            validated_data["galaxy_workflow_id"],
         )
-
-        shutil.rmtree(Path(exp_file_path).parent)
-        load_results(workflow_invocation["history_id"], validated_data["name"])
-        validated_data["galaxy_history_id"] = workflow_invocation["history_id"]
-        validated_data["galaxy_workflow_id"] = workflow_invocation["workflow_id"]
-        validated_data["galaxy_workflow_invocation_id"] = workflow_invocation["id"]
-
+        phenotype_categories = PhenotypeCategory.objects.filter(
+            name=phenotype_type_name
+        )
+        tools_params["1"]["column_pheno"] = "5"
         analysis = Analysis.objects.create(**validated_data)
         analysis.experiments.set(experiments)
+        analysis.phenotype_categories.set(phenotype_categories)
+        run_analyis(
+            project.project_name,
+            validated_data["name"],
+            exp_file_path,
+            tools_params,
+            validated_data["galaxy_workflow_id"],
+            analysis.id,
+        )
         return analysis
 
 
+class ExperimentSerializer(NestedHyperlinkedModelSerializer):
+
+    parent_lookup_kwargs = {"project_pk": "project__pk"}
+    cclines = ExperimentExperimentCclineSerializer(many=True, read_only=True,)
+    analysis_set = AnalysisSerializer(many=True, read_only=True)
+    phenotype_categories = PhenotypeCategorySerializer(many=True, read_only=True)
+
+    class Meta:
+        model = Experiment
+        fields = (
+            "url",
+            "id",
+            "name",
+            "project",
+            "description",
+            "creation_date",
+            "cclines",
+            "analysis_set",
+            "phenotype_categories",
+        )
+
+
 class LodScoreSerializer(NestedHyperlinkedModelSerializer):
     parent_lookup_kwargs = {
         "project_pk": "analysis__project__pk",
@@ -536,13 +621,7 @@ class LodScoreSerializer(NestedHyperlinkedModelSerializer):
 
     class Meta:
         model = LodScore
-        fields = ("id", "lod_scores")
-
-
-class LodScoreSignificanceThresholdSerializer(serializers.ModelSerializer):
-    class Meta:
-        model = LodScoreSignificanceThreshold
-        fields = ("id", "significance", "threshold")
+        fields = ("id", "lod_scores", "significance_thresholds")
 
 
 class CoefficientSerializer(serializers.ModelSerializer):
@@ -569,6 +648,12 @@ class TopSnpsSerializer(serializers.ModelSerializer):
         fields = ("id", "top_snps")
 
 
+class PeakGenesSerializer(serializers.ModelSerializer):
+    class Meta:
+        model = PeakGenes
+        fields = ("id", "genes")
+
+
 class PeakSerializer(NestedHyperlinkedModelSerializer):
 
     parent_lookup_kwargs = {
@@ -587,5 +672,6 @@ class PeakSerializer(NestedHyperlinkedModelSerializer):
             "lod",
             "ci_lo",
             "ci_hi",
+            "p_value",
         )
 
diff --git a/server/api/tasks.py b/server/api/tasks.py
index c0892babb1c499073a8f0d283ad9a66c03720b2b..fc25311c0ad7b1f9db5b459ceb398d00fe470de4 100644
--- a/server/api/tasks.py
+++ b/server/api/tasks.py
@@ -1,19 +1,19 @@
+import csv
 import time
 from tempfile import mkdtemp
 from pathlib import Path
 import shutil
-from celery import chain
+from celery import chain, shared_task
 from requests.exceptions import HTTPError
-
-from server import celery_app
+from django.conf import settings
 
 from .models import (
     Analysis,
     Coefficient,
     Haplotypes,
     LodScore,
-    LodScoreSignificanceThreshold,
     Peak,
+    PeakGenes,
     SnpsAssociation,
     TopSnps,
 )
@@ -26,43 +26,68 @@ runner = GalaxyRunner()
 gi = runner.galaxy_instance
 
 
-def run_analyis(project_name, analysis_name, experiment_file_path, tools_params):
-    current_history = gi.histories.create_history(f"{project_name} - {analysis_name}")
-    history_id = current_history["id"]
+def run_analyis(
+    project_name, analysis_name, experiment_file_path, tools_params, wf_id, analysis_id
+):
+
+    galaxy_workflow_excel = {"657f009ad32a3f27", "bd6cadfea4e7afba"}
+    if wf_id in galaxy_workflow_excel:
+        input_format = "excel.xls"
+    else:
+        input_format = "csv"
     chained_tasks = chain(
-        upload_file_to_galaxy.si(experiment_file_path, history_id, "excel.xls",),
-        genome_scan_wf.s(history_id, tools_params),
+        create_history.si(
+            f"{settings.HOSTLABEL} - {project_name} - {analysis_name}", analysis_id
+        ),
+        upload_file_to_galaxy.s(experiment_file_path, input_format),
+        genome_scan_wf.s(tools_params, wf_id),
+        load_lodscores_results.s(),
+        load_refine_peaks.s(),
+        load_coefficient.s(),
+        load_snps_association.s(),
+        load_top_snps.s(),
+        load_haplotypes.s(),
+        load_peak_genes.s(),
     )
-    res = chained_tasks.delay()
-    return res.get()
+    return chained_tasks.delay()
 
 
 def load_results(history_id, analysis_name):
     chained_tasks = chain(
-        load_lod_score.si(analysis_name, history_id),
-        load_significance_threshold.si(analysis_name, history_id),
+        load_lodscores_results.si(analysis_name, history_id),
         load_refine_peaks.si(analysis_name, history_id),
         load_coefficient.si(analysis_name, history_id),
         load_snps_association.si(analysis_name, history_id),
         load_top_snps.si(analysis_name, history_id),
         load_haplotypes.si(analysis_name, history_id),
+        load_peak_genes.si(analysis_name, history_id),
     )
     return chained_tasks.delay()
 
 
-def load_lodscores_results(analysis_name, history_id):
-    chained_tasks = chain(
-        load_lod_score.si(analysis_name, history_id),
-        load_significance_threshold.si(analysis_name, history_id),
-    )
-    return chained_tasks.delay().get()
+@shared_task
+def load_lodscores_results(ids):
+    chained_tasks = chain(load_lod_score.s(ids), load_significance_threshold.s())
+    return chained_tasks
+    # return chained_tasks.delay().get()
+
 
+# @celery_app.task()
+@shared_task
+def create_history(name, analysis_id):
+    current_history = gi.histories.create_history(name)
+    analysis = Analysis.objects.get(pk=analysis_id)
+    analysis.galaxy_history_id = current_history["id"]
+    analysis.save()
+    return analysis_id, current_history["id"]
 
-@celery_app.task()
-def upload_file_to_galaxy(file_path, history_id, file_type):
+
+# @celery_app.task()
+@shared_task
+def upload_file_to_galaxy(ids, file_path, file_type):
+    analysis_id, history_id = ids
     # gi = GalaxyInstance(url=url, key=key, verify=False)
     upload_response = gi.tools.upload_file(file_path, history_id, file_type=file_type)
-
     upload_data_id = upload_response["outputs"][0]["id"]
     upload_job = upload_response["jobs"][0]
     upload_job_id = upload_job["id"]
@@ -84,41 +109,45 @@ def upload_file_to_galaxy(file_path, history_id, file_type):
             f"{data['name']}, id : {upload_data_id}, "
             f"error : {data['misc_info']}"
         )
-    return upload_data_id
+    shutil.rmtree(Path(file_path).parent)
+    return analysis_id, history_id, upload_data_id
 
 
-@celery_app.task()
-def genome_scan_wf(upload_data_id, history_id, tools_params):
-    # gi = GalaxyInstance(url=url, key=key, verify=False)
-    workflows = gi.workflows.get_workflows()
-    wf_name = "cc-qtl-wf"
+# @celery_app.task()
+@shared_task
+def genome_scan_wf(ids, tools_params, wf_id):
+    analysis_id, history_id, upload_data_id = ids
     try:
-        genome_scan_wf_metadata = next(wf for wf in workflows if wf["name"] == wf_name)
+        genome_scan_wf_metadata = gi.workflows.show_workflow(wf_id)
         datamap = dict()
         datamap["0"] = {"src": "hda", "id": upload_data_id}
         workflow_invocation = gi.workflows.invoke_workflow(
-            genome_scan_wf_metadata["id"],
-            inputs=datamap,
-            params=tools_params,
-            history_id=history_id,
+            wf_id, inputs=datamap, params=tools_params, history_id=history_id,
         )
-        workflow_job_id = workflow_invocation["id"]
-        while workflow_invocation["state"] not in ["ok", "scheduled"]:
-            time.sleep(10)
-            workflow_invocation = gi.workflows.show_invocation(
-                genome_scan_wf_metadata["id"], workflow_job_id
-            )
-            if workflow_invocation["state"] in ["error", "deleted", "discarded"]:
-                raise Exception(
-                    f"Error during Galaxy workflow job - name : "
-                    f"id : {workflow_job_id}, "
-                )
-        return workflow_invocation
+        workflow_invocation_id = workflow_invocation["id"]
+        analysis = Analysis.objects.get(pk=analysis_id)
+        analysis.galaxy_workflow_invocation_id = workflow_invocation_id
+        analysis.save()
+        runner.wait_for_invocation(wf_id, workflow_invocation_id)
+        # gi.invocations.wait_for_invocation(workflow_job_id)
+        # wait for invocation
+        # while workflow_invocation["state"] not in ["ok", "scheduled"]:
+        #     time.sleep(10)
+        #     workflow_invocation = gi.workflows.show_invocation(
+        #         wf_id, workflow_invocation_id
+        #     )
+        #     if workflow_invocation["state"] in ["error", "deleted", "discarded"]:
+        #         raise Exception(
+        #             f"Error during Galaxy workflow job - name : "
+        #             f"id : {workflow_invocation_id}, "
+        #         )
+        return analysis_id, history_id, workflow_invocation_id
     except StopIteration:
-        raise Exception(f"Do not find the workflow : {wf_name}")
+        raise Exception(f"Do not find the workflow : {genome_scan_wf_metadata['name']}")
 
 
-@celery_app.task()
+# @celery_app.task()
+@shared_task
 def download_formatted_qtl2_data(history_id):
     dataset_pattern = "cc-qtl Format Data"
     try:
@@ -153,317 +182,285 @@ def download_formatted_qtl2_data(history_id):
     return Path(tmpdirpath).name + ".zip"
 
 
-@celery_app.task()
-def load_lod_score(analysis_name, history_id):
+# @celery_app.task()
+@shared_task
+def load_lod_score(ids):
+    analysis_id, history_id, _ = ids
+    lod_entry_id = None
     dataset_pattern = "lod.csv"
-    try:
-        datasets = gi.histories.show_history(history_id, contents=True)
-    except HTTPError:
-        raise Exception(f"Do not find history : {history_id}")
-    try:
-        filtered_datasets = (
-            ds for ds in datasets if ds["name"].endswith(dataset_pattern)
-        )
-    except StopIteration:
-        raise Exception(f"Do not find the dataset : {dataset_pattern}")
-
-    for dataset in filtered_datasets:
-        try:
-            downloaded_ds = gi.datasets.download_dataset(dataset["id"])
-        except HTTPError:
-            raise Exception(f"Could not get the dataset : {dataset['name']}")
-        else:
-            file_list = downloaded_ds.decode("utf-8").split("\n")
-            lod_scores = list(lod_score_gen(file_list[1:], analysis_name, history_id))
-            analysis = Analysis.objects.get(
-                name=analysis_name, galaxy_history_id=history_id
-            )
-            lod_entry = LodScore(analysis=analysis, lod_scores=lod_scores)
-            lod_entry.save()
-            # LodScore.objects.bulk_create([lod_scores])
-    return {"status": "ok", "lodscores_id": lod_entry.id}
-
-
-@celery_app.task()
-def load_refine_peaks(analysis_name, history_id):
+    filtered_datasets = list(runner.get_datasets_endswith(history_id, dataset_pattern))
+    if len(filtered_datasets) == 1:
+        for dataset in filtered_datasets:
+            if dataset["state"] not in TERMINAL_STATES:
+                continue
+            else:
+                file_path = runner.download_dataset_in_tmp(dataset, history_id)
+                with open(file_path, newline="") as csvfile:
+                    lodscore_fh = csv.reader(csvfile)
+                    # skip header with next
+                    next(lodscore_fh, None)
+                    analysis = Analysis.objects.get(pk=analysis_id)
+                    lod_scores = list(lod_score_gen(lodscore_fh))
+                    lod_entry = LodScore(
+                        analysis=analysis,
+                        lod_scores=lod_scores,
+                        significance_thresholds=[],
+                    )
+                    lod_entry.save()
+                    lod_entry_id = lod_entry.id
+
+        return analysis_id, history_id, lod_entry_id
+    else:
+        raise Exception("Multiple lod score files")
+
+
+# @celery_app.task()
+@shared_task
+def load_refine_peaks(ids):
+    analysis_id, history_id, _ = ids
     dataset_pattern = "refine-peaks.csv"
-    try:
-        # TODO: test to put a fake history in order to catch exception and
-        # do whatever needed
-        datasets = gi.histories.show_history(history_id, contents=True)
-        # for d in datasets:
-        # Get the lod score dataset
-    except HTTPError:
-        raise Exception(f"Do not find history : {history_id}")
-    try:
-        filtered_datasets = (
-            ds for ds in datasets if ds["name"].endswith(dataset_pattern)
-        )
-    except StopIteration:
-        raise Exception(f"Do not find the dataset : {dataset_pattern}")
+    filtered_datasets = runner.get_datasets_endswith(history_id, dataset_pattern)
 
     peak_ids = []
     for dataset in filtered_datasets:
-        try:
-            downloaded_ds = gi.datasets.download_dataset(dataset["id"])
-        except HTTPError:
-            raise Exception(f"Could not get the dataset : {dataset['name']}")
+        if dataset["state"] not in TERMINAL_STATES:
+            continue
         else:
-            file_list = downloaded_ds.decode("utf-8").split("\n")
-            bulk = peaks_gen(file_list[1:], analysis_name, history_id)
-            for peak in bulk:
-                peak.save()
-                peak_ids.append(peak.id)
+            file_path = runner.download_dataset_in_tmp(dataset, history_id)
+            with open(file_path, newline="") as csvfile:
+                refine_peaks_fh = csv.reader(csvfile)
+                # skip header with next
+                next(refine_peaks_fh, None)
+                # analysis = Analysis.objects.get(pk=analysis_id)
+                # file_list = downloaded_ds.decode("utf-8").split("\n")
+                bulk = peaks_gen(refine_peaks_fh, analysis_id)
+                for peak in bulk:
+                    peak.save()
+                    peak_ids.append(peak.id)
+    return analysis_id, history_id, peak_ids
+
+
+# @celery_app.task()
+@shared_task
+def load_significance_threshold(ids):
+    analysis_id, history_id, lod_entry_id = ids
 
-    return {"status": "ok", "peak_ids": peak_ids}
-
-
-@celery_app.task()
-def load_significance_threshold(analysis_name, history_id):
     # gi = GalaxyInstance(url=url, key=key, verify=False)
     dataset_pattern = "significance-threshold.csv"
-    ids = []
+    # significance_threshold_ids = []
+    filtered_datasets = runner.get_datasets_endswith(history_id, dataset_pattern)
+
     try:
-        # TODO: test to put a fake history in order to catch exception and
-        # do whatever needed
-        datasets = gi.histories.show_history(history_id, contents=True)
+        history = gi.histories.show_history(history_id, contents=False)
     except HTTPError:
         raise Exception(f"Do not find history : {history_id}")
-    try:
-        filtered_datasets = (
-            ds for ds in datasets if ds["name"].endswith(dataset_pattern)
-        )
-    except StopIteration:
-        raise Exception(f"Do not find the dataset : {dataset_pattern}")
+    except Exception:
+        raise
+
     for dataset in filtered_datasets:
-        print(dataset["name"])
-        try:
-            downloaded_ds = gi.datasets.download_dataset(dataset["id"])
-        except HTTPError:
-            print("error dans download dataset")
-            raise Exception(f"Could not get the dataset : {dataset['name']}")
+        if dataset["state"] not in TERMINAL_STATES and history["state"] == "error":
+            pass
         else:
-            file_list = downloaded_ds.decode("utf-8").split("\n")
-            signi_thres = zip(
-                ["80%", "90%", "95%", "99%", "99.5%", "99.9%"], file_list[1:]
-            )
-            bulk = threshold_gen(signi_thres, analysis_name, history_id)
-            for threshold_db in bulk:
-                threshold_db.save()
-                ids.append(threshold_db.id)
-            # LodScoreSignificanceThreshold.objects.bulk_create(bulk, batch_size=10000)
-    return {"status": "ok", "ids": ids}
-
-
-@celery_app.task()
-def load_coefficient(analysis_name, history_id):
+            file_path = runner.download_dataset_in_tmp(dataset, history_id)
+            with open(file_path, newline="") as csvfile:
+                significance_threshold_fh = csv.reader(csvfile)
+                # skip header with next
+                next(significance_threshold_fh, None)
+
+                analysis = Analysis.objects.get(pk=analysis_id)
+                signi_thres = zip(
+                    ["80%", "90%", "95%", "99%", "99.5%", "99.9%"],
+                    (st[0] for st in significance_threshold_fh),
+                )
+                bulk = list(threshold_gen(signi_thres, analysis))
+                lod_entry = LodScore.objects.get(id=lod_entry_id)
+                lod_entry.significance_thresholds = bulk
+                lod_entry.save(update_fields=["significance_thresholds"])
+                # for threshold_db in bulk:
+                #     threshold_db.save()
+                #     significance_threshold_ids.append(threshold_db.id)
+    return analysis_id, history_id
+
+
+# @celery_app.task()
+@shared_task
+def load_coefficient(ids):
+    analysis_id, history_id, _ = ids
     dataset_pattern = "coef.csv"
-    try:
-        # TODO: test to put a fake history in order to catch exception and
-        # do whatever needed
-        datasets = gi.histories.show_history(history_id, contents=True)
-    except HTTPError:
-        raise Exception(f"Do not find history : {history_id}")
-    try:
-        filtered_datasets = (
-            ds for ds in datasets if ds["name"].endswith(dataset_pattern)
-        )
-    except StopIteration:
-        raise Exception(f"Do not find the dataset : {dataset_pattern}")
+    filtered_datasets = runner.get_datasets_endswith(history_id, dataset_pattern)
+    coefficient_ids = []
     for dataset in filtered_datasets:
-        try:
-            downloaded_ds = gi.datasets.download_dataset(dataset["id"])
-        except HTTPError:
-            raise Exception(f"Could not get the dataset : {dataset['name']}")
+        if dataset["state"] not in TERMINAL_STATES:
+            continue
         else:
-            peak_info_it = iter(dataset["name"].split("--"))
-            peak_info = dict(zip(peak_info_it, peak_info_it))
-            analysis = Analysis.objects.get(
-                name=analysis_name, galaxy_history_id=history_id
-            )
-            peak = Peak.objects.get(
-                analysis=analysis,
-                variable_name=peak_info["var"],
-                chromosome=peak_info["chr"],
-                position=peak_info["pos"],
-            )
-
-            file_list = downloaded_ds.decode("utf-8").split("\n")
-            coef_gen = coefficient_gen(file_list[1:])
-            coef_db = Coefficient(peak=peak, coefficients=list(coef_gen))
-            coef_db.save()
-    return {"status": "ok", "coefficient_id": coef_db.id}
-
-
-@celery_app.task()
-def load_haplotypes(analysis_name, history_id):
+            file_path = runner.download_dataset_in_tmp(dataset, history_id)
+            peak = Peak.objects.peak_from_dataset_name(dataset["name"], analysis_id)
+            with open(file_path, newline="") as csvfile:
+                coef_fh = csv.reader(csvfile)
+                # skip header with next
+                next(coef_fh, None)
+                coef_gen = list(coefficient_gen(coef_fh))
+                coef_db = Coefficient(peak=peak, coefficients=coef_gen)
+                coef_db.save()
+                coefficient_ids.append(coef_db.id)
+    return analysis_id, history_id, coefficient_ids
+
+
+# @celery_app.task()
+@shared_task
+def load_haplotypes(ids):
+    analysis_id, history_id, _ = ids
     dataset_pattern = "haplo.csv"
-    try:
-        datasets = gi.histories.show_history(history_id, contents=True)
-    except HTTPError:
-        raise Exception(f"Do not find history : {history_id}")
-    try:
-        filtered_datasets = (
-            ds for ds in datasets if ds["name"].endswith(dataset_pattern)
-        )
-    except StopIteration:
-        raise Exception(f"Do not find the dataset : {dataset_pattern}")
+    filtered_datasets = runner.get_datasets_endswith(history_id, dataset_pattern)
+    haplo_ids = []
 
     for dataset in filtered_datasets:
-
-        try:
-            downloaded_ds = gi.datasets.download_dataset(dataset["id"])
-        except HTTPError:
-            raise Exception(f"Could not get the dataset : {dataset['name']}")
+        if dataset["state"] not in TERMINAL_STATES:
+            continue
         else:
-            file_list = downloaded_ds.decode("utf-8").split("\n")
-            peak_info_it = iter(dataset["name"].split("--"))
-            peak_info = dict(zip(peak_info_it, peak_info_it))
-            analysis = Analysis.objects.get(
-                name=analysis_name, galaxy_history_id=history_id
-            )
-            peak = Peak.objects.get(
-                analysis=analysis,
-                variable_name=peak_info["var"],
-                chromosome=peak_info["chr"],
-                position=peak_info["pos"],
-            )
-            haplo_gen = haplotype_gen(file_list[1:])
-            haplotype_db = Haplotypes(peak=peak, haplotypes=list(haplo_gen))
-            haplotype_db.save()
-    return {"status": "ok", "id": haplotype_db.id}
-
-
-@celery_app.task()
-def load_top_snps(analysis_name, history_id):
+            file_path = runner.download_dataset_in_tmp(dataset, history_id)
+            peak = Peak.objects.peak_from_dataset_name(dataset["name"], analysis_id)
+            with open(file_path, newline="") as csvfile:
+                haplotype_fh = csv.reader(csvfile)
+                # skip header with next
+                next(haplotype_fh, None)
+                haplo_gen = haplotype_gen(haplotype_fh)
+                haplotype_db = Haplotypes(peak=peak, haplotypes=list(haplo_gen))
+                haplotype_db.save()
+                haplo_ids.append(haplotype_db.id)
+
+    return analysis_id, history_id, haplo_ids
+
+
+# @celery_app.task()
+@shared_task
+def load_top_snps(ids):
+    analysis_id, history_id, _ = ids
     dataset_pattern = "top_snps.csv"
-    try:
-        datasets = gi.histories.show_history(history_id, contents=True)
-    except HTTPError:
-        raise Exception(f"Do not find history : {history_id}")
-    try:
-        filtered_datasets = (
-            ds for ds in datasets if ds["name"].endswith(dataset_pattern)
-        )
-    except StopIteration:
-        raise Exception(f"Do not find the dataset : {dataset_pattern}")
+    top_snps_ids = []
+    filtered_datasets = runner.get_datasets_endswith(history_id, dataset_pattern)
 
     for dataset in filtered_datasets:
-        try:
-            downloaded_ds = gi.datasets.download_dataset(dataset["id"])
-        except HTTPError:
-            raise Exception(f"Could not get the dataset : {dataset['name']}")
+        if dataset["state"] not in TERMINAL_STATES:
+            continue
         else:
-            analysis = Analysis.objects.get(
-                name=analysis_name, galaxy_history_id=history_id
-            )
-            peak_info_it = iter(dataset["name"].split("--"))
-            peak_info = dict(zip(peak_info_it, peak_info_it))
-            peak = Peak.objects.get(
-                analysis=analysis,
-                variable_name=peak_info["var"],
-                chromosome=peak_info["chr"],
-                position=peak_info["pos"],
-            )
-            file_list = downloaded_ds.decode("utf-8").split("\n")
-            top_snps = list(top_snps_gen(file_list[1:]))
-            top_snps_db = TopSnps(peak=peak, top_snps=top_snps)
-            top_snps_db.save()
-    return {"status": "ok", "id": top_snps_db.id}
-
-
-@celery_app.task()
-def load_snps_association(analysis_name, history_id):
+            file_path = runner.download_dataset_in_tmp(dataset, history_id)
+            peak = Peak.objects.peak_from_dataset_name(dataset["name"], analysis_id)
+            with open(file_path, newline="") as csvfile:
+                top_snps_fh = csv.reader(csvfile)
+                # skip header with next
+                next(top_snps_fh, None)
+                top_snps = list(top_snps_gen(top_snps_fh))
+                top_snps_db = TopSnps(peak=peak, top_snps=top_snps)
+                top_snps_db.save()
+                top_snps_ids.append(top_snps_db.id)
+    return analysis_id, history_id, top_snps_ids
+
+
+@shared_task
+def load_peak_genes(ids):
+    analysis_id, history_id, _ = ids
+    dataset_pattern = "genes.csv"
+    filtered_datasets = runner.get_datasets_endswith(history_id, dataset_pattern)
+    peak_genes_ids = []
+    for dataset in filtered_datasets:
+        if dataset["state"] not in TERMINAL_STATES:
+            continue
+        else:
+            file_path = runner.download_dataset_in_tmp(dataset, history_id)
+            peak = Peak.objects.peak_from_dataset_name(dataset["name"], analysis_id)
+            with open(file_path, newline="") as csvfile:
+                peak_genes_fh = csv.reader(csvfile)
+                # skip header with next
+                next(peak_genes_fh, None)
+                peak_genes = list(peak_genes_gen(peak_genes_fh))
+                peak_genes_db = PeakGenes(peak=peak, genes=peak_genes)
+                peak_genes_db.save()
+                peak_genes_ids.append(peak_genes_db.id)
+    return analysis_id, history_id, peak_genes_ids
+
+
+# @celery_app.task()
+@shared_task
+def load_snps_association(ids):
+    analysis_id, history_id, _ = ids
     dataset_pattern = "snps_assoc.csv"
-    try:
-        datasets = gi.histories.show_history(history_id, contents=True)
-    except HTTPError:
-        raise Exception(f"Do not find history : {history_id}")
-    try:
-        filtered_datasets = (
-            ds for ds in datasets if ds["name"].endswith(dataset_pattern)
-        )
-    except StopIteration:
-        raise Exception(f"Do not find the dataset : {dataset_pattern}")
-
+    filtered_datasets = runner.get_datasets_endswith(history_id, dataset_pattern)
+    snps_associations_ids = []
     for dataset in filtered_datasets:
-
-        try:
-            downloaded_ds = gi.datasets.download_dataset(dataset["id"])
-        except HTTPError:
-            raise Exception(f"Could not get the dataset : {dataset['name']}")
+        if dataset["state"] not in TERMINAL_STATES:
+            continue
         else:
-            analysis = Analysis.objects.get(
-                name=analysis_name, galaxy_history_id=history_id
-            )
-            peak_info_it = iter(dataset["name"].split("--"))
-            peak_info = dict(zip(peak_info_it, peak_info_it))
-            peak = Peak.objects.get(
-                analysis=analysis,
-                variable_name=peak_info["var"],
-                chromosome=peak_info["chr"],
-                position=peak_info["pos"],
-            )
-            file_list = downloaded_ds.decode("utf-8").split("\n")
-
-            snps_assoc = list(snps_association_gen(file_list[1:]))
-            snps_assoc_db = SnpsAssociation(peak=peak, snps_association=snps_assoc)
-            snps_assoc_db.save()
-    return {"status": "ok", "id": snps_assoc_db.id}
-
-
-def threshold_gen(thresholds, analysis_name, history_id):
+            file_path = runner.download_dataset_in_tmp(dataset, history_id)
+            peak = Peak.objects.peak_from_dataset_name(dataset["name"], analysis_id)
+            with open(file_path, newline="") as csvfile:
+                snps_asso_fh = csv.reader(csvfile)
+                # skip header with next
+                next(snps_asso_fh, None)
+                snps_assoc = list(snps_association_gen(snps_asso_fh))
+                snps_assoc_db = SnpsAssociation(peak=peak, snps_association=snps_assoc)
+                snps_assoc_db.save()
+                snps_associations_ids.append(snps_assoc_db.id)
+    return analysis_id, history_id, snps_associations_ids
+
+
+def threshold_gen(thresholds, analysis):
     for threshold in thresholds:
         if len(threshold) == 2:
             raw_significance, threshold = threshold
             significance = float(raw_significance.strip('"%'))
-            yield LodScoreSignificanceThreshold(
-                analysis=Analysis.objects.get(
-                    name=analysis_name, galaxy_history_id=history_id
-                ),
-                significance=significance,
-                threshold=float(threshold),
-            )
+            yield ({"significance": significance, "threshold": float(threshold)})
         else:
             continue
 
 
-def peaks_gen(peaks, analysis_name, history_id):
-    for peak in peaks:
-        peak_tuple = peak.split(",")
+def peaks_gen(peaks, analysis_id):
+    coef = 1e6
+    for peak_tuple in peaks:
+        # peak_tuple = peak.split(",")
         if len(peak_tuple) == 12:
             (_, lodcolumn, chr, pos, lod, ci_lo, ci_hi, *_) = peak_tuple
-            analysis = Analysis.objects.get(
-                name=analysis_name, galaxy_history_id=history_id
+            analysis = Analysis.objects.get(pk=analysis_id)
+            peak_obj = Peak(
+                analysis=analysis,
+                variable_name=lodcolumn,
+                chromosome=chr,
+                position=float(pos) * coef,
+                lod=float(lod),
+                ci_lo=float(ci_lo) * coef,
+                ci_hi=float(ci_hi) * coef,
             )
+            yield peak_obj
+        elif len(peak_tuple) == 13:
+            (_, lodcolumn, chr, pos, lod, ci_lo, ci_hi, p_value, *_) = peak_tuple
+            analysis = Analysis.objects.get(pk=analysis_id)
             peak_obj = Peak(
                 analysis=analysis,
-                variable_name=lodcolumn.strip('"'),
-                chromosome=chr.strip('"'),
-                position=float(pos) * 1000000,
+                variable_name=lodcolumn,
+                chromosome=chr,
+                position=float(pos) * coef,
                 lod=float(lod),
-                ci_lo=float(ci_lo) * 1000000,
-                ci_hi=float(ci_hi) * 1000000,
+                ci_lo=float(ci_lo) * coef,
+                ci_hi=float(ci_hi) * coef,
+                p_value=float(p_value)
             )
             yield peak_obj
         else:
             continue
 
 
-def lod_score_gen(lods, analysis_name, history_id):
-    column_names = ["marker", "position", "chromosome", "lod"]
-    for lod_entry in lods:
-        lod_tuple = lod_entry.split(",")
+def lod_score_gen(lods):
+    column_names = ["marker", "chromosome", "position", "lod"]
+
+    def sanitize(entry):
+        entry["marker"] = entry["marker"].split(".")[1]
+        entry["position"] = int(float(entry["position"]) * 1e6)
+        entry["lod"] = float(entry["lod"])
+        return entry
+
+    for lod_tuple in lods:
         if len(lod_tuple) == len(column_names):
-            marker_name, chromosome, position, lod_score = lod_tuple
-            yield (
-                {
-                    "marker": marker_name.strip('"').split(".")[1],
-                    "position": float(position) * 1000000,
-                    "chromosome": chromosome.strip('"'),
-                    "lod": float(lod_score),
-                }
-            )
+            yield (sanitize(dict(zip(column_names, lod_tuple))))
         else:
             if len(lod_tuple) == 1 and lod_tuple[0] == "":
                 continue
@@ -472,7 +469,6 @@ def lod_score_gen(lods, analysis_name, history_id):
 
 
 def coefficient_gen(coefficients):
-    # TODO use simple split and then yield a dict directly
     column_names = [
         "marker",
         "chromosome",
@@ -488,28 +484,23 @@ def coefficient_gen(coefficients):
         "H",
     ]
 
-    def gen_transform_coef_tuple(coef_tuple):
+    def gen_sanitize_coef_tuple(coef_tuple):
         for i, val in enumerate(coef_tuple):
-            if i == 0:
-                yield val.strip('"')
-                # .split(".")[1]
-            if i == 1:
-                yield val.strip('"')
+            sanitized_val = val
             if i == 2:
-                yield float(val) * 1000000
+                sanitized_val = int(float(val) * 1e6)
             if i == 3:
-                yield float(val)
+                sanitized_val = float(val)
             if i > 3:
                 if val == "NA":
-                    yield None
+                    sanitized_val = None
                 else:
-                    yield float(val)
+                    sanitized_val = float(val)
+            yield sanitized_val
 
-    for coef_entry in coefficients:
-        coef_tuple = coef_entry.split(",")
+    for coef_tuple in coefficients:
         if len(coef_tuple) == len(column_names):
-            # marker,chromosome,position,lodscore,A, B, C, D, E, F, G, H = coef_tuple
-            yield (dict(zip(column_names, gen_transform_coef_tuple(coef_tuple))))
+            yield (dict(zip(column_names, gen_sanitize_coef_tuple(coef_tuple))))
         else:
             if len(coef_tuple) == 1 and coef_tuple[0] == "":
                 continue
@@ -519,17 +510,12 @@ def coefficient_gen(coefficients):
 
 def haplotype_gen(haplotypes):
     column_names = ["phenotype", "haplotype", "ccline"]
-    for haplo_entry in haplotypes:
-        haplo_tuple = haplo_entry.split(",")
+    for haplo_tuple in haplotypes:
         if len(haplo_tuple) == len(column_names):
-            phenotype, haplo, ccline = haplo_tuple
-            yield (
-                {
-                    column_names[0]: float(phenotype),
-                    column_names[1]: haplo.strip('"'),
-                    column_names[2]: ccline.strip('"'),
-                }
+            sanitized_haplo = (
+                float(h) if i == 0 else h for (i, h) in enumerate(haplo_tuple)
             )
+            yield (dict(zip(column_names, sanitized_haplo)))
         else:
             if len(haplo_tuple) == 1 and haplo_tuple[0] == "":
                 continue
@@ -538,19 +524,19 @@ def haplotype_gen(haplotypes):
 
 
 def top_snps_gen(top_snps):
-    column_names = ["phenotype", "ccline", "genotype"]
-
-    for top_snp_entry in top_snps:
-        top_snp_tuple = top_snp_entry.split(",")
-        if len(top_snp_tuple) == len(column_names):
-            phenotype, id_cc, genotype = top_snp_tuple
-            yield (
-                {
-                    column_names[0]: float(phenotype),
-                    column_names[1]: id_cc.strip('"'),
-                    column_names[2]: genotype.strip('"'),
-                }
+    column_names = ["phenotype", "ccline"]
+    top_snp_column_name = "top_snp"
+    for top_snp_tuple in top_snps:
+        if len(top_snp_tuple) > 2:
+            top_snp_cols = top_snp_tuple[2:]
+            for i in range(len(top_snp_cols)):
+                column_names.append(f"{top_snp_column_name}_{i+1}")
+            # if len(top_snp_tuple) == len(column_names):
+            sanitized_top_snp = (
+                float(snp) if i == 0 else snp for i, snp in enumerate(top_snp_tuple)
             )
+
+            yield dict(zip(column_names, sanitized_top_snp))
         else:
             if len(top_snp_tuple) == 1 and top_snp_tuple[0] == "":
                 continue
@@ -558,21 +544,60 @@ def top_snps_gen(top_snps):
                 raise Exception(f"Wrong number of columns {top_snp_tuple}")
 
 
+def peak_genes_gen(genes):
+    column_names = [
+        "chromosome",
+        "source",
+        "type",
+        "start",
+        "stop",
+        "score",
+        "strand",
+        "phase",
+        "id",
+        "name",
+        "parent",
+        "dbxref",
+        "mgiName",
+        "bioType",
+        "alias",
+    ]
+
+    def sanitize(entry_values):
+        for i, val in enumerate(entry_values):
+            if val == "NA":
+                val = None
+            if i == 3 or i == 4:
+                val = int(float(val) * 1e6)
+            yield val
+
+    for entry_values in genes:
+        if len(entry_values) == len(column_names):
+            # sanitized_values = (val if val != "NA" else None for val in entry_values)
+            yield dict(zip(column_names, sanitize(entry_values)))
+        else:
+            if len(entry_values) == 1 and entry_values[0] == "":
+                continue
+            else:
+                raise Exception(f"Wrong number of columns {entry_values}")
+
+
 def snps_association_gen(snps_associations):
     column_names = ["snp_id", "chromosome", "position", "lodscore"]
 
-    for assoc_entry in snps_associations:
-        assoc_tuple = assoc_entry.split(",")
+    def sanitize(assoc_tuple):
+        for i, val in enumerate(assoc_tuple):
+            if i == 2:
+                # postion
+                val = int(float(val) * 1e6)
+            if i == 3:
+                # lodscore
+                val = float(val)
+            yield val
+
+    for assoc_tuple in snps_associations:
         if len(assoc_tuple) == len(column_names):
-            snp_id, chromosome, position, lodscore = assoc_tuple
-            yield (
-                {
-                    column_names[0]: snp_id.strip('"'),
-                    column_names[1]: chromosome.strip('"'),
-                    column_names[2]: float(position) * 1000000,
-                    column_names[3]: float(lodscore),
-                }
-            )
+            yield dict(zip(column_names, sanitize(assoc_tuple)))
         else:
             if len(assoc_tuple) == 1 and assoc_tuple[0] == "":
                 continue
diff --git a/server/api/tests/conftest.py b/server/api/tests/conftest.py
index 5643accf8abccdc688d885c3b2261d1637de6109..18d6474e6e5cfc088acd086b375cd7094e683715 100644
--- a/server/api/tests/conftest.py
+++ b/server/api/tests/conftest.py
@@ -1,14 +1,17 @@
+import json
+
 # Django
 from django.urls import reverse
 from django.core.management import call_command
 
+
 # Pytest
 import pytest
 from pytest_factoryboy import register
 
 # django app
 from api.factories import SuperuserFactory, UserFactory
-from api.models import User
+from api.models import User, RoleGroup
 from .utils import authenticate
 
 register(SuperuserFactory)
@@ -53,12 +56,6 @@ def normaluser_build(user_factory):
     yield user_factory.build()
 
 
-@pytest.mark.django_db
-@pytest.fixture
-def normaluser(user_factory, user_password):
-    yield user_factory(password=user_password)
-
-
 @pytest.mark.django_db
 @pytest.fixture
 def normaluser_build_batch(user_factory):
@@ -109,6 +106,56 @@ def user_created_with_api(
     user.delete()
 
 
+# Create fixture that get the role groups
+# Load fixture and extract information
+@pytest.mark.django_db
+@pytest.fixture
+def role_groups():
+    with open("api/fixtures/groups.json", "r") as f:
+        role_groups_fixture = json.loads(f.read())
+        role_groups = [
+            {
+                "group_name": group["fields"]["group_ptr"][0],
+                "role": group["fields"]["role"][0],
+            }
+            for group in role_groups_fixture
+            if group["model"] == "api.rolegroup"
+        ]
+        yield role_groups
+
+
+@pytest.mark.django_db
+@pytest.fixture
+def role_users_created_with_api(
+    api_client_with_superuser_credential, user_factory, user_password, role_groups,
+):
+
+    for role_group in role_groups:
+        db_group = RoleGroup.objects.get(name__exact=role_group["group_name"])
+        normaluser_build = user_factory.build()
+        response = api_client_with_superuser_credential.post(
+            "/api/users/",
+            data={
+                "username": normaluser_build.username,
+                "first_name": normaluser_build.first_name,
+                "last_name": normaluser_build.last_name,
+                "email": normaluser_build.email,
+                "is_active": normaluser_build.is_active,
+                "password": user_password,
+                "appGroup": {"id": db_group.id, "name": db_group.name},
+            },
+            format="json",
+        )
+        assert response.status_code == 201
+        user_id = response.data["id"]
+        user = User.objects.get(pk=user_id)
+        assert normaluser_build.username == user.username
+        role_group["user"] = user
+    yield role_groups
+    for role_group in role_groups:
+        role_group["user"].delete()
+
+
 @pytest.mark.django_db
 @pytest.fixture
 def user_created_with_api_factory(api_client, superuser, user_factory, user_password):
diff --git a/server/api/tests/projects/conftest.py b/server/api/tests/projects/conftest.py
index 13fd047b7243ed9b58ee27d76b40e4dd499e1c54..0cda09adfb04f4779f27826162d16fb59b2021d8 100644
--- a/server/api/tests/projects/conftest.py
+++ b/server/api/tests/projects/conftest.py
@@ -1,3 +1,4 @@
+import json
 from api.models import ProjectRole
 import pytest
 from pytest_factoryboy import register
@@ -13,6 +14,74 @@ from api.tests.utils import authenticate
 register(ProjectFactory)
 
 
+permission_to_http_status_code = {"add": 201, "delete": 204, "change": 200, "view": 200}
+
+
+def getEmptyModelPermission():
+    return {"view": 403, "change": 403, "delete": 403, "add": 403}
+
+
+def getEmptyRole(role):
+    return dict(
+        zip(
+            [
+                "role",
+                "project",
+                "experiment",
+                "analysis",
+                "lodscore",
+                "peak",
+                "projectgroup",
+                "team",
+            ],
+            [
+                role,
+                getEmptyModelPermission(),
+                getEmptyModelPermission(),
+                getEmptyModelPermission(),
+                getEmptyModelPermission(),
+                getEmptyModelPermission(),
+                getEmptyModelPermission(),
+                getEmptyModelPermission(),
+            ],
+        )
+    )
+
+
+def load_project_role():
+    with open("api/fixtures/project-role-permissions.json", "r") as f:
+        project_role_permissions_fix = json.loads(f.read())
+        permissions_dict = dict()
+        permissions_dict[None] = getEmptyRole(None)
+
+        for pr_permission in project_role_permissions_fix:
+            role = pr_permission["fields"]["projectrole"][0]
+            if role not in permissions_dict:
+                permissions_dict[role] = getEmptyRole(role)
+
+            # like project, experiement, lodscore
+            model_permission = pr_permission["fields"]["permission"][2]
+            # add, change, view, delete
+            permission = pr_permission["fields"]["permission"][0].split("_", 2)[0]
+            permissions_dict[role][model_permission][
+                permission
+            ] = permission_to_http_status_code[permission]
+            # since it is control by project permissions some model need to have
+            # the same permissions as project
+            if model_permission == "project":
+                for model in ["lodscore", "peak"]:
+                    permissions_dict[role][model][
+                        permission
+                    ] = permission_to_http_status_code[permission]
+
+        # need to be 404 when not member
+        permissions_dict[None]["project"]["view"] = 404
+        import pprint
+
+        pprint.pprint(permissions_dict)
+        return list(permissions_dict.values())
+
+
 @pytest.mark.django_db
 @pytest.fixture
 def project_build(project_factory):
@@ -22,6 +91,7 @@ def project_build(project_factory):
 @pytest.mark.django_db
 @pytest.fixture
 def project_created_from_api_reponse(api_client_with_credentials, project_build):
+    load_project_role()
     resp = api_client_with_credentials.post(
         "/api/projects/",
         {
@@ -74,41 +144,7 @@ def project_changed_from_api(project_changed_from_api_reponse):
 
 @pytest.mark.django_db
 @pytest.fixture(
-    params=[
-        {
-            "role": None,
-            "project": {"view": 404, "change": 403, "delete": 403},
-            "experiment": {"view": 403, "change": 403, "delete": 403, "add": 403},
-            "analysis": {"view": 403, "change": 403, "delete": 403, "add": 403},
-            "lodscores": {"view": 403, "change": 403, "delete": 403, "add": 403},
-            "peaks": {"view": 403, "change": 403, "delete": 403, "add": 403},
-        },
-        {
-            "role": "reader",
-            "project": {"view": 200, "change": 403, "delete": 403},
-            "experiment": {"view": 200, "change": 200, "delete": 204, "add": 201},
-            "analysis": {"view": 200, "change": 200, "delete": 204, "add": 201},
-            "lodscores": {"view": 200, "change": 403, "delete": 403, "add": 403},
-            "peaks": {"view": 200, "change": 403, "delete": 403, "add": 403},
-        },
-        {
-            "role": "maintainer",
-            "project": {"view": 200, "change": 200, "delete": 403},
-            "experiment": {"view": 200, "change": 200, "delete": 204, "add": 201},
-            "analysis": {"view": 200, "change": 200, "delete": 204, "add": 201},
-            "lodscores": {"view": 200, "change": 200, "delete": 403, "add": 201},
-            "peaks": {"view": 200, "change": 403, "delete": 403, "add": 403},
-        },
-        {
-            "role": "manager",
-            "project": {"view": 200, "change": 200, "delete": 204},
-            "experiment": {"view": 200, "change": 200, "delete": 204, "add": 201},
-            "analysis": {"view": 200, "change": 200, "delete": 204, "add": 201},
-            "lodscores": {"view": 200, "change": 200, "delete": 204, "add": 201},
-            "peaks": {"view": 200, "change": 403, "delete": 403, "add": 403},
-        },
-    ],
-    ids=["not-member", "reader", "maintainer", "manager"],
+    params=load_project_role(), ids=["not-member", "reader", "maintainer", "manager"],
 )
 def project_with_members_response(
     api_client,
diff --git a/server/api/tests/projects/experiments_and_analysis/conftest.py b/server/api/tests/projects/experiments_and_analysis/conftest.py
index deaf74aa2082b7606a0b61bb73dd14a0282e70f9..be45f988bad3b94a906e37389b48a72c74c6e12d 100644
--- a/server/api/tests/projects/experiments_and_analysis/conftest.py
+++ b/server/api/tests/projects/experiments_and_analysis/conftest.py
@@ -7,7 +7,6 @@ from api.models import (
     Experiment,
     Haplotypes,
     LodScore,
-    LodScoreSignificanceThreshold,
     Peak,
     SnpsAssociation,
     TopSnps,
@@ -17,7 +16,6 @@ from api.tasks import (
     load_haplotypes,
     load_lod_score,
     load_refine_peaks,
-    load_significance_threshold,
     load_snps_association,
     load_top_snps,
 )
@@ -55,12 +53,12 @@ def get_only_lungs_metadata():
                 "name": "logNKnb.lungs",
                 "description": "blabla",
                 "datatype": "Float",
-                "dataclass": "Variable",
+                "dataclass": "Phenotype",
                 "nature": "Count",
                 "location": "Organ",
                 "colid": 4,
                 "colIndex": 4,
-                "colName": "logNKnb.lungs_Variable_Float_Count_Organ",
+                "colName": "logNKnb.lungs_Phenotype_Float_Count_Organ",
             },
         ]
     ),
@@ -105,7 +103,6 @@ def experiment_created_from_api_response(
 @pytest.mark.django_db
 @pytest.fixture
 def experiment_created_from_api(experiment_created_from_api_response):
-    print(experiment_created_from_api_response)
     experiment = Experiment.objects.get(
         id=experiment_created_from_api_response.data["id"]
     )
@@ -131,21 +128,29 @@ def mock_analysis_wf(mocker):
     def mock_run_analysis(*args, **kwargs):
         return {"history_id": "history_id", "workflow_id": "workflow_id", "id": "id"}
 
-    def mock_load_results(*args, **kwargs):
-        print("fake load analyis results")
+    # def mock_load_results(*args, **kwargs):
+    #     print("fake load analyis results")
 
     mocker.patch("api.serializers.run_analyis", mock_run_analysis)
-    mocker.patch("api.serializers.load_results", mock_load_results)
+    # mocker.patch("api.serializers.load_results", mock_load_results)
     yield mocker
 
 
-@pytest.fixture
+@pytest.fixture(scope="function", params=["ok"])
 def mock_show_history_factory(request, mocker):
     def _factory(*datasets):
         def _mock_show_history(*args, **kwargs):
-            return [
-                {"name": dataset["name"], "id": dataset["id"]} for dataset in datasets
-            ]
+            if kwargs["contents"]:
+                return [
+                    {
+                        "name": dataset["name"],
+                        "id": dataset["id"],
+                        "state": request.param,
+                    }
+                    for dataset in datasets
+                ]
+            else:
+                return {"name": "fake-history-name", "state": "error"}
 
         mocker.patch("api.tasks.gi.histories.show_history", _mock_show_history)
         # return mocker
@@ -153,12 +158,32 @@ def mock_show_history_factory(request, mocker):
     yield _factory
 
 
+@pytest.fixture
+def mock_mkdtemp_factory(mocker, request, shared_datadir):
+    def _factory():
+        def _mock_mkdtemp(*args, **kwargs):
+            # TODO
+            # message = f"Dataset state is not 'ok'. Dataset id: {dataset_id}, current state: {dataset['state']}"
+            # if require_ok_state:
+            #     raise DatasetStateException(message)
+            return shared_datadir
+
+        mocker.patch("api.galaxy.mkdtemp", _mock_mkdtemp)
+        # yield mocker
+
+    yield _factory
+
+
 @pytest.fixture
 def mock_download_dataset_factory(
     mocker, request, shared_datadir,
 ):
     def _factory():
         def _mock_download_dataset(*args, **kwargs):
+            # TODO
+            # message = f"Dataset state is not 'ok'. Dataset id: {dataset_id}, current state: {dataset['state']}"
+            # if require_ok_state:
+            #     raise DatasetStateException(message)
             file_path = shared_datadir / args[0]
             with open(file_path, "rb") as fp:
                 return fp.read()
@@ -169,6 +194,20 @@ def mock_download_dataset_factory(
     yield _factory
 
 
+@pytest.fixture
+def mock_download_dataset_in_tmp_factory(
+    mocker, request, shared_datadir,
+):
+    def _factory():
+        def _mock_download_dataset(*args, **kwargs):
+            # TODO
+            return kwargs["file_path"]
+
+        mocker.patch("api.tasks.gi.datasets.download_dataset", _mock_download_dataset)
+
+    yield _factory
+
+
 @pytest.fixture
 def mock_get_history_status(mocker):
     def _mock_get_history_status(*args, **kwargs):
@@ -178,12 +217,21 @@ def mock_get_history_status(mocker):
     yield mocker
 
 
+@pytest.fixture
+def mock_get_history_status_in_model(mocker):
+    def _mock_get_history_status(*args, **kwargs):
+        return {"history_status": {"state": "ok"}}
+
+    mocker.patch("api.models.runner.get_history_status", _mock_get_history_status)
+    yield mocker
+
+
 @pytest.fixture
 def mock_delete_history(mocker):
     def _mock_delete_history(*args, **kwargs):
         return {}
 
-    mocker.patch("api.views.delete_history", _mock_delete_history)
+    mocker.patch("api.views.runner.delete_history", _mock_delete_history)
     yield mocker
 
 
@@ -192,7 +240,7 @@ def analysis_tool_params():
     yield {
         "1": {
             "cc_giga_muga": "cc_giga_muga_v1",
-            "column_pheno": "5",
+            "column_pheno": "logNKnb.lungs",
             "founder_giga_muga": "founder_giga_muga_v1",
             "funnel_codes": "funnel_codes_v1",
         },
@@ -208,6 +256,13 @@ def analysis_tool_params():
 
 
 @pytest.fixture
+def workflow_id():
+    yield "657f009ad32a3f27"
+
+
+@pytest.fixture(
+    params=["657f009ad32a3f27"], ids=["v0.22_11"],
+)
 def analysis_created_from_api_response(
     api_client,
     user_created_with_api,
@@ -217,6 +272,8 @@ def analysis_created_from_api_response(
     user_password,
     analysis_tool_params,
     mock_analysis_wf,
+    mock_get_history_status_in_model,
+    request,
 ):
     client = authenticate(api_client, user_created_with_api, user_password)
 
@@ -225,9 +282,11 @@ def analysis_created_from_api_response(
         url,
         {
             "name": analysis_build.name,
-            "galaxy_history_id": "",
+            "galaxy_history_id": "fake-galaxy-history-id",
+            "description": analysis_build.description,
             "experiments": [experiment_created_from_api.id],
             "toolsParams": analysis_tool_params,
+            "galaxy_workflow_id": request.param,
         },
         format="json",
     )
@@ -236,7 +295,6 @@ def analysis_created_from_api_response(
 
 @pytest.fixture
 def analysis_created_from_api(analysis_created_from_api_response):
-
     analysis = Analysis.objects.get(id=analysis_created_from_api_response.data["id"])
     yield analysis
     analysis.delete()
@@ -244,21 +302,25 @@ def analysis_created_from_api(analysis_created_from_api_response):
 
 @pytest.fixture
 def lodscores_created_from_task_result(
-    analysis_created_from_api, mock_download_dataset_factory, mock_show_history_factory,
+    analysis_created_from_api,
+    mock_mkdtemp_factory,
+    mock_download_dataset_in_tmp_factory,
+    mock_show_history_factory,
 ):
-    mock_show_history_factory({"name": "xxxx_lod.csv", "id": "lodscores.csv"})
-    mock_download_dataset_factory()
+    mock_mkdtemp_factory()
+    mock_show_history_factory({"name": "lod.csv", "id": "lod"})
+    mock_download_dataset_in_tmp_factory()
     yield load_lod_score(
-        analysis_created_from_api.name, analysis_created_from_api.galaxy_history_id
+        (analysis_created_from_api.id, analysis_created_from_api.galaxy_history_id, "",)
     )
 
 
 @pytest.fixture
 def lodscores_created_from_task(lodscores_created_from_task_result):
-    lodscore = LodScore.objects.get(
-        id=lodscores_created_from_task_result["lodscores_id"]
-    )
-    yield lodscore
+    if lodscores_created_from_task_result[2] is not None:
+        yield LodScore.objects.get(id=lodscores_created_from_task_result[2])
+    else:
+        yield lodscores_created_from_task_result[2]
 
 
 @pytest.fixture
@@ -268,18 +330,23 @@ def peak_build(peak_factory):
 
 @pytest.fixture
 def peaks_created_from_task_result(
-    analysis_created_from_api, mock_show_history_factory, mock_download_dataset_factory
+    analysis_created_from_api,
+    mock_show_history_factory,
+    mock_mkdtemp_factory,
+    mock_download_dataset_in_tmp_factory,
 ):
-    mock_show_history_factory({"name": "xxxx_refine-peaks.csv", "id": "peaks.csv"})
-    mock_download_dataset_factory()
+    mock_mkdtemp_factory()
+    mock_show_history_factory({"name": "refine-peaks.csv", "id": "peaks.csv"})
+    mock_download_dataset_in_tmp_factory()
+
     yield load_refine_peaks(
-        analysis_created_from_api.name, analysis_created_from_api.galaxy_history_id
+        (analysis_created_from_api.id, analysis_created_from_api.galaxy_history_id, "",)
     )
 
 
 @pytest.fixture
 def peaks_created_from_task(peaks_created_from_task_result):
-    peaks = Peak.objects.filter(id__in=peaks_created_from_task_result["peak_ids"])
+    peaks = Peak.objects.filter(id__in=peaks_created_from_task_result[2])
     yield peaks
 
 
@@ -288,9 +355,11 @@ def coefficients_created_from_task_result(
     analysis_created_from_api,
     peaks_created_from_task_result,
     mock_show_history_factory,
-    mock_download_dataset_factory,
+    # mock_download_dataset_factory,
+    mock_mkdtemp_factory,
+    mock_download_dataset_in_tmp_factory,
 ):
-
+    mock_mkdtemp_factory()
     # show_history
     # download_dataset
     mock_show_history_factory(
@@ -299,18 +368,20 @@ def coefficients_created_from_task_result(
             "id": "coef.csv",
         }
     )
-    mock_download_dataset_factory()
+    mock_download_dataset_in_tmp_factory()
     yield load_coefficient(
-        analysis_created_from_api.name, analysis_created_from_api.galaxy_history_id
+        (analysis_created_from_api.id, analysis_created_from_api.galaxy_history_id, "")
     )
 
 
 @pytest.fixture
 def coefficient_created_from_task(coefficients_created_from_task_result):
-    coeff = Coefficient.objects.get(
-        id=coefficients_created_from_task_result["coefficient_id"]
-    )
-    yield coeff
+    if len(coefficients_created_from_task_result[2]) > 0:
+        yield Coefficient.objects.filter(
+            id__in=coefficients_created_from_task_result[2]
+        )
+    else:
+        yield None
 
 
 @pytest.fixture
@@ -318,9 +389,10 @@ def haplotypes_created_from_task_result(
     analysis_created_from_api,
     peaks_created_from_task_result,
     mock_show_history_factory,
-    mock_download_dataset_factory,
+    mock_mkdtemp_factory,
+    mock_download_dataset_in_tmp_factory,
 ):
-
+    mock_mkdtemp_factory()
     # show_history
     # download_dataset
     mock_show_history_factory(
@@ -329,26 +401,30 @@ def haplotypes_created_from_task_result(
             "id": "haplo.csv",
         }
     )
-    mock_download_dataset_factory()
+    mock_download_dataset_in_tmp_factory()
     yield load_haplotypes(
-        analysis_created_from_api.name, analysis_created_from_api.galaxy_history_id
+        (analysis_created_from_api.id, analysis_created_from_api.galaxy_history_id, "")
     )
 
 
 @pytest.fixture
 def haplotypes_created_from_task(haplotypes_created_from_task_result):
-    haplo = Haplotypes.objects.get(id=haplotypes_created_from_task_result["id"])
-    yield haplo
+    if len(haplotypes_created_from_task_result[2]) > 0:
+        yield Haplotypes.objects.filter(id__in=haplotypes_created_from_task_result[2])
+
+    else:
+        yield None
 
 
 @pytest.fixture
 def snps_assoc_created_from_task_result(
     analysis_created_from_api,
     peaks_created_from_task_result,
+    mock_mkdtemp_factory,
     mock_show_history_factory,
-    mock_download_dataset_factory,
+    mock_download_dataset_in_tmp_factory,
 ):
-
+    mock_mkdtemp_factory()
     # show_history
     # download_dataset
     mock_show_history_factory(
@@ -357,16 +433,20 @@ def snps_assoc_created_from_task_result(
             "id": "snps_assoc.csv",
         }
     )
-    mock_download_dataset_factory()
+    mock_download_dataset_in_tmp_factory()
     yield load_snps_association(
-        analysis_created_from_api.name, analysis_created_from_api.galaxy_history_id
+        (analysis_created_from_api.id, analysis_created_from_api.galaxy_history_id, "",)
     )
 
 
 @pytest.fixture
 def snps_assoc_created_from_task(snps_assoc_created_from_task_result):
-    snps = SnpsAssociation.objects.get(id=snps_assoc_created_from_task_result["id"])
-    yield snps
+    if len(snps_assoc_created_from_task_result[2]) > 0:
+        yield SnpsAssociation.objects.filter(
+            id__in=snps_assoc_created_from_task_result[2]
+        )
+    else:
+        yield None
 
 
 # TOP SNPS
@@ -374,10 +454,11 @@ def snps_assoc_created_from_task(snps_assoc_created_from_task_result):
 def top_snps_created_from_task_result(
     analysis_created_from_api,
     peaks_created_from_task_result,
+    mock_mkdtemp_factory,
     mock_show_history_factory,
-    mock_download_dataset_factory,
+    mock_download_dataset_in_tmp_factory,
 ):
-
+    mock_mkdtemp_factory()
     # show_history
     # download_dataset
     mock_show_history_factory(
@@ -386,44 +467,16 @@ def top_snps_created_from_task_result(
             "id": "top_snps.csv",
         }
     )
-    mock_download_dataset_factory()
+    mock_download_dataset_in_tmp_factory()
     yield load_top_snps(
-        analysis_created_from_api.name, analysis_created_from_api.galaxy_history_id
+        (analysis_created_from_api.id, analysis_created_from_api.galaxy_history_id, "",)
     )
 
 
 @pytest.fixture
 def top_snps_created_from_task(top_snps_created_from_task_result):
-    snps = TopSnps.objects.get(id=top_snps_created_from_task_result["id"])
-    yield snps
-
-
-# SIGNIFICANCE_THRESHOLD
-@pytest.fixture
-def significance_threshold_created_from_task_result(
-    analysis_created_from_api,
-    peaks_created_from_task_result,
-    mock_show_history_factory,
-    mock_download_dataset_factory,
-):
-
-    # show_history
-    # download_dataset
-    mock_show_history_factory(
-        {"name": "xxxx_significance-threshold.csv", "id": "significance-threshold.csv"}
-    )
-    mock_download_dataset_factory()
-    yield load_significance_threshold(
-        analysis_created_from_api.name, analysis_created_from_api.galaxy_history_id
-    )
-
-
-@pytest.fixture
-def significance_threshold_created_from_task(
-    significance_threshold_created_from_task_result,
-):
-    thresholds = LodScoreSignificanceThreshold.objects.filter(
-        id__in=significance_threshold_created_from_task_result["ids"]
-    )
-    yield thresholds
+    if len(top_snps_created_from_task_result[2]) > 0:
+        yield TopSnps.objects.filter(id__in=top_snps_created_from_task_result[2])
+    else:
+        yield None
 
diff --git a/server/api/tests/projects/experiments_and_analysis/data/lodscores.csv b/server/api/tests/projects/experiments_and_analysis/data/lod.csv
similarity index 100%
rename from server/api/tests/projects/experiments_and_analysis/data/lodscores.csv
rename to server/api/tests/projects/experiments_and_analysis/data/lod.csv
diff --git a/server/api/tests/projects/experiments_and_analysis/data/only_lungs.csv b/server/api/tests/projects/experiments_and_analysis/data/only_lungs.csv
index 69adccdbee607f68517c7bdc67bc78dcb7aba4a4..bbd3f6d70725dac47823d9719a75a9ab47612136 100644
--- a/server/api/tests/projects/experiments_and_analysis/data/only_lungs.csv
+++ b/server/api/tests/projects/experiments_and_analysis/data/only_lungs.csv
@@ -1,4 +1,4 @@
-CC_ID,Line_M,Line_F,Sex,logNKnb.lungs
+Individual_ID,Mother_Line,Father_Line,Sex,logNKnb.lungs
 1,CC001,CC001,F,6.37445505240996
 2,CC001,CC001,F,5.73511963408187
 3,CC001,CC001,F,5.7769915848564
diff --git a/server/api/tests/projects/experiments_and_analysis/data/only_lungs_with_bad_ccline.csv b/server/api/tests/projects/experiments_and_analysis/data/only_lungs_with_bad_ccline.csv
index 449ea5015663fd0ad93cc239f6ba621b5275b7c4..821a89b36f0e8ed1e54ac1534a43389b98a8b20c 100644
--- a/server/api/tests/projects/experiments_and_analysis/data/only_lungs_with_bad_ccline.csv
+++ b/server/api/tests/projects/experiments_and_analysis/data/only_lungs_with_bad_ccline.csv
@@ -1,4 +1,4 @@
-CC_ID,Line_M,Line_F,Sex,logNKnb.lungs
+Individual_ID,Mother_Line,Father_Line,Sex,logNKnb.lungs
 1,NOT_EXISTING_CCLINE,CC001,F,6.37445505240996
 2,CC001,CC001,F,5.73511963408187
 3,CC001,CC001,F,5.7769915848564
diff --git a/server/api/tests/projects/experiments_and_analysis/data/peaks.csv b/server/api/tests/projects/experiments_and_analysis/data/refine-peaks.csv
similarity index 100%
rename from server/api/tests/projects/experiments_and_analysis/data/peaks.csv
rename to server/api/tests/projects/experiments_and_analysis/data/refine-peaks.csv
diff --git a/server/api/tests/projects/experiments_and_analysis/data/coef.csv b/server/api/tests/projects/experiments_and_analysis/data/var--matched_data.PHENO...input.phenocol.--chr--13--pos--93912931--coef.csv
similarity index 100%
rename from server/api/tests/projects/experiments_and_analysis/data/coef.csv
rename to server/api/tests/projects/experiments_and_analysis/data/var--matched_data.PHENO...input.phenocol.--chr--13--pos--93912931--coef.csv
diff --git a/server/api/tests/projects/experiments_and_analysis/data/haplo.csv b/server/api/tests/projects/experiments_and_analysis/data/var--matched_data.PHENO...input.phenocol.--chr--13--pos--93912931--haplo.csv
similarity index 100%
rename from server/api/tests/projects/experiments_and_analysis/data/haplo.csv
rename to server/api/tests/projects/experiments_and_analysis/data/var--matched_data.PHENO...input.phenocol.--chr--13--pos--93912931--haplo.csv
diff --git a/server/api/tests/projects/experiments_and_analysis/data/snps_assoc.csv b/server/api/tests/projects/experiments_and_analysis/data/var--matched_data.PHENO...input.phenocol.--chr--13--pos--93912931--snps_assoc.csv
similarity index 100%
rename from server/api/tests/projects/experiments_and_analysis/data/snps_assoc.csv
rename to server/api/tests/projects/experiments_and_analysis/data/var--matched_data.PHENO...input.phenocol.--chr--13--pos--93912931--snps_assoc.csv
diff --git a/server/api/tests/projects/experiments_and_analysis/data/top_snps.csv b/server/api/tests/projects/experiments_and_analysis/data/var--matched_data.PHENO...input.phenocol.--chr--13--pos--93912931--top_snps.csv
similarity index 100%
rename from server/api/tests/projects/experiments_and_analysis/data/top_snps.csv
rename to server/api/tests/projects/experiments_and_analysis/data/var--matched_data.PHENO...input.phenocol.--chr--13--pos--93912931--top_snps.csv
diff --git a/server/api/tests/projects/experiments_and_analysis/test_analysis.py b/server/api/tests/projects/experiments_and_analysis/test_analysis.py
index 173e93d621e10674a6add7042b94991778b7f7f9..8dd3cce2c10b9075126d43f22a87c3e5ce808f7e 100644
--- a/server/api/tests/projects/experiments_and_analysis/test_analysis.py
+++ b/server/api/tests/projects/experiments_and_analysis/test_analysis.py
@@ -24,8 +24,9 @@ def test_analysis_permissions(
     analysis_created_from_api,
     user_password,
     analysis_tool_params,
-    mock_get_history_status,
     mock_delete_history,
+    mock_get_history_status_in_model,
+    workflow_id,
 ):
 
     role_param = project_with_members_response[1]
@@ -40,7 +41,7 @@ def test_analysis_permissions(
 
         # test change experiment
         new_name = f"new-name-{i}"
-        resp = client.put(url, {"name": new_name},)
+        resp = client.patch(url, {"name": new_name},)
         assert resp.status_code == expected["change"]
         if expected["change"] == 200:
             assert resp.data["name"] == new_name
@@ -54,6 +55,7 @@ def test_analysis_permissions(
                 "galaxy_history_id": "",
                 "experiments": [experiment_created_from_api.id],
                 "toolsParams": analysis_tool_params,
+                "galaxy_workflow_id": workflow_id,
             },
             format="json",
         )
diff --git a/server/api/tests/projects/experiments_and_analysis/test_coefficients.py b/server/api/tests/projects/experiments_and_analysis/test_coefficients.py
index 421612686cee5c2af29814bc6cba3525b7010509..4a0bc5ede03162f121df4c649d4ed9dadcaf1cdd 100644
--- a/server/api/tests/projects/experiments_and_analysis/test_coefficients.py
+++ b/server/api/tests/projects/experiments_and_analysis/test_coefficients.py
@@ -3,8 +3,10 @@ from api.tests.utils import authenticate
 
 
 @pytest.mark.django_db
-def test_coefficient_creation(coefficients_created_from_task_result):
-    assert coefficients_created_from_task_result["status"] == "ok"
+def test_coefficient_creation(
+    analysis_created_from_api, coefficients_created_from_task_result
+):
+    assert coefficients_created_from_task_result[0] == analysis_created_from_api.id
 
 
 @pytest.mark.django_db
@@ -17,20 +19,23 @@ def test_coefficent_permissions(
     user_password,
     coefficient_created_from_task,
 ):
-
-    role_param = project_with_members_response[1]
-    expected = role_param["peaks"]
-    base_url = (
-        f"/api/projects/{project_created_from_api.id}/analysis"
-        + f"/{analysis_created_from_api.id}/peaks"
-    )
-    for i, member in enumerate(user_batch_created_with_api):
-        client = authenticate(api_client, member, user_password)
-        # test view experiment
-        peak = coefficient_created_from_task.peak
-        url = f"{base_url}/{peak.id}/coefficients/"
-        resp = client.get(url)
-        assert resp.status_code == expected["view"]
-        if expected["view"] == 200:
-            assert len(resp.data["coefficients"]) == 215
+    if coefficient_created_from_task is None:
+        pass
+    else:
+        for coeff in coefficient_created_from_task:
+            role_param = project_with_members_response[1]
+            expected = role_param["peak"]
+            base_url = (
+                f"/api/projects/{project_created_from_api.id}/analysis"
+                + f"/{analysis_created_from_api.id}/peaks"
+            )
+            for i, member in enumerate(user_batch_created_with_api):
+                client = authenticate(api_client, member, user_password)
+                # test view experiment
+                peak = coeff.peak
+                url = f"{base_url}/{peak.id}/coefficients/"
+                resp = client.get(url)
+                assert resp.status_code == expected["view"]
+                if expected["view"] == 200:
+                    assert len(resp.data["coefficients"]) == 215
 
diff --git a/server/api/tests/projects/experiments_and_analysis/test_haplotype.py b/server/api/tests/projects/experiments_and_analysis/test_haplotype.py
index 904cbcfcb7aa806fe12f5dc376763a877700c16e..b12c51051d3efcfb96972c26467d9705fe199f31 100644
--- a/server/api/tests/projects/experiments_and_analysis/test_haplotype.py
+++ b/server/api/tests/projects/experiments_and_analysis/test_haplotype.py
@@ -3,8 +3,10 @@ from api.tests.utils import authenticate
 
 
 @pytest.mark.django_db
-def test_haplotype_creation(haplotypes_created_from_task_result):
-    assert haplotypes_created_from_task_result["status"] == "ok"
+def test_haplotype_creation(
+    analysis_created_from_api, haplotypes_created_from_task_result
+):
+    assert haplotypes_created_from_task_result[0] == analysis_created_from_api.id
 
 
 @pytest.mark.django_db
@@ -17,20 +19,22 @@ def test_haplotype_permissions(
     user_password,
     haplotypes_created_from_task,
 ):
-
-    role_param = project_with_members_response[1]
-    expected = role_param["peaks"]
-    base_url = (
-        f"/api/projects/{project_created_from_api.id}/analysis"
-        + f"/{analysis_created_from_api.id}/peaks"
-    )
-    for i, member in enumerate(user_batch_created_with_api):
-        client = authenticate(api_client, member, user_password)
-        # test view experiment
-        peak = haplotypes_created_from_task.peak
-        url = f"{base_url}/{peak.id}/haplotypes/"
-        resp = client.get(url)
-        assert resp.status_code == expected["view"]
-        if expected["view"] == 200:
-            assert len(resp.data["haplotypes"]) == 139
-
+    if haplotypes_created_from_task is None:
+        pass
+    else:
+        for haplo in haplotypes_created_from_task:
+            role_param = project_with_members_response[1]
+            expected = role_param["peak"]
+            base_url = (
+                f"/api/projects/{project_created_from_api.id}/analysis"
+                + f"/{analysis_created_from_api.id}/peaks"
+            )
+            for i, member in enumerate(user_batch_created_with_api):
+                client = authenticate(api_client, member, user_password)
+                # test view experiment
+                peak = haplo.peak
+                url = f"{base_url}/{peak.id}/haplotypes/"
+                resp = client.get(url)
+                assert resp.status_code == expected["view"]
+                if expected["view"] == 200:
+                    assert len(resp.data["haplotypes"]) == 139
diff --git a/server/api/tests/projects/experiments_and_analysis/test_lodscores.py b/server/api/tests/projects/experiments_and_analysis/test_lodscores.py
index bbd28c1e0524699018f9a8bc1fec11a58197a63e..b78777d0d558a9729176c6dfa593157675dde7d4 100644
--- a/server/api/tests/projects/experiments_and_analysis/test_lodscores.py
+++ b/server/api/tests/projects/experiments_and_analysis/test_lodscores.py
@@ -49,19 +49,23 @@ def test_lodscores_permissions(
     user_password,
     lodscores_created_from_task,
 ):
-    role_param = project_with_members_response[1]
-    expected = role_param["lodscores"]
-    base_url = (
-        f"/api/projects/{project_created_from_api.id}/analysis"
-        + f"/{analysis_created_from_api.id}/lodscores"
-    )
-    # url = f"{base_url}/{lodscores_created_from_task.id}/"
-    url = f"{base_url}/"
-    for i, member in enumerate(user_batch_created_with_api):
-        client = authenticate(api_client, member, user_password)
-        # test view experiment
-        resp = client.get(url)
-        assert resp.status_code == expected["view"]
-        if expected["view"] == 200:
-            assert len(resp.data["lod_scores"]) == 100
+
+    if lodscores_created_from_task is None:
+        pass
+    else:
+        role_param = project_with_members_response[1]
+        expected = role_param["lodscore"]
+        base_url = (
+            f"/api/projects/{project_created_from_api.id}/analysis"
+            + f"/{analysis_created_from_api.id}/lodscores"
+        )
+        # url = f"{base_url}/{lodscores_created_from_task.id}/"
+        url = f"{base_url}/"
+        for i, member in enumerate(user_batch_created_with_api):
+            client = authenticate(api_client, member, user_password)
+            # test view experiment
+            resp = client.get(url)
+            assert resp.status_code == expected["view"]
+            if expected["view"] == 200:
+                assert len(resp.data["lod_scores"]) == 100
 
diff --git a/server/api/tests/projects/experiments_and_analysis/test_peaks.py b/server/api/tests/projects/experiments_and_analysis/test_peaks.py
index 8ebc8b2a0db4afe6197ed32fbc7d645fb650f79b..c7d22e76e02e64246f4efe19de937b4be5a6aa61 100644
--- a/server/api/tests/projects/experiments_and_analysis/test_peaks.py
+++ b/server/api/tests/projects/experiments_and_analysis/test_peaks.py
@@ -14,7 +14,7 @@ def test_peaks_permissions(
 ):
 
     role_param = project_with_members_response[1]
-    expected = role_param["peaks"]
+    expected = role_param["peak"]
     base_url = (
         f"/api/projects/{project_created_from_api.id}/analysis"
         + f"/{analysis_created_from_api.id}/peaks"
diff --git a/server/api/tests/projects/experiments_and_analysis/test_significance_thresholds.py b/server/api/tests/projects/experiments_and_analysis/test_significance_thresholds.py
deleted file mode 100644
index 4642eebe07dfc77d2a00ac17b89da88013b560e4..0000000000000000000000000000000000000000
--- a/server/api/tests/projects/experiments_and_analysis/test_significance_thresholds.py
+++ /dev/null
@@ -1,37 +0,0 @@
-import pytest
-from api.tests.utils import authenticate
-
-
-@pytest.mark.django_db
-def test_significance_thresholds_creation(
-    significance_threshold_created_from_task_result,
-):
-    assert significance_threshold_created_from_task_result["status"] == "ok"
-
-
-@pytest.mark.django_db
-def test_significance_thresholds_permissions(
-    api_client,
-    user_batch_created_with_api,
-    project_created_from_api,
-    project_with_members_response,
-    analysis_created_from_api,
-    
-    user_password,
-    significance_threshold_created_from_task,
-):
-
-    role_param = project_with_members_response[1]
-    expected = role_param["peaks"]
-    base_url = (
-        f"/api/projects/{project_created_from_api.id}/analysis"
-        + f"/{analysis_created_from_api.id}/significance_thresholds/"
-    )
-    for i, member in enumerate(user_batch_created_with_api):
-        client = authenticate(api_client, member, user_password)
-        # test view experiment
-        resp = client.get(base_url)
-        assert resp.status_code == expected["view"]
-        if expected["view"] == 200:
-            assert len(resp.data) == 6
-
diff --git a/server/api/tests/projects/experiments_and_analysis/test_snps_associations.py b/server/api/tests/projects/experiments_and_analysis/test_snps_associations.py
index d07eaf786a9c0104aeb8c7213ca247886081f18f..198fd89c382c42ad09cd9a6b21c21bd9d13be1f8 100644
--- a/server/api/tests/projects/experiments_and_analysis/test_snps_associations.py
+++ b/server/api/tests/projects/experiments_and_analysis/test_snps_associations.py
@@ -3,8 +3,10 @@ from api.tests.utils import authenticate
 
 
 @pytest.mark.django_db
-def test_snps_assoc_creation(snps_assoc_created_from_task_result):
-    assert snps_assoc_created_from_task_result["status"] == "ok"
+def test_snps_assoc_creation(
+    analysis_created_from_api, snps_assoc_created_from_task_result
+):
+    assert snps_assoc_created_from_task_result[0] == analysis_created_from_api.id
 
 
 @pytest.mark.django_db
@@ -17,20 +19,23 @@ def test_snps_assoc_permissions(
     user_password,
     snps_assoc_created_from_task,
 ):
-
-    role_param = project_with_members_response[1]
-    expected = role_param["peaks"]
-    base_url = (
-        f"/api/projects/{project_created_from_api.id}/analysis"
-        + f"/{analysis_created_from_api.id}/peaks"
-    )
-    for i, member in enumerate(user_batch_created_with_api):
-        client = authenticate(api_client, member, user_password)
-        # test view experiment
-        peak = snps_assoc_created_from_task.peak
-        url = f"{base_url}/{peak.id}/snps_association/"
-        resp = client.get(url)
-        assert resp.status_code == expected["view"]
-        if expected["view"] == 200:
-            assert len(resp.data["snps_association"]) == 649
+    if snps_assoc_created_from_task is None:
+        pass
+    else:
+        for snps_assoc in snps_assoc_created_from_task:
+            role_param = project_with_members_response[1]
+            expected = role_param["peak"]
+            base_url = (
+                f"/api/projects/{project_created_from_api.id}/analysis"
+                + f"/{analysis_created_from_api.id}/peaks"
+            )
+            for i, member in enumerate(user_batch_created_with_api):
+                client = authenticate(api_client, member, user_password)
+                # test view experiment
+                peak = snps_assoc.peak
+                url = f"{base_url}/{peak.id}/snps_association/"
+                resp = client.get(url)
+                assert resp.status_code == expected["view"]
+                if expected["view"] == 200:
+                    assert len(resp.data["snps_association"]) == 649
 
diff --git a/server/api/tests/projects/experiments_and_analysis/test_top_snps.py b/server/api/tests/projects/experiments_and_analysis/test_top_snps.py
index 13aadde9ffa622722ebc8545f89d3a0d14f91f8d..977560b2fe6c6a29360991513fe50048a43406ce 100644
--- a/server/api/tests/projects/experiments_and_analysis/test_top_snps.py
+++ b/server/api/tests/projects/experiments_and_analysis/test_top_snps.py
@@ -3,8 +3,10 @@ from api.tests.utils import authenticate
 
 
 @pytest.mark.django_db
-def test_top_snps_creation(top_snps_created_from_task_result):
-    assert top_snps_created_from_task_result["status"] == "ok"
+def test_top_snps_creation(
+    analysis_created_from_api, top_snps_created_from_task_result
+):
+    assert top_snps_created_from_task_result[0] == analysis_created_from_api.id
 
 
 @pytest.mark.django_db
@@ -17,20 +19,23 @@ def test_top_snps_permissions(
     user_password,
     top_snps_created_from_task,
 ):
-
-    role_param = project_with_members_response[1]
-    expected = role_param["peaks"]
-    base_url = (
-        f"/api/projects/{project_created_from_api.id}/analysis"
-        + f"/{analysis_created_from_api.id}/peaks"
-    )
-    for i, member in enumerate(user_batch_created_with_api):
-        client = authenticate(api_client, member, user_password)
-        # test view experiment
-        peak = top_snps_created_from_task.peak
-        url = f"{base_url}/{peak.id}/top_snps/"
-        resp = client.get(url)
-        assert resp.status_code == expected["view"]
-        if expected["view"] == 200:
-            assert len(resp.data["top_snps"]) == 139
+    if top_snps_created_from_task is None:
+        pass
+    else:
+        for top_snps in top_snps_created_from_task:
+            role_param = project_with_members_response[1]
+            expected = role_param["peak"]
+            base_url = (
+                f"/api/projects/{project_created_from_api.id}/analysis"
+                + f"/{analysis_created_from_api.id}/peaks"
+            )
+            for i, member in enumerate(user_batch_created_with_api):
+                client = authenticate(api_client, member, user_password)
+                # test view experiment
+                peak = top_snps.peak
+                url = f"{base_url}/{peak.id}/top_snps/"
+                resp = client.get(url)
+                assert resp.status_code == expected["view"]
+                if expected["view"] == 200:
+                    assert len(resp.data["top_snps"]) == 139
 
diff --git a/server/api/tests/projects/test_project.py b/server/api/tests/projects/test_project.py
index 813fc99dbf4cb391f4f12b0b2760f3ad142a6cb6..03a7733a30e0a37a487c24d067aebac5d2085a4e 100644
--- a/server/api/tests/projects/test_project.py
+++ b/server/api/tests/projects/test_project.py
@@ -1,4 +1,4 @@
-from api.models import ProjectGroup
+from api.models import ProjectGroup, ProjectRole
 import pytest
 from ..utils import authenticate
 
@@ -29,6 +29,19 @@ def test_create_project(project_created_from_api_reponse, project_build):
         == project_build.project_name
     )
 
+    project_groups = ProjectGroup.objects.filter(
+        project__id=project_created_from_api_reponse.data["id"]
+    )
+    project_roles = ProjectRole.objects.all()
+
+    project_group_names_in_db = set([pg.name for pg in project_groups])
+
+    expected_project_group_names = set(
+        [f"{project_build.project_name}_{role.name}" for role in project_roles]
+    )
+    assert project_group_names_in_db == expected_project_group_names
+    # assert False
+
 
 @pytest.mark.django_db
 def test_get_project(
@@ -76,7 +89,6 @@ def test_role_permissions(
 ):
 
     role_param = project_with_members_response[1]
-    print(project_created_from_api.project_name)
     assert project_with_members_response[0].status_code == 200
     for i, member in enumerate(user_batch_created_with_api):
         # test view project
diff --git a/server/api/tests/test_jwt_auth.py b/server/api/tests/test_jwt_auth.py
index 5dc6b7a59ec1c97eaaa7ff8a538c72484f97eade..62a452e6f836c4d4da729fe4b25fd42361a80908 100644
--- a/server/api/tests/test_jwt_auth.py
+++ b/server/api/tests/test_jwt_auth.py
@@ -26,11 +26,13 @@ def test_auth_superuser(superuser, api_client, status_code_expected, user_passwo
 
 @pytest.mark.django_db
 @pytest.mark.parametrize("status_code_expected", [200])
-def test_auth_normaluser(normaluser, api_client, status_code_expected, user_password):
+def test_auth_normaluser(
+    user_created_with_api, api_client, status_code_expected, user_password
+):
     url = reverse("token_obtain_pair")
     resp = api_client.post(
         url,
-        {"username": normaluser.username, "password": user_password},
+        {"username": user_created_with_api.username, "password": user_password},
         format="json",
     )
     assert resp.status_code == status_code_expected
@@ -57,15 +59,17 @@ def test_superuser_auth(api_client, superuser, status_code_expected, user_passwo
 
 @pytest.mark.django_db
 @pytest.mark.parametrize("status_code_expected", [200])
-def test_normaluser_auth(api_client, normaluser, status_code_expected, user_password):
-    auth_client = authenticate(api_client, normaluser, user_password)
+def test_normaluser_auth(
+    api_client, user_created_with_api, status_code_expected, user_password
+):
+    auth_client = authenticate(api_client, user_created_with_api, user_password)
     # test current-user
     response = auth_client.get("/api/current-user/")
     assert response.status_code == status_code_expected
-    assert response.data["id"] == normaluser.id
+    assert response.data["id"] == user_created_with_api.id
 
     # test same user
-    response = auth_client.get(f"/api/users/{normaluser.id}/")
+    response = auth_client.get(f"/api/users/{user_created_with_api.id}/")
     assert response.status_code == status_code_expected
-    assert response.data["username"] == normaluser.username
+    assert response.data["username"] == user_created_with_api.username
 
diff --git a/server/api/tests/test_phenotype_category.py b/server/api/tests/test_phenotype_category.py
new file mode 100644
index 0000000000000000000000000000000000000000..0ead3e82b68b8946ac8f857465323894247dfc3b
--- /dev/null
+++ b/server/api/tests/test_phenotype_category.py
@@ -0,0 +1,94 @@
+import pytest
+from .utils import authenticate
+import json
+from pytest_factoryboy import register
+from api.factories import PhenotypeCategoryFactory
+
+register(PhenotypeCategoryFactory)
+
+
+@pytest.mark.django_db
+def test_manager_permissions(
+    api_client,
+    api_client_with_superuser_credential,
+    role_users_created_with_api,
+    user_password,
+    phenotype_category_factory,
+):
+
+    for role_user in role_users_created_with_api:
+        with open("api/fixtures/role-permissions.json", "r") as f:
+            role_permissions = json.loads(f.read())
+            fixture_permissions = set(
+                [
+                    perm["fields"]["permission"][0].replace("_phenotypecategory", "")
+                    for perm in role_permissions
+                    if perm["fields"]["role"][0] == role_user["role"]
+                    and perm["fields"]["permission"][2] == "phenotypecategory"
+                ]
+            )
+
+            phenotype_category = phenotype_category_factory.build()
+
+            # get phenotype category permissions
+            client = authenticate(api_client, role_user["user"], user_password)
+            response = client.get("/api/phenotype-categories/permissions/")
+            response_permissions = set(response.data)
+            assert response_permissions == fixture_permissions
+            phenotype_category_db = None
+            if "add" in response_permissions:
+                response = client.post(
+                    "/api/phenotype-categories/",
+                    data={
+                        "name": phenotype_category.name,
+                        "description": phenotype_category.description,
+                        "datatype": phenotype_category.datatype,
+                        "dataclass": phenotype_category.dataclass,
+                        "nature": phenotype_category.nature,
+                        "location": phenotype_category.location,
+                    },
+                )
+                assert response.status_code == 201
+                phenotype_category_db = response.data
+            else:
+                # create a phenotype category anyway
+                response = api_client_with_superuser_credential.post(
+                    "/api/phenotype-categories/",
+                    data={
+                        "name": phenotype_category.name,
+                        "description": phenotype_category.description,
+                        "datatype": phenotype_category.datatype,
+                        "dataclass": phenotype_category.dataclass,
+                        "nature": phenotype_category.nature,
+                        "location": phenotype_category.location,
+                    },
+                )
+                assert response.status_code == 201
+                phenotype_category_db = response.data
+
+            if "change" in response_permissions:
+                response = client.put(
+                    f"/api/phenotype-categories/{phenotype_category_db['id']}/",
+                    data={
+                        "name": phenotype_category.name,
+                        "description": "new description",
+                        "datatype": phenotype_category.datatype,
+                        "dataclass": phenotype_category.dataclass,
+                        "nature": phenotype_category.nature,
+                        "location": phenotype_category.location,
+                    },
+                )
+                assert response.status_code == 200
+
+            if "view" in response_permissions:
+                response = client.get(
+                    f"/api/phenotype-categories/{phenotype_category_db['id']}/"
+                )
+                assert response.status_code == 200
+
+            if "delete" in response_permissions:
+                response = client.delete(
+                    f"/api/phenotype-categories/{phenotype_category_db['id']}/"
+                )
+                assert response.status_code == 204
+
diff --git a/server/api/tests/test_tasks.py b/server/api/tests/test_tasks.py
index ee5f8007f67474027002748b849e0eb3ace2b196..4697b33b09ab155928085c84900181bdf1097022 100644
--- a/server/api/tests/test_tasks.py
+++ b/server/api/tests/test_tasks.py
@@ -37,14 +37,26 @@ def mock_show_dataset(mocker):
     yield mocker
 
 
+@pytest.fixture
+def mock_rmtree(mocker):
+    def _mock_rmtree(*args, **kwargs):
+        print("mocking rmtree")
+
+    mocker.patch("api.tasks.shutil.rmtree", _mock_rmtree)
+    yield mocker
+
+
 def test_celery_raw_fixtures(
     mock_show_job,
     mock_upload_file,
     mock_show_dataset,
+    mock_rmtree,
     upload_data_id
     # celery_app,
     # celery_session_worker,
 ):
-    res = upload_file_to_galaxy("/toto", "history_id", "auto")
-    assert res == upload_data_id
+    analysis_id = 1
+    history_id = "history_id"
+    res = upload_file_to_galaxy((analysis_id, history_id), "/fake-folder", "auto")
+    assert res[2] == upload_data_id
 
diff --git a/server/api/tests/test_user.py b/server/api/tests/test_user.py
index d5e3c548a54beea005679ca2d9468f827247ad50..fb207917e14b1911e9e220ffca3ccdc0e6e3e1ac 100644
--- a/server/api/tests/test_user.py
+++ b/server/api/tests/test_user.py
@@ -1,7 +1,4 @@
-from django.contrib import auth
 import pytest
-
-from guardian.shortcuts import get_perms
 from .utils import authenticate
 
 
@@ -10,14 +7,14 @@ from .utils import authenticate
 def test_with_superuser_client(api_client_with_superuser_credential, expected):
     response = api_client_with_superuser_credential.get("/api/current-user/")
     assert response.status_code == expected
-    assert response.data == {"id": 2}
+    assert response.data["id"] == 2
 
 
 @pytest.mark.django_db
 def test_with_client(api_client_with_credentials, user_logged):
     response = api_client_with_credentials.get("/api/current-user/")
     assert response.status_code == 200
-    assert response.data == {"id": user_logged.id}
+    assert response.data["id"] == user_logged.id
 
 
 @pytest.mark.django_db
@@ -28,8 +25,8 @@ def test_user_permissions(
     for user in user_batch_created_with_api:
         # authenticate as a user
         client = authenticate(api_client, user, user_password)
+        # other_users = (u for u in user_batch_created_with_api if u.id != user.id)
         other_users = (u for u in user_batch_created_with_api if u.id != user.id)
-
         # Can view all users
         response = client.get("/api/users/")
         assert response.status_code == 200
@@ -88,6 +85,53 @@ def test_user_permissions(
             response = client.delete(f"/api/users/{other_user.id}/")
             assert response.status_code == 403
 
+            # change password other user
+            response = client.put(
+                f"/api/users/{other_user.id}/password_change/",
+                {
+                    "old_password": user_password,
+                    "new_password": user_password,
+                    "new_password_confirmation": user_password,
+                },
+            )
+            assert response.status_code == 403
+
+        # change password
+        # client = authenticate(api_client, user, user_password)
+        new_password = "new_password"
+        response = client.put(
+            f"/api/users/{user.id}/password_change/",
+            {
+                "old_password": user_password,
+                "new_password": new_password,
+                "new_password_confirmation": new_password,
+            },
+        )
+        assert response.status_code == 200
+
+        response = client.put(
+            f"/api/users/{user.id}/password_change/",
+            {
+                "old_password": "wrong_password",
+                "new_password": user_password,
+                "new_password_confirmation": user_password,
+            },
+        )
+
+        assert response.status_code == 400
+        assert response.data["old_password"]["old_password"] is not None
+
+        response = client.put(
+            f"/api/users/{user.id}/password_change/",
+            {
+                "old_password": new_password,
+                "new_password": user_password,
+                "new_password_confirmation": user_password + "wrong",
+            },
+        )
+        assert response.status_code == 400
+        assert response.data["password"] is not None
+
 
 @pytest.mark.django_db
 def test_change_user(api_client_with_credentials, user_logged, user_password):
@@ -96,7 +140,7 @@ def test_change_user(api_client_with_credentials, user_logged, user_password):
     assert user_id == user_logged.id
     user_resp = api_client_with_credentials.get(f"/api/users/{user_id}/")
     assert user_resp.status_code == 200
-    print(user_logged.groups.all())
+    # print(user_logged.groups.all())
     assert user_logged.has_perm("api.change_user", user_logged)
 
     # Change current_user
@@ -150,4 +194,3 @@ def test_delete_user(api_client_with_credentials, user_logged):
 def test_count_users(api_client_with_credentials):
     response = api_client_with_credentials.get("/api/users/")
     assert len(response.data) == 2
-
diff --git a/server/api/urls.py b/server/api/urls.py
index 064e1daffd9f23ceae4acfa39f8893528ce9e417..4615be61216df7096529f881db398502ceebcac4 100644
--- a/server/api/urls.py
+++ b/server/api/urls.py
@@ -5,14 +5,17 @@ from django.urls import path, include
 from rest_framework_nested import routers
 from .views import (
     AnalysisViewSet,
+    ExperimentViewSet,
     FounderViewSet,
     # LodScoreViewSet,
     PeakViewSet,
+    ProjectGroupRoleViewSet,
     ProjectGroupViewSet,
     ProjectMemberViewSet,
-    VariableCategoryResolveViewSet,
+    RoleGroupViewSet,
+    PhenotypeCategoryResolveViewSet,
     # ToolsParameters,
-    tools_parameters,
+    # tools_parameters,
     UserViewSet,
     CurrentUserViewSet,
     DepartmentViewSet,
@@ -20,42 +23,50 @@ from .views import (
     ProjectViewSet,
     RoleViewSet,
     ProjectRoleViewSet,
-    ExperimentViewSet,
-    VariableCategoryViewSet,
+    ProjectExperimentViewSet,
+    PhenotypeCategoryViewSet,
     ExperimentCclineViewSet,
     CclineViewSet,
     ProjectAnalysisViewSet,
-    workflow_default_parameters,
-    workflow_tools,
+    WorkflowDefaultParameters,
+    WorkflowTools,
+    CcQtlWorkflows,
 )
 
 
 router = routers.DefaultRouter()
 router.register(r"users", UserViewSet)
-router.register(r"current-user", CurrentUserViewSet)
+router.register(r"app-roles", RoleGroupViewSet)
+router.register(r"current-user", CurrentUserViewSet, basename="current_user")
 router.register(r"roles", RoleViewSet)
 router.register(r"project-roles", ProjectRoleViewSet)
+router.register(r"project-groups", ProjectGroupRoleViewSet, basename="project_groups")
 router.register(r"departments", DepartmentViewSet)
 router.register(r"teams", TeamViewSet)
 router.register(r"cclines", CclineViewSet)
 router.register(r"founders", FounderViewSet)
 # router.register(r"tools-parameters", ToolsParameters, basename="tools-parameters")
 router.register(r"analysis", AnalysisViewSet)
+router.register(r"experiments", ExperimentViewSet)
 
+# router.register(
+#     r"cc-qtl-workflows", CcQtlWorkflows.as_view(), basename="ccqtl_workflows"
+# )
 
-router.register(r"variable-categories", VariableCategoryViewSet)
+router.register(r"phenotype-categories", PhenotypeCategoryViewSet)
 router.register(
-    r"variable-categories-resolve",
-    VariableCategoryResolveViewSet,
-    basename="variable-categories-resolve",
+    r"phenotype-categories-resolve",
+    PhenotypeCategoryResolveViewSet,
+    basename="phenotype-categories-resolve",
 )
 
+
 ############
 # Projects #
 ############
 router.register(r"projects", ProjectViewSet)
 project_router = routers.NestedSimpleRouter(router, r"projects", lookup="project")
-project_router.register(r"experiments", ExperimentViewSet, basename="experiment")
+project_router.register(r"experiments", ProjectExperimentViewSet, basename="experiment")
 project_router.register(r"analysis", ProjectAnalysisViewSet, basename="analysis")
 project_router.register(r"members", ProjectMemberViewSet, basename="projectmembers")
 project_router.register(r"groups", ProjectGroupViewSet, basename="projectgroup")
@@ -72,13 +83,19 @@ analysis_router = routers.NestedDefaultRouter(
     project_router, r"analysis", lookup="analysis"
 )
 analysis_router.register(r"peaks", PeakViewSet)
-
 urlpatterns = [
+    path("accounts/", include("django.contrib.auth.urls")),
     path("", include(router.urls)),
     path("", include(project_router.urls)),
     path("", include(experiment_router.urls)),
     path("", include(analysis_router.urls)),
-    path("tools/", tools_parameters),
-    path("workflow-default-parameters/", workflow_default_parameters),
-    path("workflow-tools/", workflow_tools),
+    path(
+        "workflow-default-parameters/<slug:wf_id>/",
+        WorkflowDefaultParameters.as_view(),
+        name="workflow-default-parameters",
+    ),
+    path(
+        "workflow-tools/<slug:wf_id>/", WorkflowTools.as_view(), name="worklow-tools",
+    ),
+    path("cc-qtl-workflows/", CcQtlWorkflows.as_view(), name="cc-qtl-workflows"),
 ]
diff --git a/server/api/views.py b/server/api/views.py
index 693ab5d7e4c0d3a282e0fb1b440ac0e86a18a3d8..9d59c97549b0fe37ee0506b4ffb648a211ac11c5 100644
--- a/server/api/views.py
+++ b/server/api/views.py
@@ -3,15 +3,14 @@
 import json
 
 # Django
-from django.core.exceptions import ObjectDoesNotExist
 from django.contrib.auth import get_user_model
 from django.contrib.auth.models import Group
 from django.http.request import QueryDict
 from django.shortcuts import get_object_or_404
 from django.http import JsonResponse
-from django.db import transaction
+from django.db import transaction, DataError
+from django.db.models import ProtectedError
 from django.db.utils import IntegrityError
-from django.conf import settings
 
 
 # Guardian
@@ -19,29 +18,48 @@ from guardian.shortcuts import assign_perm, get_perms
 import pandas as pd
 
 # DRF
-from rest_framework import viewsets, status, serializers, mixins
-from rest_framework.exceptions import NotFound
+from rest_framework import (
+    views,
+    viewsets,
+    status,
+    serializers,
+    mixins,
+    authentication,
+)
 from rest_framework.permissions import IsAuthenticated
 
+
 # from rest_framework.views import APIView
 from rest_framework.response import Response
 from rest_framework.decorators import action
 
+
+from rest_framework_simplejwt.authentication import JWTAuthentication
+
 # DRF guardian
 from rest_framework_guardian import filters
 
 from .exceptions import RessourceAlreadyExists
 
+from bioblend import ConnectionError
+from bioblend.galaxy.datasets import DatasetStateException
+
+
 # Serializers
 from .serializers import (
+    ChangePasswordSerializer,
+    ExperimentLightSerializer,
     FounderSerializer,
+    GroupSerializer,
     HaplotypeSerializer,
     LodScoreSerializer,
-    LodScoreSignificanceThresholdSerializer,
+    PeakGenesSerializer,
     PeakSerializer,
+    ProjectGroupRoleSerializer,
     ProjectGroupSerializer,
     ProjectMemberSerializer,
     ProjectRoleSerializer,
+    RoleGroupSerializer,
     SnpsAssociationSerializer,
     TopSnpsSerializer,
     UserSerializer,
@@ -52,8 +70,8 @@ from .serializers import (
     CclineSerializer,
     ExperimentCclineSerializer,
     ExperimentSerializer,
-    VariableCategorySerializer,
-    VariableSerializer,
+    PhenotypeCategorySerializer,
+    PhenotypeSerializer,
     AnalysisSerializer,
     CoefficientSerializer,
 )
@@ -64,8 +82,8 @@ from .models import (
     Founder,
     Haplotypes,
     LodScore,
-    LodScoreSignificanceThreshold,
     Peak,
+    PeakGenes,
     Project,
     ProjectRole,
     Role,
@@ -78,15 +96,15 @@ from .models import (
     Ccline,
     ExperimentCcline,
     TopSnps,
-    VariableCategory,
-    Variable,
+    PhenotypeCategory,
+    Phenotype,
     Analysis,
 )
 
-from .galaxy import get_history_status, GalaxyRunner, delete_history
-from bioblend import ConnectionError
+from .galaxy import GalaxyRunner
 
 from .tasks import (
+    load_peak_genes,
     load_refine_peaks,
     load_coefficient,
     load_haplotypes,
@@ -97,8 +115,9 @@ from .tasks import (
 )
 
 # Permissions
-from .permissions import CustomObjectPermissions
+from .permissions import CustomObjectPermissions, CustomPermissions, IsAdminOrIsSelf
 
+PERMISSION_NAMES = ["add", "change", "delete", "view"]
 
 # filters
 
@@ -111,6 +130,33 @@ from .permissions import CustomObjectPermissions
 
 
 User = get_user_model()
+runner = GalaxyRunner()
+
+
+class ErrorDataResponse:
+    def __init__(self, type, message, status):
+        self.type = type
+        self.message = message
+        self.status = status
+
+    def get_error_response(self):
+        return Response(
+            {"type": self.type, "message": self.message}, status=self.status
+        )
+
+
+galaxy_connection_error = ErrorDataResponse(
+    "galaxy",
+    f"Not able to reach {runner.galaxy_url} instance",
+    status.HTTP_503_SERVICE_UNAVAILABLE,
+)
+
+
+class AppGroupViewSet(viewsets.ModelViewSet):
+    queryset = Group.objects.exclude(projectgroup__isnull=False).exclude(
+        team__isnull=False
+    )
+    serializer_class = GroupSerializer
 
 
 class UserViewSet(viewsets.ModelViewSet):
@@ -120,11 +166,50 @@ class UserViewSet(viewsets.ModelViewSet):
 
     queryset = User.objects.exclude(username__exact="AnonymousUser")
     serializer_class = UserSerializer
+    permission_classes = [CustomPermissions]
+
     # permission_classes = [CustomObjectPermissions]
     # permission_classes = [DjangoModelPermissions]
-
+    # permission_classes = [DjangoObjectPermissions]
     # filter_backends = [filters.ObjectPermissionsFilter]
 
+    def list(self, request):
+        current_user = User.objects.get(pk=request.user.id)
+        queryset = self.get_queryset()
+        serializer = self.get_serializer(
+            queryset, many=True, context={"request": request}
+        )
+        data = serializer.data
+        for user in data:
+            member_permissions = set()
+            user_db = User.objects.get(pk=user["id"])
+            for perm in get_perms(current_user, user_db):
+                member_permissions.add(perm)
+            user["permissions"] = member_permissions
+        return Response(data)
+
+    def get_serializer_class(self):
+        if self.action == "password_change":
+            return ChangePasswordSerializer
+        return self.serializer_class
+
+    @action(
+        detail=True,
+        methods=["put"],
+        name="Change Password",
+        permission_classes=[IsAdminOrIsSelf],
+    )
+    def password_change(self, request, pk=None):
+        """Change the user's password."""
+        serializer = ChangePasswordSerializer(
+            data=request.data, context={"request": request}
+        )
+        if serializer.is_valid():
+            self.partial_update(request)
+            return Response("Password updated successfully")
+        else:
+            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
+
 
 class CurrentUserViewSet(viewsets.ViewSet):
     """
@@ -133,13 +218,14 @@ class CurrentUserViewSet(viewsets.ViewSet):
 
     http_method_names = ["get"]
     queryset = User.objects.all()
-    # serializer_class = UserSerializer
+    serializer_class = UserSerializer
     permission_classes = [CustomObjectPermissions]
     filter_backends = [filters.ObjectPermissionsFilter]
 
     def list(self, request, format=None):
         user = User.objects.get(pk=request.user.id)
-        return Response({"id": user.id})
+        serializer = UserSerializer(user)
+        return Response(serializer.data)
 
 
 class ProjectViewSet(viewsets.ModelViewSet):
@@ -152,6 +238,11 @@ class ProjectViewSet(viewsets.ModelViewSet):
     permission_classes = [CustomObjectPermissions]
     filter_backends = [filters.ObjectPermissionsFilter]
 
+    @action(detail=False)
+    def count(self, request):
+        queryset = self.filter_queryset(self.get_queryset())
+        return Response({"count": queryset.count()})
+
     @action(detail=True)
     def permissions(self, request, pk=None):
         current_user = User.objects.get(pk=request.user.id)
@@ -197,9 +288,8 @@ class ProjectMemberViewSet(
             many=True,
             context={"request": request, "project_pk": int(project_pk)},
         )
-        membersWithPermissions = []
-
-        for member in serializer.data:
+        data = serializer.data
+        for member in data:
             member_permissions = set()
             current_user = User.objects.get(pk=member["id"])
             for perm in get_perms(current_user, Project.objects.get(pk=project_pk)):
@@ -213,8 +303,7 @@ class ProjectMemberViewSet(
                     member_permissions.add(perm)
 
             member["permissions"] = member_permissions
-            membersWithPermissions.append(member)
-        return Response(membersWithPermissions)
+        return Response(data)
 
     def update(self, request, *args, **kwargs):
         partial = kwargs.pop("partial", False)
@@ -243,25 +332,45 @@ class FounderViewSet(viewsets.ReadOnlyModelViewSet):
 
 
 class ExperimentViewSet(viewsets.ModelViewSet):
+    serializer_class = ExperimentLightSerializer
+    queryset = Experiment.objects.all()
+    permission_classes = [CustomObjectPermissions]
+    filter_backends = [filters.ObjectPermissionsFilter]
+
+    def list(self, request, *args, **kwargs):
+
+        queryset = self.filter_queryset(self.get_queryset())
+        page = self.paginate_queryset(queryset)
+        if page is not None:
+            serializer = self.get_serializer(page, many=True)
+            return self.get_paginated_response(serializer.data)
+        serializer = self.get_serializer(queryset, many=True)
+        return Response(serializer.data)
+
+    @action(detail=False)
+    def count(self, request):
+        queryset = self.filter_queryset(self.get_queryset())
+        return Response({"count": queryset.count()})
+
+
+class ProjectExperimentViewSet(viewsets.ModelViewSet):
     """
     API endpoint that allows experiment to be viewed or edited.
     """
 
     serializer_class = ExperimentSerializer
-    # queryset = Experiment.objects.all()
+    queryset = Experiment.objects.all()
     permission_classes = [CustomObjectPermissions]
     filter_backends = [filters.ObjectPermissionsFilter]
 
-    def get_queryset(self):
-        return Experiment.objects.filter(project=self.kwargs["project_pk"])
-
-    def addExperimentVariable(self, experiment_cc_line, metadata, value):
-        variable_category = VariableCategory.objects.get(id=metadata.get("id"))
-        Variable.objects.create(
-            category=variable_category,
+    def addExperimentPhenotype(self, experiment, experiment_cc_line, metadata, value):
+        phenotype_category = PhenotypeCategory.objects.get(id=metadata.get("id"))
+        Phenotype.objects.create(
+            category=phenotype_category,
             experiment_cc_line=experiment_cc_line,
             value=value,
         )
+        experiment.phenotype_categories.add(phenotype_category)
 
     def create(self, request, *args, **kwargs):
         raw_experiment_metadata = request.data.pop("experiment-metadata")
@@ -274,30 +383,34 @@ class ExperimentViewSet(viewsets.ModelViewSet):
         column_exp_metadata = {md["colIndex"]: md for md in experiment_metadata}
         serializer = self.get_serializer(data=request.data)
         serializer.is_valid(raise_exception=True)
-        self.perform_create(serializer)
+
         experiment_df = pd.read_csv(up_file[0])
-        variable_index_start = 4
-        variable_columns = experiment_df.columns[variable_index_start:]
+        phenotype_index_start = 4
+        phenotype_columns = experiment_df.columns[phenotype_index_start:]
         try:
             with transaction.atomic():
+                self.perform_create(serializer)
                 experiment = serializer.instance
                 for _, row in experiment_df.iterrows():
-                    cc_line_m = Ccline.objects.get(id_cc=row["Line_M"])
-                    cc_line_f = Ccline.objects.get(id_cc=row["Line_F"])
+                    cc_line_m = Ccline.objects.get(id_cc=row["Mother_Line"])
+                    cc_line_f = Ccline.objects.get(id_cc=row["Father_Line"])
                     experiment_cc_line = ExperimentCcline.objects.create(
                         experiment=experiment,
-                        cc_line_id=int(row["CC_ID"]),
+                        cc_line_id=row["Individual_ID"],
                         cc_line_m=cc_line_m,
                         cc_line_f=cc_line_f,
                         sex=row["Sex"],
                     )
 
-                    for idx, variable_col in enumerate(variable_columns):
+                    for idx, phenotype_col in enumerate(phenotype_columns):
                         column_metadata = column_exp_metadata[
-                            idx + variable_index_start
+                            idx + phenotype_index_start
                         ]
-                        self.addExperimentVariable(
-                            experiment_cc_line, column_metadata, row[variable_col],
+                        self.addExperimentPhenotype(
+                            experiment,
+                            experiment_cc_line,
+                            column_metadata,
+                            row[phenotype_col],
                         )
 
                 project_roles = ProjectRole.objects.all()
@@ -313,45 +426,44 @@ class ExperimentViewSet(viewsets.ModelViewSet):
                         assign_perm(perm, project_group, experiment)
         except Ccline.DoesNotExist:
             serializer.instance.delete()
-            raise serializers.ValidationError(f"Ccline does not exist.")
-        except IntegrityError:
-            raise RessourceAlreadyExists()
-        except VariableCategory.DoesNotExist:
+            raise serializers.ValidationError("Ccline does not exist.")
+        except PhenotypeCategory.DoesNotExist:
             serializer.instance.delete()
-            raise serializers.ValidationError(f"Variable category does not exist.")
+            raise serializers.ValidationError("Phenotype category does not exist.")
+        except IntegrityError as e:
+            # if "experiement_cc_line_unique" in e:
+            #     raise serializers.ValidationError(
+            #         "Duplicate ccline_id in the experiment file"
+            #     )
+            # else if
+            raise serializers.ValidationError(e)
+        except DataError as e:
+            raise serializers.ValidationError(e)
         headers = self.get_success_headers(serializer.data)
         return Response(
             serializer.data, status=status.HTTP_201_CREATED, headers=headers
         )
 
-    def get_object(self):
-        obj = get_object_or_404(
-            self.get_queryset(), pk=self.kwargs["pk"], project=self.kwargs["project_pk"]
-        )
-        self.check_object_permissions(self.request, obj)
-        return obj
+    # def get_object(self):
+    #     obj = get_object_or_404(
+    #         self.get_queryset(), pk=self.kwargs["pk"], project=self.kwargs["project_pk"]
+    #     )
+    #     self.check_object_permissions(self.request, obj)
+    #     return obj
 
     def list(self, request, project_pk=None):
 
-        queryset = Experiment.objects.filter(
-            project=project_pk,
-            # project__projectgroup__project_role__permissions__content_type__model="experiment",
-            # project__projectgroup__group
-        )
-        # perm_queryset = get_objects_for_user(request.user, "api.view_experiment")
-        # queryset = perm_queryset.filter(project=project_pk)
+        queryset = Experiment.objects.filter(project=project_pk)
         serializer = ExperimentSerializer(
             queryset, many=True, context={"request": request}
         )
         return Response(serializer.data)
 
-    # def retrieve(self, request, pk=None, project_pk=None):
-    #     queryset = Experiment.objects.filter(pk=pk, project=project_pk)
-    #     experiment = get_object_or_404(queryset, pk=pk)
-    #     print(f"in retrieve exp : {experiment}")
-    #     serializer = ExperimentSerializer(experiment, context={"request": request})
-    #     # print(serializer.data)
-    #     return Response(serializer.data)
+    def retrieve(self, request, pk=None, project_pk=None):
+        queryset = Experiment.objects.filter(pk=pk, project=project_pk)
+        experiment = get_object_or_404(queryset, pk=pk)
+        serializer = ExperimentSerializer(experiment, context={"request": request})
+        return Response(serializer.data)
 
     @action(detail=True)
     def permissions(self, request, pk=None, project_pk=None):
@@ -362,12 +474,12 @@ class ExperimentViewSet(viewsets.ModelViewSet):
         return Response(permissions)
 
     @action(detail=True)
-    def variables(self, request, pk=None, project_pk=None):
+    def phenotypes(self, request, pk=None, project_pk=None):
         return Response(self.get_object().get_experiment_data())
 
     @action(detail=True)
-    def variable_types(self, request, pk=None, project_pk=None):
-        return Response(self.get_object().get_experiment_variable_types())
+    def phenotype_types(self, request, pk=None, project_pk=None):
+        return Response(self.get_object().get_experiment_phenotype_types())
 
 
 class ExperimentCclineViewSet(viewsets.ModelViewSet):
@@ -394,48 +506,71 @@ class ExperimentCclineViewSet(viewsets.ModelViewSet):
         return Response(serializer.data)
 
 
-class VariableCategoryResolveViewSet(
+class PhenotypeCategoryResolveViewSet(
     mixins.CreateModelMixin,
     # mixins.ListModelMixin,
     # mixins.RetrieveModelMixin,
     viewsets.GenericViewSet,
 ):
-    queryset = VariableCategory.objects.all()
-    serializer_class = VariableCategorySerializer
+    queryset = PhenotypeCategory.objects.all()
+    serializer_class = PhenotypeCategorySerializer
     permission_classes = [IsAuthenticated]
 
     def create(self, request):
         response = []
-        for variableCategory in request.data:
+        for phenotypeCategory in request.data:
             try:
                 var_cat_qs = self.get_queryset().get(
-                    name=variableCategory["name"],
-                    nature=variableCategory["nature"],
-                    location=variableCategory["location"],
-                    datatype=variableCategory["datatype"],
-                    dataclass=variableCategory["dataclass"],
+                    name=phenotypeCategory["name"],
+                    # nature=phenotypeCategory["nature"],
+                    # location=phenotypeCategory["location"],
+                    # datatype=phenotypeCategory["datatype"],
+                    # dataclass=phenotypeCategory["dataclass"],
                 )
                 serializer = self.get_serializer(var_cat_qs)
                 responseData = serializer.data
-                responseData["colid"] = variableCategory["colid"]
+                responseData["colid"] = phenotypeCategory["colid"]
                 response.append(responseData)
 
             except Exception:
-                response.append({"colid": variableCategory["colid"]})
+                response.append({"colid": phenotypeCategory["colid"]})
         return Response(response)
 
 
-class VariableCategoryViewSet(viewsets.ModelViewSet):
-    queryset = VariableCategory.objects.all()
-    serializer_class = VariableCategorySerializer
+class PhenotypeCategoryViewSet(viewsets.ModelViewSet):
+    queryset = PhenotypeCategory.objects.all()
+    serializer_class = PhenotypeCategorySerializer
+    permission_classes = [CustomPermissions]
 
+    def perform_destroy(self, instance):
+        try:
+            instance.delete()
+        except ProtectedError as e:
+            print(e)
+            raise serializers.ValidationError(
+                f"The phenotype category {instance.name} describes uploaded experiment"
+                + " phenotype. You cannot delete it !!"
+            )
 
-class VariableViewSet(viewsets.ModelViewSet):
-    queryset = Variable.objects.all()
-    serializer_class = VariableSerializer
+    @action(detail=False)
+    def permissions(self, request, pk=None):
+        current_user = request.user
+        permissions_set = set(
+            [
+                perm
+                for perm in PERMISSION_NAMES
+                if current_user.has_perm(f"api.{perm}_phenotypecategory")
+            ]
+        )
+        return Response(permissions_set)
+
+
+class PhenotypeViewSet(viewsets.ModelViewSet):
+    queryset = Phenotype.objects.all()
+    serializer_class = PhenotypeSerializer
 
     def get_queryset(self):
-        return Variable.objects.filter(
+        return Phenotype.objects.filter(
             project=self.kwargs["project_pk"], experiment=self.kwargs["experiment_pk"]
         )
 
@@ -459,6 +594,13 @@ class ProjectRoleViewSet(viewsets.ModelViewSet):
     serializer_class = ProjectRoleSerializer
 
 
+class ProjectGroupRoleViewSet(viewsets.ModelViewSet):
+    queryset = ProjectGroup.objects.all()
+    serializer_class = ProjectGroupRoleSerializer
+    permission_classes = [CustomObjectPermissions]
+    filter_backends = [filters.ObjectPermissionsFilter]
+
+
 class ProjectGroupViewSet(viewsets.ModelViewSet):
     # queryset = ProjectGroup.objects.all()
     serializer_class = ProjectGroupSerializer
@@ -536,12 +678,9 @@ class RoleViewSet(viewsets.ReadOnlyModelViewSet):
     # filter_backends = [filters.ObjectPermissionsFilter]
 
 
-def update_rolegroup_permissions():
-    for rolegroup in RoleGroup.objects.all():
-        permissions = rolegroup.role.permissions.all()
-        rolegroup.permissions.clear()
-        for perm in permissions:
-            rolegroup.permissions.add(perm)
+class RoleGroupViewSet(viewsets.ModelViewSet):
+    queryset = RoleGroup.objects.all()
+    serializer_class = RoleGroupSerializer
 
 
 class PeakViewSet(viewsets.ReadOnlyModelViewSet):
@@ -551,20 +690,28 @@ class PeakViewSet(viewsets.ReadOnlyModelViewSet):
     filter_backends = [filters.ObjectPermissionsFilter]
 
     def list(self, request, project_pk=None, analysis_pk=None):
-        queryset = Peak.objects.filter(
-            analysis__project=project_pk, analysis=analysis_pk
-        )
-
+        queryset = self.peaks_per_analysis_queryset(project_pk, analysis_pk)
         if queryset.count() == 0:
+            # Empty queryset,
+            # try to load dataset from Galaxy
             analysis_db = Analysis.objects.get(id=analysis_pk)
-            load_refine_peaks.apply_async(
-                (analysis_db.name, analysis_db.galaxy_history_id)
-            ).get()
-            queryset = Peak.objects.filter(
-                analysis__project=project_pk, analysis=analysis_pk
-            )
-        serializer = PeakSerializer(queryset, many=True, context={"request": request})
-        return Response(serializer.data)
+            try:
+                load_refine_peaks.apply_async(
+                    args=[(analysis_pk, analysis_db.galaxy_history_id, None)]
+                ).get()
+            except ConnectionError:
+                return galaxy_connection_error.get_error_response()
+            except DatasetStateException as e:
+                return Response(str(e), status=status.HTTP_404_NOT_FOUND)
+            except Exception as e:
+                return Response(str(e), status=status.HTTP_400_BAD_REQUEST)
+            else:
+                if queryset.count() == 0:
+                    return Response("No peak found", status=status.HTTP_404_NOT_FOUND)
+                else:
+                    # queryset = self.peaks_per_analysis_queryset(project_pk, analysis_pk)
+                    return self.get_serialized_response(queryset, request)
+        return self.get_serialized_response(queryset, request)
 
     def retrieve(self, request, pk=None, analysis_pk=None, project_pk=None):
         queryset = Peak.objects.filter(
@@ -574,6 +721,13 @@ class PeakViewSet(viewsets.ReadOnlyModelViewSet):
         serializer = PeakSerializer(peak, context={"request": request})
         return Response(serializer.data)
 
+    def get_serialized_response(self, queryset, request):
+        serializer = PeakSerializer(queryset, many=True, context={"request": request})
+        return Response(serializer.data)
+
+    def peaks_per_analysis_queryset(self, project_pk, analysis_pk):
+        return Peak.objects.filter(analysis__project=project_pk, analysis=analysis_pk)
+
     @action(detail=True)
     def coefficients(self, request, pk=None, project_pk=None, analysis_pk=None):
 
@@ -581,13 +735,27 @@ class PeakViewSet(viewsets.ReadOnlyModelViewSet):
 
         if queryset.count() == 0:
             analysis_db = Analysis.objects.get(id=analysis_pk)
-            load_coefficient.apply_async(
-                (analysis_db.name, analysis_db.galaxy_history_id)
-            ).get()
-            queryset = Coefficient.objects.filter(peak=pk)
+            ids = (analysis_pk, analysis_db.galaxy_history_id, None)
+            try:
+                load_coefficient.apply_async(args=[ids]).get()
+            except ConnectionError:
+                return galaxy_connection_error.get_error_response()
+            except DatasetStateException as e:
+                return Response(str(e), status=status.HTTP_404_NOT_FOUND)
+            except Exception as e:
+                return Response(str(e), status=status.HTTP_400_BAD_REQUEST)
+            else:
+                if queryset.count() == 0:
+                    return Response(
+                        "No coefficient found", status=status.HTTP_404_NOT_FOUND
+                    )
+                # else:
+                #     # queryset = Coefficient.objects.filter(peak=pk)
+                #     serializer = CoefficientSerializer(queryset.first())
+                #     return Response(serializer.data)
 
-        coefficients = CoefficientSerializer(queryset.first())
-        return Response(coefficients.data)
+        serializer = CoefficientSerializer(queryset.first())
+        return Response(serializer.data)
 
     @action(detail=True)
     def snps_association(self, request, pk=None, project_pk=None, analysis_pk=None):
@@ -595,10 +763,22 @@ class PeakViewSet(viewsets.ReadOnlyModelViewSet):
         queryset = SnpsAssociation.objects.filter(peak=pk)
         if queryset.count() == 0:
             analysis_db = Analysis.objects.get(id=analysis_pk)
-            load_snps_association.apply_async(
-                (analysis_db.name, analysis_db.galaxy_history_id)
-            ).get()
-            queryset = SnpsAssociation.objects.filter(peak=pk)
+            ids = (analysis_pk, analysis_db.galaxy_history_id, None)
+            try:
+                load_snps_association.apply_async(args=[ids]).get()
+            except ConnectionError:
+                return galaxy_connection_error.get_error_response()
+            except DatasetStateException as e:
+                return Response(str(e), status=status.HTTP_404_NOT_FOUND)
+            except Exception as e:
+                return Response(str(e), status=status.HTTP_400_BAD_REQUEST)
+            else:
+                if queryset.count() == 0:
+                    return Response(
+                        "No snps association found", status=status.HTTP_404_NOT_FOUND
+                    )
+
+            # queryset = SnpsAssociation.objects.filter(peak=pk)
         snps = SnpsAssociationSerializer(queryset.first())
         return Response(snps.data)
 
@@ -608,14 +788,45 @@ class PeakViewSet(viewsets.ReadOnlyModelViewSet):
 
         if queryset.count() == 0:
             analysis_db = Analysis.objects.get(id=analysis_pk)
-            load_top_snps.apply_async(
-                (analysis_db.name, analysis_db.galaxy_history_id)
-            ).get()
-            queryset = TopSnps.objects.filter(peak=pk)
-
+            ids = (analysis_pk, analysis_db.galaxy_history_id, None)
+            try:
+                load_top_snps.apply_async(args=[ids]).get()
+            except ConnectionError:
+                return galaxy_connection_error.get_error_response()
+            except DatasetStateException as e:
+                return Response(str(e), status=status.HTTP_404_NOT_FOUND)
+            except Exception as e:
+                return Response(str(e), status=status.HTTP_400_BAD_REQUEST)
+            else:
+                if queryset.count() == 0:
+                    return Response(
+                        "No top snps found", status=status.HTTP_404_NOT_FOUND
+                    )
         snps = TopSnpsSerializer(queryset.first())
         return Response(snps.data)
 
+    @action(detail=True)
+    def genes(self, request, pk=None, project_pk=None, analysis_pk=None):
+        queryset = PeakGenes.objects.filter(peak=pk)
+        if queryset.count() == 0:
+            analysis_db = Analysis.objects.get(id=analysis_pk)
+            ids = (analysis_pk, analysis_db.galaxy_history_id, None)
+            try:
+                load_peak_genes.apply_async(args=[ids]).get()
+            except ConnectionError:
+                return galaxy_connection_error.get_error_response()
+            except DatasetStateException as e:
+                return Response(str(e), status=status.HTTP_404_NOT_FOUND)
+            except Exception as e:
+                return Response(str(e), status=status.HTTP_400_BAD_REQUEST)
+            else:
+                if queryset.count() == 0:
+                    return Response(
+                        "No genes list found for peak", status=status.HTTP_404_NOT_FOUND
+                    )
+        genes = PeakGenesSerializer(queryset.first())
+        return Response(genes.data)
+
     @action(detail=True)
     def haplotypes(self, request, pk=None, project_pk=None, analysis_pk=None):
         # load_haplotypes
@@ -623,13 +834,23 @@ class PeakViewSet(viewsets.ReadOnlyModelViewSet):
 
         if queryset.count() == 0:
             analysis_db = Analysis.objects.get(id=analysis_pk)
-            load_haplotypes.apply_async(
-                (analysis_db.name, analysis_db.galaxy_history_id)
-            ).get()
-            queryset = Haplotypes.objects.filter(peak=pk)
-
-        haplotypes = HaplotypeSerializer(queryset.first())
-        return Response(haplotypes.data)
+            ids = (analysis_pk, analysis_db.galaxy_history_id, None)
+            try:
+                load_haplotypes.apply_async(args=[ids]).get()
+            except ConnectionError:
+                return galaxy_connection_error.get_error_response()
+            except DatasetStateException as e:
+                return Response(str(e), status=status.HTTP_404_NOT_FOUND)
+            except Exception as e:
+                return Response(str(e), status=status.HTTP_400_BAD_REQUEST)
+            else:
+                if queryset.count() == 0:
+                    return Response("No peak found", status=status.HTTP_404_NOT_FOUND)
+                # else:
+                #     queryset = Haplotypes.objects.filter(peak=pk)
+
+        serializer = HaplotypeSerializer(queryset.first())
+        return Response(serializer.data)
 
 
 class LodScoreViewSet(viewsets.ModelViewSet):
@@ -669,24 +890,13 @@ class AnalysisViewSet(viewsets.ModelViewSet):
         if page is not None:
             serializer = self.get_serializer(page, many=True)
             return self.get_paginated_response(serializer.data)
-
         serializer = self.get_serializer(queryset, many=True)
-        analysis = serializer.data
-        for analyse in analysis:
-            try:
-                analyse["history_status"] = get_history_status(
-                    analyse["galaxy_history_id"]
-                )
-            except ConnectionError:
-                return Response(
-                    {
-                        "type": "galaxy",
-                        "message": "Galaxy server is not reachable",
-                        "url": settings.GALAXY_BASE_URL,
-                    },
-                    status=status.HTTP_503_SERVICE_UNAVAILABLE,
-                )
-        return Response(analysis)
+        return Response(serializer.data)
+
+    @action(detail=False)
+    def count(self, request):
+        queryset = self.filter_queryset(self.get_queryset())
+        return Response({"count": queryset.count()})
 
 
 class ProjectAnalysisViewSet(viewsets.ModelViewSet):
@@ -708,42 +918,63 @@ class ProjectAnalysisViewSet(viewsets.ModelViewSet):
         queryset = Analysis.objects.filter(pk=pk, project=project_pk)
         analysis = get_object_or_404(queryset, pk=pk)
         serializer = AnalysisSerializer(analysis, context={"request": request})
-        data = serializer.data
-        try:
-            data["history_status"] = get_history_status(analysis.galaxy_history_id)
-            return Response(data)
-        except ConnectionError:
-            return Response(
-                {
-                    "type": "galaxy",
-                    "message": "Galaxy server is not reachable",
-                    "url": settings.GALAXY_BASE_URL,
-                },
-                status=status.HTTP_503_SERVICE_UNAVAILABLE,
-            )
+        return Response(serializer.data)
 
     def destroy(self, request, *args, **kwargs):
         instance = self.get_object()
-        delete_history(instance.galaxy_history_id)
-        self.perform_destroy(instance)
-        return Response(status=status.HTTP_204_NO_CONTENT)
+        try:
+            runner.delete_history(instance.galaxy_history_id)
+            self.perform_destroy(instance)
+            return Response(status=status.HTTP_204_NO_CONTENT)
+        except ConnectionError:
+            return galaxy_connection_error.get_error_response()
 
     def perform_destroy(self, instance):
         instance.delete()
 
+    @action(detail=False)
+    def permissions(self, request, pk=None, project_pk=None):
+        current_user = request.user
+        return Response(
+            [
+                perm.split(".")[1].split("_")[0]
+                for perm in current_user.get_all_permissions()
+                if perm.endswith("analysis")
+            ]
+        )
+
     @action(detail=True)
     def lodscores(self, request, pk=None, project_pk=None):
-        lodscores = LodScore.objects.filter(analysis=pk)
-        lodscores_count = lodscores.count()
-        if lodscores_count > 0:
-            return Response(LodScoreSerializer(lodscores.first()).data)
-        # Missing data, try to get it from galaxy
-        else:
+        # Get the lodscores
+        queryset = LodScore.objects.filter(analysis=pk)
+
+        # If no load score in databse
+        if queryset.count() == 0:
             analysis_db = Analysis.objects.get(id=pk)
-            load_lodscores_results(analysis_db.name, analysis_db.galaxy_history_id)
-            lodscores = LodScoreSerializer(LodScore.objects.filter(analysis=pk).first())
+            ids = (pk, analysis_db.galaxy_history_id, None)
+            try:
+                load_lodscores_results(ids).apply_async().get()
+            except ConnectionError:
+                return galaxy_connection_error.get_error_response()
+            except DatasetStateException as e:
+                exception_msg = str(e)
+                if "significance-threshold.csv" in exception_msg:
+                    print("No significance threshold")
+                    pass
+                else:
+                    return Response(str(e), status=status.HTTP_400_BAD_REQUEST)
+            except Exception as e:
+                return Response(str(e), status=status.HTTP_400_BAD_REQUEST)
+            else:
+                if queryset.count() == 0:
+                    return Response(
+                        "No load score found", status=status.HTTP_404_NOT_FOUND
+                    )
+                # else:
+                #     queryset = LodScore.objects.filter(analysis=pk)
 
-            return Response(lodscores.data)
+        lodscores = LodScoreSerializer(queryset.first())
+        return Response(lodscores.data)
 
     @action(detail=True)
     def haslodscores(self, request, pk=None, project_pk=None):
@@ -754,88 +985,161 @@ class ProjectAnalysisViewSet(viewsets.ModelViewSet):
         else:
             return Response({"has_lodscores": False})
 
-    @action(detail=True)
-    def significance_thresholds(self, request, pk=None, project_pk=None):
-        thresholds = LodScoreSignificanceThreshold.objects.filter(analysis=pk).order_by(
-            "significance"
-        )
-        significance_thresholds = LodScoreSignificanceThresholdSerializer(
-            thresholds, many=True
-        )
-        return Response(significance_thresholds.data)
-
     @action(detail=True)
     def download_qtl2_data(self, request, pk=None, project_pk=None):
-        analysis = Analysis.objects.get(id=pk)
+        queryset = Analysis.objects.get(id=pk)
         # download_formatted_qtl2_data()
-        result = download_formatted_qtl2_data.apply_async((analysis.galaxy_history_id,))
-        return Response(
-            {"archive_name": result.get(), "project_id": project_pk, "analysis_id": pk}
-        )
+        try:
+            result = download_formatted_qtl2_data.apply_async(
+                args=[queryset.galaxy_history_id]
+            ).get()
+        except ConnectionError:
+            return galaxy_connection_error.get_error_response()
+        except DatasetStateException as e:
+            return Response(str(e), status=status.HTTP_404_NOT_FOUND)
+        except Exception as e:
+            return Response(str(e), status=status.HTTP_400_BAD_REQUEST)
+        else:
+            return Response(
+                {"archive_name": result, "project_id": project_pk, "analysis_id": pk}
+            )
 
     @action(detail=True)
     def workflow_invocation_parameters(self, request, pk=None, project_pk=None):
-        return Response(self.get_object().get_workflow_invocation())
+        if self.get_object().galaxy_workflow_invocation_id:
+            try:
+                wf_invocation = self.get_object().get_workflow_invocation()
+                wf_invocation["steps"].sort(key=lambda step: step["step_id"])
+                return Response(wf_invocation)
+            except ConnectionError:
+                return galaxy_connection_error.get_error_response()
+        else:
+            return Response(None)
 
     @action(detail=True)
-    def workflow_job_params(self, request, pk=None, project_pk=None):
-        return Response(self.get_object().get_workflow_job_params())
-
-
-def tools_parameters(request):
-    runner = GalaxyRunner()
-    gi = runner.galaxy_instance
-    wf = gi.workflows.get_workflows(name="cc-qtl-wf")[0]
-    wf_invocation = gi.workflows.get_invocations(wf["id"])[0]
-    invocation_id = wf_invocation["id"]
-    invocation_details = gi.workflows.show_invocation(wf["id"], invocation_id)
-    invocation_step = gi.workflows.show_invocation_step(
-        wf["id"], invocation_id, invocation_details["steps"][4]["id"]
-    )
-    job = gi.jobs.show_job(invocation_step["job_id"])
-    return JsonResponse(job, safe=False)
+    def workflow_job_parameters(self, request, pk=None, project_pk=None):
+        return Response(self.get_object().get_workflow_job_parameters())
+
+
+# class ToolsParameters(views.APIView):
+#     authentication_classes = [JWTAuthentication, authentication.SessionAuthentication]
+#     permission_classes = [IsAuthenticated]
+
+#     def get(self, request, *args, **kwargs):
+#         wf_id = kwargs["wf_id"]
+#         runner = GalaxyRunner()
+#         gi = runner.galaxy_instance
+#         try:
+#             wf = gi.workflows.show_workflow(wf_id)
+#             wf_invocation = gi.workflows.get_invocations(wf["id"])[0]
+#             invocation_id = wf_invocation["id"]
+#             invocation_details = gi.workflows.show_invocation(wf["id"], invocation_id)
+#             invocation_step = gi.workflows.show_invocation_step(
+#                 wf["id"], invocation_id, invocation_details["steps"][4]["id"]
+#             )
+#             job = gi.jobs.show_job(invocation_step["job_id"])
+#             return Response(job)
+#         except ConnectionError as e:
+#             return Response(
+#                 status=status.HTTP_400_BAD_REQUEST, data=json.loads(e.body)["err_msg"]
+#             )
+
+
+# def tools_parameters(request):
+#     runner = GalaxyRunner()
+#     gi = runner.galaxy_instance
+#     wf = gi.workflows.get_workflows(name="cc-qtl-wf")[0]
+#     wf_invocation = gi.workflows.get_invocations(wf["id"])[0]
+#     invocation_id = wf_invocation["id"]
+#     invocation_details = gi.workflows.show_invocation(wf["id"], invocation_id)
+#     invocation_step = gi.workflows.show_invocation_step(
+#         wf["id"], invocation_id, invocation_details["steps"][4]["id"]
+#     )
+#     job = gi.jobs.show_job(invocation_step["job_id"])
+#     return JsonResponse(job, safe=False)
+
+
+class WorkflowTools(views.APIView):
+    authentication_classes = [JWTAuthentication, authentication.SessionAuthentication]
+    permission_classes = [IsAuthenticated]
 
+    def get(self, request, *args, **kwargs):
+        wf_id = kwargs["wf_id"]
+        # runner = GalaxyRunner()
+        gi = runner.galaxy_instance
 
-def workflow_tools(request):
-    runner = GalaxyRunner()
-    gi = runner.galaxy_instance
+        # TODO worflow_id should be a parameter
 
-    # TODO worflow_id should be a parameter
+        # workflow_id = request["workflow_id"]
+        try:
+            wf_with_details = gi.workflows.show_workflow(wf_id)
+            wf_step_tool_ids = [
+                (step_id, step["tool_id"])
+                for step_id, step in wf_with_details["steps"].items()
+            ]
+            return Response(dict(get_job_params(wf_step_tool_ids, gi)))
+        except ConnectionError:
+            return galaxy_connection_error.get_error_response()
 
-    # workflow_id = request["workflow_id"]
-    wf = gi.workflows.get_workflows(name="cc-qtl-wf")[0]
-    wf_with_details = gi.workflows.show_workflow(wf["id"])
-    wf_step_tool_ids = [
-        (step_id, step["tool_id"]) for step_id, step in wf_with_details["steps"].items()
-    ]
-    return JsonResponse(dict(get_job_params(wf_step_tool_ids, gi)))
 
+class WorkflowDefaultParameters(views.APIView):
+    authentication_classes = [JWTAuthentication, authentication.SessionAuthentication]
+    permission_classes = [IsAuthenticated]
 
-def workflow_default_parameters(request):
-    runner = GalaxyRunner()
-    gi = runner.galaxy_instance
-    wf = gi.workflows.get_workflows(name="cc-qtl-wf")[0]
-    wf_id = wf["id"]
-    wf = gi.workflows.show_workflow(wf_id)
-
-    wf_steps_inputs = dict(
-        [
-            (
-                step_id,
-                dict(
-                    [
-                        (input_id, input_val)
-                        for input_id, input_val in step["tool_inputs"].items()
-                        if input_val is not None and type(input_val) is not dict
-                    ]
-                ),
+    def get(self, request, *args, **kwargs):
+        wf_id = kwargs["wf_id"]
+        # runner = GalaxyRunner()
+        gi = runner.galaxy_instance
+        try:
+            wf = gi.workflows.show_workflow(wf_id)
+            wf_steps_inputs = dict(
+                [
+                    (
+                        step_id,
+                        dict(
+                            [
+                                (input_id, input_val)
+                                for input_id, input_val in step["tool_inputs"].items()
+                                if input_val is not None and type(input_val) is not dict
+                            ]
+                        ),
+                    )
+                    for step_id, step in wf["steps"].items()
+                    if step_id != "0"
+                ]
             )
-            for step_id, step in wf["steps"].items()
-            if step_id != "0"
-        ]
-    )
+            return Response(wf_steps_inputs)
+        except ConnectionError:
+            return galaxy_connection_error.get_error_response()
 
-    return JsonResponse(wf_steps_inputs)
+
+def workflow_default_parameters(request):
+    # runner = GalaxyRunner()
+    try:
+        gi = runner.galaxy_instance
+        wf = gi.workflows.get_workflows(name="cc-qtl-wf")[0]
+        wf_id = wf["id"]
+        wf = gi.workflows.show_workflow(wf_id)
+
+        wf_steps_inputs = dict(
+            [
+                (
+                    step_id,
+                    dict(
+                        [
+                            (input_id, input_val)
+                            for input_id, input_val in step["tool_inputs"].items()
+                            if input_val is not None and type(input_val) is not dict
+                        ]
+                    ),
+                )
+                for step_id, step in wf["steps"].items()
+                if step_id != "0"
+            ]
+        )
+        return JsonResponse(wf_steps_inputs)
+    except ConnectionError:
+        return galaxy_connection_error.get_error_response()
 
 
 def get_job_params(job_ids, gi):
@@ -846,3 +1150,25 @@ def get_job_params(job_ids, gi):
                 gi.tools.show_tool(job_id, io_details=True),
             )
 
+
+class CcQtlWorkflows(views.APIView):
+
+    authentication_classes = [JWTAuthentication, authentication.SessionAuthentication]
+    permission_classes = [IsAuthenticated]
+
+    def get(self, request, *args, **kwargs):
+        # runner = GalaxyRunner()
+        gi = runner.galaxy_instance
+        try:
+            workflows = [
+                wf for wf in gi.workflows.get_workflows() if wf["name"] == "cc-qtl-wf"
+            ]
+            for w in workflows:
+                import pprint
+
+                pprint.pprint(w)
+                w["details"] = gi.workflows.show_workflow(w["id"])
+            return Response(workflows)
+        except ConnectionError:
+            return galaxy_connection_error.get_error_response()
+
diff --git a/server/poetry.lock b/server/poetry.lock
index 24ee431513cb87a5f8cd79ac349ec2a66c7dffee..d594838d134d3dcb2d33cb1ec866c3f28d53a041 100644
--- a/server/poetry.lock
+++ b/server/poetry.lock
@@ -1,6 +1,6 @@
 [[package]]
 name = "amqp"
-version = "5.0.1"
+version = "5.0.6"
 description = "Low-level AMQP client for Python (fork of amqplib)."
 category = "main"
 optional = false
@@ -11,7 +11,7 @@ vine = "5.0.0"
 
 [[package]]
 name = "appdirs"
-version = "1.4.3"
+version = "1.4.4"
 description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
 category = "dev"
 optional = false
@@ -19,27 +19,26 @@ python-versions = "*"
 
 [[package]]
 name = "asgiref"
-version = "3.3.0"
+version = "3.4.1"
 description = "ASGI specs, helper code, and adapters"
 category = "main"
 optional = false
-python-versions = ">=3.5"
+python-versions = ">=3.6"
 
 [package.extras]
-tests = ["pytest", "pytest-asyncio"]
+tests = ["pytest", "pytest-asyncio", "mypy (>=0.800)"]
 
 [[package]]
 name = "astroid"
-version = "2.4.1"
+version = "2.7.3"
 description = "An abstract syntax tree for Python with inference support."
 category = "dev"
 optional = false
-python-versions = ">=3.5"
+python-versions = "~=3.6"
 
 [package.dependencies]
-lazy-object-proxy = ">=1.4.0,<1.5.0"
-six = ">=1.12,<2.0"
-wrapt = ">=1.11,<2.0"
+lazy-object-proxy = ">=1.4.0"
+wrapt = ">=1.11,<1.13"
 
 [[package]]
 name = "atomicwrites"
@@ -51,21 +50,21 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
 
 [[package]]
 name = "attrs"
-version = "19.3.0"
+version = "21.2.0"
 description = "Classes Without Boilerplate"
 category = "dev"
 optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
 
 [package.extras]
-azure-pipelines = ["coverage", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface", "pytest-azurepipelines"]
-dev = ["coverage", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface", "sphinx", "pre-commit"]
-docs = ["sphinx", "zope.interface"]
-tests = ["coverage", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface"]
+dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "furo", "sphinx", "sphinx-notfound-page", "pre-commit"]
+docs = ["furo", "sphinx", "zope.interface", "sphinx-notfound-page"]
+tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface"]
+tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins"]
 
 [[package]]
 name = "billiard"
-version = "3.6.3.0"
+version = "3.6.4.0"
 description = "Python multiprocessing fork with improvements and bugfixes"
 category = "main"
 optional = false
@@ -73,11 +72,11 @@ python-versions = "*"
 
 [[package]]
 name = "bioblend"
-version = "0.14.0"
-description = "CloudMan and Galaxy API library"
+version = "0.16.0"
+description = "Galaxy and CloudMan API library"
 category = "main"
 optional = false
-python-versions = ">=3.5"
+python-versions = ">=3.6"
 
 [package.dependencies]
 boto = ">=2.9.7"
@@ -118,28 +117,29 @@ python-versions = "*"
 
 [[package]]
 name = "celery"
-version = "5.0.2"
+version = "5.1.2"
 description = "Distributed Task Queue."
 category = "main"
 optional = false
 python-versions = ">=3.6,"
 
 [package.dependencies]
-billiard = ">=3.6.3.0,<4.0"
-click = ">=7.0"
+billiard = ">=3.6.4.0,<4.0"
+click = ">=7.0,<8.0"
 click-didyoumean = ">=0.0.3"
+click-plugins = ">=1.1.1"
 click-repl = ">=0.1.6"
-kombu = ">=5.0.0,<6.0"
+kombu = ">=5.1.0,<6.0"
 pytz = ">0.0-dev"
 vine = ">=5.0.0,<6.0"
 
 [package.extras]
 arangodb = ["pyArango (>=1.3.2)"]
 auth = ["cryptography"]
-azureblockblob = ["azure-storage (==0.36.0)", "azure-common (==1.1.5)", "azure-storage-common (==1.1.0)"]
+azureblockblob = ["azure-storage-blob (==12.6.0)"]
 brotli = ["brotli (>=1.0.0)", "brotlipy (>=0.7.0)"]
 cassandra = ["cassandra-driver (<3.21.0)"]
-consul = ["python-consul"]
+consul = ["python-consul2"]
 cosmosdbsql = ["pydocumentdb (==2.3.2)"]
 couchbase = ["couchbase (>=3.0.0)"]
 couchdb = ["pycouchdb"]
@@ -149,12 +149,12 @@ elasticsearch = ["elasticsearch"]
 eventlet = ["eventlet (>=0.26.1)"]
 gevent = ["gevent (>=1.0.0)"]
 librabbitmq = ["librabbitmq (>=1.5.0)"]
-lzma = ["backports.lzma"]
 memcache = ["pylibmc"]
 mongodb = ["pymongo[srv] (>=3.3.0)"]
 msgpack = ["msgpack"]
 pymemcache = ["python-memcached"]
 pyro = ["pyro4"]
+pytest = ["pytest-celery"]
 redis = ["redis (>=3.2.0)"]
 s3 = ["boto3 (>=1.9.125)"]
 slmq = ["softlayer-messaging (>=1.0.3)"]
@@ -168,27 +168,30 @@ zstd = ["zstandard"]
 
 [[package]]
 name = "certifi"
-version = "2020.6.20"
+version = "2021.5.30"
 description = "Python package for providing Mozilla's CA Bundle."
 category = "main"
 optional = false
 python-versions = "*"
 
 [[package]]
-name = "chardet"
-version = "3.0.4"
-description = "Universal encoding detector for Python 2 and 3"
+name = "charset-normalizer"
+version = "2.0.4"
+description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
 category = "main"
 optional = false
-python-versions = "*"
+python-versions = ">=3.5.0"
+
+[package.extras]
+unicode_backport = ["unicodedata2"]
 
 [[package]]
 name = "click"
-version = "7.0"
+version = "7.1.2"
 description = "Composable command line interface toolkit"
 category = "main"
 optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
 
 [[package]]
 name = "click-didyoumean"
@@ -201,9 +204,23 @@ python-versions = "*"
 [package.dependencies]
 click = "*"
 
+[[package]]
+name = "click-plugins"
+version = "1.1.1"
+description = "An extension module for click to enable registering CLI commands via setuptools entry-points."
+category = "main"
+optional = false
+python-versions = "*"
+
+[package.dependencies]
+click = ">=4.0"
+
+[package.extras]
+dev = ["pytest (>=3.6)", "pytest-cov", "wheel", "coveralls"]
+
 [[package]]
 name = "click-repl"
-version = "0.1.6"
+version = "0.2.0"
 description = "REPL plugin for Click"
 category = "main"
 optional = false
@@ -216,7 +233,7 @@ six = "*"
 
 [[package]]
 name = "colorama"
-version = "0.4.3"
+version = "0.4.4"
 description = "Cross-platform colored terminal text."
 category = "dev"
 optional = false
@@ -235,57 +252,57 @@ toml = ["toml"]
 
 [[package]]
 name = "django"
-version = "3.1.3"
+version = "3.2.7"
 description = "A high-level Python Web framework that encourages rapid development and clean, pragmatic design."
 category = "main"
 optional = false
 python-versions = ">=3.6"
 
 [package.dependencies]
-asgiref = ">=3.2.10,<4"
+asgiref = ">=3.3.2,<4"
 pytz = "*"
 sqlparse = ">=0.2.2"
 
 [package.extras]
-argon2 = ["argon2-cffi (>=16.1.0)"]
+argon2 = ["argon2-cffi (>=19.1.0)"]
 bcrypt = ["bcrypt"]
 
 [[package]]
 name = "django-cors-headers"
-version = "3.2.1"
+version = "3.8.0"
 description = "django-cors-headers is a Django application for handling the server headers required for Cross-Origin Resource Sharing (CORS)."
 category = "main"
 optional = false
-python-versions = ">=3.5"
+python-versions = ">=3.6"
 
 [package.dependencies]
-Django = ">=1.11"
+Django = ">=2.2"
 
 [[package]]
 name = "django-filter"
-version = "2.2.0"
+version = "2.4.0"
 description = "Django-filter is a reusable Django application for allowing users to filter querysets dynamically."
 category = "main"
 optional = false
-python-versions = ">=3.4"
+python-versions = ">=3.5"
 
 [package.dependencies]
-Django = ">=1.11"
+Django = ">=2.2"
 
 [[package]]
 name = "django-guardian"
-version = "2.2.0"
+version = "2.4.0"
 description = "Implementation of per object permissions for Django."
 category = "main"
 optional = false
 python-versions = ">=3.5"
 
 [package.dependencies]
-Django = ">=2.1"
+Django = ">=2.2"
 
 [[package]]
 name = "djangorestframework"
-version = "3.12.2"
+version = "3.12.4"
 description = "Web APIs for Django, made easy."
 category = "main"
 optional = false
@@ -309,7 +326,7 @@ djangorestframework = "*"
 
 [[package]]
 name = "djangorestframework-simplejwt"
-version = "4.6.0"
+version = "4.8.0"
 description = "A minimal JSON Web Token authentication plugin for Django REST Framework"
 category = "main"
 optional = false
@@ -318,10 +335,10 @@ python-versions = ">=3.7"
 [package.dependencies]
 django = "*"
 djangorestframework = "*"
-pyjwt = "*"
+pyjwt = ">=2,<3"
 
 [package.extras]
-dev = ["bumpversion (>=0.5.3,<1)", "pytest-watch", "wheel", "twine", "ipython", "cryptography", "pytest-cov", "pytest-django", "pytest-xdist", "pytest", "tox", "flake8", "pep8", "isort", "Sphinx (>=1.6.5,<2)", "sphinx-rtd-theme (>=0.1.9)", "python-jose (==3.0.0)"]
+dev = ["pytest-watch", "wheel", "twine", "ipython", "cryptography", "pytest-cov", "pytest-django", "pytest-xdist", "pytest", "tox", "flake8", "pep8", "isort", "Sphinx (>=1.6.5,<2)", "sphinx-rtd-theme (>=0.1.9)", "python-jose (==3.0.0)"]
 doc = ["Sphinx (>=1.6.5,<2)", "sphinx-rtd-theme (>=0.1.9)"]
 lint = ["flake8", "pep8", "isort"]
 python-jose = ["python-jose (==3.0.0)"]
@@ -339,21 +356,13 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
 Django = ">=1.11"
 djangorestframework = ">=3.6.0"
 
-[[package]]
-name = "entrypoints"
-version = "0.3"
-description = "Discover and load entry points from installed packages."
-category = "dev"
-optional = false
-python-versions = ">=2.7"
-
 [[package]]
 name = "et-xmlfile"
-version = "1.0.1"
+version = "1.1.0"
 description = "An implementation of lxml.xmlfile for the standard library"
 category = "main"
 optional = false
-python-versions = "*"
+python-versions = ">=3.6"
 
 [[package]]
 name = "factory-boy"
@@ -368,11 +377,11 @@ Faker = ">=0.7.0"
 
 [[package]]
 name = "faker"
-version = "4.0.3"
+version = "8.12.1"
 description = "Faker is a Python package that generates fake data for you."
 category = "main"
 optional = false
-python-versions = ">=3.4"
+python-versions = ">=3.6"
 
 [package.dependencies]
 python-dateutil = ">=2.4"
@@ -380,69 +389,69 @@ text-unidecode = "1.3"
 
 [[package]]
 name = "flake8"
-version = "3.7.9"
-description = "the modular source code checker: pep8, pyflakes and co"
+version = "3.9.2"
+description = "the modular source code checker: pep8 pyflakes and co"
 category = "dev"
 optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
 
 [package.dependencies]
-entrypoints = ">=0.3.0,<0.4.0"
 mccabe = ">=0.6.0,<0.7.0"
-pycodestyle = ">=2.5.0,<2.6.0"
-pyflakes = ">=2.1.0,<2.2.0"
+pycodestyle = ">=2.7.0,<2.8.0"
+pyflakes = ">=2.3.0,<2.4.0"
 
 [[package]]
 name = "idna"
-version = "2.10"
+version = "3.2"
 description = "Internationalized Domain Names in Applications (IDNA)"
 category = "main"
 optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+python-versions = ">=3.5"
 
 [[package]]
 name = "inflection"
-version = "0.4.0"
+version = "0.5.1"
 description = "A port of Ruby on Rails inflector to Python"
 category = "dev"
 optional = false
 python-versions = ">=3.5"
 
+[[package]]
+name = "iniconfig"
+version = "1.1.1"
+description = "iniconfig: brain-dead simple config-ini parsing"
+category = "dev"
+optional = false
+python-versions = "*"
+
 [[package]]
 name = "isort"
-version = "4.3.21"
+version = "5.9.3"
 description = "A Python utility / library to sort Python imports."
 category = "dev"
 optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+python-versions = ">=3.6.1,<4.0"
 
 [package.extras]
-pipfile = ["pipreqs", "requirementslib"]
-pyproject = ["toml"]
-requirements = ["pipreqs", "pip-api"]
-xdg_home = ["appdirs (>=1.4.0)"]
-
-[[package]]
-name = "jdcal"
-version = "1.4.1"
-description = "Julian dates from proleptic Gregorian and Julian calendars."
-category = "main"
-optional = false
-python-versions = "*"
+pipfile_deprecated_finder = ["pipreqs", "requirementslib"]
+requirements_deprecated_finder = ["pipreqs", "pip-api"]
+colors = ["colorama (>=0.4.3,<0.5.0)"]
+plugins = ["setuptools"]
 
 [[package]]
 name = "kombu"
-version = "5.0.2"
+version = "5.1.0"
 description = "Messaging library for Python."
 category = "main"
 optional = false
 python-versions = ">=3.6"
 
 [package.dependencies]
-amqp = ">=5.0.0,<6.0.0"
+amqp = ">=5.0.6,<6.0.0"
+vine = "*"
 
 [package.extras]
-azureservicebus = ["azure-servicebus (>=0.21.1)"]
+azureservicebus = ["azure-servicebus (>=7.0.0)"]
 azurestoragequeues = ["azure-storage-queue"]
 consul = ["python-consul (>=0.6.0)"]
 librabbitmq = ["librabbitmq (>=1.5.2)"]
@@ -453,17 +462,17 @@ qpid = ["qpid-python (>=0.26)", "qpid-tools (>=0.26)"]
 redis = ["redis (>=3.3.11)"]
 slmq = ["softlayer-messaging (>=1.0.3)"]
 sqlalchemy = ["sqlalchemy"]
-sqs = ["boto3 (>=1.4.4)", "pycurl (==7.43.0.2)"]
+sqs = ["boto3 (>=1.4.4)", "pycurl (==7.43.0.2)", "urllib3 (<1.26)"]
 yaml = ["PyYAML (>=3.10)"]
 zookeeper = ["kazoo (>=1.3.1)"]
 
 [[package]]
 name = "lazy-object-proxy"
-version = "1.4.1"
+version = "1.6.0"
 description = "A fast and thorough lazy object proxy."
 category = "dev"
 optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*"
 
 [[package]]
 name = "mccabe"
@@ -473,25 +482,17 @@ category = "dev"
 optional = false
 python-versions = "*"
 
-[[package]]
-name = "more-itertools"
-version = "8.3.0"
-description = "More routines for operating on iterables, beyond itertools"
-category = "dev"
-optional = false
-python-versions = ">=3.5"
-
 [[package]]
 name = "numpy"
-version = "1.18.4"
+version = "1.21.2"
 description = "NumPy is the fundamental package for array computing with Python."
 category = "main"
 optional = false
-python-versions = ">=3.5"
+python-versions = ">=3.7,<3.11"
 
 [[package]]
 name = "openpyxl"
-version = "3.0.5"
+version = "3.0.7"
 description = "A Python library to read/write Excel 2010 xlsx/xlsm files"
 category = "main"
 optional = false
@@ -499,77 +500,88 @@ python-versions = ">=3.6,"
 
 [package.dependencies]
 et-xmlfile = "*"
-jdcal = "*"
 
 [[package]]
 name = "packaging"
-version = "20.4"
+version = "21.0"
 description = "Core utilities for Python packages"
 category = "dev"
 optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+python-versions = ">=3.6"
 
 [package.dependencies]
 pyparsing = ">=2.0.2"
-six = "*"
 
 [[package]]
 name = "pandas"
-version = "1.0.3"
+version = "1.3.2"
 description = "Powerful data structures for data analysis, time series, and statistics"
 category = "main"
 optional = false
-python-versions = ">=3.6.1"
+python-versions = ">=3.7.1"
 
 [package.dependencies]
-numpy = ">=1.13.3"
-python-dateutil = ">=2.6.1"
-pytz = ">=2017.2"
+numpy = ">=1.17.3"
+python-dateutil = ">=2.7.3"
+pytz = ">=2017.3"
 
 [package.extras]
-test = ["pytest (>=4.0.2)", "pytest-xdist", "hypothesis (>=3.58)"]
+test = ["hypothesis (>=3.58)", "pytest (>=6.0)", "pytest-xdist"]
 
 [[package]]
 name = "pathspec"
-version = "0.8.0"
+version = "0.9.0"
 description = "Utility library for gitignore style pattern matching of file paths."
 category = "dev"
 optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
+python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
+
+[[package]]
+name = "platformdirs"
+version = "2.3.0"
+description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
+category = "dev"
+optional = false
+python-versions = ">=3.6"
+
+[package.extras]
+docs = ["Sphinx (>=4)", "furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx-autodoc-typehints (>=1.12)"]
+test = ["appdirs (==1.4.4)", "pytest (>=6)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)"]
 
 [[package]]
 name = "pluggy"
-version = "0.13.1"
+version = "1.0.0"
 description = "plugin and hook calling mechanisms for python"
 category = "dev"
 optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+python-versions = ">=3.6"
 
 [package.extras]
 dev = ["pre-commit", "tox"]
+testing = ["pytest", "pytest-benchmark"]
 
 [[package]]
 name = "prompt-toolkit"
-version = "3.0.8"
+version = "3.0.20"
 description = "Library for building powerful interactive command lines in Python"
 category = "main"
 optional = false
-python-versions = ">=3.6.1"
+python-versions = ">=3.6.2"
 
 [package.dependencies]
 wcwidth = "*"
 
 [[package]]
 name = "psycopg2"
-version = "2.8.5"
+version = "2.9.1"
 description = "psycopg2 - Python-PostgreSQL Database Adapter"
 category = "main"
 optional = false
-python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*"
+python-versions = ">=3.6"
 
 [[package]]
 name = "py"
-version = "1.8.1"
+version = "1.10.0"
 description = "library with cross-python path, ini-parsing, io, code, log facilities"
 category = "dev"
 optional = false
@@ -577,7 +589,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
 
 [[package]]
 name = "pycodestyle"
-version = "2.5.0"
+version = "2.7.0"
 description = "Python style guide checker"
 category = "dev"
 optional = false
@@ -585,7 +597,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
 
 [[package]]
 name = "pyflakes"
-version = "2.1.1"
+version = "2.3.1"
 description = "passive checker of Python programs"
 category = "dev"
 optional = false
@@ -593,30 +605,32 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
 
 [[package]]
 name = "pyjwt"
-version = "1.7.1"
+version = "2.1.0"
 description = "JSON Web Token implementation in Python"
 category = "main"
 optional = false
-python-versions = "*"
+python-versions = ">=3.6"
 
 [package.extras]
-crypto = ["cryptography (>=1.4)"]
-flake8 = ["flake8", "flake8-import-order", "pep8-naming"]
-test = ["pytest (>=4.0.1,<5.0.0)", "pytest-cov (>=2.6.0,<3.0.0)", "pytest-runner (>=4.2,<5.0.0)"]
+crypto = ["cryptography (>=3.3.1,<4.0.0)"]
+dev = ["sphinx", "sphinx-rtd-theme", "zope.interface", "cryptography (>=3.3.1,<4.0.0)", "pytest (>=6.0.0,<7.0.0)", "coverage[toml] (==5.0.4)", "mypy", "pre-commit"]
+docs = ["sphinx", "sphinx-rtd-theme", "zope.interface"]
+tests = ["pytest (>=6.0.0,<7.0.0)", "coverage[toml] (==5.0.4)"]
 
 [[package]]
 name = "pylint"
-version = "2.5.2"
+version = "2.10.2"
 description = "python code static checker"
 category = "dev"
 optional = false
-python-versions = ">=3.5.*"
+python-versions = "~=3.6"
 
 [package.dependencies]
-astroid = ">=2.4.0,<=2.5"
+astroid = ">=2.7.2,<2.8"
 colorama = {version = "*", markers = "sys_platform == \"win32\""}
-isort = ">=4.2.5,<5"
+isort = ">=4.2.5,<6"
 mccabe = ">=0.6,<0.7"
+platformdirs = ">=2.2.0"
 toml = ">=0.7.1"
 
 [[package]]
@@ -629,29 +643,28 @@ python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
 
 [[package]]
 name = "pytest"
-version = "5.4.2"
+version = "6.2.5"
 description = "pytest: simple powerful testing with Python"
 category = "dev"
 optional = false
-python-versions = ">=3.5"
+python-versions = ">=3.6"
 
 [package.dependencies]
 atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""}
-attrs = ">=17.4.0"
+attrs = ">=19.2.0"
 colorama = {version = "*", markers = "sys_platform == \"win32\""}
-more-itertools = ">=4.0.0"
+iniconfig = "*"
 packaging = "*"
-pluggy = ">=0.12,<1.0"
-py = ">=1.5.0"
-wcwidth = "*"
+pluggy = ">=0.12,<2.0"
+py = ">=1.8.2"
+toml = "*"
 
 [package.extras]
-checkqa-mypy = ["mypy (==v0.761)"]
 testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"]
 
 [[package]]
 name = "pytest-celery"
-version = "0.0.0a1"
+version = "0.0.0"
 description = "pytest-celery a shim pytest plugin to enable celery.contrib.pytest"
 category = "dev"
 optional = false
@@ -662,7 +675,7 @@ celery = ">=4.4.0"
 
 [[package]]
 name = "pytest-cov"
-version = "2.11.1"
+version = "2.12.1"
 description = "Pytest plugin for measuring coverage."
 category = "dev"
 optional = false
@@ -671,9 +684,10 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
 [package.dependencies]
 coverage = ">=5.2.1"
 pytest = ">=4.6"
+toml = "*"
 
 [package.extras]
-testing = ["fields", "hunter", "process-tests (==2.0.2)", "six", "pytest-xdist", "virtualenv"]
+testing = ["fields", "hunter", "process-tests", "six", "pytest-xdist", "virtualenv"]
 
 [[package]]
 name = "pytest-datadir"
@@ -703,20 +717,20 @@ testing = ["django", "django-configurations (>=2.0)", "six"]
 
 [[package]]
 name = "pytest-factoryboy"
-version = "2.0.3"
+version = "2.1.0"
 description = "Factory Boy support for pytest."
 category = "dev"
 optional = false
-python-versions = "*"
+python-versions = ">=3.6"
 
 [package.dependencies]
-factory_boy = ">=2.10.0"
+factory-boy = ">=2.10.0"
 inflection = "*"
-pytest = ">=3.3.2"
+pytest = ">=4.6"
 
 [[package]]
 name = "pytest-mock"
-version = "3.6.0"
+version = "3.6.1"
 description = "Thin-wrapper around the mock package for easier use with pytest"
 category = "dev"
 optional = false
@@ -730,7 +744,7 @@ dev = ["pre-commit", "tox", "pytest-asyncio"]
 
 [[package]]
 name = "python-dateutil"
-version = "2.8.1"
+version = "2.8.2"
 description = "Extensions to the standard Python datetime module"
 category = "main"
 optional = false
@@ -741,7 +755,7 @@ six = ">=1.5"
 
 [[package]]
 name = "python-decouple"
-version = "3.3"
+version = "3.4"
 description = "Strict separation of settings from code."
 category = "main"
 optional = false
@@ -749,7 +763,7 @@ python-versions = "*"
 
 [[package]]
 name = "pytz"
-version = "2019.2"
+version = "2021.1"
 description = "World timezone definitions, modern and historical"
 category = "main"
 optional = false
@@ -757,11 +771,11 @@ python-versions = "*"
 
 [[package]]
 name = "pyyaml"
-version = "5.3.1"
+version = "5.4.1"
 description = "YAML parser and emitter for Python"
 category = "main"
 optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*"
 
 [[package]]
 name = "redis"
@@ -776,7 +790,7 @@ hiredis = ["hiredis (>=0.1.3)"]
 
 [[package]]
 name = "regex"
-version = "2020.5.7"
+version = "2021.8.28"
 description = "Alternative regular expression module, to replace re."
 category = "dev"
 optional = false
@@ -784,21 +798,21 @@ python-versions = "*"
 
 [[package]]
 name = "requests"
-version = "2.24.0"
+version = "2.26.0"
 description = "Python HTTP for Humans."
 category = "main"
 optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*"
 
 [package.dependencies]
 certifi = ">=2017.4.17"
-chardet = ">=3.0.2,<4"
-idna = ">=2.5,<3"
-urllib3 = ">=1.21.1,<1.25.0 || >1.25.0,<1.25.1 || >1.25.1,<1.26"
+charset-normalizer = {version = ">=2.0.0,<2.1.0", markers = "python_version >= \"3\""}
+idna = {version = ">=2.5,<4", markers = "python_version >= \"3\""}
+urllib3 = ">=1.21.1,<1.27"
 
 [package.extras]
-security = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)"]
 socks = ["PySocks (>=1.5.6,!=1.5.7)", "win-inet-pton"]
+use_chardet_on_py3 = ["chardet (>=3.0.2,<5)"]
 
 [[package]]
 name = "requests-toolbelt"
@@ -813,19 +827,19 @@ requests = ">=2.0.1,<3.0.0"
 
 [[package]]
 name = "six"
-version = "1.12.0"
+version = "1.16.0"
 description = "Python 2 and 3 compatibility utilities"
 category = "main"
 optional = false
-python-versions = ">=2.6, !=3.0.*, !=3.1.*"
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
 
 [[package]]
 name = "sqlparse"
-version = "0.3.0"
-description = "Non-validating SQL parser"
+version = "0.4.1"
+description = "A non-validating SQL parser."
 category = "main"
 optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+python-versions = ">=3.5"
 
 [[package]]
 name = "text-unidecode"
@@ -837,23 +851,31 @@ python-versions = "*"
 
 [[package]]
 name = "toml"
-version = "0.10.0"
+version = "0.10.2"
 description = "Python Library for Tom's Obvious, Minimal Language"
 category = "dev"
 optional = false
-python-versions = "*"
+python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
 
 [[package]]
 name = "typed-ast"
-version = "1.4.0"
+version = "1.4.3"
 description = "a fork of Python 2 and 3 ast modules with type comment support"
 category = "dev"
 optional = false
 python-versions = "*"
 
+[[package]]
+name = "unidecode"
+version = "1.3.3"
+description = "ASCII transliterations of Unicode text"
+category = "main"
+optional = false
+python-versions = ">=3.5"
+
 [[package]]
 name = "urllib3"
-version = "1.25.11"
+version = "1.26.6"
 description = "HTTP library with thread-safe connection pooling, file post, and more."
 category = "main"
 optional = false
@@ -874,15 +896,15 @@ python-versions = ">=3.6"
 
 [[package]]
 name = "wcwidth"
-version = "0.1.9"
-description = "Measures number of Terminal column cells of wide-character codes"
+version = "0.2.5"
+description = "Measures the displayed width of unicode strings in a terminal"
 category = "main"
 optional = false
 python-versions = "*"
 
 [[package]]
 name = "wrapt"
-version = "1.11.2"
+version = "1.12.1"
 description = "Module for decorators, wrappers and monkey patching."
 category = "dev"
 optional = false
@@ -907,40 +929,40 @@ python-versions = "*"
 [metadata]
 lock-version = "1.1"
 python-versions = "^3.8, <3.9"
-content-hash = "93c43f7f565fb8208498354b3ebf51c0624fc54f5639cd25da0e308de9269371"
+content-hash = "bbca07df04ebf421f1941920d67c3fc77f65f492c23770784e0c8d65e16e5cb1"
 
 [metadata.files]
 amqp = [
-    {file = "amqp-5.0.1-py2.py3-none-any.whl", hash = "sha256:a8fb8151eb9d12204c9f1784c0da920476077609fa0a70f2468001e3a4258484"},
-    {file = "amqp-5.0.1.tar.gz", hash = "sha256:9881f8e6fe23e3db9faa6cfd8c05390213e1d1b95c0162bc50552cad75bffa5f"},
+    {file = "amqp-5.0.6-py3-none-any.whl", hash = "sha256:493a2ac6788ce270a2f6a765b017299f60c1998f5a8617908ee9be082f7300fb"},
+    {file = "amqp-5.0.6.tar.gz", hash = "sha256:03e16e94f2b34c31f8bf1206d8ddd3ccaa4c315f7f6a1879b7b1210d229568c2"},
 ]
 appdirs = [
-    {file = "appdirs-1.4.3-py2.py3-none-any.whl", hash = "sha256:d8b24664561d0d34ddfaec54636d502d7cea6e29c3eaf68f3df6180863e2166e"},
-    {file = "appdirs-1.4.3.tar.gz", hash = "sha256:9e5896d1372858f8dd3344faf4e5014d21849c756c8d5701f78f8a103b372d92"},
+    {file = "appdirs-1.4.4-py2.py3-none-any.whl", hash = "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128"},
+    {file = "appdirs-1.4.4.tar.gz", hash = "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41"},
 ]
 asgiref = [
-    {file = "asgiref-3.3.0-py3-none-any.whl", hash = "sha256:a5098bc870b80e7b872bff60bb363c7f2c2c89078759f6c47b53ff8c525a152e"},
-    {file = "asgiref-3.3.0.tar.gz", hash = "sha256:cd88907ecaec59d78e4ac00ea665b03e571cb37e3a0e37b3702af1a9e86c365a"},
+    {file = "asgiref-3.4.1-py3-none-any.whl", hash = "sha256:ffc141aa908e6f175673e7b1b3b7af4fdb0ecb738fc5c8b88f69f055c2415214"},
+    {file = "asgiref-3.4.1.tar.gz", hash = "sha256:4ef1ab46b484e3c706329cedeff284a5d40824200638503f5768edb6de7d58e9"},
 ]
 astroid = [
-    {file = "astroid-2.4.1-py3-none-any.whl", hash = "sha256:d8506842a3faf734b81599c8b98dcc423de863adcc1999248480b18bd31a0f38"},
-    {file = "astroid-2.4.1.tar.gz", hash = "sha256:4c17cea3e592c21b6e222f673868961bad77e1f985cb1694ed077475a89229c1"},
+    {file = "astroid-2.7.3-py3-none-any.whl", hash = "sha256:dc1e8b28427d6bbef6b8842b18765ab58f558c42bb80540bd7648c98412af25e"},
+    {file = "astroid-2.7.3.tar.gz", hash = "sha256:3b680ce0419b8a771aba6190139a3998d14b413852506d99aff8dc2bf65ee67c"},
 ]
 atomicwrites = [
     {file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"},
     {file = "atomicwrites-1.4.0.tar.gz", hash = "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"},
 ]
 attrs = [
-    {file = "attrs-19.3.0-py2.py3-none-any.whl", hash = "sha256:08a96c641c3a74e44eb59afb61a24f2cb9f4d7188748e76ba4bb5edfa3cb7d1c"},
-    {file = "attrs-19.3.0.tar.gz", hash = "sha256:f7b7ce16570fe9965acd6d30101a28f62fb4a7f9e926b3bbc9b61f8b04247e72"},
+    {file = "attrs-21.2.0-py2.py3-none-any.whl", hash = "sha256:149e90d6d8ac20db7a955ad60cf0e6881a3f20d37096140088356da6c716b0b1"},
+    {file = "attrs-21.2.0.tar.gz", hash = "sha256:ef6aaac3ca6cd92904cdd0d83f629a15f18053ec84e6432106f7a4d04ae4f5fb"},
 ]
 billiard = [
-    {file = "billiard-3.6.3.0-py3-none-any.whl", hash = "sha256:bff575450859a6e0fbc2f9877d9b715b0bbc07c3565bb7ed2280526a0cdf5ede"},
-    {file = "billiard-3.6.3.0.tar.gz", hash = "sha256:d91725ce6425f33a97dfa72fb6bfef0e47d4652acd98a032bd1a7fbf06d5fa6a"},
+    {file = "billiard-3.6.4.0-py3-none-any.whl", hash = "sha256:87103ea78fa6ab4d5c751c4909bcff74617d985de7fa8b672cf8618afd5a875b"},
+    {file = "billiard-3.6.4.0.tar.gz", hash = "sha256:299de5a8da28a783d51b197d496bef4f1595dd023a93a4f59dde1886ae905547"},
 ]
 bioblend = [
-    {file = "bioblend-0.14.0-py2.py3-none-any.whl", hash = "sha256:b63505ddbecdebcc30406bc3186247d7d205ec6ba0fa4bfd220518c96ff92dd7"},
-    {file = "bioblend-0.14.0.tar.gz", hash = "sha256:c6455547914c49e4da3053e7b2059f0a3f7278f46c9ffe69072472c4ffd4acbd"},
+    {file = "bioblend-0.16.0-py2.py3-none-any.whl", hash = "sha256:057450d39054cf91fff31e9025f269eb08e1ef1b437d71dfc73957e7cb0d8195"},
+    {file = "bioblend-0.16.0.tar.gz", hash = "sha256:814312e3583a4cbb4ffaa1fb103107d9a24c069604abf51c670251fdc8bf094a"},
 ]
 black = [
     {file = "black-19.10b0-py36-none-any.whl", hash = "sha256:1b30e59be925fafc1ee4565e5e08abef6b03fe455102883820fe5ee2e4734e0b"},
@@ -951,31 +973,35 @@ boto = [
     {file = "boto-2.49.0.tar.gz", hash = "sha256:ea0d3b40a2d852767be77ca343b58a9e3a4b00d9db440efb8da74b4e58025e5a"},
 ]
 celery = [
-    {file = "celery-5.0.2-py3-none-any.whl", hash = "sha256:930c3acd55349d028c4e7104a7d377729cbcca19d9fce470c17172d9e7f9a8b6"},
-    {file = "celery-5.0.2.tar.gz", hash = "sha256:012c814967fe89e3f5d2cf49df2dba3de5f29253a7f4f2270e8fce6b901b4ebf"},
+    {file = "celery-5.1.2-py3-none-any.whl", hash = "sha256:9dab2170b4038f7bf10ef2861dbf486ddf1d20592290a1040f7b7a1259705d42"},
+    {file = "celery-5.1.2.tar.gz", hash = "sha256:8d9a3de9162965e97f8e8cc584c67aad83b3f7a267584fa47701ed11c3e0d4b0"},
 ]
 certifi = [
-    {file = "certifi-2020.6.20-py2.py3-none-any.whl", hash = "sha256:8fc0819f1f30ba15bdb34cceffb9ef04d99f420f68eb75d901e9560b8749fc41"},
-    {file = "certifi-2020.6.20.tar.gz", hash = "sha256:5930595817496dd21bb8dc35dad090f1c2cd0adfaf21204bf6732ca5d8ee34d3"},
+    {file = "certifi-2021.5.30-py2.py3-none-any.whl", hash = "sha256:50b1e4f8446b06f41be7dd6338db18e0990601dce795c2b1686458aa7e8fa7d8"},
+    {file = "certifi-2021.5.30.tar.gz", hash = "sha256:2bbf76fd432960138b3ef6dda3dde0544f27cbf8546c458e60baf371917ba9ee"},
 ]
-chardet = [
-    {file = "chardet-3.0.4-py2.py3-none-any.whl", hash = "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"},
-    {file = "chardet-3.0.4.tar.gz", hash = "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae"},
+charset-normalizer = [
+    {file = "charset-normalizer-2.0.4.tar.gz", hash = "sha256:f23667ebe1084be45f6ae0538e4a5a865206544097e4e8bbcacf42cd02a348f3"},
+    {file = "charset_normalizer-2.0.4-py3-none-any.whl", hash = "sha256:0c8911edd15d19223366a194a513099a302055a962bca2cec0f54b8b63175d8b"},
 ]
 click = [
-    {file = "Click-7.0-py2.py3-none-any.whl", hash = "sha256:2335065e6395b9e67ca716de5f7526736bfa6ceead690adf616d925bdc622b13"},
-    {file = "Click-7.0.tar.gz", hash = "sha256:5b94b49521f6456670fdb30cd82a4eca9412788a93fa6dd6df72c94d5a8ff2d7"},
+    {file = "click-7.1.2-py2.py3-none-any.whl", hash = "sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc"},
+    {file = "click-7.1.2.tar.gz", hash = "sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a"},
 ]
 click-didyoumean = [
     {file = "click-didyoumean-0.0.3.tar.gz", hash = "sha256:112229485c9704ff51362fe34b2d4f0b12fc71cc20f6d2b3afabed4b8bfa6aeb"},
 ]
+click-plugins = [
+    {file = "click-plugins-1.1.1.tar.gz", hash = "sha256:46ab999744a9d831159c3411bb0c79346d94a444df9a3a3742e9ed63645f264b"},
+    {file = "click_plugins-1.1.1-py2.py3-none-any.whl", hash = "sha256:5d262006d3222f5057fd81e1623d4443e41dcda5dc815c06b442aa3c02889fc8"},
+]
 click-repl = [
-    {file = "click-repl-0.1.6.tar.gz", hash = "sha256:b9f29d52abc4d6059f8e276132a111ab8d94980afe6a5432b9d996544afa95d5"},
-    {file = "click_repl-0.1.6-py3-none-any.whl", hash = "sha256:9c4c3d022789cae912aad8a3f5e1d7c2cdd016ee1225b5212ad3e8691563cda5"},
+    {file = "click-repl-0.2.0.tar.gz", hash = "sha256:cd12f68d745bf6151210790540b4cb064c7b13e571bc64b6957d98d120dacfd8"},
+    {file = "click_repl-0.2.0-py3-none-any.whl", hash = "sha256:94b3fbbc9406a236f176e0506524b2937e4b23b6f4c0c0b2a0a83f8a64e9194b"},
 ]
 colorama = [
-    {file = "colorama-0.4.3-py2.py3-none-any.whl", hash = "sha256:7d73d2a99753107a36ac6b455ee49046802e59d9d076ef8e47b61499fa29afff"},
-    {file = "colorama-0.4.3.tar.gz", hash = "sha256:e96da0d330793e2cb9485e9ddfd918d456036c7149416295932478192f4436a1"},
+    {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"},
+    {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"},
 ]
 coverage = [
     {file = "coverage-5.5-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:b6d534e4b2ab35c9f93f46229363e17f63c53ad01330df9f2d6bd1187e5eaacf"},
@@ -1032,215 +1058,224 @@ coverage = [
     {file = "coverage-5.5.tar.gz", hash = "sha256:ebe78fe9a0e874362175b02371bdfbee64d8edc42a044253ddf4ee7d3c15212c"},
 ]
 django = [
-    {file = "Django-3.1.3-py3-none-any.whl", hash = "sha256:14a4b7cd77297fba516fc0d92444cc2e2e388aa9de32d7a68d4a83d58f5a4927"},
-    {file = "Django-3.1.3.tar.gz", hash = "sha256:14b87775ffedab2ef6299b73343d1b4b41e5d4e2aa58c6581f114dbec01e3f8f"},
+    {file = "Django-3.2.7-py3-none-any.whl", hash = "sha256:e93c93565005b37ddebf2396b4dc4b6913c1838baa82efdfb79acedd5816c240"},
+    {file = "Django-3.2.7.tar.gz", hash = "sha256:95b318319d6997bac3595517101ad9cc83fe5672ac498ba48d1a410f47afecd2"},
 ]
 django-cors-headers = [
-    {file = "django-cors-headers-3.2.1.tar.gz", hash = "sha256:a5960addecc04527ab26617e51b8ed42f0adab4594b24bb0f3c33e2bd3857c3f"},
-    {file = "django_cors_headers-3.2.1-py3-none-any.whl", hash = "sha256:a785b5f446f6635810776d9f5f5d23e6a2a2f728ea982648370afaf0dfdf2627"},
+    {file = "django-cors-headers-3.8.0.tar.gz", hash = "sha256:4b8e13bf8d3df50ac4b986bd87085c3073dd56402ede109222ea34a774f9ec1b"},
+    {file = "django_cors_headers-3.8.0-py3-none-any.whl", hash = "sha256:425c20ceffa42b9ac11b02611eece4ae6c5fef2ff0f039c14c1df20e00c80df8"},
 ]
 django-filter = [
-    {file = "django-filter-2.2.0.tar.gz", hash = "sha256:c3deb57f0dd7ff94d7dce52a047516822013e2b441bed472b722a317658cfd14"},
-    {file = "django_filter-2.2.0-py3-none-any.whl", hash = "sha256:558c727bce3ffa89c4a7a0b13bc8976745d63e5fd576b3a9a851650ef11c401b"},
+    {file = "django-filter-2.4.0.tar.gz", hash = "sha256:84e9d5bb93f237e451db814ed422a3a625751cbc9968b484ecc74964a8696b06"},
+    {file = "django_filter-2.4.0-py3-none-any.whl", hash = "sha256:e00d32cebdb3d54273c48f4f878f898dced8d5dfaad009438fe61ebdf535ace1"},
 ]
 django-guardian = [
-    {file = "django-guardian-2.2.0.tar.gz", hash = "sha256:8cacf49ebcc1e545f0a8997971eec0fe109f5ed31fc2a569a7bf5615453696e2"},
-    {file = "django_guardian-2.2.0-py3-none-any.whl", hash = "sha256:ac81e88372fdf1795d84ba065550e739b42e9c6d07cdf201cf5bbf9efa7f396c"},
+    {file = "django-guardian-2.4.0.tar.gz", hash = "sha256:c58a68ae76922d33e6bdc0e69af1892097838de56e93e78a8361090bcd9f89a0"},
+    {file = "django_guardian-2.4.0-py3-none-any.whl", hash = "sha256:440ca61358427e575323648b25f8384739e54c38b3d655c81d75e0cd0d61b697"},
 ]
 djangorestframework = [
-    {file = "djangorestframework-3.12.2-py3-none-any.whl", hash = "sha256:0209bafcb7b5010fdfec784034f059d512256424de2a0f084cb82b096d6dd6a7"},
-    {file = "djangorestframework-3.12.2.tar.gz", hash = "sha256:0898182b4737a7b584a2c73735d89816343369f259fea932d90dc78e35d8ac33"},
+    {file = "djangorestframework-3.12.4-py3-none-any.whl", hash = "sha256:6d1d59f623a5ad0509fe0d6bfe93cbdfe17b8116ebc8eda86d45f6e16e819aaf"},
+    {file = "djangorestframework-3.12.4.tar.gz", hash = "sha256:f747949a8ddac876e879190df194b925c177cdeb725a099db1460872f7c0a7f2"},
 ]
 djangorestframework-guardian = [
     {file = "djangorestframework-guardian-0.3.0.tar.gz", hash = "sha256:1883756452d9bfcc2a51fb4e039a6837a8f6697c756447aa83af085749b59330"},
     {file = "djangorestframework_guardian-0.3.0-py2.py3-none-any.whl", hash = "sha256:3bd3dd6ea58e1bceca5048faf6f8b1a93bb5dcff30ba5eb91b9a0e190a48a0c7"},
 ]
 djangorestframework-simplejwt = [
-    {file = "djangorestframework_simplejwt-4.6.0-py3-none-any.whl", hash = "sha256:bd587700b6ab34a6c6b12d426cce4fa580d57ef1952ad4ba3b79707784619ed3"},
-    {file = "djangorestframework_simplejwt-4.6.0.tar.gz", hash = "sha256:7adc913ba0d2ed7f46e0b9bf6e86f9bd9248f1c4201722b732b8213e0ea66f9f"},
+    {file = "djangorestframework_simplejwt-4.8.0-py3-none-any.whl", hash = "sha256:6f09f97cb015265e85d1d02dc6bfc299c72c231eecbe261c5bee5c6b2867f2b4"},
+    {file = "djangorestframework_simplejwt-4.8.0.tar.gz", hash = "sha256:153c973c5c154baf566be431de8527c2bd62557fde7373ebcb0f02b73b28e07a"},
 ]
 drf-nested-routers = [
     {file = "drf-nested-routers-0.91.tar.gz", hash = "sha256:46e5c3abc15c782cafafd7d75028e8f9121bbc6228e3599bbb48a3daa4585034"},
     {file = "drf_nested_routers-0.91-py2.py3-none-any.whl", hash = "sha256:60c1e1f5cc801e757d26a8138e61c44419ef800c213c3640c5b6138e77d46762"},
 ]
-entrypoints = [
-    {file = "entrypoints-0.3-py2.py3-none-any.whl", hash = "sha256:589f874b313739ad35be6e0cd7efde2a4e9b6fea91edcc34e58ecbb8dbe56d19"},
-    {file = "entrypoints-0.3.tar.gz", hash = "sha256:c70dd71abe5a8c85e55e12c19bd91ccfeec11a6e99044204511f9ed547d48451"},
-]
 et-xmlfile = [
-    {file = "et_xmlfile-1.0.1.tar.gz", hash = "sha256:614d9722d572f6246302c4491846d2c393c199cfa4edc9af593437691683335b"},
+    {file = "et_xmlfile-1.1.0-py3-none-any.whl", hash = "sha256:a2ba85d1d6a74ef63837eed693bcb89c3f752169b0e3e7ae5b16ca5e1b3deada"},
+    {file = "et_xmlfile-1.1.0.tar.gz", hash = "sha256:8eb9e2bc2f8c97e37a2dc85a09ecdcdec9d8a396530a6d5a33b30b9a92da0c5c"},
 ]
 factory-boy = [
     {file = "factory_boy-2.12.0-py2.py3-none-any.whl", hash = "sha256:728df59b372c9588b83153facf26d3d28947fc750e8e3c95cefa9bed0e6394ee"},
     {file = "factory_boy-2.12.0.tar.gz", hash = "sha256:faf48d608a1735f0d0a3c9cbf536d64f9132b547dae7ba452c4d99a79e84a370"},
 ]
 faker = [
-    {file = "Faker-4.0.3-py3-none-any.whl", hash = "sha256:53bf2c8a2de8af271466e7b9cc2f08ecf83c4c947981680eb61080779a0adace"},
-    {file = "Faker-4.0.3.tar.gz", hash = "sha256:7292806948ed848f1bcea1e7b963bae6f398687d1da0ea096e156fea2787f454"},
+    {file = "Faker-8.12.1-py3-none-any.whl", hash = "sha256:6714c153433086681b26e5c95ee314ee0fcd45ec05f2426097543dd4c70789a6"},
+    {file = "Faker-8.12.1.tar.gz", hash = "sha256:810859626d19e62a2a13aa4a08d59ada131f0522431eec163b09b6df147a25b9"},
 ]
 flake8 = [
-    {file = "flake8-3.7.9-py2.py3-none-any.whl", hash = "sha256:49356e766643ad15072a789a20915d3c91dc89fd313ccd71802303fd67e4deca"},
-    {file = "flake8-3.7.9.tar.gz", hash = "sha256:45681a117ecc81e870cbf1262835ae4af5e7a8b08e40b944a8a6e6b895914cfb"},
+    {file = "flake8-3.9.2-py2.py3-none-any.whl", hash = "sha256:bf8fd333346d844f616e8d47905ef3a3384edae6b4e9beb0c5101e25e3110907"},
+    {file = "flake8-3.9.2.tar.gz", hash = "sha256:07528381786f2a6237b061f6e96610a4167b226cb926e2aa2b6b1d78057c576b"},
 ]
 idna = [
-    {file = "idna-2.10-py2.py3-none-any.whl", hash = "sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0"},
-    {file = "idna-2.10.tar.gz", hash = "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6"},
+    {file = "idna-3.2-py3-none-any.whl", hash = "sha256:14475042e284991034cb48e06f6851428fb14c4dc953acd9be9a5e95c7b6dd7a"},
+    {file = "idna-3.2.tar.gz", hash = "sha256:467fbad99067910785144ce333826c71fb0e63a425657295239737f7ecd125f3"},
 ]
 inflection = [
-    {file = "inflection-0.4.0-py2.py3-none-any.whl", hash = "sha256:9a15d3598f01220e93f2207c432cfede50daff53137ce660fb8be838ef1ca6cc"},
-    {file = "inflection-0.4.0.tar.gz", hash = "sha256:32a5c3341d9583ec319548b9015b7fbdf8c429cbcb575d326c33ae3a0e90d52c"},
+    {file = "inflection-0.5.1-py2.py3-none-any.whl", hash = "sha256:f38b2b640938a4f35ade69ac3d053042959b62a0f1076a5bbaa1b9526605a8a2"},
+    {file = "inflection-0.5.1.tar.gz", hash = "sha256:1a29730d366e996aaacffb2f1f1cb9593dc38e2ddd30c91250c6dde09ea9b417"},
 ]
-isort = [
-    {file = "isort-4.3.21-py2.py3-none-any.whl", hash = "sha256:6e811fcb295968434526407adb8796944f1988c5b65e8139058f2014cbe100fd"},
-    {file = "isort-4.3.21.tar.gz", hash = "sha256:54da7e92468955c4fceacd0c86bd0ec997b0e1ee80d97f67c35a78b719dccab1"},
+iniconfig = [
+    {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"},
+    {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"},
 ]
-jdcal = [
-    {file = "jdcal-1.4.1-py2.py3-none-any.whl", hash = "sha256:1abf1305fce18b4e8aa248cf8fe0c56ce2032392bc64bbd61b5dff2a19ec8bba"},
-    {file = "jdcal-1.4.1.tar.gz", hash = "sha256:472872e096eb8df219c23f2689fc336668bdb43d194094b5cc1707e1640acfc8"},
+isort = [
+    {file = "isort-5.9.3-py3-none-any.whl", hash = "sha256:e17d6e2b81095c9db0a03a8025a957f334d6ea30b26f9ec70805411e5c7c81f2"},
+    {file = "isort-5.9.3.tar.gz", hash = "sha256:9c2ea1e62d871267b78307fe511c0838ba0da28698c5732d54e2790bf3ba9899"},
 ]
 kombu = [
-    {file = "kombu-5.0.2-py2.py3-none-any.whl", hash = "sha256:6dc509178ac4269b0e66ab4881f70a2035c33d3a622e20585f965986a5182006"},
-    {file = "kombu-5.0.2.tar.gz", hash = "sha256:f4965fba0a4718d47d470beeb5d6446e3357a62402b16c510b6a2f251e05ac3c"},
+    {file = "kombu-5.1.0-py3-none-any.whl", hash = "sha256:e2dedd8a86c9077c350555153825a31e456a0dc20c15d5751f00137ec9c75f0a"},
+    {file = "kombu-5.1.0.tar.gz", hash = "sha256:01481d99f4606f6939cdc9b637264ed353ee9e3e4f62cfb582324142c41a572d"},
 ]
 lazy-object-proxy = [
-    {file = "lazy-object-proxy-1.4.1.tar.gz", hash = "sha256:4ba73f6089cd9b9478bc0a4fa807b47dbdb8fad1d8f31a0f0a5dbf26a4527a71"},
-    {file = "lazy_object_proxy-1.4.1-cp27-cp27m-macosx_10_13_x86_64.whl", hash = "sha256:3b11be575475db2e8a6e11215f5aa95b9ec14de658628776e10d96fa0b4dac13"},
-    {file = "lazy_object_proxy-1.4.1-cp27-cp27m-win32.whl", hash = "sha256:4f53eadd9932055eac465bd3ca1bd610e4d7141e1278012bd1f28646aebc1d0e"},
-    {file = "lazy_object_proxy-1.4.1-cp27-cp27m-win_amd64.whl", hash = "sha256:a262c7dfb046f00e12a2bdd1bafaed2408114a89ac414b0af8755c696eb3fc16"},
-    {file = "lazy_object_proxy-1.4.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:acce4e3267610c4fdb6632b3886fe3f2f7dd641158a843cf6b6a68e4ce81477b"},
-    {file = "lazy_object_proxy-1.4.1-cp34-cp34m-manylinux1_x86_64.whl", hash = "sha256:23f63c0821cc96a23332e45dfaa83266feff8adc72b9bcaef86c202af765244f"},
-    {file = "lazy_object_proxy-1.4.1-cp34-cp34m-win32.whl", hash = "sha256:be089bb6b83fac7f29d357b2dc4cf2b8eb8d98fe9d9ff89f9ea6012970a853c7"},
-    {file = "lazy_object_proxy-1.4.1-cp34-cp34m-win_amd64.whl", hash = "sha256:7c7f1ec07b227bdc561299fa2328e85000f90179a2f44ea30579d38e037cb3d4"},
-    {file = "lazy_object_proxy-1.4.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:64483bd7154580158ea90de5b8e5e6fc29a16a9b4db24f10193f0c1ae3f9d1ea"},
-    {file = "lazy_object_proxy-1.4.1-cp35-cp35m-win32.whl", hash = "sha256:e408f1eacc0a68fed0c08da45f31d0ebb38079f043328dce69ff133b95c29dc1"},
-    {file = "lazy_object_proxy-1.4.1-cp35-cp35m-win_amd64.whl", hash = "sha256:7c8b1ba1e15c10b13cad4171cfa77f5bb5ec2580abc5a353907780805ebe158e"},
-    {file = "lazy_object_proxy-1.4.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:c10d29019927301d524a22ced72706380de7cfc50f767217485a912b4c8bd82a"},
-    {file = "lazy_object_proxy-1.4.1-cp36-cp36m-win32.whl", hash = "sha256:3f447aff8bc61ca8b42b73304f6a44fa0d915487de144652816f950a3f1ab821"},
-    {file = "lazy_object_proxy-1.4.1-cp36-cp36m-win_amd64.whl", hash = "sha256:dd6e2b598849b3d7aee2295ac765a578879830fb8966f70be8cd472e6069932e"},
-    {file = "lazy_object_proxy-1.4.1-cp37-cp37m-macosx_10_13_x86_64.whl", hash = "sha256:6f72d42b0d04bfee2397aa1862262654b56922c20a9bb66bb76b6f0e5e4f9229"},
-    {file = "lazy_object_proxy-1.4.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:bfab710d859c779f273cc48fb86af38d6e9210f38287df0069a63e40b45a2f5c"},
-    {file = "lazy_object_proxy-1.4.1-cp37-cp37m-win32.whl", hash = "sha256:8559b94b823f85342e10d3d9ca4ba5478168e1ac5658a8a2f18c991ba9c52c20"},
-    {file = "lazy_object_proxy-1.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:159a745e61422217881c4de71f9eafd9d703b93af95618635849fe469a283661"},
+    {file = "lazy-object-proxy-1.6.0.tar.gz", hash = "sha256:489000d368377571c6f982fba6497f2aa13c6d1facc40660963da62f5c379726"},
+    {file = "lazy_object_proxy-1.6.0-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:c6938967f8528b3668622a9ed3b31d145fab161a32f5891ea7b84f6b790be05b"},
+    {file = "lazy_object_proxy-1.6.0-cp27-cp27m-win32.whl", hash = "sha256:ebfd274dcd5133e0afae738e6d9da4323c3eb021b3e13052d8cbd0e457b1256e"},
+    {file = "lazy_object_proxy-1.6.0-cp27-cp27m-win_amd64.whl", hash = "sha256:ed361bb83436f117f9917d282a456f9e5009ea12fd6de8742d1a4752c3017e93"},
+    {file = "lazy_object_proxy-1.6.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:d900d949b707778696fdf01036f58c9876a0d8bfe116e8d220cfd4b15f14e741"},
+    {file = "lazy_object_proxy-1.6.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:5743a5ab42ae40caa8421b320ebf3a998f89c85cdc8376d6b2e00bd12bd1b587"},
+    {file = "lazy_object_proxy-1.6.0-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:bf34e368e8dd976423396555078def5cfc3039ebc6fc06d1ae2c5a65eebbcde4"},
+    {file = "lazy_object_proxy-1.6.0-cp36-cp36m-win32.whl", hash = "sha256:b579f8acbf2bdd9ea200b1d5dea36abd93cabf56cf626ab9c744a432e15c815f"},
+    {file = "lazy_object_proxy-1.6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:4f60460e9f1eb632584c9685bccea152f4ac2130e299784dbaf9fae9f49891b3"},
+    {file = "lazy_object_proxy-1.6.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:d7124f52f3bd259f510651450e18e0fd081ed82f3c08541dffc7b94b883aa981"},
+    {file = "lazy_object_proxy-1.6.0-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:22ddd618cefe54305df49e4c069fa65715be4ad0e78e8d252a33debf00f6ede2"},
+    {file = "lazy_object_proxy-1.6.0-cp37-cp37m-win32.whl", hash = "sha256:9d397bf41caad3f489e10774667310d73cb9c4258e9aed94b9ec734b34b495fd"},
+    {file = "lazy_object_proxy-1.6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:24a5045889cc2729033b3e604d496c2b6f588c754f7a62027ad4437a7ecc4837"},
+    {file = "lazy_object_proxy-1.6.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:17e0967ba374fc24141738c69736da90e94419338fd4c7c7bef01ee26b339653"},
+    {file = "lazy_object_proxy-1.6.0-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:410283732af311b51b837894fa2f24f2c0039aa7f220135192b38fcc42bd43d3"},
+    {file = "lazy_object_proxy-1.6.0-cp38-cp38-win32.whl", hash = "sha256:85fb7608121fd5621cc4377a8961d0b32ccf84a7285b4f1d21988b2eae2868e8"},
+    {file = "lazy_object_proxy-1.6.0-cp38-cp38-win_amd64.whl", hash = "sha256:d1c2676e3d840852a2de7c7d5d76407c772927addff8d742b9808fe0afccebdf"},
+    {file = "lazy_object_proxy-1.6.0-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:b865b01a2e7f96db0c5d12cfea590f98d8c5ba64ad222300d93ce6ff9138bcad"},
+    {file = "lazy_object_proxy-1.6.0-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:4732c765372bd78a2d6b2150a6e99d00a78ec963375f236979c0626b97ed8e43"},
+    {file = "lazy_object_proxy-1.6.0-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:9698110e36e2df951c7c36b6729e96429c9c32b3331989ef19976592c5f3c77a"},
+    {file = "lazy_object_proxy-1.6.0-cp39-cp39-win32.whl", hash = "sha256:1fee665d2638491f4d6e55bd483e15ef21f6c8c2095f235fef72601021e64f61"},
+    {file = "lazy_object_proxy-1.6.0-cp39-cp39-win_amd64.whl", hash = "sha256:f5144c75445ae3ca2057faac03fda5a902eff196702b0a24daf1d6ce0650514b"},
 ]
 mccabe = [
     {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"},
     {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"},
 ]
-more-itertools = [
-    {file = "more-itertools-8.3.0.tar.gz", hash = "sha256:558bb897a2232f5e4f8e2399089e35aecb746e1f9191b6584a151647e89267be"},
-    {file = "more_itertools-8.3.0-py3-none-any.whl", hash = "sha256:7818f596b1e87be009031c7653d01acc46ed422e6656b394b0f765ce66ed4982"},
-]
 numpy = [
-    {file = "numpy-1.18.4-cp35-cp35m-macosx_10_9_intel.whl", hash = "sha256:efdba339fffb0e80fcc19524e4fdbda2e2b5772ea46720c44eaac28096d60720"},
-    {file = "numpy-1.18.4-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:2b573fcf6f9863ce746e4ad00ac18a948978bb3781cffa4305134d31801f3e26"},
-    {file = "numpy-1.18.4-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:3f0dae97e1126f529ebb66f3c63514a0f72a177b90d56e4bce8a0b5def34627a"},
-    {file = "numpy-1.18.4-cp35-cp35m-win32.whl", hash = "sha256:dccd380d8e025c867ddcb2f84b439722cf1f23f3a319381eac45fd077dee7170"},
-    {file = "numpy-1.18.4-cp35-cp35m-win_amd64.whl", hash = "sha256:02ec9582808c4e48be4e93cd629c855e644882faf704bc2bd6bbf58c08a2a897"},
-    {file = "numpy-1.18.4-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:904b513ab8fbcbdb062bed1ce2f794ab20208a1b01ce9bd90776c6c7e7257032"},
-    {file = "numpy-1.18.4-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:e22cd0f72fc931d6abc69dc7764484ee20c6a60b0d0fee9ce0426029b1c1bdae"},
-    {file = "numpy-1.18.4-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:2466fbcf23711ebc5daa61d28ced319a6159b260a18839993d871096d66b93f7"},
-    {file = "numpy-1.18.4-cp36-cp36m-win32.whl", hash = "sha256:00d7b54c025601e28f468953d065b9b121ddca7fff30bed7be082d3656dd798d"},
-    {file = "numpy-1.18.4-cp36-cp36m-win_amd64.whl", hash = "sha256:7d59f21e43bbfd9a10953a7e26b35b6849d888fc5a331fa84a2d9c37bd9fe2a2"},
-    {file = "numpy-1.18.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:efb7ac5572c9a57159cf92c508aad9f856f1cb8e8302d7fdb99061dbe52d712c"},
-    {file = "numpy-1.18.4-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:0e6f72f7bb08f2f350ed4408bb7acdc0daba637e73bce9f5ea2b207039f3af88"},
-    {file = "numpy-1.18.4-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:9933b81fecbe935e6a7dc89cbd2b99fea1bf362f2790daf9422a7bb1dc3c3085"},
-    {file = "numpy-1.18.4-cp37-cp37m-win32.whl", hash = "sha256:96dd36f5cdde152fd6977d1bbc0f0561bccffecfde63cd397c8e6033eb66baba"},
-    {file = "numpy-1.18.4-cp37-cp37m-win_amd64.whl", hash = "sha256:57aea170fb23b1fd54fa537359d90d383d9bf5937ee54ae8045a723caa5e0961"},
-    {file = "numpy-1.18.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ed722aefb0ebffd10b32e67f48e8ac4c5c4cf5d3a785024fdf0e9eb17529cd9d"},
-    {file = "numpy-1.18.4-cp38-cp38-manylinux1_i686.whl", hash = "sha256:50fb72bcbc2cf11e066579cb53c4ca8ac0227abb512b6cbc1faa02d1595a2a5d"},
-    {file = "numpy-1.18.4-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:709c2999b6bd36cdaf85cf888d8512da7433529f14a3689d6e37ab5242e7add5"},
-    {file = "numpy-1.18.4-cp38-cp38-win32.whl", hash = "sha256:f22273dd6a403ed870207b853a856ff6327d5cbce7a835dfa0645b3fc00273ec"},
-    {file = "numpy-1.18.4-cp38-cp38-win_amd64.whl", hash = "sha256:1be2e96314a66f5f1ce7764274327fd4fb9da58584eaff00b5a5221edefee7d6"},
-    {file = "numpy-1.18.4.zip", hash = "sha256:bbcc85aaf4cd84ba057decaead058f43191cc0e30d6bc5d44fe336dc3d3f4509"},
+    {file = "numpy-1.21.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:52a664323273c08f3b473548bf87c8145b7513afd63e4ebba8496ecd3853df13"},
+    {file = "numpy-1.21.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51a7b9db0a2941434cd930dacaafe0fc9da8f3d6157f9d12f761bbde93f46218"},
+    {file = "numpy-1.21.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:9f2dc79c093f6c5113718d3d90c283f11463d77daa4e83aeeac088ec6a0bda52"},
+    {file = "numpy-1.21.2-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:a55e4d81c4260386f71d22294795c87609164e22b28ba0d435850fbdf82fc0c5"},
+    {file = "numpy-1.21.2-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:426a00b68b0d21f2deb2ace3c6d677e611ad5a612d2c76494e24a562a930c254"},
+    {file = "numpy-1.21.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:298156f4d3d46815eaf0fcf0a03f9625fc7631692bd1ad851517ab93c3168fc6"},
+    {file = "numpy-1.21.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:09858463db6dd9f78b2a1a05c93f3b33d4f65975771e90d2cf7aadb7c2f66edf"},
+    {file = "numpy-1.21.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:805459ad8baaf815883d0d6f86e45b3b0b67d823a8f3fa39b1ed9c45eaf5edf1"},
+    {file = "numpy-1.21.2-cp37-cp37m-win32.whl", hash = "sha256:f545c082eeb09ae678dd451a1b1dbf17babd8a0d7adea02897a76e639afca310"},
+    {file = "numpy-1.21.2-cp37-cp37m-win_amd64.whl", hash = "sha256:b160b9a99ecc6559d9e6d461b95c8eec21461b332f80267ad2c10394b9503496"},
+    {file = "numpy-1.21.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:a5109345f5ce7ddb3840f5970de71c34a0ff7fceb133c9441283bb8250f532a3"},
+    {file = "numpy-1.21.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:209666ce9d4a817e8a4597cd475b71b4878a85fa4b8db41d79fdb4fdee01dde2"},
+    {file = "numpy-1.21.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c01b59b33c7c3ba90744f2c695be571a3bd40ab2ba7f3d169ffa6db3cfba614f"},
+    {file = "numpy-1.21.2-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:e42029e184008a5fd3d819323345e25e2337b0ac7f5c135b7623308530209d57"},
+    {file = "numpy-1.21.2-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:7fdc7689daf3b845934d67cb221ba8d250fdca20ac0334fea32f7091b93f00d3"},
+    {file = "numpy-1.21.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:550564024dc5ceee9421a86fc0fb378aa9d222d4d0f858f6669eff7410c89bef"},
+    {file = "numpy-1.21.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bf75d5825ef47aa51d669b03ce635ecb84d69311e05eccea083f31c7570c9931"},
+    {file = "numpy-1.21.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:a9da45b748caad72ea4a4ed57e9cd382089f33c5ec330a804eb420a496fa760f"},
+    {file = "numpy-1.21.2-cp38-cp38-win32.whl", hash = "sha256:e167b9805de54367dcb2043519382be541117503ce99e3291cc9b41ca0a83557"},
+    {file = "numpy-1.21.2-cp38-cp38-win_amd64.whl", hash = "sha256:466e682264b14982012887e90346d33435c984b7fead7b85e634903795c8fdb0"},
+    {file = "numpy-1.21.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:dd0e3651d210068d13e18503d75aaa45656eef51ef0b261f891788589db2cc38"},
+    {file = "numpy-1.21.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:92a0ab128b07799dd5b9077a9af075a63467d03ebac6f8a93e6440abfea4120d"},
+    {file = "numpy-1.21.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:fde50062d67d805bc96f1a9ecc0d37bfc2a8f02b937d2c50824d186aa91f2419"},
+    {file = "numpy-1.21.2-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:640c1ccfd56724f2955c237b6ccce2e5b8607c3bc1cc51d3933b8c48d1da3723"},
+    {file = "numpy-1.21.2-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:5de64950137f3a50b76ce93556db392e8f1f954c2d8207f78a92d1f79aa9f737"},
+    {file = "numpy-1.21.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b342064e647d099ca765f19672696ad50c953cac95b566af1492fd142283580f"},
+    {file = "numpy-1.21.2-cp39-cp39-win32.whl", hash = "sha256:30fc68307c0155d2a75ad19844224be0f2c6f06572d958db4e2053f816b859ad"},
+    {file = "numpy-1.21.2-cp39-cp39-win_amd64.whl", hash = "sha256:b5e8590b9245803c849e09bae070a8e1ff444f45e3f0bed558dd722119eea724"},
+    {file = "numpy-1.21.2-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d96a6a7d74af56feb11e9a443150216578ea07b7450f7c05df40eec90af7f4a7"},
+    {file = "numpy-1.21.2.zip", hash = "sha256:423216d8afc5923b15df86037c6053bf030d15cc9e3224206ef868c2d63dd6dc"},
 ]
 openpyxl = [
-    {file = "openpyxl-3.0.5-py2.py3-none-any.whl", hash = "sha256:f7d666b569f729257082cf7ddc56262431878f602dcc2bc3980775c59439cdab"},
-    {file = "openpyxl-3.0.5.tar.gz", hash = "sha256:18e11f9a650128a12580a58e3daba14e00a11d9e907c554a17ea016bf1a2c71b"},
+    {file = "openpyxl-3.0.7-py2.py3-none-any.whl", hash = "sha256:46af4eaf201a89b610fcca177eed957635f88770a5462fb6aae4a2a52b0ff516"},
+    {file = "openpyxl-3.0.7.tar.gz", hash = "sha256:6456a3b472e1ef0facb1129f3c6ef00713cebf62e736cd7a75bcc3247432f251"},
 ]
 packaging = [
-    {file = "packaging-20.4-py2.py3-none-any.whl", hash = "sha256:998416ba6962ae7fbd6596850b80e17859a5753ba17c32284f67bfff33784181"},
-    {file = "packaging-20.4.tar.gz", hash = "sha256:4357f74f47b9c12db93624a82154e9b120fa8293699949152b22065d556079f8"},
+    {file = "packaging-21.0-py3-none-any.whl", hash = "sha256:c86254f9220d55e31cc94d69bade760f0847da8000def4dfe1c6b872fd14ff14"},
+    {file = "packaging-21.0.tar.gz", hash = "sha256:7dc96269f53a4ccec5c0670940a4281106dd0bb343f47b7471f779df49c2fbe7"},
 ]
 pandas = [
-    {file = "pandas-1.0.3-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:d234bcf669e8b4d6cbcd99e3ce7a8918414520aeb113e2a81aeb02d0a533d7f7"},
-    {file = "pandas-1.0.3-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:ca84a44cf727f211752e91eab2d1c6c1ab0f0540d5636a8382a3af428542826e"},
-    {file = "pandas-1.0.3-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:1fa4bae1a6784aa550a1c9e168422798104a85bf9c77a1063ea77ee6f8452e3a"},
-    {file = "pandas-1.0.3-cp36-cp36m-win32.whl", hash = "sha256:863c3e4b7ae550749a0bb77fa22e601a36df9d2905afef34a6965bed092ba9e5"},
-    {file = "pandas-1.0.3-cp36-cp36m-win_amd64.whl", hash = "sha256:a210c91a02ec5ff05617a298ad6f137b9f6f5771bf31f2d6b6367d7f71486639"},
-    {file = "pandas-1.0.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:11c7cb654cd3a0e9c54d81761b5920cdc86b373510d829461d8f2ed6d5905266"},
-    {file = "pandas-1.0.3-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:6597df07ea361231e60c00692d8a8099b519ed741c04e65821e632bc9ccb924c"},
-    {file = "pandas-1.0.3-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:743bba36e99d4440403beb45a6f4f3a667c090c00394c176092b0b910666189b"},
-    {file = "pandas-1.0.3-cp37-cp37m-win32.whl", hash = "sha256:07c1b58936b80eafdfe694ce964ac21567b80a48d972879a359b3ebb2ea76835"},
-    {file = "pandas-1.0.3-cp37-cp37m-win_amd64.whl", hash = "sha256:12f492dd840e9db1688126216706aa2d1fcd3f4df68a195f9479272d50054645"},
-    {file = "pandas-1.0.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0ebe327fb088df4d06145227a4aa0998e4f80a9e6aed4b61c1f303bdfdf7c722"},
-    {file = "pandas-1.0.3-cp38-cp38-manylinux1_i686.whl", hash = "sha256:858a0d890d957ae62338624e4aeaf1de436dba2c2c0772570a686eaca8b4fc85"},
-    {file = "pandas-1.0.3-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:387dc7b3c0424327fe3218f81e05fc27832772a5dffbed385013161be58df90b"},
-    {file = "pandas-1.0.3-cp38-cp38-win32.whl", hash = "sha256:167a1315367cea6ec6a5e11e791d9604f8e03f95b57ad227409de35cf850c9c5"},
-    {file = "pandas-1.0.3-cp38-cp38-win_amd64.whl", hash = "sha256:1a7c56f1df8d5ad8571fa251b864231f26b47b59cbe41aa5c0983d17dbb7a8e4"},
-    {file = "pandas-1.0.3.tar.gz", hash = "sha256:32f42e322fb903d0e189a4c10b75ba70d90958cc4f66a1781ed027f1a1d14586"},
+    {file = "pandas-1.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:ba7ceb8abc6dbdb1e34612d1173d61e4941f1a1eb7e6f703b2633134ae6a6c89"},
+    {file = "pandas-1.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fcb71b1935249de80e3a808227189eee381d4d74a31760ced2df21eedc92a8e3"},
+    {file = "pandas-1.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa54dc1d3e5d004a09ab0b1751473698011ddf03e14f1f59b84ad9a6ac630975"},
+    {file = "pandas-1.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:34ced9ce5d5b17b556486da7256961b55b471d64a8990b56e67a84ebeb259416"},
+    {file = "pandas-1.3.2-cp37-cp37m-win32.whl", hash = "sha256:a56246de744baf646d1f3e050c4653d632bc9cd2e0605f41051fea59980e880a"},
+    {file = "pandas-1.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:53b17e4debba26b7446b1e4795c19f94f0c715e288e08145e44bdd2865e819b3"},
+    {file = "pandas-1.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f07a9745ca075ae73a5ce116f5e58f691c0dc9de0bff163527858459df5c176f"},
+    {file = "pandas-1.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c9e8e0ce5284ebebe110efd652c164ed6eab77f5de4c3533abc756302ee77765"},
+    {file = "pandas-1.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:59a78d7066d1c921a77e3306aa0ebf6e55396c097d5dfcc4df8defe3dcecb735"},
+    {file = "pandas-1.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:132def05e73d292c949b02e7ef873debb77acc44a8b119d215921046f0c3a91d"},
+    {file = "pandas-1.3.2-cp38-cp38-win32.whl", hash = "sha256:69e1b2f5811f46827722fd641fdaeedb26002bd1e504eacc7a8ec36bdc25393e"},
+    {file = "pandas-1.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:7996d311413379136baf0f3cf2a10e331697657c87ced3f17ac7c77f77fe34a3"},
+    {file = "pandas-1.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1738154049062156429a5cf2fd79a69c9f3fa4f231346a7ec6fd156cd1a9a621"},
+    {file = "pandas-1.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cce01f6d655b4add966fcd36c32c5d1fe84628e200626b3f5e2f40db2d16a0f"},
+    {file = "pandas-1.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1099e2a0cd3a01ec62cca183fc1555833a2d43764950ef8cb5948c8abfc51014"},
+    {file = "pandas-1.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0cd5776be891331a3e6b425b5abeab9596abea18435c5982191356f9b24ae731"},
+    {file = "pandas-1.3.2-cp39-cp39-win32.whl", hash = "sha256:66a95361b81b4ba04b699ecd2416b0591f40cd1e24c60a8bfe0d19009cfa575a"},
+    {file = "pandas-1.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:89f40e5d21814192802421df809f948247d39ffe171e45fe2ab4abf7bd4279d8"},
+    {file = "pandas-1.3.2.tar.gz", hash = "sha256:cbcb84d63867af3411fa063af3de64902665bb5b3d40b25b2059e40603594e87"},
 ]
 pathspec = [
-    {file = "pathspec-0.8.0-py2.py3-none-any.whl", hash = "sha256:7d91249d21749788d07a2d0f94147accd8f845507400749ea19c1ec9054a12b0"},
-    {file = "pathspec-0.8.0.tar.gz", hash = "sha256:da45173eb3a6f2a5a487efba21f050af2b41948be6ab52b6a1e3ff22bb8b7061"},
+    {file = "pathspec-0.9.0-py2.py3-none-any.whl", hash = "sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a"},
+    {file = "pathspec-0.9.0.tar.gz", hash = "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1"},
+]
+platformdirs = [
+    {file = "platformdirs-2.3.0-py3-none-any.whl", hash = "sha256:8003ac87717ae2c7ee1ea5a84a1a61e87f3fbd16eb5aadba194ea30a9019f648"},
+    {file = "platformdirs-2.3.0.tar.gz", hash = "sha256:15b056538719b1c94bdaccb29e5f81879c7f7f0f4a153f46086d155dffcd4f0f"},
 ]
 pluggy = [
-    {file = "pluggy-0.13.1-py2.py3-none-any.whl", hash = "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d"},
-    {file = "pluggy-0.13.1.tar.gz", hash = "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0"},
+    {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"},
+    {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"},
 ]
 prompt-toolkit = [
-    {file = "prompt_toolkit-3.0.8-py3-none-any.whl", hash = "sha256:7debb9a521e0b1ee7d2fe96ee4bd60ef03c6492784de0547337ca4433e46aa63"},
-    {file = "prompt_toolkit-3.0.8.tar.gz", hash = "sha256:25c95d2ac813909f813c93fde734b6e44406d1477a9faef7c915ff37d39c0a8c"},
+    {file = "prompt_toolkit-3.0.20-py3-none-any.whl", hash = "sha256:6076e46efae19b1e0ca1ec003ed37a933dc94b4d20f486235d436e64771dcd5c"},
+    {file = "prompt_toolkit-3.0.20.tar.gz", hash = "sha256:eb71d5a6b72ce6db177af4a7d4d7085b99756bf656d98ffcc4fecd36850eea6c"},
 ]
 psycopg2 = [
-    {file = "psycopg2-2.8.5-cp27-cp27m-win32.whl", hash = "sha256:a0984ff49e176062fcdc8a5a2a670c9bb1704a2f69548bce8f8a7bad41c661bf"},
-    {file = "psycopg2-2.8.5-cp27-cp27m-win_amd64.whl", hash = "sha256:acf56d564e443e3dea152efe972b1434058244298a94348fc518d6dd6a9fb0bb"},
-    {file = "psycopg2-2.8.5-cp34-cp34m-win32.whl", hash = "sha256:440a3ea2c955e89321a138eb7582aa1d22fe286c7d65e26a2c5411af0a88ae72"},
-    {file = "psycopg2-2.8.5-cp34-cp34m-win_amd64.whl", hash = "sha256:6b306dae53ec7f4f67a10942cf8ac85de930ea90e9903e2df4001f69b7833f7e"},
-    {file = "psycopg2-2.8.5-cp35-cp35m-win32.whl", hash = "sha256:d3b29d717d39d3580efd760a9a46a7418408acebbb784717c90d708c9ed5f055"},
-    {file = "psycopg2-2.8.5-cp35-cp35m-win_amd64.whl", hash = "sha256:6a471d4d2a6f14c97a882e8d3124869bc623f3df6177eefe02994ea41fd45b52"},
-    {file = "psycopg2-2.8.5-cp36-cp36m-win32.whl", hash = "sha256:27c633f2d5db0fc27b51f1b08f410715b59fa3802987aec91aeb8f562724e95c"},
-    {file = "psycopg2-2.8.5-cp36-cp36m-win_amd64.whl", hash = "sha256:2df2bf1b87305bd95eb3ac666ee1f00a9c83d10927b8144e8e39644218f4cf81"},
-    {file = "psycopg2-2.8.5-cp37-cp37m-win32.whl", hash = "sha256:ac5b23d0199c012ad91ed1bbb971b7666da651c6371529b1be8cbe2a7bf3c3a9"},
-    {file = "psycopg2-2.8.5-cp37-cp37m-win_amd64.whl", hash = "sha256:2c0afb40cfb4d53487ee2ebe128649028c9a78d2476d14a67781e45dc287f080"},
-    {file = "psycopg2-2.8.5-cp38-cp38-win32.whl", hash = "sha256:2327bf42c1744a434ed8ed0bbaa9168cac7ee5a22a9001f6fc85c33b8a4a14b7"},
-    {file = "psycopg2-2.8.5-cp38-cp38-win_amd64.whl", hash = "sha256:132efc7ee46a763e68a815f4d26223d9c679953cd190f1f218187cb60decf535"},
-    {file = "psycopg2-2.8.5.tar.gz", hash = "sha256:f7d46240f7a1ae1dd95aab38bd74f7428d46531f69219954266d669da60c0818"},
+    {file = "psycopg2-2.9.1-cp36-cp36m-win32.whl", hash = "sha256:7f91312f065df517187134cce8e395ab37f5b601a42446bdc0f0d51773621854"},
+    {file = "psycopg2-2.9.1-cp36-cp36m-win_amd64.whl", hash = "sha256:830c8e8dddab6b6716a4bf73a09910c7954a92f40cf1d1e702fb93c8a919cc56"},
+    {file = "psycopg2-2.9.1-cp37-cp37m-win32.whl", hash = "sha256:89409d369f4882c47f7ea20c42c5046879ce22c1e4ea20ef3b00a4dfc0a7f188"},
+    {file = "psycopg2-2.9.1-cp37-cp37m-win_amd64.whl", hash = "sha256:7640e1e4d72444ef012e275e7b53204d7fab341fb22bc76057ede22fe6860b25"},
+    {file = "psycopg2-2.9.1-cp38-cp38-win32.whl", hash = "sha256:079d97fc22de90da1d370c90583659a9f9a6ee4007355f5825e5f1c70dffc1fa"},
+    {file = "psycopg2-2.9.1-cp38-cp38-win_amd64.whl", hash = "sha256:2c992196719fadda59f72d44603ee1a2fdcc67de097eea38d41c7ad9ad246e62"},
+    {file = "psycopg2-2.9.1-cp39-cp39-win32.whl", hash = "sha256:2087013c159a73e09713294a44d0c8008204d06326006b7f652bef5ace66eebb"},
+    {file = "psycopg2-2.9.1-cp39-cp39-win_amd64.whl", hash = "sha256:bf35a25f1aaa8a3781195595577fcbb59934856ee46b4f252f56ad12b8043bcf"},
+    {file = "psycopg2-2.9.1.tar.gz", hash = "sha256:de5303a6f1d0a7a34b9d40e4d3bef684ccc44a49bbe3eb85e3c0bffb4a131b7c"},
 ]
 py = [
-    {file = "py-1.8.1-py2.py3-none-any.whl", hash = "sha256:c20fdd83a5dbc0af9efd622bee9a5564e278f6380fffcacc43ba6f43db2813b0"},
-    {file = "py-1.8.1.tar.gz", hash = "sha256:5e27081401262157467ad6e7f851b7aa402c5852dbcb3dae06768434de5752aa"},
+    {file = "py-1.10.0-py2.py3-none-any.whl", hash = "sha256:3b80836aa6d1feeaa108e046da6423ab8f6ceda6468545ae8d02d9d58d18818a"},
+    {file = "py-1.10.0.tar.gz", hash = "sha256:21b81bda15b66ef5e1a777a21c4dcd9c20ad3efd0b3f817e7a809035269e1bd3"},
 ]
 pycodestyle = [
-    {file = "pycodestyle-2.5.0-py2.py3-none-any.whl", hash = "sha256:95a2219d12372f05704562a14ec30bc76b05a5b297b21a5dfe3f6fac3491ae56"},
-    {file = "pycodestyle-2.5.0.tar.gz", hash = "sha256:e40a936c9a450ad81df37f549d676d127b1b66000a6c500caa2b085bc0ca976c"},
+    {file = "pycodestyle-2.7.0-py2.py3-none-any.whl", hash = "sha256:514f76d918fcc0b55c6680472f0a37970994e07bbb80725808c17089be302068"},
+    {file = "pycodestyle-2.7.0.tar.gz", hash = "sha256:c389c1d06bf7904078ca03399a4816f974a1d590090fecea0c63ec26ebaf1cef"},
 ]
 pyflakes = [
-    {file = "pyflakes-2.1.1-py2.py3-none-any.whl", hash = "sha256:17dbeb2e3f4d772725c777fabc446d5634d1038f234e77343108ce445ea69ce0"},
-    {file = "pyflakes-2.1.1.tar.gz", hash = "sha256:d976835886f8c5b31d47970ed689944a0262b5f3afa00a5a7b4dc81e5449f8a2"},
+    {file = "pyflakes-2.3.1-py2.py3-none-any.whl", hash = "sha256:7893783d01b8a89811dd72d7dfd4d84ff098e5eed95cfa8905b22bbffe52efc3"},
+    {file = "pyflakes-2.3.1.tar.gz", hash = "sha256:f5bc8ecabc05bb9d291eb5203d6810b49040f6ff446a756326104746cc00c1db"},
 ]
 pyjwt = [
-    {file = "PyJWT-1.7.1-py2.py3-none-any.whl", hash = "sha256:5c6eca3c2940464d106b99ba83b00c6add741c9becaec087fb7ccdefea71350e"},
-    {file = "PyJWT-1.7.1.tar.gz", hash = "sha256:8d59a976fb773f3e6a39c85636357c4f0e242707394cadadd9814f5cbaa20e96"},
+    {file = "PyJWT-2.1.0-py3-none-any.whl", hash = "sha256:934d73fbba91b0483d3857d1aff50e96b2a892384ee2c17417ed3203f173fca1"},
+    {file = "PyJWT-2.1.0.tar.gz", hash = "sha256:fba44e7898bbca160a2b2b501f492824fc8382485d3a6f11ba5d0c1937ce6130"},
 ]
 pylint = [
-    {file = "pylint-2.5.2-py3-none-any.whl", hash = "sha256:dd506acce0427e9e08fb87274bcaa953d38b50a58207170dbf5b36cf3e16957b"},
-    {file = "pylint-2.5.2.tar.gz", hash = "sha256:b95e31850f3af163c2283ed40432f053acbc8fc6eba6a069cb518d9dbf71848c"},
+    {file = "pylint-2.10.2-py3-none-any.whl", hash = "sha256:e178e96b6ba171f8ef51fbce9ca30931e6acbea4a155074d80cc081596c9e852"},
+    {file = "pylint-2.10.2.tar.gz", hash = "sha256:6758cce3ddbab60c52b57dcc07f0c5d779e5daf0cf50f6faacbef1d3ea62d2a1"},
 ]
 pyparsing = [
     {file = "pyparsing-2.4.7-py2.py3-none-any.whl", hash = "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"},
     {file = "pyparsing-2.4.7.tar.gz", hash = "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1"},
 ]
 pytest = [
-    {file = "pytest-5.4.2-py3-none-any.whl", hash = "sha256:95c710d0a72d91c13fae35dce195633c929c3792f54125919847fdcdf7caa0d3"},
-    {file = "pytest-5.4.2.tar.gz", hash = "sha256:eb2b5e935f6a019317e455b6da83dd8650ac9ffd2ee73a7b657a30873d67a698"},
+    {file = "pytest-6.2.5-py3-none-any.whl", hash = "sha256:7310f8d27bc79ced999e760ca304d69f6ba6c6649c0b60fb0e04a4a77cacc134"},
+    {file = "pytest-6.2.5.tar.gz", hash = "sha256:131b36680866a76e6781d13f101efb86cf674ebb9762eb70d3082b6f29889e89"},
 ]
 pytest-celery = [
-    {file = "pytest-celery-0.0.0a1.tar.gz", hash = "sha256:3e0e0817c2d3f2870dafebd915bf13100fc12920b5d42dfe5fdc35844fe42e62"},
-    {file = "pytest_celery-0.0.0a1-py2.py3-none-any.whl", hash = "sha256:2fa8d0ae0d573fb2ee51902bfa220e891044eafadbfb132b28b7087295c3004f"},
+    {file = "pytest-celery-0.0.0.tar.gz", hash = "sha256:cfd060fc32676afa1e4f51b2938f903f7f75d952186b8c6cf631628c4088f406"},
+    {file = "pytest_celery-0.0.0-py2.py3-none-any.whl", hash = "sha256:63dec132df3a839226ecb003ffdbb0c2cb88dd328550957e979c942766578060"},
 ]
 pytest-cov = [
-    {file = "pytest-cov-2.11.1.tar.gz", hash = "sha256:359952d9d39b9f822d9d29324483e7ba04a3a17dd7d05aa6beb7ea01e359e5f7"},
-    {file = "pytest_cov-2.11.1-py2.py3-none-any.whl", hash = "sha256:bdb9fdb0b85a7cc825269a4c56b48ccaa5c7e365054b6038772c32ddcdc969da"},
+    {file = "pytest-cov-2.12.1.tar.gz", hash = "sha256:261ceeb8c227b726249b376b8526b600f38667ee314f910353fa318caa01f4d7"},
+    {file = "pytest_cov-2.12.1-py2.py3-none-any.whl", hash = "sha256:261bb9e47e65bd099c89c3edf92972865210c36813f80ede5277dceb77a4a62a"},
 ]
 pytest-datadir = [
     {file = "pytest-datadir-1.3.1.tar.gz", hash = "sha256:d3af1e738df87515ee509d6135780f25a15959766d9c2b2dbe02bf4fb979cb18"},
@@ -1251,126 +1286,169 @@ pytest-django = [
     {file = "pytest_django-3.10.0-py2.py3-none-any.whl", hash = "sha256:c33e3d3da14d8409b125d825d4e74da17bb252191bf6fc3da6856e27a8b73ea4"},
 ]
 pytest-factoryboy = [
-    {file = "pytest-factoryboy-2.0.3.tar.gz", hash = "sha256:ffef3fb7ddec1299d3df0d334846259023f3d1da5ab887ad880139a8253a5a1a"},
+    {file = "pytest-factoryboy-2.1.0.tar.gz", hash = "sha256:23bc562ab32cc39eddfbbbf70e618a1b30e834a4cfa451c4bedc36216f0a7b19"},
+    {file = "pytest_factoryboy-2.1.0-py3-none-any.whl", hash = "sha256:10c02d2736cb52c7af28065db9617e7f50634e95eaa07eeb9a007026aa3dc0a8"},
 ]
 pytest-mock = [
-    {file = "pytest-mock-3.6.0.tar.gz", hash = "sha256:f7c3d42d6287f4e45846c8231c31902b6fa2bea98735af413a43da4cf5b727f1"},
-    {file = "pytest_mock-3.6.0-py3-none-any.whl", hash = "sha256:952139a535b5b48ac0bb2f90b5dd36b67c7e1ba92601f3a8012678c4bd7f0bcc"},
+    {file = "pytest-mock-3.6.1.tar.gz", hash = "sha256:40217a058c52a63f1042f0784f62009e976ba824c418cced42e88d5f40ab0e62"},
+    {file = "pytest_mock-3.6.1-py3-none-any.whl", hash = "sha256:30c2f2cc9759e76eee674b81ea28c9f0b94f8f0445a1b87762cadf774f0df7e3"},
 ]
 python-dateutil = [
-    {file = "python-dateutil-2.8.1.tar.gz", hash = "sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c"},
-    {file = "python_dateutil-2.8.1-py2.py3-none-any.whl", hash = "sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a"},
+    {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"},
+    {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"},
 ]
 python-decouple = [
-    {file = "python-decouple-3.3.tar.gz", hash = "sha256:55c546b85b0c47a15a47a4312d451a437f7344a9be3e001660bccd93b637de95"},
+    {file = "python-decouple-3.4.tar.gz", hash = "sha256:2e5adb0263a4f963b58d7407c4760a2465d464ee212d733e2a2c179e54c08d8f"},
+    {file = "python_decouple-3.4-py3-none-any.whl", hash = "sha256:a8268466e6389a639a20deab9d880faee186eb1eb6a05e54375bdf158d691981"},
 ]
 pytz = [
-    {file = "pytz-2019.2-py2.py3-none-any.whl", hash = "sha256:c894d57500a4cd2d5c71114aaab77dbab5eabd9022308ce5ac9bb93a60a6f0c7"},
-    {file = "pytz-2019.2.tar.gz", hash = "sha256:26c0b32e437e54a18161324a2fca3c4b9846b74a8dccddd843113109e1116b32"},
+    {file = "pytz-2021.1-py2.py3-none-any.whl", hash = "sha256:eb10ce3e7736052ed3623d49975ce333bcd712c7bb19a58b9e2089d4057d0798"},
+    {file = "pytz-2021.1.tar.gz", hash = "sha256:83a4a90894bf38e243cf052c8b58f381bfe9a7a483f6a9cab140bc7f702ac4da"},
 ]
 pyyaml = [
-    {file = "PyYAML-5.3.1-cp27-cp27m-win32.whl", hash = "sha256:74809a57b329d6cc0fdccee6318f44b9b8649961fa73144a98735b0aaf029f1f"},
-    {file = "PyYAML-5.3.1-cp27-cp27m-win_amd64.whl", hash = "sha256:240097ff019d7c70a4922b6869d8a86407758333f02203e0fc6ff79c5dcede76"},
-    {file = "PyYAML-5.3.1-cp35-cp35m-win32.whl", hash = "sha256:4f4b913ca1a7319b33cfb1369e91e50354d6f07a135f3b901aca02aa95940bd2"},
-    {file = "PyYAML-5.3.1-cp35-cp35m-win_amd64.whl", hash = "sha256:cc8955cfbfc7a115fa81d85284ee61147059a753344bc51098f3ccd69b0d7e0c"},
-    {file = "PyYAML-5.3.1-cp36-cp36m-win32.whl", hash = "sha256:7739fc0fa8205b3ee8808aea45e968bc90082c10aef6ea95e855e10abf4a37b2"},
-    {file = "PyYAML-5.3.1-cp36-cp36m-win_amd64.whl", hash = "sha256:69f00dca373f240f842b2931fb2c7e14ddbacd1397d57157a9b005a6a9942648"},
-    {file = "PyYAML-5.3.1-cp37-cp37m-win32.whl", hash = "sha256:d13155f591e6fcc1ec3b30685d50bf0711574e2c0dfffd7644babf8b5102ca1a"},
-    {file = "PyYAML-5.3.1-cp37-cp37m-win_amd64.whl", hash = "sha256:73f099454b799e05e5ab51423c7bcf361c58d3206fa7b0d555426b1f4d9a3eaf"},
-    {file = "PyYAML-5.3.1-cp38-cp38-win32.whl", hash = "sha256:06a0d7ba600ce0b2d2fe2e78453a470b5a6e000a985dd4a4e54e436cc36b0e97"},
-    {file = "PyYAML-5.3.1-cp38-cp38-win_amd64.whl", hash = "sha256:95f71d2af0ff4227885f7a6605c37fd53d3a106fcab511b8860ecca9fcf400ee"},
-    {file = "PyYAML-5.3.1-cp39-cp39-win32.whl", hash = "sha256:ad9c67312c84def58f3c04504727ca879cb0013b2517c85a9a253f0cb6380c0a"},
-    {file = "PyYAML-5.3.1-cp39-cp39-win_amd64.whl", hash = "sha256:6034f55dab5fea9e53f436aa68fa3ace2634918e8b5994d82f3621c04ff5ed2e"},
-    {file = "PyYAML-5.3.1.tar.gz", hash = "sha256:b8eac752c5e14d3eca0e6dd9199cd627518cb5ec06add0de9d32baeee6fe645d"},
+    {file = "PyYAML-5.4.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:3b2b1824fe7112845700f815ff6a489360226a5609b96ec2190a45e62a9fc922"},
+    {file = "PyYAML-5.4.1-cp27-cp27m-win32.whl", hash = "sha256:129def1b7c1bf22faffd67b8f3724645203b79d8f4cc81f674654d9902cb4393"},
+    {file = "PyYAML-5.4.1-cp27-cp27m-win_amd64.whl", hash = "sha256:4465124ef1b18d9ace298060f4eccc64b0850899ac4ac53294547536533800c8"},
+    {file = "PyYAML-5.4.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:bb4191dfc9306777bc594117aee052446b3fa88737cd13b7188d0e7aa8162185"},
+    {file = "PyYAML-5.4.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:6c78645d400265a062508ae399b60b8c167bf003db364ecb26dcab2bda048253"},
+    {file = "PyYAML-5.4.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:4e0583d24c881e14342eaf4ec5fbc97f934b999a6828693a99157fde912540cc"},
+    {file = "PyYAML-5.4.1-cp36-cp36m-win32.whl", hash = "sha256:3bd0e463264cf257d1ffd2e40223b197271046d09dadf73a0fe82b9c1fc385a5"},
+    {file = "PyYAML-5.4.1-cp36-cp36m-win_amd64.whl", hash = "sha256:e4fac90784481d221a8e4b1162afa7c47ed953be40d31ab4629ae917510051df"},
+    {file = "PyYAML-5.4.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5accb17103e43963b80e6f837831f38d314a0495500067cb25afab2e8d7a4018"},
+    {file = "PyYAML-5.4.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:e1d4970ea66be07ae37a3c2e48b5ec63f7ba6804bdddfdbd3cfd954d25a82e63"},
+    {file = "PyYAML-5.4.1-cp37-cp37m-win32.whl", hash = "sha256:dd5de0646207f053eb0d6c74ae45ba98c3395a571a2891858e87df7c9b9bd51b"},
+    {file = "PyYAML-5.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:08682f6b72c722394747bddaf0aa62277e02557c0fd1c42cb853016a38f8dedf"},
+    {file = "PyYAML-5.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d2d9808ea7b4af864f35ea216be506ecec180628aced0704e34aca0b040ffe46"},
+    {file = "PyYAML-5.4.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:8c1be557ee92a20f184922c7b6424e8ab6691788e6d86137c5d93c1a6ec1b8fb"},
+    {file = "PyYAML-5.4.1-cp38-cp38-win32.whl", hash = "sha256:fa5ae20527d8e831e8230cbffd9f8fe952815b2b7dae6ffec25318803a7528fc"},
+    {file = "PyYAML-5.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:0f5f5786c0e09baddcd8b4b45f20a7b5d61a7e7e99846e3c799b05c7c53fa696"},
+    {file = "PyYAML-5.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:294db365efa064d00b8d1ef65d8ea2c3426ac366c0c4368d930bf1c5fb497f77"},
+    {file = "PyYAML-5.4.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:74c1485f7707cf707a7aef42ef6322b8f97921bd89be2ab6317fd782c2d53183"},
+    {file = "PyYAML-5.4.1-cp39-cp39-win32.whl", hash = "sha256:49d4cdd9065b9b6e206d0595fee27a96b5dd22618e7520c33204a4a3239d5b10"},
+    {file = "PyYAML-5.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:c20cfa2d49991c8b4147af39859b167664f2ad4561704ee74c1de03318e898db"},
+    {file = "PyYAML-5.4.1.tar.gz", hash = "sha256:607774cbba28732bfa802b54baa7484215f530991055bb562efbed5b2f20a45e"},
 ]
 redis = [
     {file = "redis-3.5.3-py2.py3-none-any.whl", hash = "sha256:432b788c4530cfe16d8d943a09d40ca6c16149727e4afe8c2c9d5580c59d9f24"},
     {file = "redis-3.5.3.tar.gz", hash = "sha256:0e7e0cfca8660dea8b7d5cd8c4f6c5e29e11f31158c0b0ae91a397f00e5a05a2"},
 ]
 regex = [
-    {file = "regex-2020.5.7-cp27-cp27m-win32.whl", hash = "sha256:5493a02c1882d2acaaf17be81a3b65408ff541c922bfd002535c5f148aa29f74"},
-    {file = "regex-2020.5.7-cp27-cp27m-win_amd64.whl", hash = "sha256:021a0ae4d2baeeb60a3014805a2096cb329bd6d9f30669b7ad0da51a9cb73349"},
-    {file = "regex-2020.5.7-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:4df91094ced6f53e71f695c909d9bad1cca8761d96fd9f23db12245b5521136e"},
-    {file = "regex-2020.5.7-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:7ce4a213a96d6c25eeae2f7d60d4dad89ac2b8134ec3e69db9bc522e2c0f9388"},
-    {file = "regex-2020.5.7-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:3b059e2476b327b9794c792c855aa05531a3f3044737e455d283c7539bd7534d"},
-    {file = "regex-2020.5.7-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:652ab4836cd5531d64a34403c00ada4077bb91112e8bcdae933e2eae232cf4a8"},
-    {file = "regex-2020.5.7-cp36-cp36m-win32.whl", hash = "sha256:1e2255ae938a36e9bd7db3b93618796d90c07e5f64dd6a6750c55f51f8b76918"},
-    {file = "regex-2020.5.7-cp36-cp36m-win_amd64.whl", hash = "sha256:8127ca2bf9539d6a64d03686fd9e789e8c194fc19af49b69b081f8c7e6ecb1bc"},
-    {file = "regex-2020.5.7-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:f7f2f4226db6acd1da228adf433c5c3792858474e49d80668ea82ac87cf74a03"},
-    {file = "regex-2020.5.7-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:2bc6a17a7fa8afd33c02d51b6f417fc271538990297167f68a98cae1c9e5c945"},
-    {file = "regex-2020.5.7-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:b7c9f65524ff06bf70c945cd8d8d1fd90853e27ccf86026af2afb4d9a63d06b1"},
-    {file = "regex-2020.5.7-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:fa09da4af4e5b15c0e8b4986a083f3fd159302ea115a6cc0649cd163435538b8"},
-    {file = "regex-2020.5.7-cp37-cp37m-win32.whl", hash = "sha256:669a8d46764a09f198f2e91fc0d5acdac8e6b620376757a04682846ae28879c4"},
-    {file = "regex-2020.5.7-cp37-cp37m-win_amd64.whl", hash = "sha256:b5b5b2e95f761a88d4c93691716ce01dc55f288a153face1654f868a8034f494"},
-    {file = "regex-2020.5.7-cp38-cp38-manylinux1_i686.whl", hash = "sha256:0ff50843535593ee93acab662663cb2f52af8e31c3f525f630f1dc6156247938"},
-    {file = "regex-2020.5.7-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:1b17bf37c2aefc4cac8436971fe6ee52542ae4225cfc7762017f7e97a63ca998"},
-    {file = "regex-2020.5.7-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:04d6e948ef34d3eac133bedc0098364a9e635a7914f050edb61272d2ddae3608"},
-    {file = "regex-2020.5.7-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:5b741ecc3ad3e463d2ba32dce512b412c319993c1bb3d999be49e6092a769fb2"},
-    {file = "regex-2020.5.7-cp38-cp38-win32.whl", hash = "sha256:099568b372bda492be09c4f291b398475587d49937c659824f891182df728cdf"},
-    {file = "regex-2020.5.7-cp38-cp38-win_amd64.whl", hash = "sha256:3ab5e41c4ed7cd4fa426c50add2892eb0f04ae4e73162155cd668257d02259dd"},
-    {file = "regex-2020.5.7.tar.gz", hash = "sha256:73a10404867b835f1b8a64253e4621908f0d71150eb4e97ab2e7e441b53e9451"},
+    {file = "regex-2021.8.28-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9d05ad5367c90814099000442b2125535e9d77581855b9bee8780f1b41f2b1a2"},
+    {file = "regex-2021.8.28-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f3bf1bc02bc421047bfec3343729c4bbbea42605bcfd6d6bfe2c07ade8b12d2a"},
+    {file = "regex-2021.8.28-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5f6a808044faae658f546dd5f525e921de9fa409de7a5570865467f03a626fc0"},
+    {file = "regex-2021.8.28-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:a617593aeacc7a691cc4af4a4410031654f2909053bd8c8e7db837f179a630eb"},
+    {file = "regex-2021.8.28-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:79aef6b5cd41feff359acaf98e040844613ff5298d0d19c455b3d9ae0bc8c35a"},
+    {file = "regex-2021.8.28-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:0fc1f8f06977c2d4f5e3d3f0d4a08089be783973fc6b6e278bde01f0544ff308"},
+    {file = "regex-2021.8.28-cp310-cp310-win32.whl", hash = "sha256:6eebf512aa90751d5ef6a7c2ac9d60113f32e86e5687326a50d7686e309f66ed"},
+    {file = "regex-2021.8.28-cp310-cp310-win_amd64.whl", hash = "sha256:ac88856a8cbccfc14f1b2d0b829af354cc1743cb375e7f04251ae73b2af6adf8"},
+    {file = "regex-2021.8.28-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:c206587c83e795d417ed3adc8453a791f6d36b67c81416676cad053b4104152c"},
+    {file = "regex-2021.8.28-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8690ed94481f219a7a967c118abaf71ccc440f69acd583cab721b90eeedb77c"},
+    {file = "regex-2021.8.28-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:328a1fad67445550b982caa2a2a850da5989fd6595e858f02d04636e7f8b0b13"},
+    {file = "regex-2021.8.28-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:c7cb4c512d2d3b0870e00fbbac2f291d4b4bf2634d59a31176a87afe2777c6f0"},
+    {file = "regex-2021.8.28-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:66256b6391c057305e5ae9209941ef63c33a476b73772ca967d4a2df70520ec1"},
+    {file = "regex-2021.8.28-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:8e44769068d33e0ea6ccdf4b84d80c5afffe5207aa4d1881a629cf0ef3ec398f"},
+    {file = "regex-2021.8.28-cp36-cp36m-win32.whl", hash = "sha256:08d74bfaa4c7731b8dac0a992c63673a2782758f7cfad34cf9c1b9184f911354"},
+    {file = "regex-2021.8.28-cp36-cp36m-win_amd64.whl", hash = "sha256:abb48494d88e8a82601af905143e0de838c776c1241d92021e9256d5515b3645"},
+    {file = "regex-2021.8.28-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b4c220a1fe0d2c622493b0a1fd48f8f991998fb447d3cd368033a4b86cf1127a"},
+    {file = "regex-2021.8.28-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d4a332404baa6665b54e5d283b4262f41f2103c255897084ec8f5487ce7b9e8e"},
+    {file = "regex-2021.8.28-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c61dcc1cf9fd165127a2853e2c31eb4fb961a4f26b394ac9fe5669c7a6592892"},
+    {file = "regex-2021.8.28-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:ee329d0387b5b41a5dddbb6243a21cb7896587a651bebb957e2d2bb8b63c0791"},
+    {file = "regex-2021.8.28-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f60667673ff9c249709160529ab39667d1ae9fd38634e006bec95611f632e759"},
+    {file = "regex-2021.8.28-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:b844fb09bd9936ed158ff9df0ab601e2045b316b17aa8b931857365ea8586906"},
+    {file = "regex-2021.8.28-cp37-cp37m-win32.whl", hash = "sha256:4cde065ab33bcaab774d84096fae266d9301d1a2f5519d7bd58fc55274afbf7a"},
+    {file = "regex-2021.8.28-cp37-cp37m-win_amd64.whl", hash = "sha256:1413b5022ed6ac0d504ba425ef02549a57d0f4276de58e3ab7e82437892704fc"},
+    {file = "regex-2021.8.28-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ed4b50355b066796dacdd1cf538f2ce57275d001838f9b132fab80b75e8c84dd"},
+    {file = "regex-2021.8.28-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28fc475f560d8f67cc8767b94db4c9440210f6958495aeae70fac8faec631797"},
+    {file = "regex-2021.8.28-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bdc178caebd0f338d57ae445ef8e9b737ddf8fbc3ea187603f65aec5b041248f"},
+    {file = "regex-2021.8.28-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:999ad08220467b6ad4bd3dd34e65329dd5d0df9b31e47106105e407954965256"},
+    {file = "regex-2021.8.28-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:808ee5834e06f57978da3e003ad9d6292de69d2bf6263662a1a8ae30788e080b"},
+    {file = "regex-2021.8.28-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d5111d4c843d80202e62b4fdbb4920db1dcee4f9366d6b03294f45ed7b18b42e"},
+    {file = "regex-2021.8.28-cp38-cp38-win32.whl", hash = "sha256:473858730ef6d6ff7f7d5f19452184cd0caa062a20047f6d6f3e135a4648865d"},
+    {file = "regex-2021.8.28-cp38-cp38-win_amd64.whl", hash = "sha256:31a99a4796bf5aefc8351e98507b09e1b09115574f7c9dbb9cf2111f7220d2e2"},
+    {file = "regex-2021.8.28-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:04f6b9749e335bb0d2f68c707f23bb1773c3fb6ecd10edf0f04df12a8920d468"},
+    {file = "regex-2021.8.28-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9b006628fe43aa69259ec04ca258d88ed19b64791693df59c422b607b6ece8bb"},
+    {file = "regex-2021.8.28-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:121f4b3185feaade3f85f70294aef3f777199e9b5c0c0245c774ae884b110a2d"},
+    {file = "regex-2021.8.28-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:a577a21de2ef8059b58f79ff76a4da81c45a75fe0bfb09bc8b7bb4293fa18983"},
+    {file = "regex-2021.8.28-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1743345e30917e8c574f273f51679c294effba6ad372db1967852f12c76759d8"},
+    {file = "regex-2021.8.28-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:e1e8406b895aba6caa63d9fd1b6b1700d7e4825f78ccb1e5260551d168db38ed"},
+    {file = "regex-2021.8.28-cp39-cp39-win32.whl", hash = "sha256:ed283ab3a01d8b53de3a05bfdf4473ae24e43caee7dcb5584e86f3f3e5ab4374"},
+    {file = "regex-2021.8.28-cp39-cp39-win_amd64.whl", hash = "sha256:610b690b406653c84b7cb6091facb3033500ee81089867ee7d59e675f9ca2b73"},
+    {file = "regex-2021.8.28.tar.gz", hash = "sha256:f585cbbeecb35f35609edccb95efd95a3e35824cd7752b586503f7e6087303f1"},
 ]
 requests = [
-    {file = "requests-2.24.0-py2.py3-none-any.whl", hash = "sha256:fe75cc94a9443b9246fc7049224f75604b113c36acb93f87b80ed42c44cbb898"},
-    {file = "requests-2.24.0.tar.gz", hash = "sha256:b3559a131db72c33ee969480840fff4bb6dd111de7dd27c8ee1f820f4f00231b"},
+    {file = "requests-2.26.0-py2.py3-none-any.whl", hash = "sha256:6c1246513ecd5ecd4528a0906f910e8f0f9c6b8ec72030dc9fd154dc1a6efd24"},
+    {file = "requests-2.26.0.tar.gz", hash = "sha256:b8aa58f8cf793ffd8782d3d8cb19e66ef36f7aba4353eec859e74678b01b07a7"},
 ]
 requests-toolbelt = [
     {file = "requests-toolbelt-0.9.1.tar.gz", hash = "sha256:968089d4584ad4ad7c171454f0a5c6dac23971e9472521ea3b6d49d610aa6fc0"},
     {file = "requests_toolbelt-0.9.1-py2.py3-none-any.whl", hash = "sha256:380606e1d10dc85c3bd47bf5a6095f815ec007be7a8b69c878507068df059e6f"},
 ]
 six = [
-    {file = "six-1.12.0-py2.py3-none-any.whl", hash = "sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c"},
-    {file = "six-1.12.0.tar.gz", hash = "sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73"},
+    {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
+    {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
 ]
 sqlparse = [
-    {file = "sqlparse-0.3.0-py2.py3-none-any.whl", hash = "sha256:40afe6b8d4b1117e7dff5504d7a8ce07d9a1b15aeeade8a2d10f130a834f8177"},
-    {file = "sqlparse-0.3.0.tar.gz", hash = "sha256:7c3dca29c022744e95b547e867cee89f4fce4373f3549ccd8797d8eb52cdb873"},
+    {file = "sqlparse-0.4.1-py3-none-any.whl", hash = "sha256:017cde379adbd6a1f15a61873f43e8274179378e95ef3fede90b5aa64d304ed0"},
+    {file = "sqlparse-0.4.1.tar.gz", hash = "sha256:0f91fd2e829c44362cbcfab3e9ae12e22badaa8a29ad5ff599f9ec109f0454e8"},
 ]
 text-unidecode = [
     {file = "text-unidecode-1.3.tar.gz", hash = "sha256:bad6603bb14d279193107714b288be206cac565dfa49aa5b105294dd5c4aab93"},
     {file = "text_unidecode-1.3-py2.py3-none-any.whl", hash = "sha256:1311f10e8b895935241623731c2ba64f4c455287888b18189350b67134a822e8"},
 ]
 toml = [
-    {file = "toml-0.10.0-py2.7.egg", hash = "sha256:f1db651f9657708513243e61e6cc67d101a39bad662eaa9b5546f789338e07a3"},
-    {file = "toml-0.10.0-py2.py3-none-any.whl", hash = "sha256:235682dd292d5899d361a811df37e04a8828a5b1da3115886b73cf81ebc9100e"},
-    {file = "toml-0.10.0.tar.gz", hash = "sha256:229f81c57791a41d65e399fc06bf0848bab550a9dfd5ed66df18ce5f05e73d5c"},
+    {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"},
+    {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"},
 ]
 typed-ast = [
-    {file = "typed_ast-1.4.0-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:262c247a82d005e43b5b7f69aff746370538e176131c32dda9cb0f324d27141e"},
-    {file = "typed_ast-1.4.0-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:71211d26ffd12d63a83e079ff258ac9d56a1376a25bc80b1cdcdf601b855b90b"},
-    {file = "typed_ast-1.4.0-cp35-cp35m-win32.whl", hash = "sha256:630968c5cdee51a11c05a30453f8cd65e0cc1d2ad0d9192819df9978984529f4"},
-    {file = "typed_ast-1.4.0-cp35-cp35m-win_amd64.whl", hash = "sha256:ffde2fbfad571af120fcbfbbc61c72469e72f550d676c3342492a9dfdefb8f12"},
-    {file = "typed_ast-1.4.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:4e0b70c6fc4d010f8107726af5fd37921b666f5b31d9331f0bd24ad9a088e631"},
-    {file = "typed_ast-1.4.0-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:bc6c7d3fa1325a0c6613512a093bc2a2a15aeec350451cbdf9e1d4bffe3e3233"},
-    {file = "typed_ast-1.4.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:cc34a6f5b426748a507dd5d1de4c1978f2eb5626d51326e43280941206c209e1"},
-    {file = "typed_ast-1.4.0-cp36-cp36m-win32.whl", hash = "sha256:d896919306dd0aa22d0132f62a1b78d11aaf4c9fc5b3410d3c666b818191630a"},
-    {file = "typed_ast-1.4.0-cp36-cp36m-win_amd64.whl", hash = "sha256:354c16e5babd09f5cb0ee000d54cfa38401d8b8891eefa878ac772f827181a3c"},
-    {file = "typed_ast-1.4.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:95bd11af7eafc16e829af2d3df510cecfd4387f6453355188342c3e79a2ec87a"},
-    {file = "typed_ast-1.4.0-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:18511a0b3e7922276346bcb47e2ef9f38fb90fd31cb9223eed42c85d1312344e"},
-    {file = "typed_ast-1.4.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:d7c45933b1bdfaf9f36c579671fec15d25b06c8398f113dab64c18ed1adda01d"},
-    {file = "typed_ast-1.4.0-cp37-cp37m-win32.whl", hash = "sha256:d755f03c1e4a51e9b24d899561fec4ccaf51f210d52abdf8c07ee2849b212a36"},
-    {file = "typed_ast-1.4.0-cp37-cp37m-win_amd64.whl", hash = "sha256:2b907eb046d049bcd9892e3076c7a6456c93a25bebfe554e931620c90e6a25b0"},
-    {file = "typed_ast-1.4.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:fdc1c9bbf79510b76408840e009ed65958feba92a88833cdceecff93ae8fff66"},
-    {file = "typed_ast-1.4.0-cp38-cp38-manylinux1_i686.whl", hash = "sha256:7954560051331d003b4e2b3eb822d9dd2e376fa4f6d98fee32f452f52dd6ebb2"},
-    {file = "typed_ast-1.4.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:48e5b1e71f25cfdef98b013263a88d7145879fbb2d5185f2a0c79fa7ebbeae47"},
-    {file = "typed_ast-1.4.0-cp38-cp38-win32.whl", hash = "sha256:1170afa46a3799e18b4c977777ce137bb53c7485379d9706af8a59f2ea1aa161"},
-    {file = "typed_ast-1.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:838997f4310012cf2e1ad3803bce2f3402e9ffb71ded61b5ee22617b3a7f6b6e"},
-    {file = "typed_ast-1.4.0.tar.gz", hash = "sha256:66480f95b8167c9c5c5c87f32cf437d585937970f3fc24386f313a4c97b44e34"},
+    {file = "typed_ast-1.4.3-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:2068531575a125b87a41802130fa7e29f26c09a2833fea68d9a40cf33902eba6"},
+    {file = "typed_ast-1.4.3-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:c907f561b1e83e93fad565bac5ba9c22d96a54e7ea0267c708bffe863cbe4075"},
+    {file = "typed_ast-1.4.3-cp35-cp35m-manylinux2014_aarch64.whl", hash = "sha256:1b3ead4a96c9101bef08f9f7d1217c096f31667617b58de957f690c92378b528"},
+    {file = "typed_ast-1.4.3-cp35-cp35m-win32.whl", hash = "sha256:dde816ca9dac1d9c01dd504ea5967821606f02e510438120091b84e852367428"},
+    {file = "typed_ast-1.4.3-cp35-cp35m-win_amd64.whl", hash = "sha256:777a26c84bea6cd934422ac2e3b78863a37017618b6e5c08f92ef69853e765d3"},
+    {file = "typed_ast-1.4.3-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f8afcf15cc511ada719a88e013cec87c11aff7b91f019295eb4530f96fe5ef2f"},
+    {file = "typed_ast-1.4.3-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:52b1eb8c83f178ab787f3a4283f68258525f8d70f778a2f6dd54d3b5e5fb4341"},
+    {file = "typed_ast-1.4.3-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:01ae5f73431d21eead5015997ab41afa53aa1fbe252f9da060be5dad2c730ace"},
+    {file = "typed_ast-1.4.3-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:c190f0899e9f9f8b6b7863debfb739abcb21a5c054f911ca3596d12b8a4c4c7f"},
+    {file = "typed_ast-1.4.3-cp36-cp36m-win32.whl", hash = "sha256:398e44cd480f4d2b7ee8d98385ca104e35c81525dd98c519acff1b79bdaac363"},
+    {file = "typed_ast-1.4.3-cp36-cp36m-win_amd64.whl", hash = "sha256:bff6ad71c81b3bba8fa35f0f1921fb24ff4476235a6e94a26ada2e54370e6da7"},
+    {file = "typed_ast-1.4.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0fb71b8c643187d7492c1f8352f2c15b4c4af3f6338f21681d3681b3dc31a266"},
+    {file = "typed_ast-1.4.3-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:760ad187b1041a154f0e4d0f6aae3e40fdb51d6de16e5c99aedadd9246450e9e"},
+    {file = "typed_ast-1.4.3-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:5feca99c17af94057417d744607b82dd0a664fd5e4ca98061480fd8b14b18d04"},
+    {file = "typed_ast-1.4.3-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:95431a26309a21874005845c21118c83991c63ea800dd44843e42a916aec5899"},
+    {file = "typed_ast-1.4.3-cp37-cp37m-win32.whl", hash = "sha256:aee0c1256be6c07bd3e1263ff920c325b59849dc95392a05f258bb9b259cf39c"},
+    {file = "typed_ast-1.4.3-cp37-cp37m-win_amd64.whl", hash = "sha256:9ad2c92ec681e02baf81fdfa056fe0d818645efa9af1f1cd5fd6f1bd2bdfd805"},
+    {file = "typed_ast-1.4.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b36b4f3920103a25e1d5d024d155c504080959582b928e91cb608a65c3a49e1a"},
+    {file = "typed_ast-1.4.3-cp38-cp38-manylinux1_i686.whl", hash = "sha256:067a74454df670dcaa4e59349a2e5c81e567d8d65458d480a5b3dfecec08c5ff"},
+    {file = "typed_ast-1.4.3-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7538e495704e2ccda9b234b82423a4038f324f3a10c43bc088a1636180f11a41"},
+    {file = "typed_ast-1.4.3-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:af3d4a73793725138d6b334d9d247ce7e5f084d96284ed23f22ee626a7b88e39"},
+    {file = "typed_ast-1.4.3-cp38-cp38-win32.whl", hash = "sha256:f2362f3cb0f3172c42938946dbc5b7843c2a28aec307c49100c8b38764eb6927"},
+    {file = "typed_ast-1.4.3-cp38-cp38-win_amd64.whl", hash = "sha256:dd4a21253f42b8d2b48410cb31fe501d32f8b9fbeb1f55063ad102fe9c425e40"},
+    {file = "typed_ast-1.4.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f328adcfebed9f11301eaedfa48e15bdece9b519fb27e6a8c01aa52a17ec31b3"},
+    {file = "typed_ast-1.4.3-cp39-cp39-manylinux1_i686.whl", hash = "sha256:2c726c276d09fc5c414693a2de063f521052d9ea7c240ce553316f70656c84d4"},
+    {file = "typed_ast-1.4.3-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:cae53c389825d3b46fb37538441f75d6aecc4174f615d048321b716df2757fb0"},
+    {file = "typed_ast-1.4.3-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:b9574c6f03f685070d859e75c7f9eeca02d6933273b5e69572e5ff9d5e3931c3"},
+    {file = "typed_ast-1.4.3-cp39-cp39-win32.whl", hash = "sha256:209596a4ec71d990d71d5e0d312ac935d86930e6eecff6ccc7007fe54d703808"},
+    {file = "typed_ast-1.4.3-cp39-cp39-win_amd64.whl", hash = "sha256:9c6d1a54552b5330bc657b7ef0eae25d00ba7ffe85d9ea8ae6540d2197a3788c"},
+    {file = "typed_ast-1.4.3.tar.gz", hash = "sha256:fb1bbeac803adea29cedd70781399c99138358c26d05fcbd23c13016b7f5ec65"},
+]
+unidecode = [
+    {file = "Unidecode-1.3.3-py3-none-any.whl", hash = "sha256:a5a8a4b6fb033724ffba8502af2e65ca5bfc3dd53762dedaafe4b0134ad42e3c"},
+    {file = "Unidecode-1.3.3.tar.gz", hash = "sha256:8521f2853fd250891dc27d156a9d30e61c4e76319da963c4a1c27083a909ac30"},
 ]
 urllib3 = [
-    {file = "urllib3-1.25.11-py2.py3-none-any.whl", hash = "sha256:f5321fbe4bf3fefa0efd0bfe7fb14e90909eb62a48ccda331726b4319897dd5e"},
-    {file = "urllib3-1.25.11.tar.gz", hash = "sha256:8d7eaa5a82a1cac232164990f04874c594c9453ec55eef02eab885aa02fc17a2"},
+    {file = "urllib3-1.26.6-py2.py3-none-any.whl", hash = "sha256:39fb8672126159acb139a7718dd10806104dec1e2f0f6c88aab05d17df10c8d4"},
+    {file = "urllib3-1.26.6.tar.gz", hash = "sha256:f57b4c16c62fa2760b7e3d97c35b255512fb6b59a259730f36ba32ce9f8e342f"},
 ]
 vine = [
     {file = "vine-5.0.0-py2.py3-none-any.whl", hash = "sha256:4c9dceab6f76ed92105027c49c823800dd33cacce13bdedc5b914e3514b7fb30"},
     {file = "vine-5.0.0.tar.gz", hash = "sha256:7d3b1624a953da82ef63462013bbd271d3eb75751489f9807598e8f340bd637e"},
 ]
 wcwidth = [
-    {file = "wcwidth-0.1.9-py2.py3-none-any.whl", hash = "sha256:cafe2186b3c009a04067022ce1dcd79cb38d8d65ee4f4791b8888d6599d1bbe1"},
-    {file = "wcwidth-0.1.9.tar.gz", hash = "sha256:ee73862862a156bf77ff92b09034fc4825dd3af9cf81bc5b360668d425f3c5f1"},
+    {file = "wcwidth-0.2.5-py2.py3-none-any.whl", hash = "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784"},
+    {file = "wcwidth-0.2.5.tar.gz", hash = "sha256:c4d647b99872929fdb7bdcaa4fbe7f01413ed3d98077df798530e5b04f116c83"},
 ]
 wrapt = [
-    {file = "wrapt-1.11.2.tar.gz", hash = "sha256:565a021fd19419476b9362b05eeaa094178de64f8361e44468f9e9d7843901e1"},
+    {file = "wrapt-1.12.1.tar.gz", hash = "sha256:b62ffa81fb85f4332a4f609cab4ac40709470da05643a082ec1eb88e6d9b97d7"},
 ]
 xlrd = [
     {file = "xlrd-1.2.0-py2.py3-none-any.whl", hash = "sha256:e551fb498759fa3a5384a94ccd4c3c02eb7c00ea424426e212ac0c57be9dfbde"},
diff --git a/server/pyproject.toml b/server/pyproject.toml
index dcc15be03fe3a7f3576459c60b5cc12e482d725a..50f2a94d2f664b4159bc548b1473d8e894046a64 100644
--- a/server/pyproject.toml
+++ b/server/pyproject.toml
@@ -18,12 +18,13 @@ psycopg2 = "^2.8.5"
 pandas = "^1.0.3"
 factory-boy = "^2.12.0"
 drf-nested-routers = "^0.91"
-bioblend = "^0.14.0"
+bioblend = "^0.16.0"
 celery = "^5.0.2"
 redis = "^3.5.3"
 openpyxl = "^3.0.5"
 xlrd = "^1.2.0"
 xlwt = "^1.3.0"
+Unidecode = "^1.3.3"
 
 [tool.poetry.dev-dependencies]
 black = "^19.10b0"
diff --git a/server/server/settings.py b/server/server/settings.py
index 24bf7a0aff50f3cc7ed37a6932fedcb2d6034393..c7e8c27d901ef7b5ba8e399caa6b784ad293908d 100644
--- a/server/server/settings.py
+++ b/server/server/settings.py
@@ -30,16 +30,18 @@ else:
 SECRET_KEY = config(
     "SECRET_KEY", default="g1ptpec(cxezd+w1hz$$5!j7y9n563!^z7=_bnulq$3qd#+0id"
 )
-
+HOSTLABEL = config("HOSTLABEL", default="local")
 GALAXY_API_KEY = config("GALAXY_API_KEY", default="")
 GALAXY_BASE_URL = config("GALAXY_BASE_URL", default="localhost:9090")
 
 # SECURITY WARNING: don't run with debug turned on in production!
-DEBUG = config("DEBUG", default=True, cast=bool)
+DEBUG = config("DEBUG", default=False, cast=bool)
 
 ALLOWED_HOSTS = [s.strip() for s in config("ALLOWED_HOSTS", default="*").split(",")]
 
 
+DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
+
 # Application definition
 
 INSTALLED_APPS = [
@@ -195,7 +197,7 @@ REDIS_PORT = 6379
 REDIS_HOST = config("REDIS_HOST", default="redis://redis")
 CELERY_BROKER_URL = f"{REDIS_HOST}:{REDIS_PORT}"
 CELERY_RESULT_BACKEND = f"{REDIS_HOST}:{REDIS_PORT}"
-
+CELERY_TASK_TIME_LIMIT = 30 * 60
 # CELERY_BEAT_SCHEDULE = {
 #     "sample_task": {
 #         "task": "server.tasks.sample_task",
diff --git a/server/server/urls.py b/server/server/urls.py
index 1a4ecfe8de8e55143f88069bf2f5f1984d170d1e..987f8598ec27c6ff70e551e15403cb22d6064393 100644
--- a/server/server/urls.py
+++ b/server/server/urls.py
@@ -15,7 +15,7 @@ Including another URLconf
 """
 from django.contrib import admin
 from django.urls import path, include
-from rest_framework_simplejwt.views import TokenObtainPairView, TokenRefreshView  # new
+from rest_framework_simplejwt.views import TokenObtainPairView, TokenRefreshView
 
 urlpatterns = [path("admin/", admin.site.urls)]