Merge branch 'master' into 3112-report-bug
authorradhika <radhika@curoverse.com>
Fri, 15 Aug 2014 18:37:17 +0000 (14:37 -0400)
committerradhika <radhika@curoverse.com>
Fri, 15 Aug 2014 18:37:17 +0000 (14:37 -0400)
15 files changed:
apps/workbench/app/controllers/actions_controller.rb
apps/workbench/app/controllers/application_controller.rb
apps/workbench/app/mailers/issue_reporter.rb [new file with mode: 0644]
apps/workbench/app/views/application/404.html.erb
apps/workbench/app/views/application/_report_issue_popup.html.erb [new file with mode: 0644]
apps/workbench/app/views/application/report_issue.js.erb [new file with mode: 0644]
apps/workbench/app/views/application/report_issue_popup.js.erb [new file with mode: 0644]
apps/workbench/app/views/issue_reporter/send_report.text.erb [new file with mode: 0644]
apps/workbench/app/views/layouts/body.html.erb
apps/workbench/config/application.default.yml
apps/workbench/config/routes.rb
apps/workbench/test/functional/actions_controller_test.rb [new file with mode: 0644]
apps/workbench/test/integration/application_layout_test.rb
services/api/app/controllers/arvados/v1/schema_controller.rb
services/api/config/application.default.yml

index d1dc0fca354b7969d77317ec161a58d5f245ea62..695f7703204dfdaf7eb306a77ab0eb14d8008340 100644 (file)
@@ -177,4 +177,22 @@ class ActionsController < ApplicationController
     redirect_to controller: 'collections', action: :show, id: newc.uuid
   end
 
+  def report_issue_popup
+    @popup_params = params
+    respond_to do |format|
+      format.js
+      format.html
+    end
+  end
+
+  def report_issue
+    $stderr.puts "Issue being reported with these parameters: #{params.inspect}"
+    logger.warn "Issue being reported with these parameters: #{params.inspect}"
+
+    respond_to do |format|
+      IssueReporter.send_report(current_user, params).deliver
+      format.js
+    end
+  end
+
 end
index 222888085d9e3bb95973f2a2865c3efbb569b7f5..e0183635610d99a1def0e0df254ff1c1e14d38bd 100644 (file)
@@ -11,9 +11,9 @@ class ApplicationController < ActionController::Base
   around_filter :set_thread_api_token
   # Methods that don't require login should
   #   skip_around_filter :require_thread_api_token
-  around_filter :require_thread_api_token, except: ERROR_ACTIONS
+  around_filter :require_thread_api_token, except: [:report_issue_popup, :report_issue] + ERROR_ACTIONS
   before_filter :accept_uuid_as_id_param, except: ERROR_ACTIONS
-  before_filter :check_user_agreements, except: ERROR_ACTIONS
+  before_filter :check_user_agreements, except: [:report_issue_popup, :report_issue] + ERROR_ACTIONS
   before_filter :check_user_profile, except: [:update_profile] + ERROR_ACTIONS
   before_filter :check_user_notifications, except: ERROR_ACTIONS
   before_filter :load_filters_and_paging_params, except: ERROR_ACTIONS
diff --git a/apps/workbench/app/mailers/issue_reporter.rb b/apps/workbench/app/mailers/issue_reporter.rb
new file mode 100644 (file)
index 0000000..5f3cf13
--- /dev/null
@@ -0,0 +1,12 @@
+class IssueReporter < ActionMailer::Base
+  default from: Rails.configuration.report_notifier_email_from
+  default to: Rails.configuration.report_notifier_email_to
+
+  def send_report(user, params)
+    @user = user
+    @params = params
+    subject = 'Issue reported'
+    subject += " by #{@user.email}" if @user
+    mail(subject: subject)
+  end
+end
index fd972959560faf14ae74a061d348cddc5d1d7554..ae7dc223b704a4d77082ea59199fb026a1844ba1 100644 (file)
@@ -4,6 +4,7 @@
      class_name_h = class_name.humanize(capitalize: false)
      req_item = safe_join([class_name_h, " with UUID ",
                            raw("<code>"), params[:uuid], raw("</code>")], "")
