mozreview: make double-clicking to open a comment optional per user (bug 1246769); r?mdoglio draft
authorMike Conley <mconley@mozilla.com>
Thu, 18 Feb 2016 10:04:10 -0500
changeset 7277 6aa1a23874202d6c1ce92dad807c3f35ece828b7
parent 7276 fbbac518215ad0a639a52f1cb9e34ce3413b7aa5
push id645
push usermconley@mozilla.com
push dateThu, 18 Feb 2016 15:45:38 +0000
reviewersmdoglio
bugs1246769
mozreview: make double-clicking to open a comment optional per user (bug 1246769); r?mdoglio MozReview-Commit-ID: 9cZ83ZehALQ
pylib/mozreview/mozreview/extension.py
pylib/mozreview/mozreview/forms.py
pylib/mozreview/mozreview/pages.py
pylib/mozreview/mozreview/static/mozreview/js/diffviewer_customizations.js
pylib/mozreview/mozreview/templates/mozreview/review-scripts-js.html
pylib/mozreview/mozreview/templatetags/mozreview.py
--- a/pylib/mozreview/mozreview/extension.py
+++ b/pylib/mozreview/mozreview/extension.py
@@ -2,17 +2,18 @@ from __future__ import unicode_literals
 
 import json
 import logging
 import os
 
 from django.conf.urls import include, patterns, url
 
 from reviewboard.extensions.base import Extension, JSExtension
