Merge lp:~thumper/launchpad/edit-commit-msg-link into lp:launchpad/db-devel

Proposed by Tim Penhey
Status: Merged
Merged at revision: not available
Proposed branch: lp:~thumper/launchpad/edit-commit-msg-link
Merge into: lp:launchpad/db-devel
Diff against target: 316 lines (+120/-27)
7 files modified
lib/canonical/launchpad/javascript/code/codereview.js (+66/-3)
lib/canonical/widgets/lazrjs.py (+7/-2)
lib/lp/app/templates/base-layout-macros.pt (+3/-1)
lib/lp/code/browser/branchmergeproposal.py (+5/-5)
lib/lp/code/stories/branches/xx-branch-merge-proposals.txt (+4/-3)
lib/lp/code/templates/branchmergeproposal-index.pt (+32/-10)
lib/lp/code/windmill/tests/test_branch_merge_proposal.py (+3/-3)
To merge this branch: bzr merge lp:~thumper/launchpad/edit-commit-msg-link
Reviewer Review Type Date Requested Status
Francis J. Lacoste (community) release-critical Approve
Māris Fogels (community) js Approve
Michael Hudson-Doyle Abstain
Martin Albisetti (community) ui Approve
Guilherme Salgado Pending
Review via email: mp+15260@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Tim Penhey (thumper) wrote :

Change the UI so it doesn't show an empty commit message in the editor, but instead shows a link.

Hooks into the editor events so it knows to flash green or red when the commit message ends up empty.

Revision history for this message
Martin Albisetti (beuno) wrote :

This looks great, Tim! Thanks for working on it :)

What do you think about moving the link closer to the information on the MP? (ie, underneath "merge into")?

review: Approve (ui)
Revision history for this message
Michael Hudson-Doyle (mwhudson) wrote :

All the interesting stuff is Javascript, which I don't really feel competent to review :( It looks fine, but I don't know anything about our coding standards really.

I'm not sure that the block starting:

+ <div id="commit-message" class="yui-g">
+ <tal:no-commit-message condition="not: context/commit_message">

Can't be better factored, but it's TAL so maybe not.

review: Abstain
Revision history for this message
Tim Penhey (thumper) wrote :