+     req_item_plain_text = safe_join([class_name_h, " with UUID ", params[:uuid]])
    else
      req_item = "page you requested"
    end
@@ -20,3 +21,12 @@ Perhaps you'd like to
 
 </p>
 
+<p>
+<br/>
+<% error_message = "The #{req_item_plain_text} was not found." %>
+Would you like to report this problem?
+<%= link_to report_issue_popup_path(popup_type: 'report', current_location: request.fullpath, action_method: 'post', error_message: error_message),
+      {class: 'btn btn-primary report-issue-modal-window', 'data-toggle' =>  "modal", 'data-target' => '#report-issue-modal-window', :remote => true, return_to: request.url} do %>
+      <i class="fa fa-fw fa-support"></i> Report problem
+<% end %>
+</p>
diff --git a/apps/workbench/app/views/application/_report_issue_popup.html.erb b/apps/workbench/app/views/application/_report_issue_popup.html.erb
new file mode 100644 (file)
index 0000000..2600593
--- /dev/null
@@ -0,0 +1,110 @@
+<%
+  api_version = arvados_api_client.discovery[:source_version]
+  generated_at = arvados_api_client.discovery[:generatedAt]
+  wb_version = Rails.configuration.source_version
+  wb_version += Rails.configuration.source_version if Rails.configuration.local_modified
+  arvados_base = Rails.configuration.arvados_v1_base
+  support_email = Rails.configuration.support_email_address
+
+  additional_info = {}
+  additional_info['Current location'] = @popup_params[:current_location]
+  additional_info['User UUID'] = current_user.uuid if current_user
+  additional_info['User email'] = current_user.email if current_user
+
+  additional_info_str = additional_info.map {|k,v| "#{k}=#{v}"}.join("\n")
+
+  additional_info['api_version'] = api_version
+  additional_info['generated_at'] = generated_at
+  additional_info['workbench_version'] = wb_version
+  additional_info['arvados_base'] = arvados_base
+  additional_info['support_email'] = support_email
+  additional_info['error_message'] = @popup_params[:error_message] if @popup_params[:error_message]
+  additional_info['api_error_request_url'] = @popup_params[:api_error_request_url] if @popup_params[:api_error_request_url]
+  additional_info['api_error_response'] = @popup_params[:api_error_response] if @popup_params[:api_error_response]
+%>
+
+<div class="modal-dialog modal-with-loading-spinner">
+  <div class="modal-content">
+
+    <%= form_tag report_issue_path, {name: 'report-issue-form', method: 'post',
+        class: 'form-horizontal', remote: true} do %>
+
+      <%
+        title = 'Version / debugging info'
+        title = 'Report a problem' if @popup_params[:popup_type] == 'report'
+      %>
+
+      <div class="modal-header">
+        <button type="button" class="close" onClick="reset_form()" data-dismiss="modal" aria-hidden="true">&times;</button>
+        <div>
+          <div class="col-sm-8"> <h4 class="modal-title"><%=title%></h4> </div>
+          <div class="spinner spinner-32px spinner-h-center col-sm-1" hidden="true"></div>
+        </div>
+        <br/>
+      </div>
+
+      <div class="modal-body">
+        <div class="form-group">
+          <label for="support_version" class="col-sm-4 control-label"> Support email </label>
+          <div class="col-sm-8">
+            <p class="form-control-static" name="support_version"><%=support_email%></p>
+          </div>
+        </div>
+
+        <div class="form-group">
+          <label for="server_version" class="col-sm-4 control-label"> Server version </label>
+          <div class="col-sm-8">
+            <p class="form-control-static" name="server_version"><%=api_version%></p>
+          </div>
+        </div>
+
+        <div class="form-group">
+          <label for="generated_at" class="col-sm-4 control-label"> Server restarted at </label>
+          <div class="col-sm-8">
+            <p class="form-control-static" name="generated_at"><%=generated_at%></p>
+          </div>
+        </div>
+
+        <div class="form-group">
+          <label for="wb_version" class="col-sm-4 control-label"> Workbench version </label>
+          <div class="col-sm-8">
+            <p class="form-control-static" name="wb_version"><%=wb_version%></p>
+          </div>
+        </div>
+
+        <div class="form-group">
+          <label for="arvados_base" class="col-sm-4 control-label"> Arvados base </label>
+          <div class="col-sm-8">
+            <p class="form-control-static" name="arvados_base"><%=arvados_base%></p>
+          </div>
+        </div>
+
+        <% if @popup_params[:popup_type] == 'report' %>
+          <div class="form-group">
+            <label for="report_text_label" class="col-sm-4 control-label"> Found a problem? Tell us what happened </label>
+            <div class="col-sm-8">
+              <textarea class="form-control" rows="1" id="report_issue_text" name="report_issue_text" type="text"/>
+            </div>
+          </div>
+        <% end %>
+
+        <div class="form-group">
+          <label for="additional_info" class="col-sm-4 control-label"> Additional info </label>
+          <div class="col-sm-8">
+            <textarea readonly class="form-control" rows="1" name="additional_info" type="text"><%=additional_info_str%></textarea>
+        </div>
+        <input type="hidden" name="report_additional_info" value="<%=additional_info.to_json%>">
+      </div>
+
+      <div class="modal-footer">
+        <% if @popup_params[:popup_type] == 'report' %>
+          <button type="submit" id="report-issue-submit" class="btn btn-primary report-issue-submit" autofocus>Report issue</button>
+          <button class="btn btn-default report-issue-cancel" id="report-issue-cancel" onClick="reset_form()" data-dismiss="modal" aria-hidden="true">Cancel</button>
+        <% else %>
+          <button class="btn btn-default" onClick="reset_form()" data-dismiss="modal" aria-hidden="true">Close</button>
+        <% end %>
+      </div>
+
+    <% end #form %>
+  </div>
+</div>
diff --git a/apps/workbench/app/views/application/report_issue.js.erb b/apps/workbench/app/views/application/report_issue.js.erb
new file mode 100644 (file)
index 0000000..26113a9
--- /dev/null
@@ -0,0 +1 @@
+// Let ajax events handle hiding of the popup.
diff --git a/apps/workbench/app/views/application/report_issue_popup.js.erb b/apps/workbench/app/views/application/report_issue_popup.js.erb
new file mode 100644 (file)
index 0000000..48b66dc
--- /dev/null
@@ -0,0 +1,48 @@
+$("#report-issue-modal-window").html("<%= escape_javascript(render partial: 'report_issue_popup') %>");
+
+// reset form input fields, for the next time around
+function reset_form() {
+  $('#report_issue_text').val("");
+  $('#additional_info').val("");
+}
+
+// ajax handling for report-issue function
+$(document).
+  on('ajax:send', function() {
+    var sendButton = document.getElementById('report-issue-submit');
+    if (sendButton) {
+      var text = document.getElementById('report-issue-submit').firstChild;
+      text.data = "Sending...";
+      sendButton.disabled = true;
+    }
+    var cancelButton = document.getElementById('report-issue-cancel');
+    if (cancelButton) {
+      var text = document.getElementById('report-issue-cancel').firstChild;
+      text.data = "Close";
+    }
+    $('div').remove('.modal-footer-status');
+  }).
+  on('ajax:success', function() {
+    var sendButton = document.getElementById('report-issue-submit');
+    if (sendButton && sendButton.disabled) {
+      var text = document.getElementById('report-issue-submit').firstChild;
+      text.data = "Report sent";
+      $('div').remove('.modal-footer-status');
+      $('.modal-footer').append('<div class="modal-footer-status pull-left"><div><p>Thanks for reporting this issue!</p></div></div>');
+    }
+  }).
+  on('ajax:failure', function() {
+    var sendButton = document.getElementById('report-issue-submit');
+    if (sendButton && sendButton.disabled) {
+      $('div').remove('.modal-footer-status');
+      $('.modal-footer').append('<div class="modal-footer-status pull-left"></br><p>We are sorry. We could not submit your report! We really want this to work, though -- please try again.</p></div>');
+      var text = document.getElementById('report-issue-submit').firstChild;
+      text.data = "Report issue";
+      sendButton.disabled = false;
+    }
+    var cancelButton = document.getElementById('report-issue-cancel');
+    if (cancelButton) {
+      var text = document.getElementById('report-issue-cancel').firstChild;
+      text.data = "Cancel";
+    }
+  });
diff --git a/apps/workbench/app/views/issue_reporter/send_report.text.erb b/apps/workbench/app/views/issue_reporter/send_report.text.erb
new file mode 100644 (file)
index 0000000..4cbb371
--- /dev/null
@@ -0,0 +1,13 @@
+<% if @user %>
+Issue reported by user <%=@user.full_name%> <%=@user.email%>
+<% else %>
+Issue reported
+<% end %>
+
+Details of the report:
+<% if @params['report_additional_info'] %>
+<% json_map = JSON.parse(@params['report_additional_info']).map %>
+<%  map_to_s = json_map.map {|k,v| "#{k}=#{v}"}.join("\n") %>
+<%= map_to_s %>
+<% end %>
+Report text=<%=@params['report_issue_text'] %>
index 4c58daba70e85efeddb34704e89fe6badde9cdab..dd80822656d5692d768d14a1996451bb6bb22e2e 100644 (file)
               <li><%= link_to raw('<i class="fa fa-book fa-fw"></i> Tutorials and User guide'), "#{Rails.configuration.arvados_docsite}/user", target: "_blank" %></li>
               <li><%= link_to raw('<i class="fa fa-book fa-fw"></i> API Reference'), "#{Rails.configuration.arvados_docsite}/api", target: "_blank" %></li>
               <li><%= link_to raw('<i class="fa fa-book fa-fw"></i> SDK Reference'), "#{Rails.configuration.arvados_docsite}/sdk", target: "_blank" %></li>
