##// END OF EJS Templates
templates: use safe md5 for str template rendering
super-admin -
r4981:43b9c166 default
parent child Browse files
Show More
@@ -1,1263 +1,1263 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2
2
3 <%!
3 <%!
4 from rhodecode.lib import html_filters
4 from rhodecode.lib import html_filters
5 %>
5 %>
6
6
7 <%inherit file="root.mako"/>
7 <%inherit file="root.mako"/>
8
8
9 <%include file="/ejs_templates/templates.html"/>
9 <%include file="/ejs_templates/templates.html"/>
10
10
11 <div class="outerwrapper">
11 <div class="outerwrapper">
12 <!-- HEADER -->
12 <!-- HEADER -->
13 <div class="header">
13 <div class="header">
14 <div id="header-inner" class="wrapper">
14 <div id="header-inner" class="wrapper">
15 <div id="logo">
15 <div id="logo">
16 <div class="logo-wrapper">
16 <div class="logo-wrapper">
17 <a href="${h.route_path('home')}"><img src="${h.asset('images/rhodecode-logo-white-60x60.png')}" alt="RhodeCode"/></a>
17 <a href="${h.route_path('home')}"><img src="${h.asset('images/rhodecode-logo-white-60x60.png')}" alt="RhodeCode"/></a>
18 </div>
18 </div>
19 % if c.rhodecode_name:
19 % if c.rhodecode_name:
20 <div class="branding">
20 <div class="branding">
21 <a href="${h.route_path('home')}">${h.branding(c.rhodecode_name)}</a>
21 <a href="${h.route_path('home')}">${h.branding(c.rhodecode_name)}</a>
22 </div>
22 </div>
23 % endif
23 % endif
24 </div>
24 </div>
25 <!-- MENU BAR NAV -->
25 <!-- MENU BAR NAV -->
26 ${self.menu_bar_nav()}
26 ${self.menu_bar_nav()}
27 <!-- END MENU BAR NAV -->
27 <!-- END MENU BAR NAV -->
28 </div>
28 </div>
29 </div>
29 </div>
30 ${self.menu_bar_subnav()}
30 ${self.menu_bar_subnav()}
31 <!-- END HEADER -->
31 <!-- END HEADER -->
32
32
33 <!-- CONTENT -->
33 <!-- CONTENT -->
34 <div id="content" class="wrapper">
34 <div id="content" class="wrapper">
35
35
36 <rhodecode-toast id="notifications"></rhodecode-toast>
36 <rhodecode-toast id="notifications"></rhodecode-toast>
37
37
38 <div class="main">
38 <div class="main">
39 ${next.main()}
39 ${next.main()}
40 </div>
40 </div>
41
41
42 </div>
42 </div>
43 <!-- END CONTENT -->
43 <!-- END CONTENT -->
44
44
45 </div>
45 </div>
46
46
47 <!-- FOOTER -->
47 <!-- FOOTER -->
48 <div id="footer">
48 <div id="footer">
49 <div id="footer-inner" class="title wrapper">
49 <div id="footer-inner" class="title wrapper">
50 <div>
50 <div>
51 <% sid = 'block' if request.GET.get('showrcid') else 'none' %>
51 <% sid = 'block' if request.GET.get('showrcid') else 'none' %>
52
52
53 <p class="footer-link-right">
53 <p class="footer-link-right">
54 <a class="grey-link-action" href="${h.route_path('home', _query={'showrcid': 1})}">
54 <a class="grey-link-action" href="${h.route_path('home', _query={'showrcid': 1})}">
55 RhodeCode
55 RhodeCode
56 % if c.visual.show_version:
56 % if c.visual.show_version:
57 ${c.rhodecode_version}
57 ${c.rhodecode_version}
58 % endif
58 % endif
59 ${c.rhodecode_edition}
59 ${c.rhodecode_edition}
60 </a> |
60 </a> |
61
61
62 % if c.visual.rhodecode_support_url:
62 % if c.visual.rhodecode_support_url:
63 <a class="grey-link-action" href="${c.visual.rhodecode_support_url}" target="_blank">${_('Support')}</a> |
63 <a class="grey-link-action" href="${c.visual.rhodecode_support_url}" target="_blank">${_('Support')}</a> |
64 <a class="grey-link-action" href="https://docs.rhodecode.com" target="_blank">${_('Documentation')}</a>
64 <a class="grey-link-action" href="https://docs.rhodecode.com" target="_blank">${_('Documentation')}</a>
65 % endif
65 % endif
66
66
67 </p>
67 </p>
68
68
69 <p class="server-instance" style="display:${sid}">
69 <p class="server-instance" style="display:${sid}">
70 ## display hidden instance ID if specially defined
70 ## display hidden instance ID if specially defined
71 &copy; 2010-${h.datetime.today().year}, <a href="${h.route_url('rhodecode_official')}" target="_blank">RhodeCode GmbH</a>. All rights reserved.
71 &copy; 2010-${h.datetime.today().year}, <a href="${h.route_url('rhodecode_official')}" target="_blank">RhodeCode GmbH</a>. All rights reserved.
72 % if c.rhodecode_instanceid:
72 % if c.rhodecode_instanceid:
73 ${_('RhodeCode instance id: {}').format(c.rhodecode_instanceid)}
73 ${_('RhodeCode instance id: {}').format(c.rhodecode_instanceid)}
74 % endif
74 % endif
75 </p>
75 </p>
76 </div>
76 </div>
77 </div>
77 </div>
78 </div>
78 </div>
79
79
80 <!-- END FOOTER -->
80 <!-- END FOOTER -->
81
81
82 ### MAKO DEFS ###
82 ### MAKO DEFS ###
83
83
84 <%def name="menu_bar_subnav()">
84 <%def name="menu_bar_subnav()">
85 </%def>
85 </%def>
86
86
87 <%def name="breadcrumbs(class_='breadcrumbs')">
87 <%def name="breadcrumbs(class_='breadcrumbs')">
88 <div class="${class_}">
88 <div class="${class_}">
89 ${self.breadcrumbs_links()}
89 ${self.breadcrumbs_links()}
90 </div>
90 </div>
91 </%def>
91 </%def>
92
92
93 <%def name="admin_menu(active=None)">
93 <%def name="admin_menu(active=None)">
94
94
95 <div id="context-bar">
95 <div id="context-bar">
96 <div class="wrapper">
96 <div class="wrapper">
97 <div class="title">
97 <div class="title">
98 <div class="title-content">
98 <div class="title-content">
99 <div class="title-main">
99 <div class="title-main">
100 % if c.is_super_admin:
100 % if c.is_super_admin:
101 ${_('Super-admin Panel')}
101 ${_('Super-admin Panel')}
102 % else:
102 % else:
103 ${_('Delegated Admin Panel')}
103 ${_('Delegated Admin Panel')}
104 % endif
104 % endif
105 </div>
105 </div>
106 </div>
106 </div>
107 </div>
107 </div>
108
108
109 <ul id="context-pages" class="navigation horizontal-list">
109 <ul id="context-pages" class="navigation horizontal-list">
110
110
111 ## super-admin case
111 ## super-admin case
112 % if c.is_super_admin:
112 % if c.is_super_admin:
113 <li class="${h.is_active('audit_logs', active)}"><a href="${h.route_path('admin_audit_logs')}">${_('Admin audit logs')}</a></li>
113 <li class="${h.is_active('audit_logs', active)}"><a href="${h.route_path('admin_audit_logs')}">${_('Admin audit logs')}</a></li>
114 <li class="${h.is_active('repositories', active)}"><a href="${h.route_path('repos')}">${_('Repositories')}</a></li>
114 <li class="${h.is_active('repositories', active)}"><a href="${h.route_path('repos')}">${_('Repositories')}</a></li>
115 <li class="${h.is_active('repository_groups', active)}"><a href="${h.route_path('repo_groups')}">${_('Repository groups')}</a></li>
115 <li class="${h.is_active('repository_groups', active)}"><a href="${h.route_path('repo_groups')}">${_('Repository groups')}</a></li>
116 <li class="${h.is_active('users', active)}"><a href="${h.route_path('users')}">${_('Users')}</a></li>
116 <li class="${h.is_active('users', active)}"><a href="${h.route_path('users')}">${_('Users')}</a></li>
117 <li class="${h.is_active('user_groups', active)}"><a href="${h.route_path('user_groups')}">${_('User groups')}</a></li>
117 <li class="${h.is_active('user_groups', active)}"><a href="${h.route_path('user_groups')}">${_('User groups')}</a></li>
118 <li class="${h.is_active('artifacts', active)}"><a href="${h.route_path('admin_artifacts')}">${_('Artifacts')}</a></li>
118 <li class="${h.is_active('artifacts', active)}"><a href="${h.route_path('admin_artifacts')}">${_('Artifacts')}</a></li>
119 <li class="${h.is_active('permissions', active)}"><a href="${h.route_path('admin_permissions_application')}">${_('Permissions')}</a></li>
119 <li class="${h.is_active('permissions', active)}"><a href="${h.route_path('admin_permissions_application')}">${_('Permissions')}</a></li>
120 <li class="${h.is_active('authentication', active)}"><a href="${h.route_path('auth_home', traverse='')}">${_('Authentication')}</a></li>
120 <li class="${h.is_active('authentication', active)}"><a href="${h.route_path('auth_home', traverse='')}">${_('Authentication')}</a></li>
121 <li class="${h.is_active('integrations', active)}"><a href="${h.route_path('global_integrations_home')}">${_('Integrations')}</a></li>
121 <li class="${h.is_active('integrations', active)}"><a href="${h.route_path('global_integrations_home')}">${_('Integrations')}</a></li>
122 <li class="${h.is_active('defaults', active)}"><a href="${h.route_path('admin_defaults_repositories')}">${_('Defaults')}</a></li>
122 <li class="${h.is_active('defaults', active)}"><a href="${h.route_path('admin_defaults_repositories')}">${_('Defaults')}</a></li>
123 <li class="${h.is_active('settings', active)}"><a href="${h.route_path('admin_settings')}">${_('Settings')}</a></li>
123 <li class="${h.is_active('settings', active)}"><a href="${h.route_path('admin_settings')}">${_('Settings')}</a></li>
124
124
125 ## delegated admin
125 ## delegated admin
126 % elif c.is_delegated_admin:
126 % elif c.is_delegated_admin:
127 <%
127 <%
128 repositories=c.auth_user.repositories_admin or c.can_create_repo
128 repositories=c.auth_user.repositories_admin or c.can_create_repo
129 repository_groups=c.auth_user.repository_groups_admin or c.can_create_repo_group
129 repository_groups=c.auth_user.repository_groups_admin or c.can_create_repo_group
130 user_groups=c.auth_user.user_groups_admin or c.can_create_user_group
130 user_groups=c.auth_user.user_groups_admin or c.can_create_user_group
131 %>
131 %>
132
132
133 %if repositories:
133 %if repositories:
134 <li class="${h.is_active('repositories', active)} local-admin-repos"><a href="${h.route_path('repos')}">${_('Repositories')}</a></li>
134 <li class="${h.is_active('repositories', active)} local-admin-repos"><a href="${h.route_path('repos')}">${_('Repositories')}</a></li>
135 %endif
135 %endif
136 %if repository_groups:
136 %if repository_groups:
137 <li class="${h.is_active('repository_groups', active)} local-admin-repo-groups"><a href="${h.route_path('repo_groups')}">${_('Repository groups')}</a></li>
137 <li class="${h.is_active('repository_groups', active)} local-admin-repo-groups"><a href="${h.route_path('repo_groups')}">${_('Repository groups')}</a></li>
138 %endif
138 %endif
139 %if user_groups:
139 %if user_groups:
140 <li class="${h.is_active('user_groups', active)} local-admin-user-groups"><a href="${h.route_path('user_groups')}">${_('User groups')}</a></li>
140 <li class="${h.is_active('user_groups', active)} local-admin-user-groups"><a href="${h.route_path('user_groups')}">${_('User groups')}</a></li>
141 %endif
141 %endif
142 % endif
142 % endif
143 </ul>
143 </ul>
144
144
145 </div>
145 </div>
146 <div class="clear"></div>
146 <div class="clear"></div>
147 </div>
147 </div>
148 </%def>
148 </%def>
149
149
150 <%def name="dt_info_panel(elements)">
150 <%def name="dt_info_panel(elements)">
151 <dl class="dl-horizontal">
151 <dl class="dl-horizontal">
152 %for dt, dd, title, show_items in elements:
152 %for dt, dd, title, show_items in elements:
153 <dt>${dt}:</dt>
153 <dt>${dt}:</dt>
154 <dd title="${h.tooltip(title)}">
154 <dd title="${h.tooltip(title)}">
155 %if callable(dd):
155 %if callable(dd):
156 ## allow lazy evaluation of elements
156 ## allow lazy evaluation of elements
157 ${dd()}
157 ${dd()}
158 %else:
158 %else:
159 ${dd}
159 ${dd}
160 %endif
160 %endif
161 %if show_items:
161 %if show_items:
162 <span class="btn-collapse" data-toggle="item-${h.md5_safe(dt)[:6]}-details">${_('Show More')} </span>
162 <span class="btn-collapse" data-toggle="item-${h.md5_safe(dt)[:6]}-details">${_('Show More')} </span>
163 %endif
163 %endif
164 </dd>
164 </dd>
165
165
166 %if show_items:
166 %if show_items:
167 <div class="collapsable-content" data-toggle="item-${h.md5_safe(dt)[:6]}-details" style="display: none">
167 <div class="collapsable-content" data-toggle="item-${h.md5_safe(dt)[:6]}-details" style="display: none">
168 %for item in show_items:
168 %for item in show_items:
169 <dt></dt>
169 <dt></dt>
170 <dd>${item}</dd>
170 <dd>${item}</dd>
171 %endfor
171 %endfor
172 </div>
172 </div>
173 %endif
173 %endif
174
174
175 %endfor
175 %endfor
176 </dl>
176 </dl>
177 </%def>
177 </%def>
178
178
179 <%def name="tr_info_entry(element)">
179 <%def name="tr_info_entry(element)">
180 <% key, val, title, show_items = element %>
180 <% key, val, title, show_items = element %>
181
181
182 <tr>
182 <tr>
183 <td style="vertical-align: top">${key}</td>
183 <td style="vertical-align: top">${key}</td>
184 <td title="${h.tooltip(title)}">
184 <td title="${h.tooltip(title)}">
185 %if callable(val):
185 %if callable(val):
186 ## allow lazy evaluation of elements
186 ## allow lazy evaluation of elements
187 ${val()}
187 ${val()}
188 %else:
188 %else:
189 ${val}
189 ${val}
190 %endif
190 %endif
191 %if show_items:
191 %if show_items:
192 <div class="collapsable-content" data-toggle="item-${h.md5_safe(val)[:6]}-details" style="display: none">
192 <div class="collapsable-content" data-toggle="item-${h.md5_safe(h.safe_str(val))[:6]}-details" style="display: none">
193 % for item in show_items:
193 % for item in show_items:
194 <dt></dt>
194 <dt></dt>
195 <dd>${item}</dd>
195 <dd>${item}</dd>
196 % endfor
196 % endfor
197 </div>
197 </div>
198 %endif
198 %endif
199 </td>
199 </td>
200 <td style="vertical-align: top">
200 <td style="vertical-align: top">
201 %if show_items:
201 %if show_items:
202 <span class="btn-collapse" data-toggle="item-${h.md5_safe(val)[:6]}-details">${_('Show More')} </span>
202 <span class="btn-collapse" data-toggle="item-${h.md5_safe(h.safe_str(val))[:6]}-details">${_('Show More')} </span>
203 %endif
203 %endif
204 </td>
204 </td>
205 </tr>
205 </tr>
206
206
207 </%def>
207 </%def>
208
208
209 <%def name="gravatar(email, size=16, tooltip=False, tooltip_alt=None, user=None, extra_class=None)">
209 <%def name="gravatar(email, size=16, tooltip=False, tooltip_alt=None, user=None, extra_class=None)">
210 <%
210 <%
211 if size > 16:
211 if size > 16:
212 gravatar_class = ['gravatar','gravatar-large']
212 gravatar_class = ['gravatar','gravatar-large']
213 else:
213 else:
214 gravatar_class = ['gravatar']
214 gravatar_class = ['gravatar']
215
215
216 data_hovercard_url = ''
216 data_hovercard_url = ''
217 data_hovercard_alt = tooltip_alt.replace('<', '&lt;').replace('>', '&gt;') if tooltip_alt else ''
217 data_hovercard_alt = tooltip_alt.replace('<', '&lt;').replace('>', '&gt;') if tooltip_alt else ''
218
218
219 if tooltip:
219 if tooltip:
220 gravatar_class += ['tooltip-hovercard']
220 gravatar_class += ['tooltip-hovercard']
221 if extra_class:
221 if extra_class:
222 gravatar_class += extra_class
222 gravatar_class += extra_class
223 if tooltip and user:
223 if tooltip and user:
224 if user.username == h.DEFAULT_USER:
224 if user.username == h.DEFAULT_USER:
225 gravatar_class.pop(-1)
225 gravatar_class.pop(-1)
226 else:
226 else:
227 data_hovercard_url = request.route_path('hovercard_user', user_id=getattr(user, 'user_id', ''))
227 data_hovercard_url = request.route_path('hovercard_user', user_id=getattr(user, 'user_id', ''))
228 gravatar_class = ' '.join(gravatar_class)
228 gravatar_class = ' '.join(gravatar_class)
229
229
230 %>
230 %>
231 <%doc>
231 <%doc>
232 TODO: johbo: For now we serve double size images to make it smooth
232 TODO: johbo: For now we serve double size images to make it smooth
233 for retina. This is how it worked until now. Should be replaced
233 for retina. This is how it worked until now. Should be replaced
234 with a better solution at some point.
234 with a better solution at some point.
235 </%doc>
235 </%doc>
236
236
237 <img class="${gravatar_class}" height="${size}" width="${size}" data-hovercard-url="${data_hovercard_url}" data-hovercard-alt="${data_hovercard_alt}" src="${h.gravatar_url(email, size * 2)}" />
237 <img class="${gravatar_class}" height="${size}" width="${size}" data-hovercard-url="${data_hovercard_url}" data-hovercard-alt="${data_hovercard_alt}" src="${h.gravatar_url(email, size * 2)}" />
238 </%def>
238 </%def>
239
239
240
240
241 <%def name="gravatar_with_user(contact, size=16, show_disabled=False, tooltip=False, _class='rc-user')">
241 <%def name="gravatar_with_user(contact, size=16, show_disabled=False, tooltip=False, _class='rc-user')">
242 <%
242 <%
243 email = h.email_or_none(contact)
243 email = h.email_or_none(contact)
244 rc_user = h.discover_user(contact)
244 rc_user = h.discover_user(contact)
245 %>
245 %>
246
246
247 <div class="${_class}">
247 <div class="${_class}">
248 ${self.gravatar(email, size, tooltip=tooltip, tooltip_alt=contact, user=rc_user)}
248 ${self.gravatar(email, size, tooltip=tooltip, tooltip_alt=contact, user=rc_user)}
249 <span class="${('user user-disabled' if show_disabled else 'user')}">
249 <span class="${('user user-disabled' if show_disabled else 'user')}">
250 ${h.link_to_user(rc_user or contact)}
250 ${h.link_to_user(rc_user or contact)}
251 </span>
251 </span>
252 </div>
252 </div>
253 </%def>
253 </%def>
254
254
255
255
256 <%def name="user_group_icon(user_group=None, size=16, tooltip=False)">
256 <%def name="user_group_icon(user_group=None, size=16, tooltip=False)">
257 <%
257 <%
258 if (size > 16):
258 if (size > 16):
259 gravatar_class = 'icon-user-group-alt'
259 gravatar_class = 'icon-user-group-alt'
260 else:
260 else:
261 gravatar_class = 'icon-user-group-alt'
261 gravatar_class = 'icon-user-group-alt'
262
262
263 if tooltip:
263 if tooltip:
264 gravatar_class += ' tooltip-hovercard'
264 gravatar_class += ' tooltip-hovercard'
265
265
266 data_hovercard_url = request.route_path('hovercard_user_group', user_group_id=user_group.users_group_id)
266 data_hovercard_url = request.route_path('hovercard_user_group', user_group_id=user_group.users_group_id)
267 %>
267 %>
268 <%doc>
268 <%doc>
269 TODO: johbo: For now we serve double size images to make it smooth
269 TODO: johbo: For now we serve double size images to make it smooth
270 for retina. This is how it worked until now. Should be replaced
270 for retina. This is how it worked until now. Should be replaced
271 with a better solution at some point.
271 with a better solution at some point.
272 </%doc>
272 </%doc>
273
273
274 <i style="font-size: ${size}px" class="${gravatar_class} x-icon-size-${size}" data-hovercard-url="${data_hovercard_url}"></i>
274 <i style="font-size: ${size}px" class="${gravatar_class} x-icon-size-${size}" data-hovercard-url="${data_hovercard_url}"></i>
275 </%def>
275 </%def>
276
276
277 <%def name="repo_page_title(repo_instance)">
277 <%def name="repo_page_title(repo_instance)">
278 <div class="title-content repo-title">
278 <div class="title-content repo-title">
279
279
280 <div class="title-main">
280 <div class="title-main">
281 ## SVN/HG/GIT icons
281 ## SVN/HG/GIT icons
282 %if h.is_hg(repo_instance):
282 %if h.is_hg(repo_instance):
283 <i class="icon-hg"></i>
283 <i class="icon-hg"></i>
284 %endif
284 %endif
285 %if h.is_git(repo_instance):
285 %if h.is_git(repo_instance):
286 <i class="icon-git"></i>
286 <i class="icon-git"></i>
287 %endif
287 %endif
288 %if h.is_svn(repo_instance):
288 %if h.is_svn(repo_instance):
289 <i class="icon-svn"></i>
289 <i class="icon-svn"></i>
290 %endif
290 %endif
291
291
292 ## public/private
292 ## public/private
293 %if repo_instance.private:
293 %if repo_instance.private:
294 <i class="icon-repo-private"></i>
294 <i class="icon-repo-private"></i>
295 %else:
295 %else:
296 <i class="icon-repo-public"></i>
296 <i class="icon-repo-public"></i>
297 %endif
297 %endif
298
298
299 ## repo name with group name
299 ## repo name with group name
300 ${h.breadcrumb_repo_link(repo_instance)}
300 ${h.breadcrumb_repo_link(repo_instance)}
301
301
302 ## Context Actions
302 ## Context Actions
303 <div class="pull-right">
303 <div class="pull-right">
304 %if c.rhodecode_user.username != h.DEFAULT_USER:
304 %if c.rhodecode_user.username != h.DEFAULT_USER:
305 <a href="${h.route_path('atom_feed_home', repo_name=c.rhodecode_db_repo.repo_uid, _query=dict(auth_token=c.rhodecode_user.feed_token))}" title="${_('RSS Feed')}" class="btn btn-sm"><i class="icon-rss-sign"></i>RSS</a>
305 <a href="${h.route_path('atom_feed_home', repo_name=c.rhodecode_db_repo.repo_uid, _query=dict(auth_token=c.rhodecode_user.feed_token))}" title="${_('RSS Feed')}" class="btn btn-sm"><i class="icon-rss-sign"></i>RSS</a>
306
306
307 <a href="#WatchRepo" onclick="toggleFollowingRepo(this, templateContext.repo_id); return false" title="${_('Watch this Repository and actions on it in your personalized journal')}" class="btn btn-sm ${('watching' if c.repository_is_user_following else '')}">
307 <a href="#WatchRepo" onclick="toggleFollowingRepo(this, templateContext.repo_id); return false" title="${_('Watch this Repository and actions on it in your personalized journal')}" class="btn btn-sm ${('watching' if c.repository_is_user_following else '')}">
308 % if c.repository_is_user_following:
308 % if c.repository_is_user_following:
309 <i class="icon-eye-off"></i>${_('Unwatch')}
309 <i class="icon-eye-off"></i>${_('Unwatch')}
310 % else:
310 % else:
311 <i class="icon-eye"></i>${_('Watch')}
311 <i class="icon-eye"></i>${_('Watch')}
312 % endif
312 % endif
313
313
314 </a>
314 </a>
315 %else:
315 %else:
316 <a href="${h.route_path('atom_feed_home', repo_name=c.rhodecode_db_repo.repo_uid)}" title="${_('RSS Feed')}" class="btn btn-sm"><i class="icon-rss-sign"></i>RSS</a>
316 <a href="${h.route_path('atom_feed_home', repo_name=c.rhodecode_db_repo.repo_uid)}" title="${_('RSS Feed')}" class="btn btn-sm"><i class="icon-rss-sign"></i>RSS</a>
317 %endif
317 %endif
318 </div>
318 </div>
319
319
320 </div>
320 </div>
321
321
322 ## FORKED
322 ## FORKED
323 %if repo_instance.fork:
323 %if repo_instance.fork:
324 <p class="discreet">
324 <p class="discreet">
325 <i class="icon-code-fork"></i> ${_('Fork of')}
325 <i class="icon-code-fork"></i> ${_('Fork of')}
326 ${h.link_to_if(c.has_origin_repo_read_perm,repo_instance.fork.repo_name, h.route_path('repo_summary', repo_name=repo_instance.fork.repo_name))}
326 ${h.link_to_if(c.has_origin_repo_read_perm,repo_instance.fork.repo_name, h.route_path('repo_summary', repo_name=repo_instance.fork.repo_name))}
327 </p>
327 </p>
328 %endif
328 %endif
329
329
330 ## IMPORTED FROM REMOTE
330 ## IMPORTED FROM REMOTE
331 %if repo_instance.clone_uri:
331 %if repo_instance.clone_uri:
332 <p class="discreet">
332 <p class="discreet">
333 <i class="icon-code-fork"></i> ${_('Clone from')}
333 <i class="icon-code-fork"></i> ${_('Clone from')}
334 <a href="${h.safe_str(h.hide_credentials(repo_instance.clone_uri))}">${h.hide_credentials(repo_instance.clone_uri)}</a>
334 <a href="${h.safe_str(h.hide_credentials(repo_instance.clone_uri))}">${h.hide_credentials(repo_instance.clone_uri)}</a>
335 </p>
335 </p>
336 %endif
336 %endif
337
337
338 ## LOCKING STATUS
338 ## LOCKING STATUS
339 %if repo_instance.locked[0]:
339 %if repo_instance.locked[0]:
340 <p class="locking_locked discreet">
340 <p class="locking_locked discreet">
341 <i class="icon-repo-lock"></i>
341 <i class="icon-repo-lock"></i>
342 ${_('Repository locked by %(user)s') % {'user': h.person_by_id(repo_instance.locked[0])}}
342 ${_('Repository locked by %(user)s') % {'user': h.person_by_id(repo_instance.locked[0])}}
343 </p>
343 </p>
344 %elif repo_instance.enable_locking:
344 %elif repo_instance.enable_locking:
345 <p class="locking_unlocked discreet">
345 <p class="locking_unlocked discreet">
346 <i class="icon-repo-unlock"></i>
346 <i class="icon-repo-unlock"></i>
347 ${_('Repository not locked. Pull repository to lock it.')}
347 ${_('Repository not locked. Pull repository to lock it.')}
348 </p>
348 </p>
349 %endif
349 %endif
350
350
351 </div>
351 </div>
352 </%def>
352 </%def>
353
353
354 <%def name="repo_menu(active=None)">
354 <%def name="repo_menu(active=None)">
355 <%
355 <%
356 ## determine if we have "any" option available
356 ## determine if we have "any" option available
357 can_lock = h.HasRepoPermissionAny('repository.write','repository.admin')(c.repo_name) and c.rhodecode_db_repo.enable_locking
357 can_lock = h.HasRepoPermissionAny('repository.write','repository.admin')(c.repo_name) and c.rhodecode_db_repo.enable_locking
358 has_actions = can_lock
358 has_actions = can_lock
359
359
360 %>
360 %>
361 % if c.rhodecode_db_repo.archived:
361 % if c.rhodecode_db_repo.archived:
362 <div class="alert alert-warning text-center">
362 <div class="alert alert-warning text-center">
363 <strong>${_('This repository has been archived. It is now read-only.')}</strong>
363 <strong>${_('This repository has been archived. It is now read-only.')}</strong>
364 </div>
364 </div>
365 % endif
365 % endif
366
366
367 <!--- REPO CONTEXT BAR -->
367 <!--- REPO CONTEXT BAR -->
368 <div id="context-bar">
368 <div id="context-bar">
369 <div class="wrapper">
369 <div class="wrapper">
370
370
371 <div class="title">
371 <div class="title">
372 ${self.repo_page_title(c.rhodecode_db_repo)}
372 ${self.repo_page_title(c.rhodecode_db_repo)}
373 </div>
373 </div>
374
374
375 <ul id="context-pages" class="navigation horizontal-list">
375 <ul id="context-pages" class="navigation horizontal-list">
376 <li class="${h.is_active('summary', active)}"><a class="menulink" href="${h.route_path('repo_summary_explicit', repo_name=c.repo_name)}"><div class="menulabel">${_('Summary')}</div></a></li>
376 <li class="${h.is_active('summary', active)}"><a class="menulink" href="${h.route_path('repo_summary_explicit', repo_name=c.repo_name)}"><div class="menulabel">${_('Summary')}</div></a></li>
377 <li class="${h.is_active('commits', active)}"><a class="menulink" href="${h.route_path('repo_commits', repo_name=c.repo_name)}"><div class="menulabel">${_('Commits')}</div></a></li>
377 <li class="${h.is_active('commits', active)}"><a class="menulink" href="${h.route_path('repo_commits', repo_name=c.repo_name)}"><div class="menulabel">${_('Commits')}</div></a></li>
378 <li class="${h.is_active('files', active)}"><a class="menulink" href="${h.repo_files_by_ref_url(c.repo_name, c.rhodecode_db_repo.repo_type, f_path='', ref_name=c.rhodecode_db_repo.landing_ref_name, commit_id='tip', query={'at':c.rhodecode_db_repo.landing_ref_name})}"><div class="menulabel">${_('Files')}</div></a></li>
378 <li class="${h.is_active('files', active)}"><a class="menulink" href="${h.repo_files_by_ref_url(c.repo_name, c.rhodecode_db_repo.repo_type, f_path='', ref_name=c.rhodecode_db_repo.landing_ref_name, commit_id='tip', query={'at':c.rhodecode_db_repo.landing_ref_name})}"><div class="menulabel">${_('Files')}</div></a></li>
379 <li class="${h.is_active('compare', active)}"><a class="menulink" href="${h.route_path('repo_compare_select',repo_name=c.repo_name)}"><div class="menulabel">${_('Compare')}</div></a></li>
379 <li class="${h.is_active('compare', active)}"><a class="menulink" href="${h.route_path('repo_compare_select',repo_name=c.repo_name)}"><div class="menulabel">${_('Compare')}</div></a></li>
380
380
381 ## TODO: anderson: ideally it would have a function on the scm_instance "enable_pullrequest() and enable_fork()"
381 ## TODO: anderson: ideally it would have a function on the scm_instance "enable_pullrequest() and enable_fork()"
382 %if c.rhodecode_db_repo.repo_type in ['git','hg']:
382 %if c.rhodecode_db_repo.repo_type in ['git','hg']:
383 <li class="${h.is_active('showpullrequest', active)}">
383 <li class="${h.is_active('showpullrequest', active)}">
384 <a class="menulink" href="${h.route_path('pullrequest_show_all', repo_name=c.repo_name)}" title="${h.tooltip(_('Show Pull Requests for %s') % c.repo_name)}">
384 <a class="menulink" href="${h.route_path('pullrequest_show_all', repo_name=c.repo_name)}" title="${h.tooltip(_('Show Pull Requests for %s') % c.repo_name)}">
385 <div class="menulabel">
385 <div class="menulabel">
386 ${_('Pull Requests')} <span class="menulink-counter">${c.repository_pull_requests}</span>
386 ${_('Pull Requests')} <span class="menulink-counter">${c.repository_pull_requests}</span>
387 </div>
387 </div>
388 </a>
388 </a>
389 </li>
389 </li>
390 %endif
390 %endif
391
391
392 <li class="${h.is_active('artifacts', active)}">
392 <li class="${h.is_active('artifacts', active)}">
393 <a class="menulink" href="${h.route_path('repo_artifacts_list',repo_name=c.repo_name)}">
393 <a class="menulink" href="${h.route_path('repo_artifacts_list',repo_name=c.repo_name)}">
394 <div class="menulabel">
394 <div class="menulabel">
395 ${_('Artifacts')} <span class="menulink-counter">${c.repository_artifacts}</span>
395 ${_('Artifacts')} <span class="menulink-counter">${c.repository_artifacts}</span>
396 </div>
396 </div>
397 </a>
397 </a>
398 </li>
398 </li>
399
399
400 %if not c.rhodecode_db_repo.archived and h.HasRepoPermissionAll('repository.admin')(c.repo_name):
400 %if not c.rhodecode_db_repo.archived and h.HasRepoPermissionAll('repository.admin')(c.repo_name):
401 <li class="${h.is_active('settings', active)}"><a class="menulink" href="${h.route_path('edit_repo',repo_name=c.repo_name)}"><div class="menulabel">${_('Repository Settings')}</div></a></li>
401 <li class="${h.is_active('settings', active)}"><a class="menulink" href="${h.route_path('edit_repo',repo_name=c.repo_name)}"><div class="menulabel">${_('Repository Settings')}</div></a></li>
402 %endif
402 %endif
403
403
404 <li class="${h.is_active('options', active)}">
404 <li class="${h.is_active('options', active)}">
405 % if has_actions:
405 % if has_actions:
406 <a class="menulink dropdown">
406 <a class="menulink dropdown">
407 <div class="menulabel">${_('Options')}<div class="show_more"></div></div>
407 <div class="menulabel">${_('Options')}<div class="show_more"></div></div>
408 </a>
408 </a>
409 <ul class="submenu">
409 <ul class="submenu">
410 %if can_lock:
410 %if can_lock:
411 %if c.rhodecode_db_repo.locked[0]:
411 %if c.rhodecode_db_repo.locked[0]:
412 <li><a class="locking_del" href="${h.route_path('repo_edit_toggle_locking',repo_name=c.repo_name)}">${_('Unlock Repository')}</a></li>
412 <li><a class="locking_del" href="${h.route_path('repo_edit_toggle_locking',repo_name=c.repo_name)}">${_('Unlock Repository')}</a></li>
413 %else:
413 %else:
414 <li><a class="locking_add" href="${h.route_path('repo_edit_toggle_locking',repo_name=c.repo_name)}">${_('Lock Repository')}</a></li>
414 <li><a class="locking_add" href="${h.route_path('repo_edit_toggle_locking',repo_name=c.repo_name)}">${_('Lock Repository')}</a></li>
415 %endif
415 %endif
416 %endif
416 %endif
417 </ul>
417 </ul>
418 % endif
418 % endif
419 </li>
419 </li>
420
420
421 </ul>
421 </ul>
422 </div>
422 </div>
423 <div class="clear"></div>
423 <div class="clear"></div>
424 </div>
424 </div>
425
425
426 <!--- REPO END CONTEXT BAR -->
426 <!--- REPO END CONTEXT BAR -->
427
427
428 </%def>
428 </%def>
429
429
430 <%def name="repo_group_page_title(repo_group_instance)">
430 <%def name="repo_group_page_title(repo_group_instance)">
431 <div class="title-content">
431 <div class="title-content">
432 <div class="title-main">
432 <div class="title-main">
433 ## Repository Group icon
433 ## Repository Group icon
434 <i class="icon-repo-group"></i>
434 <i class="icon-repo-group"></i>
435
435
436 ## repo name with group name
436 ## repo name with group name
437 ${h.breadcrumb_repo_group_link(repo_group_instance)}
437 ${h.breadcrumb_repo_group_link(repo_group_instance)}
438 </div>
438 </div>
439
439
440 <%namespace name="dt" file="/data_table/_dt_elements.mako"/>
440 <%namespace name="dt" file="/data_table/_dt_elements.mako"/>
441 <div class="repo-group-desc discreet">
441 <div class="repo-group-desc discreet">
442 ${dt.repo_group_desc(repo_group_instance.description_safe, repo_group_instance.personal, c.visual.stylify_metatags)}
442 ${dt.repo_group_desc(repo_group_instance.description_safe, repo_group_instance.personal, c.visual.stylify_metatags)}
443 </div>
443 </div>
444
444
445 </div>
445 </div>
446 </%def>
446 </%def>
447
447
448
448
449 <%def name="repo_group_menu(active=None)">
449 <%def name="repo_group_menu(active=None)">
450 <%
450 <%
451 gr_name = c.repo_group.group_name if c.repo_group else None
451 gr_name = c.repo_group.group_name if c.repo_group else None
452 # create repositories with write permission on group is set to true
452 # create repositories with write permission on group is set to true
453 group_admin = h.HasRepoGroupPermissionAny('group.admin')(gr_name, 'group admin index page')
453 group_admin = h.HasRepoGroupPermissionAny('group.admin')(gr_name, 'group admin index page')
454
454
455 %>
455 %>
456
456
457
457
458 <!--- REPO GROUP CONTEXT BAR -->
458 <!--- REPO GROUP CONTEXT BAR -->
459 <div id="context-bar">
459 <div id="context-bar">
460 <div class="wrapper">
460 <div class="wrapper">
461 <div class="title">
461 <div class="title">
462 ${self.repo_group_page_title(c.repo_group)}
462 ${self.repo_group_page_title(c.repo_group)}
463 </div>
463 </div>
464
464
465 <ul id="context-pages" class="navigation horizontal-list">
465 <ul id="context-pages" class="navigation horizontal-list">
466 <li class="${h.is_active('home', active)}">
466 <li class="${h.is_active('home', active)}">
467 <a class="menulink" href="${h.route_path('repo_group_home', repo_group_name=c.repo_group.group_name)}"><div class="menulabel">${_('Group Home')}</div></a>
467 <a class="menulink" href="${h.route_path('repo_group_home', repo_group_name=c.repo_group.group_name)}"><div class="menulabel">${_('Group Home')}</div></a>
468 </li>
468 </li>
469 % if c.is_super_admin or group_admin:
469 % if c.is_super_admin or group_admin:
470 <li class="${h.is_active('settings', active)}">
470 <li class="${h.is_active('settings', active)}">
471 <a class="menulink" href="${h.route_path('edit_repo_group',repo_group_name=c.repo_group.group_name)}" title="${_('You have admin right to this group, and can edit it')}"><div class="menulabel">${_('Group Settings')}</div></a>
471 <a class="menulink" href="${h.route_path('edit_repo_group',repo_group_name=c.repo_group.group_name)}" title="${_('You have admin right to this group, and can edit it')}"><div class="menulabel">${_('Group Settings')}</div></a>
472 </li>
472 </li>
473 % endif
473 % endif
474
474
475 </ul>
475 </ul>
476 </div>
476 </div>
477 <div class="clear"></div>
477 <div class="clear"></div>
478 </div>
478 </div>
479
479
480 <!--- REPO GROUP CONTEXT BAR -->
480 <!--- REPO GROUP CONTEXT BAR -->
481
481
482 </%def>
482 </%def>
483
483
484
484
485 <%def name="usermenu(active=False)">
485 <%def name="usermenu(active=False)">
486 <%
486 <%
487 not_anonymous = c.rhodecode_user.username != h.DEFAULT_USER
487 not_anonymous = c.rhodecode_user.username != h.DEFAULT_USER
488
488
489 gr_name = c.repo_group.group_name if (hasattr(c, 'repo_group') and c.repo_group) else None
489 gr_name = c.repo_group.group_name if (hasattr(c, 'repo_group') and c.repo_group) else None
490 # create repositories with write permission on group is set to true
490 # create repositories with write permission on group is set to true
491
491
492 can_fork = c.is_super_admin or h.HasPermissionAny('hg.fork.repository')()
492 can_fork = c.is_super_admin or h.HasPermissionAny('hg.fork.repository')()
493 create_on_write = h.HasPermissionAny('hg.create.write_on_repogroup.true')()
493 create_on_write = h.HasPermissionAny('hg.create.write_on_repogroup.true')()
494 group_write = h.HasRepoGroupPermissionAny('group.write')(gr_name, 'can write into group index page')
494 group_write = h.HasRepoGroupPermissionAny('group.write')(gr_name, 'can write into group index page')
495 group_admin = h.HasRepoGroupPermissionAny('group.admin')(gr_name, 'group admin index page')
495 group_admin = h.HasRepoGroupPermissionAny('group.admin')(gr_name, 'group admin index page')
496
496
497 can_create_repos = c.is_super_admin or c.can_create_repo
497 can_create_repos = c.is_super_admin or c.can_create_repo
498 can_create_repo_groups = c.is_super_admin or c.can_create_repo_group
498 can_create_repo_groups = c.is_super_admin or c.can_create_repo_group
499
499
500 can_create_repos_in_group = c.is_super_admin or group_admin or (group_write and create_on_write)
500 can_create_repos_in_group = c.is_super_admin or group_admin or (group_write and create_on_write)
501 can_create_repo_groups_in_group = c.is_super_admin or group_admin
501 can_create_repo_groups_in_group = c.is_super_admin or group_admin
502 %>
502 %>
503
503
504 % if not_anonymous:
504 % if not_anonymous:
505 <%
505 <%
506 default_target_group = dict()
506 default_target_group = dict()
507 if c.rhodecode_user.personal_repo_group:
507 if c.rhodecode_user.personal_repo_group:
508 default_target_group = dict(parent_group=c.rhodecode_user.personal_repo_group.group_id)
508 default_target_group = dict(parent_group=c.rhodecode_user.personal_repo_group.group_id)
509 %>
509 %>
510
510
511 ## create action
511 ## create action
512 <li>
512 <li>
513 <a href="#create-actions" onclick="return false;" class="menulink childs">
513 <a href="#create-actions" onclick="return false;" class="menulink childs">
514 <i class="icon-plus-circled"></i>
514 <i class="icon-plus-circled"></i>
515 </a>
515 </a>
516
516
517 <div class="action-menu submenu">
517 <div class="action-menu submenu">
518
518
519 <ol>
519 <ol>
520 ## scope of within a repository
520 ## scope of within a repository
521 % if hasattr(c, 'rhodecode_db_repo') and c.rhodecode_db_repo:
521 % if hasattr(c, 'rhodecode_db_repo') and c.rhodecode_db_repo:
522 <li class="submenu-title">${_('This Repository')}</li>
522 <li class="submenu-title">${_('This Repository')}</li>
523 <li>
523 <li>
524 <a href="${h.route_path('pullrequest_new',repo_name=c.repo_name)}">${_('Create Pull Request')}</a>
524 <a href="${h.route_path('pullrequest_new',repo_name=c.repo_name)}">${_('Create Pull Request')}</a>
525 </li>
525 </li>
526 % if can_fork:
526 % if can_fork:
527 <li>
527 <li>
528 <a href="${h.route_path('repo_fork_new',repo_name=c.repo_name,_query=default_target_group)}">${_('Fork this repository')}</a>
528 <a href="${h.route_path('repo_fork_new',repo_name=c.repo_name,_query=default_target_group)}">${_('Fork this repository')}</a>
529 </li>
529 </li>
530 % endif
530 % endif
531 % endif
531 % endif
532
532
533 ## scope of within repository groups
533 ## scope of within repository groups
534 % if hasattr(c, 'repo_group') and c.repo_group and (can_create_repos_in_group or can_create_repo_groups_in_group):
534 % if hasattr(c, 'repo_group') and c.repo_group and (can_create_repos_in_group or can_create_repo_groups_in_group):
535 <li class="submenu-title">${_('This Repository Group')}</li>
535 <li class="submenu-title">${_('This Repository Group')}</li>
536
536
537 % if can_create_repos_in_group:
537 % if can_create_repos_in_group:
538 <li>
538 <li>
539 <a href="${h.route_path('repo_new',_query=dict(parent_group=c.repo_group.group_id))}">${_('New Repository')}</a>
539 <a href="${h.route_path('repo_new',_query=dict(parent_group=c.repo_group.group_id))}">${_('New Repository')}</a>
540 </li>
540 </li>
541 % endif
541 % endif
542
542
543 % if can_create_repo_groups_in_group:
543 % if can_create_repo_groups_in_group:
544 <li>
544 <li>
545 <a href="${h.route_path('repo_group_new',_query=dict(parent_group=c.repo_group.group_id))}">${_(u'New Repository Group')}</a>
545 <a href="${h.route_path('repo_group_new',_query=dict(parent_group=c.repo_group.group_id))}">${_(u'New Repository Group')}</a>
546 </li>
546 </li>
547 % endif
547 % endif
548 % endif
548 % endif
549
549
550 ## personal group
550 ## personal group
551 % if c.rhodecode_user.personal_repo_group:
551 % if c.rhodecode_user.personal_repo_group:
552 <li class="submenu-title">Personal Group</li>
552 <li class="submenu-title">Personal Group</li>
553
553
554 <li>
554 <li>
555 <a href="${h.route_path('repo_new',_query=dict(parent_group=c.rhodecode_user.personal_repo_group.group_id))}" >${_('New Repository')} </a>
555 <a href="${h.route_path('repo_new',_query=dict(parent_group=c.rhodecode_user.personal_repo_group.group_id))}" >${_('New Repository')} </a>
556 </li>
556 </li>
557
557
558 <li>
558 <li>
559 <a href="${h.route_path('repo_group_new',_query=dict(parent_group=c.rhodecode_user.personal_repo_group.group_id))}">${_('New Repository Group')} </a>
559 <a href="${h.route_path('repo_group_new',_query=dict(parent_group=c.rhodecode_user.personal_repo_group.group_id))}">${_('New Repository Group')} </a>
560 </li>
560 </li>
561 % endif
561 % endif
562
562
563 ## Global actions
563 ## Global actions
564 <li class="submenu-title">RhodeCode</li>
564 <li class="submenu-title">RhodeCode</li>
565 % if can_create_repos:
565 % if can_create_repos:
566 <li>
566 <li>
567 <a href="${h.route_path('repo_new')}" >${_('New Repository')}</a>
567 <a href="${h.route_path('repo_new')}" >${_('New Repository')}</a>
568 </li>
568 </li>
569 % endif
569 % endif
570
570
571 % if can_create_repo_groups:
571 % if can_create_repo_groups:
572 <li>
572 <li>
573 <a href="${h.route_path('repo_group_new')}" >${_(u'New Repository Group')}</a>
573 <a href="${h.route_path('repo_group_new')}" >${_(u'New Repository Group')}</a>
574 </li>
574 </li>
575 % endif
575 % endif
576
576
577 <li>
577 <li>
578 <a href="${h.route_path('gists_new')}">${_(u'New Gist')}</a>
578 <a href="${h.route_path('gists_new')}">${_(u'New Gist')}</a>
579 </li>
579 </li>
580
580
581 </ol>
581 </ol>
582
582
583 </div>
583 </div>
584 </li>
584 </li>
585
585
586 ## notifications
586 ## notifications
587 <li>
587 <li>
588 <a class="${('empty' if c.unread_notifications == 0 else '')}" href="${h.route_path('notifications_show_all')}">
588 <a class="${('empty' if c.unread_notifications == 0 else '')}" href="${h.route_path('notifications_show_all')}">
589 ${c.unread_notifications}
589 ${c.unread_notifications}
590 </a>
590 </a>
591 </li>
591 </li>
592 % endif
592 % endif
593
593
594 ## USER MENU
594 ## USER MENU
595 <li id="quick_login_li" class="${'active' if active else ''}">
595 <li id="quick_login_li" class="${'active' if active else ''}">
596 % if c.rhodecode_user.username == h.DEFAULT_USER:
596 % if c.rhodecode_user.username == h.DEFAULT_USER:
597 <a id="quick_login_link" class="menulink childs" href="${h.route_path('login', _query={'came_from': h.current_route_path(request)})}">
597 <a id="quick_login_link" class="menulink childs" href="${h.route_path('login', _query={'came_from': h.current_route_path(request)})}">
598 ${gravatar(c.rhodecode_user.email, 20)}
598 ${gravatar(c.rhodecode_user.email, 20)}
599 <span class="user">
599 <span class="user">
600 <span>${_('Sign in')}</span>
600 <span>${_('Sign in')}</span>
601 </span>
601 </span>
602 </a>
602 </a>
603 % else:
603 % else:
604 ## logged in user
604 ## logged in user
605 <a id="quick_login_link" class="menulink childs">
605 <a id="quick_login_link" class="menulink childs">
606 ${gravatar(c.rhodecode_user.email, 20)}
606 ${gravatar(c.rhodecode_user.email, 20)}
607 <span class="user">
607 <span class="user">
608 <span class="menu_link_user">${c.rhodecode_user.username}</span>
608 <span class="menu_link_user">${c.rhodecode_user.username}</span>
609 <div class="show_more"></div>
609 <div class="show_more"></div>
610 </span>
610 </span>
611 </a>
611 </a>
612 ## subnav with menu for logged in user
612 ## subnav with menu for logged in user
613 <div class="user-menu submenu">
613 <div class="user-menu submenu">
614 <div id="quick_login">
614 <div id="quick_login">
615 %if c.rhodecode_user.username != h.DEFAULT_USER:
615 %if c.rhodecode_user.username != h.DEFAULT_USER:
616 <div class="">
616 <div class="">
617 <div class="big_gravatar">${gravatar(c.rhodecode_user.email, 48)}</div>
617 <div class="big_gravatar">${gravatar(c.rhodecode_user.email, 48)}</div>
618 <div class="full_name">${c.rhodecode_user.full_name_or_username}</div>
618 <div class="full_name">${c.rhodecode_user.full_name_or_username}</div>
619 <div class="email">${c.rhodecode_user.email}</div>
619 <div class="email">${c.rhodecode_user.email}</div>
620 </div>
620 </div>
621 <div class="">
621 <div class="">
622 <ol class="links">
622 <ol class="links">
623 <li>${h.link_to(_(u'My account'),h.route_path('my_account_profile'))}</li>
623 <li>${h.link_to(_(u'My account'),h.route_path('my_account_profile'))}</li>
624 % if c.rhodecode_user.personal_repo_group:
624 % if c.rhodecode_user.personal_repo_group:
625 <li>${h.link_to(_(u'My personal group'), h.route_path('repo_group_home', repo_group_name=c.rhodecode_user.personal_repo_group.group_name))}</li>
625 <li>${h.link_to(_(u'My personal group'), h.route_path('repo_group_home', repo_group_name=c.rhodecode_user.personal_repo_group.group_name))}</li>
626 % endif
626 % endif
627 <li>${h.link_to(_(u'Pull Requests'), h.route_path('my_account_pullrequests'))}</li>
627 <li>${h.link_to(_(u'Pull Requests'), h.route_path('my_account_pullrequests'))}</li>
628
628
629 % if c.debug_style:
629 % if c.debug_style:
630 <li>
630 <li>
631 <a class="menulink" title="${_('Style')}" href="${h.route_path('debug_style_home')}">
631 <a class="menulink" title="${_('Style')}" href="${h.route_path('debug_style_home')}">
632 <div class="menulabel">${_('[Style]')}</div>
632 <div class="menulabel">${_('[Style]')}</div>
633 </a>
633 </a>
634 </li>
634 </li>
635 % endif
635 % endif
636
636
637 ## bookmark-items
637 ## bookmark-items
638 <li class="bookmark-items">
638 <li class="bookmark-items">
639 ${_('Bookmarks')}
639 ${_('Bookmarks')}
640 <div class="pull-right">
640 <div class="pull-right">
641 <a href="${h.route_path('my_account_bookmarks')}">
641 <a href="${h.route_path('my_account_bookmarks')}">
642
642
643 <i class="icon-cog"></i>
643 <i class="icon-cog"></i>
644 </a>
644 </a>
645 </div>
645 </div>
646 </li>
646 </li>
647 % if not c.bookmark_items:
647 % if not c.bookmark_items:
648 <li>
648 <li>
649 <a href="${h.route_path('my_account_bookmarks')}">${_('No Bookmarks yet.')}</a>
649 <a href="${h.route_path('my_account_bookmarks')}">${_('No Bookmarks yet.')}</a>
650 </li>
650 </li>
651 % endif
651 % endif
652 % for item in c.bookmark_items:
652 % for item in c.bookmark_items:
653 <li>
653 <li>
654 % if item.repository:
654 % if item.repository:
655 <div>
655 <div>
656 <a class="bookmark-item" href="${h.route_path('my_account_goto_bookmark', bookmark_id=item.position)}">
656 <a class="bookmark-item" href="${h.route_path('my_account_goto_bookmark', bookmark_id=item.position)}">
657 <code>${item.position}</code>
657 <code>${item.position}</code>
658 % if item.repository.repo_type == 'hg':
658 % if item.repository.repo_type == 'hg':
659 <i class="icon-hg" title="${_('Repository')}" style="font-size: 16px"></i>
659 <i class="icon-hg" title="${_('Repository')}" style="font-size: 16px"></i>
660 % elif item.repository.repo_type == 'git':
660 % elif item.repository.repo_type == 'git':
661 <i class="icon-git" title="${_('Repository')}" style="font-size: 16px"></i>
661 <i class="icon-git" title="${_('Repository')}" style="font-size: 16px"></i>
662 % elif item.repository.repo_type == 'svn':
662 % elif item.repository.repo_type == 'svn':
663 <i class="icon-svn" title="${_('Repository')}" style="font-size: 16px"></i>
663 <i class="icon-svn" title="${_('Repository')}" style="font-size: 16px"></i>
664 % endif
664 % endif
665 ${(item.title or h.shorter(item.repository.repo_name, 30))}
665 ${(item.title or h.shorter(item.repository.repo_name, 30))}
666 </a>
666 </a>
667 </div>
667 </div>
668 % elif item.repository_group:
668 % elif item.repository_group:
669 <div>
669 <div>
670 <a class="bookmark-item" href="${h.route_path('my_account_goto_bookmark', bookmark_id=item.position)}">
670 <a class="bookmark-item" href="${h.route_path('my_account_goto_bookmark', bookmark_id=item.position)}">
671 <code>${item.position}</code>
671 <code>${item.position}</code>
672 <i class="icon-repo-group" title="${_('Repository group')}" style="font-size: 14px"></i>
672 <i class="icon-repo-group" title="${_('Repository group')}" style="font-size: 14px"></i>
673 ${(item.title or h.shorter(item.repository_group.group_name, 30))}
673 ${(item.title or h.shorter(item.repository_group.group_name, 30))}
674 </a>
674 </a>
675 </div>
675 </div>
676 % else:
676 % else:
677 <a class="bookmark-item" href="${h.route_path('my_account_goto_bookmark', bookmark_id=item.position)}">
677 <a class="bookmark-item" href="${h.route_path('my_account_goto_bookmark', bookmark_id=item.position)}">
678 <code>${item.position}</code>
678 <code>${item.position}</code>
679 ${item.title}
679 ${item.title}
680 </a>
680 </a>
681 % endif
681 % endif
682 </li>
682 </li>
683 % endfor
683 % endfor
684
684
685 <li class="logout">
685 <li class="logout">
686 ${h.secure_form(h.route_path('logout'), request=request)}
686 ${h.secure_form(h.route_path('logout'), request=request)}
687 ${h.submit('log_out', _(u'Sign Out'),class_="btn btn-primary")}
687 ${h.submit('log_out', _(u'Sign Out'),class_="btn btn-primary")}
688 ${h.end_form()}
688 ${h.end_form()}
689 </li>
689 </li>
690 </ol>
690 </ol>
691 </div>
691 </div>
692 %endif
692 %endif
693 </div>
693 </div>
694 </div>
694 </div>
695
695
696 % endif
696 % endif
697 </li>
697 </li>
698 </%def>
698 </%def>
699
699
700 <%def name="menu_items(active=None)">
700 <%def name="menu_items(active=None)">
701 <%
701 <%
702 notice_messages, notice_level = c.rhodecode_user.get_notice_messages()
702 notice_messages, notice_level = c.rhodecode_user.get_notice_messages()
703 notice_display = 'none' if len(notice_messages) == 0 else ''
703 notice_display = 'none' if len(notice_messages) == 0 else ''
704 %>
704 %>
705
705
706 <ul id="quick" class="main_nav navigation horizontal-list">
706 <ul id="quick" class="main_nav navigation horizontal-list">
707 ## notice box for important system messages
707 ## notice box for important system messages
708 <li style="display: ${notice_display}">
708 <li style="display: ${notice_display}">
709 <a class="notice-box" href="#openNotice" onclick="$('.notice-messages-container').toggle(); return false">
709 <a class="notice-box" href="#openNotice" onclick="$('.notice-messages-container').toggle(); return false">
710 <div class="menulabel-notice ${notice_level}" >
710 <div class="menulabel-notice ${notice_level}" >
711 ${len(notice_messages)}
711 ${len(notice_messages)}
712 </div>
712 </div>
713 </a>
713 </a>
714 </li>
714 </li>
715 <div class="notice-messages-container" style="display: none">
715 <div class="notice-messages-container" style="display: none">
716 <div class="notice-messages">
716 <div class="notice-messages">
717 <table class="rctable">
717 <table class="rctable">
718 % for notice in notice_messages:
718 % for notice in notice_messages:
719 <tr id="notice-message-${notice['msg_id']}" class="notice-message-${notice['level']}">
719 <tr id="notice-message-${notice['msg_id']}" class="notice-message-${notice['level']}">
720 <td style="vertical-align: text-top; width: 20px">
720 <td style="vertical-align: text-top; width: 20px">
721 <i class="tooltip icon-info notice-color-${notice['level']}" title="${notice['level']}"></i>
721 <i class="tooltip icon-info notice-color-${notice['level']}" title="${notice['level']}"></i>
722 </td>
722 </td>
723 <td>
723 <td>
724 <span><i class="icon-plus-squared cursor-pointer" onclick="$('#notice-${notice['msg_id']}').toggle()"></i> </span>
724 <span><i class="icon-plus-squared cursor-pointer" onclick="$('#notice-${notice['msg_id']}').toggle()"></i> </span>
725 ${notice['subject']}
725 ${notice['subject']}
726
726
727 <div id="notice-${notice['msg_id']}" style="display: none">
727 <div id="notice-${notice['msg_id']}" style="display: none">
728 ${h.render(notice['body'], renderer='markdown')}
728 ${h.render(notice['body'], renderer='markdown')}
729 </div>
729 </div>
730 </td>
730 </td>
731 <td style="vertical-align: text-top; width: 35px;">
731 <td style="vertical-align: text-top; width: 35px;">
732 <a class="tooltip" title="${_('dismiss')}" href="#dismiss" onclick="dismissNotice(${notice['msg_id']});return false">
732 <a class="tooltip" title="${_('dismiss')}" href="#dismiss" onclick="dismissNotice(${notice['msg_id']});return false">
733 <i class="icon-remove icon-filled-red"></i>
733 <i class="icon-remove icon-filled-red"></i>
734 </a>
734 </a>
735 </td>
735 </td>
736 </tr>
736 </tr>
737
737
738 % endfor
738 % endfor
739 </table>
739 </table>
740 </div>
740 </div>
741 </div>
741 </div>
742 ## Main filter
742 ## Main filter
743 <li>
743 <li>
744 <div class="menulabel main_filter_box">
744 <div class="menulabel main_filter_box">
745 <div class="main_filter_input_box">
745 <div class="main_filter_input_box">
746 <ul class="searchItems">
746 <ul class="searchItems">
747
747
748 <li class="searchTag searchTagIcon">
748 <li class="searchTag searchTagIcon">
749 <i class="icon-search"></i>
749 <i class="icon-search"></i>
750 </li>
750 </li>
751
751
752 % if c.template_context['search_context']['repo_id']:
752 % if c.template_context['search_context']['repo_id']:
753 <li class="searchTag searchTagFilter searchTagHidable" >
753 <li class="searchTag searchTagFilter searchTagHidable" >
754 ##<a href="${h.route_path('search_repo',repo_name=c.template_context['search_context']['repo_name'])}">
754 ##<a href="${h.route_path('search_repo',repo_name=c.template_context['search_context']['repo_name'])}">
755 <span class="tag">
755 <span class="tag">
756 This repo
756 This repo
757 <a href="#removeGoToFilter" onclick="removeGoToFilter(); return false"><i class="icon-cancel-circled"></i></a>
757 <a href="#removeGoToFilter" onclick="removeGoToFilter(); return false"><i class="icon-cancel-circled"></i></a>
758 </span>
758 </span>
759 ##</a>
759 ##</a>
760 </li>
760 </li>
761 % elif c.template_context['search_context']['repo_group_id']:
761 % elif c.template_context['search_context']['repo_group_id']:
762 <li class="searchTag searchTagFilter searchTagHidable">
762 <li class="searchTag searchTagFilter searchTagHidable">
763 ##<a href="${h.route_path('search_repo_group',repo_group_name=c.template_context['search_context']['repo_group_name'])}">
763 ##<a href="${h.route_path('search_repo_group',repo_group_name=c.template_context['search_context']['repo_group_name'])}">
764 <span class="tag">
764 <span class="tag">
765 This group
765 This group
766 <a href="#removeGoToFilter" onclick="removeGoToFilter(); return false"><i class="icon-cancel-circled"></i></a>
766 <a href="#removeGoToFilter" onclick="removeGoToFilter(); return false"><i class="icon-cancel-circled"></i></a>
767 </span>
767 </span>
768 ##</a>
768 ##</a>
769 </li>
769 </li>
770 % endif
770 % endif
771
771
772 <li class="searchTagInput">
772 <li class="searchTagInput">
773 <input class="main_filter_input" id="main_filter" size="25" type="text" name="main_filter" placeholder="${_('search / go to...')}" value="" />
773 <input class="main_filter_input" id="main_filter" size="25" type="text" name="main_filter" placeholder="${_('search / go to...')}" value="" />
774 </li>
774 </li>
775 <li class="searchTag searchTagHelp">
775 <li class="searchTag searchTagHelp">
776 <a href="#showFilterHelp" onclick="showMainFilterBox(); return false">?</a>
776 <a href="#showFilterHelp" onclick="showMainFilterBox(); return false">?</a>
777 </li>
777 </li>
778 </ul>
778 </ul>
779 </div>
779 </div>
780 </div>
780 </div>
781
781
782 <div id="main_filter_help" style="display: none">
782 <div id="main_filter_help" style="display: none">
783 - Use '/' key to quickly access this field.
783 - Use '/' key to quickly access this field.
784
784
785 - Enter a name of repository, or repository group for quick search.
785 - Enter a name of repository, or repository group for quick search.
786
786
787 - Prefix query to allow special search:
787 - Prefix query to allow special search:
788
788
789 <strong>user:</strong>admin, to search for usernames, always global
789 <strong>user:</strong>admin, to search for usernames, always global
790
790
791 <strong>user_group:</strong>devops, to search for user groups, always global
791 <strong>user_group:</strong>devops, to search for user groups, always global
792
792
793 <strong>pr:</strong>303, to search for pull request number, title, or description, always global
793 <strong>pr:</strong>303, to search for pull request number, title, or description, always global
794
794
795 <strong>commit:</strong>efced4, to search for commits, scoped to repositories or groups
795 <strong>commit:</strong>efced4, to search for commits, scoped to repositories or groups
796
796
797 <strong>file:</strong>models.py, to search for file paths, scoped to repositories or groups
797 <strong>file:</strong>models.py, to search for file paths, scoped to repositories or groups
798
798
799 % if c.template_context['search_context']['repo_id']:
799 % if c.template_context['search_context']['repo_id']:
800 For advanced full text search visit: <a href="${h.route_path('search_repo',repo_name=c.template_context['search_context']['repo_name'])}">repository search</a>
800 For advanced full text search visit: <a href="${h.route_path('search_repo',repo_name=c.template_context['search_context']['repo_name'])}">repository search</a>
801 % elif c.template_context['search_context']['repo_group_id']:
801 % elif c.template_context['search_context']['repo_group_id']:
802 For advanced full text search visit: <a href="${h.route_path('search_repo_group',repo_group_name=c.template_context['search_context']['repo_group_name'])}">repository group search</a>
802 For advanced full text search visit: <a href="${h.route_path('search_repo_group',repo_group_name=c.template_context['search_context']['repo_group_name'])}">repository group search</a>
803 % else:
803 % else:
804 For advanced full text search visit: <a href="${h.route_path('search')}">global search</a>
804 For advanced full text search visit: <a href="${h.route_path('search')}">global search</a>
805 % endif
805 % endif
806 </div>
806 </div>
807 </li>
807 </li>
808
808
809 ## ROOT MENU
809 ## ROOT MENU
810 <li class="${h.is_active('home', active)}">
810 <li class="${h.is_active('home', active)}">
811 <a class="menulink" title="${_('Home')}" href="${h.route_path('home')}">
811 <a class="menulink" title="${_('Home')}" href="${h.route_path('home')}">
812 <div class="menulabel">${_('Home')}</div>
812 <div class="menulabel">${_('Home')}</div>
813 </a>
813 </a>
814 </li>
814 </li>
815
815
816 %if c.rhodecode_user.username != h.DEFAULT_USER:
816 %if c.rhodecode_user.username != h.DEFAULT_USER:
817 <li class="${h.is_active('journal', active)}">
817 <li class="${h.is_active('journal', active)}">
818 <a class="menulink" title="${_('Show activity journal')}" href="${h.route_path('journal')}">
818 <a class="menulink" title="${_('Show activity journal')}" href="${h.route_path('journal')}">
819 <div class="menulabel">${_('Journal')}</div>
819 <div class="menulabel">${_('Journal')}</div>
820 </a>
820 </a>
821 </li>
821 </li>
822 %else:
822 %else:
823 <li class="${h.is_active('journal', active)}">
823 <li class="${h.is_active('journal', active)}">
824 <a class="menulink" title="${_('Show Public activity journal')}" href="${h.route_path('journal_public')}">
824 <a class="menulink" title="${_('Show Public activity journal')}" href="${h.route_path('journal_public')}">
825 <div class="menulabel">${_('Public journal')}</div>
825 <div class="menulabel">${_('Public journal')}</div>
826 </a>
826 </a>
827 </li>
827 </li>
828 %endif
828 %endif
829
829
830 <li class="${h.is_active('gists', active)}">
830 <li class="${h.is_active('gists', active)}">
831 <a class="menulink childs" title="${_('Show Gists')}" href="${h.route_path('gists_show')}">
831 <a class="menulink childs" title="${_('Show Gists')}" href="${h.route_path('gists_show')}">
832 <div class="menulabel">${_('Gists')}</div>
832 <div class="menulabel">${_('Gists')}</div>
833 </a>
833 </a>
834 </li>
834 </li>
835
835
836 % if c.is_super_admin or c.is_delegated_admin:
836 % if c.is_super_admin or c.is_delegated_admin:
837 <li class="${h.is_active('admin', active)}">
837 <li class="${h.is_active('admin', active)}">
838 <a class="menulink childs" title="${_('Admin settings')}" href="${h.route_path('admin_home')}">
838 <a class="menulink childs" title="${_('Admin settings')}" href="${h.route_path('admin_home')}">
839 <div class="menulabel">${_('Admin')} </div>
839 <div class="menulabel">${_('Admin')} </div>
840 </a>
840 </a>
841 </li>
841 </li>
842 % endif
842 % endif
843
843
844 ## render extra user menu
844 ## render extra user menu
845 ${usermenu(active=(active=='my_account'))}
845 ${usermenu(active=(active=='my_account'))}
846
846
847 </ul>
847 </ul>
848
848
849 <script type="text/javascript">
849 <script type="text/javascript">
850 var visualShowPublicIcon = "${c.visual.show_public_icon}" == "True";
850 var visualShowPublicIcon = "${c.visual.show_public_icon}" == "True";
851
851
852 var formatRepoResult = function(result, container, query, escapeMarkup) {
852 var formatRepoResult = function(result, container, query, escapeMarkup) {
853 return function(data, escapeMarkup) {
853 return function(data, escapeMarkup) {
854 if (!data.repo_id){
854 if (!data.repo_id){
855 return data.text; // optgroup text Repositories
855 return data.text; // optgroup text Repositories
856 }
856 }
857
857
858 var tmpl = '';
858 var tmpl = '';
859 var repoType = data['repo_type'];
859 var repoType = data['repo_type'];
860 var repoName = data['text'];
860 var repoName = data['text'];
861
861
862 if(data && data.type == 'repo'){
862 if(data && data.type == 'repo'){
863 if(repoType === 'hg'){
863 if(repoType === 'hg'){
864 tmpl += '<i class="icon-hg"></i> ';
864 tmpl += '<i class="icon-hg"></i> ';
865 }
865 }
866 else if(repoType === 'git'){
866 else if(repoType === 'git'){
867 tmpl += '<i class="icon-git"></i> ';
867 tmpl += '<i class="icon-git"></i> ';
868 }
868 }
869 else if(repoType === 'svn'){
869 else if(repoType === 'svn'){
870 tmpl += '<i class="icon-svn"></i> ';
870 tmpl += '<i class="icon-svn"></i> ';
871 }
871 }
872 if(data['private']){
872 if(data['private']){
873 tmpl += '<i class="icon-lock" ></i> ';
873 tmpl += '<i class="icon-lock" ></i> ';
874 }
874 }
875 else if(visualShowPublicIcon){
875 else if(visualShowPublicIcon){
876 tmpl += '<i class="icon-unlock-alt"></i> ';
876 tmpl += '<i class="icon-unlock-alt"></i> ';
877 }
877 }
878 }
878 }
879 tmpl += escapeMarkup(repoName);
879 tmpl += escapeMarkup(repoName);
880 return tmpl;
880 return tmpl;
881
881
882 }(result, escapeMarkup);
882 }(result, escapeMarkup);
883 };
883 };
884
884
885 var formatRepoGroupResult = function(result, container, query, escapeMarkup) {
885 var formatRepoGroupResult = function(result, container, query, escapeMarkup) {
886 return function(data, escapeMarkup) {
886 return function(data, escapeMarkup) {
887 if (!data.repo_group_id){
887 if (!data.repo_group_id){
888 return data.text; // optgroup text Repositories
888 return data.text; // optgroup text Repositories
889 }
889 }
890
890
891 var tmpl = '';
891 var tmpl = '';
892 var repoGroupName = data['text'];
892 var repoGroupName = data['text'];
893
893
894 if(data){
894 if(data){
895
895
896 tmpl += '<i class="icon-repo-group"></i> ';
896 tmpl += '<i class="icon-repo-group"></i> ';
897
897
898 }
898 }
899 tmpl += escapeMarkup(repoGroupName);
899 tmpl += escapeMarkup(repoGroupName);
900 return tmpl;
900 return tmpl;
901
901
902 }(result, escapeMarkup);
902 }(result, escapeMarkup);
903 };
903 };
904
904
905 var escapeRegExChars = function (value) {
905 var escapeRegExChars = function (value) {
906 return value.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
906 return value.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
907 };
907 };
908
908
909 var getRepoIcon = function(repo_type) {
909 var getRepoIcon = function(repo_type) {
910 if (repo_type === 'hg') {
910 if (repo_type === 'hg') {
911 return '<i class="icon-hg"></i> ';
911 return '<i class="icon-hg"></i> ';
912 }
912 }
913 else if (repo_type === 'git') {
913 else if (repo_type === 'git') {
914 return '<i class="icon-git"></i> ';
914 return '<i class="icon-git"></i> ';
915 }
915 }
916 else if (repo_type === 'svn') {
916 else if (repo_type === 'svn') {
917 return '<i class="icon-svn"></i> ';
917 return '<i class="icon-svn"></i> ';
918 }
918 }
919 return ''
919 return ''
920 };
920 };
921
921
922 var autocompleteMainFilterFormatResult = function (data, value, org_formatter) {
922 var autocompleteMainFilterFormatResult = function (data, value, org_formatter) {
923
923
924 if (value.split(':').length === 2) {
924 if (value.split(':').length === 2) {
925 value = value.split(':')[1]
925 value = value.split(':')[1]
926 }
926 }
927
927
928 var searchType = data['type'];
928 var searchType = data['type'];
929 var searchSubType = data['subtype'];
929 var searchSubType = data['subtype'];
930 var valueDisplay = data['value_display'];
930 var valueDisplay = data['value_display'];
931 var valueIcon = data['value_icon'];
931 var valueIcon = data['value_icon'];
932
932
933 var pattern = '(' + escapeRegExChars(value) + ')';
933 var pattern = '(' + escapeRegExChars(value) + ')';
934
934
935 valueDisplay = Select2.util.escapeMarkup(valueDisplay);
935 valueDisplay = Select2.util.escapeMarkup(valueDisplay);
936
936
937 // highlight match
937 // highlight match
938 if (searchType != 'text') {
938 if (searchType != 'text') {
939 valueDisplay = valueDisplay.replace(new RegExp(pattern, 'gi'), '<strong>$1<\/strong>');
939 valueDisplay = valueDisplay.replace(new RegExp(pattern, 'gi'), '<strong>$1<\/strong>');
940 }
940 }
941
941
942 var icon = '';
942 var icon = '';
943
943
944 if (searchType === 'hint') {
944 if (searchType === 'hint') {
945 icon += '<i class="icon-repo-group"></i> ';
945 icon += '<i class="icon-repo-group"></i> ';
946 }
946 }
947 // full text search/hints
947 // full text search/hints
948 else if (searchType === 'search') {
948 else if (searchType === 'search') {
949 if (valueIcon === undefined) {
949 if (valueIcon === undefined) {
950 icon += '<i class="icon-more"></i> ';
950 icon += '<i class="icon-more"></i> ';
951 } else {
951 } else {
952 icon += valueIcon + ' ';
952 icon += valueIcon + ' ';
953 }
953 }
954
954
955 if (searchSubType !== undefined && searchSubType == 'repo') {
955 if (searchSubType !== undefined && searchSubType == 'repo') {
956 valueDisplay += '<div class="pull-right tag">repository</div>';
956 valueDisplay += '<div class="pull-right tag">repository</div>';
957 }
957 }
958 else if (searchSubType !== undefined && searchSubType == 'repo_group') {
958 else if (searchSubType !== undefined && searchSubType == 'repo_group') {
959 valueDisplay += '<div class="pull-right tag">repo group</div>';
959 valueDisplay += '<div class="pull-right tag">repo group</div>';
960 }
960 }
961 }
961 }
962 // repository
962 // repository
963 else if (searchType === 'repo') {
963 else if (searchType === 'repo') {
964
964
965 var repoIcon = getRepoIcon(data['repo_type']);
965 var repoIcon = getRepoIcon(data['repo_type']);
966 icon += repoIcon;
966 icon += repoIcon;
967
967
968 if (data['private']) {
968 if (data['private']) {
969 icon += '<i class="icon-lock" ></i> ';
969 icon += '<i class="icon-lock" ></i> ';
970 }
970 }
971 else if (visualShowPublicIcon) {
971 else if (visualShowPublicIcon) {
972 icon += '<i class="icon-unlock-alt"></i> ';
972 icon += '<i class="icon-unlock-alt"></i> ';
973 }
973 }
974 }
974 }
975 // repository groups
975 // repository groups
976 else if (searchType === 'repo_group') {
976 else if (searchType === 'repo_group') {
977 icon += '<i class="icon-repo-group"></i> ';
977 icon += '<i class="icon-repo-group"></i> ';
978 }
978 }
979 // user group
979 // user group
980 else if (searchType === 'user_group') {
980 else if (searchType === 'user_group') {
981 icon += '<i class="icon-group"></i> ';
981 icon += '<i class="icon-group"></i> ';
982 }
982 }
983 // user
983 // user
984 else if (searchType === 'user') {
984 else if (searchType === 'user') {
985 icon += '<img class="gravatar" src="{0}"/>'.format(data['icon_link']);
985 icon += '<img class="gravatar" src="{0}"/>'.format(data['icon_link']);
986 }
986 }
987 // pull request
987 // pull request
988 else if (searchType === 'pull_request') {
988 else if (searchType === 'pull_request') {
989 icon += '<i class="icon-merge"></i> ';
989 icon += '<i class="icon-merge"></i> ';
990 }
990 }
991 // commit
991 // commit
992 else if (searchType === 'commit') {
992 else if (searchType === 'commit') {
993 var repo_data = data['repo_data'];
993 var repo_data = data['repo_data'];
994 var repoIcon = getRepoIcon(repo_data['repository_type']);
994 var repoIcon = getRepoIcon(repo_data['repository_type']);
995 if (repoIcon) {
995 if (repoIcon) {
996 icon += repoIcon;
996 icon += repoIcon;
997 } else {
997 } else {
998 icon += '<i class="icon-tag"></i>';
998 icon += '<i class="icon-tag"></i>';
999 }
999 }
1000 }
1000 }
1001 // file
1001 // file
1002 else if (searchType === 'file') {
1002 else if (searchType === 'file') {
1003 var repo_data = data['repo_data'];
1003 var repo_data = data['repo_data'];
1004 var repoIcon = getRepoIcon(repo_data['repository_type']);
1004 var repoIcon = getRepoIcon(repo_data['repository_type']);
1005 if (repoIcon) {
1005 if (repoIcon) {
1006 icon += repoIcon;
1006 icon += repoIcon;
1007 } else {
1007 } else {
1008 icon += '<i class="icon-tag"></i>';
1008 icon += '<i class="icon-tag"></i>';
1009 }
1009 }
1010 }
1010 }
1011 // generic text
1011 // generic text
1012 else if (searchType === 'text') {
1012 else if (searchType === 'text') {
1013 icon = '';
1013 icon = '';
1014 }
1014 }
1015
1015
1016 var tmpl = '<div class="ac-container-wrap">{0}{1}</div>';
1016 var tmpl = '<div class="ac-container-wrap">{0}{1}</div>';
1017 return tmpl.format(icon, valueDisplay);
1017 return tmpl.format(icon, valueDisplay);
1018 };
1018 };
1019
1019
1020 var handleSelect = function(element, suggestion) {
1020 var handleSelect = function(element, suggestion) {
1021 if (suggestion.type === "hint") {
1021 if (suggestion.type === "hint") {
1022 // we skip action
1022 // we skip action
1023 $('#main_filter').focus();
1023 $('#main_filter').focus();
1024 }
1024 }
1025 else if (suggestion.type === "text") {
1025 else if (suggestion.type === "text") {
1026 // we skip action
1026 // we skip action
1027 $('#main_filter').focus();
1027 $('#main_filter').focus();
1028
1028
1029 } else {
1029 } else {
1030 window.location = suggestion['url'];
1030 window.location = suggestion['url'];
1031 }
1031 }
1032 };
1032 };
1033
1033
1034 var autocompleteMainFilterResult = function (suggestion, originalQuery, queryLowerCase) {
1034 var autocompleteMainFilterResult = function (suggestion, originalQuery, queryLowerCase) {
1035 if (queryLowerCase.split(':').length === 2) {
1035 if (queryLowerCase.split(':').length === 2) {
1036 queryLowerCase = queryLowerCase.split(':')[1]
1036 queryLowerCase = queryLowerCase.split(':')[1]
1037 }
1037 }
1038 if (suggestion.type === "text") {
1038 if (suggestion.type === "text") {
1039 // special case we don't want to "skip" display for
1039 // special case we don't want to "skip" display for
1040 return true
1040 return true
1041 }
1041 }
1042 return suggestion.value_display.toLowerCase().indexOf(queryLowerCase) !== -1;
1042 return suggestion.value_display.toLowerCase().indexOf(queryLowerCase) !== -1;
1043 };
1043 };
1044
1044
1045 var cleanContext = {
1045 var cleanContext = {
1046 repo_view_type: null,
1046 repo_view_type: null,
1047
1047
1048 repo_id: null,
1048 repo_id: null,
1049 repo_name: "",
1049 repo_name: "",
1050
1050
1051 repo_group_id: null,
1051 repo_group_id: null,
1052 repo_group_name: null
1052 repo_group_name: null
1053 };
1053 };
1054 var removeGoToFilter = function () {
1054 var removeGoToFilter = function () {
1055 $('.searchTagHidable').hide();
1055 $('.searchTagHidable').hide();
1056 $('#main_filter').autocomplete(
1056 $('#main_filter').autocomplete(
1057 'setOptions', {params:{search_context: cleanContext}});
1057 'setOptions', {params:{search_context: cleanContext}});
1058 };
1058 };
1059
1059
1060 $('#main_filter').autocomplete({
1060 $('#main_filter').autocomplete({
1061 serviceUrl: pyroutes.url('goto_switcher_data'),
1061 serviceUrl: pyroutes.url('goto_switcher_data'),
1062 params: {
1062 params: {
1063 "search_context": templateContext.search_context
1063 "search_context": templateContext.search_context
1064 },
1064 },
1065 minChars:2,
1065 minChars:2,
1066 maxHeight:400,
1066 maxHeight:400,
1067 deferRequestBy: 300, //miliseconds
1067 deferRequestBy: 300, //miliseconds
1068 tabDisabled: true,
1068 tabDisabled: true,
1069 autoSelectFirst: false,
1069 autoSelectFirst: false,
1070 containerClass: 'autocomplete-qfilter-suggestions',
1070 containerClass: 'autocomplete-qfilter-suggestions',
1071 formatResult: autocompleteMainFilterFormatResult,
1071 formatResult: autocompleteMainFilterFormatResult,
1072 lookupFilter: autocompleteMainFilterResult,
1072 lookupFilter: autocompleteMainFilterResult,
1073 onSelect: function (element, suggestion) {
1073 onSelect: function (element, suggestion) {
1074 handleSelect(element, suggestion);
1074 handleSelect(element, suggestion);
1075 return false;
1075 return false;
1076 },
1076 },
1077 onSearchError: function (element, query, jqXHR, textStatus, errorThrown) {
1077 onSearchError: function (element, query, jqXHR, textStatus, errorThrown) {
1078 if (jqXHR !== 'abort') {
1078 if (jqXHR !== 'abort') {
1079 var message = formatErrorMessage(jqXHR, textStatus, errorThrown);
1079 var message = formatErrorMessage(jqXHR, textStatus, errorThrown);
1080 SwalNoAnimation.fire({
1080 SwalNoAnimation.fire({
1081 icon: 'error',
1081 icon: 'error',
1082 title: _gettext('Error during search operation'),
1082 title: _gettext('Error during search operation'),
1083 html: '<span style="white-space: pre-line">{0}</span>'.format(message),
1083 html: '<span style="white-space: pre-line">{0}</span>'.format(message),
1084 }).then(function(result) {
1084 }).then(function(result) {
1085 window.location.reload();
1085 window.location.reload();
1086 })
1086 })
1087 }
1087 }
1088 },
1088 },
1089 onSearchStart: function (params) {
1089 onSearchStart: function (params) {
1090 $('.searchTag.searchTagIcon').html('<i class="icon-spin animate-spin"></i>')
1090 $('.searchTag.searchTagIcon').html('<i class="icon-spin animate-spin"></i>')
1091 },
1091 },
1092 onSearchComplete: function (query, suggestions) {
1092 onSearchComplete: function (query, suggestions) {
1093 $('.searchTag.searchTagIcon').html('<i class="icon-search"></i>')
1093 $('.searchTag.searchTagIcon').html('<i class="icon-search"></i>')
1094 },
1094 },
1095 });
1095 });
1096
1096
1097 showMainFilterBox = function () {
1097 showMainFilterBox = function () {
1098 $('#main_filter_help').toggle();
1098 $('#main_filter_help').toggle();
1099 };
1099 };
1100
1100
1101 $('#main_filter').on('keydown.autocomplete', function (e) {
1101 $('#main_filter').on('keydown.autocomplete', function (e) {
1102
1102
1103 var BACKSPACE = 8;
1103 var BACKSPACE = 8;
1104 var el = $(e.currentTarget);
1104 var el = $(e.currentTarget);
1105 if(e.which === BACKSPACE){
1105 if(e.which === BACKSPACE){
1106 var inputVal = el.val();
1106 var inputVal = el.val();
1107 if (inputVal === ""){
1107 if (inputVal === ""){
1108 removeGoToFilter()
1108 removeGoToFilter()
1109 }
1109 }
1110 }
1110 }
1111 });
1111 });
1112
1112
1113 var dismissNotice = function(noticeId) {
1113 var dismissNotice = function(noticeId) {
1114
1114
1115 var url = pyroutes.url('user_notice_dismiss',
1115 var url = pyroutes.url('user_notice_dismiss',
1116 {"user_id": templateContext.rhodecode_user.user_id});
1116 {"user_id": templateContext.rhodecode_user.user_id});
1117
1117
1118 var postData = {
1118 var postData = {
1119 'csrf_token': CSRF_TOKEN,
1119 'csrf_token': CSRF_TOKEN,
1120 'notice_id': noticeId,
1120 'notice_id': noticeId,
1121 };
1121 };
1122
1122
1123 var success = function(response) {
1123 var success = function(response) {
1124 $('#notice-message-' + noticeId).remove();
1124 $('#notice-message-' + noticeId).remove();
1125 return false;
1125 return false;
1126 };
1126 };
1127 var failure = function(data, textStatus, xhr) {
1127 var failure = function(data, textStatus, xhr) {
1128 alert("error processing request: " + textStatus);
1128 alert("error processing request: " + textStatus);
1129 return false;
1129 return false;
1130 };
1130 };
1131 ajaxPOST(url, postData, success, failure);
1131 ajaxPOST(url, postData, success, failure);
1132 }
1132 }
1133
1133
1134 var hideLicenseWarning = function () {
1134 var hideLicenseWarning = function () {
1135 var fingerprint = templateContext.session_attrs.license_fingerprint;
1135 var fingerprint = templateContext.session_attrs.license_fingerprint;
1136 storeUserSessionAttr('rc_user_session_attr.hide_license_warning', fingerprint);
1136 storeUserSessionAttr('rc_user_session_attr.hide_license_warning', fingerprint);
1137 $('#notifications').hide();
1137 $('#notifications').hide();
1138 }
1138 }
1139
1139
1140 var hideLicenseError = function () {
1140 var hideLicenseError = function () {
1141 var fingerprint = templateContext.session_attrs.license_fingerprint;
1141 var fingerprint = templateContext.session_attrs.license_fingerprint;
1142 storeUserSessionAttr('rc_user_session_attr.hide_license_error', fingerprint);
1142 storeUserSessionAttr('rc_user_session_attr.hide_license_error', fingerprint);
1143 $('#notifications').hide();
1143 $('#notifications').hide();
1144 }
1144 }
1145
1145
1146 </script>
1146 </script>
1147 <script src="${h.asset('js/rhodecode/base/keyboard-bindings.js', ver=c.rhodecode_version_hash)}"></script>
1147 <script src="${h.asset('js/rhodecode/base/keyboard-bindings.js', ver=c.rhodecode_version_hash)}"></script>
1148 </%def>
1148 </%def>
1149
1149
1150 <div class="modal" id="help_kb" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
1150 <div class="modal" id="help_kb" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
1151 <div class="modal-dialog">
1151 <div class="modal-dialog">
1152 <div class="modal-content">
1152 <div class="modal-content">
1153 <div class="modal-header">
1153 <div class="modal-header">
1154 <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
1154 <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
1155 <h4 class="modal-title" id="myModalLabel">${_('Keyboard shortcuts')}</h4>
1155 <h4 class="modal-title" id="myModalLabel">${_('Keyboard shortcuts')}</h4>
1156 </div>
1156 </div>
1157 <div class="modal-body">
1157 <div class="modal-body">
1158 <div class="block-left">
1158 <div class="block-left">
1159 <table class="keyboard-mappings">
1159 <table class="keyboard-mappings">
1160 <tbody>
1160 <tbody>
1161 <tr>
1161 <tr>
1162 <th></th>
1162 <th></th>
1163 <th>${_('Site-wide shortcuts')}</th>
1163 <th>${_('Site-wide shortcuts')}</th>
1164 </tr>
1164 </tr>
1165 <%
1165 <%
1166 elems = [
1166 elems = [
1167 ('/', 'Use quick search box'),
1167 ('/', 'Use quick search box'),
1168 ('g h', 'Goto home page'),
1168 ('g h', 'Goto home page'),
1169 ('g g', 'Goto my private gists page'),
1169 ('g g', 'Goto my private gists page'),
1170 ('g G', 'Goto my public gists page'),
1170 ('g G', 'Goto my public gists page'),
1171 ('g 0-9', 'Goto bookmarked items from 0-9'),
1171 ('g 0-9', 'Goto bookmarked items from 0-9'),
1172 ('n r', 'New repository page'),
1172 ('n r', 'New repository page'),
1173 ('n g', 'New gist page'),
1173 ('n g', 'New gist page'),
1174 ]
1174 ]
1175 %>
1175 %>
1176 %for key, desc in elems:
1176 %for key, desc in elems:
1177 <tr>
1177 <tr>
1178 <td class="keys">
1178 <td class="keys">
1179 <span class="key tag">${key}</span>
1179 <span class="key tag">${key}</span>
1180 </td>
1180 </td>
1181 <td>${desc}</td>
1181 <td>${desc}</td>
1182 </tr>
1182 </tr>
1183 %endfor
1183 %endfor
1184 </tbody>
1184 </tbody>
1185 </table>
1185 </table>
1186 </div>
1186 </div>
1187 <div class="block-left">
1187 <div class="block-left">
1188 <table class="keyboard-mappings">
1188 <table class="keyboard-mappings">
1189 <tbody>
1189 <tbody>
1190 <tr>
1190 <tr>
1191 <th></th>
1191 <th></th>
1192 <th>${_('Repositories')}</th>
1192 <th>${_('Repositories')}</th>
1193 </tr>
1193 </tr>
1194 <%
1194 <%
1195 elems = [
1195 elems = [
1196 ('g s', 'Goto summary page'),
1196 ('g s', 'Goto summary page'),
1197 ('g c', 'Goto changelog page'),
1197 ('g c', 'Goto changelog page'),
1198 ('g f', 'Goto files page'),
1198 ('g f', 'Goto files page'),
1199 ('g F', 'Goto files page with file search activated'),
1199 ('g F', 'Goto files page with file search activated'),
1200 ('g p', 'Goto pull requests page'),
1200 ('g p', 'Goto pull requests page'),
1201 ('g o', 'Goto repository settings'),
1201 ('g o', 'Goto repository settings'),
1202 ('g O', 'Goto repository access permissions settings'),
1202 ('g O', 'Goto repository access permissions settings'),
1203 ('t s', 'Toggle sidebar on some pages'),
1203 ('t s', 'Toggle sidebar on some pages'),
1204 ]
1204 ]
1205 %>
1205 %>
1206 %for key, desc in elems:
1206 %for key, desc in elems:
1207 <tr>
1207 <tr>
1208 <td class="keys">
1208 <td class="keys">
1209 <span class="key tag">${key}</span>
1209 <span class="key tag">${key}</span>
1210 </td>
1210 </td>
1211 <td>${desc}</td>
1211 <td>${desc}</td>
1212 </tr>
1212 </tr>
1213 %endfor
1213 %endfor
1214 </tbody>
1214 </tbody>
1215 </table>
1215 </table>
1216 </div>
1216 </div>
1217 </div>
1217 </div>
1218 <div class="modal-footer">
1218 <div class="modal-footer">
1219 </div>
1219 </div>
1220 </div><!-- /.modal-content -->
1220 </div><!-- /.modal-content -->
1221 </div><!-- /.modal-dialog -->
1221 </div><!-- /.modal-dialog -->
1222 </div><!-- /.modal -->
1222 </div><!-- /.modal -->
1223
1223
1224
1224
1225 <script type="text/javascript">
1225 <script type="text/javascript">
1226 (function () {
1226 (function () {
1227 "use sctrict";
1227 "use sctrict";
1228
1228
1229 // details block auto-hide menu
1229 // details block auto-hide menu
1230 $(document).mouseup(function(e) {
1230 $(document).mouseup(function(e) {
1231 var container = $('.details-inline-block');
1231 var container = $('.details-inline-block');
1232 if (!container.is(e.target) && container.has(e.target).length === 0) {
1232 if (!container.is(e.target) && container.has(e.target).length === 0) {
1233 $('.details-inline-block[open]').removeAttr('open')
1233 $('.details-inline-block[open]').removeAttr('open')
1234 }
1234 }
1235 });
1235 });
1236
1236
1237 var $sideBar = $('.right-sidebar');
1237 var $sideBar = $('.right-sidebar');
1238 var expanded = $sideBar.hasClass('right-sidebar-expanded');
1238 var expanded = $sideBar.hasClass('right-sidebar-expanded');
1239 var sidebarState = templateContext.session_attrs.sidebarState;
1239 var sidebarState = templateContext.session_attrs.sidebarState;
1240 var sidebarEnabled = $('aside.right-sidebar').get(0);
1240 var sidebarEnabled = $('aside.right-sidebar').get(0);
1241
1241
1242 if (sidebarState === 'expanded') {
1242 if (sidebarState === 'expanded') {
1243 expanded = true
1243 expanded = true
1244 } else if (sidebarState === 'collapsed') {
1244 } else if (sidebarState === 'collapsed') {
1245 expanded = false
1245 expanded = false
1246 }
1246 }
1247 if (sidebarEnabled) {
1247 if (sidebarEnabled) {
1248 // show sidebar since it's hidden on load
1248 // show sidebar since it's hidden on load
1249 $('.right-sidebar').show();
1249 $('.right-sidebar').show();
1250
1250
1251 // init based on set initial class, or if defined user session attrs
1251 // init based on set initial class, or if defined user session attrs
1252 if (expanded) {
1252 if (expanded) {
1253 window.expandSidebar();
1253 window.expandSidebar();
1254 window.updateStickyHeader();
1254 window.updateStickyHeader();
1255
1255
1256 } else {
1256 } else {
1257 window.collapseSidebar();
1257 window.collapseSidebar();
1258 window.updateStickyHeader();
1258 window.updateStickyHeader();
1259 }
1259 }
1260 }
1260 }
1261 })()
1261 })()
1262
1262
1263 </script>
1263 </script>
@@ -1,1404 +1,1404 b''
1 <%namespace name="base" file="/base/base.mako"/>
1 <%namespace name="base" file="/base/base.mako"/>
2 <%namespace name="commentblock" file="/changeset/changeset_file_comment.mako"/>
2 <%namespace name="commentblock" file="/changeset/changeset_file_comment.mako"/>
3
3
4 <%def name="diff_line_anchor(commit, filename, line, type)"><%
4 <%def name="diff_line_anchor(commit, filename, line, type)"><%
5 return '%s_%s_%i' % (h.md5_safe(commit+filename), type, line)
5 return '%s_%s_%i' % (h.md5_safe(commit+filename), type, line)
6 %></%def>
6 %></%def>
7
7
8 <%def name="action_class(action)">
8 <%def name="action_class(action)">
9 <%
9 <%
10 return {
10 return {
11 '-': 'cb-deletion',
11 '-': 'cb-deletion',
12 '+': 'cb-addition',
12 '+': 'cb-addition',
13 ' ': 'cb-context',
13 ' ': 'cb-context',
14 }.get(action, 'cb-empty')
14 }.get(action, 'cb-empty')
15 %>
15 %>
16 </%def>
16 </%def>
17
17
18 <%def name="op_class(op_id)">
18 <%def name="op_class(op_id)">
19 <%
19 <%
20 return {
20 return {
21 DEL_FILENODE: 'deletion', # file deleted
21 DEL_FILENODE: 'deletion', # file deleted
22 BIN_FILENODE: 'warning' # binary diff hidden
22 BIN_FILENODE: 'warning' # binary diff hidden
23 }.get(op_id, 'addition')
23 }.get(op_id, 'addition')
24 %>
24 %>
25 </%def>
25 </%def>
26
26
27
27
28
28
29 <%def name="render_diffset(diffset, commit=None,
29 <%def name="render_diffset(diffset, commit=None,
30
30
31 # collapse all file diff entries when there are more than this amount of files in the diff
31 # collapse all file diff entries when there are more than this amount of files in the diff
32 collapse_when_files_over=20,
32 collapse_when_files_over=20,
33
33
34 # collapse lines in the diff when more than this amount of lines changed in the file diff
34 # collapse lines in the diff when more than this amount of lines changed in the file diff
35 lines_changed_limit=500,
35 lines_changed_limit=500,
36
36
37 # add a ruler at to the output
37 # add a ruler at to the output
38 ruler_at_chars=0,
38 ruler_at_chars=0,
39
39
40 # show inline comments
40 # show inline comments
41 use_comments=False,
41 use_comments=False,
42
42
43 # disable new comments
43 # disable new comments
44 disable_new_comments=False,
44 disable_new_comments=False,
45
45
46 # special file-comments that were deleted in previous versions
46 # special file-comments that were deleted in previous versions
47 # it's used for showing outdated comments for deleted files in a PR
47 # it's used for showing outdated comments for deleted files in a PR
48 deleted_files_comments=None,
48 deleted_files_comments=None,
49
49
50 # for cache purpose
50 # for cache purpose
51 inline_comments=None,
51 inline_comments=None,
52
52
53 # additional menu for PRs
53 # additional menu for PRs
54 pull_request_menu=None,
54 pull_request_menu=None,
55
55
56 # show/hide todo next to comments
56 # show/hide todo next to comments
57 show_todos=True,
57 show_todos=True,
58
58
59 )">
59 )">
60
60
61 <%
61 <%
62 diffset_container_id = h.md5(diffset.target_ref)
62 diffset_container_id = h.md5_safe(diffset.target_ref)
63 collapse_all = len(diffset.files) > collapse_when_files_over
63 collapse_all = len(diffset.files) > collapse_when_files_over
64 active_pattern_entries = h.get_active_pattern_entries(getattr(c, 'repo_name', None))
64 active_pattern_entries = h.get_active_pattern_entries(getattr(c, 'repo_name', None))
65 from rhodecode.lib.diffs import NEW_FILENODE, DEL_FILENODE, \
65 from rhodecode.lib.diffs import NEW_FILENODE, DEL_FILENODE, \
66 MOD_FILENODE, RENAMED_FILENODE, CHMOD_FILENODE, BIN_FILENODE, COPIED_FILENODE
66 MOD_FILENODE, RENAMED_FILENODE, CHMOD_FILENODE, BIN_FILENODE, COPIED_FILENODE
67 %>
67 %>
68
68
69 %if use_comments:
69 %if use_comments:
70
70
71 ## Template for injecting comments
71 ## Template for injecting comments
72 <div id="cb-comments-inline-container-template" class="js-template">
72 <div id="cb-comments-inline-container-template" class="js-template">
73 ${inline_comments_container([])}
73 ${inline_comments_container([])}
74 </div>
74 </div>
75
75
76 <div class="js-template" id="cb-comment-inline-form-template">
76 <div class="js-template" id="cb-comment-inline-form-template">
77 <div class="comment-inline-form ac">
77 <div class="comment-inline-form ac">
78 %if not c.rhodecode_user.is_default:
78 %if not c.rhodecode_user.is_default:
79 ## render template for inline comments
79 ## render template for inline comments
80 ${commentblock.comment_form(form_type='inline')}
80 ${commentblock.comment_form(form_type='inline')}
81 %endif
81 %endif
82 </div>
82 </div>
83 </div>
83 </div>
84
84
85 %endif
85 %endif
86
86
87 %if c.user_session_attrs["diffmode"] == 'sideside':
87 %if c.user_session_attrs["diffmode"] == 'sideside':
88 <style>
88 <style>
89 .wrapper {
89 .wrapper {
90 max-width: 1600px !important;
90 max-width: 1600px !important;
91 }
91 }
92 </style>
92 </style>
93 %endif
93 %endif
94
94
95 %if ruler_at_chars:
95 %if ruler_at_chars:
96 <style>
96 <style>
97 .diff table.cb .cb-content:after {
97 .diff table.cb .cb-content:after {
98 content: "";
98 content: "";
99 border-left: 1px solid blue;
99 border-left: 1px solid blue;
100 position: absolute;
100 position: absolute;
101 top: 0;
101 top: 0;
102 height: 18px;
102 height: 18px;
103 opacity: .2;
103 opacity: .2;
104 z-index: 10;
104 z-index: 10;
105 //## +5 to account for diff action (+/-)
105 //## +5 to account for diff action (+/-)
106 left: ${ruler_at_chars + 5}ch;
106 left: ${ruler_at_chars + 5}ch;
107 </style>
107 </style>
108 %endif
108 %endif
109
109
110 <div class="diffset ${disable_new_comments and 'diffset-comments-disabled'}">
110 <div class="diffset ${disable_new_comments and 'diffset-comments-disabled'}">
111
111
112 <div style="height: 20px; line-height: 20px">
112 <div style="height: 20px; line-height: 20px">
113 ## expand/collapse action
113 ## expand/collapse action
114 <div class="pull-left">
114 <div class="pull-left">
115 <a class="${'collapsed' if collapse_all else ''}" href="#expand-files" onclick="toggleExpand(this, '${diffset_container_id}'); return false">
115 <a class="${'collapsed' if collapse_all else ''}" href="#expand-files" onclick="toggleExpand(this, '${diffset_container_id}'); return false">
116 % if collapse_all:
116 % if collapse_all:
117 <i class="icon-plus-squared-alt icon-no-margin"></i>${_('Expand all files')}
117 <i class="icon-plus-squared-alt icon-no-margin"></i>${_('Expand all files')}
118 % else:
118 % else:
119 <i class="icon-minus-squared-alt icon-no-margin"></i>${_('Collapse all files')}
119 <i class="icon-minus-squared-alt icon-no-margin"></i>${_('Collapse all files')}
120 % endif
120 % endif
121 </a>
121 </a>
122
122
123 </div>
123 </div>
124
124
125 ## todos
125 ## todos
126 % if show_todos and getattr(c, 'at_version', None):
126 % if show_todos and getattr(c, 'at_version', None):
127 <div class="pull-right">
127 <div class="pull-right">
128 <i class="icon-flag-filled" style="color: #949494">TODOs:</i>
128 <i class="icon-flag-filled" style="color: #949494">TODOs:</i>
129 ${_('not available in this view')}
129 ${_('not available in this view')}
130 </div>
130 </div>
131 % elif show_todos:
131 % elif show_todos:
132 <div class="pull-right">
132 <div class="pull-right">
133 <div class="comments-number" style="padding-left: 10px">
133 <div class="comments-number" style="padding-left: 10px">
134 % if hasattr(c, 'unresolved_comments') and hasattr(c, 'resolved_comments'):
134 % if hasattr(c, 'unresolved_comments') and hasattr(c, 'resolved_comments'):
135 <i class="icon-flag-filled" style="color: #949494">TODOs:</i>
135 <i class="icon-flag-filled" style="color: #949494">TODOs:</i>
136 % if c.unresolved_comments:
136 % if c.unresolved_comments:
137 <a href="#show-todos" onclick="$('#todo-box').toggle(); return false">
137 <a href="#show-todos" onclick="$('#todo-box').toggle(); return false">
138 ${_('{} unresolved').format(len(c.unresolved_comments))}
138 ${_('{} unresolved').format(len(c.unresolved_comments))}
139 </a>
139 </a>
140 % else:
140 % else:
141 ${_('0 unresolved')}
141 ${_('0 unresolved')}
142 % endif
142 % endif
143
143
144 ${_('{} Resolved').format(len(c.resolved_comments))}
144 ${_('{} Resolved').format(len(c.resolved_comments))}
145 % endif
145 % endif
146 </div>
146 </div>
147 </div>
147 </div>
148 % endif
148 % endif
149
149
150 ## ## comments
150 ## ## comments
151 ## <div class="pull-right">
151 ## <div class="pull-right">
152 ## <div class="comments-number" style="padding-left: 10px">
152 ## <div class="comments-number" style="padding-left: 10px">
153 ## % if hasattr(c, 'comments') and hasattr(c, 'inline_cnt'):
153 ## % if hasattr(c, 'comments') and hasattr(c, 'inline_cnt'):
154 ## <i class="icon-comment" style="color: #949494">COMMENTS:</i>
154 ## <i class="icon-comment" style="color: #949494">COMMENTS:</i>
155 ## % if c.comments:
155 ## % if c.comments:
156 ## <a href="#comments">${_ungettext("{} General", "{} General", len(c.comments)).format(len(c.comments))}</a>,
156 ## <a href="#comments">${_ungettext("{} General", "{} General", len(c.comments)).format(len(c.comments))}</a>,
157 ## % else:
157 ## % else:
158 ## ${_('0 General')}
158 ## ${_('0 General')}
159 ## % endif
159 ## % endif
160 ##
160 ##
161 ## % if c.inline_cnt:
161 ## % if c.inline_cnt:
162 ## <a href="#" onclick="return Rhodecode.comments.nextComment();"
162 ## <a href="#" onclick="return Rhodecode.comments.nextComment();"
163 ## id="inline-comments-counter">${_ungettext("{} Inline", "{} Inline", c.inline_cnt).format(c.inline_cnt)}
163 ## id="inline-comments-counter">${_ungettext("{} Inline", "{} Inline", c.inline_cnt).format(c.inline_cnt)}
164 ## </a>
164 ## </a>
165 ## % else:
165 ## % else:
166 ## ${_('0 Inline')}
166 ## ${_('0 Inline')}
167 ## % endif
167 ## % endif
168 ## % endif
168 ## % endif
169 ##
169 ##
170 ## % if pull_request_menu:
170 ## % if pull_request_menu:
171 ## <%
171 ## <%
172 ## outdated_comm_count_ver = pull_request_menu['outdated_comm_count_ver']
172 ## outdated_comm_count_ver = pull_request_menu['outdated_comm_count_ver']
173 ## %>
173 ## %>
174 ##
174 ##
175 ## % if outdated_comm_count_ver:
175 ## % if outdated_comm_count_ver:
176 ## <a href="#" onclick="showOutdated(); Rhodecode.comments.nextOutdatedComment(); return false;">
176 ## <a href="#" onclick="showOutdated(); Rhodecode.comments.nextOutdatedComment(); return false;">
177 ## (${_("{} Outdated").format(outdated_comm_count_ver)})
177 ## (${_("{} Outdated").format(outdated_comm_count_ver)})
178 ## </a>
178 ## </a>
179 ## <a href="#" class="showOutdatedComments" onclick="showOutdated(this); return false;"> | ${_('show outdated')}</a>
179 ## <a href="#" class="showOutdatedComments" onclick="showOutdated(this); return false;"> | ${_('show outdated')}</a>
180 ## <a href="#" class="hideOutdatedComments" style="display: none" onclick="hideOutdated(this); return false;"> | ${_('hide outdated')}</a>
180 ## <a href="#" class="hideOutdatedComments" style="display: none" onclick="hideOutdated(this); return false;"> | ${_('hide outdated')}</a>
181 ## % else:
181 ## % else:
182 ## (${_("{} Outdated").format(outdated_comm_count_ver)})
182 ## (${_("{} Outdated").format(outdated_comm_count_ver)})
183 ## % endif
183 ## % endif
184 ##
184 ##
185 ## % endif
185 ## % endif
186 ##
186 ##
187 ## </div>
187 ## </div>
188 ## </div>
188 ## </div>
189
189
190 </div>
190 </div>
191
191
192 % if diffset.limited_diff:
192 % if diffset.limited_diff:
193 <div class="diffset-heading ${(diffset.limited_diff and 'diffset-heading-warning' or '')}">
193 <div class="diffset-heading ${(diffset.limited_diff and 'diffset-heading-warning' or '')}">
194 <h2 class="clearinner">
194 <h2 class="clearinner">
195 ${_('The requested changes are too big and content was truncated.')}
195 ${_('The requested changes are too big and content was truncated.')}
196 <a href="${h.current_route_path(request, fulldiff=1)}" onclick="return confirm('${_("Showing a big diff might take some time and resources, continue?")}')">${_('Show full diff')}</a>
196 <a href="${h.current_route_path(request, fulldiff=1)}" onclick="return confirm('${_("Showing a big diff might take some time and resources, continue?")}')">${_('Show full diff')}</a>
197 </h2>
197 </h2>
198 </div>
198 </div>
199 % endif
199 % endif
200
200
201 <div id="todo-box">
201 <div id="todo-box">
202 % if hasattr(c, 'unresolved_comments') and c.unresolved_comments:
202 % if hasattr(c, 'unresolved_comments') and c.unresolved_comments:
203 % for co in c.unresolved_comments:
203 % for co in c.unresolved_comments:
204 <a class="permalink" href="#comment-${co.comment_id}"
204 <a class="permalink" href="#comment-${co.comment_id}"
205 onclick="Rhodecode.comments.scrollToComment($('#comment-${co.comment_id}'))">
205 onclick="Rhodecode.comments.scrollToComment($('#comment-${co.comment_id}'))">
206 <i class="icon-flag-filled-red"></i>
206 <i class="icon-flag-filled-red"></i>
207 ${co.comment_id}</a>${('' if loop.last else ',')}
207 ${co.comment_id}</a>${('' if loop.last else ',')}
208 % endfor
208 % endfor
209 % endif
209 % endif
210 </div>
210 </div>
211 %if diffset.has_hidden_changes:
211 %if diffset.has_hidden_changes:
212 <p class="empty_data">${_('Some changes may be hidden')}</p>
212 <p class="empty_data">${_('Some changes may be hidden')}</p>
213 %elif not diffset.files:
213 %elif not diffset.files:
214 <p class="empty_data">${_('No files')}</p>
214 <p class="empty_data">${_('No files')}</p>
215 %endif
215 %endif
216
216
217 <div class="filediffs">
217 <div class="filediffs">
218
218
219 ## initial value could be marked as False later on
219 ## initial value could be marked as False later on
220 <% over_lines_changed_limit = False %>
220 <% over_lines_changed_limit = False %>
221 %for i, filediff in enumerate(diffset.files):
221 %for i, filediff in enumerate(diffset.files):
222
222
223 %if filediff.source_file_path and filediff.target_file_path:
223 %if filediff.source_file_path and filediff.target_file_path:
224 %if filediff.source_file_path != filediff.target_file_path:
224 %if filediff.source_file_path != filediff.target_file_path:
225 ## file was renamed, or copied
225 ## file was renamed, or copied
226 %if RENAMED_FILENODE in filediff.patch['stats']['ops']:
226 %if RENAMED_FILENODE in filediff.patch['stats']['ops']:
227 <%
227 <%
228 final_file_name = h.literal(u'{} <i class="icon-angle-left"></i> <del>{}</del>'.format(filediff.target_file_path, filediff.source_file_path))
228 final_file_name = h.literal(u'{} <i class="icon-angle-left"></i> <del>{}</del>'.format(filediff.target_file_path, filediff.source_file_path))
229 final_path = filediff.target_file_path
229 final_path = filediff.target_file_path
230 %>
230 %>
231 %elif COPIED_FILENODE in filediff.patch['stats']['ops']:
231 %elif COPIED_FILENODE in filediff.patch['stats']['ops']:
232 <%
232 <%
233 final_file_name = h.literal(u'{} <i class="icon-angle-left"></i> {}'.format(filediff.target_file_path, filediff.source_file_path))
233 final_file_name = h.literal(u'{} <i class="icon-angle-left"></i> {}'.format(filediff.target_file_path, filediff.source_file_path))
234 final_path = filediff.target_file_path
234 final_path = filediff.target_file_path
235 %>
235 %>
236 %endif
236 %endif
237 %else:
237 %else:
238 ## file was modified
238 ## file was modified
239 <%
239 <%
240 final_file_name = filediff.source_file_path
240 final_file_name = filediff.source_file_path
241 final_path = final_file_name
241 final_path = final_file_name
242 %>
242 %>
243 %endif
243 %endif
244 %else:
244 %else:
245 %if filediff.source_file_path:
245 %if filediff.source_file_path:
246 ## file was deleted
246 ## file was deleted
247 <%
247 <%
248 final_file_name = filediff.source_file_path
248 final_file_name = filediff.source_file_path
249 final_path = final_file_name
249 final_path = final_file_name
250 %>
250 %>
251 %else:
251 %else:
252 ## file was added
252 ## file was added
253 <%
253 <%
254 final_file_name = filediff.target_file_path
254 final_file_name = filediff.target_file_path
255 final_path = final_file_name
255 final_path = final_file_name
256 %>
256 %>
257 %endif
257 %endif
258 %endif
258 %endif
259
259
260 <%
260 <%
261 lines_changed = filediff.patch['stats']['added'] + filediff.patch['stats']['deleted']
261 lines_changed = filediff.patch['stats']['added'] + filediff.patch['stats']['deleted']
262 over_lines_changed_limit = lines_changed > lines_changed_limit
262 over_lines_changed_limit = lines_changed > lines_changed_limit
263 %>
263 %>
264 ## anchor with support of sticky header
264 ## anchor with support of sticky header
265 <div class="anchor" id="a_${h.FID(filediff.raw_id, filediff.patch['filename'])}"></div>
265 <div class="anchor" id="a_${h.FID(filediff.raw_id, filediff.patch['filename'])}"></div>
266
266
267 <input ${(collapse_all and 'checked' or '')} class="filediff-collapse-state collapse-${diffset_container_id}" id="filediff-collapse-${id(filediff)}" type="checkbox" onchange="updateSticky();">
267 <input ${(collapse_all and 'checked' or '')} class="filediff-collapse-state collapse-${diffset_container_id}" id="filediff-collapse-${id(filediff)}" type="checkbox" onchange="updateSticky();">
268 <div
268 <div
269 class="filediff"
269 class="filediff"
270 data-f-path="${filediff.patch['filename']}"
270 data-f-path="${filediff.patch['filename']}"
271 data-anchor-id="${h.FID(filediff.raw_id, filediff.patch['filename'])}"
271 data-anchor-id="${h.FID(filediff.raw_id, filediff.patch['filename'])}"
272 >
272 >
273 <label for="filediff-collapse-${id(filediff)}" class="filediff-heading">
273 <label for="filediff-collapse-${id(filediff)}" class="filediff-heading">
274 <%
274 <%
275 file_comments = (get_inline_comments(inline_comments, filediff.patch['filename']) or {}).values()
275 file_comments = (get_inline_comments(inline_comments, filediff.patch['filename']) or {}).values()
276 total_file_comments = [_c for _c in h.itertools.chain.from_iterable(file_comments) if not (_c.outdated or _c.draft)]
276 total_file_comments = [_c for _c in h.itertools.chain.from_iterable(file_comments) if not (_c.outdated or _c.draft)]
277 %>
277 %>
278 <div class="filediff-collapse-indicator icon-"></div>
278 <div class="filediff-collapse-indicator icon-"></div>
279
279
280 ## Comments/Options PILL
280 ## Comments/Options PILL
281 <span class="pill-group pull-right">
281 <span class="pill-group pull-right">
282 <span class="pill" op="comments">
282 <span class="pill" op="comments">
283 <i class="icon-comment"></i> ${len(total_file_comments)}
283 <i class="icon-comment"></i> ${len(total_file_comments)}
284 </span>
284 </span>
285
285
286 <details class="details-reset details-inline-block">
286 <details class="details-reset details-inline-block">
287 <summary class="noselect">
287 <summary class="noselect">
288 <i class="pill icon-options cursor-pointer" op="options"></i>
288 <i class="pill icon-options cursor-pointer" op="options"></i>
289 </summary>
289 </summary>
290 <details-menu class="details-dropdown">
290 <details-menu class="details-dropdown">
291
291
292 <div class="dropdown-item">
292 <div class="dropdown-item">
293 <span>${final_path}</span>
293 <span>${final_path}</span>
294 <span class="pull-right icon-clipboard clipboard-action" data-clipboard-text="${final_path}" title="Copy file path"></span>
294 <span class="pull-right icon-clipboard clipboard-action" data-clipboard-text="${final_path}" title="Copy file path"></span>
295 </div>
295 </div>
296
296
297 <div class="dropdown-divider"></div>
297 <div class="dropdown-divider"></div>
298
298
299 <div class="dropdown-item">
299 <div class="dropdown-item">
300 <% permalink = request.current_route_url(_anchor='a_{}'.format(h.FID(filediff.raw_id, filediff.patch['filename']))) %>
300 <% permalink = request.current_route_url(_anchor='a_{}'.format(h.FID(filediff.raw_id, filediff.patch['filename']))) %>
301 <a href="${permalink}">ΒΆ permalink</a>
301 <a href="${permalink}">ΒΆ permalink</a>
302 <span class="pull-right icon-clipboard clipboard-action" data-clipboard-text="${permalink}" title="Copy permalink"></span>
302 <span class="pull-right icon-clipboard clipboard-action" data-clipboard-text="${permalink}" title="Copy permalink"></span>
303 </div>
303 </div>
304
304
305
305
306 </details-menu>
306 </details-menu>
307 </details>
307 </details>
308
308
309 </span>
309 </span>
310
310
311 ${diff_ops(final_file_name, filediff)}
311 ${diff_ops(final_file_name, filediff)}
312
312
313 </label>
313 </label>
314
314
315 ${diff_menu(filediff, use_comments=use_comments)}
315 ${diff_menu(filediff, use_comments=use_comments)}
316 <table id="file-${h.safeid(h.safe_unicode(filediff.patch['filename']))}" data-f-path="${filediff.patch['filename']}" data-anchor-id="${h.FID(filediff.raw_id, filediff.patch['filename'])}" class="code-visible-block cb cb-diff-${c.user_session_attrs["diffmode"]} code-highlight ${(over_lines_changed_limit and 'cb-collapsed' or '')}">
316 <table id="file-${h.safeid(h.safe_unicode(filediff.patch['filename']))}" data-f-path="${filediff.patch['filename']}" data-anchor-id="${h.FID(filediff.raw_id, filediff.patch['filename'])}" class="code-visible-block cb cb-diff-${c.user_session_attrs["diffmode"]} code-highlight ${(over_lines_changed_limit and 'cb-collapsed' or '')}">
317
317
318 ## new/deleted/empty content case
318 ## new/deleted/empty content case
319 % if not filediff.hunks:
319 % if not filediff.hunks:
320 ## Comment container, on "fakes" hunk that contains all data to render comments
320 ## Comment container, on "fakes" hunk that contains all data to render comments
321 ${render_hunk_lines(filediff, c.user_session_attrs["diffmode"], filediff.hunk_ops, use_comments=use_comments, inline_comments=inline_comments, active_pattern_entries=active_pattern_entries)}
321 ${render_hunk_lines(filediff, c.user_session_attrs["diffmode"], filediff.hunk_ops, use_comments=use_comments, inline_comments=inline_comments, active_pattern_entries=active_pattern_entries)}
322 % endif
322 % endif
323
323
324 %if filediff.limited_diff:
324 %if filediff.limited_diff:
325 <tr class="cb-warning cb-collapser">
325 <tr class="cb-warning cb-collapser">
326 <td class="cb-text" ${(c.user_session_attrs["diffmode"] == 'unified' and 'colspan=4' or 'colspan=6')}>
326 <td class="cb-text" ${(c.user_session_attrs["diffmode"] == 'unified' and 'colspan=4' or 'colspan=6')}>
327 ${_('The requested commit or file is too big and content was truncated.')} <a href="${h.current_route_path(request, fulldiff=1)}" onclick="return confirm('${_("Showing a big diff might take some time and resources, continue?")}')">${_('Show full diff')}</a>
327 ${_('The requested commit or file is too big and content was truncated.')} <a href="${h.current_route_path(request, fulldiff=1)}" onclick="return confirm('${_("Showing a big diff might take some time and resources, continue?")}')">${_('Show full diff')}</a>
328 </td>
328 </td>
329 </tr>
329 </tr>
330 %else:
330 %else:
331 %if over_lines_changed_limit:
331 %if over_lines_changed_limit:
332 <tr class="cb-warning cb-collapser">
332 <tr class="cb-warning cb-collapser">
333 <td class="cb-text" ${(c.user_session_attrs["diffmode"] == 'unified' and 'colspan=4' or 'colspan=6')}>
333 <td class="cb-text" ${(c.user_session_attrs["diffmode"] == 'unified' and 'colspan=4' or 'colspan=6')}>
334 ${_('This diff has been collapsed as it changes many lines, (%i lines changed)' % lines_changed)}
334 ${_('This diff has been collapsed as it changes many lines, (%i lines changed)' % lines_changed)}
335 <a href="#" class="cb-expand"
335 <a href="#" class="cb-expand"
336 onclick="$(this).closest('table').removeClass('cb-collapsed'); updateSticky(); return false;">${_('Show them')}
336 onclick="$(this).closest('table').removeClass('cb-collapsed'); updateSticky(); return false;">${_('Show them')}
337 </a>
337 </a>
338 <a href="#" class="cb-collapse"
338 <a href="#" class="cb-collapse"
339 onclick="$(this).closest('table').addClass('cb-collapsed'); updateSticky(); return false;">${_('Hide them')}
339 onclick="$(this).closest('table').addClass('cb-collapsed'); updateSticky(); return false;">${_('Hide them')}
340 </a>
340 </a>
341 </td>
341 </td>
342 </tr>
342 </tr>
343 %endif
343 %endif
344 %endif
344 %endif
345
345
346 % for hunk in filediff.hunks:
346 % for hunk in filediff.hunks:
347 <tr class="cb-hunk">
347 <tr class="cb-hunk">
348 <td ${(c.user_session_attrs["diffmode"] == 'unified' and 'colspan=3' or '')}>
348 <td ${(c.user_session_attrs["diffmode"] == 'unified' and 'colspan=3' or '')}>
349 ## TODO: dan: add ajax loading of more context here
349 ## TODO: dan: add ajax loading of more context here
350 ## <a href="#">
350 ## <a href="#">
351 <i class="icon-more"></i>
351 <i class="icon-more"></i>
352 ## </a>
352 ## </a>
353 </td>
353 </td>
354 <td ${(c.user_session_attrs["diffmode"] == 'sideside' and 'colspan=5' or '')}>
354 <td ${(c.user_session_attrs["diffmode"] == 'sideside' and 'colspan=5' or '')}>
355 @@
355 @@
356 -${hunk.source_start},${hunk.source_length}
356 -${hunk.source_start},${hunk.source_length}
357 +${hunk.target_start},${hunk.target_length}
357 +${hunk.target_start},${hunk.target_length}
358 ${hunk.section_header}
358 ${hunk.section_header}
359 </td>
359 </td>
360 </tr>
360 </tr>
361
361
362 ${render_hunk_lines(filediff, c.user_session_attrs["diffmode"], hunk, use_comments=use_comments, inline_comments=inline_comments, active_pattern_entries=active_pattern_entries)}
362 ${render_hunk_lines(filediff, c.user_session_attrs["diffmode"], hunk, use_comments=use_comments, inline_comments=inline_comments, active_pattern_entries=active_pattern_entries)}
363 % endfor
363 % endfor
364
364
365 <% unmatched_comments = (inline_comments or {}).get(filediff.patch['filename'], {}) %>
365 <% unmatched_comments = (inline_comments or {}).get(filediff.patch['filename'], {}) %>
366
366
367 ## outdated comments that do not fit into currently displayed lines
367 ## outdated comments that do not fit into currently displayed lines
368 % for lineno, comments in unmatched_comments.items():
368 % for lineno, comments in unmatched_comments.items():
369
369
370 %if c.user_session_attrs["diffmode"] == 'unified':
370 %if c.user_session_attrs["diffmode"] == 'unified':
371 % if loop.index == 0:
371 % if loop.index == 0:
372 <tr class="cb-hunk">
372 <tr class="cb-hunk">
373 <td colspan="3"></td>
373 <td colspan="3"></td>
374 <td>
374 <td>
375 <div>
375 <div>
376 ${_('Unmatched/outdated inline comments below')}
376 ${_('Unmatched/outdated inline comments below')}
377 </div>
377 </div>
378 </td>
378 </td>
379 </tr>
379 </tr>
380 % endif
380 % endif
381 <tr class="cb-line">
381 <tr class="cb-line">
382 <td class="cb-data cb-context"></td>
382 <td class="cb-data cb-context"></td>
383 <td class="cb-lineno cb-context"></td>
383 <td class="cb-lineno cb-context"></td>
384 <td class="cb-lineno cb-context"></td>
384 <td class="cb-lineno cb-context"></td>
385 <td class="cb-content cb-context">
385 <td class="cb-content cb-context">
386 ${inline_comments_container(comments, active_pattern_entries=active_pattern_entries)}
386 ${inline_comments_container(comments, active_pattern_entries=active_pattern_entries)}
387 </td>
387 </td>
388 </tr>
388 </tr>
389 %elif c.user_session_attrs["diffmode"] == 'sideside':
389 %elif c.user_session_attrs["diffmode"] == 'sideside':
390 % if loop.index == 0:
390 % if loop.index == 0:
391 <tr class="cb-comment-info">
391 <tr class="cb-comment-info">
392 <td colspan="2"></td>
392 <td colspan="2"></td>
393 <td class="cb-line">
393 <td class="cb-line">
394 <div>
394 <div>
395 ${_('Unmatched/outdated inline comments below')}
395 ${_('Unmatched/outdated inline comments below')}
396 </div>
396 </div>
397 </td>
397 </td>
398 <td colspan="2"></td>
398 <td colspan="2"></td>
399 <td class="cb-line">
399 <td class="cb-line">
400 <div>
400 <div>
401 ${_('Unmatched/outdated comments below')}
401 ${_('Unmatched/outdated comments below')}
402 </div>
402 </div>
403 </td>
403 </td>
404 </tr>
404 </tr>
405 % endif
405 % endif
406 <tr class="cb-line">
406 <tr class="cb-line">
407 <td class="cb-data cb-context"></td>
407 <td class="cb-data cb-context"></td>
408 <td class="cb-lineno cb-context"></td>
408 <td class="cb-lineno cb-context"></td>
409 <td class="cb-content cb-context">
409 <td class="cb-content cb-context">
410 % if lineno.startswith('o'):
410 % if lineno.startswith('o'):
411 ${inline_comments_container(comments, active_pattern_entries=active_pattern_entries)}
411 ${inline_comments_container(comments, active_pattern_entries=active_pattern_entries)}
412 % endif
412 % endif
413 </td>
413 </td>
414
414
415 <td class="cb-data cb-context"></td>
415 <td class="cb-data cb-context"></td>
416 <td class="cb-lineno cb-context"></td>
416 <td class="cb-lineno cb-context"></td>
417 <td class="cb-content cb-context">
417 <td class="cb-content cb-context">
418 % if lineno.startswith('n'):
418 % if lineno.startswith('n'):
419 ${inline_comments_container(comments, active_pattern_entries=active_pattern_entries)}
419 ${inline_comments_container(comments, active_pattern_entries=active_pattern_entries)}
420 % endif
420 % endif
421 </td>
421 </td>
422 </tr>
422 </tr>
423 %endif
423 %endif
424
424
425 % endfor
425 % endfor
426
426
427 </table>
427 </table>
428 </div>
428 </div>
429 %endfor
429 %endfor
430
430
431 ## outdated comments that are made for a file that has been deleted
431 ## outdated comments that are made for a file that has been deleted
432 % for filename, comments_dict in (deleted_files_comments or {}).items():
432 % for filename, comments_dict in (deleted_files_comments or {}).items():
433
433
434 <%
434 <%
435 display_state = 'display: none'
435 display_state = 'display: none'
436 open_comments_in_file = [x for x in comments_dict['comments'] if x.outdated is False]
436 open_comments_in_file = [x for x in comments_dict['comments'] if x.outdated is False]
437 if open_comments_in_file:
437 if open_comments_in_file:
438 display_state = ''
438 display_state = ''
439 fid = str(id(filename))
439 fid = str(id(filename))
440 %>
440 %>
441 <div class="filediffs filediff-outdated" style="${display_state}">
441 <div class="filediffs filediff-outdated" style="${display_state}">
442 <input ${(collapse_all and 'checked' or '')} class="filediff-collapse-state collapse-${diffset_container_id}" id="filediff-collapse-${id(filename)}" type="checkbox" onchange="updateSticky();">
442 <input ${(collapse_all and 'checked' or '')} class="filediff-collapse-state collapse-${diffset_container_id}" id="filediff-collapse-${id(filename)}" type="checkbox" onchange="updateSticky();">
443 <div class="filediff" data-f-path="${filename}" id="a_${h.FID(fid, filename)}">
443 <div class="filediff" data-f-path="${filename}" id="a_${h.FID(fid, filename)}">
444 <label for="filediff-collapse-${id(filename)}" class="filediff-heading">
444 <label for="filediff-collapse-${id(filename)}" class="filediff-heading">
445 <div class="filediff-collapse-indicator icon-"></div>
445 <div class="filediff-collapse-indicator icon-"></div>
446
446
447 <span class="pill">
447 <span class="pill">
448 ## file was deleted
448 ## file was deleted
449 ${filename}
449 ${filename}
450 </span>
450 </span>
451 <span class="pill-group pull-left" >
451 <span class="pill-group pull-left" >
452 ## file op, doesn't need translation
452 ## file op, doesn't need translation
453 <span class="pill" op="removed">unresolved comments</span>
453 <span class="pill" op="removed">unresolved comments</span>
454 </span>
454 </span>
455 <a class="pill filediff-anchor" href="#a_${h.FID(fid, filename)}">ΒΆ</a>
455 <a class="pill filediff-anchor" href="#a_${h.FID(fid, filename)}">ΒΆ</a>
456 <span class="pill-group pull-right">
456 <span class="pill-group pull-right">
457 <span class="pill" op="deleted">
457 <span class="pill" op="deleted">
458 % if comments_dict['stats'] >0:
458 % if comments_dict['stats'] >0:
459 -${comments_dict['stats']}
459 -${comments_dict['stats']}
460 % else:
460 % else:
461 ${comments_dict['stats']}
461 ${comments_dict['stats']}
462 % endif
462 % endif
463 </span>
463 </span>
464 </span>
464 </span>
465 </label>
465 </label>
466
466
467 <table class="cb cb-diff-${c.user_session_attrs["diffmode"]} code-highlight ${(over_lines_changed_limit and 'cb-collapsed' or '')}">
467 <table class="cb cb-diff-${c.user_session_attrs["diffmode"]} code-highlight ${(over_lines_changed_limit and 'cb-collapsed' or '')}">
468 <tr>
468 <tr>
469 % if c.user_session_attrs["diffmode"] == 'unified':
469 % if c.user_session_attrs["diffmode"] == 'unified':
470 <td></td>
470 <td></td>
471 %endif
471 %endif
472
472
473 <td></td>
473 <td></td>
474 <td class="cb-text cb-${op_class(BIN_FILENODE)}" ${(c.user_session_attrs["diffmode"] == 'unified' and 'colspan=4' or 'colspan=5')}>
474 <td class="cb-text cb-${op_class(BIN_FILENODE)}" ${(c.user_session_attrs["diffmode"] == 'unified' and 'colspan=4' or 'colspan=5')}>
475 <strong>${_('This file was removed from diff during updates to this pull-request.')}</strong><br/>
475 <strong>${_('This file was removed from diff during updates to this pull-request.')}</strong><br/>
476 ${_('There are still outdated/unresolved comments attached to it.')}
476 ${_('There are still outdated/unresolved comments attached to it.')}
477 </td>
477 </td>
478 </tr>
478 </tr>
479 %if c.user_session_attrs["diffmode"] == 'unified':
479 %if c.user_session_attrs["diffmode"] == 'unified':
480 <tr class="cb-line">
480 <tr class="cb-line">
481 <td class="cb-data cb-context"></td>
481 <td class="cb-data cb-context"></td>
482 <td class="cb-lineno cb-context"></td>
482 <td class="cb-lineno cb-context"></td>
483 <td class="cb-lineno cb-context"></td>
483 <td class="cb-lineno cb-context"></td>
484 <td class="cb-content cb-context">
484 <td class="cb-content cb-context">
485 ${inline_comments_container(comments_dict['comments'], active_pattern_entries=active_pattern_entries)}
485 ${inline_comments_container(comments_dict['comments'], active_pattern_entries=active_pattern_entries)}
486 </td>
486 </td>
487 </tr>
487 </tr>
488 %elif c.user_session_attrs["diffmode"] == 'sideside':
488 %elif c.user_session_attrs["diffmode"] == 'sideside':
489 <tr class="cb-line">
489 <tr class="cb-line">
490 <td class="cb-data cb-context"></td>
490 <td class="cb-data cb-context"></td>
491 <td class="cb-lineno cb-context"></td>
491 <td class="cb-lineno cb-context"></td>
492 <td class="cb-content cb-context"></td>
492 <td class="cb-content cb-context"></td>
493
493
494 <td class="cb-data cb-context"></td>
494 <td class="cb-data cb-context"></td>
495 <td class="cb-lineno cb-context"></td>
495 <td class="cb-lineno cb-context"></td>
496 <td class="cb-content cb-context">
496 <td class="cb-content cb-context">
497 ${inline_comments_container(comments_dict['comments'], active_pattern_entries=active_pattern_entries)}
497 ${inline_comments_container(comments_dict['comments'], active_pattern_entries=active_pattern_entries)}
498 </td>
498 </td>
499 </tr>
499 </tr>
500 %endif
500 %endif
501 </table>
501 </table>
502 </div>
502 </div>
503 </div>
503 </div>
504 % endfor
504 % endfor
505
505
506 </div>
506 </div>
507 </div>
507 </div>
508 </%def>
508 </%def>
509
509
510 <%def name="diff_ops(file_name, filediff)">
510 <%def name="diff_ops(file_name, filediff)">
511 <%
511 <%
512 from rhodecode.lib.diffs import NEW_FILENODE, DEL_FILENODE, \
512 from rhodecode.lib.diffs import NEW_FILENODE, DEL_FILENODE, \
513 MOD_FILENODE, RENAMED_FILENODE, CHMOD_FILENODE, BIN_FILENODE, COPIED_FILENODE
513 MOD_FILENODE, RENAMED_FILENODE, CHMOD_FILENODE, BIN_FILENODE, COPIED_FILENODE
514 %>
514 %>
515 <span class="pill">
515 <span class="pill">
516 <i class="icon-file-text"></i>
516 <i class="icon-file-text"></i>
517 ${file_name}
517 ${file_name}
518 </span>
518 </span>
519
519
520 <span class="pill-group pull-right">
520 <span class="pill-group pull-right">
521
521
522 ## ops pills
522 ## ops pills
523 %if filediff.limited_diff:
523 %if filediff.limited_diff:
524 <span class="pill tooltip" op="limited" title="The stats for this diff are not complete">limited diff</span>
524 <span class="pill tooltip" op="limited" title="The stats for this diff are not complete">limited diff</span>
525 %endif
525 %endif
526
526
527 %if NEW_FILENODE in filediff.patch['stats']['ops']:
527 %if NEW_FILENODE in filediff.patch['stats']['ops']:
528 <span class="pill" op="created">created</span>
528 <span class="pill" op="created">created</span>
529 %if filediff['target_mode'].startswith('120'):
529 %if filediff['target_mode'].startswith('120'):
530 <span class="pill" op="symlink">symlink</span>
530 <span class="pill" op="symlink">symlink</span>
531 %else:
531 %else:
532 <span class="pill" op="mode">${nice_mode(filediff['target_mode'])}</span>
532 <span class="pill" op="mode">${nice_mode(filediff['target_mode'])}</span>
533 %endif
533 %endif
534 %endif
534 %endif
535
535
536 %if RENAMED_FILENODE in filediff.patch['stats']['ops']:
536 %if RENAMED_FILENODE in filediff.patch['stats']['ops']:
537 <span class="pill" op="renamed">renamed</span>
537 <span class="pill" op="renamed">renamed</span>
538 %endif
538 %endif
539
539
540 %if COPIED_FILENODE in filediff.patch['stats']['ops']:
540 %if COPIED_FILENODE in filediff.patch['stats']['ops']:
541 <span class="pill" op="copied">copied</span>
541 <span class="pill" op="copied">copied</span>
542 %endif
542 %endif
543
543
544 %if DEL_FILENODE in filediff.patch['stats']['ops']:
544 %if DEL_FILENODE in filediff.patch['stats']['ops']:
545 <span class="pill" op="removed">removed</span>
545 <span class="pill" op="removed">removed</span>
546 %endif
546 %endif
547
547
548 %if CHMOD_FILENODE in filediff.patch['stats']['ops']:
548 %if CHMOD_FILENODE in filediff.patch['stats']['ops']:
549 <span class="pill" op="mode">
549 <span class="pill" op="mode">
550 ${nice_mode(filediff['source_mode'])} ➑ ${nice_mode(filediff['target_mode'])}
550 ${nice_mode(filediff['source_mode'])} ➑ ${nice_mode(filediff['target_mode'])}
551 </span>
551 </span>
552 %endif
552 %endif
553
553
554 %if BIN_FILENODE in filediff.patch['stats']['ops']:
554 %if BIN_FILENODE in filediff.patch['stats']['ops']:
555 <span class="pill" op="binary">binary</span>
555 <span class="pill" op="binary">binary</span>
556 %if MOD_FILENODE in filediff.patch['stats']['ops']:
556 %if MOD_FILENODE in filediff.patch['stats']['ops']:
557 <span class="pill" op="modified">modified</span>
557 <span class="pill" op="modified">modified</span>
558 %endif
558 %endif
559 %endif
559 %endif
560
560
561 <span class="pill" op="added">${('+' if filediff.patch['stats']['added'] else '')}${filediff.patch['stats']['added']}</span>
561 <span class="pill" op="added">${('+' if filediff.patch['stats']['added'] else '')}${filediff.patch['stats']['added']}</span>
562 <span class="pill" op="deleted">${((h.safe_int(filediff.patch['stats']['deleted']) or 0) * -1)}</span>
562 <span class="pill" op="deleted">${((h.safe_int(filediff.patch['stats']['deleted']) or 0) * -1)}</span>
563
563
564 </span>
564 </span>
565
565
566 </%def>
566 </%def>
567
567
568 <%def name="nice_mode(filemode)">
568 <%def name="nice_mode(filemode)">
569 ${(filemode.startswith('100') and filemode[3:] or filemode)}
569 ${(filemode.startswith('100') and filemode[3:] or filemode)}
570 </%def>
570 </%def>
571
571
572 <%def name="diff_menu(filediff, use_comments=False)">
572 <%def name="diff_menu(filediff, use_comments=False)">
573 <div class="filediff-menu">
573 <div class="filediff-menu">
574
574
575 %if filediff.diffset.source_ref:
575 %if filediff.diffset.source_ref:
576
576
577 ## FILE BEFORE CHANGES
577 ## FILE BEFORE CHANGES
578 %if filediff.operation in ['D', 'M']:
578 %if filediff.operation in ['D', 'M']:
579 <a
579 <a
580 class="tooltip"
580 class="tooltip"
581 href="${h.route_path('repo_files',repo_name=filediff.diffset.target_repo_name,commit_id=filediff.diffset.source_ref,f_path=filediff.source_file_path)}"
581 href="${h.route_path('repo_files',repo_name=filediff.diffset.target_repo_name,commit_id=filediff.diffset.source_ref,f_path=filediff.source_file_path)}"
582 title="${h.tooltip(_('Show file at commit: %(commit_id)s') % {'commit_id': filediff.diffset.source_ref[:12]})}"
582 title="${h.tooltip(_('Show file at commit: %(commit_id)s') % {'commit_id': filediff.diffset.source_ref[:12]})}"
583 >
583 >
584 ${_('Show file before')}
584 ${_('Show file before')}
585 </a> |
585 </a> |
586 %else:
586 %else:
587 <span
587 <span
588 class="tooltip"
588 class="tooltip"
589 title="${h.tooltip(_('File not present at commit: %(commit_id)s') % {'commit_id': filediff.diffset.source_ref[:12]})}"
589 title="${h.tooltip(_('File not present at commit: %(commit_id)s') % {'commit_id': filediff.diffset.source_ref[:12]})}"
590 >
590 >
591 ${_('Show file before')}
591 ${_('Show file before')}
592 </span> |
592 </span> |
593 %endif
593 %endif
594
594
595 ## FILE AFTER CHANGES
595 ## FILE AFTER CHANGES
596 %if filediff.operation in ['A', 'M']:
596 %if filediff.operation in ['A', 'M']:
597 <a
597 <a
598 class="tooltip"
598 class="tooltip"
599 href="${h.route_path('repo_files',repo_name=filediff.diffset.source_repo_name,commit_id=filediff.diffset.target_ref,f_path=filediff.target_file_path)}"
599 href="${h.route_path('repo_files',repo_name=filediff.diffset.source_repo_name,commit_id=filediff.diffset.target_ref,f_path=filediff.target_file_path)}"
600 title="${h.tooltip(_('Show file at commit: %(commit_id)s') % {'commit_id': filediff.diffset.target_ref[:12]})}"
600 title="${h.tooltip(_('Show file at commit: %(commit_id)s') % {'commit_id': filediff.diffset.target_ref[:12]})}"
601 >
601 >
602 ${_('Show file after')}
602 ${_('Show file after')}
603 </a>
603 </a>
604 %else:
604 %else:
605 <span
605 <span
606 class="tooltip"
606 class="tooltip"
607 title="${h.tooltip(_('File not present at commit: %(commit_id)s') % {'commit_id': filediff.diffset.target_ref[:12]})}"
607 title="${h.tooltip(_('File not present at commit: %(commit_id)s') % {'commit_id': filediff.diffset.target_ref[:12]})}"
608 >
608 >
609 ${_('Show file after')}
609 ${_('Show file after')}
610 </span>
610 </span>
611 %endif
611 %endif
612
612
613 % if use_comments:
613 % if use_comments:
614 |
614 |
615 <a href="#" onclick="Rhodecode.comments.toggleDiffComments(this);return toggleElement(this)"
615 <a href="#" onclick="Rhodecode.comments.toggleDiffComments(this);return toggleElement(this)"
616 data-toggle-on="${_('Hide comments')}"
616 data-toggle-on="${_('Hide comments')}"
617 data-toggle-off="${_('Show comments')}">
617 data-toggle-off="${_('Show comments')}">
618 <span class="hide-comment-button">${_('Hide comments')}</span>
618 <span class="hide-comment-button">${_('Hide comments')}</span>
619 </a>
619 </a>
620 % endif
620 % endif
621
621
622 %endif
622 %endif
623
623
624 </div>
624 </div>
625 </%def>
625 </%def>
626
626
627
627
628 <%def name="inline_comments_container(comments, active_pattern_entries=None, line_no='', f_path='')">
628 <%def name="inline_comments_container(comments, active_pattern_entries=None, line_no='', f_path='')">
629
629
630 <div class="inline-comments">
630 <div class="inline-comments">
631 %for comment in comments:
631 %for comment in comments:
632 ${commentblock.comment_block(comment, inline=True, active_pattern_entries=active_pattern_entries)}
632 ${commentblock.comment_block(comment, inline=True, active_pattern_entries=active_pattern_entries)}
633 %endfor
633 %endfor
634
634
635 <%
635 <%
636 extra_class = ''
636 extra_class = ''
637 extra_style = ''
637 extra_style = ''
638
638
639 if comments and comments[-1].outdated_at_version(c.at_version_num):
639 if comments and comments[-1].outdated_at_version(c.at_version_num):
640 extra_class = ' comment-outdated'
640 extra_class = ' comment-outdated'
641 extra_style = 'display: none;'
641 extra_style = 'display: none;'
642
642
643 %>
643 %>
644
644
645 <div class="reply-thread-container-wrapper${extra_class}" style="${extra_style}">
645 <div class="reply-thread-container-wrapper${extra_class}" style="${extra_style}">
646 <div class="reply-thread-container${extra_class}">
646 <div class="reply-thread-container${extra_class}">
647 <div class="reply-thread-gravatar">
647 <div class="reply-thread-gravatar">
648 % if c.rhodecode_user.username != h.DEFAULT_USER:
648 % if c.rhodecode_user.username != h.DEFAULT_USER:
649 ${base.gravatar(c.rhodecode_user.email, 20, tooltip=True, user=c.rhodecode_user)}
649 ${base.gravatar(c.rhodecode_user.email, 20, tooltip=True, user=c.rhodecode_user)}
650 % endif
650 % endif
651 </div>
651 </div>
652
652
653 <div class="reply-thread-reply-button">
653 <div class="reply-thread-reply-button">
654 % if c.rhodecode_user.username != h.DEFAULT_USER:
654 % if c.rhodecode_user.username != h.DEFAULT_USER:
655 ## initial reply button, some JS logic can append here a FORM to leave a first comment.
655 ## initial reply button, some JS logic can append here a FORM to leave a first comment.
656 <button class="cb-comment-add-button" onclick="return Rhodecode.comments.createComment(this, '${f_path}', '${line_no}', null)">Reply...</button>
656 <button class="cb-comment-add-button" onclick="return Rhodecode.comments.createComment(this, '${f_path}', '${line_no}', null)">Reply...</button>
657 % endif
657 % endif
658 </div>
658 </div>
659 ##% endif
659 ##% endif
660 <div class="reply-thread-last"></div>
660 <div class="reply-thread-last"></div>
661 </div>
661 </div>
662 </div>
662 </div>
663 </div>
663 </div>
664
664
665 </%def>
665 </%def>
666
666
667 <%!
667 <%!
668
668
669 def get_inline_comments(comments, filename):
669 def get_inline_comments(comments, filename):
670 if hasattr(filename, 'unicode_path'):
670 if hasattr(filename, 'unicode_path'):
671 filename = filename.unicode_path
671 filename = filename.unicode_path
672
672
673 if not isinstance(filename, str):
673 if not isinstance(filename, str):
674 return None
674 return None
675
675
676 if comments and filename in comments:
676 if comments and filename in comments:
677 return comments[filename]
677 return comments[filename]
678
678
679 return None
679 return None
680
680
681 def get_comments_for(diff_type, comments, filename, line_version, line_number):
681 def get_comments_for(diff_type, comments, filename, line_version, line_number):
682 if hasattr(filename, 'unicode_path'):
682 if hasattr(filename, 'unicode_path'):
683 filename = filename.unicode_path
683 filename = filename.unicode_path
684
684
685 if not isinstance(filename, str):
685 if not isinstance(filename, str):
686 return None
686 return None
687
687
688 file_comments = get_inline_comments(comments, filename)
688 file_comments = get_inline_comments(comments, filename)
689 if file_comments is None:
689 if file_comments is None:
690 return None
690 return None
691
691
692 line_key = '{}{}'.format(line_version, line_number) ## e.g o37, n12
692 line_key = '{}{}'.format(line_version, line_number) ## e.g o37, n12
693 if line_key in file_comments:
693 if line_key in file_comments:
694 data = file_comments.pop(line_key)
694 data = file_comments.pop(line_key)
695 return data
695 return data
696 %>
696 %>
697
697
698 <%def name="render_hunk_lines_sideside(filediff, hunk, use_comments=False, inline_comments=None, active_pattern_entries=None)">
698 <%def name="render_hunk_lines_sideside(filediff, hunk, use_comments=False, inline_comments=None, active_pattern_entries=None)">
699
699
700 <% chunk_count = 1 %>
700 <% chunk_count = 1 %>
701 %for loop_obj, item in h.looper(hunk.sideside):
701 %for loop_obj, item in h.looper(hunk.sideside):
702 <%
702 <%
703 line = item
703 line = item
704 i = loop_obj.index
704 i = loop_obj.index
705 prev_line = loop_obj.previous
705 prev_line = loop_obj.previous
706 old_line_anchor, new_line_anchor = None, None
706 old_line_anchor, new_line_anchor = None, None
707
707
708 if line.original.lineno:
708 if line.original.lineno:
709 old_line_anchor = diff_line_anchor(filediff.raw_id, hunk.source_file_path, line.original.lineno, 'o')
709 old_line_anchor = diff_line_anchor(filediff.raw_id, hunk.source_file_path, line.original.lineno, 'o')
710 if line.modified.lineno:
710 if line.modified.lineno:
711 new_line_anchor = diff_line_anchor(filediff.raw_id, hunk.target_file_path, line.modified.lineno, 'n')
711 new_line_anchor = diff_line_anchor(filediff.raw_id, hunk.target_file_path, line.modified.lineno, 'n')
712
712
713 line_action = line.modified.action or line.original.action
713 line_action = line.modified.action or line.original.action
714 prev_line_action = prev_line and (prev_line.modified.action or prev_line.original.action)
714 prev_line_action = prev_line and (prev_line.modified.action or prev_line.original.action)
715 %>
715 %>
716
716
717 <tr class="cb-line">
717 <tr class="cb-line">
718 <td class="cb-data ${action_class(line.original.action)}"
718 <td class="cb-data ${action_class(line.original.action)}"
719 data-line-no="${line.original.lineno}"
719 data-line-no="${line.original.lineno}"
720 >
720 >
721
721
722 <% line_old_comments, line_old_comments_no_drafts = None, None %>
722 <% line_old_comments, line_old_comments_no_drafts = None, None %>
723 %if line.original.get_comment_args:
723 %if line.original.get_comment_args:
724 <%
724 <%
725 line_old_comments = get_comments_for('side-by-side', inline_comments, *line.original.get_comment_args)
725 line_old_comments = get_comments_for('side-by-side', inline_comments, *line.original.get_comment_args)
726 line_old_comments_no_drafts = [c for c in line_old_comments if not c.draft] if line_old_comments else []
726 line_old_comments_no_drafts = [c for c in line_old_comments if not c.draft] if line_old_comments else []
727 has_outdated = any([x.outdated for x in line_old_comments_no_drafts])
727 has_outdated = any([x.outdated for x in line_old_comments_no_drafts])
728 %>
728 %>
729 %endif
729 %endif
730 %if line_old_comments_no_drafts:
730 %if line_old_comments_no_drafts:
731 % if has_outdated:
731 % if has_outdated:
732 <i class="tooltip toggle-comment-action icon-comment-toggle" title="${_('Comments including outdated: {}. Click here to toggle them.').format(len(line_old_comments_no_drafts))}" onclick="return Rhodecode.comments.toggleLineComments(this)"></i>
732 <i class="tooltip toggle-comment-action icon-comment-toggle" title="${_('Comments including outdated: {}. Click here to toggle them.').format(len(line_old_comments_no_drafts))}" onclick="return Rhodecode.comments.toggleLineComments(this)"></i>
733 % else:
733 % else:
734 <i class="tooltip toggle-comment-action icon-comment" title="${_('Comments: {}. Click to toggle them.').format(len(line_old_comments_no_drafts))}" onclick="return Rhodecode.comments.toggleLineComments(this)"></i>
734 <i class="tooltip toggle-comment-action icon-comment" title="${_('Comments: {}. Click to toggle them.').format(len(line_old_comments_no_drafts))}" onclick="return Rhodecode.comments.toggleLineComments(this)"></i>
735 % endif
735 % endif
736 %endif
736 %endif
737 </td>
737 </td>
738 <td class="cb-lineno ${action_class(line.original.action)}"
738 <td class="cb-lineno ${action_class(line.original.action)}"
739 data-line-no="${line.original.lineno}"
739 data-line-no="${line.original.lineno}"
740 %if old_line_anchor:
740 %if old_line_anchor:
741 id="${old_line_anchor}"
741 id="${old_line_anchor}"
742 %endif
742 %endif
743 >
743 >
744 %if line.original.lineno:
744 %if line.original.lineno:
745 <a name="${old_line_anchor}" href="#${old_line_anchor}">${line.original.lineno}</a>
745 <a name="${old_line_anchor}" href="#${old_line_anchor}">${line.original.lineno}</a>
746 %endif
746 %endif
747 </td>
747 </td>
748
748
749 <% line_no = 'o{}'.format(line.original.lineno) %>
749 <% line_no = 'o{}'.format(line.original.lineno) %>
750 <td class="cb-content ${action_class(line.original.action)}"
750 <td class="cb-content ${action_class(line.original.action)}"
751 data-line-no="${line_no}"
751 data-line-no="${line_no}"
752 >
752 >
753 %if use_comments and line.original.lineno:
753 %if use_comments and line.original.lineno:
754 ${render_add_comment_button(line_no=line_no, f_path=filediff.patch['filename'])}
754 ${render_add_comment_button(line_no=line_no, f_path=filediff.patch['filename'])}
755 %endif
755 %endif
756 <span class="cb-code"><span class="cb-action ${action_class(line.original.action)}"></span>${line.original.content or '' | n}</span>
756 <span class="cb-code"><span class="cb-action ${action_class(line.original.action)}"></span>${line.original.content or '' | n}</span>
757
757
758 %if use_comments and line.original.lineno and line_old_comments:
758 %if use_comments and line.original.lineno and line_old_comments:
759 ${inline_comments_container(line_old_comments, active_pattern_entries=active_pattern_entries, line_no=line_no, f_path=filediff.patch['filename'])}
759 ${inline_comments_container(line_old_comments, active_pattern_entries=active_pattern_entries, line_no=line_no, f_path=filediff.patch['filename'])}
760 %endif
760 %endif
761
761
762 </td>
762 </td>
763 <td class="cb-data ${action_class(line.modified.action)}"
763 <td class="cb-data ${action_class(line.modified.action)}"
764 data-line-no="${line.modified.lineno}"
764 data-line-no="${line.modified.lineno}"
765 >
765 >
766 <div>
766 <div>
767
767
768 <% line_new_comments, line_new_comments_no_drafts = None, None %>
768 <% line_new_comments, line_new_comments_no_drafts = None, None %>
769 %if line.modified.get_comment_args:
769 %if line.modified.get_comment_args:
770 <%
770 <%
771 line_new_comments = get_comments_for('side-by-side', inline_comments, *line.modified.get_comment_args)
771 line_new_comments = get_comments_for('side-by-side', inline_comments, *line.modified.get_comment_args)
772 line_new_comments_no_drafts = [c for c in line_new_comments if not c.draft] if line_new_comments else []
772 line_new_comments_no_drafts = [c for c in line_new_comments if not c.draft] if line_new_comments else []
773 has_outdated = any([x.outdated for x in line_new_comments_no_drafts])
773 has_outdated = any([x.outdated for x in line_new_comments_no_drafts])
774 %>
774 %>
775 %endif
775 %endif
776
776
777 %if line_new_comments_no_drafts:
777 %if line_new_comments_no_drafts:
778 % if has_outdated:
778 % if has_outdated:
779 <i class="tooltip toggle-comment-action icon-comment-toggle" title="${_('Comments including outdated: {}. Click here to toggle them.').format(len(line_new_comments_no_drafts))}" onclick="return Rhodecode.comments.toggleLineComments(this)"></i>
779 <i class="tooltip toggle-comment-action icon-comment-toggle" title="${_('Comments including outdated: {}. Click here to toggle them.').format(len(line_new_comments_no_drafts))}" onclick="return Rhodecode.comments.toggleLineComments(this)"></i>
780 % else:
780 % else:
781 <i class="tooltip toggle-comment-action icon-comment" title="${_('Comments: {}. Click to toggle them.').format(len(line_new_comments_no_drafts))}" onclick="return Rhodecode.comments.toggleLineComments(this)"></i>
781 <i class="tooltip toggle-comment-action icon-comment" title="${_('Comments: {}. Click to toggle them.').format(len(line_new_comments_no_drafts))}" onclick="return Rhodecode.comments.toggleLineComments(this)"></i>
782 % endif
782 % endif
783 %endif
783 %endif
784 </div>
784 </div>
785 </td>
785 </td>
786 <td class="cb-lineno ${action_class(line.modified.action)}"
786 <td class="cb-lineno ${action_class(line.modified.action)}"
787 data-line-no="${line.modified.lineno}"
787 data-line-no="${line.modified.lineno}"
788 %if new_line_anchor:
788 %if new_line_anchor:
789 id="${new_line_anchor}"
789 id="${new_line_anchor}"
790 %endif
790 %endif
791 >
791 >
792 %if line.modified.lineno:
792 %if line.modified.lineno:
793 <a name="${new_line_anchor}" href="#${new_line_anchor}">${line.modified.lineno}</a>
793 <a name="${new_line_anchor}" href="#${new_line_anchor}">${line.modified.lineno}</a>
794 %endif
794 %endif
795 </td>
795 </td>
796
796
797 <% line_no = 'n{}'.format(line.modified.lineno) %>
797 <% line_no = 'n{}'.format(line.modified.lineno) %>
798 <td class="cb-content ${action_class(line.modified.action)}"
798 <td class="cb-content ${action_class(line.modified.action)}"
799 data-line-no="${line_no}"
799 data-line-no="${line_no}"
800 >
800 >
801 %if use_comments and line.modified.lineno:
801 %if use_comments and line.modified.lineno:
802 ${render_add_comment_button(line_no=line_no, f_path=filediff.patch['filename'])}
802 ${render_add_comment_button(line_no=line_no, f_path=filediff.patch['filename'])}
803 %endif
803 %endif
804 <span class="cb-code"><span class="cb-action ${action_class(line.modified.action)}"></span>${line.modified.content or '' | n}</span>
804 <span class="cb-code"><span class="cb-action ${action_class(line.modified.action)}"></span>${line.modified.content or '' | n}</span>
805 % if line_action in ['+', '-'] and prev_line_action not in ['+', '-']:
805 % if line_action in ['+', '-'] and prev_line_action not in ['+', '-']:
806 <div class="nav-chunk" style="visibility: hidden">
806 <div class="nav-chunk" style="visibility: hidden">
807 <i class="icon-eye" title="viewing diff hunk-${hunk.index}-${chunk_count}"></i>
807 <i class="icon-eye" title="viewing diff hunk-${hunk.index}-${chunk_count}"></i>
808 </div>
808 </div>
809 <% chunk_count +=1 %>
809 <% chunk_count +=1 %>
810 % endif
810 % endif
811 %if use_comments and line.modified.lineno and line_new_comments:
811 %if use_comments and line.modified.lineno and line_new_comments:
812 ${inline_comments_container(line_new_comments, active_pattern_entries=active_pattern_entries, line_no=line_no, f_path=filediff.patch['filename'])}
812 ${inline_comments_container(line_new_comments, active_pattern_entries=active_pattern_entries, line_no=line_no, f_path=filediff.patch['filename'])}
813 %endif
813 %endif
814
814
815 </td>
815 </td>
816 </tr>
816 </tr>
817 %endfor
817 %endfor
818 </%def>
818 </%def>
819
819
820
820
821 <%def name="render_hunk_lines_unified(filediff, hunk, use_comments=False, inline_comments=None, active_pattern_entries=None)">
821 <%def name="render_hunk_lines_unified(filediff, hunk, use_comments=False, inline_comments=None, active_pattern_entries=None)">
822 %for old_line_no, new_line_no, action, content, comments_args in hunk.unified:
822 %for old_line_no, new_line_no, action, content, comments_args in hunk.unified:
823
823
824 <%
824 <%
825 old_line_anchor, new_line_anchor = None, None
825 old_line_anchor, new_line_anchor = None, None
826 if old_line_no:
826 if old_line_no:
827 old_line_anchor = diff_line_anchor(filediff.raw_id, hunk.source_file_path, old_line_no, 'o')
827 old_line_anchor = diff_line_anchor(filediff.raw_id, hunk.source_file_path, old_line_no, 'o')
828 if new_line_no:
828 if new_line_no:
829 new_line_anchor = diff_line_anchor(filediff.raw_id, hunk.target_file_path, new_line_no, 'n')
829 new_line_anchor = diff_line_anchor(filediff.raw_id, hunk.target_file_path, new_line_no, 'n')
830 %>
830 %>
831 <tr class="cb-line">
831 <tr class="cb-line">
832 <td class="cb-data ${action_class(action)}">
832 <td class="cb-data ${action_class(action)}">
833 <div>
833 <div>
834
834
835 <% comments, comments_no_drafts = None, None %>
835 <% comments, comments_no_drafts = None, None %>
836 %if comments_args:
836 %if comments_args:
837 <%
837 <%
838 comments = get_comments_for('unified', inline_comments, *comments_args)
838 comments = get_comments_for('unified', inline_comments, *comments_args)
839 comments_no_drafts = [c for c in line_new_comments if not c.draft] if line_new_comments else []
839 comments_no_drafts = [c for c in line_new_comments if not c.draft] if line_new_comments else []
840 has_outdated = any([x.outdated for x in comments_no_drafts])
840 has_outdated = any([x.outdated for x in comments_no_drafts])
841 %>
841 %>
842 %endif
842 %endif
843
843
844 % if comments_no_drafts:
844 % if comments_no_drafts:
845 % if has_outdated:
845 % if has_outdated:
846 <i class="tooltip toggle-comment-action icon-comment-toggle" title="${_('Comments including outdated: {}. Click here to toggle them.').format(len(comments_no_drafts))}" onclick="return Rhodecode.comments.toggleLineComments(this)"></i>
846 <i class="tooltip toggle-comment-action icon-comment-toggle" title="${_('Comments including outdated: {}. Click here to toggle them.').format(len(comments_no_drafts))}" onclick="return Rhodecode.comments.toggleLineComments(this)"></i>
847 % else:
847 % else:
848 <i class="tooltip toggle-comment-action icon-comment" title="${_('Comments: {}. Click to toggle them.').format(len(comments_no_drafts))}" onclick="return Rhodecode.comments.toggleLineComments(this)"></i>
848 <i class="tooltip toggle-comment-action icon-comment" title="${_('Comments: {}. Click to toggle them.').format(len(comments_no_drafts))}" onclick="return Rhodecode.comments.toggleLineComments(this)"></i>
849 % endif
849 % endif
850 % endif
850 % endif
851 </div>
851 </div>
852 </td>
852 </td>
853 <td class="cb-lineno ${action_class(action)}"
853 <td class="cb-lineno ${action_class(action)}"
854 data-line-no="${old_line_no}"
854 data-line-no="${old_line_no}"
855 %if old_line_anchor:
855 %if old_line_anchor:
856 id="${old_line_anchor}"
856 id="${old_line_anchor}"
857 %endif
857 %endif
858 >
858 >
859 %if old_line_anchor:
859 %if old_line_anchor:
860 <a name="${old_line_anchor}" href="#${old_line_anchor}">${old_line_no}</a>
860 <a name="${old_line_anchor}" href="#${old_line_anchor}">${old_line_no}</a>
861 %endif
861 %endif
862 </td>
862 </td>
863 <td class="cb-lineno ${action_class(action)}"
863 <td class="cb-lineno ${action_class(action)}"
864 data-line-no="${new_line_no}"
864 data-line-no="${new_line_no}"
865 %if new_line_anchor:
865 %if new_line_anchor:
866 id="${new_line_anchor}"
866 id="${new_line_anchor}"
867 %endif
867 %endif
868 >
868 >
869 %if new_line_anchor:
869 %if new_line_anchor:
870 <a name="${new_line_anchor}" href="#${new_line_anchor}">${new_line_no}</a>
870 <a name="${new_line_anchor}" href="#${new_line_anchor}">${new_line_no}</a>
871 %endif
871 %endif
872 </td>
872 </td>
873 <% line_no = '{}{}'.format(new_line_no and 'n' or 'o', new_line_no or old_line_no) %>
873 <% line_no = '{}{}'.format(new_line_no and 'n' or 'o', new_line_no or old_line_no) %>
874 <td class="cb-content ${action_class(action)}"
874 <td class="cb-content ${action_class(action)}"
875 data-line-no="${line_no}"
875 data-line-no="${line_no}"
876 >
876 >
877 %if use_comments:
877 %if use_comments:
878 ${render_add_comment_button(line_no=line_no, f_path=filediff.patch['filename'])}
878 ${render_add_comment_button(line_no=line_no, f_path=filediff.patch['filename'])}
879 %endif
879 %endif
880 <span class="cb-code"><span class="cb-action ${action_class(action)}"></span> ${content or '' | n}</span>
880 <span class="cb-code"><span class="cb-action ${action_class(action)}"></span> ${content or '' | n}</span>
881 %if use_comments and comments:
881 %if use_comments and comments:
882 ${inline_comments_container(comments, active_pattern_entries=active_pattern_entries, line_no=line_no, f_path=filediff.patch['filename'])}
882 ${inline_comments_container(comments, active_pattern_entries=active_pattern_entries, line_no=line_no, f_path=filediff.patch['filename'])}
883 %endif
883 %endif
884 </td>
884 </td>
885 </tr>
885 </tr>
886 %endfor
886 %endfor
887 </%def>
887 </%def>
888
888
889
889
890 <%def name="render_hunk_lines(filediff, diff_mode, hunk, use_comments, inline_comments, active_pattern_entries)">
890 <%def name="render_hunk_lines(filediff, diff_mode, hunk, use_comments, inline_comments, active_pattern_entries)">
891 % if diff_mode == 'unified':
891 % if diff_mode == 'unified':
892 ${render_hunk_lines_unified(filediff, hunk, use_comments=use_comments, inline_comments=inline_comments, active_pattern_entries=active_pattern_entries)}
892 ${render_hunk_lines_unified(filediff, hunk, use_comments=use_comments, inline_comments=inline_comments, active_pattern_entries=active_pattern_entries)}
893 % elif diff_mode == 'sideside':
893 % elif diff_mode == 'sideside':
894 ${render_hunk_lines_sideside(filediff, hunk, use_comments=use_comments, inline_comments=inline_comments, active_pattern_entries=active_pattern_entries)}
894 ${render_hunk_lines_sideside(filediff, hunk, use_comments=use_comments, inline_comments=inline_comments, active_pattern_entries=active_pattern_entries)}
895 % else:
895 % else:
896 <tr class="cb-line">
896 <tr class="cb-line">
897 <td>unknown diff mode</td>
897 <td>unknown diff mode</td>
898 </tr>
898 </tr>
899 % endif
899 % endif
900 </%def>file changes
900 </%def>file changes
901
901
902
902
903 <%def name="render_add_comment_button(line_no='', f_path='')">
903 <%def name="render_add_comment_button(line_no='', f_path='')">
904 % if not c.rhodecode_user.is_default:
904 % if not c.rhodecode_user.is_default:
905 <button class="btn btn-small btn-primary cb-comment-box-opener" onclick="return Rhodecode.comments.createComment(this, '${f_path}', '${line_no}', null)">
905 <button class="btn btn-small btn-primary cb-comment-box-opener" onclick="return Rhodecode.comments.createComment(this, '${f_path}', '${line_no}', null)">
906 <span><i class="icon-comment"></i></span>
906 <span><i class="icon-comment"></i></span>
907 </button>
907 </button>
908 % endif
908 % endif
909 </%def>
909 </%def>
910
910
911 <%def name="render_diffset_menu(diffset, range_diff_on=None, commit=None, pull_request_menu=None)">
911 <%def name="render_diffset_menu(diffset, range_diff_on=None, commit=None, pull_request_menu=None)">
912 <% diffset_container_id = h.md5(diffset.target_ref) %>
912 <% diffset_container_id = h.md5_safe(diffset.target_ref) %>
913
913
914 <div id="diff-file-sticky" class="diffset-menu clearinner">
914 <div id="diff-file-sticky" class="diffset-menu clearinner">
915 ## auto adjustable
915 ## auto adjustable
916 <div class="sidebar__inner">
916 <div class="sidebar__inner">
917 <div class="sidebar__bar">
917 <div class="sidebar__bar">
918 <div class="pull-right">
918 <div class="pull-right">
919
919
920 <div class="btn-group" style="margin-right: 5px;">
920 <div class="btn-group" style="margin-right: 5px;">
921 <a class="tooltip btn" onclick="scrollDown();return false" title="${_('Scroll to page bottom')}">
921 <a class="tooltip btn" onclick="scrollDown();return false" title="${_('Scroll to page bottom')}">
922 <i class="icon-arrow_down"></i>
922 <i class="icon-arrow_down"></i>
923 </a>
923 </a>
924 <a class="tooltip btn" onclick="scrollUp();return false" title="${_('Scroll to page top')}">
924 <a class="tooltip btn" onclick="scrollUp();return false" title="${_('Scroll to page top')}">
925 <i class="icon-arrow_up"></i>
925 <i class="icon-arrow_up"></i>
926 </a>
926 </a>
927 </div>
927 </div>
928
928
929 <div class="btn-group">
929 <div class="btn-group">
930 <a class="btn tooltip toggle-wide-diff" href="#toggle-wide-diff" onclick="toggleWideDiff(this); return false" title="${h.tooltip(_('Toggle wide diff'))}">
930 <a class="btn tooltip toggle-wide-diff" href="#toggle-wide-diff" onclick="toggleWideDiff(this); return false" title="${h.tooltip(_('Toggle wide diff'))}">
931 <i class="icon-wide-mode"></i>
931 <i class="icon-wide-mode"></i>
932 </a>
932 </a>
933 </div>
933 </div>
934 <div class="btn-group">
934 <div class="btn-group">
935
935
936 <a
936 <a
937 class="btn ${(c.user_session_attrs["diffmode"] == 'sideside' and 'btn-active')} tooltip"
937 class="btn ${(c.user_session_attrs["diffmode"] == 'sideside' and 'btn-active')} tooltip"
938 title="${h.tooltip(_('View diff as side by side'))}"
938 title="${h.tooltip(_('View diff as side by side'))}"
939 href="${h.current_route_path(request, diffmode='sideside')}">
939 href="${h.current_route_path(request, diffmode='sideside')}">
940 <span>${_('Side by Side')}</span>
940 <span>${_('Side by Side')}</span>
941 </a>
941 </a>
942
942
943 <a
943 <a
944 class="btn ${(c.user_session_attrs["diffmode"] == 'unified' and 'btn-active')} tooltip"
944 class="btn ${(c.user_session_attrs["diffmode"] == 'unified' and 'btn-active')} tooltip"
945 title="${h.tooltip(_('View diff as unified'))}" href="${h.current_route_path(request, diffmode='unified')}">
945 title="${h.tooltip(_('View diff as unified'))}" href="${h.current_route_path(request, diffmode='unified')}">
946 <span>${_('Unified')}</span>
946 <span>${_('Unified')}</span>
947 </a>
947 </a>
948
948
949 % if range_diff_on is True:
949 % if range_diff_on is True:
950 <a
950 <a
951 title="${_('Turn off: Show the diff as commit range')}"
951 title="${_('Turn off: Show the diff as commit range')}"
952 class="btn btn-primary"
952 class="btn btn-primary"
953 href="${h.current_route_path(request, **{"range-diff":"0"})}">
953 href="${h.current_route_path(request, **{"range-diff":"0"})}">
954 <span>${_('Range Diff')}</span>
954 <span>${_('Range Diff')}</span>
955 </a>
955 </a>
956 % elif range_diff_on is False:
956 % elif range_diff_on is False:
957 <a
957 <a
958 title="${_('Show the diff as commit range')}"
958 title="${_('Show the diff as commit range')}"
959 class="btn"
959 class="btn"
960 href="${h.current_route_path(request, **{"range-diff":"1"})}">
960 href="${h.current_route_path(request, **{"range-diff":"1"})}">
961 <span>${_('Range Diff')}</span>
961 <span>${_('Range Diff')}</span>
962 </a>
962 </a>
963 % endif
963 % endif
964 </div>
964 </div>
965 <div class="btn-group">
965 <div class="btn-group">
966
966
967 <details class="details-reset details-inline-block">
967 <details class="details-reset details-inline-block">
968 <summary class="noselect btn">
968 <summary class="noselect btn">
969 <i class="icon-options cursor-pointer" op="options"></i>
969 <i class="icon-options cursor-pointer" op="options"></i>
970 </summary>
970 </summary>
971
971
972 <div>
972 <div>
973 <details-menu class="details-dropdown" style="top: 35px;">
973 <details-menu class="details-dropdown" style="top: 35px;">
974
974
975 <div class="dropdown-item">
975 <div class="dropdown-item">
976 <div style="padding: 2px 0px">
976 <div style="padding: 2px 0px">
977 % if request.GET.get('ignorews', '') == '1':
977 % if request.GET.get('ignorews', '') == '1':
978 <a href="${h.current_route_path(request, ignorews=0)}">${_('Show whitespace changes')}</a>
978 <a href="${h.current_route_path(request, ignorews=0)}">${_('Show whitespace changes')}</a>
979 % else:
979 % else:
980 <a href="${h.current_route_path(request, ignorews=1)}">${_('Hide whitespace changes')}</a>
980 <a href="${h.current_route_path(request, ignorews=1)}">${_('Hide whitespace changes')}</a>
981 % endif
981 % endif
982 </div>
982 </div>
983 </div>
983 </div>
984
984
985 <div class="dropdown-item">
985 <div class="dropdown-item">
986 <div style="padding: 2px 0px">
986 <div style="padding: 2px 0px">
987 % if request.GET.get('fullcontext', '') == '1':
987 % if request.GET.get('fullcontext', '') == '1':
988 <a href="${h.current_route_path(request, fullcontext=0)}">${_('Hide full context diff')}</a>
988 <a href="${h.current_route_path(request, fullcontext=0)}">${_('Hide full context diff')}</a>
989 % else:
989 % else:
990 <a href="${h.current_route_path(request, fullcontext=1)}">${_('Show full context diff')}</a>
990 <a href="${h.current_route_path(request, fullcontext=1)}">${_('Show full context diff')}</a>
991 % endif
991 % endif
992 </div>
992 </div>
993 </div>
993 </div>
994
994
995 </details-menu>
995 </details-menu>
996 </div>
996 </div>
997 </details>
997 </details>
998
998
999 </div>
999 </div>
1000 </div>
1000 </div>
1001 <div class="pull-left">
1001 <div class="pull-left">
1002 <div class="btn-group">
1002 <div class="btn-group">
1003 <div class="pull-left">
1003 <div class="pull-left">
1004 ${h.hidden('file_filter_{}'.format(diffset_container_id))}
1004 ${h.hidden('file_filter_{}'.format(diffset_container_id))}
1005 </div>
1005 </div>
1006
1006
1007 </div>
1007 </div>
1008 </div>
1008 </div>
1009 </div>
1009 </div>
1010 <div class="fpath-placeholder pull-left">
1010 <div class="fpath-placeholder pull-left">
1011 <i class="icon-file-text"></i>
1011 <i class="icon-file-text"></i>
1012 <strong class="fpath-placeholder-text">
1012 <strong class="fpath-placeholder-text">
1013 Context file:
1013 Context file:
1014 </strong>
1014 </strong>
1015 </div>
1015 </div>
1016 <div class="pull-right noselect">
1016 <div class="pull-right noselect">
1017 %if commit:
1017 %if commit:
1018 <span>
1018 <span>
1019 <code>${h.show_id(commit)}</code>
1019 <code>${h.show_id(commit)}</code>
1020 </span>
1020 </span>
1021 %elif pull_request_menu and pull_request_menu.get('pull_request'):
1021 %elif pull_request_menu and pull_request_menu.get('pull_request'):
1022 <span>
1022 <span>
1023 <code>!${pull_request_menu['pull_request'].pull_request_id}</code>
1023 <code>!${pull_request_menu['pull_request'].pull_request_id}</code>
1024 </span>
1024 </span>
1025 %endif
1025 %endif
1026 % if commit or pull_request_menu:
1026 % if commit or pull_request_menu:
1027 <span class="tooltip" title="Navigate to previous or next change inside files." id="diff_nav">Loading diff...:</span>
1027 <span class="tooltip" title="Navigate to previous or next change inside files." id="diff_nav">Loading diff...:</span>
1028 <span class="cursor-pointer" onclick="scrollToPrevChunk(); return false">
1028 <span class="cursor-pointer" onclick="scrollToPrevChunk(); return false">
1029 <i class="icon-angle-up"></i>
1029 <i class="icon-angle-up"></i>
1030 </span>
1030 </span>
1031 <span class="cursor-pointer" onclick="scrollToNextChunk(); return false">
1031 <span class="cursor-pointer" onclick="scrollToNextChunk(); return false">
1032 <i class="icon-angle-down"></i>
1032 <i class="icon-angle-down"></i>
1033 </span>
1033 </span>
1034 % endif
1034 % endif
1035 </div>
1035 </div>
1036 <div class="sidebar_inner_shadow"></div>
1036 <div class="sidebar_inner_shadow"></div>
1037 </div>
1037 </div>
1038 </div>
1038 </div>
1039
1039
1040 % if diffset:
1040 % if diffset:
1041 %if diffset.limited_diff:
1041 %if diffset.limited_diff:
1042 <% file_placeholder = _ungettext('%(num)s file changed', '%(num)s files changed', diffset.changed_files) % {'num': diffset.changed_files} %>
1042 <% file_placeholder = _ungettext('%(num)s file changed', '%(num)s files changed', diffset.changed_files) % {'num': diffset.changed_files} %>
1043 %else:
1043 %else:
1044 <% file_placeholder = h.literal(_ungettext('%(num)s file changed: <span class="op-added">%(linesadd)s inserted</span>, <span class="op-deleted">%(linesdel)s deleted</span>', '%(num)s files changed: <span class="op-added">%(linesadd)s inserted</span>, <span class="op-deleted">%(linesdel)s deleted</span>',
1044 <% file_placeholder = h.literal(_ungettext('%(num)s file changed: <span class="op-added">%(linesadd)s inserted</span>, <span class="op-deleted">%(linesdel)s deleted</span>', '%(num)s files changed: <span class="op-added">%(linesadd)s inserted</span>, <span class="op-deleted">%(linesdel)s deleted</span>',
1045 diffset.changed_files) % {'num': diffset.changed_files, 'linesadd': diffset.lines_added, 'linesdel': diffset.lines_deleted}) %>
1045 diffset.changed_files) % {'num': diffset.changed_files, 'linesadd': diffset.lines_added, 'linesdel': diffset.lines_deleted}) %>
1046
1046
1047 %endif
1047 %endif
1048 ## case on range-diff placeholder needs to be updated
1048 ## case on range-diff placeholder needs to be updated
1049 % if range_diff_on is True:
1049 % if range_diff_on is True:
1050 <% file_placeholder = _('Disabled on range diff') %>
1050 <% file_placeholder = _('Disabled on range diff') %>
1051 % endif
1051 % endif
1052
1052
1053 <script type="text/javascript">
1053 <script type="text/javascript">
1054 var feedFilesOptions = function (query, initialData) {
1054 var feedFilesOptions = function (query, initialData) {
1055 var data = {results: []};
1055 var data = {results: []};
1056 var isQuery = typeof query.term !== 'undefined';
1056 var isQuery = typeof query.term !== 'undefined';
1057
1057
1058 var section = _gettext('Changed files');
1058 var section = _gettext('Changed files');
1059 var filteredData = [];
1059 var filteredData = [];
1060
1060
1061 //filter results
1061 //filter results
1062 $.each(initialData.results, function (idx, value) {
1062 $.each(initialData.results, function (idx, value) {
1063
1063
1064 if (!isQuery || query.term.length === 0 || value.text.toUpperCase().indexOf(query.term.toUpperCase()) >= 0) {
1064 if (!isQuery || query.term.length === 0 || value.text.toUpperCase().indexOf(query.term.toUpperCase()) >= 0) {
1065 filteredData.push({
1065 filteredData.push({
1066 'id': this.id,
1066 'id': this.id,
1067 'text': this.text,
1067 'text': this.text,
1068 "ops": this.ops,
1068 "ops": this.ops,
1069 })
1069 })
1070 }
1070 }
1071
1071
1072 });
1072 });
1073
1073
1074 data.results = filteredData;
1074 data.results = filteredData;
1075
1075
1076 query.callback(data);
1076 query.callback(data);
1077 };
1077 };
1078
1078
1079 var selectionFormatter = function(data, escapeMarkup) {
1079 var selectionFormatter = function(data, escapeMarkup) {
1080 var container = '<div class="filelist" style="padding-right:100px">{0}</div>';
1080 var container = '<div class="filelist" style="padding-right:100px">{0}</div>';
1081 var tmpl = '<div><strong>{0}</strong></div>'.format(escapeMarkup(data['text']));
1081 var tmpl = '<div><strong>{0}</strong></div>'.format(escapeMarkup(data['text']));
1082 var pill = '<div class="pill-group" style="position: absolute; top:7px; right: 0">' +
1082 var pill = '<div class="pill-group" style="position: absolute; top:7px; right: 0">' +
1083 '<span class="pill" op="added">{0}</span>' +
1083 '<span class="pill" op="added">{0}</span>' +
1084 '<span class="pill" op="deleted">{1}</span>' +
1084 '<span class="pill" op="deleted">{1}</span>' +
1085 '</div>'
1085 '</div>'
1086 ;
1086 ;
1087 var added = data['ops']['added'];
1087 var added = data['ops']['added'];
1088 if (added === 0) {
1088 if (added === 0) {
1089 // don't show +0
1089 // don't show +0
1090 added = 0;
1090 added = 0;
1091 } else {
1091 } else {
1092 added = '+' + added;
1092 added = '+' + added;
1093 }
1093 }
1094
1094
1095 var deleted = -1*data['ops']['deleted'];
1095 var deleted = -1*data['ops']['deleted'];
1096
1096
1097 tmpl += pill.format(added, deleted);
1097 tmpl += pill.format(added, deleted);
1098 return container.format(tmpl);
1098 return container.format(tmpl);
1099 };
1099 };
1100 var formatFileResult = function(result, container, query, escapeMarkup) {
1100 var formatFileResult = function(result, container, query, escapeMarkup) {
1101 return selectionFormatter(result, escapeMarkup);
1101 return selectionFormatter(result, escapeMarkup);
1102 };
1102 };
1103
1103
1104 var formatSelection = function (data, container) {
1104 var formatSelection = function (data, container) {
1105 return '${file_placeholder}'
1105 return '${file_placeholder}'
1106 };
1106 };
1107
1107
1108 if (window.preloadFileFilterData === undefined) {
1108 if (window.preloadFileFilterData === undefined) {
1109 window.preloadFileFilterData = {}
1109 window.preloadFileFilterData = {}
1110 }
1110 }
1111
1111
1112 preloadFileFilterData["${diffset_container_id}"] = {
1112 preloadFileFilterData["${diffset_container_id}"] = {
1113 results: [
1113 results: [
1114 % for filediff in diffset.files:
1114 % for filediff in diffset.files:
1115 {id:"a_${h.FID(filediff.raw_id, filediff.patch['filename'])}",
1115 {id:"a_${h.FID(filediff.raw_id, filediff.patch['filename'])}",
1116 text:"${filediff.patch['filename']}",
1116 text:"${filediff.patch['filename']}",
1117 ops:${h.str_json(filediff.patch['stats'])|n}}${('' if loop.last else ',')}
1117 ops:${h.str_json(filediff.patch['stats'])|n}}${('' if loop.last else ',')}
1118 % endfor
1118 % endfor
1119 ]
1119 ]
1120 };
1120 };
1121
1121
1122 var diffFileFilterId = "#file_filter_" + "${diffset_container_id}";
1122 var diffFileFilterId = "#file_filter_" + "${diffset_container_id}";
1123 var diffFileFilter = $(diffFileFilterId).select2({
1123 var diffFileFilter = $(diffFileFilterId).select2({
1124 'dropdownAutoWidth': true,
1124 'dropdownAutoWidth': true,
1125 'width': 'auto',
1125 'width': 'auto',
1126
1126
1127 containerCssClass: "drop-menu",
1127 containerCssClass: "drop-menu",
1128 dropdownCssClass: "drop-menu-dropdown",
1128 dropdownCssClass: "drop-menu-dropdown",
1129 data: preloadFileFilterData["${diffset_container_id}"],
1129 data: preloadFileFilterData["${diffset_container_id}"],
1130 query: function(query) {
1130 query: function(query) {
1131 feedFilesOptions(query, preloadFileFilterData["${diffset_container_id}"]);
1131 feedFilesOptions(query, preloadFileFilterData["${diffset_container_id}"]);
1132 },
1132 },
1133 initSelection: function(element, callback) {
1133 initSelection: function(element, callback) {
1134 callback({'init': true});
1134 callback({'init': true});
1135 },
1135 },
1136 formatResult: formatFileResult,
1136 formatResult: formatFileResult,
1137 formatSelection: formatSelection
1137 formatSelection: formatSelection
1138 });
1138 });
1139
1139
1140 % if range_diff_on is True:
1140 % if range_diff_on is True:
1141 diffFileFilter.select2("enable", false);
1141 diffFileFilter.select2("enable", false);
1142 % endif
1142 % endif
1143
1143
1144 $(diffFileFilterId).on('select2-selecting', function (e) {
1144 $(diffFileFilterId).on('select2-selecting', function (e) {
1145 var idSelector = e.choice.id;
1145 var idSelector = e.choice.id;
1146
1146
1147 // expand the container if we quick-select the field
1147 // expand the container if we quick-select the field
1148 $('#'+idSelector).next().prop('checked', false);
1148 $('#'+idSelector).next().prop('checked', false);
1149 // hide the mast as we later do preventDefault()
1149 // hide the mast as we later do preventDefault()
1150 $("#select2-drop-mask").click();
1150 $("#select2-drop-mask").click();
1151
1151
1152 window.location.hash = '#'+idSelector;
1152 window.location.hash = '#'+idSelector;
1153 updateSticky();
1153 updateSticky();
1154
1154
1155 e.preventDefault();
1155 e.preventDefault();
1156 });
1156 });
1157
1157
1158 diffNavText = 'diff navigation:'
1158 diffNavText = 'diff navigation:'
1159
1159
1160 getCurrentChunk = function () {
1160 getCurrentChunk = function () {
1161
1161
1162 var chunksAll = $('.nav-chunk').filter(function () {
1162 var chunksAll = $('.nav-chunk').filter(function () {
1163 return $(this).parents('.filediff').prev().get(0).checked !== true
1163 return $(this).parents('.filediff').prev().get(0).checked !== true
1164 })
1164 })
1165 var chunkSelected = $('.nav-chunk.selected');
1165 var chunkSelected = $('.nav-chunk.selected');
1166 var initial = false;
1166 var initial = false;
1167
1167
1168 if (chunkSelected.length === 0) {
1168 if (chunkSelected.length === 0) {
1169 // no initial chunk selected, we pick first
1169 // no initial chunk selected, we pick first
1170 chunkSelected = $(chunksAll.get(0));
1170 chunkSelected = $(chunksAll.get(0));
1171 var initial = true;
1171 var initial = true;
1172 }
1172 }
1173
1173
1174 return {
1174 return {
1175 'all': chunksAll,
1175 'all': chunksAll,
1176 'selected': chunkSelected,
1176 'selected': chunkSelected,
1177 'initial': initial,
1177 'initial': initial,
1178 }
1178 }
1179 }
1179 }
1180
1180
1181 animateDiffNavText = function () {
1181 animateDiffNavText = function () {
1182 var $diffNav = $('#diff_nav')
1182 var $diffNav = $('#diff_nav')
1183
1183
1184 var callback = function () {
1184 var callback = function () {
1185 $diffNav.animate({'opacity': 1.00}, 200)
1185 $diffNav.animate({'opacity': 1.00}, 200)
1186 };
1186 };
1187 $diffNav.animate({'opacity': 0.15}, 200, callback);
1187 $diffNav.animate({'opacity': 0.15}, 200, callback);
1188 }
1188 }
1189
1189
1190 scrollToChunk = function (moveBy) {
1190 scrollToChunk = function (moveBy) {
1191 var chunk = getCurrentChunk();
1191 var chunk = getCurrentChunk();
1192 var all = chunk.all
1192 var all = chunk.all
1193 var selected = chunk.selected
1193 var selected = chunk.selected
1194
1194
1195 var curPos = all.index(selected);
1195 var curPos = all.index(selected);
1196 var newPos = curPos;
1196 var newPos = curPos;
1197 if (!chunk.initial) {
1197 if (!chunk.initial) {
1198 var newPos = curPos + moveBy;
1198 var newPos = curPos + moveBy;
1199 }
1199 }
1200
1200
1201 var curElem = all.get(newPos);
1201 var curElem = all.get(newPos);
1202
1202
1203 if (curElem === undefined) {
1203 if (curElem === undefined) {
1204 // end or back
1204 // end or back
1205 $('#diff_nav').html('no next diff element:')
1205 $('#diff_nav').html('no next diff element:')
1206 animateDiffNavText()
1206 animateDiffNavText()
1207 return
1207 return
1208 } else if (newPos < 0) {
1208 } else if (newPos < 0) {
1209 $('#diff_nav').html('no previous diff element:')
1209 $('#diff_nav').html('no previous diff element:')
1210 animateDiffNavText()
1210 animateDiffNavText()
1211 return
1211 return
1212 } else {
1212 } else {
1213 $('#diff_nav').html(diffNavText)
1213 $('#diff_nav').html(diffNavText)
1214 }
1214 }
1215
1215
1216 curElem = $(curElem)
1216 curElem = $(curElem)
1217 var offset = 100;
1217 var offset = 100;
1218 $(window).scrollTop(curElem.position().top - offset);
1218 $(window).scrollTop(curElem.position().top - offset);
1219
1219
1220 //clear selection
1220 //clear selection
1221 all.removeClass('selected')
1221 all.removeClass('selected')
1222 curElem.addClass('selected')
1222 curElem.addClass('selected')
1223 }
1223 }
1224
1224
1225 scrollToPrevChunk = function () {
1225 scrollToPrevChunk = function () {
1226 scrollToChunk(-1)
1226 scrollToChunk(-1)
1227 }
1227 }
1228 scrollToNextChunk = function () {
1228 scrollToNextChunk = function () {
1229 scrollToChunk(1)
1229 scrollToChunk(1)
1230 }
1230 }
1231
1231
1232 </script>
1232 </script>
1233 % endif
1233 % endif
1234
1234
1235 <script type="text/javascript">
1235 <script type="text/javascript">
1236 $('#diff_nav').html('loading diff...') // wait until whole page is loaded
1236 $('#diff_nav').html('loading diff...') // wait until whole page is loaded
1237
1237
1238 $(document).ready(function () {
1238 $(document).ready(function () {
1239
1239
1240 var contextPrefix = _gettext('Context file: ');
1240 var contextPrefix = _gettext('Context file: ');
1241 ## sticky sidebar
1241 ## sticky sidebar
1242 var sidebarElement = document.getElementById('diff-file-sticky');
1242 var sidebarElement = document.getElementById('diff-file-sticky');
1243 sidebar = new StickySidebar(sidebarElement, {
1243 sidebar = new StickySidebar(sidebarElement, {
1244 topSpacing: 0,
1244 topSpacing: 0,
1245 bottomSpacing: 0,
1245 bottomSpacing: 0,
1246 innerWrapperSelector: '.sidebar__inner'
1246 innerWrapperSelector: '.sidebar__inner'
1247 });
1247 });
1248 sidebarElement.addEventListener('affixed.static.stickySidebar', function () {
1248 sidebarElement.addEventListener('affixed.static.stickySidebar', function () {
1249 // reset our file so it's not holding new value
1249 // reset our file so it's not holding new value
1250 $('.fpath-placeholder-text').html(contextPrefix + ' - ')
1250 $('.fpath-placeholder-text').html(contextPrefix + ' - ')
1251 });
1251 });
1252
1252
1253 updateSticky = function () {
1253 updateSticky = function () {
1254 sidebar.updateSticky();
1254 sidebar.updateSticky();
1255 Waypoint.refreshAll();
1255 Waypoint.refreshAll();
1256 };
1256 };
1257
1257
1258 var animateText = function (fPath, anchorId) {
1258 var animateText = function (fPath, anchorId) {
1259 fPath = Select2.util.escapeMarkup(fPath);
1259 fPath = Select2.util.escapeMarkup(fPath);
1260 $('.fpath-placeholder-text').html(contextPrefix + '<a href="#a_' + anchorId + '">' + fPath + '</a>')
1260 $('.fpath-placeholder-text').html(contextPrefix + '<a href="#a_' + anchorId + '">' + fPath + '</a>')
1261 };
1261 };
1262
1262
1263 ## dynamic file waypoints
1263 ## dynamic file waypoints
1264 var setFPathInfo = function(fPath, anchorId){
1264 var setFPathInfo = function(fPath, anchorId){
1265 animateText(fPath, anchorId)
1265 animateText(fPath, anchorId)
1266 };
1266 };
1267
1267
1268 var codeBlock = $('.filediff');
1268 var codeBlock = $('.filediff');
1269
1269
1270 // forward waypoint
1270 // forward waypoint
1271 codeBlock.waypoint(
1271 codeBlock.waypoint(
1272 function(direction) {
1272 function(direction) {
1273 if (direction === "down"){
1273 if (direction === "down"){
1274 setFPathInfo($(this.element).data('fPath'), $(this.element).data('anchorId'))
1274 setFPathInfo($(this.element).data('fPath'), $(this.element).data('anchorId'))
1275 }
1275 }
1276 }, {
1276 }, {
1277 offset: function () {
1277 offset: function () {
1278 return 70;
1278 return 70;
1279 },
1279 },
1280 context: '.fpath-placeholder'
1280 context: '.fpath-placeholder'
1281 }
1281 }
1282 );
1282 );
1283
1283
1284 // backward waypoint
1284 // backward waypoint
1285 codeBlock.waypoint(
1285 codeBlock.waypoint(
1286 function(direction) {
1286 function(direction) {
1287 if (direction === "up"){
1287 if (direction === "up"){
1288 setFPathInfo($(this.element).data('fPath'), $(this.element).data('anchorId'))
1288 setFPathInfo($(this.element).data('fPath'), $(this.element).data('anchorId'))
1289 }
1289 }
1290 }, {
1290 }, {
1291 offset: function () {
1291 offset: function () {
1292 return -this.element.clientHeight + 90;
1292 return -this.element.clientHeight + 90;
1293 },
1293 },
1294 context: '.fpath-placeholder'
1294 context: '.fpath-placeholder'
1295 }
1295 }
1296 );
1296 );
1297
1297
1298 toggleWideDiff = function (el) {
1298 toggleWideDiff = function (el) {
1299 updateSticky();
1299 updateSticky();
1300 var wide = Rhodecode.comments.toggleWideMode(this);
1300 var wide = Rhodecode.comments.toggleWideMode(this);
1301 storeUserSessionAttr('rc_user_session_attr.wide_diff_mode', wide);
1301 storeUserSessionAttr('rc_user_session_attr.wide_diff_mode', wide);
1302 if (wide === true) {
1302 if (wide === true) {
1303 $(el).addClass('btn-active');
1303 $(el).addClass('btn-active');
1304 } else {
1304 } else {
1305 $(el).removeClass('btn-active');
1305 $(el).removeClass('btn-active');
1306 }
1306 }
1307 return null;
1307 return null;
1308 };
1308 };
1309
1309
1310 toggleExpand = function (el, diffsetEl) {
1310 toggleExpand = function (el, diffsetEl) {
1311 var el = $(el);
1311 var el = $(el);
1312 if (el.hasClass('collapsed')) {
1312 if (el.hasClass('collapsed')) {
1313 $('.filediff-collapse-state.collapse-{0}'.format(diffsetEl)).prop('checked', false);
1313 $('.filediff-collapse-state.collapse-{0}'.format(diffsetEl)).prop('checked', false);
1314 el.removeClass('collapsed');
1314 el.removeClass('collapsed');
1315 el.html(
1315 el.html(
1316 '<i class="icon-minus-squared-alt icon-no-margin"></i>' +
1316 '<i class="icon-minus-squared-alt icon-no-margin"></i>' +
1317 _gettext('Collapse all files'));
1317 _gettext('Collapse all files'));
1318 }
1318 }
1319 else {
1319 else {
1320 $('.filediff-collapse-state.collapse-{0}'.format(diffsetEl)).prop('checked', true);
1320 $('.filediff-collapse-state.collapse-{0}'.format(diffsetEl)).prop('checked', true);
1321 el.addClass('collapsed');
1321 el.addClass('collapsed');
1322 el.html(
1322 el.html(
1323 '<i class="icon-plus-squared-alt icon-no-margin"></i>' +
1323 '<i class="icon-plus-squared-alt icon-no-margin"></i>' +
1324 _gettext('Expand all files'));
1324 _gettext('Expand all files'));
1325 }
1325 }
1326 updateSticky()
1326 updateSticky()
1327 };
1327 };
1328
1328
1329 toggleCommitExpand = function (el) {
1329 toggleCommitExpand = function (el) {
1330 var $el = $(el);
1330 var $el = $(el);
1331 var commits = $el.data('toggleCommitsCnt');
1331 var commits = $el.data('toggleCommitsCnt');
1332 var collapseMsg = _ngettext('Collapse {0} commit', 'Collapse {0} commits', commits).format(commits);
1332 var collapseMsg = _ngettext('Collapse {0} commit', 'Collapse {0} commits', commits).format(commits);
1333 var expandMsg = _ngettext('Expand {0} commit', 'Expand {0} commits', commits).format(commits);
1333 var expandMsg = _ngettext('Expand {0} commit', 'Expand {0} commits', commits).format(commits);
1334
1334
1335 if ($el.hasClass('collapsed')) {
1335 if ($el.hasClass('collapsed')) {
1336 $('.compare_select').show();
1336 $('.compare_select').show();
1337 $('.compare_select_hidden').hide();
1337 $('.compare_select_hidden').hide();
1338
1338
1339 $el.removeClass('collapsed');
1339 $el.removeClass('collapsed');
1340 $el.html(
1340 $el.html(
1341 '<i class="icon-minus-squared-alt icon-no-margin"></i>' +
1341 '<i class="icon-minus-squared-alt icon-no-margin"></i>' +
1342 collapseMsg);
1342 collapseMsg);
1343 }
1343 }
1344 else {
1344 else {
1345 $('.compare_select').hide();
1345 $('.compare_select').hide();
1346 $('.compare_select_hidden').show();
1346 $('.compare_select_hidden').show();
1347 $el.addClass('collapsed');
1347 $el.addClass('collapsed');
1348 $el.html(
1348 $el.html(
1349 '<i class="icon-plus-squared-alt icon-no-margin"></i>' +
1349 '<i class="icon-plus-squared-alt icon-no-margin"></i>' +
1350 expandMsg);
1350 expandMsg);
1351 }
1351 }
1352 updateSticky();
1352 updateSticky();
1353 };
1353 };
1354
1354
1355 // get stored diff mode and pre-enable it
1355 // get stored diff mode and pre-enable it
1356 if (templateContext.session_attrs.wide_diff_mode === "true") {
1356 if (templateContext.session_attrs.wide_diff_mode === "true") {
1357 Rhodecode.comments.toggleWideMode(null);
1357 Rhodecode.comments.toggleWideMode(null);
1358 $('.toggle-wide-diff').addClass('btn-active');
1358 $('.toggle-wide-diff').addClass('btn-active');
1359 updateSticky();
1359 updateSticky();
1360 }
1360 }
1361
1361
1362 // DIFF NAV //
1362 // DIFF NAV //
1363
1363
1364 // element to detect scroll direction of
1364 // element to detect scroll direction of
1365 var $window = $(window);
1365 var $window = $(window);
1366
1366
1367 // initialize last scroll position
1367 // initialize last scroll position
1368 var lastScrollY = $window.scrollTop();
1368 var lastScrollY = $window.scrollTop();
1369
1369
1370 $window.on('resize scrollstop', {latency: 350}, function () {
1370 $window.on('resize scrollstop', {latency: 350}, function () {
1371 var visibleChunks = $('.nav-chunk').withinviewport({top: 75});
1371 var visibleChunks = $('.nav-chunk').withinviewport({top: 75});
1372
1372
1373 // get current scroll position
1373 // get current scroll position
1374 var currentScrollY = $window.scrollTop();
1374 var currentScrollY = $window.scrollTop();
1375
1375
1376 // determine current scroll direction
1376 // determine current scroll direction
1377 if (currentScrollY > lastScrollY) {
1377 if (currentScrollY > lastScrollY) {
1378 var y = 'down'
1378 var y = 'down'
1379 } else if (currentScrollY !== lastScrollY) {
1379 } else if (currentScrollY !== lastScrollY) {
1380 var y = 'up';
1380 var y = 'up';
1381 }
1381 }
1382
1382
1383 var pos = -1; // by default we use last element in viewport
1383 var pos = -1; // by default we use last element in viewport
1384 if (y === 'down') {
1384 if (y === 'down') {
1385 pos = -1;
1385 pos = -1;
1386 } else if (y === 'up') {
1386 } else if (y === 'up') {
1387 pos = 0;
1387 pos = 0;
1388 }
1388 }
1389
1389
1390 if (visibleChunks.length > 0) {
1390 if (visibleChunks.length > 0) {
1391 $('.nav-chunk').removeClass('selected');
1391 $('.nav-chunk').removeClass('selected');
1392 $(visibleChunks.get(pos)).addClass('selected');
1392 $(visibleChunks.get(pos)).addClass('selected');
1393 }
1393 }
1394
1394
1395 // update last scroll position to current position
1395 // update last scroll position to current position
1396 lastScrollY = currentScrollY;
1396 lastScrollY = currentScrollY;
1397
1397
1398 });
1398 });
1399 $('#diff_nav').html(diffNavText);
1399 $('#diff_nav').html(diffNavText);
1400
1400
1401 });
1401 });
1402 </script>
1402 </script>
1403
1403
1404 </%def>
1404 </%def>
General Comments 0
You need to be logged in to leave comments. Login now