diff --git a/app/assets/javascripts/issue.js.coffee b/app/assets/javascripts/issue.js.coffee
index eff80bf63bb61cd67ff7db5d639317786b3e9101..c256ec8f41bb178189c5e39ce1a589d312a05dd8 100644
--- a/app/assets/javascripts/issue.js.coffee
+++ b/app/assets/javascripts/issue.js.coffee
@@ -1,3 +1,4 @@
+#= require flash
 #= require jquery.waitforimages
 #= require task_list
 
@@ -6,13 +7,44 @@ class @Issue
     # Prevent duplicate event bindings
     @disableTaskList()
 
-    if $("a.btn-close").length
+    if $('a.btn-close').length
       @initTaskList()
+      @initIssueBtnEventListeners()
 
   initTaskList: ->
     $('.detail-page-description .js-task-list-container').taskList('enable')
     $(document).on 'tasklist:changed', '.detail-page-description .js-task-list-container', @updateTaskList
 
+  initIssueBtnEventListeners: ->
+    issueFailMessage = 'Unable to update this issue at this time.'
+    $('a.btn-close, a.btn-reopen').on 'click', (e) ->
+      e.preventDefault()
+      e.stopImmediatePropagation()
+      $this = $(this)
+      isClose = $this.hasClass('btn-close')
+      $this.prop('disabled', true)
+      url = $this.attr('href')
+      $.ajax
+        type: 'PUT'
+        url: url,
+        error: (jqXHR, textStatus, errorThrown) ->
+          issueStatus = if isClose then 'close' else 'open'
+          new Flash(issueFailMessage, 'alert')
+        success: (data, textStatus, jqXHR) ->
+          if data.saved
+            $this.addClass('hidden')
+            if isClose
+              $('a.btn-reopen').removeClass('hidden')
+              $('div.status-box-closed').removeClass('hidden')
+              $('div.status-box-open').addClass('hidden')
+            else
+              $('a.btn-close').removeClass('hidden')
+              $('div.status-box-closed').addClass('hidden')
+              $('div.status-box-open').removeClass('hidden')
+          else
+            new Flash(issueFailMessage, 'alert')
+          $this.prop('disabled', false)
+
   disableTaskList: ->
     $('.detail-page-description .js-task-list-container').taskList('disable')
     $(document).off 'tasklist:changed', '.detail-page-description .js-task-list-container'
diff --git a/app/helpers/issues_helper.rb b/app/helpers/issues_helper.rb
index c1053554fbdcbe21eb76d4f68a0980b126da6fcc..80e2741b09a07795b4678a3346859b0fbbe07495 100644
--- a/app/helpers/issues_helper.rb
+++ b/app/helpers/issues_helper.rb
@@ -69,6 +69,10 @@ module IssuesHelper
     end
   end
 