+              <li role="presentation" class="divider"></li>
+              <li> <%= link_to report_issue_popup_path(popup_type: 'version', current_location: request.fullpath, action_method: 'post'),
+                      {class: 'report-issue-modal-window', 'data-toggle' =>  "modal", 'data-target' => '#report-issue-modal-window', :remote => true, return_to: request.url} do %>
+                       <i class="fa fa-fw fa-support"></i> Show version / debugging info
+                      <% end %>
+              </li>
+              <li> <%= link_to report_issue_popup_path(popup_type: 'report', current_location: request.fullpath, action_method: 'post'),
+                      {class: 'report-issue-modal-window', 'data-toggle' =>  "modal", 'data-target' => '#report-issue-modal-window', :remote => true, return_to: request.url} do %>
+                       <i class="fa fa-fw fa-support"></i> Report a problem
+                      <% end %>
+              </li>
             </ul>
           </li>
         </ul>
   <%= yield :footer_html %>
 
 <div class="modal-container"></div>
+<div id="report-issue-modal-window" class="modal fade" role="dialog" aria-labelledby="report-issue-modal" aria-hidden="true"></div>
index 3b4c2c0684bdb6cff3795776bc60b5588d2ec3ec..13829b6e18a3289c9ac6a283051508e3ef3a27ae 100644 (file)
@@ -12,6 +12,7 @@ development:
   assets.debug: true
   profiling_enabled: true
   site_name: Arvados Workbench (dev)