-from reviewboard.extensions.hooks import (HeaderDropdownActionHook,
+from reviewboard.extensions.hooks import (AccountPagesHook,
+                                          HeaderDropdownActionHook,
                                           HostingServiceHook,
                                           ReviewRequestDropdownActionHook,
                                           ReviewRequestFieldsHook,
                                           TemplateHook,
                                           URLHook)
 from reviewboard.reviews.builtin_fields import (TestingDoneField,
                                                 BranchField,
                                                 DependsOnField,
@@ -58,16 +59,17 @@ from mozreview.hostingservice.hmo_reposi
 )
 from mozreview.ldap.resources import (
     ldap_association_resource,
 )
 from mozreview.middleware import (
     MozReviewCacheDisableMiddleware,
     MozReviewUserProfileMiddleware,
 )
+
 from mozreview.pulse import (
     initialize_pulse_handlers,
 )
 from mozreview.resources.bugzilla_login import (
     bugzilla_api_key_login_resource,
 )
 from mozreview.resources.batch_review_request import (
     batch_review_request_resource,
@@ -292,16 +294,21 @@ class MozReviewExtension(Extension):
         initialize_signal_handlers(self)
 
         HostingServiceHook(self, HMORepository)
 
         URLHook(self, patterns('',
             url(r'^import-pullrequest/(?P<user>.+)/(?P<repo>.+)/(?P<pullrequest>\d+)/$',
             import_pullrequest, name='import_pullrequest')))
 
+        # Importing here to avoid an import loop
+        from mozreview.pages import MozReviewAccountSettingsPage
+
+        AccountPagesHook(self, [MozReviewAccountSettingsPage])
+
     def shutdown(self):
         # We have to put the TestingDone field back before we shut down
         # in order to get the instance back to its original state.
         main_fieldset = get_review_request_fieldset('main')
         if not get_review_request_field('testing_done'):
             main_fieldset.add_field(TestingDoneField)
 
         info_fieldset = get_review_request_fieldset('info')
--- a/pylib/mozreview/mozreview/forms.py
+++ b/pylib/mozreview/mozreview/forms.py
@@ -1,13 +1,48 @@
 from django import forms
+from django.contrib import messages
 from django.utils.translation import ugettext as _
 from djblets.extensions.forms import SettingsForm
 
+from reviewboard.accounts.forms.pages import AccountPageForm
+
 import mozreview.extension
 
 
 class MozReviewSettingsForm(SettingsForm):
     config = forms.CharField(
         required=False,
         help_text=_('Configure this extension by editing ' +
                     mozreview.extension.SETTINGS_PATH)
     )
+
+
+class MozReviewAccountSettingsForm(AccountPageForm):
+    form_id = 'mozreview_accountsettings_page'
+    extra_data_key = 'mozreview_dblclick_comment'
+    form_title = 'Additional MozReview Customizations'
+    default = True
+
+    mozreview_dblclick_comment = forms.BooleanField(
+        label=_('Double-clicking a line number should start a comment'),
+        help_text=_('This is similar to how Bugzilla Splinter behaves'),
+        initial=True,
+        required=False)
+
+    def load(self):
+        """Loads in data for the Account Settings form"""
+        current = self.default
+        if self.extra_data_key in self.profile.extra_data:
+            current = self.profile.extra_data[self.extra_data_key]
+
+        self.set_initial({
+            self.extra_data_key: current,
+        })
+
+    def save(self):
+        """Save data for the Account Settings form"""
+        cleaned = self.cleaned_data[self.extra_data_key]
+        self.profile.extra_data[self.extra_data_key] = cleaned
+        self.profile.save(update_fields=('extra_data',))
+
+        messages.add_message(self.request, messages.INFO,
+                             _('Your settings have been saved.'))
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/pylib/mozreview/mozreview/pages.py
@@ -0,0 +1,10 @@
+from __future__ import unicode_literals
+
+from mozreview.forms import MozReviewAccountSettingsForm
+from reviewboard.accounts.pages import AccountPage
+
+
+class MozReviewAccountSettingsPage(AccountPage):
+    page_id = 'mozreview_accountsettings_page'
+    page_title = 'MozReview Customizations'
+    form_classes = [MozReviewAccountSettingsForm]
--- a/pylib/mozreview/mozreview/static/mozreview/js/diffviewer_customizations.js
+++ b/pylib/mozreview/mozreview/static/mozreview/js/diffviewer_customizations.js
@@ -2,16 +2,21 @@
  * Monkey-patch RB.TextCommentRowSelector so that double-clicks will
  * result in a comment being opened, a la Splinter.
  */
 RB.TextCommentRowSelector = RB.TextCommentRowSelector.extend({
   events: _.extend({
     'dblclick': '_onDoubleClick',
   }, RB.TextCommentRowSelector.prototype.events),
 
+  initialize: function() {
+    _super(this).initialize.apply(this, arguments);
+    this._isEnabled = $('#mozreview-dblclick-comment').data('value');
+  },
+
   /*
    * Returns whether a node represents source code in the diff viewer.
    *
    * A node represents source code when it is within the section of
    * the diff viewer that's actually displaying code. That means
    * that it's within a <td> with a class "l", or a <td> with class
    * "r".
    */
@@ -29,16 +34,20 @@ RB.TextCommentRowSelector = RB.TextComme
 
   /*
    * Handler for when the user double-clicks on a row.
    *
    * This will open a comment dialog for the row that the user
    * double-clicked on.
    */
   _onDoubleClick: function(e) {
+    if (!this._isEnabled) {
+      return;
+    }
+
     var node = e.target,
         $row,
         lineNum;
 
     if (this._isWithinCodeCell(node)) {
       $row = this._getRowFromChild($(node));
       lineNum = this.getLineNum($row[0]);
       this.options.reviewableView.createAndEditCommentBlock({
--- a/pylib/mozreview/mozreview/templates/mozreview/review-scripts-js.html
+++ b/pylib/mozreview/mozreview/templates/mozreview/review-scripts-js.html
@@ -3,10 +3,16 @@
 
 {% if review_request|isPush %}
 {%   ext_js_bundle extension "reviews" %}
 
 {%   if review_request|isSquashed %}
 {%     ext_js_bundle extension "try" %}
 {%   endif %}
 
+{% comment %}
+TODO: This should get moved into the "diffviewer only" TemplateHook once
+bug 1248364 is closed.
+{% endcomment %}
+<div id="mozreview-dblclick-comment" data-value="{{ user_profile|dblclick_comment|yesno:'true,false' }}"></div>
+
 {% endif %}
 
--- a/pylib/mozreview/mozreview/templatetags/mozreview.py
+++ b/pylib/mozreview/mozreview/templatetags/mozreview.py
@@ -32,18 +32,21 @@ def commit_id(review_request_details):
 
 
 def reviewer_list(review_request):
     return ', '.join([user.username
                       for user in review_request.target_people.all()])
 
 
 @register.filter()
-def extra_data(review_request, key):
-    return review_request.extra_data[key]
+def dblclick_comment(user_profile):
+    try:
+        return user_profile.extra_data['mozreview_dblclick_comment']
+    except (AttributeError, KeyError):
+        return 'true'
 
 
 @register.filter()
 def scm_level(mozreview_profile):
     if mozreview_profile is None:
         return ''
     elif mozreview_profile.has_scm_ldap_group('scm_level_3'):
         return '3'