]> BookStack Code Mirror - bookstack/commitdiff
Improved error messages for image uploads and formatted much js
authorDan Brown <redacted>
Wed, 30 Dec 2015 19:57:17 +0000 (19:57 +0000)
committerDan Brown <redacted>
Wed, 30 Dec 2015 19:57:17 +0000 (19:57 +0000)
resources/assets/js/controllers.js
resources/assets/js/directives.js
resources/assets/js/global.js
resources/assets/js/pages/page-form.js
resources/assets/sass/_image-manager.scss

index 5d2d4bbcad5e23640adf8a1a222aca729f1fffaf..5cf71579aa4716a06df6a2e92c1d1d98b79e4b63 100644 (file)
 "use strict";
 
-module.exports = function(ngApp) {
-
-    ngApp.controller('ImageManagerController', ['$scope', '$attrs', '$http', '$timeout','imageManagerService',
-    function($scope, $attrs, $http, $timeout, imageManagerService) {
-        $scope.images = [];
-        $scope.imageType = $attrs.imageType;
-        $scope.selectedImage = false;
-        $scope.dependantPages = false;
-        $scope.showing = false;
-        $scope.hasMore = false;
-        $scope.imageUpdateSuccess = false;
-        $scope.imageDeleteSuccess = false;
-        var page = 0;
-        var previousClickTime = 0;
-        var dataLoaded = false;
-        var callback = false;
-
-        $scope.getUploadUrl = function() {
-            return '/images/' + $scope.imageType + '/upload';
-        };
-
-        $scope.uploadSuccess = function(file, data) {
-            $scope.$apply(() => {
-                $scope.images.unshift(data);
-            });
-        };
-
-        function callbackAndHide(returnData) {
-            if (callback) callback(returnData);
+module.exports = function (ngApp) {
+
+    ngApp.controller('ImageManagerController', ['$scope', '$attrs', '$http', '$timeout', 'imageManagerService',
+        function ($scope, $attrs, $http, $timeout, imageManagerService) {
+            $scope.images = [];
+            $scope.imageType = $attrs.imageType;
+            $scope.selectedImage = false;
+            $scope.dependantPages = false;
             $scope.showing = false;
-        }
-
-        $scope.imageSelect = function (image) {
-            var dblClickTime = 300;
-            var currentTime = Date.now();
-            var timeDiff = currentTime - previousClickTime;
-
-            if (timeDiff < dblClickTime) {
-                // If double click
-                callbackAndHide(image);
-            } else {
-                // If single
-                $scope.selectedImage = image;
-                $scope.dependantPages = false;
-            }
-            previousClickTime = currentTime;
-        };
-
-        $scope.selectButtonClick = function() {
-            callbackAndHide($scope.selectedImage);
-        };
+            $scope.hasMore = false;
+            $scope.imageUpdateSuccess = false;
+            $scope.imageDeleteSuccess = false;
+            var page = 0;
+            var previousClickTime = 0;
+            var dataLoaded = false;
+            var callback = false;
+
+            $scope.getUploadUrl = function () {
+                return '/images/' + $scope.imageType + '/upload';
+            };
+
+            $scope.uploadSuccess = function (file, data) {
+                $scope.$apply(() => {
+                    $scope.images.unshift(data);
+                });
+            };
 
-        function show(doneCallback) {
-            callback = doneCallback;
-            $scope.showing = true;
-            // Get initial images if they have not yet been loaded in.
-            if (!dataLoaded) {
-                fetchData();
-                dataLoaded = true;
+            function callbackAndHide(returnData) {
+                if (callback) callback(returnData);
+                $scope.showing = false;
             }
-        }
 
-        imageManagerService.show = show;
-        imageManagerService.showExternal = function(doneCallback) {
-            $scope.$apply(() => {
-                show(doneCallback);
-            });
-        };
-        window.ImageManager = imageManagerService;
-
-        $scope.hide = function() {
-            $scope.showing = false;
-        };
+            $scope.imageSelect = function (image) {
+                var dblClickTime = 300;
+                var currentTime = Date.now();
+                var timeDiff = currentTime - previousClickTime;
+
+                if (timeDiff < dblClickTime) {
+                    // If double click
+                    callbackAndHide(image);
+                } else {
+                    // If single
+                    $scope.selectedImage = image;
+                    $scope.dependantPages = false;
+                }
+                previousClickTime = currentTime;
+            };
+
+            $scope.selectButtonClick = function () {
+                callbackAndHide($scope.selectedImage);
+            };
+
+            function show(doneCallback) {
+                callback = doneCallback;
+                $scope.showing = true;
+                // Get initial images if they have not yet been loaded in.
+                if (!dataLoaded) {
+                    fetchData();
+                    dataLoaded = true;
+                }
+            }
 
-        function fetchData() {
-            var url = '/images/' + $scope.imageType + '/all/' + page;
-            $http.get(url).then((response) => {
-                $scope.images = $scope.images.concat(response.data.images);
-                $scope.hasMore = response.data.hasMore;
-                page++;
-            });
-        }
-
-        $scope.saveImageDetails = function(event) {
-            event.preventDefault();
-            var url = '/images/update/' + $scope.selectedImage.id;
-            $http.put(url, this.selectedImage).then((response) => {
-                $scope.imageUpdateSuccess = true;
-                $timeout(() => {
-                    $scope.imageUpdateSuccess = false;
-                }, 3000);
-            }, (response) => {
-                var errors = response.data;
-                var message = '';
-                Object.keys(errors).forEach((key) => {
-                    message += errors[key].join('\n');
+            imageManagerService.show = show;
+            imageManagerService.showExternal = function (doneCallback) {
+                $scope.$apply(() => {
+                    show(doneCallback);
                 });
-                $scope.imageUpdateFailure = message;
-                $timeout(() => {
-                    $scope.imageUpdateFailure = false;
-                }, 5000);
-            });
-        };
+            };
+            window.ImageManager = imageManagerService;
+
+            $scope.hide = function () {
+                $scope.showing = false;
+            };
+
+            function fetchData() {
+                var url = '/images/' + $scope.imageType + '/all/' + page;
+                $http.get(url).then((response) => {
+                    $scope.images = $scope.images.concat(response.data.images);
+                    $scope.hasMore = response.data.hasMore;
+                    page++;
+                });
+            }
 
-        $scope.deleteImage = function(event) {
-            event.preventDefault();
-            var force = $scope.dependantPages !== false;
-            var url = '/images/' + $scope.selectedImage.id;
-            if (force) url += '?force=true';
-            $http.delete(url).then((response) => {
-                $scope.images.splice($scope.images.indexOf($scope.selectedImage), 1);
-                $scope.selectedImage = false;
-                $scope.imageDeleteSuccess = true;
-                $timeout(() => {
-                    $scope.imageDeleteSuccess = false;
-                }, 3000);
-            }, (response) => {
-                // Pages failure
-                if (response.status === 400) {
-                    $scope.dependantPages = response.data;
-                }
-            });
-        };
+            $scope.saveImageDetails = function (event) {
+                event.preventDefault();
+                var url = '/images/update/' + $scope.selectedImage.id;
+                $http.put(url, this.selectedImage).then((response) => {
+                    $scope.imageUpdateSuccess = true;
+                    $timeout(() => {
+                        $scope.imageUpdateSuccess = false;
+                    }, 3000);
+                }, (response) => {
+                    var errors = response.data;
+                    var message = '';
+                    Object.keys(errors).forEach((key) => {
+                        message += errors[key].join('\n');
+                    });
+                    $scope.imageUpdateFailure = message;
+                    $timeout(() => {
+                        $scope.imageUpdateFailure = false;
+                    }, 5000);
+                });
+            };
+
+            $scope.deleteImage = function (event) {
+                event.preventDefault();
+                var force = $scope.dependantPages !== false;
+                var url = '/images/' + $scope.selectedImage.id;
+                if (force) url += '?force=true';
+                $http.delete(url).then((response) => {
+                    $scope.images.splice($scope.images.indexOf($scope.selectedImage), 1);
+                    $scope.selectedImage = false;
+                    $scope.imageDeleteSuccess = true;
+                    $timeout(() => {
+                        $scope.imageDeleteSuccess = false;
+                    }, 3000);
+                }, (response) => {
+                    // Pages failure
+                    if (response.status === 400) {
+                        $scope.dependantPages = response.data;
+                    }
+                });
+            };
 
-    }]);
+        }]);
 
 
-    ngApp.controller('BookShowController', ['$scope', '$http', '$attrs', function($scope, $http, $attrs) {
+    ngApp.controller('BookShowController', ['$scope', '$http', '$attrs', function ($scope, $http, $attrs) {
         $scope.searching = false;
         $scope.searchTerm = '';
         $scope.searchResults = '';
@@ -151,7 +151,7 @@ module.exports = function(ngApp) {
             }
         };
 
-        $scope.clearSearch = function() {
+        $scope.clearSearch = function () {
             $scope.searching = false;
             $scope.searchTerm = '';
         };
index 4e936388b51f6840655551b0963d5c3cda74aa71..758f16cd2c5fdc75c4481cdf449e53f795c46572 100644 (file)
@@ -5,25 +5,25 @@ var toggleSwitchTemplate = require('./components/toggle-switch.html');
 var imagePickerTemplate = require('./components/image-picker.html');
 var dropZoneTemplate = require('./components/drop-zone.html');
 
-module.exports = function(ngApp) {
+module.exports = function (ngApp) {
 
     /**
      * Toggle Switches
      * Has basic on/off functionality.
      * Use string values of 'true' & 'false' to dictate the current state.
      */
-    ngApp.directive('toggleSwitch', function() {
+    ngApp.directive('toggleSwitch', function () {
         return {
             restrict: 'E',
             template: toggleSwitchTemplate,
             scope: true,
-            link: function(scope, element, attrs) {
+            link: function (scope, element, attrs) {
                 scope.name = attrs.name;
                 scope.value = attrs.value;
                 scope.isActive = scope.value == true && scope.value != 'false';
                 scope.value = (scope.value == true && scope.value != 'false') ? 'true' : 'false';
 
-                scope.switch = function() {
+                scope.switch = function () {
                     scope.isActive = !scope.isActive;
                     scope.value = scope.isActive ? 'true' : 'false';
                 }
@@ -37,7 +37,7 @@ module.exports = function(ngApp) {
      * Image Picker
      * Is a simple front-end interface that connects to an ImageManager if present.
      */
-    ngApp.directive('imagePicker', ['$http', 'imageManagerService', function($http, imageManagerService) {
+    ngApp.directive('imagePicker', ['$http', 'imageManagerService', function ($http, imageManagerService) {
         return {
             restrict: 'E',
             template: imagePickerTemplate,
@@ -52,7 +52,7 @@ module.exports = function(ngApp) {
                 defaultImage: '@',
                 imageClass: '@'
             },
-            link: function(scope, element, attrs) {
+            link: function (scope, element, attrs) {
                 var usingIds = typeof scope.currentId !== 'undefined' || scope.currentId === 'false';
                 scope.image = scope.currentImage;
                 scope.value = scope.currentImage || '';
@@ -62,22 +62,22 @@ module.exports = function(ngApp) {
                     scope.value = usingIds ? imageModel.id : imageUrl;
                 }
 
-                scope.reset = function() {
+                scope.reset = function () {
                     setImage({id: 0}, scope.defaultImage);
                 };
 
-                scope.remove = function() {
+                scope.remove = function () {
                     scope.image = 'none';
                     scope.value = 'none';
                 };
 
-                scope.showImageManager = function() {
+                scope.showImageManager = function () {
                     imageManagerService.show((image) => {
                         scope.updateImageFromModel(image);
                     });
                 };
 
-                scope.updateImageFromModel = function(model) {
+                scope.updateImageFromModel = function (model) {
                     var isResized = scope.resizeWidth && scope.resizeHeight;
 
                     if (!isResized) {
@@ -102,7 +102,7 @@ module.exports = function(ngApp) {
      * DropZone
      * Used for uploading images
      */
-    ngApp.directive('dropZone', [function() {
+    ngApp.directive('dropZone', [function () {
         return {
             restrict: 'E',
             template: dropZoneTemplate,
@@ -111,26 +111,32 @@ module.exports = function(ngApp) {
                 eventSuccess: '=',
                 eventError: '='
             },
-            link: function(scope, element, attrs) {
+            link: function (scope, element, attrs) {
                 var dropZone = new DropZone(element[0].querySelector('.dropzone-container'), {
                     url: scope.uploadUrl,
-                    init: function() {
+                    init: function () {
                         var dz = this;
-                        dz.on('sending', function(file, xhr, data) {
+                        dz.on('sending', function (file, xhr, data) {
                             var token = window.document.querySelector('meta[name=token]').getAttribute('content');
                             data.append('_token', token);
                         });
                         if (typeof scope.eventSuccess !== 'undefined') dz.on('success', scope.eventSuccess);
-                        dz.on('success', function(file, data) {
+                        dz.on('success', function (file, data) {
                             $(file.previewElement).fadeOut(400, function () {
                                 dz.removeFile(file);
                             });
                         });
                         if (typeof scope.eventError !== 'undefined') dz.on('error', scope.eventError);
                         dz.on('error', function (file, errorMessage, xhr) {
-                            if (errorMessage.file) {
-                                $(file.previewElement).find('[data-dz-errormessage]').text(errorMessage.file[0]);
+                            console.log(errorMessage);
+                            console.log(xhr);
+                            function setMessage(message) {
+                                $(file.previewElement).find('[data-dz-errormessage]').text(message);
                             }
+
+                            if (xhr.status === 413) setMessage('The server does not allow uploads of this size. Please try a smaller file.');
+                            if (errorMessage.file) setMessage(errorMessage.file[0]);
+
                         });
                     }
                 });
@@ -139,14 +145,14 @@ module.exports = function(ngApp) {
     }]);
 
 
-    ngApp.directive('dropdown', [function() {
+    ngApp.directive('dropdown', [function () {
         return {
             restrict: 'A',
-            link: function(scope, element, attrs) {
+            link: function (scope, element, attrs) {
                 var menu = element.find('ul');
-                element.find('[dropdown-toggle]').on('click', function() {
+                element.find('[dropdown-toggle]').on('click', function () {
                     menu.show().addClass('anim menuIn');
-                    element.mouseleave(function() {
+                    element.mouseleave(function () {
                         menu.hide();
                         menu.removeClass('anim menuIn');
                     });
index e740654fd2a5d8d8ef03bea0d569a5aad2717c30..2cd45e5bcd4c747d02d033ffc8e56dd6d3acf75a 100644 (file)
@@ -18,8 +18,8 @@ var controllers = require('./controllers')(ngApp);
 //Global jQuery Config & Extensions
 
 // Smooth scrolling
-jQuery.fn.smoothScrollTo = function() {
-    if(this.length === 0) return;
+jQuery.fn.smoothScrollTo = function () {
+    if (this.length === 0) return;
     $('body').animate({
         scrollTop: this.offset().top - 60 // Adjust to change final scroll position top margin
     }, 800); // Adjust to change animations speed (ms)
@@ -27,8 +27,8 @@ jQuery.fn.smoothScrollTo = function() {
 };
 
 // Making contains text expression not worry about casing
-$.expr[":"].contains = $.expr.createPseudo(function(arg) {
-    return function( elem ) {
+$.expr[":"].contains = $.expr.createPseudo(function (arg) {
+    return function (elem) {
         return $(elem).text().toUpperCase().indexOf(arg.toUpperCase()) >= 0;
     };
 });
@@ -42,7 +42,7 @@ $(function () {
     });
 
     // Chapter page list toggles
-    $('.chapter-toggle').click(function(e) {
+    $('.chapter-toggle').click(function (e) {
         e.preventDefault();
         $(this).toggleClass('open');
         $(this).closest('.chapter').find('.inset-list').slideToggle(180);
@@ -56,7 +56,7 @@ function elemExists(selector) {
 }
 
 // TinyMCE editor
-if(elemExists('#html-editor')) {
+if (elemExists('#html-editor')) {
     var tinyMceOptions = require('./pages/page-form');
     tinymce.init(tinyMceOptions);
 }
\ No newline at end of file
index cadccb59cfc79cd7772e9f7aaffd8ddff1dc0e4a..b5773ec7d527500e88f70c42a6b6bbc9601003c0 100644 (file)
@@ -1,4 +1,3 @@
-
 module.exports = {
     selector: '#html-editor',
     content_css: [
@@ -27,13 +26,13 @@ module.exports = {
         {title: "Code Block", icon: "code", format: "pre"},
         {title: "Inline Code", icon: "code", inline: "code"}
     ],
-    formats : {
-        alignleft : {selector : 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table,img', classes : 'align-left'},
-        aligncenter : {selector : 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table,img', classes : 'align-center'},
-        alignright : {selector : 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table,img', classes : 'align-right'},
+    formats: {
+        alignleft: {selector: 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table,img', classes: 'align-left'},
+        aligncenter: {selector: 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table,img', classes: 'align-center'},
+        alignright: {selector: 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table,img', classes: 'align-right'},
     },
-    file_browser_callback: function(field_name, url, type, win) {
-        ImageManager.show(function(image) {
+    file_browser_callback: function (field_name, url, type, win) {
+        ImageManager.show(function (image) {
             win.document.getElementById(field_name).value = image.url;
             if ("createEvent" in document) {
                 var evt = document.createEvent("HTMLEvents");
@@ -44,63 +43,63 @@ module.exports = {
             }
         });
     },
-    paste_preprocess: function(plugin, args) {
+    paste_preprocess: function (plugin, args) {
         var content = args.content;
-        if(content.indexOf('<img src="file://') !== -1) {
+        if (content.indexOf('<img src="file://') !== -1) {
             args.content = '';
         }
     },
-    setup: function(editor) {
+    setup: function (editor) {
 
-        ( function() {
+        (function () {
             var wrap;
 
-            function hasTextContent( node ) {
-                return node && !! ( node.textContent || node.innerText );
+            function hasTextContent(node) {
+                return node && !!( node.textContent || node.innerText );
             }
 
-            editor.on( 'dragstart', function() {
+            editor.on('dragstart', function () {
                 var node = editor.selection.getNode();
 
-                if ( node.nodeName === 'IMG' ) {
-                    wrap = editor.dom.getParent( node, '.mceTemp' );
+                if (node.nodeName === 'IMG') {
+                    wrap = editor.dom.getParent(node, '.mceTemp');
 
-                    if ( ! wrap && node.parentNode.nodeName === 'A' && ! hasTextContent( node.parentNode ) ) {
+                    if (!wrap && node.parentNode.nodeName === 'A' && !hasTextContent(node.parentNode)) {
                         wrap = node.parentNode;
                     }
                 }
-            } );
+            });
 
-            editor.on( 'drop', function( event ) {
+            editor.on('drop', function (event) {
                 var dom = editor.dom,
-                    rng = tinymce.dom.RangeUtils.getCaretRangeFromPoint( event.clientX, event.clientY, editor.getDoc() );
+                    rng = tinymce.dom.RangeUtils.getCaretRangeFromPoint(event.clientX, event.clientY, editor.getDoc());
 
                 // Don't allow anything to be dropped in a captioned image.
-                if ( dom.getParent( rng.startContainer, '.mceTemp' ) ) {
+                if (dom.getParent(rng.startContainer, '.mceTemp')) {
                     event.preventDefault();
-                } else if ( wrap ) {
+                } else if (wrap) {
                     event.preventDefault();
 
-                    editor.undoManager.transact( function() {
-                        editor.selection.setRng( rng );
-                        editor.selection.setNode( wrap );
-                        dom.remove( wrap );
-                    } );
+                    editor.undoManager.transact(function () {
+                        editor.selection.setRng(rng);
+                        editor.selection.setNode(wrap);
+                        dom.remove(wrap);
+                    });
                 }
 
                 wrap = null;
-            } );
-        } )();
+            });
+        })();
 
         // Image picker button
         editor.addButton('image-insert', {
             title: 'My title',
             icon: 'image',
             tooltip: 'Insert an image',
-            onclick: function() {
-                window.ImageManager.showExternal(function(image) {
-                    var html = '<a href="'+image.url+'" target="_blank">';
-                    html += '<img src="'+image.thumbs.display+'" alt="'+image.name+'">';
+            onclick: function () {
+                window.ImageManager.showExternal(function (image) {
+                    var html = '<a href="' + image.url + '" target="_blank">';
+                    html += '<img src="' + image.thumbs.display + '" alt="' + image.name + '">';
                     html += '</a>';
                     editor.execCommand('mceInsertContent', false, html);
                 });
@@ -108,10 +107,10 @@ module.exports = {
         });
 
         // Paste image-uploads
-        editor.on('paste', function(e) {
-            if(e.clipboardData) {
+        editor.on('paste', function (e) {
+            if (e.clipboardData) {
                 var items = e.clipboardData.items;
-                if (items){
+                if (items) {
                     for (var i = 0; i < items.length; i++) {
                         if (items[i].type.indexOf("image") !== -1) {
 
@@ -128,14 +127,14 @@ module.exports = {
                             }
 
                             var id = "image-" + Math.random().toString(16).slice(2);
-                            editor.execCommand('mceInsertContent', false, '<img src="/loading.gif" id="'+id+'">');
+                            editor.execCommand('mceInsertContent', false, '<img src="/loading.gif" id="' + id + '">');
 
                             var remoteFilename = "image-" + Date.now() + "." + ext;
                             formData.append('file', file, remoteFilename);
                             formData.append('_token', document.querySelector('meta[name="token"]').getAttribute('content'));
 
                             xhr.open('POST', '/upload/image');
-                            xhr.onload = function() {
+                            xhr.onload = function () {
                                 if (xhr.status === 200 || xhr.status === 201) {
                                     var result = JSON.parse(xhr.responseText);
                                     editor.dom.setAttrib(id, 'src', result.url);
index 3b3ce7d9ca67e88e6f811b7d2863606fbb73c506..babbad0c10395aa471816226fa647ed67871e817 100644 (file)
@@ -32,6 +32,7 @@
     font-weight: 300;
   }
 }
+
 #image-manager .dropzone-container {
   position: relative;
   border: 3px dashed #DDD;
@@ -52,7 +53,7 @@
   width: (100%/6);
   height: auto;
   border: 1px solid #FFF;
-  transition: all cubic-bezier(.4,0,1,1) 160ms;
+  transition: all cubic-bezier(.4, 0, 1, 1) 160ms;
   &.selected {
     transform: scale3d(0.92, 0.92, 0.92);
   }
@@ -77,6 +78,7 @@
   padding: 0 $-l;
   border-left: 1px solid #DDD;
 }
+
 .image-manager-close {
   position: absolute;
   top: 0;
@@ -84,6 +86,7 @@
   margin: 0;
   border-radius: 0;
 }
+
 .image-manager-list {
   overflow-y: scroll;
   flex: 1;
   flex: 1;
 }
 
-
-
-
 // Dropzone
 /*
  * The MIT License
   padding: $-xl $-m;
   transition: all ease-in-out 120ms;
 }
+
 .dz-drag-hover .dz-message {
   background-color: rgb(16, 126, 210);
   color: #EEE;
 }
+
 @keyframes passing-through {
   0% {
     opacity: 0;
-    transform: translateY(40px); }
+    transform: translateY(40px);
+  }
   30%, 70% {
     opacity: 1;
-    transform: translateY(0px); }
+    transform: translateY(0px);
+  }
   100% {
     opacity: 0;
-    transform: translateY(-40px); } }
+    transform: translateY(-40px);
+  }
+}
 
 @keyframes slide-in {
   0% {
     opacity: 0;
-    transform: translateY(40px); }
+    transform: translateY(40px);
+  }
   30% {
     opacity: 1;
-    transform: translateY(0px); } }
+    transform: translateY(0px);
+  }
+}
+
 @keyframes pulse {
   0% {
-    transform: scale(1); }
+    transform: scale(1);
+  }
   10% {
-    transform: scale(1.1); }
+    transform: scale(1.1);
+  }
   20% {
-    transform: scale(1); } }
-.dropzone, .dropzone * {
-  box-sizing: border-box; }
+    transform: scale(1);
+  }
+}
 
+.dropzone, .dropzone * {
+  box-sizing: border-box;
+}
 
 .dz-preview {
   position: relative;
   display: inline-block;
   vertical-align: top;
   margin: 12px;
-  min-height: 80px; }
+  min-height: 80px;
+}
+
 .dz-preview:hover {
-  z-index: 1000; }
+  z-index: 1000;
+}
+
 .dz-preview:hover .dz-details {
-  opacity: 1; }
+  opacity: 1;
+}
+
 .dz-preview.dz-file-preview .dz-image {
   border-radius: 4px;
   background: #999;
-  background: linear-gradient(to bottom, #eee, #ddd); }
+  background: linear-gradient(to bottom, #eee, #ddd);
+}
+
 .dz-preview.dz-file-preview .dz-details {
-  opacity: 1; }
+  opacity: 1;
+}
+
 .dz-preview.dz-image-preview {
-  background: white; }
+  background: white;
+}
+
 .dz-preview.dz-image-preview .dz-details {
-  transition: opacity 0.2s linear; }
+  transition: opacity 0.2s linear;
+}
+
 .dz-preview .dz-remove {
   font-size: 14px;
   text-align: center;
   display: block;
   cursor: pointer;
-  border: none; }
+  border: none;
+}
+
 .dz-preview .dz-remove:hover {
-  text-decoration: underline; }
+  text-decoration: underline;
+}
+
 .dz-preview:hover .dz-details {
-  opacity: 1; }
+  opacity: 1;
+}
+
 .dz-preview .dz-details {
   z-index: 20;
   position: absolute;
   padding: 6px 3px;
   text-align: center;
   color: rgba(0, 0, 0, 0.9);
-  line-height: 150%; }
+  line-height: 150%;
+}
+
 .dz-preview .dz-details .dz-size {
   margin-bottom: 0.5em;
-  font-size: 12px; }
+  font-size: 12px;
+}
+
 .dz-preview .dz-details .dz-filename {
-  white-space: nowrap; }
+  white-space: nowrap;
+}
+
 .dz-preview .dz-details .dz-filename:hover span {
   border: 1px solid rgba(200, 200, 200, 0.8);
-  background-color: rgba(255, 255, 255, 0.8); }
+  background-color: rgba(255, 255, 255, 0.8);
+}
+
 .dz-preview .dz-details .dz-filename:not(:hover) {
   overflow: hidden;
-  text-overflow: ellipsis; }
+  text-overflow: ellipsis;
+}
+
 .dz-preview .dz-details .dz-filename:not(:hover) span {
-  border: 1px solid transparent; }
+  border: 1px solid transparent;
+}
+
 .dz-preview .dz-details .dz-filename span, .dz-preview .dz-details .dz-size span {
   background-color: rgba(255, 255, 255, 0.4);
   padding: 0 0.4em;
-  border-radius: 3px; }
+  border-radius: 3px;
+}
+
 .dz-preview:hover .dz-image img {
-  filter: blur(8px); }
+  filter: blur(8px);
+}
+
 .dz-preview .dz-image {
   border-radius: 4px;
   overflow: hidden;
   height: 80px;
   position: relative;
   display: block;
-  z-index: 10; }
+  z-index: 10;
+}
+
 .dz-preview .dz-image img {
-  display: block; }
+  display: block;
+}
+
 .dz-preview.dz-success .dz-success-mark {
-  animation: passing-through 3s cubic-bezier(0.77, 0, 0.175, 1); }
+  animation: passing-through 3s cubic-bezier(0.77, 0, 0.175, 1);
+}
+
 .dz-preview.dz-error .dz-error-mark {
   opacity: 1;
-  animation: slide-in 3s cubic-bezier(0.77, 0, 0.175, 1); }
+  animation: slide-in 3s cubic-bezier(0.77, 0, 0.175, 1);
+}
+
 .dz-preview .dz-success-mark, .dz-preview .dz-error-mark {
   pointer-events: none;
   opacity: 0;
   top: 50%;
   left: 50%;
   margin-left: -27px;
-  margin-top: -27px; }
+  margin-top: -27px;
+}
+
 .dz-preview .dz-success-mark svg, .dz-preview .dz-error-mark svg {
   display: block;
   width: 54px;
-  height: 54px; }
+  height: 54px;
+}
+
 .dz-preview.dz-processing .dz-progress {
   opacity: 1;
-  transition: all 0.2s linear; }
+  transition: all 0.2s linear;
+}
+
 .dz-preview.dz-complete .dz-progress {
   opacity: 0;
-  transition: opacity 0.4s ease-in; }
+  transition: opacity 0.4s ease-in;
+}
+
 .dz-preview:not(.dz-processing) .dz-progress {
-  animation: pulse 6s ease infinite; }
+  animation: pulse 6s ease infinite;
+}
+
 .dz-preview .dz-progress {
   opacity: 1;
   z-index: 1000;
   background: rgba(255, 255, 255, 0.9);
   transform: scale(1);
   border-radius: 8px;
-  overflow: hidden; }
+  overflow: hidden;
+}
+
 .dz-preview .dz-progress .dz-upload {
   background: #333;
   background: linear-gradient(to bottom, #666, #444);
   left: 0;
   bottom: 0;
   width: 0;
-  transition: width 300ms ease-in-out; }
+  transition: width 300ms ease-in-out;
+}
+
 .dz-preview.dz-error .dz-error-message {
-  display: block; }
+  display: block;
+}
+
 .dz-preview.dz-error:hover .dz-error-message {
   opacity: 1;
-  pointer-events: auto; }
+  pointer-events: auto;
+}
+
 .dz-preview .dz-error-message {
   pointer-events: none;
   z-index: 1000;
   display: none;
   opacity: 0;
   transition: opacity 0.3s ease;
-  border-radius: 8px;
-  font-size: 13px;
-  top: 130px;
-  left: -10px;
-  width: 140px;
-  background: #be2626;
-  background: linear-gradient(to bottom, #be2626, #a92222);
-  padding: 0.5em 1.2em;
-  color: white; }
+  border-radius: 4px;
+  font-size: 11.5px;
+  line-height: 1.2;
+  top: 88px;
+  left: -26px;
+  width: 148px;
+  background: $negative;
+  padding: $-xs;
+  color: white;
+}
+
 .dz-preview .dz-error-message:after {
   content: '';
   position: absolute;
   height: 0;
   border-left: 6px solid transparent;
   border-right: 6px solid transparent;
-  border-bottom: 6px solid #be2626; }
+  border-bottom: 6px solid $negative;
+}
Morty Proxy This is a proxified and sanitized view of the page, visit original site.