• 
      

    DnD inline images frontend.

    Review Request #8147 — Created May 6, 2016 and submitted

    Information

    Review Board
    release-3.0.x
    4db0143...

    Reviewers

    This change implements the frontend for letting users drag-and-drop images into
    their markdown editors. This will upload the image as a user file attachment
    and insert the relevant markdown syntax into the editor.

    This is based on work by David Kus at https://reviews.reviewboard.org/r/6510/
    Compared to that change, I've reworked the UI a bit to avoid the overlapping
    drop targets (the review request file attachments drop target is now isolated
    to the "Files" section, which appears momentarily if it wasn't already
    visible). I've also done a bunch of refactoring of the code to modernize and
    clean it up.

    At the moment, this adds overlays over the entire text field, and will insert
    the markdown text as a new line wherever the cursor is. I'd like to improve
    this in the future to make it more obvious where the new entry will end up
    (basically moving the cursor during the dragover with inline feedback) but
    that's a larger change.

    • Dragged images into a variety of text fields.
    • Dragged files to create new file attachments.
    • Ran unit tests.
    • Ran js-tests.
    Description From Last Updated

    Since RB.BaseResource.prototype.defaults is a method that returns an object fo extra data, we'll want to make this a function.

    brenniebrennie

    Can we do: const url = `${SITE_ROOT}api/users/${this.get('username')}/file-attachments/`; or similar?

    brenniebrennie

    you can use { $target } here as shorthand for { $target: $target }

    brenniebrennie

    You can do: const target = new DnDDropTarget({ $target, dropText, callback });

    brenniebrennie

    Why do we need the !important? Can we rework things to not need it?

    chipx86chipx86

    What does the 64px relate to? Can we add a constant?

    chipx86chipx86

    Can we add constants for these colors and border size?

    chipx86chipx86

    Can we use a relative font size (percentage)?

    chipx86chipx86

    Same here.

    chipx86chipx86

    Should use the standard multi-line comment format.

    chipx86chipx86

    Are we limiting this exclusively to images? I can think of other file formats that would be useful in discussions.

    chipx86chipx86

    "append"

    chipx86chipx86

    This is too long.

    chipx86chipx86

    While the new shorthand in ES6 probably has some good uses, I think it's not very future-proof. If anyone ever …

    chipx86chipx86

    One too many "anys," probably.

    chipx86chipx86

    You can do this.el.value += `\n${text}`; here

    brenniebrennie

    Same here.

    brenniebrennie

    (Almost) the same here.

    brenniebrennie

    And here.

    brenniebrennie

    Should these be .jpeg etc? Because I couldn't I upload foojpeg and it would allow it? Or do something like: …

    brenniebrennie

    You can do callback() {} in the object literal.

    brenniebrennie

    Can we put the comparison in parens, to help visually distinguish it better from the => ?

    chipx86chipx86
    reviewbot
    1. Tool: Pyflakes
      Processed Files:
          reviewboard/staticbundles.py
      
      Ignored Files:
          reviewboard/static/rb/js/resources/models/tests/userFileAttachmentModelTests.js
          reviewboard/static/rb/css/ui/dnd-uploader.less
          reviewboard/static/rb/js/resources/models/userFileAttachmentModel.es6.js
          reviewboard/static/rb/js/ui/views/textEditorView.es6.js
          reviewboard/static/rb/js/views/dndUploaderView.es6.js
          reviewboard/static/rb/js/pages/views/tests/reviewablePageViewTests.js
          reviewboard/static/rb/js/views/reviewReplyEditorView.js
          reviewboard/templates/reviews/review_request_box.html
          reviewboard/static/rb/css/pages/reviews.less
          reviewboard/static/rb/js/ui/views/tests/textEditorViewTests.js
          reviewboard/static/rb/css/common.less
          reviewboard/static/rb/css/defs.less
          reviewboard/static/rb/js/views/reviewRequestEditorView.js
          reviewboard/static/rb/js/pages/views/reviewablePageView.js
      
      
      
      Tool: PEP8 Style Checker
      Processed Files:
          reviewboard/staticbundles.py
      
      Ignored Files:
          reviewboard/static/rb/js/resources/models/tests/userFileAttachmentModelTests.js
          reviewboard/static/rb/css/ui/dnd-uploader.less
          reviewboard/static/rb/js/resources/models/userFileAttachmentModel.es6.js
          reviewboard/static/rb/js/ui/views/textEditorView.es6.js
          reviewboard/static/rb/js/views/dndUploaderView.es6.js
          reviewboard/static/rb/js/pages/views/tests/reviewablePageViewTests.js
          reviewboard/static/rb/js/views/reviewReplyEditorView.js
          reviewboard/templates/reviews/review_request_box.html
          reviewboard/static/rb/css/pages/reviews.less
          reviewboard/static/rb/js/ui/views/tests/textEditorViewTests.js
          reviewboard/static/rb/css/common.less
          reviewboard/static/rb/css/defs.less
          reviewboard/static/rb/js/views/reviewRequestEditorView.js
          reviewboard/static/rb/js/pages/views/reviewablePageView.js
      
      
    2. 
        
    brennie
    1. 
        
    2. Show all issues

      Since RB.BaseResource.prototype.defaults is a method that returns an object fo extra data, we'll want to make this a function.

      1. We can just call it as a function, actually.

        Looks like there are several other places with the same issue. I'll fix those up in a separate change.

    3. Show all issues

      Can we do:

      const url = `${SITE_ROOT}api/users/${this.get('username')}/file-attachments/`;
      

      or similar?

    4. Show all issues

      you can use { $target } here as shorthand for { $target: $target }

    5. reviewboard/static/rb/js/views/dndUploaderView.es6.js (Diff revision 1)
       
       
       
       
       
       
      Show all issues

      You can do:

      const target = new DnDDropTarget({
          $target,
          dropText,
          callback
      });
      
    6. 
        
    david
    reviewbot
    1. Tool: Pyflakes
      Processed Files:
          reviewboard/staticbundles.py
      
      Ignored Files:
          reviewboard/static/rb/js/resources/models/tests/userFileAttachmentModelTests.js
          reviewboard/static/rb/css/ui/dnd-uploader.less
          reviewboard/static/rb/js/resources/models/userFileAttachmentModel.es6.js
          reviewboard/static/rb/js/ui/views/textEditorView.es6.js
          reviewboard/static/rb/js/views/dndUploaderView.es6.js
          reviewboard/static/rb/js/pages/views/tests/reviewablePageViewTests.js
          reviewboard/static/rb/js/views/reviewReplyEditorView.js
          reviewboard/templates/reviews/review_request_box.html
          reviewboard/static/rb/css/pages/reviews.less
          reviewboard/static/rb/js/ui/views/tests/textEditorViewTests.js
          reviewboard/static/rb/css/common.less
          reviewboard/static/rb/css/defs.less
          reviewboard/static/rb/js/views/reviewRequestEditorView.js
          reviewboard/static/rb/js/pages/views/reviewablePageView.js
      
      
      
      Tool: PEP8 Style Checker
      Processed Files:
          reviewboard/staticbundles.py
      
      Ignored Files:
          reviewboard/static/rb/js/resources/models/tests/userFileAttachmentModelTests.js
          reviewboard/static/rb/css/ui/dnd-uploader.less
          reviewboard/static/rb/js/resources/models/userFileAttachmentModel.es6.js
          reviewboard/static/rb/js/ui/views/textEditorView.es6.js
          reviewboard/static/rb/js/views/dndUploaderView.es6.js
          reviewboard/static/rb/js/pages/views/tests/reviewablePageViewTests.js
          reviewboard/static/rb/js/views/reviewReplyEditorView.js
          reviewboard/templates/reviews/review_request_box.html
          reviewboard/static/rb/css/pages/reviews.less
          reviewboard/static/rb/js/ui/views/tests/textEditorViewTests.js
          reviewboard/static/rb/css/common.less
          reviewboard/static/rb/css/defs.less
          reviewboard/static/rb/js/views/reviewRequestEditorView.js
          reviewboard/static/rb/js/pages/views/reviewablePageView.js
      
      
    2. 
        
    david
    reviewbot
    1. Tool: PEP8 Style Checker
      Processed Files:
          reviewboard/staticbundles.py
      
      Ignored Files:
          reviewboard/static/rb/js/resources/models/tests/userFileAttachmentModelTests.js
          reviewboard/static/rb/css/ui/dnd-uploader.less
          reviewboard/static/rb/js/resources/models/userFileAttachmentModel.es6.js
          reviewboard/static/rb/js/ui/views/textEditorView.es6.js
          reviewboard/static/rb/js/views/dndUploaderView.es6.js
          reviewboard/static/rb/js/pages/views/tests/reviewablePageViewTests.js
          reviewboard/static/rb/js/views/reviewReplyEditorView.js
          reviewboard/templates/reviews/review_request_box.html
          reviewboard/static/rb/css/pages/reviews.less
          reviewboard/static/rb/js/ui/views/tests/textEditorViewTests.js
          reviewboard/static/rb/css/common.less
          reviewboard/static/rb/css/defs.less
          reviewboard/static/rb/js/views/reviewRequestEditorView.js
          reviewboard/static/rb/js/pages/views/reviewablePageView.js
      
      
      
      Tool: Pyflakes
      Processed Files:
          reviewboard/staticbundles.py
      
      Ignored Files:
          reviewboard/static/rb/js/resources/models/tests/userFileAttachmentModelTests.js
          reviewboard/static/rb/css/ui/dnd-uploader.less
          reviewboard/static/rb/js/resources/models/userFileAttachmentModel.es6.js
          reviewboard/static/rb/js/ui/views/textEditorView.es6.js
          reviewboard/static/rb/js/views/dndUploaderView.es6.js
          reviewboard/static/rb/js/pages/views/tests/reviewablePageViewTests.js
          reviewboard/static/rb/js/views/reviewReplyEditorView.js
          reviewboard/templates/reviews/review_request_box.html
          reviewboard/static/rb/css/pages/reviews.less
          reviewboard/static/rb/js/ui/views/tests/textEditorViewTests.js
          reviewboard/static/rb/css/common.less
          reviewboard/static/rb/css/defs.less
          reviewboard/static/rb/js/views/reviewRequestEditorView.js
          reviewboard/static/rb/js/pages/views/reviewablePageView.js
      
      
    2. 
        
    chipx86
    1. Can you upload some screenshots? Would love to see this.

      1. A video/animation would also be very cool for this.

      2. Will make one tomorrow. I do want to tweak the visuals a bit but this change was getting pretty big already.

    2. 
        
    chipx86
    1. 
        
    2. Show all issues

      Why do we need the !important? Can we rework things to not need it?

      1. We do need it. The files box is shown in jquery using show() and hide(), which updates the inline style in the DOM. This needs to take precedence over that.

    3. Show all issues

      What does the 64px relate to? Can we add a constant?

      1. It's just pulled out of a hat. I'll add a comment.

    4. reviewboard/static/rb/css/ui/dnd-uploader.less (Diff revision 3)
       
       
       
       
       
      Show all issues

      Can we add constants for these colors and border size?

      1. Constants are useful when things are used more than once. In this case they're not.

      2. I've been trying to move all "theme"-y values to constants so it's easier to update as we change styles. When I was doing the 2.5 restyling, it was much easier to work with the constants than to hunt for the values. I ended up adding constants for a lot of things because of it. I'd like to make this easier on my future self.

    5. Show all issues

      Can we use a relative font size (percentage)?

    6. Show all issues

      Same here.

    7. Show all issues

      Should use the standard multi-line comment format.

    8. Show all issues

      Are we limiting this exclusively to images? I can think of other file formats that would be useful in discussions.

      1. Well yes, because the markdown syntax will turn it into an <img> tag...

        Perhaps in the future we'll add the capability to insert some kind of download link instead for non-image types, but I think that's definitely a separate change.

    9. Show all issues

      "append"

    10. Show all issues

      This is too long.

    11. Show all issues

      While the new shorthand in ES6 probably has some good uses, I think it's not very future-proof. If anyone ever changes one of these variable names down the road for any reason (or in some other case where we use this syntax), we will break.

      I don't mind using it for the case where you're defining an object inline and want to give it those properties with those values, but when we're calling into another function (here or in findWhere above, for example), we should be explicit.

      1. I'm not sure I agree. It's new syntax to learn, and sure, it does require being aware of how it works, but it's no less fragile to search/replace than it would be if it were { $target: $target }, and it's a lot more DRY.

      2. Okay. I think this will bite us eventually in a confusing way, when someone mistakes the {} for a [] or something and starts changing variables, but go for it.

      3. And to clarify my position, I think these are useful for the case of creating local objects that you know are going to be based on particular variables and have those variables' names. Something like:

        function createFoo(a, b, c) {
            return {a, b, c};
        }
        

        I just don't like it when calling into external functions/objects. I like being explicit about saying "I'm fulfilling these specific keyword arguments/fields of this function/class, and providing these values," not "these keyword arguments/fields happen to match these variable names, yay magic."

    12. Show all issues

      One too many "anys," probably.

    13. 
        
    david
    reviewbot
    1. Tool: PEP8 Style Checker
      Processed Files:
          reviewboard/staticbundles.py
      
      Ignored Files:
          reviewboard/static/rb/js/resources/models/tests/userFileAttachmentModelTests.js
          reviewboard/static/rb/css/ui/dnd-uploader.less
          reviewboard/static/rb/js/resources/models/userFileAttachmentModel.es6.js
          reviewboard/static/rb/js/ui/views/textEditorView.es6.js
          reviewboard/static/rb/js/views/dndUploaderView.es6.js
          reviewboard/static/rb/js/pages/views/tests/reviewablePageViewTests.js
          reviewboard/static/rb/js/views/reviewReplyEditorView.js
          reviewboard/templates/reviews/review_request_box.html
          reviewboard/static/rb/css/pages/reviews.less
          reviewboard/static/rb/js/ui/views/tests/textEditorViewTests.js
          reviewboard/static/rb/css/common.less
          reviewboard/static/rb/css/defs.less
          reviewboard/static/rb/js/views/reviewRequestEditorView.js
          reviewboard/static/rb/js/pages/views/reviewablePageView.js
      
      
      
      Tool: Pyflakes
      Processed Files:
          reviewboard/staticbundles.py
      
      Ignored Files:
          reviewboard/static/rb/js/resources/models/tests/userFileAttachmentModelTests.js
          reviewboard/static/rb/css/ui/dnd-uploader.less
          reviewboard/static/rb/js/resources/models/userFileAttachmentModel.es6.js
          reviewboard/static/rb/js/ui/views/textEditorView.es6.js
          reviewboard/static/rb/js/views/dndUploaderView.es6.js
          reviewboard/static/rb/js/pages/views/tests/reviewablePageViewTests.js
          reviewboard/static/rb/js/views/reviewReplyEditorView.js
          reviewboard/templates/reviews/review_request_box.html
          reviewboard/static/rb/css/pages/reviews.less
          reviewboard/static/rb/js/ui/views/tests/textEditorViewTests.js
          reviewboard/static/rb/css/common.less
          reviewboard/static/rb/css/defs.less
          reviewboard/static/rb/js/views/reviewRequestEditorView.js
          reviewboard/static/rb/js/pages/views/reviewablePageView.js
      
      
    2. 
        
    brennie
    1. 
        
    2. Show all issues

      You can do

      this.el.value += `\n${text}`;
      

      here

      1. I don't think that's really an improvement. Template strings are cool for medium-complexity things but for something simple like this I think it's more readable this way.

    3. Show all issues

      Same here.

    4. Show all issues

      (Almost) the same here.

    5. Show all issues

      And here.

    6. Show all issues

      Should these be .jpeg etc? Because I couldn't I upload foojpeg and it would allow it?

      Or do something like:

      return [/*...*/].some(extension => filename.endsWith(`.${extension}`));
      
    7. Show all issues

      You can do callback() {} in the object literal.

      1. As I think I've mentioned before, I like the callback() {} syntax when something looks like a class, but in this case it doesn't.

    8. 
        
    chipx86
    1. Looks good. Only one comment, beyond Barret's that were fixed.

    2. Show all issues

      Can we put the comparison in parens, to help visually distinguish it better from the => ?

    3. 
        
    david
    reviewbot
    1. Tool: PEP8 Style Checker
      Processed Files:
          reviewboard/staticbundles.py
      
      Ignored Files:
          reviewboard/static/rb/js/resources/models/tests/userFileAttachmentModelTests.js
          reviewboard/static/rb/css/ui/dnd-uploader.less
          reviewboard/static/rb/js/resources/models/userFileAttachmentModel.es6.js
          reviewboard/static/rb/js/ui/views/textEditorView.es6.js
          reviewboard/static/rb/js/views/dndUploaderView.es6.js
          reviewboard/static/rb/js/pages/views/tests/reviewablePageViewTests.js
          reviewboard/static/rb/js/views/reviewReplyEditorView.js
          reviewboard/templates/reviews/review_request_box.html
          reviewboard/static/rb/css/pages/reviews.less
          reviewboard/static/rb/js/ui/views/tests/textEditorViewTests.js
          reviewboard/static/rb/css/common.less
          reviewboard/static/rb/css/defs.less
          reviewboard/static/rb/js/views/reviewRequestEditorView.js
          reviewboard/static/rb/js/pages/views/reviewablePageView.js
      
      
      
      Tool: Pyflakes
      Processed Files:
          reviewboard/staticbundles.py
      
      Ignored Files:
          reviewboard/static/rb/js/resources/models/tests/userFileAttachmentModelTests.js
          reviewboard/static/rb/css/ui/dnd-uploader.less
          reviewboard/static/rb/js/resources/models/userFileAttachmentModel.es6.js
          reviewboard/static/rb/js/ui/views/textEditorView.es6.js
          reviewboard/static/rb/js/views/dndUploaderView.es6.js
          reviewboard/static/rb/js/pages/views/tests/reviewablePageViewTests.js
          reviewboard/static/rb/js/views/reviewReplyEditorView.js
          reviewboard/templates/reviews/review_request_box.html
          reviewboard/static/rb/css/pages/reviews.less
          reviewboard/static/rb/js/ui/views/tests/textEditorViewTests.js
          reviewboard/static/rb/css/common.less
          reviewboard/static/rb/css/defs.less
          reviewboard/static/rb/js/views/reviewRequestEditorView.js
          reviewboard/static/rb/js/pages/views/reviewablePageView.js
      
      
    2. 
        
    brennie
    1. Ship It!
    2. 
        
    david
    Review request changed
    Status:
    Completed
    Change Summary:
    Pushed to ucosp/dkus/dnd-inline-images (c85bea4)