Merge lp:~mwhudson/loggerhead/ajaxy-changelog into lp:loggerhead

Proposed by Michael Hudson-Doyle
Status: Merged
Approved by: Paul Hummer
Approved revision: 307
Merged at revision: not available
Proposed branch: lp:~mwhudson/loggerhead/ajaxy-changelog
Merge into: lp:loggerhead
Diff against target: None lines
To merge this branch: bzr merge lp:~mwhudson/loggerhead/ajaxy-changelog
Reviewer Review Type Date Requested Status
Paul Hummer (community) Approve
Review via email: mp+4515@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Michael Hudson-Doyle (mwhudson) wrote :

The main point of this branch is not including the lists of files changed in the changelog view and, if the user clicks the disclosure triangle, loading this bit via AJAX (or AHAH, really).

It also thoroughly rejigs the way the animation is done to animate marginBottom instead of height (after reading the source for Fx.Slide from mootools...). If you artificially slow the anims down in custom.js you can see the difference fairly clearly. This bit could/should have been done in a different branch, oh well, sorry about that :)

307. By Michael Hudson-Doyle

merge trunk

Revision history for this message
Paul Hummer (rockstar) wrote :

Hi Michael-

  These changes look good. The animations look better now. I still think we
should seriously consider a lazr-js dependency, as I think that it would be a
great help to both the loggerhead project and the lazr-js project.

 vote approve
 status approved

Cheers,
Paul

