Browse Source

add of newsletter component; use message and add user help

Jérôme BUISINE 1 year ago
parent
commit
03cd473729

+ 1 - 1
config.messagesId.js

@@ -17,7 +17,7 @@ export const EXPERIMENT = {
   DATA: 'EXPERIMENT_DATA',
 
   // An experiment was validated
-  VALIDATED: 'EXPERIMENT_VALIDATED',
+  VALIDATED: 'EXPERIMENT_VALIDATED'
 
 }
 

+ 4 - 0
server/database/controllers/Data.js

@@ -33,4 +33,8 @@ export default class Data {
   static find(dataId) {
     return DataModel.findById(dataId)
   }
+
+  static findOne(data) {
+    return DataModel.findOne(data)
+  }
 }

+ 81 - 0
server/routes/experimentCheck.js

@@ -0,0 +1,81 @@
+'use strict'
+
+import express from 'express'
+import boom from '@hapi/boom'
+
+import { TEST_MODE } from '../../config'
+import DataController from '../database/controllers/Data'
+import { asyncMiddleware, checkRequiredParameters } from '../functions'
+
+const router = express.Router()
+
+/**
+ * @api {post} /experimentCheck /experimentCheck
+ * @apiVersion 0.1.11
+ * @apiName experimentCheck
+ * @apiGroup API
+ *
+ * @apiDescription Collect user's data
+ *
+ * @apiParam {String} msgId The type of message to store
+ * @apiParam {any} Any data that needs to be stored
+ *
+ * @apiExample Usage example
+ * curl -i -L -H "Content-Type: application/json" -X POST "https://diran.univ-littoral.fr/api/experimentCheck" -d {"msgId":"test","msg":{}}
+ *
+ * @apiSuccessExample {string} Success response example
+ * HTTP/1.1 204 OK /api/experimentCheck
+ *
+ * @apiError (Error 4xx) 400_[1] Missing parameter(s)
+ * @apiErrorExample {json} Missing parameter
+ * HTTP/1.1 400 Bad Request
+ * {
+ *   "message": "Missing parameter(s). Required parameters : msgId, msg."
+ * }
+ *
+ * @apiError (Error 4xx) 400_[2] Invalid query parameter
+ * @apiErrorExample {json} Invalid query parameter(s)
+ * HTTP/1.1 400 Bad Request
+ * {
+ *   "message": "Invalid body parameter(s).",
+ *   "data": [
+ *     "\"msgId\" must be a string."
+ *   ]
+ * }
+ *
+ */
+
+router.post('/', asyncMiddleware(async (req, res) => {
+  // Check the request contains all the required body parameters
+  const b = req.body
+  checkRequiredParameters(['msgId', 'msg'], b)
+
+  const {
+    msgId,
+    msg,
+    userId = null,
+    experimentId = null
+  } = req.body
+
+  console.log('Trying to find data')
+
+  // Check there is no errors with parameters
+  if (typeof b.msgId !== 'string')
+    throw boom.badRequest('Invalid body parameter(s).', ['"msgId" must be a string.'])
+
+  let status = 204
+
+  console.log('Trying to find data')
+  // Add data to the database
+  if (!TEST_MODE) {
+    console.log({ msgId, msg, userId, experimentId })
+    const findDoc = await DataController.findOne({ msgId, msg, userId, experimentId })
+    console.log(findDoc)
+    if (findDoc)
+      status = 208
+  }
+
+  res.status(status).send()
+}))
+
+export default router

+ 2 - 0
server/routes/index.js

@@ -8,6 +8,7 @@ import getImageExtracts from './getImageExtracts'
 import ping from './ping'
 import dataCollect from './dataCollect'
 import experimentCollect from './experimentCollect'
+import experimentCheck from './experimentCheck'
 
 const router = express.Router()
 
@@ -17,6 +18,7 @@ router.use('/getImage', getImage)
 router.use('/getImageExtracts', getImageExtracts)
 router.use('/dataCollect', dataCollect)
 router.use('/experimentCollect', experimentCollect)