+  local_modified: <%= '-modified' if `git status -s` %>
 
 production:
   force_ssl: true
@@ -131,3 +132,12 @@ common:
   # Use "user_profile_form_message" to configure the message you want to display in
   # the profile page. If this is not provided, a default message will be displayed.
   user_profile_form_message: Welcome to Arvados. Please fill in all required fields before you can access Arvados Workbench. Missing required fields are in <span style="color:red">red</span>.
+
+  # source_version
+  source_version: <%= `git log -n 1 --format=%h` %>
+  local_modified: false
+
+  # report nitification to and from addresses
+  report_notifier_email_from: arvados@example.com
+  report_notifier_email_to: arvados@example.com
+  support_email_address: arvados@example.com
index 4ef26612ab194a2df62eefa3945aa1ab75ab5c4e..839118dc772c78064429d8b5047fc9989cc0e3b1 100644 (file)
@@ -10,6 +10,8 @@ ArvadosWorkbench::Application.routes.draw do
   get '/user_agreements/signatures' => 'user_agreements#signatures'
   get "users/setup_popup" => 'users#setup_popup', :as => :setup_user_popup
   get "users/setup" => 'users#setup', :as => :setup_user
+  get "actions/report_issue_popup" => 'actions#report_issue_popup', :as => :report_issue_popup
+  post "actions/report_issue" => 'actions#report_issue', :as => :report_issue
   resources :nodes
   resources :humans
   resources :traits
