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&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>></span> or <span><</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>…</span></td> + <td><span>…</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>…</span></td> + <td><span>…</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: '…', + value: 'phenotypeI', + }, + { + text: 'NameOfPhenotypeN', + value: 'phenotypeN', + }, + + { + text: 'NameOfCovariate1', + value: 'covariate', + helpText: + 'Covariate values must be written US/UK format: dots instead of comma', + }, + { + text: '…', + 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: '…', + covariateI: '…', + phenotypeN: 24, + covariate: 10, + covariateN: 5, + }, + { + mouseId: '2', + ccMother: 'CC001', + ccFather: 'CC001', + sex: 'M', + phenotype: 8.732, + phenotypeN: 12, + covariate: 2, + covariateN: 18, + phenotypeI: '…', + covariateI: '…', + }, + { + mouseId: '3', + ccMother: 'CC002', + ccFather: 'CC002', + sex: 'M', + phenotype: 7.238, + phenotypeN: 17, + covariate: 5, + covariateN: 31, + phenotypeI: '…', + covariateI: '…', + }, + ], + 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>© {{ 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)]