--
Paul Hummer
http://theironlion.net
1024/862FF08F C921 E962 58F8 5547 6723 0E8C 1C4D 8AC5 862F F08F

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'loggerhead/apps/branch.py'
2--- loggerhead/apps/branch.py 2009-02-18 10:36:48 +0000
3+++ loggerhead/apps/branch.py 2009-03-13 05:36:26 +0000
4@@ -15,6 +15,7 @@
5 from loggerhead.controllers.inventory_ui import InventoryUI
6 from loggerhead.controllers.annotate_ui import AnnotateUI
7 from loggerhead.controllers.revision_ui import RevisionUI
8+from loggerhead.controllers.revlog_ui import RevLogUI
9 from loggerhead.controllers.atom_ui import AtomUI
10 from loggerhead.controllers.download_ui import DownloadUI
11 from loggerhead.controllers.search_ui import SearchUI
12@@ -82,6 +83,7 @@
13 'changes': ChangeLogUI,
14 'files': InventoryUI,
15 'revision': RevisionUI,
16+ '+revlog': RevLogUI,
17 'download': DownloadUI,
18 'atom': AtomUI,
19 'search': SearchUI,
20
21=== modified file 'loggerhead/controllers/changelog_ui.py'
22--- loggerhead/controllers/changelog_ui.py 2008-12-05 18:52:44 +0000
23+++ loggerhead/controllers/changelog_ui.py 2009-03-13 05:36:26 +0000
24@@ -17,6 +17,8 @@
25 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 #
27
28+import simplejson
29+
30 from paste.httpexceptions import HTTPServerError
31
32 from loggerhead import util
33@@ -58,7 +60,10 @@
34 scan_list = revid_list[i:]
35 change_list = scan_list[:pagesize]
36 changes = list(history.get_changes(change_list))
37- history.add_changes(changes)
38+ data = {}
39+ for i, c in enumerate(changes):
40+ c.index = i
41+ data[str(i)] = c.revid
42 except:
43 self.log.exception('Exception fetching changes')
44 raise HTTPServerError('Could not fetch changes')
45@@ -71,9 +76,6 @@
46 navigation.query = query
47 util.fill_in_navigation(navigation)
48
49- # add parent & merge-point branch-nick info, in case it's useful
50- history.get_branch_nicks(changes)
51-
52 # Directory Breadcrumbs
53 directory_breadcrumbs = (
54 util.directory_breadcrumbs(
55@@ -84,6 +86,7 @@
56 return {
57 'branch': self._branch,
58 'changes': changes,
59+ 'data': simplejson.dumps(data),
60 'util': util,
61 'history': history,
62 'revid': revid,
63
64=== added file 'loggerhead/controllers/revlog_ui.py'
65--- loggerhead/controllers/revlog_ui.py 1970-01-01 00:00:00 +0000
66+++ loggerhead/controllers/revlog_ui.py 2009-03-13 05:36:26 +0000
67@@ -0,0 +1,23 @@
68+from loggerhead import util
69+from loggerhead.controllers import TemplatedBranchView
70+
71+
72+class RevLogUI(TemplatedBranchView):
73+
74+ template_path = 'loggerhead.templates.revlog'
75+
76+ def get_values(self, path, kwargs, headers):
77+ history = self._history
78+ revid = self.get_revid()
79+
80+ changes = list(history.get_changes([revid]))
81+ history.add_changes(changes)
82+ history.get_branch_nicks(changes)
83+
84+ return {
85+ 'branch': self._branch,
86+ 'entry': changes[0],
87+ 'util': util,
88+ 'revid': revid,
89+ 'url': self._branch.context_url,
90+ }
91
92=== added file 'loggerhead/static/images/spinner.gif'
93Binary files loggerhead/static/images/spinner.gif 1970-01-01 00:00:00 +0000 and loggerhead/static/images/spinner.gif 2009-03-16 03:05:49 +0000 differ
94=== modified file 'loggerhead/static/javascript/changelog.js'
95--- loggerhead/static/javascript/changelog.js 2009-02-20 03:30:31 +0000
96+++ loggerhead/static/javascript/changelog.js 2009-03-16 02:58:10 +0000
97@@ -53,15 +53,24 @@
98 revlogs.each(
99 function(item, i)
100 {
101- var item_slide = item.query('.revisioninfo');
102- var open_content = new Array();
103- var close_content = new Array();
104- open_content.push(item.query('.long_description'));
105- close_content.push(item.query('.short_description'));
106- var expand_icon = item.query('.expand_icon');
107- var collapsable = new Collapsable(item_slide, expand_icon, open_content, close_content, false);
108+ var revid = revids[item.get('id').replace('log-', '')];
109+ var collapsable = new Collapsable(
110+ {
111+ expand_icon: item.query('.expand_icon'),
112+ open_node: item.query('.long_description'),
113+ close_node: item.query('.short_description'),
114+ source: global_path + '+revlog/' + revid,
115+ source_target: item.query('.source_target'),
116+ loading: item.query('.loading'),
117+ is_open: false
118+ });
119
120- item.query('.expand_revisioninfo').on('click',function(){collapsable.toggle();});
121+ item.query('.expand_revisioninfo a').on(
122+ 'click',
123+ function(e) {
124+ e.preventDefault();
125+ collapsable.toggle();
126+ });
127 item.collapsable = collapsable;
128 });
129
130
131=== modified file 'loggerhead/static/javascript/custom.js'
132--- loggerhead/static/javascript/custom.js 2009-02-26 01:04:18 +0000
133+++ loggerhead/static/javascript/custom.js 2009-03-16 02:58:10 +0000
134@@ -75,30 +75,15 @@
135 setTimeout("Y.get('#search_terms').setStyle('display','none')", 300);
136 }
137
138-function Collapsable(item, expand_icon, open_content, close_content, is_open)
139+function Collapsable(config)
140 {
141- this.is_open = is_open;
142- this.item = item;
143- this.open_content = open_content;
144- this.close_content = close_content;
145- this.expand_icon = expand_icon;
146-
147- if (this.is_open) {
148- this.height = item.get('region').height;
149- }
150- else {
151- this.height = null;
152- }
153-
154- //var expander = new Fx.Slide(this.item, { duration: 200 } );
155- if (!this.is_open)
156- {
157- this.expand_icon.set('src',this.expand_icon.get('title'));
158- }
159- else
160- {
161- this.expand_icon.set('src',this.expand_icon.get('alt'));
162- }
163+ this.is_open = config.is_open;
164+ this.source_target = config.source_target;
165+ this.open_node = config.open_node;
166+ this.close_node = config.close_node;
167+ this.expand_icon = config.expand_icon;
168+ this.source = config.source;
169+ this.loading = config.loading;
170 }
171
172 function get_height(node) {
173@@ -112,56 +97,90 @@
174 return height;
175 }
176
177+Collapsable.prototype._load_finished = function(tid, res)
178+{
179+ var newNode = Y.Node.create(res.responseText.split('\n').splice(1).join(''));
180+ this.source_target.ancestor().replaceChild(newNode, this.source_target);
181+ this.source_target = null;
182+ this.source = null;
183+ this.loading.setStyle('display', 'none');
184+ this.open();
185+};
186+
187 Collapsable.prototype.open = function()
188 {
189- if (this.height == null) {
190- this.height = get_height(this.item);
191- }
192+ if (this.source) {
193+ this.loading.setStyle('display', 'block');
194+ Y.io(
195+ this.source,
196+ {
197+ on: {complete: this._load_finished},
198+ context: this
199+ });
200+ return;
201+ }
202+
203+ var open_height = get_height(this.open_node);
204+
205+ var close_height;
206+ if (this.close_node) {
207+ close_height = this.close_node.get('region').height;
208+ }
209+ else {
210+ close_height = 0;
211+ }
212+
213+ var container = this.open_node.ancestor('.container');
214
215 var anim = new Y.Anim(
216 {
217- node: this.item,
218+ node: container,
219 from: {
220- height: 0
221+ marginBottom: close_height - open_height
222 },
223 to: {
224- height: this.height
225+ marginBottom: 0
226 },
227 duration: 0.2
228 });
229+
230 anim.on('end', this.openComplete, this);
231- this.item.setStyle('height', 0);
232- this.item.setStyle('display', 'block');
233+ container.setStyle('marginBottom', close_height - open_height);
234+ if (this.close_node) {
235+ this.close_node.setStyle('display', 'none');
236+ }
237+ this.open_node.setStyle('display', 'block');
238+ this.expand_icon.set('src', this.expand_icon.get('alt'));
239 anim.run();
240 };
241
242 Collapsable.prototype.openComplete = function()
243 {
244- for (var i=0;i<this.open_content.length;++i)
245- {
246- this.open_content[i].setStyle('display','block');
247- }
248-
249- for (var i=0;i<this.close_content.length;++i)
250- {
251- this.close_content[i].setStyle('display','none');
252- }
253-
254- this.expand_icon.set('src',this.expand_icon.get('alt'));
255 this.is_open = true;
256 };
257
258 Collapsable.prototype.close = function()
259 {
260- var item = this.item;
261+ var container = this.open_node.ancestor('.container');
262+
263+ var open_height = this.open_node.get('region').height;
264+
265+ var close_height;
266+ if (this.close_node) {
267+ close_height = get_height(this.close_node);
268+ }
269+ else {
270+ close_height = 0;
271+ }
272+
273 var anim = new Y.Anim(
274 {
275- node: this.item,
276+ node: container,
277 from: {
278- height: this.height
279+ marginBottom: 0
280 },
281 to: {
282- height: 0
283+ marginBottom: close_height - open_height
284 },
285 duration: 0.2
286 });
287@@ -170,29 +189,18 @@
288 };
289
290 Collapsable.prototype.closeComplete = function () {
291- this.item.setStyle('display', 'none');
292- var i;
293- for (i=0;i<this.open_content.length;++i)
294- {
295- this.open_content[i].setStyle('display','none');
296- }
297-
298- for (i=0;i<this.close_content.length;++i)
299- {
300- this.close_content[i].setStyle('display','block');
301- }
302- this.expand_icon.set('src',this.expand_icon.get('title'));
303+ this.open_node.setStyle('display', 'none');
304+ if (this.close_node) {
305+ this.close_node.setStyle('display', 'block');
306+ }
307+ this.open_node.ancestor('.container').setStyle('marginBottom', 0);
308+ this.expand_icon.set('src', this.expand_icon.get('title'));
309 this.is_open = false;
310 };
311
312-Collapsable.prototype.isOpen = function()
313-{
314- return this.is_open;
315-};
316-
317 Collapsable.prototype.toggle = function()
318 {
319- if (this.isOpen())
320+ if (this.is_open)
321 {
322 this.close();
323 }
324
325=== modified file 'loggerhead/static/javascript/diff.js'
326--- loggerhead/static/javascript/diff.js 2009-02-26 02:06:31 +0000
327+++ loggerhead/static/javascript/diff.js 2009-03-16 02:15:47 +0000
328@@ -151,10 +151,17 @@
329 diffs.each(
330 function(item, i)
331 {
332- var item_slide = item.next('.diffinfo');
333- var expand_icon = item.query( '.expand_diff' );
334- var collapsable = new Collapsable(item_slide, expand_icon, [], [], true);
335- item.query('.expand_diff').on('click', function(){collapsable.toggle();});
336- item.collapsable=collapsable;
337- });
338+ item.query('.expand_diff').on('click', function() { collapsable.toggle(); });
339+ Y.log(item.ancestor().query('.diffinfo'));
340+ var collapsable = new Collapsable(
341+ {
342+ expand_icon: item.query('.expand_diff'),
343+ open_node: item.ancestor().query('.diffinfo'),
344+ close_node: null,
345+ source: null,
346+ source_target: null,
347+ is_open: true
348+ });
349+ item.collapsable=collapsable;
350+ });
351 });
352
353=== modified file 'loggerhead/templates/changelog.pt'
354--- loggerhead/templates/changelog.pt 2009-03-04 22:30:32 +0000
355+++ loggerhead/templates/changelog.pt 2009-03-16 03:05:49 +0000
356@@ -7,6 +7,9 @@
357 <link rel="alternate" type="application/atom+xml"
358 tal:attributes="href python:url(['/atom']);
359 title string:RSS feed for ${branch/friendly_name}" />
360+ <script type="text/javascript">
361+ var revids = <tal:block content="data" />;
362+ </script>
363 <script type="text/javascript"
364 tal:attributes="src python:branch.static_url('/static/javascript/changelog.js')"></script>
365 </metal:block>
366@@ -67,7 +70,7 @@
367 <table id="logentries">
368 <tr class="logheader">
369 <td class="revisionnumber">Rev</td>
370- <td class="expandcell">&nbsp;</td>
371+ <td class="expandcell show_if_js">&nbsp;</td>
372 <td class="summarycell">Summary</td>
373 <td class="authorcell">Author</td>
374 <td class="datecell">Date</td>
375@@ -76,55 +79,45 @@
376 </tr>
377 <tal:block tal:repeat="entry changes">
378 <a tal:attributes="name string:entry-${entry/revno}"/>
379- <tr tal:attributes="class string:blueRow${entry/parity} revision_log">
380+ <tr tal:attributes="class string:blueRow${entry/parity} revision_log; id string:log-${entry/index}">
381 <td class="revnro revnolink"><a tal:attributes="title python:'Show revision '+entry.revno;
382 href python:url(['/revision', entry.revno], clear=1)"
383 tal:content="python:util.trunc(entry.revno)"></a>
384 </td>
385- <td class="expcell">
386+ <td class="expcell show_if_js">
387 <div class="expand_revisioninfo">
388 <!-- So, this is interesting. I'm using "alt" to have the correct URL for the image of the expanded icon
389 and "title" tag for the contracted URL of the image. This is a bit of a hack, but it's better than
390 other approaches I tried :) -->
391- <img tal:attributes="src python:branch.static_url('/static/images/treeCollapsed.png');
392- alt python:branch.static_url('/static/images/treeExpanded.png');
393- title python:branch.static_url('/static/images/treeCollapsed.png')"
394- class="expand_icon" />
395+ <a href="#">
396+ <img tal:attributes="src python:branch.static_url('/static/images/treeCollapsed.png');
397+ alt python:branch.static_url('/static/images/treeExpanded.png');
398+ title python:branch.static_url('/static/images/treeCollapsed.png')"
399+ class="expand_icon" />
400+ </a>
401 </div>
402 </td>
403- <td class="summcell"><div tal:attributes="class string:short_description">
404- <a tal:attributes="title python:'Show revision '+entry.revno;
405- href python:url(['/revision', entry.revno], clear=1);
406- class string:link"
407- tal:content="entry/short_comment"></a>
408- </div>
409- <div tal:attributes="class string:long_description;
410- style string:display:none">
411- <a tal:attributes="title python:'Show revision '+entry.revno;
412- href python:url(['/revision', entry.revno], clear=1);
413- class string:link"
414- tal:content="structure python:util.fixed_width(entry.comment)"></a>
415- </div>
416- <div class="revisioninfo" style="display:none;">
417- <ul class="expandrev">
418- <li class="mfrom" tal:repeat="parent python:entry.parents[1:]">
419- <span class="revnolink">
420- <a tal:attributes="href python:url(['/changes', parent.revno])"
421- tal:content="parent/revno"></a>
422- </span>
423- <a tal:condition="parent.branch_nick"
424- tal:attributes="href python:url(['/changes'], start_revid=parent.revno)"
425- tal:content="python:'(' + parent.branch_nick + ')'"
426- title="Show history" class="link"></a>
427- </li>
428- <li class="mto" tal:repeat="merge_point entry/merge_points">
429- <a tal:attributes="href python:url(['/changes'], start_revid=merge_point.revno)"
430- tal:content="python:revno_with_nick(merge_point)"
431- title="Show history" class="link"></a>
432- </li>
433- <li class="committerli" tal:content="python:util.hide_email(entry.author)"></li>
434- <tal:block content="structure python:file_change_summary(url, entry)" />
435- </ul>
436+ <td class="summcell">
437+ <div style="overflow: hidden">
438+ <div class="container">
439+ <div class="short_description">
440+ <a tal:attributes="title python:'Show revision '+entry.revno;
441+ href python:url(['/revision', entry.revno], clear=1);
442+ class string:link"
443+ tal:content="entry/short_comment"></a>
444+ <div class="loading" style="display:none;">
445+ <img tal:attributes="src python:branch.static_url('/static/images/spinner.gif')" />
446+ </div>
447+ </div>
448+ <div class="long_description" style="display: none">
449+ <a tal:attributes="title python:'Show revision '+entry.revno;
450+ href python:url(['/revision', entry.revno], clear=1);
451+ class string:link"
452+ tal:content="structure python:util.fixed_width(entry.comment)"></a>
453+ <div class="source_target">
454+ </div>
455+ </div>
456+ </div>
457 </div>
458 </td>
459 <td tal:content="python:util.trunc(util.hide_email(entry.author), 20)"
460
461=== modified file 'loggerhead/templates/revision.pt'
462--- loggerhead/templates/revision.pt 2009-03-05 22:56:59 +0000
463+++ loggerhead/templates/revision.pt 2009-03-16 02:15:47 +0000
464@@ -123,28 +123,32 @@
465 tal:content="item/filename">
466 </a>
467 </div>
468- <div class="diffinfo">
469- <div class="pseudotable unified"
470- tal:repeat="chunk item/chunks">
471-
472- <tal:block condition="not:repeat/chunk/start">
473- <div class="pseudorow context">
474- <div class="lineNumber separate"></div>
475- <div class="lineNumber second separate"></div>
476- <div class="code separate"></div>
477- <div class="clear"><!-- --></div>
478+ <div style="overflow: hidden">
479+ <div class="container">
480+ <div class="diffinfo">
481+ <div class="pseudotable unified"
482+ tal:repeat="chunk item/chunks">
483+
484+ <tal:block condition="not:repeat/chunk/start">
485+ <div class="pseudorow context">
486+ <div class="lineNumber separate"></div>
487+ <div class="lineNumber second separate"></div>
488+ <div class="code separate"></div>
489+ <div class="clear"><!-- --></div>
490+ </div>
491+ </tal:block>
492+
493+ <div tal:repeat="line chunk/diff"
494+ tal:attributes="class string:pseudorow ${line/type}-row">
495+ <div class="lineNumber first"
496+ tal:content="structure python:util.fill_div(line.old_lineno)"></div>
497+ <div class="lineNumber second"
498+ tal:content="structure python:util.fill_div(line.new_lineno)"></div>
499+ <div tal:attributes="class string:code ${line/type}"
500+ tal:content="structure python:util.fill_div(util.html_clean(line.line))"></div>
501+ <div class="clear"><!-- --></div>
502+ </div>
503 </div>
504- </tal:block>
505-
506- <div tal:repeat="line chunk/diff"
507- tal:attributes="class string:pseudorow ${line/type}-row">
508- <div class="lineNumber first"
509- tal:content="structure python:util.fill_div(line.old_lineno)"></div>
510- <div class="lineNumber second"
511- tal:content="structure python:util.fill_div(line.new_lineno)"></div>
512- <div tal:attributes="class string:code ${line/type}"
513- tal:content="structure python:util.fill_div(util.html_clean(line.line))"></div>
514- <div class="clear"><!-- --></div>
515 </div>
516 </div>
517 </div>
518
519=== added file 'loggerhead/templates/revlog.pt'
520--- loggerhead/templates/revlog.pt 1970-01-01 00:00:00 +0000
521+++ loggerhead/templates/revlog.pt 2009-03-13 05:36:26 +0000
522@@ -0,0 +1,21 @@
523+<div class="revisioninfo">
524+ <ul class="expandrev">
525+ <li class="mfrom" tal:repeat="parent python:entry.parents[1:]">
526+ <span class="revnolink">
527+ <a tal:attributes="href python:url(['/changes', parent.revno])"
528+ tal:content="parent/revno"></a>
529+ </span>
530+ <a tal:condition="parent.branch_nick"
531+ tal:attributes="href python:url(['/changes'], start_revid=parent.revno)"
532+ tal:content="python:'(' + parent.branch_nick + ')'"
533+ title="Show history" class="link"></a>
534+ </li>
535+ <li class="mto" tal:repeat="merge_point entry/merge_points">
536+ <a tal:attributes="href python:url(['/changes'], start_revid=merge_point.revno)"
537+ tal:content="python:revno_with_nick(merge_point)"
538+ title="Show history" class="link"></a>
539+ </li>
540+ <li class="committerli" tal:content="python:util.hide_email(entry.author)"></li>
541+ <tal:block content="structure python:file_change_summary(url, entry)" />
542+ </ul>
543+</div>

Subscribers

People subscribed via source and target branches