← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~jcsackett/launchpad/oh-oh-pick-me-pick-me-3 into lp:launchpad

 

j.c.sackett has proposed merging lp:~jcsackett/launchpad/oh-oh-pick-me-pick-me-3 into lp:launchpad with lp:~jcsackett/launchpad/oh-oh-pick-me-pick-me-2 as a prerequisite.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~jcsackett/launchpad/oh-oh-pick-me-pick-me-3/+merge/63885

Summary
=======
Shortly after the person picker widget was created and added to the web ui in oh-oh-pick-me-pick-me-(1,2), a new picker widget was created for launchpad extending the lazr picker to add launchpad specific data.

This branch retargets personpicker to extend that new picker. As a byproduct, both pickers were moved into a new javascript file, lib/lp/app/javascript/widgets.js in order to deal with circular dependencies.

Some drive by fixes were made to the personpicker as well.

Preimplementation
=================
Spoke with Curtis Hovey and Ian Booth.

Implementation
==============
lib/canonical/launchpad/webapp/configure.zcml
---------------------------------------------
Drive by fix; changed the field for the personpicker popup.

lib/lp/app/javascript/picker.js
lib/lp/app/javascript/widgets.js
lib/lp/app/javascript/tests/test_personpicker.js
lib/lp/app/javascript/tests/test_personpicker.html
------------------------------------------------
Migrated the new lp picker and personpicker to lib/lp/app/javascript/widgets.js. Moved the personpicker yui tests to the app javascript module along with personpicker. Updated the personpicker js to extend the lp picker js. Lastly, did a quick fix to change the placement of a paren in the lp picker. 

Tests
=====
firefox lib/lp/app/javascript/tests/test_personpicker.html

QA
==
qa-untestable; this will be landed as part of oh-oh-pick-me-pick-me-2, so that lands completely useable. Since that branch was already reviewed and this is dealing with separate issues, it seemed best to submit as a different branch.

Lint
====
= Launchpad lint =

Checking for conflicts and issues in changed files.

Linting changed files:
  lib/canonical/launchpad/webapp/configure.zcml
  lib/lp/app/javascript/picker.js
  lib/lp/app/javascript/widgets.js
  lib/lp/app/javascript/tests/test_personpicker.html
  lib/lp/app/javascript/tests/test_personpicker.js

-- 
https://code.launchpad.net/~jcsackett/launchpad/oh-oh-pick-me-pick-me-3/+merge/63885
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~jcsackett/launchpad/oh-oh-pick-me-pick-me-3 into lp:launchpad.
=== modified file 'lib/canonical/launchpad/webapp/configure.zcml'
--- lib/canonical/launchpad/webapp/configure.zcml	2011-05-27 21:03:22 +0000
+++ lib/canonical/launchpad/webapp/configure.zcml	2011-06-08 15:31:34 +0000
@@ -399,7 +399,7 @@
     <!-- Define the widget used by PublicPersonChoice fields. -->
     <view
       type="zope.publisher.interfaces.browser.IBrowserRequest"
-      for="lp.services.fields.PublicPersonChoice
+      for="lp.services.fields.PersonChoice
         canonical.launchpad.webapp.vocabulary.IHugeVocabulary"
       provides="zope.app.form.interfaces.IInputWidget"
       factory="lp.app.widgets.popup.PersonPickerWidget"

=== modified file 'lib/lp/app/javascript/picker.js'
--- lib/lp/app/javascript/picker.js	2011-06-06 03:24:06 +0000
+++ lib/lp/app/javascript/picker.js	2011-06-08 15:31:34 +0000
@@ -328,47 +328,6 @@
     Y.on('change', copy_selected_value, select_menu);
     };
 