+router.use('/experimentCheck', experimentCheck)
 router.use('/ping', ping)
 
 export default router

+ 130 - 0
src/components/ExperimentsComponents/Newsletter.vue

@@ -0,0 +1,130 @@
+<template>
+  <v-flex xs12>
+    <div style="margin-top:10%">
+      <p style="font-size: 1.4em;">Si vous souhaitez être informé des résultats non nomminatifs de ces recherches vous pouvez, sans obligation, laisser votre adresse mail, elle ne sera utilisée que pour vous permettre d'accéder aux résultats de l'étude une fois analysés.</p>
+
+      <v-text-field
+        v-model="email"
+        :rules="emailRules"
+        label="Votre adresse email"
+        required
+      />
+
+      <v-btn @click="addNewsletter" color="success" large>Valider mon adresse</v-btn>
+    </div>
+
+    <div class="text-center">
+      <v-dialog
+        v-model="dialogError"
+        width="500"
+      >
+        <v-card>
+          <v-card-title
+            class="headline lighten-2"
+            primary-title
+          >
+            <p style="font-size:0.8em;">L'adresse email saisie n'est pas correcte.</p>
+          </v-card-title>
+
+          <v-divider />
+
+          <v-card-actions>
+            <v-spacer />
+            <v-btn
+              color="#DF0101"
+              text
+              @click="dialogError = false"
+            >
+              Fermer
+            </v-btn>
+          </v-card-actions>
+        </v-card>
+      </v-dialog>
+    </div>
+
+    <div class="text-center">
+      <v-dialog
+        v-model="dialogSuccess"
+        width="500"
+      >
+        <v-card>
+          <v-card-title
+            class="headline lighten-4"
+            primary-title
+          >
+            <p style="font-size:0.8em;">Votre adresse email a bien été ajoutée à la newsletter.</p>
+          </v-card-title>
+          <!-- <v-card-text>
+          </v-card-text> -->
+
+          <v-divider />
+
+          <v-card-actions>
+            <v-spacer />
+            <v-btn
+              color="success"
+              text
+              @click="dialogSuccess = false"
+            >
+              Ok
+            </v-btn>
+          </v-card-actions>
+        </v-card>
+      </v-dialog>
+    </div>
+  </v-flex>
+</template>
+
+<script>
+import { NEWS as newsletter } from '@/../config.messagesId'
+import { mapActions } from 'vuex'
+
+export default {
+  name: 'Newsletter',
+  data() {
+    return {
+      emailRules: [
+        v => !!v || 'L\'adresse email est obligatoire',
+        v => /.+@.+/.test(v) || 'L\'email doit être valide'
+      ],
+      email: '',
+      dialogError: false,
+      dialogSuccess: false
+    }
+  },
+  methods: {
+    ...mapActions(['sendMessage', 'checkExistData']),
+
+    async addNewsletter() {
+      // need to check if mail is already there or not
+      const data = {
+        msgId: newsletter,
+        msg: {
+          experimentName: this.experimentName,
+          sceneName: this.sceneName,
+          userEmail: this.email
+        }
+      }
+
+      if (this.validEmail(this.email)) {
+        const findDoc = await this.checkExistData(data)
+
+        console.log(findDoc)
+
+        if (findDoc === 204) {
+          console.log('Create new email input')
+          this.sendMessage(data)
+          this.dialogSuccess = true
+        }
+      }
+      else {
+        this.dialogError = true
+      }
+    },
+    validEmail: function (email) {
+      let re = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
+      return re.test(email)
+    }
+  }
+}
+</script>

+ 1 - 0
src/functions.js