diff --git a/apps/workbench/test/functional/actions_controller_test.rb b/apps/workbench/test/functional/actions_controller_test.rb
new file mode 100644 (file)
index 0000000..9654538
--- /dev/null
@@ -0,0 +1,19 @@
+require 'test_helper'
+
+class ActionsControllerTest < ActionController::TestCase
+
+  test "send report" do
+    post :report_issue, {format: 'js'}, session_for(:admin)
+    assert_response :success
+
+    found_email = false
+    ActionMailer::Base.deliveries.andand.each do |email|
+      if email.subject.include? "Issue reported by admin"
+        found_email = true
+        break
+      end
+    end
+    assert_equal true, found_email, 'Expected email after issue reported'
+  end
+
+end
index 8a0ebc3c29c8ba04c27c41227fff289a4bdbf534..a4b30f232bf9f26b5d62e884ce8e50d3747abed9 100644 (file)
@@ -71,8 +71,55 @@ class ApplicationLayoutTest < ActionDispatch::IntegrationTest
         assert page.has_link? 'Tutorials and User guide'
         assert page.has_link? 'API Reference'
         assert page.has_link? 'SDK Reference'
+        assert page.has_link? 'Show version / debugging info'
+        assert page.has_link? 'Report a problem'
+
+        # check show version info link
+        click_link 'Show version / debugging info'
       end
     end
+
+    within '.modal-content' do
+      assert page.has_text? 'Version / debugging info'
+      assert page.has_no_text? 'Report a problem'
+      assert page.has_text? 'Server version'
+      assert page.has_text? 'Server restarted at'
+      assert page.has_text? 'Workbench version'
+      assert page.has_text? 'Arvados base'
+      assert page.has_text? 'Additional info'
+      assert page.has_no_text? 'Found a problem?'
+      assert page.has_button? 'Close'
+      assert page.has_no_button? 'Report issue'
+      click_button 'Close'
+    end
+
+    # check report issue link
+    within('.navbar-fixed-top') do
+      page.find("#arv-help").click
+      within('.dropdown-menu') do
+        click_link 'Report a problem'
+      end
+    end
+
+    within '.modal-content' do
+      assert page.has_text? 'Report a problem'
+      assert page.has_no_text? 'Version / debugging info'
+      assert page.has_text? 'Server version'
+      assert page.has_text? 'Server restarted at'
+      assert page.has_text? 'Workbench version'
+      assert page.has_text? 'Arvados base'
+      assert page.has_text? 'Additional info'
+      assert page.has_text? 'Found a problem?'
+      assert page.has_no_button? 'Close'
+      assert page.has_button? 'Report issue'
+      assert page.has_button? 'Cancel'
+
+      # enter a report text and click on report
+      page.find_field('report_issue_text').set 'my test report text'
+      click_button 'Report issue'
+    end
+
+    assert page.has_no_text? 'Version / debugging info'
   end
 
   def verify_system_menu user
