Skip to content

09. Individual Images and Commenting

Nick Doiron edited this page Apr 25, 2016 · 2 revisions

Each user has a profile page, but what if we want to link to an individual image? Let's make this a little more like Instagram by giving each image a page:

extends ./layout.jade

block content
  input.csrf(type="hidden", value=csrfToken)
  input.username(type="hidden", value=user.name)

  .row
    .col-sm-12.underbar
      if forUser
        a.btn.btn-info.pull-right(href="/logout") Log Out
      else
        a.btn.btn-primary.pull-right(href="/profile") Log In
      h2
        a(href="/feed") 1batch
        small  an app for sharing 8 photos.
  .row
    .col-sm-12.col-md-6
      h1
        a(href="/profile/#{user.name}") #{user.name}
      h4 posted #{posted}
      if forUser
        if forUser.name !== user.name
          if following
            button.btn.btn-danger.follow Unfollow
          else
            button.btn.btn-success.follow Follow

  .row
    .col-sm-12.bigimagecontainer
      hr
      img.bigimage(src=image.src.main, srcset="#{image.src.main} 1x, #{image.src.retina} 2x")

block scripts
  script(type="text/javascript", src="/lib/jquery-1.11.3.min.js")
  script(type="text/javascript", src="/follow-button.js")

We have the information and Follow button from the profile page, plus this full-size image with a bigimage class.

Now let's add comments:

if forUser
  if canComment
    .row
      .col-sm-6
        form.well(action="/comment", method="POST")
          input(type="hidden", name="_csrf", value="#{csrfToken}")
          input(type="hidden", name="id", value="#{image._id}")
          textarea.form-control(name="text")
          button.btn.btn-primary.pull-right.commenter Post
          .clearfix

This is the comment submit form - just a text area, a button, and some restrictions to only show it if we believe you can comment.

Here's how we display the comments in an HTML table layout:

.row
  .col-sm-6.comments
    table.table.table-striped
      for comment in comments
        tr
          td
            a(href="/profile/#{comment.user}")= comment.user
          td
            p= comment.text

Now for these two things to exist, we need to have a comments array in the Image object, we need to make sure that it's sent to the client-side page along with canComment for the user, and when we receive a comment back, we need to check canComment.

Server-side image

async function photo (ctx) {
  var requser = ctx.req.user;
  var user = await User.findOne({ name: ctx.params.username.toLowerCase() }).exec();
  if (!user || !user.posted) {
    return printNoExist(ctx);
  }

  var userFollowsSource = await following(requser, user, ctx);
  var sourceFollowsUser = await following(user, requser, ctx);
  var image = await Image.findOne({ _id: ctx.params.photoid }, '_id src comments caption hidden published').exec();
  if (!image) {
    return printNoExist(ctx);
  }
  if (!requser || requser.name !== user.name) {
    if (image.hidden || !image.published) {
      return printNoExist(ctx);
    }
  }
  var comments = image.comments || [];
  image = responsiveImg(image, true);
  ctx.render('image', {
    user: user,
    image: image,
    comments: comments,
    posted: cleanDate(user.posted),
    forUser: (requser || null),
    csrfToken: ctx.csrf,
    following: userFollowsSource,
    canComment: requser && ((requser.name === user.name) || userFollowsSource || sourceFollowsUser)
  });
}

Clone this wiki locally