@@ -4,6 +4,7 @@ export const API_ROUTES = {
 
   dataCollect: `${API_PREFIX}/dataCollect`,
   experimentCollect: `${API_PREFIX}/experimentCollect`,
+  experimentCheck: `${API_PREFIX}/experimentCheck`,
 
   listScenes: `${API_PREFIX}/listScenes`,
 

+ 18 - 0
src/store/actions.js

@@ -82,6 +82,24 @@ export default {
     })
   },
 
+  async checkExistData({ state, getters: { getHostURI } }, { msgId, msg = undefined }) {
+    const res = await fetch(`${getHostURI}${API_ROUTES.experimentCheck}`, {
+      method: 'POST',
+      headers: {
+        'Content-Type': 'application/json'
+      },
+      body: JSON.stringify({
+        uuid: state.uuid,
+        userId: state.userId,
+        experimentId: state.experimentId,
+        msgId,
+        msg
+      })
+    })
+
+    return res.status
+  },
+
   async loadScenesList({ getters: { isHostConfigured, getHostURI }, commit }) {
     if (!isHostConfigured) throw new Error('Host is not configured.')
 

+ 20 - 6
src/views/ExperimentValidated.vue

@@ -1,8 +1,8 @@
 <template>
-  <div>
-    <h2>"{{ experimentFullName }}"</h2>
+  <div style="text-align:center">
+    <!-- <h2>"{{ experimentFullName }}"</h2> -->
 
-    <v-card>
+    <!-- <v-card>
       <v-card-title primary-title>
         <v-spacer />
         <div class="headline">Experiment validated for the scene "{{ sceneName }}"</div>
@@ -10,7 +10,7 @@
       </v-card-title>
       <v-card-actions>
         <v-spacer />
-        <!-- <v-btn flat exact to="/experiments/">
+        <v-btn flat exact to="/experiments/">
           <v-icon left>home</v-icon>
           Select another experiment
         </v-btn>
@@ -18,7 +18,7 @@
         <v-btn flat exact :to="`/experiments/${experimentName}`">
           <v-icon left>arrow_back</v-icon>
           Go back to scene selection
-        </v-btn> -->
+        </v-btn>
         <v-btn v-if="hasScenesLeft" flat exact :to="`/experiments/${experimentName}/${getRandomScene}`">
           <v-icon left>shuffle</v-icon>
           Continue with a random scene
@@ -26,7 +26,17 @@
         <div v-if="!hasScenesLeft" class="headline">You finished all the scenes, thanks for your contribution!</div>
         <v-spacer />
       </v-card-actions>
-    </v-card>
+    </v-card> -->
+
+    <div style="margin-top:10%">
+      <p style="font-size: 1.4em;">
+        Nous vous remercions d'avoir participé à cette expérience.
+        Elle va nous permettre d'améliorer les calculs d'images.
+      </p>
+    </div>
+
+    <!-- Add of newsletter component -->
+    <Newsletter />
   </div>
 </template>
 
@@ -35,9 +45,13 @@ import { mapActions, mapGetters } from 'vuex'
 import Experiments from '@/router/experiments'
 import { getExperimentSceneList } from '@/config.utils'
 import { rand } from '@/functions'
+import Newsletter from '@/components/ExperimentsComponents/Newsletter.vue'
 
 export default {
   name: 'ExperimentValidated',
+  components: {
+    Newsletter
+  },
   props: {
     experimentName: {
       type: String,

+ 50 - 37
src/views/Experiments/MatchExtractsWithReference.vue

@@ -19,10 +19,10 @@
 
     <template v-slot:content>
       <v-flex v-if="explanation === true || disableStart === true" xs12 sm12>
-        <div style="margin-top:15%">
+        <div style="margin-top:10%">
           <p v-if="disableStart === false && calibrationScene === true" style="font-size: 1.4em;">
             Vous allez voir des images, l'image de droite constitue toujours l'image de référence. Vous devez régler la qualité de l'image de gauche pour qu'elle soit la plus proche de l'image de droite.
-            La première image est constitué de carré gris, c'est une partie de calibration. Si vous souhaitez régler votre écran (contraste, luminosité) vous pouvez le faire maintenant mais il vous est demandé de ne plus changer ce réglage au cours de l'expérience.
+            La première image est constituée de carré gris, c'est une partie de calibration. Si vous souhaitez régler votre écran (contraste, luminosité) vous pouvez le faire maintenant mais il vous est demandé de ne plus changer ce réglage au cours de l'expérience.
             Vous allez ensuite voir des scènes d'image de synthèse. Vous pouvez arrêter l'expérience quand vous souhaitez (ou faire une pause).
           </p>
 
@@ -42,8 +42,33 @@
         </div>
       </v-flex>
 
+      <v-flex v-if="haveHelp === true" xs12 sm12>
+        <div style="margin-top:10%">
+          <p style="font-size: 1.4em;">
+            Cette expérience vous propose le visuel deux images, celle de gauche considérée comme dégradée et celle de gauche, sa référence (image sans dégradation visible).
+
+            <br />
+            Vous devez régler la qualité de l'image de gauche pour qu'elle soit la plus proche de l'image de droite.
+          </p>
+
+          <br />
+          <br />
+
+          <p style="font-size: 1.4em;text-align:left">
+            Pour cela deux actions vous sont proposées :
+            <br />
+            <ul>
+              <li> <strong>clic droit de la souris :</strong> permet d'améliorer la qualité de l'image à l'endroit où de la dégradation vous est encore visible.</li>
+              <li> <strong>clic gauche de la souris :</strong> permet de revenir à une qualité inférieure de l'image si l'amélioration apportée n'était pas nécessaire (aucune amélioration visible apportée après clic droit).</li>
+            </ul>
+          </p>
+
+          <v-btn @click="startExperiment" color="#007acc" large>Continuer l'expérience</v-btn>
+        </div>
+      </v-flex>
+
       <v-flex v-if="haveBreak === true" xs12 sm12>
-        <div style="margin-top:15%">
+        <div style="margin-top:10%">
           <p style="font-size: 1.4em;">
             Nous vous remercions d'avoir participé à cette expérience.
             Elle va nous permettre d'améliorer les calculs d'images. Si vous le souhaitez, vous pouvez revenir sur l'expérience via le <a :href="launcherURI" target="_blank">launcher</a> pour revoir de nouvelles images.
@@ -52,18 +77,8 @@
           <v-btn @click="startExperiment" color="#007acc" large>Continuer l'expérience</v-btn>
         </div>
 
-        <div style="margin-top:15%">
-          <p style="font-size: 1.4em;">Si vous souhaitez être informé des résultats non nomminatifs de ces recherches vous pouvez, sans obligation, laisser votre adresse mail, elle ne sera utilisée que pour vous permettre d'accéder aux résultats de l'étude une fois analysés.</p>
-
-          <v-text-field
-            v-model="email"
-            :rules="emailRules"
-            label="Votre adresse email"
-            required
-          />
-
-          <v-btn @click="finishExperiment" color="success" large disabled>Valider mon adresse</v-btn>
-        </div>
+        <!-- Add of newsletter component -->
+        <Newsletter />
       </v-flex>
 
       <v-flex v-if="runExpe === true" xs12 sm6 :style="{ 'max-width': maxWidth + 'px', 'min-width': maxWidth + 'px', 'margin-right': 20 + 'px' }">
@@ -123,7 +138,10 @@
           label="Ajouter un commentaire ici"
         />
 
-        <v-btn @click="userBreak" color="primary" large right>Arrêter ou faire une pause</v-btn>
+
+        <v-btn @click="userHelp" color="#737373" large right>Comment ça fonctionne ?</v-btn>
+
+        <v-btn @click="userBreak" color="#cc7a00" large right>Arrêter ou faire une pause</v-btn>
 
         <v-btn @click="finishExperiment" color="success" large right>Valider & passer à l'image suivante</v-btn>
       </v-layout>
@@ -138,13 +156,13 @@ import { mapGetters } from 'vuex'
 import ExperimentBlock from '@/components/ExperimentBlock.vue'
 import ExperimentBaseExtracts from '@/mixins/ExperimentBaseExtracts'
 import ExtractConfiguration from '@/components/ExperimentsComponents/ExtractConfiguration.vue'
-
-import { NEWS as newsletter } from '@/../config.messagesId'
+import Newsletter from '@/components/ExperimentsComponents/Newsletter.vue'
 
 export default {
   components: {
     ExperimentBlock,
-    ExtractConfiguration
+    ExtractConfiguration,
+    Newsletter
   },
   mixins: [ExperimentBaseExtracts],
 
@@ -156,14 +174,10 @@ export default {
       launcherURI: null,
       explanation: false,
       haveBreak: false,
+      haveHelp: false,
       calibrationScene: false,
       runExpe: false,
-      disableStart: false,
-      emailRules: [
-        v => !!v || 'L\'adresse email est obligatoire',
-        v => /.+@.+/.test(v) || 'L\'email doit être valide'
-      ],
-      email: ''
+      disableStart: false
     }
   },
   computed: {
@@ -207,16 +221,25 @@ export default {
   },
   methods: {
     startExperiment() {
+      this.runExpe = true
       this.explanation = false
       this.haveBreak = false
-      this.runExpe = true
+      this.haveHelp = false
     },
     userBreak() {
       this.haveBreak = true
       this.explanation = false
       this.runExpe = false
+      this.haveHelp = false
+    },
+    userHelp() {
+      this.haveHelp = true
+      this.haveBreak = false
+      this.explanation = false
+      this.runExpe = false
     },
     loadExperimentState() {
+      this.haveHelp = false
       this.explanation = false
       this.haveBreak = false
       this.runExpe = false
@@ -231,26 +254,16 @@ export default {
     },
     checkWindow() {
       // check window screen size
-      console.log(window.innerWidth, ' ', window.innerHeight)
       if (window.innerWidth < 1920 || window.innerHeight < 900) {
         this.disableStart = true
         this.explanation = true
         this.runExpe = false
         this.haveBreak = false
+        this.haveHelp = false
       }
       else {
         this.disableStart = false
       }
-    },
-    addNewsletter() {
-      this.sendMessage({
-        msgId: newsletter,
-        msg: {
-          experimentName: this.experimentName,
-          sceneName: this.sceneName,
-          userEmail: this.email
-        }
-      })
     }
   }
 }

+ 7 - 121
yarn.lock

@@ -1243,11 +1243,6 @@
   resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d"
   integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==
 
-abbrev@1:
-  version "1.1.1"
-  resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8"
-  integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==
-
 accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.7:
   version "1.3.7"
   resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd"
@@ -3214,7 +3209,7 @@ debug@3.1.0, debug@~3.1.0:
   dependencies:
     ms "2.0.0"
 
-debug@^3.0.0, debug@^3.1.0, debug@^3.1.1, debug@^3.2.5, debug@^3.2.6:
+debug@^3.0.0, debug@^3.1.0, debug@^3.1.1, debug@^3.2.5:
   version "3.2.6"
   resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b"
   integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==
@@ -3394,7 +3389,7 @@ destroy@~1.0.4:
   resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80"
   integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=
 
-detect-libc@^1.0.2, detect-libc@^1.0.3:
+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=
@@ -4644,13 +4639,6 @@ fs-extra@^8.1.0:
     jsonfile "^4.0.0"
     universalify "^0.1.0"
 
-fs-minipass@^1.2.5:
-  version "1.2.7"
-  resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7"
-  integrity sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==
-  dependencies:
-    minipass "^2.6.0"
-
 fs-minipass@^2.0.0:
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb"
@@ -5260,7 +5248,7 @@ human-signals@^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.24, iconv-lite@^0.4.17, iconv-lite@^0.4.24, iconv-lite@^0.4.4:
+iconv-lite@0.4.24, iconv-lite@^0.4.17, 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==
@@ -5299,13 +5287,6 @@ ignore-by-default@^1.0.0:
   resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09"
   integrity sha1-SMptcvbGo68Aqa1K5odr44ieKwk=
 
-ignore-walk@^3.0.1:
-  version "3.0.3"
-  resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.3.tgz#017e2447184bfeade7c238e4aefdd1e8f95b1e37"
-  integrity sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==
-  dependencies:
-    minimatch "^3.0.4"
-
 ignore@^3.3.3, ignore@^3.3.5:
   version "3.3.10"
   resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043"
@@ -6666,14 +6647,6 @@ minimist@^1.2.0:
   resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
   integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=
 
-minipass@^2.6.0, minipass@^2.8.6, minipass@^2.9.0:
-  version "2.9.0"
-  resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6"
-  integrity sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==
-  dependencies:
-    safe-buffer "^5.1.2"
-    yallist "^3.0.0"
-
 minipass@^3.0.0:
   version "3.1.1"
   resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.1.1.tgz#7607ce778472a185ad6d89082aa2070f79cedcd5"
@@ -6681,13 +6654,6 @@ minipass@^3.0.0:
   dependencies:
     yallist "^4.0.0"
 
-minizlib@^1.2.1:
-  version "1.3.3"
-  resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.3.3.tgz#2290de96818a34c29551c8a8d301216bd65a861d"
-  integrity sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==
-  dependencies:
-    minipass "^2.9.0"
-
 minizlib@^2.1.0:
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.0.tgz#fd52c645301ef09a63a2c209697c294c6ce02cf3"
@@ -6906,15 +6872,6 @@ natural-compare@^1.4.0:
   resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
   integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=
 
-needle@^2.2.1:
-  version "2.3.2"
-  resolved "https://registry.yarnpkg.com/needle/-/needle-2.3.2.tgz#3342dea100b7160960a450dc8c22160ac712a528"
-  integrity sha512-DUzITvPVDUy6vczKKYTnWc/pBZ0EnjMJnQ3y+Jo5zfKFimJs7S3HFCxCRZYB9FUZcrzUQr3WsmvZgddMEIZv6w==
-  dependencies:
-    debug "^3.2.6"
-    iconv-lite "^0.4.4"
-    sax "^1.2.4"
-
 negotiator@0.6.2:
   version "0.6.2"
   resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb"
@@ -6992,22 +6949,6 @@ node-libs-browser@^2.2.1:
     util "^0.11.0"
     vm-browserify "^1.0.1"
 
-node-pre-gyp@*:
-  version "0.14.0"
-  resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.14.0.tgz#9a0596533b877289bcad4e143982ca3d904ddc83"
-  integrity sha512-+CvDC7ZttU/sSt9rFjix/P05iS43qHCOOGzcr3Ry99bXG7VX953+vFyEuph/tfqoYu8dttBkE86JSKBO2OzcxA==
-  dependencies:
-    detect-libc "^1.0.2"
-    mkdirp "^0.5.1"
-    needle "^2.2.1"
-    nopt "^4.0.1"
-    npm-packlist "^1.1.6"
-    npmlog "^4.0.2"
-    rc "^1.2.7"
-    rimraf "^2.6.1"
-    semver "^5.3.0"
-    tar "^4.4.2"
-
 node-releases@^1.1.47:
   version "1.1.48"
   resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.48.tgz#7f647f0c453a0495bcd64cbd4778c26035c2f03a"
@@ -7020,14 +6961,6 @@ noop-logger@^0.1.1:
   resolved "https://registry.yarnpkg.com/noop-logger/-/noop-logger-0.1.1.tgz#94a2b1633c4f1317553007d8966fd0e841b6a4c2"
   integrity sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI=
 
-nopt@^4.0.1:
-  version "4.0.1"
-  resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d"
-  integrity sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=
-  dependencies:
-    abbrev "1"
-    osenv "^0.1.4"
-
 normalize-package-data@^2.3.2, normalize-package-data@^2.3.4, normalize-package-data@^2.5.0:
   version "2.5.0"
   resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8"
@@ -7080,27 +7013,6 @@ normalize-url@^4.1.0:
   resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.0.tgz#453354087e6ca96957bd8f5baf753f5982142129"
   integrity sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==
 
-npm-bundled@^1.0.1:
-  version "1.1.1"
-  resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.1.1.tgz#1edd570865a94cdb1bc8220775e29466c9fb234b"
-  integrity sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA==
-  dependencies:
-    npm-normalize-package-bin "^1.0.1"
-
-npm-normalize-package-bin@^1.0.1:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz#6e79a41f23fd235c0623218228da7d9c23b8f6e2"
-  integrity sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==
-
-npm-packlist@^1.1.6:
-  version "1.4.8"
-  resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.8.tgz#56ee6cc135b9f98ad3d51c1c95da22bbb9b2ef3e"
-  integrity sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==
-  dependencies:
-    ignore-walk "^3.0.1"
-    npm-bundled "^1.0.1"
-    npm-normalize-package-bin "^1.0.1"
-
 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"
@@ -7115,7 +7027,7 @@ npm-run-path@^4.0.0:
   dependencies:
     path-key "^3.0.0"
 
-npmlog@^4.0.1, npmlog@^4.0.2, npmlog@^4.1.2:
+npmlog@^4.0.1, npmlog@^4.1.2:
   version "4.1.2"
   resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b"
   integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==
@@ -7329,11 +7241,6 @@ os-browserify@^0.3.0:
   resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27"
   integrity sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=
 
-os-homedir@^1.0.0:
-  version "1.0.2"
-  resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3"
-  integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M=
-
 os-locale@^3.0.0:
   version "3.1.0"
   resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-3.1.0.tgz#a802a6ee17f24c10483ab9935719cef4ed16bf1a"
@@ -7343,19 +7250,11 @@ os-locale@^3.0.0:
     lcid "^2.0.0"
     mem "^4.0.0"
 
-os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.2:
+os-tmpdir@^1.0.1, os-tmpdir@~1.0.2:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
   integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=
 
-osenv@^0.1.4:
-  version "0.1.5"
-  resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410"
-  integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==
-  dependencies:
-    os-homedir "^1.0.0"
-    os-tmpdir "^1.0.0"
-
 p-cancelable@^1.0.0:
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc"
@@ -8862,7 +8761,7 @@ saslprep@^1.0.0:
   dependencies:
     sparse-bitfield "^3.0.3"
 
-sax@^1.2.4, sax@~1.2.4:
+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==
@@ -9719,19 +9618,6 @@ tar-stream@^2.0.0:
     inherits "^2.0.3"
     readable-stream "^3.1.1"
 
-tar@^4.4.2:
-  version "4.4.13"
-  resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.13.tgz#43b364bc52888d555298637b10d60790254ab525"
-  integrity sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==
-  dependencies:
-    chownr "^1.1.1"
-    fs-minipass "^1.2.5"
-    minipass "^2.8.6"
-    minizlib "^1.2.1"
-    mkdirp "^0.5.0"
-    safe-buffer "^5.1.2"
-    yallist "^3.0.3"
-
 tar@^5.0.5:
   version "5.0.5"
   resolved "https://registry.yarnpkg.com/tar/-/tar-5.0.5.tgz#03fcdb7105bc8ea3ce6c86642b9c942495b04f93"
@@ -10735,7 +10621,7 @@ yallist@^2.1.2:
   resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52"
   integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=
 
-yallist@^3.0.0, yallist@^3.0.2, yallist@^3.0.3:
+yallist@^3.0.2:
   version "3.1.1"
   resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd"
   integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==