From 41351f877c550742e0e5d61c631ae36acd01f286 Mon Sep 17 00:00:00 2001 From: Danny Coates Date: Mon, 14 Aug 2017 12:04:03 -0700 Subject: [PATCH] removed jquery from upload.js --- frontend/src/fileList.js | 251 +++++++++-------------- frontend/src/fileSender.js | 156 +++++++------- frontend/src/main.css | 4 + frontend/src/upload.js | 410 ++++++++++++++++++------------------- package-lock.json | 118 ++++++----- package.json | 6 +- webpack.config.js | 6 +- 7 files changed, 440 insertions(+), 511 deletions(-) diff --git a/frontend/src/fileList.js b/frontend/src/fileList.js index 93c1f26f..74b0240a 100644 --- a/frontend/src/fileList.js +++ b/frontend/src/fileList.js @@ -2,17 +2,15 @@ import FileSender from './fileSender'; import Storage from './storage'; import * as metrics from './metrics'; import { allowedCopy, copyToClipboard, ONE_DAY_IN_MS } from './utils'; -import $ from 'jquery/dist/jquery.slim'; +import bel from 'bel'; +const HOUR = 1000 * 60 * 60; const storage = new Storage(); let fileList = null; -let $link = null; document.addEventListener('DOMContentLoaded', function() { - $link = $('#link'); fileList = document.getElementById('file-list'); toggleHeader(); - // eslint-disable-next-line prefer-const Promise.all( storage.files.map(file => { const id = file.fileId; @@ -33,180 +31,115 @@ function toggleHeader() { fileList.hidden = storage.files.length === 0; } +function timeLeft(milliseconds) { + const minutes = Math.floor(milliseconds / 1000 / 60); + const hours = Math.floor(minutes / 60); + const seconds = Math.floor(milliseconds / 1000 % 60); + if (hours >= 1) { + return `${hours}h ${minutes % 60}m`; + } else if (hours === 0) { + return `${minutes}m ${seconds}s`; + } + return 'Expired'; +} + function addFile(file) { if (!file) { return; } - const row = document.createElement('tr'); - const name = document.createElement('td'); - const link = document.createElement('td'); - const $copyIcon = $('', { - src: '/resources/copy-16.svg', - class: 'icon-copy', - 'data-l10n-id': 'copyUrlHover', - disabled: !allowedCopy() - }); - const expiry = document.createElement('td'); - const del = document.createElement('td'); - const $delIcon = $('', { - src: '/resources/close-16.svg', - class: 'icon-delete', - 'data-l10n-id': 'deleteButtonHover' - }); - const popupDiv = document.createElement('div'); - const $popupText = $('
', { class: 'popuptext' }); - const cellText = document.createTextNode(file.name); - - const url = file.url.trim() + `#${file.secretKey}`.trim(); - - $link.attr('value', url); - $('#copy-text') - .attr('data-l10n-args', `{"filename": "${file.name}"}`) - .attr('data-l10n-id', 'copyUrlFormLabelWithName'); - - $popupText.attr('tabindex', '-1'); - - name.appendChild(cellText); - - // create delete button - - const delSpan = document.createElement('span'); - $(delSpan) - .addClass('icon-cancel-1') - .attr('data-l10n-id', 'deleteButtonHover'); - del.appendChild(delSpan); - - const linkSpan = document.createElement('span'); - $(linkSpan).addClass('icon-docs').attr('data-l10n-id', 'copyUrlHover'); - - link.appendChild(linkSpan); - link.style.color = '#0A8DFF'; - - //copy link to clipboard when icon clicked - $copyIcon.on('click', () => { - // record copied event from upload list - metrics.copiedLink({ location: 'upload-list' }); - copyToClipboard(url); - document.l10n.formatValue('copiedUrl').then(translated => { - link.innerHTML = translated; - }); - setTimeout(() => { - const linkImg = document.createElement('img'); - $(linkImg) - .addClass('icon-copy') - .attr('data-l10n-id', 'copyUrlHover') - .attr('src', '/resources/copy-16.svg'); - - $(link).html(linkImg); - }, 500); - }); - file.creationDate = new Date(file.creationDate); - + const url = `${file.url}#${file.secretKey}`; const future = new Date(); future.setTime(file.creationDate.getTime() + file.expiry); + const countdown = future.getTime() - Date.now(); - let countdown = 0; - countdown = future.getTime() - Date.now(); - let minutes = Math.floor(countdown / 1000 / 60); - let hours = Math.floor(minutes / 60); - let seconds = Math.floor(countdown / 1000 % 60); - - const poll = () => { - countdown = future.getTime() - Date.now(); - minutes = Math.floor(countdown / 1000 / 60); - hours = Math.floor(minutes / 60); - seconds = Math.floor(countdown / 1000 % 60); - let t; - - if (hours >= 1) { - expiry.innerHTML = hours + 'h ' + minutes % 60 + 'm'; - t = setTimeout(() => { - poll(); - }, 60000); - } else if (hours === 0) { - expiry.innerHTML = minutes + 'm ' + seconds + 's'; - t = window.setTimeout(() => { - poll(); - }, 1000); - } - //remove from list when expired - if (countdown <= 0) { - storage.remove(file.fileId); - $(expiry).parents('tr').remove(); - window.clearTimeout(t); - toggleHeader(); - } - }; + const row = bel` + + ${file.name} + + + + + + ${timeLeft(countdown)} + + + + + + + `; + const popup = row.querySelector('.popuptext'); + const timeCol = row.querySelectorAll('td')[2]; + if (!allowedCopy()) { + row.querySelector('.icon-copy').disabled = true; + } + fileList.querySelector('tbody').appendChild(row); + toggleHeader(); poll(); - // create popup - popupDiv.classList.add('popup'); - const $popupMessage = $('
', { class: 'popup-message' }); - $popupMessage.attr('data-l10n-id', 'deletePopupText'); - const $popupAction = $('
', { class: 'popup-action' }); - const $popupNvmSpan = $('', { class: 'popup-no' }); - $popupNvmSpan.attr('data-l10n-id', 'deletePopupCancel'); - const $popupDelSpan = $('', { class: 'popup-yes' }); - $popupDelSpan.attr('data-l10n-id', 'deletePopupYes'); + function copyClick(e) { + metrics.copiedLink({ location: 'upload-list' }); + copyToClipboard(url); + const icon = e.target; + const text = e.target.nextSibling; + icon.hidden = true; + text.hidden = false; + setTimeout(() => { + icon.hidden = false; + text.hidden = true; + }, 500); + } - $popupText.html([$popupMessage, $popupAction]); - $popupAction.html([$popupNvmSpan, $popupDelSpan]); - - // add data cells to table row - row.appendChild(name); - $(link).append($copyIcon); - row.appendChild(link); - row.appendChild(expiry); - $(popupDiv).append($popupText); - $(del).append($delIcon); - del.appendChild(popupDiv); - row.appendChild(del); - $('tbody').append(row); //add row to table - - // delete file - $popupText.find('.popup-yes').on('click', e => { - FileSender.delete(file.fileId, file.deleteToken).then(() => { - $(e.target).parents('tr').remove(); - const ttl = ONE_DAY_IN_MS - (Date.now() - file.creationDate.getTime()); - metrics - .deletedUpload({ - size: file.size, - time: file.totalTime, - speed: file.uploadSpeed, - type: file.typeOfUpload, - location: 'upload-list', - ttl - }) - .then(() => { - storage.remove(file.fileId); - }); + function poll() { + const countdown = future.getTime() - Date.now(); + if (countdown <= 0) { + storage.remove(file.fileId); + row.parentNode.removeChild(row); toggleHeader(); + } + timeCol.textContent = timeLeft(countdown); + setTimeout(poll, countdown >= HOUR ? 60000 : 1000); + } + + function deleteFile() { + FileSender.delete(file.fileId, file.deleteToken); + const ttl = ONE_DAY_IN_MS - (Date.now() - file.creationDate.getTime()); + metrics.deletedUpload({ + size: file.size, + time: file.totalTime, + speed: file.uploadSpeed, + type: file.typeOfUpload, + location: 'upload-list', + ttl }); - }); + row.parentNode.removeChild(row); + storage.remove(file.fileId); + toggleHeader(); + } - // show popup - $delIcon.on('click', () => { - $popupText.addClass('show').focus(); - }); + function showPopup() { + popup.classList.add('show'); + popup.focus(); + } - // hide popup - $popupText.find('.popup-no').on('click', e => { + function cancel(e) { e.stopPropagation(); - $popupText.removeClass('show'); - }); + popup.classList.remove('show'); + } - $popupText.on('click', e => { + function stopProp(e) { e.stopPropagation(); - }); - - //close when popup loses focus - $popupText.on('blur', () => { - $popupText.removeClass('show'); - }); - - toggleHeader(); + } } async function checkExistence(id) { diff --git a/frontend/src/fileSender.js b/frontend/src/fileSender.js index dad2365a..2073c121 100644 --- a/frontend/src/fileSender.js +++ b/frontend/src/fileSender.js @@ -7,6 +7,14 @@ export default class FileSender extends EventEmitter { this.file = file; this.iv = window.crypto.getRandomValues(new Uint8Array(12)); this.uploadXHR = new XMLHttpRequest(); + this.key = window.crypto.subtle.generateKey( + { + name: 'AES-GCM', + length: 128 + }, + true, + ['encrypt'] + ); } static delete(fileId, token) { @@ -32,87 +40,79 @@ export default class FileSender extends EventEmitter { this.uploadXHR.abort(); } - upload() { - const self = this; - self.emit('loading'); - return Promise.all([ - window.crypto.subtle.generateKey( - { - name: 'AES-GCM', - length: 128 - }, - true, - ['encrypt', 'decrypt'] - ), - new Promise((resolve, reject) => { - const reader = new FileReader(); - reader.readAsArrayBuffer(this.file); - reader.onload = function(event) { - const plaintext = new Uint8Array(this.result); - resolve(plaintext); - }; - reader.onerror = function(err) { - reject(err); - }; - }) - ]) - .then(([secretKey, plaintext]) => { - self.emit('encrypting'); - return Promise.all([ - window.crypto.subtle.encrypt( - { - name: 'AES-GCM', - iv: this.iv, - tagLength: 128 - }, - secretKey, - plaintext - ), - window.crypto.subtle.exportKey('jwk', secretKey) - ]); - }) - .then(([encrypted, keydata]) => { - return new Promise((resolve, reject) => { - const file = this.file; - const fileId = arrayToHex(this.iv); - const dataView = new DataView(encrypted); - const blob = new Blob([dataView], { type: file.type }); - const fd = new FormData(); - fd.append('data', blob, file.name); + readFile() { + return new Promise((resolve, reject) => { + const reader = new FileReader(); + reader.readAsArrayBuffer(this.file); + reader.onload = function(event) { + const plaintext = new Uint8Array(this.result); + resolve(plaintext); + }; + reader.onerror = function(err) { + reject(err); + }; + }); + } - const xhr = self.uploadXHR; + uploadFile(encrypted, keydata) { + return new Promise((resolve, reject) => { + const file = this.file; + const fileId = arrayToHex(this.iv); + const dataView = new DataView(encrypted); + const blob = new Blob([dataView], { type: file.type }); + const fd = new FormData(); + fd.append('data', blob, file.name); - xhr.upload.addEventListener('progress', e => { - if (e.lengthComputable) { - self.emit('progress', [e.loaded, e.total]); - } - }); + const xhr = this.uploadXHR; - xhr.onreadystatechange = () => { - if (xhr.readyState === XMLHttpRequest.DONE) { - if (xhr.status === 200) { - const responseObj = JSON.parse(xhr.responseText); - return resolve({ - url: responseObj.url, - fileId: responseObj.id, - secretKey: keydata.k, - deleteToken: responseObj.delete - }); - } - reject(xhr.status); - } - }; - - xhr.open('post', '/upload', true); - xhr.setRequestHeader( - 'X-File-Metadata', - JSON.stringify({ - id: fileId, - filename: encodeURIComponent(file.name) - }) - ); - xhr.send(fd); - }); + xhr.upload.addEventListener('progress', e => { + if (e.lengthComputable) { + this.emit('progress', [e.loaded, e.total]); + } }); + + xhr.onreadystatechange = () => { + if (xhr.readyState === XMLHttpRequest.DONE) { + if (xhr.status === 200) { + const responseObj = JSON.parse(xhr.responseText); + return resolve({ + url: responseObj.url, + fileId: responseObj.id, + secretKey: keydata.k, + deleteToken: responseObj.delete + }); + } + reject(xhr.status); + } + }; + + xhr.open('post', '/upload', true); + xhr.setRequestHeader( + 'X-File-Metadata', + JSON.stringify({ + id: fileId, + filename: encodeURIComponent(file.name) + }) + ); + xhr.send(fd); + }); + } + + async upload() { + this.emit('loading'); + const key = await this.key; + const plaintext = await this.readFile(); + this.emit('encrypting'); + const encrypted = await window.crypto.subtle.encrypt( + { + name: 'AES-GCM', + iv: this.iv, + tagLength: 128 + }, + key, + plaintext + ); + const keydata = await window.crypto.subtle.exportKey('jwk', key); + return this.uploadFile(encrypted, keydata); } } diff --git a/frontend/src/main.css b/frontend/src/main.css index 583efd19..a8a7bc82 100644 --- a/frontend/src/main.css +++ b/frontend/src/main.css @@ -310,6 +310,10 @@ tbody { opacity: 0.3; } +.text-copied { + color: #0a8dff; +} + /* Popup container */ .popup { position: absolute; diff --git a/frontend/src/upload.js b/frontend/src/upload.js index 2863b7e7..6ab00981 100644 --- a/frontend/src/upload.js +++ b/frontend/src/upload.js @@ -13,236 +13,230 @@ import Storage from './storage'; import * as metrics from './metrics'; import * as progress from './progress'; import * as fileList from './fileList'; -import $ from 'jquery/dist/jquery.slim'; const storage = new Storage(); -$(() => { +async function upload(event) { + event.preventDefault(); + const pageOne = document.getElementById('page-one'); + const link = document.getElementById('link'); + const uploadWindow = document.querySelector('.upload-window'); + const uploadError = document.getElementById('upload-error'); + const uploadProgress = document.getElementById('upload-progress'); + const clickOrDrop = event.type === 'drop' ? 'drop' : 'click'; + + // don't allow upload if not on upload page + if (pageOne.hidden) { + return; + } + + storage.totalUploads += 1; + + let file = ''; + if (clickOrDrop === 'drop') { + if (!event.originalEvent.dataTransfer.files[0]) { + uploadWindow.classList.remove('ondrag'); + return; + } + if ( + event.originalEvent.dataTransfer.files.length > 1 || + event.originalEvent.dataTransfer.files[0].size === 0 + ) { + uploadWindow.classList.remove('ondrag'); + document.l10n.formatValue('uploadPageMultipleFilesAlert').then(str => { + alert(str); + }); + return; + } + file = event.originalEvent.dataTransfer.files[0]; + } else { + file = event.target.files[0]; + } + + if (file.size > MAXFILESIZE) { + return document.l10n + .formatValue('fileTooBig', { size: bytes(MAXFILESIZE) }) + .then(alert); + } + + pageOne.hidden = true; + uploadError.hidden = true; + uploadProgress.hidden = false; + document.l10n + .formatValue('uploadingPageProgress', { + size: bytes(file.size), + filename: file.name + }) + .then(str => { + document.getElementById('upload-filename').textContent = str; + }); + document.l10n.formatValue('importingFile').then(progress.setText); + //don't allow drag and drop when not on page-one + document.body.removeEventListener('drop', upload); + + const fileSender = new FileSender(file); + document.getElementById('cancel-upload').addEventListener('click', () => { + fileSender.cancel(); + metrics.cancelledUpload({ + size: file.size, + type: clickOrDrop + }); + location.reload(); + }); + + let uploadStart; + fileSender.on('progress', data => { + uploadStart = uploadStart || Date.now(); + progress.setProgress({ + complete: data[0], + total: data[1] + }); + }); + + fileSender.on('encrypting', () => { + document.l10n.formatValue('encryptingFile').then(progress.setText); + }); + + let t; + const startTime = Date.now(); + metrics.startedUpload({ + size: file.size, + type: clickOrDrop + }); + // For large files we need to give the ui a tick to breathe and update + // before we kick off the FileSender + setTimeout(() => { + fileSender + .upload() + .then(info => { + const endTime = Date.now(); + const time = endTime - startTime; + const uploadTime = endTime - uploadStart; + const speed = file.size / (uploadTime / 1000); + const expiration = EXPIRE_SECONDS * 1000; + + link.setAttribute('value', `${info.url}#${info.secretKey}`); + + metrics.completedUpload({ + size: file.size, + time, + speed, + type: clickOrDrop + }); + + const fileData = { + name: file.name, + size: file.size, + fileId: info.fileId, + url: info.url, + secretKey: info.secretKey, + deleteToken: info.deleteToken, + creationDate: new Date(), + expiry: expiration, + totalTime: time, + typeOfUpload: clickOrDrop, + uploadSpeed: speed + }; + + document.getElementById('delete-file').addEventListener('click', () => { + FileSender.delete(fileData.fileId, fileData.deleteToken).then(() => { + const ttl = + ONE_DAY_IN_MS - (Date.now() - fileData.creationDate.getTime()); + metrics + .deletedUpload({ + size: fileData.size, + time: fileData.totalTime, + speed: fileData.uploadSpeed, + type: fileData.typeOfUpload, + location: 'success-screen', + ttl + }) + .then(() => { + storage.remove(fileData.fileId); + location.reload(); + }); + }); + }); + + storage.addFile(info.fileId, fileData); + + pageOne.hidden = true; + uploadProgress.hidden = true; + uploadError.hidden = true; + document.getElementById('share-link').hidden = false; + + fileList.addFile(fileData); + document.l10n.formatValue('notifyUploadDone').then(str => { + notify(str); + }); + }) + .catch(err => { + // err is 0 when coming from a cancel upload event + if (err === 0) { + return; + } + // only show error page when the error is anything other than user cancelling the upload + Raven.captureException(err); + pageOne.hidden = true; + uploadProgress.hidden = true; + uploadError.hidden = false; + window.clearTimeout(t); + + metrics.stoppedUpload({ + size: file.size, + type: clickOrDrop, + err + }); + }); + }, 10); +} + +document.addEventListener('DOMContentLoaded', function() { gcmCompliant() .then(function() { - const $pageOne = $('#page-one'); - const $copyBtn = $('#copy-btn'); - const $link = $('#link'); - const $uploadWindow = $('.upload-window'); - const $uploadError = $('#upload-error'); - const $uploadProgress = $('#upload-progress'); + const pageOne = document.getElementById('page-one'); + const copyBtn = document.getElementById('copy-btn'); + const link = document.getElementById('link'); + const uploadWindow = document.querySelector('.upload-window'); - $pageOne.removeAttr('hidden'); - $('#file-upload').on('change', onUpload); + pageOne.hidden = false; + document.getElementById('file-upload').addEventListener('change', upload); - $(document.body).on('dragover', allowDrop).on('drop', onUpload); + document.body.addEventListener('dragover', allowDrop); + document.body.addEventListener('drop', upload); // reset copy button - $copyBtn.attr({ - disabled: !allowedCopy(), - 'data-l10n-id': 'copyUrlFormButton' - }); + copyBtn.disabled = !allowedCopy(); + copyBtn.setAttribute('data-l10n-id', 'copyUrlFormButton'); - $link.attr('disabled', false); + link.disabled = false; // copy link to clipboard - $copyBtn.on('click', () => { - if (allowedCopy() && copyToClipboard($link.attr('value'))) { + copyBtn.addEventListener('click', () => { + if (allowedCopy() && copyToClipboard(link.getAttribute('value'))) { metrics.copiedLink({ location: 'success-screen' }); //disable button for 3s - $copyBtn.attr('disabled', true); - $link.attr('disabled', true); - $copyBtn.html( - '' - ); + copyBtn.disabled = true; + link.disabled = true; + copyBtn.innerHtml = + ''; setTimeout(() => { - $copyBtn.attr({ - disabled: false, - 'data-l10n-id': 'copyUrlFormButton' - }); - $link.attr('disabled', false); + copyBtn.disabled = !allowedCopy(); + copyBtn.setAttribute('data-l10n-id', 'copyUrlFormButton'); + link.disabled = false; }, 3000); } }); - $uploadWindow - .on('dragover', () => { - $uploadWindow.addClass('ondrag'); - }) - .on('dragleave', () => { - $uploadWindow.removeClass('ondrag'); - }); + uploadWindow.addEventListener('dragover', () => + uploadWindow.classList.add('ondrag') + ); + uploadWindow.addEventListener('dragleave', () => + uploadWindow.classList.remove('ondrag') + ); // on file upload by browse or drag & drop - function onUpload(event) { - event.preventDefault(); - const clickOrDrop = event.type === 'drop' ? 'drop' : 'click'; - - // don't allow upload if not on upload page - if ($pageOne.attr('hidden')) { - return; - } - - storage.totalUploads += 1; - - let file = ''; - if (clickOrDrop === 'drop') { - if (!event.originalEvent.dataTransfer.files[0]) { - $uploadWindow.removeClass('ondrag'); - return; - } - if ( - event.originalEvent.dataTransfer.files.length > 1 || - event.originalEvent.dataTransfer.files[0].size === 0 - ) { - $uploadWindow.removeClass('ondrag'); - document.l10n - .formatValue('uploadPageMultipleFilesAlert') - .then(str => { - alert(str); - }); - return; - } - file = event.originalEvent.dataTransfer.files[0]; - } else { - file = event.target.files[0]; - } - - if (file.size > MAXFILESIZE) { - return document.l10n - .formatValue('fileTooBig', { size: bytes(MAXFILESIZE) }) - .then(alert); - } - - $pageOne.attr('hidden', true); - $uploadError.attr('hidden', true); - $uploadProgress.removeAttr('hidden'); - document.l10n - .formatValue('uploadingPageProgress', { - size: bytes(file.size), - filename: file.name - }) - .then(str => { - $('#upload-filename').text(str); - }); - document.l10n.formatValue('importingFile').then(progress.setText); - //don't allow drag and drop when not on page-one - $(document.body).off('drop', onUpload); - - const fileSender = new FileSender(file); - $('#cancel-upload').on('click', () => { - fileSender.cancel(); - metrics.cancelledUpload({ - size: file.size, - type: clickOrDrop - }); - location.reload(); - }); - - let uploadStart; - fileSender.on('progress', data => { - uploadStart = uploadStart || Date.now(); - progress.setProgress({ - complete: data[0], - total: data[1] - }); - }); - - fileSender.on('encrypting', () => { - document.l10n.formatValue('encryptingFile').then(progress.setText); - }); - - let t; - const startTime = Date.now(); - metrics.startedUpload({ - size: file.size, - type: clickOrDrop - }); - // For large files we need to give the ui a tick to breathe and update - // before we kick off the FileSender - setTimeout(() => { - fileSender - .upload() - .then(info => { - const endTime = Date.now(); - const time = endTime - startTime; - const uploadTime = endTime - uploadStart; - const speed = file.size / (uploadTime / 1000); - const expiration = EXPIRE_SECONDS * 1000; - - metrics.completedUpload({ - size: file.size, - time, - speed, - type: clickOrDrop - }); - - const fileData = { - name: file.name, - size: file.size, - fileId: info.fileId, - url: info.url, - secretKey: info.secretKey, - deleteToken: info.deleteToken, - creationDate: new Date(), - expiry: expiration, - totalTime: time, - typeOfUpload: clickOrDrop, - uploadSpeed: speed - }; - - $('#delete-file').on('click', () => { - FileSender.delete( - fileData.fileId, - fileData.deleteToken - ).then(() => { - const ttl = - ONE_DAY_IN_MS - - (Date.now() - fileData.creationDate.getTime()); - metrics - .deletedUpload({ - size: fileData.size, - time: fileData.totalTime, - speed: fileData.uploadSpeed, - type: fileData.typeOfUpload, - location: 'success-screen', - ttl - }) - .then(() => { - storage.remove(fileData.fileId); - location.reload(); - }); - }); - }); - - storage.addFile(info.fileId, fileData); - - $pageOne.attr('hidden', true); - $uploadProgress.attr('hidden', true); - $uploadError.attr('hidden', true); - $('#share-link').removeAttr('hidden'); - - fileList.addFile(fileData); - document.l10n.formatValue('notifyUploadDone').then(str => { - notify(str); - }); - }) - .catch(err => { - // err is 0 when coming from a cancel upload event - if (err === 0) { - return; - } - // only show error page when the error is anything other than user cancelling the upload - Raven.captureException(err); - $pageOne.attr('hidden', true); - $uploadProgress.attr('hidden', true); - $uploadError.removeAttr('hidden'); - window.clearTimeout(t); - - metrics.stoppedUpload({ - size: file.size, - type: clickOrDrop, - err - }); - }); - }, 10); - } function allowDrop(ev) { ev.preventDefault(); diff --git a/package-lock.json b/package-lock.json index c67de524..931cd167 100644 --- a/package-lock.json +++ b/package-lock.json @@ -291,9 +291,9 @@ } }, "aws-sdk": { - "version": "2.95.0", - "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.95.0.tgz", - "integrity": "sha1-JuIdsUlEOx8GOUnch5hPDRdwDmo=", + "version": "2.98.0", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.98.0.tgz", + "integrity": "sha1-kK0CPXM4ndFex736+TLsq2VEVxE=", "requires": { "buffer": "4.9.1", "crypto-browserify": "1.0.9", @@ -1086,6 +1086,17 @@ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.1.tgz", "integrity": "sha512-dwVUVIXsBZXwTuwnXI9RK8sBmgq09NDHzyR9SAph9eqk76gKK2JSQmZARC2zRC81JC2QTtxD0ARU5qTS25gIGw==" }, + "bel": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/bel/-/bel-5.0.3.tgz", + "integrity": "sha512-bMLvUOrKBM2zWp3Ab6UugjCjFmsZtIeKH3oMNWaUr9RA94sNeicajzptZHQWU3K8KNIL8o6JwAmKG1W3mUiwXw==", + "dev": true, + "requires": { + "hyperx": "2.3.0", + "is-electron": "2.1.0", + "pelo": "0.0.3" + } + }, "big.js": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.1.3.tgz", @@ -2330,7 +2341,7 @@ "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", "dev": true, "requires": { - "es5-ext": "0.10.26" + "es5-ext": "0.10.27" } }, "dasherize": { @@ -2640,12 +2651,6 @@ } } }, - "dom-walk": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.1.tgz", - "integrity": "sha1-ZyIm3HTI95mtNTB9+TaroRrNYBg=", - "dev": true - }, "domain-browser": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.1.7.tgz", @@ -2801,9 +2806,9 @@ } }, "es5-ext": { - "version": "0.10.26", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.26.tgz", - "integrity": "sha1-UbISilMbcMT2dkCTpzy+u4IYY3I=", + "version": "0.10.27", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.27.tgz", + "integrity": "sha512-3KXJRYzKXTd7xfFy5uZsJCXue55fAYQ035PRjyYk2PicllxIwcW9l3AbM/eGaw3vgVAUW4tl4xg9AXDEI6yw0w==", "dev": true, "requires": { "es6-iterator": "2.0.1", @@ -2817,7 +2822,7 @@ "dev": true, "requires": { "d": "1.0.0", - "es5-ext": "0.10.26", + "es5-ext": "0.10.27", "es6-symbol": "3.1.1" } }, @@ -2828,7 +2833,7 @@ "dev": true, "requires": { "d": "1.0.0", - "es5-ext": "0.10.26", + "es5-ext": "0.10.27", "es6-iterator": "2.0.1", "es6-set": "0.1.5", "es6-symbol": "3.1.1", @@ -2848,7 +2853,7 @@ "dev": true, "requires": { "d": "1.0.0", - "es5-ext": "0.10.26", + "es5-ext": "0.10.27", "es6-iterator": "2.0.1", "es6-symbol": "3.1.1", "event-emitter": "0.3.5" @@ -2861,7 +2866,7 @@ "dev": true, "requires": { "d": "1.0.0", - "es5-ext": "0.10.26" + "es5-ext": "0.10.27" } }, "es6-weak-map": { @@ -2871,7 +2876,7 @@ "dev": true, "requires": { "d": "1.0.0", - "es5-ext": "0.10.26", + "es5-ext": "0.10.27", "es6-iterator": "2.0.1", "es6-symbol": "3.1.1" } @@ -3142,7 +3147,7 @@ "dev": true, "requires": { "d": "1.0.0", - "es5-ext": "0.10.26" + "es5-ext": "0.10.27" } }, "event-stream": { @@ -4520,24 +4525,6 @@ "is-glob": "2.0.1" } }, - "global": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/global/-/global-4.3.2.tgz", - "integrity": "sha1-52mJJopsdMOJCLEwWxD8DjlOnQ8=", - "dev": true, - "requires": { - "min-document": "2.19.0", - "process": "0.5.2" - }, - "dependencies": { - "process": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/process/-/process-0.5.2.tgz", - "integrity": "sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8=", - "dev": true - } - } - }, "globals": { "version": "9.18.0", "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", @@ -4784,6 +4771,21 @@ } } }, + "hyperscript-attribute-to-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hyperscript-attribute-to-property/-/hyperscript-attribute-to-property-1.0.0.tgz", + "integrity": "sha1-glMI1Ju44pV5I/cxmBvMgRytev8=", + "dev": true + }, + "hyperx": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/hyperx/-/hyperx-2.3.0.tgz", + "integrity": "sha1-cPRz1m1K1VDd0cg+S+JlEna78eI=", + "dev": true, + "requires": { + "hyperscript-attribute-to-property": "1.0.0" + } + }, "iconv-lite": { "version": "0.4.15", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.15.tgz", @@ -5064,6 +5066,12 @@ "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", "dev": true }, + "is-electron": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-electron/-/is-electron-2.1.0.tgz", + "integrity": "sha512-dkg5xT383+M6zIbbXW/z7n2nz4SFUi2OSyhntnFYkRdtV+HVEfdjEK+5AWisfYgkpe3WYjTIuh7toaKmSfFVWw==", + "dev": true + }, "is-equal-shallow": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", @@ -5260,12 +5268,6 @@ "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz", "integrity": "sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc=" }, - "jquery": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.2.1.tgz", - "integrity": "sha1-XE2d5lKvbNCncBVKYxu6ErAVx4c=", - "dev": true - }, "js-base64": { "version": "2.1.9", "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.1.9.tgz", @@ -6324,15 +6326,6 @@ "integrity": "sha1-5md4PZLonb00KBi1IwudYqZyrRg=", "dev": true }, - "min-document": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", - "integrity": "sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU=", - "dev": true, - "requires": { - "dom-walk": "0.1.1" - } - }, "minimalistic-assert": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz", @@ -6574,7 +6567,7 @@ "stream-browserify": "2.0.1", "stream-http": "2.7.2", "string_decoder": "0.10.31", - "timers-browserify": "2.0.3", + "timers-browserify": "2.0.4", "tty-browserify": "0.0.0", "url": "0.11.0", "util": "0.10.3", @@ -6638,12 +6631,11 @@ } }, "timers-browserify": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.3.tgz", - "integrity": "sha512-+JAqyNgg+M8+gXIrq2EeUr4kZqRz47Ysco7X5QKRGScRE9HIHckyHD1asozSFGeqx2nmPCgA8T5tIGVO0ML7/w==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.4.tgz", + "integrity": "sha512-uZYhyU3EX8O7HQP+J9fTVYwsq90Vr68xPEFo7yrVImIxYvHgukBEgOB/SgGoorWVTzGM/3Z+wUNnboA4M8jWrg==", "dev": true, "requires": { - "global": "4.3.2", "setimmediate": "1.0.5" } }, @@ -7046,6 +7038,12 @@ "sha.js": "2.4.8" } }, + "pelo": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/pelo/-/pelo-0.0.3.tgz", + "integrity": "sha1-+2smsGEgNtsCuRj+qrPowMTLWXw=", + "dev": true + }, "pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", @@ -10560,9 +10558,9 @@ } }, "webpack": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-3.5.2.tgz", - "integrity": "sha1-qWAQZuI688gPO/l1j9eUypd48lE=", + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-3.5.4.tgz", + "integrity": "sha1-VYPrJj7Se3i1vRe/37DrGxzRv4E=", "dev": true, "requires": { "acorn": "5.1.1", diff --git a/package.json b/package.json index 5eaf0461..78af54d9 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "version": "1.1.0", "author": "Mozilla (https://mozilla.org)", "dependencies": { - "aws-sdk": "^2.95.0", + "aws-sdk": "^2.98.0", "body-parser": "^1.17.2", "connect-busboy": "0.0.2", "convict": "^3.0.0", @@ -23,6 +23,7 @@ "babel-polyfill": "^6.23.0", "babel-preset-es2015": "^6.24.1", "babel-preset-stage-2": "^6.24.1", + "bel": "^5.0.3", "browserify": "^14.4.0", "cross-env": "^5.0.5", "css-mqpacker": "^6.0.1", @@ -33,7 +34,6 @@ "eslint-plugin-security": "^1.4.0", "git-rev-sync": "^1.9.1", "husky": "^0.14.3", - "jquery": "^3.2.1", "l20n": "^5.0.0", "lint-staged": "^4.0.3", "mocha": "^3.4.2", @@ -50,7 +50,7 @@ "supertest": "^3.0.0", "testpilot-ga": "^0.3.0", "webcrypto-liner": "^0.1.25", - "webpack": "^3.5.2", + "webpack": "^3.5.4", "webpack-dev-middleware": "^1.12.0" }, "engines": { diff --git a/webpack.config.js b/webpack.config.js index cd576cec..c9439dd4 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -11,15 +11,15 @@ module.exports = { publicPath: '/' }, module: { - loaders: [ + rules: [ { test: /\.js$/, - loaders: 'babel-loader', + loader: 'babel-loader', include: [ path.resolve(__dirname, 'frontend'), path.resolve(__dirname, 'node_modules/testpilot-ga/src') ], - query: { + options: { babelrc: false, presets: [['es2015', { modules: false }], 'stage-2'] }