-
-/**
- * Extend the lazr-js Picker.
- */
-var Picker = function() {
-    Picker.superclass.constructor.apply(this, arguments);
-};
-
-Y.extend(Picker, Y.lazr.Picker, {
-    // We want to render alt title slightly differently.
-    _renderTitleUI: function(data) {
-        var li_title = Y.Node.create(
-            '<span></span>').addClass(Y.lazr.Picker.C_RESULT_TITLE);
-        var title = this._text_or_link(
-            data.title, data.title_link, data.link_css);
-        li_title.appendChild(title);
-        if (data.alt_title) {
-            var alt_link = null;
-            if (data.alt_title_link) {
-                alt_link =Y.Node.create('<a></a>')
-                    .addClass(data.link_css)
-                    .addClass('discreet');
-                alt_link.set('text', " Details...")
-                    .set('href', data.alt_title_link);
-                Y.on('click', function(e) {
-                    e.halt();
-                    window.open(data.alt_title_link);
-                }, alt_link);
-            }
-            li_title.appendChild('&nbsp;(');
-            li_title.appendChild(document.createTextNode(data.alt_title));
-            if (alt_link !== null)
-                li_title.appendChild(alt_link);
-            li_title.appendChild(')');
-        }
-        return li_title;
-    }
-});
-Picker.NAME = 'picker';
-namespace.Picker = Picker;
-
 /**
   * Creates a picker widget that has already been rendered and hidden.
   *
@@ -397,6 +356,9 @@
         if (config.step_title !== undefined) {
             step_title = config.step_title;
         }
+        if (config.picker_type !== undefined) {
+            picker_type = config.picker_type;
+        }
     }
 
     if (typeof vocabulary !== 'string' && typeof vocabulary !== 'object') {
@@ -417,7 +379,13 @@
         zIndex: 1000,
         visible: false
         });
-    var picker = new Picker(new_config);
+
+    var picker = null;
+    if (picker_type === 'person') {
+        picker = new Y.lp.app.widgets.PersonPicker(new_config);
+    } else {
+        picker = new Y.lp.app.widgets.Picker(new_config);
+    }
 
     // We don't want the Y.lazr.Picker default save to fire since this hides
     // the form. We want to do this ourselves after any validation has had a
@@ -540,5 +508,5 @@
 
 }, "0.1", {"requires": [
     "io", "dom", "dump", "event", "lazr.picker", "lazr.activator",
-    "json-parse", "lp.client"
+    "json-parse", "lp.client", "lp.app.widgets"
     ]});

=== renamed file 'lib/lp/registry/javascript/tests/test_personpicker.html' => 'lib/lp/app/javascript/tests/test_personpicker.html'
--- lib/lp/registry/javascript/tests/test_personpicker.html	2011-06-01 13:59:43 +0000
+++ lib/lp/app/javascript/tests/test_personpicker.html	2011-06-08 15:31:34 +0000
@@ -17,7 +17,7 @@
     <script type="text/javascript" src="../../../app/javascript/lp.js"></script>
 
     <!-- The module under test -->
-    <script type="text/javascript" src="../personpicker.js"></script>
+    <script type="text/javascript" src="../widgets.js"></script>
 
     <!-- The test suite -->
     <script type="text/javascript" src="test_personpicker.js"></script>

=== renamed file 'lib/lp/registry/javascript/tests/test_personpicker.js' => 'lib/lp/app/javascript/tests/test_personpicker.js'
--- lib/lp/registry/javascript/tests/test_personpicker.js	2011-05-31 21:18:08 +0000
+++ lib/lp/app/javascript/tests/test_personpicker.js	2011-06-08 15:31:34 +0000
@@ -6,10 +6,10 @@
     base: '../../../../canonical/launchpad/icing/yui/',
     filter: 'raw', combine: false,
     fetchCSS: false
-    }).use('test', 'console', 'plugin', 'lp.registry.personpicker',
+    }).use('test', 'console', 'plugin', 'lp.app.widgets',
            'node-event-simulate', function(Y) {
 
-    var suite = new Y.Test.Suite("lp.registry.personpicker Tests");
+    var suite = new Y.Test.Suite("lp.app.widgets.PersonPicker Tests");
 
     suite.add(new Y.Test.Case({
         name: 'personpicker',
@@ -18,26 +18,26 @@
             window.LP = {
                 links: {me: '/~no-one'},
                 cache: {}
-            }
+            };
         },
 
         test_render: function () {
-            var personpicker = new Y.lp.registry.personpicker.PersonPicker();
+            var personpicker = new Y.lp.app.widgets.PersonPicker();
             personpicker.render();
             personpicker.show();
-            
+
             // The extra buttons section exists
             Y.Assert.isNotNull(Y.one('.extra-form-buttons'));
             Y.Assert.isNotNull(Y.one('.yui-picker-remove-button'));
             Y.Assert.isNotNull(Y.one('.yui-picker-assign-me-button'));
         },
-        
+
         test_buttons: function () {
-            var personpicker = new Y.lp.registry.personpicker.PersonPicker();
+            var personpicker = new Y.lp.app.widgets.PersonPicker();
             personpicker.render();
             personpicker.show();
-           
-            // Patch the picker so the assign_me and remove methods can be 
+
+            // Patch the picker so the assign_me and remove methods can be
             // tested.
             var data = null;
             personpicker.on('save', function (result) {

=== renamed file 'lib/lp/registry/javascript/personpicker.js' => 'lib/lp/app/javascript/widgets.js'
--- lib/lp/registry/javascript/personpicker.js	2011-05-31 18:27:50 +0000
+++ lib/lp/app/javascript/widgets.js	2011-06-08 15:31:34 +0000
@@ -1,21 +1,62 @@
 /* Copyright 2011 Canonical Ltd.  This software is licensed under the
  * GNU Affero General Public License version 3 (see the file LICENSE).
  *
- * @namespace Y.lp.registry.personpicker
- * @requires lazr.picker
+ * @namespace Y.lp.app.widgets
+ * @requires Y.lazr.picker
  */