+  def issue_button_visibility(issue, closed)    
+    return 'hidden' if issue.closed? == closed
+  end
+
   def issue_to_atom(xml, issue)
     xml.entry do
       xml.id      namespace_project_issue_url(issue.project.namespace,
diff --git a/app/views/projects/issues/show.html.haml b/app/views/projects/issues/show.html.haml
index f548383008daf828f4f5baf13d95d59019cb3777..f931a0d3b92bcdfc6f2bfb8830f6f23ebfe43ada 100644
--- a/app/views/projects/issues/show.html.haml
+++ b/app/views/projects/issues/show.html.haml
@@ -6,11 +6,8 @@
 
 .issue
   .detail-page-header
-    .status-box{ class: status_box_class(@issue) }
-      - if @issue.closed?
-        Closed
-      - else
-        Open
+    .status-box{ class: "status-box-closed #{issue_button_visibility(@issue, false)}"} Closed
+    .status-box{ class: "status-box-open #{issue_button_visibility(@issue, true)}"} Open
     %span.identifier
       Issue ##{@issue.iid}
     %span.creator
@@ -30,10 +27,8 @@
           = icon('plus')
           New Issue
       - if can?(current_user, :update_issue, @issue)
-        - if @issue.closed?
-          = link_to 'Reopen', issue_path(@issue, issue: {state_event: :reopen}, status_only: true), method: :put, class: 'btn btn-nr btn-grouped btn-reopen'
-        - else
-          = link_to 'Close', issue_path(@issue, issue: {state_event: :close}, status_only: true), method: :put, class: 'btn btn-nr btn-grouped btn-close', title: 'Close Issue'
+        = link_to 'Reopen', issue_path(@issue, issue: {state_event: :reopen}, status_only: true, format: 'json'), data: {no_turbolink: true}, class: "btn btn-nr btn-grouped btn-reopen #{issue_button_visibility(@issue, false)}", title: 'Reopen Issue'
+        = link_to 'Close', issue_path(@issue, issue: {state_event: :close}, status_only: true, format: 'json'), data: {no_turbolink: true}, class: "btn btn-nr btn-grouped btn-close #{issue_button_visibility(@issue, true)}", title: 'Close Issue'
 
         = link_to edit_namespace_project_issue_path(@project.namespace, @project, @issue), class: 'btn btn-nr btn-grouped issuable-edit' do
           = icon('pencil-square-o')
diff --git a/spec/javascripts/fixtures/issues_show.html.haml b/spec/javascripts/fixtures/issues_show.html.haml
index 8447dfdda3205e6ac5b25a6cb25da8ba7ba3bffa..470cabeafbb90718ad18d14423ef334ac3c61894 100644
--- a/spec/javascripts/fixtures/issues_show.html.haml
+++ b/spec/javascripts/fixtures/issues_show.html.haml
@@ -1,4 +1,14 @@
-%a.btn-close
+:css
+  .hidden { display: none !important; }
+
+.flash-container
+  .flash-alert
+  .flash-notice
+
+.status-box.status-box-open Open
+.status-box.status-box-closed.hidden Closed
+%a.btn-close{"href" => "http://gitlab.com/issues/6/close"} Close
+%a.btn-reopen.hidden{"href" => "http://gitlab.com/issues/6/reopen"} Reopen
 
 .detail-page-description
   .description.js-task-list-container
diff --git a/spec/javascripts/issue_spec.js.coffee b/spec/javascripts/issue_spec.js.coffee
index 268e4c68c3150f230ffa44a949fcd2320ccd384d..7e67c77886109beb2b56c8b5c481744f16af3e16 100644
--- a/spec/javascripts/issue_spec.js.coffee
+++ b/spec/javascripts/issue_spec.js.coffee
@@ -20,3 +20,89 @@ describe 'Issue', ->
         expect(req.data.issue.description).not.toBe(null)
 
       $('.js-task-list-field').trigger('tasklist:changed')
+describe 'reopen/close issue', ->
+  fixture.preload('issues_show.html')
+  beforeEach ->
+    fixture.load('issues_show.html')
+    @issue = new Issue()
+  it 'closes an issue', ->
+    $.ajax = (obj) ->
+      expect(obj.type).toBe('PUT')
+      expect(obj.url).toBe('http://gitlab.com/issues/6/close')
+      obj.success saved: true
+    
+    $btnClose = $('a.btn-close')
+    $btnReopen = $('a.btn-reopen')
+    expect($btnReopen).toBeHidden()
+    expect($btnClose.text()).toBe('Close')
+    expect(typeof $btnClose.prop('disabled')).toBe('undefined')
+
+    $btnClose.trigger('click')
+    
+    expect($btnReopen).toBeVisible()
+    expect($btnClose).toBeHidden()
+    expect($('div.status-box-closed')).toBeVisible()
+    expect($('div.status-box-open')).toBeHidden()
+
+  it 'fails to closes an issue with success:false', ->
+
+    $.ajax = (obj) ->
+      expect(obj.type).toBe('PUT')
+      expect(obj.url).toBe('http://goesnowhere.nothing/whereami')
+      obj.success saved: false
+    
+    $btnClose = $('a.btn-close')
+    $btnReopen = $('a.btn-reopen')
+    $btnClose.attr('href','http://goesnowhere.nothing/whereami')
+    expect($btnReopen).toBeHidden()
+    expect($btnClose.text()).toBe('Close')
+    expect(typeof $btnClose.prop('disabled')).toBe('undefined')
+
+    $btnClose.trigger('click')
+    
+    expect($btnReopen).toBeHidden()
+    expect($btnClose).toBeVisible()
+    expect($('div.status-box-closed')).toBeHidden()
+    expect($('div.status-box-open')).toBeVisible()
+    expect($('div.flash-alert')).toBeVisible()
+    expect($('div.flash-alert').text()).toBe('Unable to update this issue at this time.')
+
+  it 'fails to closes an issue with HTTP error', ->
+
+    $.ajax = (obj) ->
+      expect(obj.type).toBe('PUT')
+      expect(obj.url).toBe('http://goesnowhere.nothing/whereami')
+      obj.error()
+    
+    $btnClose = $('a.btn-close')
+    $btnReopen = $('a.btn-reopen')
+    $btnClose.attr('href','http://goesnowhere.nothing/whereami')
+    expect($btnReopen).toBeHidden()
+    expect($btnClose.text()).toBe('Close')
+    expect(typeof $btnClose.prop('disabled')).toBe('undefined')
+
+    $btnClose.trigger('click')
+    
+    expect($btnReopen).toBeHidden()
+    expect($btnClose).toBeVisible()
+    expect($('div.status-box-closed')).toBeHidden()
+    expect($('div.status-box-open')).toBeVisible()
+    expect($('div.flash-alert')).toBeVisible()
+    expect($('div.flash-alert').text()).toBe('Unable to update this issue at this time.')
+
+  it 'reopens an issue', ->
+    $.ajax = (obj) ->
+      expect(obj.type).toBe('PUT')
+      expect(obj.url).toBe('http://gitlab.com/issues/6/reopen')
+      obj.success saved: true
+
+    $btnClose = $('a.btn-close')
+    $btnReopen = $('a.btn-reopen')
+    expect($btnReopen.text()).toBe('Reopen')
+
+    $btnReopen.trigger('click')
+
+    expect($btnReopen).toBeHidden()
+    expect($btnClose).toBeVisible()
+    expect($('div.status-box-open')).toBeVisible()
+    expect($('div.status-box-closed')).toBeHidden()
\ No newline at end of file