Merge lp:~mwhudson/loggerhead/ajaxy-revision-page into lp:loggerhead

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

Hi Reviewer,

The main change this branch makes is to make the default revision page not show any diffs by default and having them loaded by the wonders of xhr.

I've put some effort in to making sure non-js users have a decent experience -- instead of xhr-ing a diff, when scripting is disabled the user is taken to a page that just contains the the diff for the file.

The code, particularly in revision_ui.py, is now much less than clear. I'll fix that in the next branch tomorrow -- basically if you think the new behaviour is good, I can then clean up the innards without changing behaviour tomorrow (perhaps it would have been better to clean up the innards then clean up the behaviour, but oh well).

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

This is very sexy!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'loggerhead/apps/branch.py'
--- loggerhead/apps/branch.py 2009-03-13 05:36:26 +0000
+++ loggerhead/apps/branch.py 2009-03-17 00:02:21 +0000
@@ -11,15 +11,16 @@
11from paste import httpexceptions11from paste import httpexceptions
1212
13from loggerhead.apps import static_app13from loggerhead.apps import static_app
14from loggerhead.controllers.annotate_ui import AnnotateUI
15from loggerhead.controllers.atom_ui import AtomUI
14from loggerhead.controllers.changelog_ui import ChangeLogUI16from loggerhead.controllers.changelog_ui import ChangeLogUI
17from loggerhead.controllers.diff_ui import DiffUI
18from loggerhead.controllers.download_ui import DownloadUI
19from loggerhead.controllers.filediff_ui import FileDiffUI
15from loggerhead.controllers.inventory_ui import InventoryUI20from loggerhead.controllers.inventory_ui import InventoryUI
16from loggerhead.controllers.annotate_ui import AnnotateUI
17from loggerhead.controllers.revision_ui import RevisionUI21from loggerhead.controllers.revision_ui import RevisionUI
18from loggerhead.controllers.revlog_ui import RevLogUI22from loggerhead.controllers.revlog_ui import RevLogUI
19from loggerhead.controllers.atom_ui import AtomUI
20from loggerhead.controllers.download_ui import DownloadUI
21from loggerhead.controllers.search_ui import SearchUI23from loggerhead.controllers.search_ui import SearchUI
22from loggerhead.controllers.diff_ui import DiffUI
23from loggerhead.history import History24from loggerhead.history import History
24from loggerhead import util25from loggerhead import util
2526
@@ -79,15 +80,16 @@
79 return self._static_url_base + path80 return self._static_url_base + path
8081
81 controllers_dict = {82 controllers_dict = {
83 '+filediff': FileDiffUI,
84 '+revlog': RevLogUI,
82 'annotate': AnnotateUI,85 'annotate': AnnotateUI,
86 'atom': AtomUI,
83 'changes': ChangeLogUI,87 'changes': ChangeLogUI,
88 'diff': DiffUI,
89 'download': DownloadUI,
84 'files': InventoryUI,90 'files': InventoryUI,
85 'revision': RevisionUI,91 'revision': RevisionUI,
86 '+revlog': RevLogUI,
87 'download': DownloadUI,
88 'atom': AtomUI,
89 'search': SearchUI,92 'search': SearchUI,
90 'diff': DiffUI,
91 }93 }
9294
93 def last_updated(self):95 def last_updated(self):
9496
=== added file 'loggerhead/controllers/filediff_ui.py'
--- loggerhead/controllers/filediff_ui.py 1970-01-01 00:00:00 +0000
+++ loggerhead/controllers/filediff_ui.py 2009-03-17 06:43:34 +0000
@@ -0,0 +1,97 @@
1from StringIO import StringIO
2import urllib
3
4from bzrlib import diff
5from bzrlib import errors
6
7from loggerhead import util
8from loggerhead.controllers import TemplatedBranchView
9
10def _process_diff(difftext):
11 chunks = []
12 chunk = None
13 for line in difftext.splitlines():
14 if len(line) == 0:
15 continue
16 if line.startswith('+++ ') or line.startswith('--- '):
17 continue
18 if line.startswith('@@ '):
19 # new chunk
20 if chunk is not None:
21 chunks.append(chunk)
22 chunk = util.Container()
23 chunk.diff = []
24 split_lines = line.split(' ')[1:3]
25 lines = [int(x.split(',')[0][1:]) for x in split_lines]
26 old_lineno = lines[0]
27 new_lineno = lines[1]
28 elif line.startswith(' '):
29 chunk.diff.append(util.Container(old_lineno=old_lineno,
30 new_lineno=new_lineno,
31 type='context',
32 line=line[1:]))
33 old_lineno += 1
34 new_lineno += 1
35 elif line.startswith('+'):
36 chunk.diff.append(util.Container(old_lineno=None,
37 new_lineno=new_lineno,
38 type='insert', line=line[1:]))
39 new_lineno += 1
40 elif line.startswith('-'):
41 chunk.diff.append(util.Container(old_lineno=old_lineno,
42 new_lineno=None,
43 type='delete', line=line[1:]))
44 old_lineno += 1
45 else:
46 chunk.diff.append(util.Container(old_lineno=None,
47 new_lineno=None,
48 type='unknown',
49 line=repr(line)))
50 if chunk is not None:
51 chunks.append(chunk)
52 return chunks
53
54
55def diff_chunks_for_file(file_id, old_tree, new_tree):
56 try:
57 old_lines = old_tree.get_file_lines(file_id)
58 except errors.NoSuchId:
59 old_lines = []
60 try:
61 new_lines = new_tree.get_file_lines(file_id)
62 except errors.NoSuchId:
63 new_lines = []
64 buffer = StringIO()
65 if old_lines != new_lines:
66 try:
67 diff.internal_diff('', old_lines, '', new_lines, buffer)
68 except errors.BinaryFile:
69 difftext = ''
70 else:
71 difftext = buffer.getvalue()
72 else:
73 difftext = ''
74
75 return _process_diff(difftext)
76
77
78class FileDiffUI(TemplatedBranchView):
79
80 template_path = 'loggerhead.templates.filediff'
81
82 def get_values(self, path, kwargs, headers):
83 history = self._history
84
85 revid = urllib.unquote(self.args[0])
86 compare_revid = urllib.unquote(self.args[1])
87 file_id = urllib.unquote(self.args[2])
88
89 repository = self._history._branch.repository
90 old_tree, new_tree = repository.revision_trees([compare_revid, revid])
91
92 chunks = diff_chunks_for_file(file_id, old_tree, new_tree)
93
94 return {
95 'util': util,
96 'chunks': chunks,
97 }
098
=== modified file 'loggerhead/controllers/revision_ui.py'
--- loggerhead/controllers/revision_ui.py 2009-03-17 02:19:20 +0000
+++ loggerhead/controllers/revision_ui.py 2009-03-17 06:43:34 +0000
@@ -17,70 +17,26 @@
17# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA17# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18#18#
1919
20from StringIO import StringIO20import simplejson
2121import urllib
22import bzrlib.diff
23from bzrlib import errors
2422
25from paste.httpexceptions import HTTPServerError23from paste.httpexceptions import HTTPServerError
2624
27from loggerhead import util25from loggerhead import util
28from loggerhead.controllers import TemplatedBranchView26from loggerhead.controllers import TemplatedBranchView
27from loggerhead.controllers.filediff_ui import diff_chunks_for_file
29from loggerhead.history import rich_filename28from loggerhead.history import rich_filename
3029
3130
32DEFAULT_LINE_COUNT_LIMIT = 300031DEFAULT_LINE_COUNT_LIMIT = 3000
3332
33def dq(p):
34 return urllib.quote(urllib.quote(p, safe=''))
3435
35class RevisionUI(TemplatedBranchView):36class RevisionUI(TemplatedBranchView):
3637
37 template_path = 'loggerhead.templates.revision'38 template_path = 'loggerhead.templates.revision'
3839
39 def _process_diff(self, diff):
40 # doesn't really need to be a method; could be static.
41 chunks = []
42 chunk = None
43 for line in diff.splitlines():
44 if len(line) == 0:
45 continue
46 if line.startswith('+++ ') or line.startswith('--- '):
47 continue
48 if line.startswith('@@ '):
49 # new chunk
50 if chunk is not None:
51 chunks.append(chunk)
52 chunk = util.Container()
53 chunk.diff = []
54 split_lines = line.split(' ')[1:3]
55 lines = [int(x.split(',')[0][1:]) for x in split_lines]
56 old_lineno = lines[0]
57 new_lineno = lines[1]
58 elif line.startswith(' '):
59 chunk.diff.append(util.Container(old_lineno=old_lineno,
60 new_lineno=new_lineno,
61 type='context',
62 line=line[1:]))
63 old_lineno += 1
64 new_lineno += 1
65 elif line.startswith('+'):
66 chunk.diff.append(util.Container(old_lineno=None,
67 new_lineno=new_lineno,
68 type='insert', line=line[1:]))
69 new_lineno += 1
70 elif line.startswith('-'):
71 chunk.diff.append(util.Container(old_lineno=old_lineno,
72 new_lineno=None,
73 type='delete', line=line[1:]))
74 old_lineno += 1
75 else:
76 chunk.diff.append(util.Container(old_lineno=None,
77 new_lineno=None,
78 type='unknown',
79 line=repr(line)))
80 if chunk is not None:
81 chunks.append(chunk)
82 return chunks
83
84 def _parse_diffs(self, old_tree, new_tree, delta, specific_path):40 def _parse_diffs(self, old_tree, new_tree, delta, specific_path):
85 """41 """
86 Return a list of processed diffs, in the format::42 Return a list of processed diffs, in the format::
@@ -98,57 +54,36 @@
98 ),54 ),
99 )55 )
100 """56 """
57 if specific_path:
58 fid = new_tree.path2id(specific_path)
59 kind = new_tree.kind(fid)
60 chunks=diff_chunks_for_file(fid, old_tree, new_tree)
61 return [util.Container(
62 filename=rich_filename(specific_path, kind), file_id=fid,
63 chunks=chunks)]
64
101 process = []65 process = []
102 out = []66 out = []
10367
104 def include_specific_path(path):
105 return specific_path == path
106 def include_all_paths(path):
107 return True
108 if specific_path:
109 include_path = include_specific_path
110 else:
111 include_path = include_all_paths
112
113 for old_path, new_path, fid, \68 for old_path, new_path, fid, \
114 kind, text_modified, meta_modified in delta.renamed:69 kind, text_modified, meta_modified in delta.renamed:
115 if text_modified and include_path(new_path):70 if text_modified:
116 process.append((old_path, new_path, fid, kind))71 process.append((new_path, fid, kind))
117 for path, fid, kind, text_modified, meta_modified in delta.modified:72 for path, fid, kind, text_modified, meta_modified in delta.modified:
118 if include_path(path):73 process.append((path, fid, kind))
119 process.append((path, path, fid, kind))
120 for path, fid, kind in delta.added:74 for path, fid, kind in delta.added:
121 if kind == 'file' and include_path(path):75 if kind == 'file':
122 process.append((path, path, fid, kind))76 process.append((path, fid, kind))
123 for path, fid, kind in delta.removed:77 for path, fid, kind in delta.removed:
124 if kind == 'file' and include_path(path):78 if kind == 'file':
125 process.append((path, path, fid, kind))79 process.append((path, fid, kind))
12680
127 process.sort(key=lambda x:x[1])81 process.sort()
12882
129 for old_path, new_path, fid, kind in process:83 for new_path, fid, kind in process:
130 try:
131 old_lines = old_tree.get_file_lines(fid)
132 except errors.NoSuchId:
133 old_lines = []
134 try:
135 new_lines = new_tree.get_file_lines(fid)
136 except errors.NoSuchId:
137 new_lines = []
138 buffer = StringIO()
139 if old_lines != new_lines:
140 try:
141 bzrlib.diff.internal_diff(old_path, old_lines,
142 new_path, new_lines, buffer)
143 except bzrlib.errors.BinaryFile:
144 diff = ''
145 else:
146 diff = buffer.getvalue()
147 else:
148 diff = ''
149 out.append(util.Container(84 out.append(util.Container(
150 filename=rich_filename(new_path, kind), file_id=fid,85 filename=rich_filename(new_path, kind), file_id=fid,
151 chunks=self._process_diff(diff)))86 chunks=[]))
15287
153 return out88 return out
15489
@@ -200,6 +135,20 @@
200 if path in ('', '/'):135 if path in ('', '/'):
201 path = None136 path = None
202 change.changes, diffs = self.get_changes_with_diff(change, compare_revid, path)137 change.changes, diffs = self.get_changes_with_diff(change, compare_revid, path)
138 link_data = {}
139 path_to_id = {}
140 if compare_revid is None:
141 if change.parents:
142 cr = change.parents[0].revid
143 else:
144 cr = 'null:'
145 else:
146 cr = compare_revid
147 for i, item in enumerate(diffs):
148 item.index = i
149 link_data['diff-' + str(i)] = '%s/%s/%s' % (
150 dq(revid), dq(cr), dq(item.file_id))
151 path_to_id[item.filename] = 'diff-' + str(i)
203 # add parent & merge-point branch-nick info, in case it's useful152 # add parent & merge-point branch-nick info, in case it's useful
204 h.get_branch_nicks([change])153 h.get_branch_nicks([change])
205154
@@ -215,7 +164,10 @@
215 'revid': revid,164 'revid': revid,
216 'change': change,165 'change': change,
217 'diffs': diffs,166 'diffs': diffs,
167 'link_data': simplejson.dumps(link_data),
218 'specific_path': path,168 'specific_path': path,
169 'json_specific_path': simplejson.dumps(path),
170 'path_to_id': simplejson.dumps(path_to_id),
219 'start_revid': start_revid,171 'start_revid': start_revid,
220 'filter_file_id': filter_file_id,172 'filter_file_id': filter_file_id,
221 'util': util,173 'util': util,
222174
=== modified file 'loggerhead/static/javascript/custom.js'
--- loggerhead/static/javascript/custom.js 2009-03-16 03:22:02 +0000
+++ loggerhead/static/javascript/custom.js 2009-03-17 04:26:28 +0000
@@ -86,6 +86,7 @@
86 this.expand_icon = config.expand_icon;86 this.expand_icon = config.expand_icon;
87 this.source = config.source;87 this.source = config.source;
88 this.loading = config.loading;88 this.loading = config.loading;
89 this.node_process = config.node_process;
89}90}
9091
91function get_height(node) {92function get_height(node) {
@@ -99,17 +100,19 @@
99 return height;100 return height;
100}101}
101102
102Collapsable.prototype._load_finished = function(tid, res)103Collapsable.prototype._load_finished = function(tid, res, args)
103{104{
104 var newNode = Y.Node.create(res.responseText.split('\n').splice(1).join(''));105 var newNode = Y.Node.create(res.responseText.split('\n').splice(1).join(''));
106 if (this.node_process)
107 this.node_process(newNode);
105 this.source_target.ancestor().replaceChild(newNode, this.source_target);108 this.source_target.ancestor().replaceChild(newNode, this.source_target);
106 this.source_target = null;109 this.source_target = null;
107 this.source = null;110 this.source = null;
108 this.loading.setStyle('display', 'none');111 this.loading.setStyle('display', 'none');
109 this.open();112 this.open(args[0]);
110};113};
111114
112Collapsable.prototype.open = function()115Collapsable.prototype.open = function(callback)
113{116{
114 if (this.source) {117 if (this.source) {
115 this.loading.setStyle('display', 'block');118 this.loading.setStyle('display', 'block');
@@ -117,6 +120,7 @@
117 this.source,120 this.source,
118 {121 {
119 on: {complete: this._load_finished},122 on: {complete: this._load_finished},
123 arguments: [callback],
120 context: this124 context: this
121 });125 });
122 return;126 return;
@@ -146,7 +150,7 @@
146 duration: 0.2150 duration: 0.2
147 });151 });
148152
149 anim.on('end', this.openComplete, this);153 anim.on('end', this.openComplete, this, callback);
150 container.setStyle('marginBottom', close_height - open_height);154 container.setStyle('marginBottom', close_height - open_height);
151 if (this.close_node) {155 if (this.close_node) {
152 this.close_node.setStyle('display', 'none');156 this.close_node.setStyle('display', 'none');
@@ -156,8 +160,9 @@
156 anim.run();160 anim.run();
157};161};
158162
159Collapsable.prototype.openComplete = function()163Collapsable.prototype.openComplete = function(evt, callback)
160{164{
165 if (callback) callback();
161 this.is_open = true;166 this.is_open = true;
162};167};
163168
164169
=== modified file 'loggerhead/static/javascript/diff.js'
--- loggerhead/static/javascript/diff.js 2009-03-16 21:53:23 +0000
+++ loggerhead/static/javascript/diff.js 2009-03-17 06:51:29 +0000
@@ -87,13 +87,14 @@
8787
88function toggle_unified_sbs(event) {88function toggle_unified_sbs(event) {
89 event.preventDefault();89 event.preventDefault();
90 var pts = Y.all(".pseudotable");
90 if (unified) {91 if (unified) {
91 Y.all(".pseudotable").each(make_sbs);92 pts && pts.each(make_sbs);
92 unified = false;93 unified = false;
93 Y.get("#toggle_unified_sbs").set('innerHTML', "Show unified diffs");94 Y.get("#toggle_unified_sbs").set('innerHTML', "Show unified diffs");
94 }95 }
95 else {96 else {
96 Y.all(".pseudotable").each(make_unified);97 pts && pts.each(make_unified);
97 unified = true;98 unified = true;
98 Y.get("#toggle_unified_sbs").set('innerHTML', "Show diffs side-by-side");99 Y.get("#toggle_unified_sbs").set('innerHTML', "Show diffs side-by-side");
99 }100 }
@@ -103,7 +104,7 @@
103104
104function toggle_expand_all_revisionview(action)105function toggle_expand_all_revisionview(action)
105{106{
106 var diffs = Y.all('.diffBox');107 var diffs = Y.all('.diff');
107 if (diffs == null) return;108 if (diffs == null) return;
108 diffs.each(109 diffs.each(
109 function(item, i)110 function(item, i)
@@ -142,24 +143,61 @@
142 '#collapse_all a'143 '#collapse_all a'
143);144);
144145
146function node_process(node) {
147 if (!unified) {
148 node.get('children').filter('.pseudotable').each(make_sbs);
149 }
150}
151
152function zoom_to_diff (path) {
153 var collapsable = Y.get('#' + path_to_id[path]).collapsable;
154 if (!collapsable.is_open) {
155 collapsable.open(
156 function () {
157 window.location.hash = '#' + path;
158 });
159 }
160}
161
145Y.on(162Y.on(
146 "domready", function () {163 "domready", function () {
147 Y.all(".show_if_js").removeClass("show_if_js");164 Y.all(".show_if_js").removeClass("show_if_js");
148 var diffs = Y.all('.diffBox');165 Y.all("#list-files a").on(
166 'click',
167 function (e) {
168 e.preventDefault();
169 var path = decodeURIComponent(e.target.get('href').split('#')[1]);
170 window.location.hash = '#' + path;
171 zoom_to_diff(path);
172 });
173 var diffs = Y.all('.diff');
149 if (diffs == null) return;174 if (diffs == null) return;
150 diffs.each(175 diffs.each(
151 function(item, i)176 function(item, i)
152 {177 {
153 item.query('.expand_diff').on('click', function() { collapsable.toggle(); });178 var source_url = null;
179 if (!specific_path)
180 source_url = global_path + '+filediff/' + link_data[item.get('id')];
181 item.query('.the-link').on(
182 'click',
183 function(e) {
184 e.preventDefault();
185 collapsable.toggle();
186 });
154 var collapsable = new Collapsable(187 var collapsable = new Collapsable(
155 {188 {
156 expand_icon: item.query('.expand_diff'),189 expand_icon: item.query('.expand_diff'),
157 open_node: item.ancestor().query('.diffinfo'),190 open_node: item.query('.diffinfo'),
158 close_node: null,191 close_node: null,
159 source: null,192 source: source_url,
160 source_target: null,193 source_target: item.query('.source_target'),
161 is_open: true194 is_open: specific_path != null,
195 loading: item.query('.loading'),
196 node_process: node_process
162 });197 });
163 item.collapsable=collapsable;198 item.collapsable=collapsable;
164 });199 });
200 if (window.location.hash && !specific_path) {
201 zoom_to_diff(window.location.hash.substring(1));
202 }
165 });203 });
166204
=== modified file 'loggerhead/templatefunctions.py'
--- loggerhead/templatefunctions.py 2009-03-07 07:29:26 +0000
+++ loggerhead/templatefunctions.py 2009-03-17 06:32:25 +0000
@@ -38,20 +38,20 @@
3838
3939
40@templatefunc40@templatefunc
41def file_change_summary(url, entry, link_style='normal', currently_showing=None):41def file_change_summary(url, entry, style='normal', currently_showing=None):
42 if link_style == 'fragment':42 if style == 'fragment':
43 def file_link(filename):43 def file_link(filename):
44 if currently_showing:44 if currently_showing and filename == currently_showing:
45 if filename == currently_showing:45 return '<b><a href="#%s">%s</a></b>' % (
46 return '<b><a href="#%s">%s</a></b>' % (46 cgi.escape(filename), cgi.escape(filename))
47 cgi.escape(filename), cgi.escape(filename))
48 else:
49 return revision_link(url, entry.revno, filename)
50 else:47 else:
51 return '<a href="#%s">%s</a>' % (48 return revision_link(
52 cgi.escape(filename), cgi.escape(filename))49 url, entry.revno, filename, '#' + filename)
53 else:50 else:
54 file_link = lambda filename: revision_link(url, entry.revno, filename)51 def file_link(filename):
52 return '<a href="%s%s" title="View changes to %s in revision %s">%s</a>'%(
53 url(['/revision', entry.revno]), '#' + filename, cgi.escape(filename),
54 cgi.escape(entry.revno), cgi.escape(filename))
55 return _pt('revisionfilechanges').expand(55 return _pt('revisionfilechanges').expand(
56 url=url, entry=entry, file_link=file_link,56 url=url, entry=entry, file_link=file_link,
57 currently_showing=currently_showing, **templatefunctions)57 currently_showing=currently_showing, **templatefunctions)
@@ -120,7 +120,7 @@
120 url(['/annotate', revno, path]), cgi.escape(path), cgi.escape(path))120 url(['/annotate', revno, path]), cgi.escape(path), cgi.escape(path))
121121
122@templatefunc122@templatefunc
123def revision_link(url, revno, path):123def revision_link(url, revno, path, frag=''):
124 return '<a href="%s" title="View changes to %s in revision %s">%s</a>'%(124 return '<a href="%s%s" title="View changes to %s in revision %s">%s</a>'%(
125 url(['/revision', revno, path]), cgi.escape(path), cgi.escape(revno),125 url(['/revision', revno, path]), frag, cgi.escape(path),
126 cgi.escape(path))126 cgi.escape(revno), cgi.escape(path))
127127
=== added file 'loggerhead/templates/filediff.pt'
--- loggerhead/templates/filediff.pt 1970-01-01 00:00:00 +0000
+++ loggerhead/templates/filediff.pt 2009-03-17 00:02:21 +0000
@@ -0,0 +1,25 @@
1<div class="diffinfo">
2 <div class="pseudotable unified"
3 tal:repeat="chunk chunks">
4
5 <tal:block condition="not:repeat/chunk/start">
6 <div class="pseudorow context-row">
7 <div class="lineNumber separate"></div>
8 <div class="lineNumber second separate"></div>
9 <div class="code separate"></div>
10 <div class="clear"><!-- --></div>
11 </div>
12 </tal:block>
13
14 <div tal:repeat="line chunk/diff"
15 tal:attributes="class string:pseudorow ${line/type}-row">
16 <div class="lineNumber first"
17 tal:content="structure python:util.fill_div(line.old_lineno)"></div>
18 <div class="lineNumber second"
19 tal:content="structure python:util.fill_div(line.new_lineno)"></div>
20 <div tal:attributes="class string:code ${line/type}"
21 tal:content="structure python:util.fill_div(util.html_clean(line.line))"></div>
22 <div class="clear"><!-- --></div>
23 </div>
24 </div>
25</div>
026
=== modified file 'loggerhead/templates/revision.pt'
--- loggerhead/templates/revision.pt 2009-03-16 06:44:50 +0000
+++ loggerhead/templates/revision.pt 2009-03-17 03:49:33 +0000
@@ -11,6 +11,11 @@
11 tal:attributes="href python:branch.static_url('/static/css/diff.css')"/>11 tal:attributes="href python:branch.static_url('/static/css/diff.css')"/>
12 <script type="text/javascript"12 <script type="text/javascript"
13 tal:attributes="src python:branch.static_url('/static/javascript/diff.js')"></script>13 tal:attributes="src python:branch.static_url('/static/javascript/diff.js')"></script>
14 <script type="text/javascript">
15 var link_data = <tal:b content="link_data" />;
16 var specific_path = <tal:b content="json_specific_path" />;
17 var path_to_id = <tal:b content="path_to_id" />;
18 </script>
14 </metal:block>19 </metal:block>
15 </head>20 </head>
1621
@@ -92,14 +97,16 @@
92 </tal:we-are-comparing>97 </tal:we-are-comparing>
9398
94 <tal:revision-info replace="structure python:revisioninfo(url, branch, change, 'fragment', specific_path)" />99 <tal:revision-info replace="structure python:revisioninfo(url, branch, change, 'fragment', specific_path)" />
95 <p class="expand" id="expand_all" style="display:none;"><a href="#">100 <tal:specific-path condition="not:specific_path">
96 <img tal:attributes="src python:branch.static_url('/static/images/treeCollapsed.png')"101 <p class="expand show_if_js" id="expand_all"><a href="#">
97 alt="expand all" /> expand all</a>102 <img tal:attributes="src python:branch.static_url('/static/images/treeCollapsed.png')"
98 </p>103 alt="expand all" /> expand all</a>
99 <p class="expand show_if_js" id="collapse_all"><a href="#">104 </p>
100 <img tal:attributes="src python:branch.static_url('/static/images/treeExpanded.png')"105 <p class="expand" id="collapse_all" style="display:none;"><a href="#">
101 alt="collapse all" /> collapse all</a>106 <img tal:attributes="src python:branch.static_url('/static/images/treeExpanded.png')"
102 </p>107 alt="collapse all" /> collapse all</a>
108 </p>
109 </tal:specific-path>
103 <!-- Table -->110 <!-- Table -->
104 <p class="expand show_if_js"><a id="toggle_unified_sbs" href="#">Show diffs side-by-side</a></p>111 <p class="expand show_if_js"><a id="toggle_unified_sbs" href="#">Show diffs side-by-side</a></p>
105 <p class="codin"><img tal:attributes="src python:branch.static_url('/static/images/newCode.gif')" alt="added" /> added</p>112 <p class="codin"><img tal:attributes="src python:branch.static_url('/static/images/newCode.gif')" alt="added" /> added</p>
@@ -110,22 +117,34 @@
110117
111 <div metal:fill-slot="content">118 <div metal:fill-slot="content">
112 <div class="diff"119 <div class="diff"
113 tal:repeat="item diffs">120 tal:repeat="item diffs" tal:attributes="id string:diff-${item/index}">
114121
115 <div class="diffBox">122 <div class="diffBox">
116 <img tal:attributes="src python:branch.static_url('/static/images/treeExpanded.png');
117 title python:branch.static_url('/static/images/treeCollapsed.png');
118 alt python:branch.static_url('/static/images/treeExpanded.png')"
119 class="expand_diff" />
120 <a tal:attributes="href python:url(['/revision', change.revno, item.filename], clear=1);123 <a tal:attributes="href python:url(['/revision', change.revno, item.filename], clear=1);
121 id string:${item/filename};124 id string:${item/filename};
122 title string:View changes to ${item/filename} only"125 title string:View changes to ${item/filename} only"
123 tal:content="item/filename">126 class="the-link">
127 <img tal:attributes="src python:branch.static_url('/static/images/treeCollapsed.png');
128 title python:branch.static_url('/static/images/treeCollapsed.png');
129 alt python:branch.static_url('/static/images/treeExpanded.png')"
130 class="expand_diff" tal:condition="not:specific_path" />
131 <img tal:attributes="src python:branch.static_url('/static/images/treeExpanded.png');
132 title python:branch.static_url('/static/images/treeCollapsed.png');
133 alt python:branch.static_url('/static/images/treeExpanded.png')"
134 class="expand_diff" tal:condition="specific_path" />
135 <tal:b content="item/filename" />
124 </a>136 </a>
125 </div>137 </div>
126 <div style="overflow: hidden">138 <div style="overflow: hidden">
127 <div class="container">139 <div class="container">
128 <div class="diffinfo">140 <div class="loading" style="display:none">
141 <img tal:attributes="src python:branch.static_url('/static/images/spinner.gif')" />
142 </div>
143 <div class="diffinfo" tal:condition="not:specific_path">
144 <div class="source_target" >
145 </div>
146 </div>
147 <div class="diffinfo" tal:condition="specific_path">
129 <div class="pseudotable unified"148 <div class="pseudotable unified"
130 tal:repeat="chunk item/chunks">149 tal:repeat="chunk item/chunks">
131150

Subscribers

People subscribed via source and target branches