-YUI.add('lp.registry.personpicker', function(Y) {
-var namespace = Y.namespace('lp.registry.personpicker');
+YUI.add('lp.app.widgets', function(Y) {
+var namespace = Y.namespace('lp.app.widgets');
 
-var footer_label = ".yui3-picker-footer-slot"
+var footer_label = ".yui3-picker-footer-slot";
 
 var PersonPicker = function() {
-    PersonPicker.superclass.constructor.apply(this, arguments);
-
+    this.superclass.constructor.apply(this, arguments);
     this._extra_buttons = Y.Node.create('<div class="extra-form-buttons"/>');
 };
 
-Y.extend(PersonPicker, Y.lazr.Picker, {
+/**
+ * Extend the lazr-js Picker.
+ */
+var Picker = function() {
+    this.superclass.constructor.apply(this, arguments);
+};
+
+Y.extend(Picker, Y.lazr.Picker, {
+    // We want to render alt title slightly differently.
+    _renderTitleUI: function(data) {
+        var li_title = Y.Node.create(
+            '<span></span>').addClass(Y.lazr.Picker.C_RESULT_TITLE);
+        var title = this._text_or_link(
+            data.title, data.title_link, data.link_css);
+        li_title.appendChild(title);
+        if (data.alt_title) {
+            var alt_link = null;
+            if (data.alt_title_link) {
+                alt_link =Y.Node.create('<a></a>')
+                    .addClass(data.link_css)
+                    .addClass('discreet');
+                alt_link.set('text', " Details...")
+                    .set('href', data.alt_title_link);
+                Y.on('click', function(e) {
+                    e.halt();
+                    window.open(data.alt_title_link);
+                }, alt_link);
+            }
+            li_title.appendChild('&nbsp;(');
+            li_title.appendChild(document.createTextNode(data.alt_title));
+            li_title.appendChild(')');
+            if (alt_link !== null) {
+                li_title.appendChild(alt_link);
+            }
+        }
+        return li_title;
+    }
+});
+
+Picker.NAME = 'picker';
+namespace.Picker = Picker;
+
+Y.extend(PersonPicker, namespace.Picker, {
     hide: function() {
         this.get('boundingBox').setStyle('display', 'none');
     },
@@ -36,29 +77,24 @@
     renderUI: function() {
         this.constructor.superclass.renderUI.call(this);
         var remove_button, assign_me_button;
-        //# TODO config should set extrabuttons
-        var show_remove_button = true;
-        var show_assign_me_button = true;
         var remove_button_text = "Remove assignee";
         var assign_me_button_text = "Assign me";
-        if (show_remove_button) {
-            remove_button = Y.Node.create(
-                '<a class="yui-picker-remove-button bg-image" ' +
-                'href="javascript:void(0)" ' +
-                'style="background-image: url(/@@/remove); padding-right: 1em">' +
-                remove_button_text + '</a>');
-            remove_button.on('click', this.remove, this);
-            this._extra_buttons.appendChild(remove_button);
-        }
-        if (show_assign_me_button) {
-            assign_me_button = Y.Node.create(
-                '<a class="yui-picker-assign-me-button bg-image" ' +
-                'href="javascript:void(0)" ' +
-                'style="background-image: url(/@@/person)">' +
-                assign_me_button_text + '</a>');
-            assign_me_button.on('click', this.assign_me, this);
-            this._extra_buttons.appendChild(assign_me_button);
-        }
+
+        remove_button = Y.Node.create(
+            '<a class="yui-picker-remove-button bg-image" ' +
+            'href="javascript:void(0)" ' +
+            'style="background-image: url(/@@/remove); padding-right: 1em">' +
+            remove_button_text + '</a>');
+        remove_button.on('click', this.remove, this);
+        this._extra_buttons.appendChild(remove_button);
+
+        assign_me_button = Y.Node.create(
+            '<a class="yui-picker-assign-me-button bg-image" ' +
+            'href="javascript:void(0)" ' +
+            'style="background-image: url(/@@/person)">' +
+            assign_me_button_text + '</a>');
+        assign_me_button.on('click', this.assign_me, this);
+        this._extra_buttons.appendChild(assign_me_button);
     },
 
     syncUI: function() {
@@ -69,6 +105,6 @@
     }
 });
 PersonPicker.NAME = 'person-picker';
-namespace.PersonPicker = PersonPicker
+namespace.PersonPicker = PersonPicker;
 
-}, "0.1", {"requires": ['lazr.picker']});
+}, "0.1", {"requires": ["lazr.picker"]});

=== modified file 'lib/lp/app/widgets/popup.py'
--- lib/lp/app/widgets/popup.py	2011-06-01 13:59:43 +0000
+++ lib/lp/app/widgets/popup.py	2011-06-08 15:31:34 +0000
@@ -18,6 +18,7 @@
 
 from canonical.launchpad.webapp import canonical_url
 from lp.app.browser.stringformatter import FormattersAPI
+from lp.services.features import getFeatureFlag
 from lp.services.propertycache import cachedproperty
 
 
@@ -26,6 +27,8 @@
 
     __call__ = ViewPageTemplateFile('templates/form-picker.pt')
 
+    picker_type = 'default'
+
     popup_name = 'popup-vocabulary-picker'
 
     # Override inherited attributes for the form field.
@@ -157,6 +160,16 @@
 
     include_create_team_link = False
 
+    @property
+    def picker_type(self):
+        # This is a method for now so we can block the use of the new
+        # person picker js behind our picker_enhancments feature flag.
+        if bool(getFeatureFlag('disclosure.picker_enhancements.enabled')):
+            picker_type = 'person'
+        else:
+            picker_type = 'default'
+        return picker_type
+
     def chooseLink(self):
         link = super(PersonPickerWidget, self).chooseLink()
         if self.include_create_team_link:
@@ -172,7 +185,6 @@
 class BugTrackerPickerWidget(VocabularyPickerWidget):
 
     __call__ = ViewPageTemplateFile('templates/bugtracker-picker.pt')
-
     link_template = """
         or (<a id="create-bugtracker-link"
         href="/bugs/bugtrackers/+newbugtracker"

=== modified file 'lib/lp/app/widgets/templates/form-picker-macros.pt'
--- lib/lp/app/widgets/templates/form-picker-macros.pt	2011-06-01 20:55:24 +0000
+++ lib/lp/app/widgets/templates/form-picker-macros.pt	2011-06-08 15:31:34 +0000
@@ -40,7 +40,8 @@
             var config = {
                 header: ${view/header_text},
                 step_title: ${view/step_title_text},
-                extra_no_results_message: ${view/extra_no_results_message}
+                extra_no_results_message: ${view/extra_no_results_message},
+                picker_type: '${view/picker_type}'
             };
             var picker = Y.lp.app.picker.create('${view/vocabulary_name}', config);
             if (config.extra_no_results_message !== null) {