@@ -226,6 +273,21 @@ class ApplicationLayoutTest < ActionDispatch::IntegrationTest
 
       # we should see 'not found' error page
       assert page.has_text? 'Not Found'
+      assert page.has_link? 'Report problem'
+      click_link 'Report problem'
+      within '.modal-content' do
+        assert page.has_text? 'Report a problem'
+        assert page.has_no_text? 'Version / debugging info'
+        assert page.has_text? 'Server version'
+        assert page.has_text? 'Server restarted at'
+        assert page.has_text? 'Found a problem?'
+        assert page.has_button? 'Report issue'
+        assert page.has_button? 'Cancel'
+
+        # enter a report text and click on report
+        page.find_field('report_issue_text').set 'my test report text'
+        click_button 'Report issue'
+      end
 
       # let's search for the anonymously accessible project
       publicly_accessible_project = api_fixture('groups')['anonymously_accessible_project']
@@ -261,6 +323,7 @@ class ApplicationLayoutTest < ActionDispatch::IntegrationTest
     ['active_no_prefs', api_fixture('users')['active_no_prefs'], true, false],
     ['active_no_prefs_profile', api_fixture('users')['active_no_prefs_profile'], true, false],
   ].each do |token, user, invited, has_profile|
+
     test "visit home page when profile is configured for user #{token}" do
       # Our test config enabled profile by default. So, no need to update config
       if !token
@@ -293,12 +356,14 @@ class ApplicationLayoutTest < ActionDispatch::IntegrationTest
 
       check_help_menu
     end
+
   end
 
   [
     ['active', api_fixture('users')['active'], true, true],
     ['admin', api_fixture('users')['admin'], true, true],
   ].each do |token, user|
+
     test "test system menu for user #{token}" do
       visit page_with_token(token)
       verify_system_menu user
@@ -313,5 +378,7 @@ class ApplicationLayoutTest < ActionDispatch::IntegrationTest
       visit page_with_token(token)
       verify_search_box user
     end
+
   end
+
 end
index a2a5759c739bc1af3e83b586bd8dff96f1268e79..eccee8a70b18d183dfb69ceadf7932fce4933baf 100644 (file)
@@ -15,6 +15,7 @@ class Arvados::V1::SchemaController < ApplicationController
         name: "arvados",
         version: "v1",
         revision: "20131114",
+        source_version: (Rails.application.config.source_version ? Rails.application.config.source_version : "No version information available") + (Rails.application.config.local_modified ? Rails.application.config.local_modified.to_s : ''),
         generatedAt: Time.now.iso8601,
         title: "Arvados API",
         description: "The API to interact with Arvados.",
index ddcaa57302b5ceec5437ab1b20cb09271b2f24ea..bd877f6e725073d147e3202b74f9686d90ff64f4 100644 (file)
@@ -15,6 +15,7 @@ development:
   active_record.auto_explain_threshold_in_seconds: 0.5
   assets.compress: false
   assets.debug: true
+  local_modified: <%= '-modified' if `git status -s` %>
 
 production:
   force_ssl: true
@@ -179,3 +180,7 @@ common:
 
   # email address to which mail should be sent when the user creates profile for the first time
   user_profile_notification_address: false
+
+  # source_version
+  source_version: <%= `git log -n 1 --format=%h` %>
+  local_modified: false