UX: Lightbox support for image uploader. (#7034)

UX: Lightbox support for image uploader. (#7034)

diff --git a/app/assets/javascripts/discourse/components/image-uploader.js.es6 b/app/assets/javascripts/discourse/components/image-uploader.js.es6
index 9ebb3f9..1f73661 100644
--- a/app/assets/javascripts/discourse/components/image-uploader.js.es6
+++ b/app/assets/javascripts/discourse/components/image-uploader.js.es6
@@ -1,9 +1,25 @@
-import computed from "ember-addons/ember-computed-decorators";
+import {
+  default as computed,
+  observes
+} from "ember-addons/ember-computed-decorators";
+
 import UploadMixin from "discourse/mixins/upload";
+import lightbox from "discourse/lib/lightbox";
+import { ajax } from "discourse/lib/ajax";
+import { popupAjaxError } from "discourse/lib/ajax-error";
 
 export default Ember.Component.extend(UploadMixin, {
   classNames: ["image-uploader"],
-  infoHidden: true,
+
+  init() {
+    this._super(...arguments);
+    this._applyLightbox();
+  },
+
+  willDestroyElement() {
+    this._super(...arguments);
+    $("a.lightbox").magnificPopup("close");
+  },
 
   @computed("imageUrl")
   backgroundStyle(imageUrl) {
@@ -20,11 +36,6 @@ export default Ember.Component.extend(UploadMixin, {
     return imageUrl.split("/").slice(-1)[0];
   },
 
-  @computed("infoHidden", "imageBaseName")
-  showInfo(infoHidden, imageBaseName) {
-    return !infoHidden && imageBaseName;
-  },
-
   @computed("backgroundStyle")
   hasBackgroundStyle(backgroundStyle) {
     return !Ember.isEmpty(backgroundStyle.string);
@@ -35,16 +46,51 @@ export default Ember.Component.extend(UploadMixin, {
   },
 
   uploadDone(upload) {
-    this.setProperties({ imageUrl: upload.url, imageId: upload.id });
+    this.setProperties({
+      imageUrl: upload.url,
+      imageId: upload.id,
+      imageFilesize: upload.human_filesize,
+      imageFilename: upload.original_filename,
+      imageWidth: upload.width,
+      imageHeight: upload.height
+    });
+
+    this._applyLightbox();
 
     if (this.onUploadDone) {
       this.onUploadDone(upload);
     }
   },
 
+  _openLightbox() {
+    Ember.run.next(() => this.$("a.lightbox").magnificPopup("open"));
+  },
+
+  _applyLightbox() {
+    if (this.get("imageUrl")) Ember.run.next(() => lightbox(this.$()));
+  },
+
   actions: {
-    toggleInfo() {
-      this.toggleProperty("infoHidden");
+    toggleLightbox() {
+      if (this.get("imageFilename")) {
+        this._openLightbox();
+      } else {
+        ajax(`/uploads/lookup-metadata`, {
+          type: "POST",
+          data: { url: this.get("imageUrl") }
+        })
+          .then(json => {
+            this.setProperties({
+              imageFilename: json.original_filename,
+              imageFilesize: json.human_filesize,
+              imageWidth: json.width,
+              imageHeight: json.height
+            });
+
+            this._openLightbox();
+          })
+          .catch(popupAjaxError);
+      }
     },
 
     trash() {
diff --git a/app/assets/javascripts/discourse/templates/components/image-uploader.hbs b/app/assets/javascripts/discourse/templates/components/image-uploader.hbs
index 0014d71..d0769d0 100644
--- a/app/assets/javascripts/discourse/templates/components/image-uploader.hbs
+++ b/app/assets/javascripts/discourse/templates/components/image-uploader.hbs
@@ -9,18 +9,28 @@
       <button {{action "trash"}} class="btn btn-danger pad-left no-text">{{d-icon "far-trash-alt"}}</button>
     {{/if}}
 
-    {{#if imageBaseName}}
-      {{d-button icon="info-circle" class="btn image-uploader-info-btn no-text"
-                                    title="upload_selector.filename"
-                                    action=(action "toggleInfo")}}
+    {{#if imageUrl}}
+      {{d-button icon="discourse-expand"
+          title='expand'
+          class="btn image-uploader-lightbox-btn no-text"
+          action=(action "toggleLightbox")}}
     {{/if}}
 
     <span class="btn {{unless uploading 'hidden'}}">{{i18n 'upload_selector.uploading'}} {{uploadProgress}}%</span>
   </div>
 
-  {{#if showInfo}}
-    <div class="image-uploader-info">
-      <a href={{imageUrl}} target="_blank">{{imageBaseName}}</a>
-    </div>
+
+  {{#if imageUrl}}
+    <a class="lightbox"
+       href={{imageUrl}}
+       title={{imageFilename}}
+       rel="nofollow noopener">
+
+      <div class="meta">
+        <span class="informations">
+          {{imageWidth}}x{{imageHeight}} {{imageFilesize}}
+        </span>
+      </div>
+    </a>
   {{/if}}
 </div>
diff --git a/app/assets/stylesheets/common/base/upload.scss b/app/assets/stylesheets/common/base/upload.scss
index f7f3d8c..d52ec8c 100644
--- a/app/assets/stylesheets/common/base/upload.scss
+++ b/app/assets/stylesheets/common/base/upload.scss
@@ -3,26 +3,6 @@
   background-size: cover;
   position: relative;
 
-  .image-uploader-info {
-    position: absolute;
-    bottom: 0;
-    width: 100%;
-    background: $primary;
-    text-align: center;
-    overflow: hidden;
-    white-space: nowrap;
-    text-overflow: ellipsis;
-    opacity: 0.6;
-
-    a {
-      color: $secondary;
-
-      &:hover {
-        text-decoration: underline;
-      }
-    }
-  }
-
   .image-upload-controls {
     display: flex;
 
@@ -30,7 +10,7 @@
       margin-right: 5px;
     }
 
-    .image-uploader-info-btn {
+    .image-uploader-lightbox-btn {
       background: none;
       margin-right: 0;
       margin-left: auto;
diff --git a/app/controllers/uploads_controller.rb b/app/controllers/uploads_controller.rb
index 481d5d9..a3af31c 100644
--- a/app/controllers/uploads_controller.rb
+++ b/app/controllers/uploads_controller.rb
@@ -86,6 +86,19 @@ class UploadsController < ApplicationController
     end
   end
 
+  def metadata
+    params.require(:url)
+    upload = Upload.get_from_url(params[:url])
+    raise Discourse::NotFound unless upload
+
+    render json: {
+      original_filename: upload.original_filename,
+      width: upload.width,
+      height: upload.height,
+      human_filesize: upload.human_filesize
+    }
+  end
+
   protected
 
   def render_404
diff --git a/app/models/upload.rb b/app/models/upload.rb
index 7f58ed2..3cf5fb6 100644
--- a/app/models/upload.rb
+++ b/app/models/upload.rb
@@ -7,6 +7,8 @@ require_dependency "file_store/local_store"
 require_dependency "base62"
 
 class Upload < ActiveRecord::Base
+  include ActionView::Helpers::NumberHelper
+
   SHA1_LENGTH = 40
 
   belongs_to :user
@@ -208,6 +210,10 @@ class Upload < ActiveRecord::Base
     upload || Upload.find_by("url LIKE ?", "%#{data[1]}")
   end
 
+  def human_filesize
+    number_to_human_size(self.filesize)
+  end
+
   def self.migrate_to_new_scheme(limit = nil)
     problems = []
 
diff --git a/app/serializers/upload_serializer.rb b/app/serializers/upload_serializer.rb
index 9e2098b..5aeee22 100644
--- a/app/serializers/upload_serializer.rb
+++ b/app/serializers/upload_serializer.rb
@@ -9,5 +9,6 @@ class UploadSerializer < ApplicationSerializer
              :thumbnail_height,
              :extension,
              :short_url,
-             :retain_hours
+             :retain_hours,
+             :human_filesize
 end
diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml
index aedce12..5c23e09 100644
--- a/config/locales/client.en.yml
+++ b/config/locales/client.en.yml
@@ -206,6 +206,7 @@ en:
         us_west_2: "US West (Oregon)"
 
     edit: "edit the title and category of this topic"
+    expand: "Expand"
     not_implemented: "That feature hasn't been implemented yet, sorry!"
     no_value: "No"
     yes_value: "Yes"
@@ -1569,7 +1570,6 @@ en:
       select_file: "Select File"
       image_link: "link your image will point to"
       default_image_alt_text: image
-      filename: "Filename"
 
     search:
       sort_by: "Sort by"
diff --git a/config/routes.rb b/config/routes.rb
index cf38a68..2ea0ce8 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -461,6 +461,7 @@ Discourse::Application.routes.draw do
   get "stylesheets/:name.css" => "stylesheets#show", constraints: { name: /[-a-z0-9_]+/ }

[... diff too long, it was truncated ...]

GitHub sha: 58b0e945

This commit has been mentioned on Discourse Meta. There might be relevant details there: