diff --git a/tests/functional/reporting-non-auth.js b/tests/functional/reporting-non-auth.js index 7e0fe8ecd..daf2c1f73 100644 --- a/tests/functional/reporting-non-auth.js +++ b/tests/functional/reporting-non-auth.js @@ -120,8 +120,8 @@ define([ .findByCssSelector('#image').type('/path/to/foo.hacks') .end() // wait a bit - .sleep(100) - .findByXpath('//*[@id="new-report"]/div/form/div[2]/div[2]').getAttribute('class') + .sleep(250) + .findByCssSelector('.js-image-upload').getAttribute('class') .then(function(className) { assert.include(className, 'js-form-error'); assert.notInclude(className, 'js-no-error'); @@ -131,9 +131,9 @@ define([ .findByCssSelector('#image').type('/path/to/foo.jpg') .end() // wait a bit - .sleep(100) + .sleep(250) // validation message should be removed now - .findByXpath('//*[@id="new-report"]/div/form/div[2]/div[2]').getAttribute('class') + .findByCssSelector('.js-image-upload').getAttribute('class') .then(function(className) { assert.include(className, 'js-no-error'); assert.notInclude(className, 'js-form-error'); diff --git a/webcompat/form.py b/webcompat/form.py index 02345dc69..ea400d5f2 100644 --- a/webcompat/form.py +++ b/webcompat/form.py @@ -69,6 +69,8 @@ class IssueForm(Form): [InputRequired(message=radio_message)], choices=problem_choices) # we filter allowed type in uploads.py + # Note, we don't use the label programtically for this input[type=file], + # any changes here need to be updated in form.html. image = FileField(u'Attach a screenshot image', [Optional(), FileAllowed(Upload.ALLOWED_FORMATS, image_message)]) diff --git a/webcompat/static/css/development/base/variable.css b/webcompat/static/css/development/base/variable.css index 9c920c9ce..2ebd73bd5 100644 --- a/webcompat/static/css/development/base/variable.css +++ b/webcompat/static/css/development/base/variable.css @@ -12,7 +12,7 @@ } /* theme */ :root { - --wc-background-dark: #FFC900; /*Dark Yellow*/ + --wc-background-dark: #ffc900; /*Dark Yellow*/ --wc-background-light: var(--wc-background-dark); /* #FBC55F Light Yellow */ --wc-variant-background-dark: #404040; /* Dark Gray */ --wc-variant-background-light: #c2c2c2; /* Dark Light */ diff --git a/webcompat/static/css/development/components/form.css b/webcompat/static/css/development/components/form.css index 783368399..0d72022cd 100644 --- a/webcompat/static/css/development/components/form.css +++ b/webcompat/static/css/development/components/form.css @@ -22,8 +22,8 @@ outline: 0px none; box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.075) inset, 0px 0px 8px rgba(102, 175, 233, 0.6); } - .wc-Form-input--heightAuto { - height:auto; + .wc-Form-input--textarea { + min-height: 250px; } .wc-Form-input::placeholder { color: #999; @@ -44,6 +44,7 @@ cursor: pointer; text-decoration: underline; } + /*------Form Validation------*/ .wc-Form-error .wc-Form-input { border-color: #ff0000; @@ -141,10 +142,52 @@ legend.wc-Form-label { /* upload */ .wc-Form-upload { - text-align: center; + display: block; position: relative; + text-align: center; + border: dashed 1px #ccc; + border-radius: 20px; + min-height: 250px; + cursor: pointer; + overflow: hidden; } - .wc-Form-upload-icon { - font-size: 1.2em; - margin: 0 .4em 0 0; + + /* Form upload wrapper */ + .wc-Form-upload-wrapper { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); } + /* state */ + .wc-Form-upload-wrapper.is-hidden { + display: none; + } + + .wc-Form-upload-icon { + font-size: 6.2em; + margin: 0 0 16px; + color: #c8c8c8; + } + + /* Upload button */ + .wc-Form-upload-button { + position: absolute; + width: 100%; + bottom: 0; + left: 0; + right: 0; + padding: 1em 0; + font-weight:700; + background-color: var(--wc-background-dark); + border-bottom-left-radius: 20px; + border-bottom-right-radius: 20px; + cursor: pointer; + text-align: center; + text-decoration: underline; + transform: translateY(0); + transition: transform .2s linear 0s; + } + .wc-Form-upload-button.is-hidden { + transform: translateY(100%); + } diff --git a/webcompat/static/js/lib/bugform.js b/webcompat/static/js/lib/bugform.js index 5602a1dfe..d6501816d 100644 --- a/webcompat/static/js/lib/bugform.js +++ b/webcompat/static/js/lib/bugform.js @@ -91,7 +91,7 @@ function BugForm() { } }; - this.checkImageTypeValidity = function() { + this.checkImageTypeValidity = function(event) { var splitImg = this.uploadField.val().split('.'); var ext = splitImg[splitImg.length - 1].toLowerCase(); var allowed = ['jpg', 'jpeg', 'jpe', 'png', 'gif', 'bmp']; @@ -104,6 +104,9 @@ function BugForm() { this.makeInvalid('image'); } else { this.makeValid('image'); + if (event) { + this.showUploadPreview(event); + } } }; @@ -180,6 +183,56 @@ function BugForm() { this.enableSubmits(); } }; + /* + If the users browser understands the FileReader API, show a preview + of the image they're about to load. + */ + this.showUploadPreview = function(event) { + if (!(window.FileReader && window.File)) { + return; + } + + // We can just grab the 0th one, because we only allow uploading + // a single image at a time (for now) + var img = event.target.files[0]; + + // One last validation check. + if (!img.type.match('image.*')) { + this.makeInvalid('image'); + return; + } + + var reader = new FileReader(); + reader.onload = _.bind(function(event) { + var dataURI = event.target.result; + var label = $('.js-image-upload').find('label').eq(0); + + label.css({ + 'background': 'url(' + dataURI + ') no-repeat center / contain' + }); + + this.showRemoveUpload(label); + }, this); + reader.readAsDataURL(img); + }; + /* + Allow users to remove an image from the form upload. + */ + this.showRemoveUpload = function(label) { + var removeBanner = $('.wc-Form-upload-button'); + var uploadWrapper = $('.wc-Form-upload-wrapper'); + + removeBanner.removeClass('is-hidden'); + uploadWrapper.addClass('is-hidden'); + removeBanner.on('click', _.bind(function() { + // clear out the input value, remove the preview and hide the banner + this.uploadField.val(this.uploadField.get().defaultValue); + label.css('background', 'none'); + removeBanner.addClass('is-hidden'); + uploadWrapper.removeClass('is-hidden'); + removeBanner.off('click'); + }, this)); + }; /* copy URL from urlField into the first line of the description field. early return if the user has deleted diff --git a/webcompat/templates/form.html b/webcompat/templates/form.html index c9c148dd9..c1769b02c 100644 --- a/webcompat/templates/form.html +++ b/webcompat/templates/form.html @@ -37,19 +37,29 @@ -