Merge lp:~thumper/launchpad/use-last-rev-id into lp:launchpad
- use-last-rev-id
- Merge into devel
Status: | Merged |
---|---|
Approved by: | Tim Penhey |
Approved revision: | not available |
Merged at revision: | not available |
Proposed branch: | lp:~thumper/launchpad/use-last-rev-id |
Merge into: | lp:launchpad |
Diff against target: |
411 lines (+138/-43) 8 files modified
lib/canonical/launchpad/javascript/code/branchmergeproposal.js (+81/-8) lib/lp/code/browser/branchmergeproposal.py (+1/-0) lib/lp/code/doc/branch-merge-proposals.txt (+4/-5) lib/lp/code/interfaces/branchmergeproposal.py (+5/-5) lib/lp/code/model/branchmergeproposal.py (+5/-2) lib/lp/code/stories/webservice/xx-branchmergeproposal.txt (+7/-7) lib/lp/code/templates/branchmergeproposal-pagelet-summary.pt (+27/-13) lib/lp/code/windmill/tests/test_branchmergeproposal_commitmessage.py (+8/-3) |
To merge this branch: | bzr merge lp:~thumper/launchpad/use-last-rev-id |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Michael Nelson (community) | ui | Approve | |
Paul Hummer (community) | code js ui* | Approve | |
Review via email: mp+20023@code.launchpad.net |
Commit message
Send through the last scanned id when approving a merge proposal and update the table asynchronously.
Description of the change
Tim Penhey (thumper) wrote : | # |
Tim Penhey (thumper) wrote : | # |
Changed the windmill test to use the approved value and check for the approved revision id.
Paul Hummer (rockstar) wrote : | # |
Think adding a few comments to the insertion code would be helpful. When I look at the patch, I know what the javascript is doing because I see the tal changes as well. Seeing the javascript by itself might be a little confusing (it is a bit hairy, but clever).
Tim Penhey (thumper) wrote : | # |
http://
Michael Nelson (michael.nelson) wrote : | # |
> Need to find a good way to test this.
Heh, a script to setup the environment that you demo'd would be great. I just created an MP for ~name12/
UI-wise, it works really well, updating the display with the extra row when necessary. I laughed in your video near the end where you go to update the version number, but then hesitate and stop the video... made me click it ;). So I assume that'll get done later... do you think it's worth doing it before landing this branch? The non-js fallback works fine, but it does seem strange that it doesn't bring up an overlay and update inline. Up to you.
Now, nothing to do with a UI review, but I wrote a DynamicDomUpdater a while back for this *type* of thing - basically it allows you to plug-in the functionality so that a node (for example, a table node) knows how to update itself. YMMV, but you can find it at:
lib/canonical/
tested at:
lib/canonical/
Cheers,
Michael.
Tim Penhey (thumper) wrote : | # |
Setting the merged revision id has always behaved like that. I hesitated because it wasn't want I was wanting to demonstrate :) I'll take a look at the dynamic dom updater at some stage.
Preview Diff
1 | === modified file 'lib/canonical/launchpad/javascript/code/branchmergeproposal.js' |
2 | --- lib/canonical/launchpad/javascript/code/branchmergeproposal.js 2009-11-23 19:29:02 +0000 |
3 | +++ lib/canonical/launchpad/javascript/code/branchmergeproposal.js 2010-02-26 00:40:38 +0000 |
4 | @@ -32,19 +32,24 @@ |
5 | success: function(entry) { |
6 | var cb = status_choice_edit.get('contentBox'); |
7 | Y.Array.each(conf.status_widget_items, function(item) { |
8 | - if (item.value == status_choice_edit.get( |
9 | - 'value')) { |
10 | - cb.query('span').addClass(item.css_class); |
11 | - } else { |
12 | - cb.query('span').removeClass(item.css_class); |
13 | - } |
14 | - }); |
15 | + if (item.value == status_choice_edit.get('value')) { |
16 | + cb.query('span').addClass(item.css_class); |
17 | + } else { |
18 | + cb.query('span').removeClass(item.css_class); |
19 | + } |
20 | + }); |
21 | + update_summary(); |
22 | + }, |
23 | + end: function() { |
24 | + status_content.one('img').set('src', '/@@/edit'); |
25 | } |
26 | }, |
27 | parameters: { |
28 | - status: status_choice_edit.get('value') |
29 | + status: status_choice_edit.get('value'), |
30 | + revid: conf.source_revid |
31 | } |
32 | }; |
33 | + status_content.one('img').set('src', '/@@/spinner'); |
34 | lp_client = new LP.client.Launchpad(); |
35 | lp_client.named_post( |
36 | LP.client.cache.context.self_link, 'setStatus', config); |
37 | @@ -54,4 +59,72 @@ |
38 | } |
39 | }; |
40 | |
41 | +/* |
42 | + * Update the summary table for the merge proposal. |
43 | + * |
44 | + * An async request is made for the summary table, and the content is |
45 | + * inspected. We don't modify the status row as it is in the process of having |
46 | + * animations run on it. Each of the table rows has an id that is strictly |
47 | + * alphabetical. This ordering is used to determine if a row needs to be |
48 | + * added or removed to the table shown on the current page. If the row |
49 | + * appears in both, the content is checked (except for diffs as that'll never |
50 | + * be the same due to the javascript added classes) and if it differs the |
51 | + * shown rows are updated. |
52 | + */ |
53 | +function update_summary() { |
54 | + var existing_summary = Y.one('#proposal-summary tbody'); |
55 | + SUMMARY_SNIPPET = '+pagelet-summary'; |
56 | + Y.io(SUMMARY_SNIPPET, { |
57 | + on: { |
58 | + success: function(id, response) { |
59 | + var new_summary = Y.Node.create(response.responseText); |
60 | + var new_rows = new_summary.all('tr'); |
61 | + var old_rows = existing_summary.all('tr'); |
62 | + // Skip over the status row (row 0). |
63 | + var new_pos = 1; |
64 | + var old_pos = 1; |
65 | + var new_size = new_rows.size(); |
66 | + var old_size = old_rows.size(); |
67 | + |
68 | + while (new_pos < new_size && old_pos < old_size) { |
69 | + var new_row = new_rows.item(new_pos); |
70 | + var old_row = old_rows.item(old_pos); |
71 | + var new_id = new_row.get('id'); |
72 | + var old_id = old_row.get('id'); |
73 | + if (new_id == old_id) { |
74 | + if (new_id != 'summary-row-b-diff') { |
75 | + // Don't mess with the diff. |
76 | + if (new_row.get('innerHTML') != |
77 | + old_row.get('innerHTML')) { |
78 | + existing_summary.insertBefore(new_row, old_row); |
79 | + old_row.remove(); |
80 | + } |
81 | + } |
82 | + ++new_pos; |
83 | + ++old_pos; |
84 | + } else if (new_id < old_id) { |
85 | + ++new_pos; |
86 | + existing_summary.insertBefore(new_row, old_row); |
87 | + } else { |
88 | + ++old_pos; |
89 | + old_row.remove(); |
90 | + } |
91 | + } |
92 | + // Remove all left over old rows, and add all left over new rows. |
93 | + while (old_pos < old_size) { |
94 | + var old_row = old_rows.item(old_pos); |
95 | + ++old_pos; |
96 | + old_row.remove(); |
97 | + } |
98 | + while (new_pos < new_size) { |
99 | + var new_row = new_rows.item(new_pos); |
100 | + ++new_pos; |
101 | + if (new_row.get('id') != 'summary-row-b-diff') { |
102 | + existing_summary.append(new_row); |
103 | + } |
104 | + } |
105 | + } |
106 | + }}); |
107 | +} |
108 | + |
109 | }, "0.1", {"requires": ["io", "node", "lazr.choiceedit", "lp.client.plugins"]}); |
110 | |
111 | === modified file 'lib/lp/code/browser/branchmergeproposal.py' |
112 | --- lib/lp/code/browser/branchmergeproposal.py 2010-02-05 21:59:26 +0000 |
113 | +++ lib/lp/code/browser/branchmergeproposal.py 2010-02-26 00:40:39 +0000 |
114 | @@ -687,6 +687,7 @@ |
115 | self._createStatusVocabulary(), |
116 | css_class_prefix='mergestatus'), |
117 | 'status_value': self.context.queue_status.title, |
118 | + 'source_revid': self.context.source_branch.last_scanned_id, |
119 | 'user_can_edit_status': check_permission( |
120 | 'launchpad.Edit', self.context), |
121 | }) |
122 | |
123 | === modified file 'lib/lp/code/doc/branch-merge-proposals.txt' |
124 | --- lib/lp/code/doc/branch-merge-proposals.txt 2009-10-01 17:41:10 +0000 |
125 | +++ lib/lp/code/doc/branch-merge-proposals.txt 2010-02-26 00:40:38 +0000 |
126 | @@ -257,12 +257,11 @@ |
127 | >>> print proposal.queue_status.title |
128 | Needs review |
129 | |
130 | -Branches that had been approved that have subsequently been |
131 | -set back into the needs review state still retain their old reviewed |
132 | -revision id. |
133 | +Branches that had been approved that have subsequently been set back into the |
134 | +needs review state have their reviewed revision cleared. |
135 | |
136 | - >>> proposal.reviewed_revision_id == tip.revision_id |
137 | - True |
138 | + >>> print proposal.reviewed_revision_id |
139 | + None |
140 | |
141 | If the target branch has specified a specific reviewer, then either the owner |
142 | of the target branch or the reviewer is able to approve or reject the |
143 | |
144 | === modified file 'lib/lp/code/interfaces/branchmergeproposal.py' |
145 | --- lib/lp/code/interfaces/branchmergeproposal.py 2010-01-11 20:07:17 +0000 |
146 | +++ lib/lp/code/interfaces/branchmergeproposal.py 2010-02-26 00:40:38 +0000 |
147 | @@ -133,7 +133,7 @@ |
148 | Text( |
149 | title=_( |
150 | "The revision id that has been approved by the reviewer.")), |
151 | - exported_as='reviewed_revno') |
152 | + exported_as='reviewed_revid') |
153 | |
154 | commit_message = exported( |
155 | Summary( |
156 | @@ -159,7 +159,7 @@ |
157 | required=False, |
158 | description=_("The revision id that has been queued for " |
159 | "landing.")), |
160 | - exported_as='queued_revno') |
161 | + exported_as='queued_revid') |
162 | |
163 | merged_revno = exported( |
164 | Int( |
165 | @@ -269,7 +269,7 @@ |
166 | """True if it is valid for user update the proposal to next_state.""" |
167 | |
168 | @call_with(user=REQUEST_USER) |
169 | - @rename_parameters_as(revision_id='revno') |
170 | + @rename_parameters_as(revision_id='revid') |
171 | @operation_parameters( |
172 | status=Choice( |
173 | title=_("The new status of the merge proposal."), |
174 | @@ -284,8 +284,8 @@ |
175 | |
176 | :param status: The new status of the merge proposal. |
177 | :param user: The user making the change. |
178 | - :param revision_id: The revno to provide to the underlying status |
179 | - change method. |
180 | + :param revision_id: The revision id to provide to the underlying |
181 | + status change method. |
182 | """ |
183 | |
184 | def setAsWorkInProgress(): |
185 | |
186 | === modified file 'lib/lp/code/model/branchmergeproposal.py' |
187 | --- lib/lp/code/model/branchmergeproposal.py 2009-12-18 20:14:21 +0000 |
188 | +++ lib/lp/code/model/branchmergeproposal.py 2010-02-26 00:40:39 +0000 |
189 | @@ -340,8 +340,6 @@ |
190 | self.setAsWorkInProgress() |
191 | elif status == BranchMergeProposalStatus.NEEDS_REVIEW: |
192 | self.requestReview() |
193 | - elif status == BranchMergeProposalStatus.NEEDS_REVIEW: |
194 | - self.requestReview() |
195 | elif status == BranchMergeProposalStatus.CODE_APPROVED: |
196 | # Other half of the edge case. If the status is currently queued, |
197 | # we need to dequeue, otherwise we just approve the branch. |
198 | @@ -378,6 +376,11 @@ |
199 | if self.queue_status != BranchMergeProposalStatus.NEEDS_REVIEW: |
200 | self._transitionToState(BranchMergeProposalStatus.NEEDS_REVIEW) |
201 | self.date_review_requested = _date_requested |
202 | + # Clear out any reviewed or queued values. |
203 | + self.reviewer = None |
204 | + self.reviewed_revision_id = None |
205 | + self.queuer = None |
206 | + self.queued_revision_id = None |
207 | |
208 | def isMergable(self): |
209 | """See `IBranchMergeProposal`.""" |
210 | |
211 | === modified file 'lib/lp/code/stories/webservice/xx-branchmergeproposal.txt' |
212 | --- lib/lp/code/stories/webservice/xx-branchmergeproposal.txt 2010-02-04 16:52:05 +0000 |
213 | +++ lib/lp/code/stories/webservice/xx-branchmergeproposal.txt 2010-02-26 00:40:39 +0000 |
214 | @@ -42,12 +42,12 @@ |
215 | private: False |
216 | queue_position: None |
217 | queue_status: u'Needs review' |
218 | - queued_revno: None |
219 | + queued_revid: None |
220 | queuer_link: None |
221 | registrant_link: u'http://api.launchpad.dev/beta/~person-name...' |
222 | resource_type_link: |
223 | u'http://api.launchpad.dev/beta/#branch_merge_proposal' |
224 | - reviewed_revno: None |
225 | + reviewed_revid: None |
226 | reviewer_link: None |
227 | self_link: u'http://api.launchpad.dev/beta/~.../+merge/...' |
228 | source_branch_link: u'http://api.launchpad.dev/beta/~...' |
229 | @@ -136,11 +136,11 @@ |
230 | private: False |
231 | queue_position: None |
232 | queue_status: u'Work in progress' |
233 | - queued_revno: None |
234 | + queued_revid: None |
235 | queuer_link: None |
236 | registrant_link: u'http://.../~person-name...' |
237 | resource_type_link: u'http://.../#branch_merge_proposal' |
238 | - reviewed_revno: None |
239 | + reviewed_revid: None |
240 | reviewer_link: None |
241 | self_link: u'http://.../~source/fooix/fix-it/+merge/...' |
242 | source_branch_link: u'http://.../~source/fooix/fix-it' |
243 | @@ -259,13 +259,13 @@ |
244 | |
245 | >>> _unused = reviewer_webservice.named_post( |
246 | ... merge_proposal['self_link'], 'setStatus', |
247 | - ... status=u'Approved', revno=u'25') |
248 | + ... status=u'Approved', revid=u'25') |
249 | >>> merge_proposal = reviewer_webservice.get( |
250 | ... merge_proposal['self_link']).jsonBody() |
251 | |
252 | >>> print merge_proposal['queue_status'] |
253 | Approved |
254 | - >>> print merge_proposal['reviewed_revno'] |
255 | + >>> print merge_proposal['reviewed_revid'] |
256 | 25 |
257 | |
258 | However, there may have been breakage in the branch, and we need to revert back |
259 | @@ -279,7 +279,7 @@ |
260 | |
261 | >>> print merge_proposal['queue_status'] |
262 | Work in progress |
263 | - >>> print merge_proposal['reviewed_revno'] |
264 | + >>> print merge_proposal['reviewed_revid'] |
265 | None |
266 | |
267 | |
268 | |
269 | === modified file 'lib/lp/code/templates/branchmergeproposal-pagelet-summary.pt' |
270 | --- lib/lp/code/templates/branchmergeproposal-pagelet-summary.pt 2010-02-02 17:19:05 +0000 |
271 | +++ lib/lp/code/templates/branchmergeproposal-pagelet-summary.pt 2010-02-26 00:40:39 +0000 |
272 | @@ -6,7 +6,15 @@ |
273 | tal:define="context_menu context/menu:context"> |
274 | |
275 | <tbody> |
276 | - <tr> |
277 | + <tal:comment condition="nothing"> |
278 | + <!-- |
279 | + Each of the rows in this table have an id that is strictly |
280 | + alphabetical (according to ASCII). This is used in the javascript |
281 | + processing of the summary to determine which rows have been added, |
282 | + and removed through AJAX requests. |
283 | + --> |
284 | + </tal:comment> |
285 | + <tr id="summary-row-1-status"> |
286 | <th>Status:</th> |
287 | <td id="branchmergeproposal-status-value"> |
288 | <span tal:attributes="class string:value mergestatus${context/queue_status/name}" |
289 | @@ -21,12 +29,14 @@ |
290 | </td> |
291 | </tr> |
292 | <tal:comment condition="nothing"> |
293 | - Only show the reviewed section if the state is not superseded. |
294 | - Only show the reviewed revision if not rejected. |
295 | + <!-- |
296 | + Only show the reviewed section if the state is not superseded. |
297 | + Only show the reviewed revision if not rejected. |
298 | + --> |
299 | </tal:comment> |
300 | <tal:not-superseded condition="not: context/queue_status/enumvalue:SUPERSEDED"> |
301 | <tal:reviewed condition="context/reviewer"> |
302 | - <tr> |
303 | + <tr id="summary-row-2-reviewer"> |
304 | <th> |
305 | <tal:rejected condition="context/queue_status/enumvalue:REJECTED"> |
306 | Rejected by: |
307 | @@ -42,7 +52,8 @@ |
308 | <tal:modified replace="context/date_reviewed/fmt:displaydate" /> |
309 | </td> |
310 | </tr> |
311 | - <tr tal:condition="not: context/queue_status/enumvalue:REJECTED"> |
312 | + <tr id="summary-row-3-approved-revision" |
313 | + tal:condition="not: context/queue_status/enumvalue:REJECTED"> |
314 | <th>Approved revision:</th> |
315 | <td> |
316 | <tal:not-available condition="not: context/reviewed_revision_id"> |
317 | @@ -57,11 +68,11 @@ |
318 | </tal:reviewed> |
319 | </tal:not-superseded> |
320 | <tal:queued condition="context/queue_status/enumvalue:QUEUED"> |
321 | - <tr> |
322 | + <tr id="summary-row-4-queued-by"> |
323 | <th>Queued by:</th> |
324 | <td tal:content="structure context/queuer/fmt:link">Some User</td> |
325 | </tr> |
326 | - <tr> |
327 | + <tr id="summary-row-5-queued-revision"> |
328 | <th>Queued revision:</th> |
329 | <td> |
330 | <tal:not-available condition="not: context/queued_revision_id"> |
331 | @@ -75,11 +86,12 @@ |
332 | </tr> |
333 | </tal:queued> |
334 | <tal:merged condition="context/queue_status/enumvalue:MERGED"> |
335 | - <tr tal:condition="context/merge_reporter"> |
336 | + <tr id="summary-row-6-merge-reporter" |
337 | + tal:condition="context/merge_reporter"> |
338 | <th>Merge reported by:</th> |
339 | <td tal:content="structure context/merge_reporter/fmt:link">Some User</td> |
340 | </tr> |
341 | - <tr> |
342 | + <tr id="summary-row-7-merged-revision"> |
343 | <th>Merged at revision:</th> |
344 | <td> |
345 | <tal:not-available condition="not: context/merged_revno"> |
346 | @@ -97,19 +109,21 @@ |
347 | </td> |
348 | </tr> |
349 | </tal:merged> |
350 | - <tr> |
351 | + <tr id="summary-row-8-source-branch"> |
352 | <th>Proposed branch:</th> |
353 | <td tal:content="structure context/source_branch/fmt:bzr-link">lp:~foo/bar/baz</td> |
354 | </tr> |
355 | - <tr> |
356 | + <tr id="summary-row-9-target-branch"> |
357 | <th>Merge into:</th> |
358 | <td tal:content="structure context/target_branch/fmt:bzr-link">lp:~foo/bar/baz</td> |
359 | </tr> |
360 | - <tr tal:condition="context/prerequisite_branch"> |
361 | + <tr id="summary-row-a-prerequisite-branch" |
362 | + tal:condition="context/prerequisite_branch"> |
363 | <th>Prerequisite:</th> |
364 | <td tal:content="structure context/prerequisite_branch/fmt:bzr-link">lp:~foo/bar/baz</td> |
365 | </tr> |
366 | - <tr tal:condition="context/preview_diff"> |
367 | + <tr id="summary-row-b-diff" |
368 | + tal:condition="context/preview_diff"> |
369 | <th>Diff against target:</th> |
370 | <td> |
371 | <tal:diff replace="structure context/preview_diff/fmt:link"/> |
372 | |
373 | === modified file 'lib/lp/code/windmill/tests/test_branchmergeproposal_commitmessage.py' |
374 | --- lib/lp/code/windmill/tests/test_branchmergeproposal_commitmessage.py 2010-02-01 18:37:00 +0000 |
375 | +++ lib/lp/code/windmill/tests/test_branchmergeproposal_commitmessage.py 2010-02-26 00:40:38 +0000 |
376 | @@ -81,6 +81,7 @@ |
377 | email="mike@example.com") |
378 | branch = self.factory.makeBranch(owner=mike) |
379 | second_branch = self.factory.makeBranch(product=branch.product) |
380 | + self.factory.makeRevisionsForBranch(second_branch) |
381 | merge_proposal = second_branch.addLandingTarget(mike, branch) |
382 | transaction.commit() |
383 | |
384 | @@ -99,12 +100,16 @@ |
385 | xpath=u'//div[contains(@class, "yui-ichoicelist-content")]') |
386 | |
387 | # Change the status to experimental. |
388 | - client.click(link=u'Rejected') |
389 | + client.click(link=u'Approved') |
390 | client.waits.sleep(milliseconds=SLEEP) |
391 | |
392 | client.asserts.assertText( |
393 | xpath=u'//td[@id="branchmergeproposal-status-value"]/span', |
394 | - validator=u'Rejected') |
395 | + validator=u'Approved') |
396 | + |
397 | + client.asserts.assertText( |
398 | + xpath=u'//tr[@id="summary-row-3-approved-revision"]/td', |
399 | + validator=u'5') |
400 | |
401 | # Reload the page and make sure the change sticks. |
402 | client.open(url=merge_url) |
403 | @@ -114,7 +119,7 @@ |
404 | timeout=FOR_ELEMENT) |
405 | client.asserts.assertText( |
406 | xpath=u'//td[@id="branchmergeproposal-status-value"]/span', |
407 | - validator=u'Rejected') |
408 | + validator=u'Approved') |
409 | |
410 | |
411 | def test_suite(): |
Need to find a good way to test this.