On Fri, 27 Nov 2009 16:37:59 Michael Hudson wrote:
> Review: Abstain
> All the interesting stuff is Javascript, which I don't really feel
> competent to review :( It looks fine, but I don't know anything about our
> coding standards really.
>
> I'm not sure that the block starting:
>
> + <div id="commit-message" class="yui-g">
> + <tal:no-commit-message condition="not: context/commit_message">
>
> Can't be better factored, but it's TAL so maybe not.

No it can't really, there are several bits that follow.

  reviewer launchpad

Revision history for this message
Māris Fogels (mars) wrote :

Hi Tim,

As we discussed on IRC, your approach is good. However, I do have a question or two about how you chose to integrate the widget into Launchpad.

I'm marking this as Needs Information for now. If you have already considered and confirmed the answers, then feel free to land the code with r=mars.

First, I don't understand why you had to create your own wrapper for the multiline editor. Did the inline editor's activator widget not work? The Activator is used to make the current set of inline editors flash and spin.

Line by line:

• 13: I strongly suggest using a different namespace to store the static reference to the widget. The 'lp' namespace would be an acceptable place.
• 27: Is the message variable reliably an empty string, or could it possibly be null? Check the inline editor's message attribute getter. Does the inline editor have an isEmpty() method?
• 50: Do you want to use e.preventDefault(), or e.halt()?
• 56: Too bad you have to call a protected method to trigger the editor. That is a wart in the API.
• 89: See my above comment about using the 'lp' namespace to host the global variable instead of using Y itself.

var lpns = Y.namespace('lp');
if (!lpns.widgets) { lpns.widgets = {}; }
lpns.widgets['%s'] = widget;

Maris

review: Needs Information (js)
Revision history for this message
Tim Penhey (thumper) wrote :

On Sat, 28 Nov 2009 04:54:18 Māris Fogels wrote:
> First, I don't understand why you had to create your own wrapper for the
> multiline editor. Did the inline editor's activator widget not work? The
> Activator is used to make the current set of inline editors flash and
> spin.

I'm sorry. I don't understand this at all. What activator widget?

Do you mean this code?

> var widget = Y.lp.widgets['edit-commit-message'];
> widget.editor.on('save', function() {
> commit_message_listener(this.get('value'), true);
> });
> widget.editor.on('cancel', function() {
> commit_message_listener(this.get('value'), false);
> });

If I try to remove the ".editor" it doesn't work. So I can't just attach to
the "save" or "cancel" button of the widget - which is what I'd like to do.

> Line by line:
>
> • 13: I strongly suggest using a different namespace to store the static
> reference to the widget. The 'lp' namespace would be an acceptable place.

Done.

> • 27: Is the message variable reliably an empty string, or could it
> possibly be null? Check the inline editor's message attribute getter.
> Does the inline editor have an isEmpty() method?

The widget will never give us null, only empty strings.

Since the widget doesn't allow listening on the save or cancel events, they
had to be listened to on the ieditor - and as such the widget is not easily
available to listen to. No the inline editor does not have an isEmpty method.

> • 50: Do you want to use
> e.preventDefault(), or e.halt()?

I don't know. Halt probably, but I was copying from other code. Should we
use halt if we have handled the problem?

> • 56: Too bad you have to call a protected method to trigger the editor.
> That is a wart in the API.

Yep.

Tim

Revision history for this message
Māris Fogels (mars) wrote :

Hi Tim,

As discussed on IRC, the calls to commit_message_listener() actually flash the merge link, not the original trigger or message. I couldn't read that in the code, but it makes sense. Perhaps there is some way to make that visual feature a bit clearer.

Using e.halt() is the correct behaviour if you have handled the result. In the case of clicking on a link, you usually want to prevent others from handling a click, so e.halt() is correct.

Please try to clarify the reason for flashing code a bit, and use e.halt(). With those, you will be good to land: r=mars.

Maris

review: Approve (js)
Revision history for this message
Francis J. Lacoste (flacoste) :
review: Approve (release-critical)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/canonical/launchpad/javascript/code/codereview.js'
2--- lib/canonical/launchpad/javascript/code/codereview.js 2009-11-24 09:30:01 +0000
3+++ lib/canonical/launchpad/javascript/code/codereview.js 2009-11-30 23:54:16 +0000
4@@ -24,9 +24,67 @@
5 link.addClass('js-action');
6 link.on('click', show_request_review_form);
7 }
8+ link = Y.one('.menu-link-set_commit_message');
9+ if (link !== null) {
10+ link.addClass('js-action');
11+ link.on('click', edit_commit_message);
12+ }
13+ var widget = Y.lp.widgets['edit-commit-message'];
14+ widget.editor.on('save', function() {
15+ commit_message_listener(this.get('value'), true);
16+ });
17+ widget.editor.on('cancel', function() {
18+ commit_message_listener(this.get('value'), false);
19+ });
20 };
21
22 /*
23+ * Hide the commit message editor if the value is empty.
24+ *
25+ * If the commit message is empty, we want to show the
26+ * 'Set commit message' link again. For consistency with
27+ * page updates we want to flash this link so the user can
28+ * see what we are doing. If the commit message was saved
29+ * and is empty, then we flash green as all is good. If the
30+ * user has cancelled the edit, and the commit message is
31+ * empty, then we flash the link red.
32+ */
33+function commit_message_listener(message, saved)
34+{
35+ if (message == '') {
36+ // Hide the multiline editor
37+ Y.one('#edit-commit-message').addClass('unseen');
38+ // Show the link again
39+ var link = Y.one('.menu-link-set_commit_message');
40+ link.removeClass('unseen');
41+ if (saved) {
42+ // Flash green.
43+ Y.lazr.anim.green_flash({node:link}).run();
44+ }
45+ else {
46+ // Flash red.
47+ Y.lazr.anim.red_flash({node:link}).run();
48+ }
49+ }
50+}
51+
52+/*
53+ * Edit the commit message.
54+ *
55+ * Hide the link, show the multi-line editor, and set it to edit.
56+ */
57+function edit_commit_message(e) {
58+ // We are handling this click event.
59+ e.halt();
60+ // Make the edit button unseen.
61+ Y.one('#edit-commit-message').removeClass('unseen');
62+ // Remove the unseen class from the commit message.
63+ Y.one('.menu-link-set_commit_message').addClass('unseen');
64+ // Trigger the edit on the multiline editor.
65+ Y.lp.widgets['edit-commit-message']._triggerEdit(e);
66+}
67+
68+/*
69 * Show the "Request a reviewer" overlay.
70 */
71 function show_request_review_form(e) {
72@@ -149,10 +207,15 @@
73 '<input type="checkbox" checked="checked" id="show-no"/>' +
74 '&nbsp;Show line numbers</label></li>');
75 var ul = Y.one('#review-diff div div ul.horizontal');
76- ul.appendChild(ui);
77+ if (ul) {
78+ ul.appendChild(ui);
79+ }
80 },
81- bindUI: function(){
82- Y.one('#show-no').on('click', update_nos);
83+ bindUI: function() {
84+ var cb = Y.one('#show-no');
85+ if (cb) {
86+ cb.on('click', update_nos);
87+ }
88 }
89 });
90
91
92=== modified file 'lib/canonical/widgets/lazrjs.py'
93--- lib/canonical/widgets/lazrjs.py 2009-10-28 08:03:36 +0000
94+++ lib/canonical/widgets/lazrjs.py 2009-11-30 23:54:16 +0000
95@@ -61,7 +61,7 @@
96 # Template for the activation script.
97 ACTIVATION_TEMPLATE = dedent(u"""\
98 <script>
99- YUI().use('lazr.editor', 'lp.client.plugins', function (Y) {
100+ LPS.use('lazr.editor', 'lp.client.plugins', function (Y) {
101 var widget = new Y.EditableText({
102 contentBox: '#%(id)s',
103 accept_empty: %(accept_empty)s,
104@@ -198,7 +198,7 @@
105
106 ACTIVATION_TEMPLATE = dedent(u"""\
107 <script>
108- YUI().use('lazr.editor', 'lp.client.plugins', function (Y) {
109+ LPS.use('lazr.editor', 'lp.client.plugins', function (Y) {
110 var widget = new Y.EditableText({
111 contentBox: '#%(id)s',
112 accept_empty: %(accept_empty)s,
113@@ -215,6 +215,11 @@
114 if (!Y.UA.opera) {
115 widget.render();
116 }
117+ var lpns = Y.namespace('lp');
118+ if (!lpns.widgets) {
119+ lpns.widgets = {};
120+ }
121+ lpns.widgets['%(id)s'] = widget;
122 });
123 </script>
124 """)
125
126=== modified file 'lib/lp/app/templates/base-layout-macros.pt'
127--- lib/lp/app/templates/base-layout-macros.pt 2009-11-24 09:30:01 +0000
128+++ lib/lp/app/templates/base-layout-macros.pt 2009-11-30 23:54:16 +0000
129@@ -222,7 +222,9 @@
130 <metal:load-lavascript use-macro="context/@@+base-layout-macros/load-javascript" />
131
132 <script type="text/javascript">
133- YUI().use('node', 'lp', function(Y) {
134+ // Define a global YUI sandbox that should be used by everyone.
135+ var LPS = YUI();
136+ LPS.use('node', 'lp', function(Y) {
137 Y.on('load', function(e) {
138 sortables_init();
139 initInlineHelp();
140
141=== modified file 'lib/lp/code/browser/branchmergeproposal.py'
142--- lib/lp/code/browser/branchmergeproposal.py 2009-11-18 04:23:29 +0000
143+++ lib/lp/code/browser/branchmergeproposal.py 2009-11-30 23:54:16 +0000
144@@ -195,10 +195,10 @@
145 return Link('+edit', text, icon='edit', enabled=enabled)
146
147 @enabled_with_permission('launchpad.Edit')
148- def edit_commit_message(self):
149- text = 'Edit commit message'
150+ def set_commit_message(self):
151+ text = 'Set commit message'
152 enabled = self.context.isMergable()
153- return Link('+edit-commit-message', text, icon='edit',
154+ return Link('+edit-commit-message', text, icon='add',
155 enabled=enabled)
156
157 @enabled_with_permission('launchpad.Edit')
158@@ -292,7 +292,7 @@
159 links = [
160 'add_comment',
161 'dequeue',
162- 'edit_commit_message',
163+ 'set_commit_message',
164 'edit_status',
165 'enqueue',
166 'merge',
167@@ -600,7 +600,7 @@
168 self.context,
169 'commit_message',
170 canonical_url(self.context, view_name='+edit-commit-message'),
171- id="edit-description",
172+ id="edit-commit-message",
173 title="Commit Message",
174 value=commit_message,
175 accept_empty=True)
176
177=== modified file 'lib/lp/code/stories/branches/xx-branch-merge-proposals.txt'
178--- lib/lp/code/stories/branches/xx-branch-merge-proposals.txt 2009-11-23 03:41:39 +0000
179+++ lib/lp/code/stories/branches/xx-branch-merge-proposals.txt 2009-11-30 23:54:16 +0000
180@@ -100,7 +100,7 @@
181 ... 'Add more <b>mojo</b>')
182 >>> nopriv_browser.getControl('Update').click()
183
184- >>> print_tag_with_id(nopriv_browser.contents, 'edit-description')
185+ >>> print_tag_with_id(nopriv_browser.contents, 'edit-commit-message')
186 Commit Message
187 Add more &lt;b&gt;mojo&lt;/b&gt;
188
189@@ -111,8 +111,9 @@
190 ... '')
191 >>> nopriv_browser.getControl('Update').click()
192
193- >>> print_tag_with_id(nopriv_browser.contents, 'edit-description')
194- Commit Message
195+ >>> print_tag_with_id(nopriv_browser.contents, 'commit-message')
196+ Set commit message
197+ ...
198
199
200 Deleting merge proposals
201
202=== modified file 'lib/lp/code/templates/branchmergeproposal-index.pt'
203--- lib/lp/code/templates/branchmergeproposal-index.pt 2009-11-13 03:21:35 +0000
204+++ lib/lp/code/templates/branchmergeproposal-index.pt 2009-11-30 23:54:16 +0000
205@@ -12,14 +12,17 @@
206
207 <metal:block fill-slot="head_epilogue">
208 <style type="text/css">
209+ .menu-link-set_commit_message {
210+ margin-top: 1em;
211+ }
212 #code-review-votes {
213- margin: 2em 0;
214+ margin: 1em 0;
215 }
216- #edit-description {
217+ #commit-message, #edit-commit-message {
218 margin: 1em 0 0 0;
219 }
220 /* A page-specific fix for inline text are editing to line up box. */
221- #edit-description .yui-ieditor-input { top: 0; }
222+ #edit-commit-message .yui-ieditor-input { top: 0; }
223 </style>
224 </metal:block>
225
226@@ -38,12 +41,34 @@
227 </metal:side>
228
229
230-<div metal:fill-slot="main">
231+<div metal:fill-slot="main"
232+ tal:define="menu context/menu:context">
233
234 <div class="yui-g first">
235 <tal:summary replace="structure context/@@+pagelet-summary" />
236 </div>
237
238+ <div id="commit-message" class="yui-g">
239+ <tal:no-commit-message condition="not: context/commit_message">
240+ <div tal:define="link menu/set_commit_message"
241+ tal:condition="link/enabled"
242+ tal:content="structure link/render">
243+ Set commit message
244+ </div>
245+ <div id="edit-commit-message" class="lazr-multiline-edit unseen"
246+ tal:content="structure view/commit_message_html"/>
247+ </tal:no-commit-message>
248+ <tal:has-commit-message condition="context/commit_message">
249+ <div tal:define="link menu/set_commit_message"
250+ tal:condition="link/enabled"
251+ tal:content="structure link/render" class="unseen">
252+ Set commit message
253+ </div>
254+ <div id="edit-commit-message" class="lazr-multiline-edit"
255+ tal:content="structure view/commit_message_html"/>
256+ </tal:has-commit-message>
257+ </div>
258+
259 <div class="yui-g">
260 <div id="votes-target"
261 tal:content="structure context/@@+votes" />
262@@ -67,15 +92,12 @@
263 </div>
264
265 <div class="yui-g">
266- <div tal:define="link context/menu:context/add_comment"
267+ <div tal:define="link menu/add_comment"
268 tal:condition="link/enabled"
269 tal:content="structure link/render">
270 Add comment
271 </div>
272
273- <div id="edit-description" class="lazr-multiline-edit"
274- tal:content="structure view/commit_message_html"/>
275-
276 <div id="conversation"
277 tal:content="structure view/conversation/@@+render"/>
278 </div>
279@@ -88,7 +110,7 @@
280 </div>
281
282 <script type="text/javascript">
283- YUI().use('lp.comment', function(Y) {
284+ LPS.use('lp.comment', function(Y) {
285 var comment = new Y.lp.CodeReviewComment();
286 comment.render();
287 })
288@@ -137,7 +159,7 @@
289 string:&lt;script id='codereview-script' type='text/javascript'&gt;" />
290 conf = <tal:status-config replace="view/status_config" />
291 <!--
292- YUI().use('io-base', 'code.codereview', 'code.branchmergeproposal',
293+ LPS.use('io-base', 'code.codereview', 'code.branchmergeproposal',
294 function(Y) {
295
296
297
298=== modified file 'lib/lp/code/windmill/tests/test_branch_merge_proposal.py'
299--- lib/lp/code/windmill/tests/test_branch_merge_proposal.py 2009-11-10 18:10:12 +0000
300+++ lib/lp/code/windmill/tests/test_branch_merge_proposal.py 2009-11-30 23:54:16 +0000
301@@ -22,12 +22,12 @@
302 # There seem to be two textareas rendered for the yui-ieditor-input for some
303 # reason.
304 EDIT_COMMENT_TEXTBOX = (
305- u'//div[@id="edit-description"]//textarea[@class="yui-ieditor-input"][1]')
306+ u'//div[@id="edit-commit-message"]//textarea[@class="yui-ieditor-input"][1]')
307 EDIT_COMMENT_SUBMIT = (
308- u'//div[@id="edit-description"]//'
309+ u'//div[@id="edit-commit-message"]//'
310 'button[contains(@class, "yui-ieditor-submit_button")]')
311 COMMIT_MESSAGE_TEXT = (
312- u'//div[@id="edit-description"]//div[@class="yui-editable_text-text"]')
313+ u'//div[@id="edit-commit-message"]//div[@class="yui-editable_text-text"]')
314
315
316 class TestCommitMessage(TestCaseWithFactory):

Subscribers

People subscribed via source and target branches

to status/vote changes: