Previewing image uploads with stimulus.js

I’ve been working on a website with file uploads lately and after a bunch of googling put together a solution using stimulus.js instead of jQuery as not using jQuery is the thing now.

The website I’m working on allows people to upload images and then to tag them before sharing and I thought it was a bit sub-optimal to ask people to tag their images without being able to see them. 

I’m using rails so this component has two parts the javascript file and my html template file. In the html template file I have a html form created via the rails form_with helper. 

<%= form_with scope: :look, url: looks_path, local: true do |form| %>

  <div>
    <%= form.label :title %><br>
    <%= form.text_field :title %>
  </div>

  <div>
    <%= form.text_field :tag_list, multiple:true %>
  </div>

  <div data-controller="image-preview">
    <%= image_tag("preview.png",  :width => "100px", :hight => "100px", 
    data: { target: "image-preview.output" }) %>
  
    <div class="my-2">
      <%= form.label "Look Image" %><br>
      <%= form.file_field :image, :class => "form-control-file photo_upload", 
      data: {target: "image-preview.input", action: "image-preview#readURL" } %>
    </div>    
  </div>

  <div>
    <%= form.submit %>
  </div>
  <% end %>

You can see there that my stimulus data-controller encapsulates the form file_input and an image tag. The image tag loads a “preview.png” on page load and then replaces that white square when the user uploads an image. Ideally, you may want to play with the visibility attribute instead of using a blank square. 

// Visit The Stimulus Handbook for more details 
// https://stimulusjs.org/handbook/introduction

import { Controller } from "stimulus"

export default class extends Controller {
  static targets = [ "output", "input" ]

  readURL() {
    var input = this.inputTarget
    var output = this.outputTarget

    if (input.files && input.files[0]) {
      var reader = new FileReader();

      reader.onload = function () {
       output.src = reader.result
     }

     reader.readAsDataURL(input.files[0]);
   }
 }

}

The stimulus.js controller is here. It uses two targets the “input” which is the form file field and the “output” which is the image tag we are updating with the new image. This javascript uses the FileReader (https://developer.mozilla.org/en-US/docs/Web/API/FileReader) API to read the image off of the user’s computer and display it without needing to move the image across the network. 

This ended up being pretty simple to do in stimulus.js. I like that we don’t need QuerySelectors or anything non-deterministic like that and can just reference our targets directly. I haven’t included the webpack and rails integration code, it was a little tricky, and is a topic for another blog post. 

git format-patch and git am

# format-patch creates a patch file
# the -1 $COMMIT arguments take the last commit and put it into the file
git format-patch -1 14ab6d…..

#Applies the commits in the patch file onto the current branch
git am ../folder/2019-10-17/0001-SLEDGE-32

#This git log command pulls the history of a file into one patch
git log --pretty=email --patch-with-stat --reverse -- path/file_or_dir 
git am <  path/to/file_or_dir 

Creating a good Project README

Project README flies are typically an after thought in the software development process. If a question comes up repeatedly it gets added in an unstructured fashion. This is unfortunate, because the people who need READMEs the most are new engineers who joining the team. They don’t know any of the team’s jargon. They probably don’t have a good understanding of what the project does. And they probably don’t understand the internal architecture of the project. 

You want the first part of the README to be an introduction to your project. Answer the question “Why do we have this service?”. 

To help new engineers use as little jargon as possible, and define terms in the README. 

Include a summary of the architecture of the project in the README. It should cover what abstractions you are using and why you picked the ones that you did. If you use any patterns that are not included in every project at your company make sure to mention them in the README. The last thing you want is for people to take over the project from you, not be able to figure out why you chose these abstractions and then removing them from the codebase. 

You README should also include the  steps to get the project running. What permissions and credentials do new engineers need to run builds and integration tests? Who should they contact to get those permissions? Make sure to include the common failure cases that new engineers ask questions about. 

Include a summary of the typical build process for the project. If you use make, write explanations for every make command you support and when they should be used. If you use a standard build tool like Maven, mention the extensions and plugins you use. “We use the Jacoco Plugin to ensure 80% code coverage, if you add a Spring configuration class you can add it to the ignored list for Jacoco.”

If you have integration or end to end tests in a different package reference in your README. Include an example of typical usage of the external package and expect people to read the README for that package if they run into trouble. Make sure to include common failure cases in the test suite. If external dependencies commonly cause your integration tests to fail, call out how a new engineer can determine that is the case and what they should do in response. 

Example Table of Contents for a README 

Introduction
    Why does this project exist? 
    Where can I find additional documentation?
    Where can I find our CI/CD infrastructure?

Architecture
    What is the basic architecture of the system? 
    MVC, SPA, messaging, RPC
    Do we have any managed thread pools?
    What are our asynchronous tasks?

    What patterns do we use in our codebase? 
    Explain any unusual patterns you use and why you need them.


How to get builds running
    What tools are needed to run builds?
   What build commands and flags should a new engineer be using?

How to get Tests running
    What tools to use to run unit/functional/integration/end-to-end tests
    Are any external packages needed
   How to retrieve the external packages
   Basic commands for any external packages 

   How to know if the tests passed or failed. 

Onboarding Preparedness Quiz

I am working on some materials around onboarding new engineers.

The Quiz

When was the last time you onboarded a new engineer?

Do different team members use different development environments to run integration tests locally?

Do you have architecture diagrams that are up to date as of last month? 

Do you have an up to date list of the APIs you consume and what their SLAs are? 

Do you have a list of all the internal tools your team uses to complete their work? 

Do you have a list of all the 3rd party tools your team uses to complete their work? 

Do you have a list of all the configuration files that your services use? 

Do you have a list of all the resources your services consume, object storage, disks, caches, VMs, queues, etc?