##// END OF EJS Templates
templates: few small UI fixes
super-admin -
r5046:0c2a09c8 default
parent child Browse files
Show More
@@ -1,1262 +1,1261 b''
1
1
2 <%!
2 <%!
3 from rhodecode.lib import html_filters
3 from rhodecode.lib import html_filters
4 %>
4 %>
5
5
6 <%inherit file="root.mako"/>
6 <%inherit file="root.mako"/>
7
7
8 <%include file="/ejs_templates/templates.html"/>
8 <%include file="/ejs_templates/templates.html"/>
9
9
10 <div class="outerwrapper">
10 <div class="outerwrapper">
11 <!-- HEADER -->
11 <!-- HEADER -->
12 <div class="header">
12 <div class="header">
13 <div id="header-inner" class="wrapper">
13 <div id="header-inner" class="wrapper">
14 <div id="logo">
14 <div id="logo">
15 <div class="logo-wrapper">
15 <div class="logo-wrapper">
16 <a href="${h.route_path('home')}"><img src="${h.asset('images/rhodecode-logo-white-60x60.png')}" alt="RhodeCode"/></a>
16 <a href="${h.route_path('home')}"><img src="${h.asset('images/rhodecode-logo-white-60x60.png')}" alt="RhodeCode"/></a>
17 </div>
17 </div>
18 % if c.rhodecode_name:
18 % if c.rhodecode_name:
19 <div class="branding">
19 <div class="branding">
20 <a href="${h.route_path('home')}">${h.branding(c.rhodecode_name)}</a>
20 <a href="${h.route_path('home')}">${h.branding(c.rhodecode_name)}</a>
21 </div>
21 </div>
22 % endif
22 % endif
23 </div>
23 </div>
24 <!-- MENU BAR NAV -->
24 <!-- MENU BAR NAV -->
25 ${self.menu_bar_nav()}
25 ${self.menu_bar_nav()}
26 <!-- END MENU BAR NAV -->
26 <!-- END MENU BAR NAV -->
27 </div>
27 </div>
28 </div>
28 </div>
29 ${self.menu_bar_subnav()}
29 ${self.menu_bar_subnav()}
30 <!-- END HEADER -->
30 <!-- END HEADER -->
31
31
32 <!-- CONTENT -->
32 <!-- CONTENT -->
33 <div id="content" class="wrapper">
33 <div id="content" class="wrapper">
34
34
35 <rhodecode-toast id="notifications"></rhodecode-toast>
35 <rhodecode-toast id="notifications"></rhodecode-toast>
36
36
37 <div class="main">
37 <div class="main">
38 ${next.main()}
38 ${next.main()}
39 </div>
39 </div>
40
40
41 </div>
41 </div>
42 <!-- END CONTENT -->
42 <!-- END CONTENT -->
43
43
44 </div>
44 </div>
45
45
46 <!-- FOOTER -->
46 <!-- FOOTER -->
47 <div id="footer">
47 <div id="footer">
48 <div id="footer-inner" class="title wrapper">
48 <div id="footer-inner" class="title wrapper">
49 <div>
49 <div>
50 <% sid = 'block' if request.GET.get('showrcid') else 'none' %>
50 <% sid = 'block' if request.GET.get('showrcid') else 'none' %>
51
51
52 <p class="footer-link-right">
52 <p class="footer-link-right">
53 <a class="grey-link-action" href="${h.route_path('home', _query={'showrcid': 1})}">
53 <a class="grey-link-action" href="${h.route_path('home', _query={'showrcid': 1})}">
54 RhodeCode
54 RhodeCode
55 % if c.visual.show_version:
55 % if c.visual.show_version:
56 ${c.rhodecode_version}
56 ${c.rhodecode_version}
57 % endif
57 % endif
58 ${c.rhodecode_edition}
58 ${c.rhodecode_edition}
59 </a> |
59 </a> |
60
60
61 % if c.visual.rhodecode_support_url:
61 % if c.visual.rhodecode_support_url:
62 <a class="grey-link-action" href="${c.visual.rhodecode_support_url}" target="_blank">${_('Support')}</a> |
62 <a class="grey-link-action" href="${c.visual.rhodecode_support_url}" target="_blank">${_('Support')}</a> |
63 <a class="grey-link-action" href="https://docs.rhodecode.com" target="_blank">${_('Documentation')}</a>
63 <a class="grey-link-action" href="https://docs.rhodecode.com" target="_blank">${_('Documentation')}</a>
64 % endif
64 % endif
65
65
66 </p>
66 </p>
67
67
68 <p class="server-instance" style="display:${sid}">
68 <p class="server-instance" style="display:${sid}">
69 ## display hidden instance ID if specially defined
69 ## display hidden instance ID if specially defined
70 &copy; 2010-${h.datetime.today().year}, <a href="${h.route_url('rhodecode_official')}" target="_blank">RhodeCode GmbH</a>. All rights reserved.
70 &copy; 2010-${h.datetime.today().year}, <a href="${h.route_url('rhodecode_official')}" target="_blank">RhodeCode GmbH</a>. All rights reserved.
71 % if c.rhodecode_instanceid:
71 % if c.rhodecode_instanceid:
72 ${_('RhodeCode instance id: {}').format(c.rhodecode_instanceid)}
72 ${_('RhodeCode instance id: {}').format(c.rhodecode_instanceid)}
73 % endif
73 % endif
74 </p>
74 </p>
75 </div>
75 </div>
76 </div>
76 </div>
77 </div>
77 </div>
78
78
79 <!-- END FOOTER -->
79 <!-- END FOOTER -->
80
80
81 ### MAKO DEFS ###
81 ### MAKO DEFS ###
82
82
83 <%def name="menu_bar_subnav()">
83 <%def name="menu_bar_subnav()">
84 </%def>
84 </%def>
85
85
86 <%def name="breadcrumbs(class_='breadcrumbs')">
86 <%def name="breadcrumbs(class_='breadcrumbs')">
87 <div class="${class_}">
87 <div class="${class_}">
88 ${self.breadcrumbs_links()}
88 ${self.breadcrumbs_links()}
89 </div>
89 </div>
90 </%def>
90 </%def>
91
91
92 <%def name="admin_menu(active=None)">
92 <%def name="admin_menu(active=None)">
93
93
94 <div id="context-bar">
94 <div id="context-bar">
95 <div class="wrapper">
95 <div class="wrapper">
96 <div class="title">
96 <div class="title">
97 <div class="title-content">
97 <div class="title-content">
98 <div class="title-main">
98 <div class="title-main">
99 % if c.is_super_admin:
99 % if c.is_super_admin:
100 ${_('Super-admin Panel')}
100 ${_('Super-admin Panel')}
101 % else:
101 % else:
102 ${_('Delegated Admin Panel')}
102 ${_('Delegated Admin Panel')}
103 % endif
103 % endif
104 </div>
104 </div>
105 </div>
105 </div>
106 </div>
106 </div>
107
107
108 <ul id="context-pages" class="navigation horizontal-list">
108 <ul id="context-pages" class="navigation horizontal-list">
109
109
110 ## super-admin case
110 ## super-admin case
111 % if c.is_super_admin:
111 % if c.is_super_admin:
112 <li class="${h.is_active('audit_logs', active)}"><a href="${h.route_path('admin_audit_logs')}">${_('Admin audit logs')}</a></li>
112 <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('repositories', active)}"><a href="${h.route_path('repos')}">${_('Repositories')}</a></li>
113 <li class="${h.is_active('repositories', active)}"><a href="${h.route_path('repos')}">${_('Repositories')}</a></li>
114 <li class="${h.is_active('repository_groups', active)}"><a href="${h.route_path('repo_groups')}">${_('Repository groups')}</a></li>
114 <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('users', active)}"><a href="${h.route_path('users')}">${_('Users')}</a></li>
115 <li class="${h.is_active('users', active)}"><a href="${h.route_path('users')}">${_('Users')}</a></li>
116 <li class="${h.is_active('user_groups', active)}"><a href="${h.route_path('user_groups')}">${_('User groups')}</a></li>
116 <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('artifacts', active)}"><a href="${h.route_path('admin_artifacts')}">${_('Artifacts')}</a></li>
117 <li class="${h.is_active('artifacts', active)}"><a href="${h.route_path('admin_artifacts')}">${_('Artifacts')}</a></li>
118 <li class="${h.is_active('permissions', active)}"><a href="${h.route_path('admin_permissions_application')}">${_('Permissions')}</a></li>
118 <li class="${h.is_active('permissions', active)}"><a href="${h.route_path('admin_permissions_application')}">${_('Permissions')}</a></li>
119 <li class="${h.is_active('authentication', active)}"><a href="${h.route_path('auth_home', traverse='')}">${_('Authentication')}</a></li>
119 <li class="${h.is_active('authentication', active)}"><a href="${h.route_path('auth_home', traverse='')}">${_('Authentication')}</a></li>
120 <li class="${h.is_active('integrations', active)}"><a href="${h.route_path('global_integrations_home')}">${_('Integrations')}</a></li>
120 <li class="${h.is_active('integrations', active)}"><a href="${h.route_path('global_integrations_home')}">${_('Integrations')}</a></li>
121 <li class="${h.is_active('defaults', active)}"><a href="${h.route_path('admin_defaults_repositories')}">${_('Defaults')}</a></li>
121 <li class="${h.is_active('defaults', active)}"><a href="${h.route_path('admin_defaults_repositories')}">${_('Defaults')}</a></li>
122 <li class="${h.is_active('settings', active)}"><a href="${h.route_path('admin_settings')}">${_('Settings')}</a></li>
122 <li class="${h.is_active('settings', active)}"><a href="${h.route_path('admin_settings')}">${_('Settings')}</a></li>
123
123
124 ## delegated admin
124 ## delegated admin
125 % elif c.is_delegated_admin:
125 % elif c.is_delegated_admin:
126 <%
126 <%
127 repositories=c.auth_user.repositories_admin or c.can_create_repo
127 repositories=c.auth_user.repositories_admin or c.can_create_repo
128 repository_groups=c.auth_user.repository_groups_admin or c.can_create_repo_group
128 repository_groups=c.auth_user.repository_groups_admin or c.can_create_repo_group
129 user_groups=c.auth_user.user_groups_admin or c.can_create_user_group
129 user_groups=c.auth_user.user_groups_admin or c.can_create_user_group
130 %>
130 %>
131
131
132 %if repositories:
132 %if repositories:
133 <li class="${h.is_active('repositories', active)} local-admin-repos"><a href="${h.route_path('repos')}">${_('Repositories')}</a></li>
133 <li class="${h.is_active('repositories', active)} local-admin-repos"><a href="${h.route_path('repos')}">${_('Repositories')}</a></li>
134 %endif
134 %endif
135 %if repository_groups:
135 %if repository_groups:
136 <li class="${h.is_active('repository_groups', active)} local-admin-repo-groups"><a href="${h.route_path('repo_groups')}">${_('Repository groups')}</a></li>
136 <li class="${h.is_active('repository_groups', active)} local-admin-repo-groups"><a href="${h.route_path('repo_groups')}">${_('Repository groups')}</a></li>
137 %endif
137 %endif
138 %if user_groups:
138 %if user_groups:
139 <li class="${h.is_active('user_groups', active)} local-admin-user-groups"><a href="${h.route_path('user_groups')}">${_('User groups')}</a></li>
139 <li class="${h.is_active('user_groups', active)} local-admin-user-groups"><a href="${h.route_path('user_groups')}">${_('User groups')}</a></li>
140 %endif
140 %endif
141 % endif
141 % endif
142 </ul>
142 </ul>
143
143
144 </div>
144 </div>
145 <div class="clear"></div>
145 <div class="clear"></div>
146 </div>
146 </div>
147 </%def>
147 </%def>
148
148
149 <%def name="dt_info_panel(elements)">
149 <%def name="dt_info_panel(elements)">
150 <dl class="dl-horizontal">
150 <dl class="dl-horizontal">
151 %for dt, dd, title, show_items in elements:
151 %for dt, dd, title, show_items in elements:
152 <dt>${dt}:</dt>
152 <dt>${dt}:</dt>
153 <dd title="${h.tooltip(title)}">
153 <dd title="${h.tooltip(title)}">
154 %if callable(dd):
154 %if callable(dd):
155 ## allow lazy evaluation of elements
155 ## allow lazy evaluation of elements
156 ${dd()}
156 ${dd()}
157 %else:
157 %else:
158 ${dd}
158 ${dd}
159 %endif
159 %endif
160 %if show_items:
160 %if show_items:
161 <span class="btn-collapse" data-toggle="item-${h.md5_safe(dt)[:6]}-details">${_('Show More')} </span>
161 <span class="btn-collapse" data-toggle="item-${h.md5_safe(dt)[:6]}-details">${_('Show More')} </span>
162 %endif
162 %endif
163 </dd>
163 </dd>
164
164
165 %if show_items:
165 %if show_items:
166 <div class="collapsable-content" data-toggle="item-${h.md5_safe(dt)[:6]}-details" style="display: none">
166 <div class="collapsable-content" data-toggle="item-${h.md5_safe(dt)[:6]}-details" style="display: none">
167 %for item in show_items:
167 %for item in show_items:
168 <dt></dt>
168 <dt></dt>
169 <dd>${item}</dd>
169 <dd>${item}</dd>
170 %endfor
170 %endfor
171 </div>
171 </div>
172 %endif
172 %endif
173
173
174 %endfor
174 %endfor
175 </dl>
175 </dl>
176 </%def>
176 </%def>
177
177
178 <%def name="tr_info_entry(element)">
178 <%def name="tr_info_entry(element)">
179 <% key, val, title, show_items = element %>
179 <% key, val, title, show_items = element %>
180
180
181 <tr>
181 <tr>
182 <td style="vertical-align: top">${key}</td>
182 <td style="vertical-align: top">${key}</td>
183 <td title="${h.tooltip(title)}">
183 <td title="${h.tooltip(title)}">
184 %if callable(val):
184 %if callable(val):
185 ## allow lazy evaluation of elements
185 ## allow lazy evaluation of elements
186 ${val()}
186 ${val()}
187 %else:
187 %else:
188 ${val}
188 ${val}
189 %endif
189 %endif
190 %if show_items:
190 %if show_items:
191 <div class="collapsable-content" data-toggle="item-${h.md5_safe(h.safe_str(val))[:6]}-details" style="display: none">
191 <div class="collapsable-content" data-toggle="item-${h.md5_safe(h.safe_str(val))[:6]}-details" style="display: none">
192 % for item in show_items:
192 % for item in show_items:
193 <dt></dt>
193 <dt></dt>
194 <dd>${item}</dd>
194 <dd>${item}</dd>
195 % endfor
195 % endfor
196 </div>
196 </div>
197 %endif
197 %endif
198 </td>
198 </td>
199 <td style="vertical-align: top">
199 <td style="vertical-align: top">
200 %if show_items:
200 %if show_items:
201 <span class="btn-collapse" data-toggle="item-${h.md5_safe(h.safe_str(val))[:6]}-details">${_('Show More')} </span>
201 <span class="btn-collapse" data-toggle="item-${h.md5_safe(h.safe_str(val))[:6]}-details">${_('Show More')} </span>
202 %endif
202 %endif
203 </td>
203 </td>
204 </tr>
204 </tr>
205
205
206 </%def>
206 </%def>
207
207
208 <%def name="gravatar(email, size=16, tooltip=False, tooltip_alt=None, user=None, extra_class=None)">
208 <%def name="gravatar(email, size=16, tooltip=False, tooltip_alt=None, user=None, extra_class=None)">
209 <%
209 <%
210 if size > 16:
210 if size > 16:
211 gravatar_class = ['gravatar','gravatar-large']
211 gravatar_class = ['gravatar','gravatar-large']
212 else:
212 else:
213 gravatar_class = ['gravatar']
213 gravatar_class = ['gravatar']
214
214
215 data_hovercard_url = ''
215 data_hovercard_url = ''
216 data_hovercard_alt = tooltip_alt.replace('<', '&lt;').replace('>', '&gt;') if tooltip_alt else ''
216 data_hovercard_alt = tooltip_alt.replace('<', '&lt;').replace('>', '&gt;') if tooltip_alt else ''
217
217
218 if tooltip:
218 if tooltip:
219 gravatar_class += ['tooltip-hovercard']
219 gravatar_class += ['tooltip-hovercard']
220 if extra_class:
220 if extra_class:
221 gravatar_class += extra_class
221 gravatar_class += extra_class
222 if tooltip and user:
222 if tooltip and user:
223 if user.username == h.DEFAULT_USER:
223 if user.username == h.DEFAULT_USER:
224 gravatar_class.pop(-1)
224 gravatar_class.pop(-1)
225 else:
225 else:
226 data_hovercard_url = request.route_path('hovercard_user', user_id=getattr(user, 'user_id', ''))
226 data_hovercard_url = request.route_path('hovercard_user', user_id=getattr(user, 'user_id', ''))
227 gravatar_class = ' '.join(gravatar_class)
227 gravatar_class = ' '.join(gravatar_class)
228
228
229 %>
229 %>
230 <%doc>
230 <%doc>
231 TODO: johbo: For now we serve double size images to make it smooth
231 TODO: johbo: For now we serve double size images to make it smooth
232 for retina. This is how it worked until now. Should be replaced
232 for retina. This is how it worked until now. Should be replaced
233 with a better solution at some point.
233 with a better solution at some point.
234 </%doc>
234 </%doc>
235
235
236 <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, request=request)}" />
236 <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, request=request)}" />
237 </%def>
237 </%def>
238
238
239
239
240 <%def name="gravatar_with_user(contact, size=16, show_disabled=False, tooltip=False, _class='rc-user')">
240 <%def name="gravatar_with_user(contact, size=16, show_disabled=False, tooltip=False, _class='rc-user')">
241 <%
241 <%
242 email = h.email_or_none(contact)
242 email = h.email_or_none(contact)
243 rc_user = h.discover_user(contact)
243 rc_user = h.discover_user(contact)
244 %>
244 %>
245
245
246 <div class="${_class}">
246 <div class="${_class}">
247 ${self.gravatar(email, size, tooltip=tooltip, tooltip_alt=contact, user=rc_user)}
247 ${self.gravatar(email, size, tooltip=tooltip, tooltip_alt=contact, user=rc_user)}
248 <span class="${('user user-disabled' if show_disabled else 'user')}">
248 <span class="${('user user-disabled' if show_disabled else 'user')}">
249 ${h.link_to_user(rc_user or contact)}
249 ${h.link_to_user(rc_user or contact)}
250 </span>
250 </span>
251 </div>
251 </div>
252 </%def>
252 </%def>
253
253
254
254
255 <%def name="user_group_icon(user_group=None, size=16, tooltip=False)">
255 <%def name="user_group_icon(user_group=None, size=16, tooltip=False)">
256 <%
256 <%
257 if (size > 16):
257 if (size > 16):
258 gravatar_class = 'icon-user-group-alt'
258 gravatar_class = 'icon-user-group-alt'
259 else:
259 else:
260 gravatar_class = 'icon-user-group-alt'
260 gravatar_class = 'icon-user-group-alt'
261
261
262 if tooltip:
262 if tooltip:
263 gravatar_class += ' tooltip-hovercard'
263 gravatar_class += ' tooltip-hovercard'
264
264
265 data_hovercard_url = request.route_path('hovercard_user_group', user_group_id=user_group.users_group_id)
265 data_hovercard_url = request.route_path('hovercard_user_group', user_group_id=user_group.users_group_id)
266 %>
266 %>
267 <%doc>
267 <%doc>
268 TODO: johbo: For now we serve double size images to make it smooth
268 TODO: johbo: For now we serve double size images to make it smooth
269 for retina. This is how it worked until now. Should be replaced
269 for retina. This is how it worked until now. Should be replaced
270 with a better solution at some point.
270 with a better solution at some point.
271 </%doc>
271 </%doc>
272
272
273 <i style="font-size: ${size}px" class="${gravatar_class} x-icon-size-${size}" data-hovercard-url="${data_hovercard_url}"></i>
273 <i style="font-size: ${size}px" class="${gravatar_class} x-icon-size-${size}" data-hovercard-url="${data_hovercard_url}"></i>
274 </%def>
274 </%def>
275
275
276 <%def name="repo_page_title(repo_instance)">
276 <%def name="repo_page_title(repo_instance)">
277 <div class="title-content repo-title">
277 <div class="title-content repo-title">
278
278
279 <div class="title-main">
279 <div class="title-main">
280 ## SVN/HG/GIT icons
280 ## SVN/HG/GIT icons
281 %if h.is_hg(repo_instance):
281 %if h.is_hg(repo_instance):
282 <i class="icon-hg"></i>
282 <i class="icon-hg"></i>
283 %endif
283 %endif
284 %if h.is_git(repo_instance):
284 %if h.is_git(repo_instance):
285 <i class="icon-git"></i>
285 <i class="icon-git"></i>
286 %endif
286 %endif
287 %if h.is_svn(repo_instance):
287 %if h.is_svn(repo_instance):
288 <i class="icon-svn"></i>
288 <i class="icon-svn"></i>
289 %endif
289 %endif
290
290
291 ## public/private
291 ## public/private
292 %if repo_instance.private:
292 %if repo_instance.private:
293 <i class="icon-repo-private"></i>
293 <i class="icon-repo-private"></i>
294 %else:
294 %else:
295 <i class="icon-repo-public"></i>
295 <i class="icon-repo-public"></i>
296 %endif
296 %endif
297
297
298 ## repo name with group name
298 ## repo name with group name
299 ${h.breadcrumb_repo_link(repo_instance)}
299 ${h.breadcrumb_repo_link(repo_instance)}
300
300
301 ## Context Actions
301 ## Context Actions
302 <div class="pull-right">
302 <div class="pull-right">
303 %if c.rhodecode_user.username != h.DEFAULT_USER:
303 %if c.rhodecode_user.username != h.DEFAULT_USER:
304 <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>
304 <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
305
306 <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 '')}">
306 <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 % if c.repository_is_user_following:
307 % if c.repository_is_user_following:
308 <i class="icon-eye-off"></i>${_('Unwatch')}
308 <i class="icon-eye-off"></i>${_('Unwatch')}
309 % else:
309 % else:
310 <i class="icon-eye"></i>${_('Watch')}
310 <i class="icon-eye"></i>${_('Watch')}
311 % endif
311 % endif
312
312
313 </a>
313 </a>
314 %else:
314 %else:
315 <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>
315 <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 %endif
316 %endif
317 </div>
317 </div>
318
318
319 </div>
319 </div>
320
320
321 ## FORKED
321 ## FORKED
322 %if repo_instance.fork:
322 %if repo_instance.fork:
323 <p class="discreet">
323 <p class="discreet">
324 <i class="icon-code-fork"></i> ${_('Fork of')}
324 <i class="icon-code-fork"></i> ${_('Fork of')}
325 ${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))}
325 ${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 </p>
326 </p>
327 %endif
327 %endif
328
328
329 ## IMPORTED FROM REMOTE
329 ## IMPORTED FROM REMOTE
330 %if repo_instance.clone_uri:
330 %if repo_instance.clone_uri:
331 <p class="discreet">
331 <p class="discreet">
332 <i class="icon-code-fork"></i> ${_('Clone from')}
332 <i class="icon-code-fork"></i> ${_('Clone from')}
333 <a href="${h.safe_str(h.hide_credentials(repo_instance.clone_uri))}">${h.hide_credentials(repo_instance.clone_uri)}</a>
333 <a href="${h.safe_str(h.hide_credentials(repo_instance.clone_uri))}">${h.hide_credentials(repo_instance.clone_uri)}</a>
334 </p>
334 </p>
335 %endif
335 %endif
336
336
337 ## LOCKING STATUS
337 ## LOCKING STATUS
338 %if repo_instance.locked[0]:
338 %if repo_instance.locked[0]:
339 <p class="locking_locked discreet">
339 <p class="locking_locked discreet">
340 <i class="icon-repo-lock"></i>
340 <i class="icon-repo-lock"></i>
341 ${_('Repository locked by %(user)s') % {'user': h.person_by_id(repo_instance.locked[0])}}
341 ${_('Repository locked by %(user)s') % {'user': h.person_by_id(repo_instance.locked[0])}}
342 </p>
342 </p>
343 %elif repo_instance.enable_locking:
343 %elif repo_instance.enable_locking:
344 <p class="locking_unlocked discreet">
344 <p class="locking_unlocked discreet">
345 <i class="icon-repo-unlock"></i>
346 ${_('Repository not locked. Pull repository to lock it.')}
345 ${_('Repository not locked. Pull repository to lock it.')}
347 </p>
346 </p>
348 %endif
347 %endif
349
348
350 </div>
349 </div>
351 </%def>
350 </%def>
352
351
353 <%def name="repo_menu(active=None)">
352 <%def name="repo_menu(active=None)">
354 <%
353 <%
355 ## determine if we have "any" option available
354 ## determine if we have "any" option available
356 can_lock = h.HasRepoPermissionAny('repository.write','repository.admin')(c.repo_name) and c.rhodecode_db_repo.enable_locking
355 can_lock = h.HasRepoPermissionAny('repository.write','repository.admin')(c.repo_name) and c.rhodecode_db_repo.enable_locking
357 has_actions = can_lock
356 has_actions = can_lock
358
357
359 %>
358 %>
360 % if c.rhodecode_db_repo.archived:
359 % if c.rhodecode_db_repo.archived:
361 <div class="alert alert-warning text-center">
360 <div class="alert alert-warning text-center">
362 <strong>${_('This repository has been archived. It is now read-only.')}</strong>
361 <strong>${_('This repository has been archived. It is now read-only.')}</strong>
363 </div>
362 </div>
364 % endif
363 % endif
365
364
366 <!--- REPO CONTEXT BAR -->
365 <!--- REPO CONTEXT BAR -->
367 <div id="context-bar">
366 <div id="context-bar">
368 <div class="wrapper">
367 <div class="wrapper">
369
368
370 <div class="title">
369 <div class="title">
371 ${self.repo_page_title(c.rhodecode_db_repo)}
370 ${self.repo_page_title(c.rhodecode_db_repo)}
372 </div>
371 </div>
373
372
374 <ul id="context-pages" class="navigation horizontal-list">
373 <ul id="context-pages" class="navigation horizontal-list">
375 <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>
374 <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('commits', active)}"><a class="menulink" href="${h.route_path('repo_commits', repo_name=c.repo_name)}"><div class="menulabel">${_('Commits')}</div></a></li>
375 <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('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>
376 <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('compare', active)}"><a class="menulink" href="${h.route_path('repo_compare_select',repo_name=c.repo_name)}"><div class="menulabel">${_('Compare')}</div></a></li>
377 <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
378
380 ## TODO: anderson: ideally it would have a function on the scm_instance "enable_pullrequest() and enable_fork()"
379 ## TODO: anderson: ideally it would have a function on the scm_instance "enable_pullrequest() and enable_fork()"
381 %if c.rhodecode_db_repo.repo_type in ['git','hg']:
380 %if c.rhodecode_db_repo.repo_type in ['git','hg']:
382 <li class="${h.is_active('showpullrequest', active)}">
381 <li class="${h.is_active('showpullrequest', active)}">
383 <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)}">
382 <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 <div class="menulabel">
383 <div class="menulabel">
385 ${_('Pull Requests')} <span class="menulink-counter">${c.repository_pull_requests}</span>
384 ${_('Pull Requests')} <span class="menulink-counter">${c.repository_pull_requests}</span>
386 </div>
385 </div>
387 </a>
386 </a>
388 </li>
387 </li>
389 %endif
388 %endif
390
389
391 <li class="${h.is_active('artifacts', active)}">
390 <li class="${h.is_active('artifacts', active)}">
392 <a class="menulink" href="${h.route_path('repo_artifacts_list',repo_name=c.repo_name)}">
391 <a class="menulink" href="${h.route_path('repo_artifacts_list',repo_name=c.repo_name)}">
393 <div class="menulabel">
392 <div class="menulabel">
394 ${_('Artifacts')} <span class="menulink-counter">${c.repository_artifacts}</span>
393 ${_('Artifacts')} <span class="menulink-counter">${c.repository_artifacts}</span>
395 </div>
394 </div>
396 </a>
395 </a>
397 </li>
396 </li>
398
397
399 %if not c.rhodecode_db_repo.archived and h.HasRepoPermissionAll('repository.admin')(c.repo_name):
398 %if not c.rhodecode_db_repo.archived and h.HasRepoPermissionAll('repository.admin')(c.repo_name):
400 <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>
399 <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 %endif
400 %endif
402
401
403 <li class="${h.is_active('options', active)}">
402 <li class="${h.is_active('options', active)}">
404 % if has_actions:
403 % if has_actions:
405 <a class="menulink dropdown">
404 <a class="menulink dropdown">
406 <div class="menulabel">${_('Options')}<div class="show_more"></div></div>
405 <div class="menulabel">${_('Quick Actions')}<div class="show_more"></div></div>
407 </a>
406 </a>
408 <ul class="submenu">
407 <ul class="submenu">
409 %if can_lock:
408 %if can_lock:
410 %if c.rhodecode_db_repo.locked[0]:
409 %if c.rhodecode_db_repo.locked[0]:
411 <li><a class="locking_del" href="${h.route_path('repo_edit_toggle_locking',repo_name=c.repo_name)}">${_('Unlock Repository')}</a></li>
410 <li><a class="locking_del" href="${h.route_path('repo_settings_quick_actions',repo_name=c.repo_name, _query={'action': 'toggle-lock', 'set_unlock': 1})}">${_('Unlock Repository')}</a></li>
412 %else:
411 %else:
413 <li><a class="locking_add" href="${h.route_path('repo_edit_toggle_locking',repo_name=c.repo_name)}">${_('Lock Repository')}</a></li>
412 <li><a class="locking_add" href="${h.route_path('repo_settings_quick_actions',repo_name=c.repo_name, _query={'action': 'toggle-lock', 'set_lock': 1})}">${_('Lock Repository')}</a></li>
414 %endif
413 %endif
415 %endif
414 %endif
416 </ul>
415 </ul>
417 % endif
416 % endif
418 </li>
417 </li>
419
418
420 </ul>
419 </ul>
421 </div>
420 </div>
422 <div class="clear"></div>
421 <div class="clear"></div>
423 </div>
422 </div>
424
423
425 <!--- REPO END CONTEXT BAR -->
424 <!--- REPO END CONTEXT BAR -->
426
425
427 </%def>
426 </%def>
428
427
429 <%def name="repo_group_page_title(repo_group_instance)">
428 <%def name="repo_group_page_title(repo_group_instance)">
430 <div class="title-content">
429 <div class="title-content">
431 <div class="title-main">
430 <div class="title-main">
432 ## Repository Group icon
431 ## Repository Group icon
433 <i class="icon-repo-group"></i>
432 <i class="icon-repo-group"></i>
434
433
435 ## repo name with group name
434 ## repo name with group name
436 ${h.breadcrumb_repo_group_link(repo_group_instance)}
435 ${h.breadcrumb_repo_group_link(repo_group_instance)}
437 </div>
436 </div>
438
437
439 <%namespace name="dt" file="/data_table/_dt_elements.mako"/>
438 <%namespace name="dt" file="/data_table/_dt_elements.mako"/>
440 <div class="repo-group-desc discreet">
439 <div class="repo-group-desc discreet">
441 ${dt.repo_group_desc(repo_group_instance.description_safe, repo_group_instance.personal, c.visual.stylify_metatags)}
440 ${dt.repo_group_desc(repo_group_instance.description_safe, repo_group_instance.personal, c.visual.stylify_metatags)}
442 </div>
441 </div>
443
442
444 </div>
443 </div>
445 </%def>
444 </%def>
446
445
447
446
448 <%def name="repo_group_menu(active=None)">
447 <%def name="repo_group_menu(active=None)">
449 <%
448 <%
450 gr_name = c.repo_group.group_name if c.repo_group else None
449 gr_name = c.repo_group.group_name if c.repo_group else None
451 # create repositories with write permission on group is set to true
450 # create repositories with write permission on group is set to true
452 group_admin = h.HasRepoGroupPermissionAny('group.admin')(gr_name, 'group admin index page')
451 group_admin = h.HasRepoGroupPermissionAny('group.admin')(gr_name, 'group admin index page')
453
452
454 %>
453 %>
455
454
456
455
457 <!--- REPO GROUP CONTEXT BAR -->
456 <!--- REPO GROUP CONTEXT BAR -->
458 <div id="context-bar">
457 <div id="context-bar">
459 <div class="wrapper">
458 <div class="wrapper">
460 <div class="title">
459 <div class="title">
461 ${self.repo_group_page_title(c.repo_group)}
460 ${self.repo_group_page_title(c.repo_group)}
462 </div>
461 </div>
463
462
464 <ul id="context-pages" class="navigation horizontal-list">
463 <ul id="context-pages" class="navigation horizontal-list">
465 <li class="${h.is_active('home', active)}">
464 <li class="${h.is_active('home', active)}">
466 <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>
465 <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 </li>
466 </li>
468 % if c.is_super_admin or group_admin:
467 % if c.is_super_admin or group_admin:
469 <li class="${h.is_active('settings', active)}">
468 <li class="${h.is_active('settings', active)}">
470 <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>
469 <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 </li>
470 </li>
472 % endif
471 % endif
473
472
474 </ul>
473 </ul>
475 </div>
474 </div>
476 <div class="clear"></div>
475 <div class="clear"></div>
477 </div>
476 </div>
478
477
479 <!--- REPO GROUP CONTEXT BAR -->
478 <!--- REPO GROUP CONTEXT BAR -->
480
479
481 </%def>
480 </%def>
482
481
483
482
484 <%def name="usermenu(active=False)">
483 <%def name="usermenu(active=False)">
485 <%
484 <%
486 not_anonymous = c.rhodecode_user.username != h.DEFAULT_USER
485 not_anonymous = c.rhodecode_user.username != h.DEFAULT_USER
487
486
488 gr_name = c.repo_group.group_name if (hasattr(c, 'repo_group') and c.repo_group) else None
487 gr_name = c.repo_group.group_name if (hasattr(c, 'repo_group') and c.repo_group) else None
489 # create repositories with write permission on group is set to true
488 # create repositories with write permission on group is set to true
490
489
491 can_fork = c.is_super_admin or h.HasPermissionAny('hg.fork.repository')()
490 can_fork = c.is_super_admin or h.HasPermissionAny('hg.fork.repository')()
492 create_on_write = h.HasPermissionAny('hg.create.write_on_repogroup.true')()
491 create_on_write = h.HasPermissionAny('hg.create.write_on_repogroup.true')()
493 group_write = h.HasRepoGroupPermissionAny('group.write')(gr_name, 'can write into group index page')
492 group_write = h.HasRepoGroupPermissionAny('group.write')(gr_name, 'can write into group index page')
494 group_admin = h.HasRepoGroupPermissionAny('group.admin')(gr_name, 'group admin index page')
493 group_admin = h.HasRepoGroupPermissionAny('group.admin')(gr_name, 'group admin index page')
495
494
496 can_create_repos = c.is_super_admin or c.can_create_repo
495 can_create_repos = c.is_super_admin or c.can_create_repo
497 can_create_repo_groups = c.is_super_admin or c.can_create_repo_group
496 can_create_repo_groups = c.is_super_admin or c.can_create_repo_group
498
497
499 can_create_repos_in_group = c.is_super_admin or group_admin or (group_write and create_on_write)
498 can_create_repos_in_group = c.is_super_admin or group_admin or (group_write and create_on_write)
500 can_create_repo_groups_in_group = c.is_super_admin or group_admin
499 can_create_repo_groups_in_group = c.is_super_admin or group_admin
501 %>
500 %>
502
501
503 % if not_anonymous:
502 % if not_anonymous:
504 <%
503 <%
505 default_target_group = dict()
504 default_target_group = dict()
506 if c.rhodecode_user.personal_repo_group:
505 if c.rhodecode_user.personal_repo_group:
507 default_target_group = dict(parent_group=c.rhodecode_user.personal_repo_group.group_id)
506 default_target_group = dict(parent_group=c.rhodecode_user.personal_repo_group.group_id)
508 %>
507 %>
509
508
510 ## create action
509 ## create action
511 <li>
510 <li>
512 <a href="#create-actions" onclick="return false;" class="menulink childs">
511 <a href="#create-actions" onclick="return false;" class="menulink childs">
513 <i class="icon-plus-circled"></i>
512 <i class="icon-plus-circled"></i>
514 </a>
513 </a>
515
514
516 <div class="action-menu submenu">
515 <div class="action-menu submenu">
517
516
518 <ol>
517 <ol>
519 ## scope of within a repository
518 ## scope of within a repository
520 % if hasattr(c, 'rhodecode_db_repo') and c.rhodecode_db_repo:
519 % if hasattr(c, 'rhodecode_db_repo') and c.rhodecode_db_repo:
521 <li class="submenu-title">${_('This Repository')}</li>
520 <li class="submenu-title">${_('This Repository')}</li>
522 <li>
521 <li>
523 <a href="${h.route_path('pullrequest_new',repo_name=c.repo_name)}">${_('Create Pull Request')}</a>
522 <a href="${h.route_path('pullrequest_new',repo_name=c.repo_name)}">${_('Create Pull Request')}</a>
524 </li>
523 </li>
525 % if can_fork:
524 % if can_fork:
526 <li>
525 <li>
527 <a href="${h.route_path('repo_fork_new',repo_name=c.repo_name,_query=default_target_group)}">${_('Fork this repository')}</a>
526 <a href="${h.route_path('repo_fork_new',repo_name=c.repo_name,_query=default_target_group)}">${_('Fork this repository')}</a>
528 </li>
527 </li>
529 % endif
528 % endif
530 % endif
529 % endif
531
530
532 ## scope of within repository groups
531 ## scope of within repository groups
533 % if hasattr(c, 'repo_group') and c.repo_group and (can_create_repos_in_group or can_create_repo_groups_in_group):
532 % if hasattr(c, 'repo_group') and c.repo_group and (can_create_repos_in_group or can_create_repo_groups_in_group):
534 <li class="submenu-title">${_('This Repository Group')}</li>
533 <li class="submenu-title">${_('This Repository Group')}</li>
535
534
536 % if can_create_repos_in_group:
535 % if can_create_repos_in_group:
537 <li>
536 <li>
538 <a href="${h.route_path('repo_new',_query=dict(parent_group=c.repo_group.group_id))}">${_('New Repository')}</a>
537 <a href="${h.route_path('repo_new',_query=dict(parent_group=c.repo_group.group_id))}">${_('New Repository')}</a>
539 </li>
538 </li>
540 % endif
539 % endif
541
540
542 % if can_create_repo_groups_in_group:
541 % if can_create_repo_groups_in_group:
543 <li>
542 <li>
544 <a href="${h.route_path('repo_group_new',_query=dict(parent_group=c.repo_group.group_id))}">${_(u'New Repository Group')}</a>
543 <a href="${h.route_path('repo_group_new',_query=dict(parent_group=c.repo_group.group_id))}">${_(u'New Repository Group')}</a>
545 </li>
544 </li>
546 % endif
545 % endif
547 % endif
546 % endif
548
547
549 ## personal group
548 ## personal group
550 % if c.rhodecode_user.personal_repo_group:
549 % if c.rhodecode_user.personal_repo_group:
551 <li class="submenu-title">Personal Group</li>
550 <li class="submenu-title">Personal Group</li>
552
551
553 <li>
552 <li>
554 <a href="${h.route_path('repo_new',_query=dict(parent_group=c.rhodecode_user.personal_repo_group.group_id))}" >${_('New Repository')} </a>
553 <a href="${h.route_path('repo_new',_query=dict(parent_group=c.rhodecode_user.personal_repo_group.group_id))}" >${_('New Repository')} </a>
555 </li>
554 </li>
556
555
557 <li>
556 <li>
558 <a href="${h.route_path('repo_group_new',_query=dict(parent_group=c.rhodecode_user.personal_repo_group.group_id))}">${_('New Repository Group')} </a>
557 <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 </li>
558 </li>
560 % endif
559 % endif
561
560
562 ## Global actions
561 ## Global actions
563 <li class="submenu-title">RhodeCode</li>
562 <li class="submenu-title">RhodeCode</li>
564 % if can_create_repos:
563 % if can_create_repos:
565 <li>
564 <li>
566 <a href="${h.route_path('repo_new')}" >${_('New Repository')}</a>
565 <a href="${h.route_path('repo_new')}" >${_('New Repository')}</a>
567 </li>
566 </li>
568 % endif
567 % endif
569
568
570 % if can_create_repo_groups:
569 % if can_create_repo_groups:
571 <li>
570 <li>
572 <a href="${h.route_path('repo_group_new')}" >${_(u'New Repository Group')}</a>
571 <a href="${h.route_path('repo_group_new')}" >${_(u'New Repository Group')}</a>
573 </li>
572 </li>
574 % endif
573 % endif
575
574
576 <li>
575 <li>
577 <a href="${h.route_path('gists_new')}">${_(u'New Gist')}</a>
576 <a href="${h.route_path('gists_new')}">${_(u'New Gist')}</a>
578 </li>
577 </li>
579
578
580 </ol>
579 </ol>
581
580
582 </div>
581 </div>
583 </li>
582 </li>
584
583
585 ## notifications
584 ## notifications
586 <li>
585 <li>
587 <a class="${('empty' if c.unread_notifications == 0 else '')}" href="${h.route_path('notifications_show_all')}">
586 <a class="${('empty' if c.unread_notifications == 0 else '')}" href="${h.route_path('notifications_show_all')}">
588 ${c.unread_notifications}
587 ${c.unread_notifications}
589 </a>
588 </a>
590 </li>
589 </li>
591 % endif
590 % endif
592
591
593 ## USER MENU
592 ## USER MENU
594 <li id="quick_login_li" class="${'active' if active else ''}">
593 <li id="quick_login_li" class="${'active' if active else ''}">
595 % if c.rhodecode_user.username == h.DEFAULT_USER:
594 % if c.rhodecode_user.username == h.DEFAULT_USER:
596 <a id="quick_login_link" class="menulink childs" href="${h.route_path('login', _query={'came_from': h.current_route_path(request)})}">
595 <a id="quick_login_link" class="menulink childs" href="${h.route_path('login', _query={'came_from': h.current_route_path(request)})}">
597 ${gravatar(c.rhodecode_user.email, 20)}
596 ${gravatar(c.rhodecode_user.email, 20)}
598 <span class="user">
597 <span class="user">
599 <span>${_('Sign in')}</span>
598 <span>${_('Sign in')}</span>
600 </span>
599 </span>
601 </a>
600 </a>
602 % else:
601 % else:
603 ## logged in user
602 ## logged in user
604 <a id="quick_login_link" class="menulink childs">
603 <a id="quick_login_link" class="menulink childs">
605 ${gravatar(c.rhodecode_user.email, 20)}
604 ${gravatar(c.rhodecode_user.email, 20)}
606 <span class="user">
605 <span class="user">
607 <span class="menu_link_user">${c.rhodecode_user.username}</span>
606 <span class="menu_link_user">${c.rhodecode_user.username}</span>
608 <div class="show_more"></div>
607 <div class="show_more"></div>
609 </span>
608 </span>
610 </a>
609 </a>
611 ## subnav with menu for logged in user
610 ## subnav with menu for logged in user
612 <div class="user-menu submenu">
611 <div class="user-menu submenu">
613 <div id="quick_login">
612 <div id="quick_login">
614 %if c.rhodecode_user.username != h.DEFAULT_USER:
613 %if c.rhodecode_user.username != h.DEFAULT_USER:
615 <div class="">
614 <div class="">
616 <div class="big_gravatar">${gravatar(c.rhodecode_user.email, 48)}</div>
615 <div class="big_gravatar">${gravatar(c.rhodecode_user.email, 48)}</div>
617 <div class="full_name">${c.rhodecode_user.full_name_or_username}</div>
616 <div class="full_name">${c.rhodecode_user.full_name_or_username}</div>
618 <div class="email">${c.rhodecode_user.email}</div>
617 <div class="email">${c.rhodecode_user.email}</div>
619 </div>
618 </div>
620 <div class="">
619 <div class="">
621 <ol class="links">
620 <ol class="links">
622 <li>${h.link_to(_(u'My account'),h.route_path('my_account_profile'))}</li>
621 <li>${h.link_to(_(u'My account'),h.route_path('my_account_profile'))}</li>
623 % if c.rhodecode_user.personal_repo_group:
622 % if c.rhodecode_user.personal_repo_group:
624 <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>
623 <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 % endif
624 % endif
626 <li>${h.link_to(_(u'Pull Requests'), h.route_path('my_account_pullrequests'))}</li>
625 <li>${h.link_to(_(u'Pull Requests'), h.route_path('my_account_pullrequests'))}</li>
627
626
628 % if c.debug_style:
627 % if c.debug_style:
629 <li>
628 <li>
630 <a class="menulink" title="${_('Style')}" href="${h.route_path('debug_style_home')}">
629 <a class="menulink" title="${_('Style')}" href="${h.route_path('debug_style_home')}">
631 <div class="menulabel">${_('[Style]')}</div>
630 <div class="menulabel">${_('[Style]')}</div>
632 </a>
631 </a>
633 </li>
632 </li>
634 % endif
633 % endif
635
634
636 ## bookmark-items
635 ## bookmark-items
637 <li class="bookmark-items">
636 <li class="bookmark-items">
638 ${_('Bookmarks')}
637 ${_('Bookmarks')}
639 <div class="pull-right">
638 <div class="pull-right">
640 <a href="${h.route_path('my_account_bookmarks')}">
639 <a href="${h.route_path('my_account_bookmarks')}">
641
640
642 <i class="icon-cog"></i>
641 <i class="icon-cog"></i>
643 </a>
642 </a>
644 </div>
643 </div>
645 </li>
644 </li>
646 % if not c.bookmark_items:
645 % if not c.bookmark_items:
647 <li>
646 <li>
648 <a href="${h.route_path('my_account_bookmarks')}">${_('No Bookmarks yet.')}</a>
647 <a href="${h.route_path('my_account_bookmarks')}">${_('No Bookmarks yet.')}</a>
649 </li>
648 </li>
650 % endif
649 % endif
651 % for item in c.bookmark_items:
650 % for item in c.bookmark_items:
652 <li>
651 <li>
653 % if item.repository:
652 % if item.repository:
654 <div>
653 <div>
655 <a class="bookmark-item" href="${h.route_path('my_account_goto_bookmark', bookmark_id=item.position)}">
654 <a class="bookmark-item" href="${h.route_path('my_account_goto_bookmark', bookmark_id=item.position)}">
656 <code>${item.position}</code>
655 <code>${item.position}</code>
657 % if item.repository.repo_type == 'hg':
656 % if item.repository.repo_type == 'hg':
658 <i class="icon-hg" title="${_('Repository')}" style="font-size: 16px"></i>
657 <i class="icon-hg" title="${_('Repository')}" style="font-size: 16px"></i>
659 % elif item.repository.repo_type == 'git':
658 % elif item.repository.repo_type == 'git':
660 <i class="icon-git" title="${_('Repository')}" style="font-size: 16px"></i>
659 <i class="icon-git" title="${_('Repository')}" style="font-size: 16px"></i>
661 % elif item.repository.repo_type == 'svn':
660 % elif item.repository.repo_type == 'svn':
662 <i class="icon-svn" title="${_('Repository')}" style="font-size: 16px"></i>
661 <i class="icon-svn" title="${_('Repository')}" style="font-size: 16px"></i>
663 % endif
662 % endif
664 ${(item.title or h.shorter(item.repository.repo_name, 30))}
663 ${(item.title or h.shorter(item.repository.repo_name, 30))}
665 </a>
664 </a>
666 </div>
665 </div>
667 % elif item.repository_group:
666 % elif item.repository_group:
668 <div>
667 <div>
669 <a class="bookmark-item" href="${h.route_path('my_account_goto_bookmark', bookmark_id=item.position)}">
668 <a class="bookmark-item" href="${h.route_path('my_account_goto_bookmark', bookmark_id=item.position)}">
670 <code>${item.position}</code>
669 <code>${item.position}</code>
671 <i class="icon-repo-group" title="${_('Repository group')}" style="font-size: 14px"></i>
670 <i class="icon-repo-group" title="${_('Repository group')}" style="font-size: 14px"></i>
672 ${(item.title or h.shorter(item.repository_group.group_name, 30))}
671 ${(item.title or h.shorter(item.repository_group.group_name, 30))}
673 </a>
672 </a>
674 </div>
673 </div>
675 % else:
674 % else:
676 <a class="bookmark-item" href="${h.route_path('my_account_goto_bookmark', bookmark_id=item.position)}">
675 <a class="bookmark-item" href="${h.route_path('my_account_goto_bookmark', bookmark_id=item.position)}">
677 <code>${item.position}</code>
676 <code>${item.position}</code>
678 ${item.title}
677 ${item.title}
679 </a>
678 </a>
680 % endif
679 % endif
681 </li>
680 </li>
682 % endfor
681 % endfor
683
682
684 <li class="logout">
683 <li class="logout">
685 ${h.secure_form(h.route_path('logout'), request=request)}
684 ${h.secure_form(h.route_path('logout'), request=request)}
686 ${h.submit('log_out', _(u'Sign Out'),class_="btn btn-primary")}
685 ${h.submit('log_out', _(u'Sign Out'),class_="btn btn-primary")}
687 ${h.end_form()}
686 ${h.end_form()}
688 </li>
687 </li>
689 </ol>
688 </ol>
690 </div>
689 </div>
691 %endif
690 %endif
692 </div>
691 </div>
693 </div>
692 </div>
694
693
695 % endif
694 % endif
696 </li>
695 </li>
697 </%def>
696 </%def>
698
697
699 <%def name="menu_items(active=None)">
698 <%def name="menu_items(active=None)">
700 <%
699 <%
701 notice_messages, notice_level = c.rhodecode_user.get_notice_messages()
700 notice_messages, notice_level = c.rhodecode_user.get_notice_messages()
702 notice_display = 'none' if len(notice_messages) == 0 else ''
701 notice_display = 'none' if len(notice_messages) == 0 else ''
703 %>
702 %>
704
703
705 <ul id="quick" class="main_nav navigation horizontal-list">
704 <ul id="quick" class="main_nav navigation horizontal-list">
706 ## notice box for important system messages
705 ## notice box for important system messages
707 <li style="display: ${notice_display}">
706 <li style="display: ${notice_display}">
708 <a class="notice-box" href="#openNotice" onclick="$('.notice-messages-container').toggle(); return false">
707 <a class="notice-box" href="#openNotice" onclick="$('.notice-messages-container').toggle(); return false">
709 <div class="menulabel-notice ${notice_level}" >
708 <div class="menulabel-notice ${notice_level}" >
710 ${len(notice_messages)}
709 ${len(notice_messages)}
711 </div>
710 </div>
712 </a>
711 </a>
713 </li>
712 </li>
714 <div class="notice-messages-container" style="display: none">
713 <div class="notice-messages-container" style="display: none">
715 <div class="notice-messages">
714 <div class="notice-messages">
716 <table class="rctable">
715 <table class="rctable">
717 % for notice in notice_messages:
716 % for notice in notice_messages:
718 <tr id="notice-message-${notice['msg_id']}" class="notice-message-${notice['level']}">
717 <tr id="notice-message-${notice['msg_id']}" class="notice-message-${notice['level']}">
719 <td style="vertical-align: text-top; width: 20px">
718 <td style="vertical-align: text-top; width: 20px">
720 <i class="tooltip icon-info notice-color-${notice['level']}" title="${notice['level']}"></i>
719 <i class="tooltip icon-info notice-color-${notice['level']}" title="${notice['level']}"></i>
721 </td>
720 </td>
722 <td>
721 <td>
723 <span><i class="icon-plus-squared cursor-pointer" onclick="$('#notice-${notice['msg_id']}').toggle()"></i> </span>
722 <span><i class="icon-plus-squared cursor-pointer" onclick="$('#notice-${notice['msg_id']}').toggle()"></i> </span>
724 ${notice['subject']}
723 ${notice['subject']}
725
724
726 <div id="notice-${notice['msg_id']}" style="display: none">
725 <div id="notice-${notice['msg_id']}" style="display: none">
727 ${h.render(notice['body'], renderer='markdown')}
726 ${h.render(notice['body'], renderer='markdown')}
728 </div>
727 </div>
729 </td>
728 </td>
730 <td style="vertical-align: text-top; width: 35px;">
729 <td style="vertical-align: text-top; width: 35px;">
731 <a class="tooltip" title="${_('dismiss')}" href="#dismiss" onclick="dismissNotice(${notice['msg_id']});return false">
730 <a class="tooltip" title="${_('dismiss')}" href="#dismiss" onclick="dismissNotice(${notice['msg_id']});return false">
732 <i class="icon-remove icon-filled-red"></i>
731 <i class="icon-remove icon-filled-red"></i>
733 </a>
732 </a>
734 </td>
733 </td>
735 </tr>
734 </tr>
736
735
737 % endfor
736 % endfor
738 </table>
737 </table>
739 </div>
738 </div>
740 </div>
739 </div>
741 ## Main filter
740 ## Main filter
742 <li>
741 <li>
743 <div class="menulabel main_filter_box">
742 <div class="menulabel main_filter_box">
744 <div class="main_filter_input_box">
743 <div class="main_filter_input_box">
745 <ul class="searchItems">
744 <ul class="searchItems">
746
745
747 <li class="searchTag searchTagIcon">
746 <li class="searchTag searchTagIcon">
748 <i class="icon-search"></i>
747 <i class="icon-search"></i>
749 </li>
748 </li>
750
749
751 % if c.template_context['search_context']['repo_id']:
750 % if c.template_context['search_context']['repo_id']:
752 <li class="searchTag searchTagFilter searchTagHidable" >
751 <li class="searchTag searchTagFilter searchTagHidable" >
753 ##<a href="${h.route_path('search_repo',repo_name=c.template_context['search_context']['repo_name'])}">
752 ##<a href="${h.route_path('search_repo',repo_name=c.template_context['search_context']['repo_name'])}">
754 <span class="tag">
753 <span class="tag">
755 This repo
754 This repo
756 <a href="#removeGoToFilter" onclick="removeGoToFilter(); return false"><i class="icon-cancel-circled"></i></a>
755 <a href="#removeGoToFilter" onclick="removeGoToFilter(); return false"><i class="icon-cancel-circled"></i></a>
757 </span>
756 </span>
758 ##</a>
757 ##</a>
759 </li>
758 </li>
760 % elif c.template_context['search_context']['repo_group_id']:
759 % elif c.template_context['search_context']['repo_group_id']:
761 <li class="searchTag searchTagFilter searchTagHidable">
760 <li class="searchTag searchTagFilter searchTagHidable">
762 ##<a href="${h.route_path('search_repo_group',repo_group_name=c.template_context['search_context']['repo_group_name'])}">
761 ##<a href="${h.route_path('search_repo_group',repo_group_name=c.template_context['search_context']['repo_group_name'])}">
763 <span class="tag">
762 <span class="tag">
764 This group
763 This group
765 <a href="#removeGoToFilter" onclick="removeGoToFilter(); return false"><i class="icon-cancel-circled"></i></a>
764 <a href="#removeGoToFilter" onclick="removeGoToFilter(); return false"><i class="icon-cancel-circled"></i></a>
766 </span>
765 </span>
767 ##</a>
766 ##</a>
768 </li>
767 </li>
769 % endif
768 % endif
770
769
771 <li class="searchTagInput">
770 <li class="searchTagInput">
772 <input class="main_filter_input" id="main_filter" size="25" type="text" name="main_filter" placeholder="${_('search / go to...')}" value="" />
771 <input class="main_filter_input" id="main_filter" size="25" type="text" name="main_filter" placeholder="${_('search / go to...')}" value="" />
773 </li>
772 </li>
774 <li class="searchTag searchTagHelp">
773 <li class="searchTag searchTagHelp">
775 <a href="#showFilterHelp" onclick="showMainFilterBox(); return false">?</a>
774 <a href="#showFilterHelp" onclick="showMainFilterBox(); return false">?</a>
776 </li>
775 </li>
777 </ul>
776 </ul>
778 </div>
777 </div>
779 </div>
778 </div>
780
779
781 <div id="main_filter_help" style="display: none">
780 <div id="main_filter_help" style="display: none">
782 - Use '/' key to quickly access this field.
781 - Use '/' key to quickly access this field.
783
782
784 - Enter a name of repository, or repository group for quick search.
783 - Enter a name of repository, or repository group for quick search.
785
784
786 - Prefix query to allow special search:
785 - Prefix query to allow special search:
787
786
788 <strong>user:</strong>admin, to search for usernames, always global
787 <strong>user:</strong>admin, to search for usernames, always global
789
788
790 <strong>user_group:</strong>devops, to search for user groups, always global
789 <strong>user_group:</strong>devops, to search for user groups, always global
791
790
792 <strong>pr:</strong>303, to search for pull request number, title, or description, always global
791 <strong>pr:</strong>303, to search for pull request number, title, or description, always global
793
792
794 <strong>commit:</strong>efced4, to search for commits, scoped to repositories or groups
793 <strong>commit:</strong>efced4, to search for commits, scoped to repositories or groups
795
794
796 <strong>file:</strong>models.py, to search for file paths, scoped to repositories or groups
795 <strong>file:</strong>models.py, to search for file paths, scoped to repositories or groups
797
796
798 % if c.template_context['search_context']['repo_id']:
797 % if c.template_context['search_context']['repo_id']:
799 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>
798 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 % elif c.template_context['search_context']['repo_group_id']:
799 % elif c.template_context['search_context']['repo_group_id']:
801 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>
800 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 % else:
801 % else:
803 For advanced full text search visit: <a href="${h.route_path('search')}">global search</a>
802 For advanced full text search visit: <a href="${h.route_path('search')}">global search</a>
804 % endif
803 % endif
805 </div>
804 </div>
806 </li>
805 </li>
807
806
808 ## ROOT MENU
807 ## ROOT MENU
809 <li class="${h.is_active('home', active)}">
808 <li class="${h.is_active('home', active)}">
810 <a class="menulink" title="${_('Home')}" href="${h.route_path('home')}">
809 <a class="menulink" title="${_('Home')}" href="${h.route_path('home')}">
811 <div class="menulabel">${_('Home')}</div>
810 <div class="menulabel">${_('Home')}</div>
812 </a>
811 </a>
813 </li>
812 </li>
814
813
815 %if c.rhodecode_user.username != h.DEFAULT_USER:
814 %if c.rhodecode_user.username != h.DEFAULT_USER:
816 <li class="${h.is_active('journal', active)}">
815 <li class="${h.is_active('journal', active)}">
817 <a class="menulink" title="${_('Show activity journal')}" href="${h.route_path('journal')}">
816 <a class="menulink" title="${_('Show activity journal')}" href="${h.route_path('journal')}">
818 <div class="menulabel">${_('Journal')}</div>
817 <div class="menulabel">${_('Journal')}</div>
819 </a>
818 </a>
820 </li>
819 </li>
821 %else:
820 %else:
822 <li class="${h.is_active('journal', active)}">
821 <li class="${h.is_active('journal', active)}">
823 <a class="menulink" title="${_('Show Public activity journal')}" href="${h.route_path('journal_public')}">
822 <a class="menulink" title="${_('Show Public activity journal')}" href="${h.route_path('journal_public')}">
824 <div class="menulabel">${_('Public journal')}</div>
823 <div class="menulabel">${_('Public journal')}</div>
825 </a>
824 </a>
826 </li>
825 </li>
827 %endif
826 %endif
828
827
829 <li class="${h.is_active('gists', active)}">
828 <li class="${h.is_active('gists', active)}">
830 <a class="menulink childs" title="${_('Show Gists')}" href="${h.route_path('gists_show')}">
829 <a class="menulink childs" title="${_('Show Gists')}" href="${h.route_path('gists_show')}">
831 <div class="menulabel">${_('Gists')}</div>
830 <div class="menulabel">${_('Gists')}</div>
832 </a>
831 </a>
833 </li>
832 </li>
834
833
835 % if c.is_super_admin or c.is_delegated_admin:
834 % if c.is_super_admin or c.is_delegated_admin:
836 <li class="${h.is_active('admin', active)}">
835 <li class="${h.is_active('admin', active)}">
837 <a class="menulink childs" title="${_('Admin settings')}" href="${h.route_path('admin_home')}">
836 <a class="menulink childs" title="${_('Admin settings')}" href="${h.route_path('admin_home')}">
838 <div class="menulabel">${_('Admin')} </div>
837 <div class="menulabel">${_('Admin')} </div>
839 </a>
838 </a>
840 </li>
839 </li>
841 % endif
840 % endif
842
841
843 ## render extra user menu
842 ## render extra user menu
844 ${usermenu(active=(active=='my_account'))}
843 ${usermenu(active=(active=='my_account'))}
845
844
846 </ul>
845 </ul>
847
846
848 <script type="text/javascript">
847 <script type="text/javascript">
849 var visualShowPublicIcon = "${c.visual.show_public_icon}" == "True";
848 var visualShowPublicIcon = "${c.visual.show_public_icon}" == "True";
850
849
851 var formatRepoResult = function(result, container, query, escapeMarkup) {
850 var formatRepoResult = function(result, container, query, escapeMarkup) {
852 return function(data, escapeMarkup) {
851 return function(data, escapeMarkup) {
853 if (!data.repo_id){
852 if (!data.repo_id){
854 return data.text; // optgroup text Repositories
853 return data.text; // optgroup text Repositories
855 }
854 }
856
855
857 var tmpl = '';
856 var tmpl = '';
858 var repoType = data['repo_type'];
857 var repoType = data['repo_type'];
859 var repoName = data['text'];
858 var repoName = data['text'];
860
859
861 if(data && data.type == 'repo'){
860 if(data && data.type == 'repo'){
862 if(repoType === 'hg'){
861 if(repoType === 'hg'){
863 tmpl += '<i class="icon-hg"></i> ';
862 tmpl += '<i class="icon-hg"></i> ';
864 }
863 }
865 else if(repoType === 'git'){
864 else if(repoType === 'git'){
866 tmpl += '<i class="icon-git"></i> ';
865 tmpl += '<i class="icon-git"></i> ';
867 }
866 }
868 else if(repoType === 'svn'){
867 else if(repoType === 'svn'){
869 tmpl += '<i class="icon-svn"></i> ';
868 tmpl += '<i class="icon-svn"></i> ';
870 }
869 }
871 if(data['private']){
870 if(data['private']){
872 tmpl += '<i class="icon-lock" ></i> ';
871 tmpl += '<i class="icon-lock" ></i> ';
873 }
872 }
874 else if(visualShowPublicIcon){
873 else if(visualShowPublicIcon){
875 tmpl += '<i class="icon-unlock-alt"></i> ';
874 tmpl += '<i class="icon-unlock-alt"></i> ';
876 }
875 }
877 }
876 }
878 tmpl += escapeMarkup(repoName);
877 tmpl += escapeMarkup(repoName);
879 return tmpl;
878 return tmpl;
880
879
881 }(result, escapeMarkup);
880 }(result, escapeMarkup);
882 };
881 };
883
882
884 var formatRepoGroupResult = function(result, container, query, escapeMarkup) {
883 var formatRepoGroupResult = function(result, container, query, escapeMarkup) {
885 return function(data, escapeMarkup) {
884 return function(data, escapeMarkup) {
886 if (!data.repo_group_id){
885 if (!data.repo_group_id){
887 return data.text; // optgroup text Repositories
886 return data.text; // optgroup text Repositories
888 }
887 }
889
888
890 var tmpl = '';
889 var tmpl = '';
891 var repoGroupName = data['text'];
890 var repoGroupName = data['text'];
892
891
893 if(data){
892 if(data){
894
893
895 tmpl += '<i class="icon-repo-group"></i> ';
894 tmpl += '<i class="icon-repo-group"></i> ';
896
895
897 }
896 }
898 tmpl += escapeMarkup(repoGroupName);
897 tmpl += escapeMarkup(repoGroupName);
899 return tmpl;
898 return tmpl;
900
899
901 }(result, escapeMarkup);
900 }(result, escapeMarkup);
902 };
901 };
903
902
904 var escapeRegExChars = function (value) {
903 var escapeRegExChars = function (value) {
905 return value.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
904 return value.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
906 };
905 };
907
906
908 var getRepoIcon = function(repo_type) {
907 var getRepoIcon = function(repo_type) {
909 if (repo_type === 'hg') {
908 if (repo_type === 'hg') {
910 return '<i class="icon-hg"></i> ';
909 return '<i class="icon-hg"></i> ';
911 }
910 }
912 else if (repo_type === 'git') {
911 else if (repo_type === 'git') {
913 return '<i class="icon-git"></i> ';
912 return '<i class="icon-git"></i> ';
914 }
913 }
915 else if (repo_type === 'svn') {
914 else if (repo_type === 'svn') {
916 return '<i class="icon-svn"></i> ';
915 return '<i class="icon-svn"></i> ';
917 }
916 }
918 return ''
917 return ''
919 };
918 };
920
919
921 var autocompleteMainFilterFormatResult = function (data, value, org_formatter) {
920 var autocompleteMainFilterFormatResult = function (data, value, org_formatter) {
922
921
923 if (value.split(':').length === 2) {
922 if (value.split(':').length === 2) {
924 value = value.split(':')[1]
923 value = value.split(':')[1]
925 }
924 }
926
925
927 var searchType = data['type'];
926 var searchType = data['type'];
928 var searchSubType = data['subtype'];
927 var searchSubType = data['subtype'];
929 var valueDisplay = data['value_display'];
928 var valueDisplay = data['value_display'];
930 var valueIcon = data['value_icon'];
929 var valueIcon = data['value_icon'];
931
930
932 var pattern = '(' + escapeRegExChars(value) + ')';
931 var pattern = '(' + escapeRegExChars(value) + ')';
933
932
934 valueDisplay = Select2.util.escapeMarkup(valueDisplay);
933 valueDisplay = Select2.util.escapeMarkup(valueDisplay);
935
934
936 // highlight match
935 // highlight match
937 if (searchType != 'text') {
936 if (searchType != 'text') {
938 valueDisplay = valueDisplay.replace(new RegExp(pattern, 'gi'), '<strong>$1<\/strong>');
937 valueDisplay = valueDisplay.replace(new RegExp(pattern, 'gi'), '<strong>$1<\/strong>');
939 }
938 }
940
939
941 var icon = '';
940 var icon = '';
942
941
943 if (searchType === 'hint') {
942 if (searchType === 'hint') {
944 icon += '<i class="icon-repo-group"></i> ';
943 icon += '<i class="icon-repo-group"></i> ';
945 }
944 }
946 // full text search/hints
945 // full text search/hints
947 else if (searchType === 'search') {
946 else if (searchType === 'search') {
948 if (valueIcon === undefined) {
947 if (valueIcon === undefined) {
949 icon += '<i class="icon-more"></i> ';
948 icon += '<i class="icon-more"></i> ';
950 } else {
949 } else {
951 icon += valueIcon + ' ';
950 icon += valueIcon + ' ';
952 }
951 }
953
952
954 if (searchSubType !== undefined && searchSubType == 'repo') {
953 if (searchSubType !== undefined && searchSubType == 'repo') {
955 valueDisplay += '<div class="pull-right tag">repository</div>';
954 valueDisplay += '<div class="pull-right tag">repository</div>';
956 }
955 }
957 else if (searchSubType !== undefined && searchSubType == 'repo_group') {
956 else if (searchSubType !== undefined && searchSubType == 'repo_group') {
958 valueDisplay += '<div class="pull-right tag">repo group</div>';
957 valueDisplay += '<div class="pull-right tag">repo group</div>';
959 }
958 }
960 }
959 }
961 // repository
960 // repository
962 else if (searchType === 'repo') {
961 else if (searchType === 'repo') {
963
962
964 var repoIcon = getRepoIcon(data['repo_type']);
963 var repoIcon = getRepoIcon(data['repo_type']);
965 icon += repoIcon;
964 icon += repoIcon;
966
965
967 if (data['private']) {
966 if (data['private']) {
968 icon += '<i class="icon-lock" ></i> ';
967 icon += '<i class="icon-lock" ></i> ';
969 }
968 }
970 else if (visualShowPublicIcon) {
969 else if (visualShowPublicIcon) {
971 icon += '<i class="icon-unlock-alt"></i> ';
970 icon += '<i class="icon-unlock-alt"></i> ';
972 }
971 }
973 }
972 }
974 // repository groups
973 // repository groups
975 else if (searchType === 'repo_group') {
974 else if (searchType === 'repo_group') {
976 icon += '<i class="icon-repo-group"></i> ';
975 icon += '<i class="icon-repo-group"></i> ';
977 }
976 }
978 // user group
977 // user group
979 else if (searchType === 'user_group') {
978 else if (searchType === 'user_group') {
980 icon += '<i class="icon-group"></i> ';
979 icon += '<i class="icon-group"></i> ';
981 }
980 }
982 // user
981 // user
983 else if (searchType === 'user') {
982 else if (searchType === 'user') {
984 icon += '<img class="gravatar" src="{0}"/>'.format(data['icon_link']);
983 icon += '<img class="gravatar" src="{0}"/>'.format(data['icon_link']);
985 }
984 }
986 // pull request
985 // pull request
987 else if (searchType === 'pull_request') {
986 else if (searchType === 'pull_request') {
988 icon += '<i class="icon-merge"></i> ';
987 icon += '<i class="icon-merge"></i> ';
989 }
988 }
990 // commit
989 // commit
991 else if (searchType === 'commit') {
990 else if (searchType === 'commit') {
992 var repo_data = data['repo_data'];
991 var repo_data = data['repo_data'];
993 var repoIcon = getRepoIcon(repo_data['repository_type']);
992 var repoIcon = getRepoIcon(repo_data['repository_type']);
994 if (repoIcon) {
993 if (repoIcon) {
995 icon += repoIcon;
994 icon += repoIcon;
996 } else {
995 } else {
997 icon += '<i class="icon-tag"></i>';
996 icon += '<i class="icon-tag"></i>';
998 }
997 }
999 }
998 }
1000 // file
999 // file
1001 else if (searchType === 'file') {
1000 else if (searchType === 'file') {
1002 var repo_data = data['repo_data'];
1001 var repo_data = data['repo_data'];
1003 var repoIcon = getRepoIcon(repo_data['repository_type']);
1002 var repoIcon = getRepoIcon(repo_data['repository_type']);
1004 if (repoIcon) {
1003 if (repoIcon) {
1005 icon += repoIcon;
1004 icon += repoIcon;
1006 } else {
1005 } else {
1007 icon += '<i class="icon-tag"></i>';
1006 icon += '<i class="icon-tag"></i>';
1008 }
1007 }
1009 }
1008 }
1010 // generic text
1009 // generic text
1011 else if (searchType === 'text') {
1010 else if (searchType === 'text') {
1012 icon = '';
1011 icon = '';
1013 }
1012 }
1014
1013
1015 var tmpl = '<div class="ac-container-wrap">{0}{1}</div>';
1014 var tmpl = '<div class="ac-container-wrap">{0}{1}</div>';
1016 return tmpl.format(icon, valueDisplay);
1015 return tmpl.format(icon, valueDisplay);
1017 };
1016 };
1018
1017
1019 var handleSelect = function(element, suggestion) {
1018 var handleSelect = function(element, suggestion) {
1020 if (suggestion.type === "hint") {
1019 if (suggestion.type === "hint") {
1021 // we skip action
1020 // we skip action
1022 $('#main_filter').focus();
1021 $('#main_filter').focus();
1023 }
1022 }
1024 else if (suggestion.type === "text") {
1023 else if (suggestion.type === "text") {
1025 // we skip action
1024 // we skip action
1026 $('#main_filter').focus();
1025 $('#main_filter').focus();
1027
1026
1028 } else {
1027 } else {
1029 window.location = suggestion['url'];
1028 window.location = suggestion['url'];
1030 }
1029 }
1031 };
1030 };
1032
1031
1033 var autocompleteMainFilterResult = function (suggestion, originalQuery, queryLowerCase) {
1032 var autocompleteMainFilterResult = function (suggestion, originalQuery, queryLowerCase) {
1034 if (queryLowerCase.split(':').length === 2) {
1033 if (queryLowerCase.split(':').length === 2) {
1035 queryLowerCase = queryLowerCase.split(':')[1]
1034 queryLowerCase = queryLowerCase.split(':')[1]
1036 }
1035 }
1037 if (suggestion.type === "text") {
1036 if (suggestion.type === "text") {
1038 // special case we don't want to "skip" display for
1037 // special case we don't want to "skip" display for
1039 return true
1038 return true
1040 }
1039 }
1041 return suggestion.value_display.toLowerCase().indexOf(queryLowerCase) !== -1;
1040 return suggestion.value_display.toLowerCase().indexOf(queryLowerCase) !== -1;
1042 };
1041 };
1043
1042
1044 var cleanContext = {
1043 var cleanContext = {
1045 repo_view_type: null,
1044 repo_view_type: null,
1046
1045
1047 repo_id: null,
1046 repo_id: null,
1048 repo_name: "",
1047 repo_name: "",
1049
1048
1050 repo_group_id: null,
1049 repo_group_id: null,
1051 repo_group_name: null
1050 repo_group_name: null
1052 };
1051 };
1053 var removeGoToFilter = function () {
1052 var removeGoToFilter = function () {
1054 $('.searchTagHidable').hide();
1053 $('.searchTagHidable').hide();
1055 $('#main_filter').autocomplete(
1054 $('#main_filter').autocomplete(
1056 'setOptions', {params:{search_context: cleanContext}});
1055 'setOptions', {params:{search_context: cleanContext}});
1057 };
1056 };
1058
1057
1059 $('#main_filter').autocomplete({
1058 $('#main_filter').autocomplete({
1060 serviceUrl: pyroutes.url('goto_switcher_data'),
1059 serviceUrl: pyroutes.url('goto_switcher_data'),
1061 params: {
1060 params: {
1062 "search_context": templateContext.search_context
1061 "search_context": templateContext.search_context
1063 },
1062 },
1064 minChars:2,
1063 minChars:2,
1065 maxHeight:400,
1064 maxHeight:400,
1066 deferRequestBy: 300, //miliseconds
1065 deferRequestBy: 300, //miliseconds
1067 tabDisabled: true,
1066 tabDisabled: true,
1068 autoSelectFirst: false,
1067 autoSelectFirst: false,
1069 containerClass: 'autocomplete-qfilter-suggestions',
1068 containerClass: 'autocomplete-qfilter-suggestions',
1070 formatResult: autocompleteMainFilterFormatResult,
1069 formatResult: autocompleteMainFilterFormatResult,
1071 lookupFilter: autocompleteMainFilterResult,
1070 lookupFilter: autocompleteMainFilterResult,
1072 onSelect: function (element, suggestion) {
1071 onSelect: function (element, suggestion) {
1073 handleSelect(element, suggestion);
1072 handleSelect(element, suggestion);
1074 return false;
1073 return false;
1075 },
1074 },
1076 onSearchError: function (element, query, jqXHR, textStatus, errorThrown) {
1075 onSearchError: function (element, query, jqXHR, textStatus, errorThrown) {
1077 if (jqXHR !== 'abort') {
1076 if (jqXHR !== 'abort') {
1078 var message = formatErrorMessage(jqXHR, textStatus, errorThrown);
1077 var message = formatErrorMessage(jqXHR, textStatus, errorThrown);
1079 SwalNoAnimation.fire({
1078 SwalNoAnimation.fire({
1080 icon: 'error',
1079 icon: 'error',
1081 title: _gettext('Error during search operation'),
1080 title: _gettext('Error during search operation'),
1082 html: '<span style="white-space: pre-line">{0}</span>'.format(message),
1081 html: '<span style="white-space: pre-line">{0}</span>'.format(message),
1083 }).then(function(result) {
1082 }).then(function(result) {
1084 window.location.reload();
1083 window.location.reload();
1085 })
1084 })
1086 }
1085 }
1087 },
1086 },
1088 onSearchStart: function (params) {
1087 onSearchStart: function (params) {
1089 $('.searchTag.searchTagIcon').html('<i class="icon-spin animate-spin"></i>')
1088 $('.searchTag.searchTagIcon').html('<i class="icon-spin animate-spin"></i>')
1090 },
1089 },
1091 onSearchComplete: function (query, suggestions) {
1090 onSearchComplete: function (query, suggestions) {
1092 $('.searchTag.searchTagIcon').html('<i class="icon-search"></i>')
1091 $('.searchTag.searchTagIcon').html('<i class="icon-search"></i>')
1093 },
1092 },
1094 });
1093 });
1095
1094
1096 showMainFilterBox = function () {
1095 showMainFilterBox = function () {
1097 $('#main_filter_help').toggle();
1096 $('#main_filter_help').toggle();
1098 };
1097 };
1099
1098
1100 $('#main_filter').on('keydown.autocomplete', function (e) {
1099 $('#main_filter').on('keydown.autocomplete', function (e) {
1101
1100
1102 var BACKSPACE = 8;
1101 var BACKSPACE = 8;
1103 var el = $(e.currentTarget);
1102 var el = $(e.currentTarget);
1104 if(e.which === BACKSPACE){
1103 if(e.which === BACKSPACE){
1105 var inputVal = el.val();
1104 var inputVal = el.val();
1106 if (inputVal === ""){
1105 if (inputVal === ""){
1107 removeGoToFilter()
1106 removeGoToFilter()
1108 }
1107 }
1109 }
1108 }
1110 });
1109 });
1111
1110
1112 var dismissNotice = function(noticeId) {
1111 var dismissNotice = function(noticeId) {
1113
1112
1114 var url = pyroutes.url('user_notice_dismiss',
1113 var url = pyroutes.url('user_notice_dismiss',
1115 {"user_id": templateContext.rhodecode_user.user_id});
1114 {"user_id": templateContext.rhodecode_user.user_id});
1116
1115
1117 var postData = {
1116 var postData = {
1118 'csrf_token': CSRF_TOKEN,
1117 'csrf_token': CSRF_TOKEN,
1119 'notice_id': noticeId,
1118 'notice_id': noticeId,
1120 };
1119 };
1121
1120
1122 var success = function(response) {
1121 var success = function(response) {
1123 $('#notice-message-' + noticeId).remove();
1122 $('#notice-message-' + noticeId).remove();
1124 return false;
1123 return false;
1125 };
1124 };
1126 var failure = function(data, textStatus, xhr) {
1125 var failure = function(data, textStatus, xhr) {
1127 alert("error processing request: " + textStatus);
1126 alert("error processing request: " + textStatus);
1128 return false;
1127 return false;
1129 };
1128 };
1130 ajaxPOST(url, postData, success, failure);
1129 ajaxPOST(url, postData, success, failure);
1131 }
1130 }
1132
1131
1133 var hideLicenseWarning = function () {
1132 var hideLicenseWarning = function () {
1134 var fingerprint = templateContext.session_attrs.license_fingerprint;
1133 var fingerprint = templateContext.session_attrs.license_fingerprint;
1135 storeUserSessionAttr('rc_user_session_attr.hide_license_warning', fingerprint);
1134 storeUserSessionAttr('rc_user_session_attr.hide_license_warning', fingerprint);
1136 $('#notifications').hide();
1135 $('#notifications').hide();
1137 }
1136 }
1138
1137
1139 var hideLicenseError = function () {
1138 var hideLicenseError = function () {
1140 var fingerprint = templateContext.session_attrs.license_fingerprint;
1139 var fingerprint = templateContext.session_attrs.license_fingerprint;
1141 storeUserSessionAttr('rc_user_session_attr.hide_license_error', fingerprint);
1140 storeUserSessionAttr('rc_user_session_attr.hide_license_error', fingerprint);
1142 $('#notifications').hide();
1141 $('#notifications').hide();
1143 }
1142 }
1144
1143
1145 </script>
1144 </script>
1146 <script src="${h.asset('js/rhodecode/base/keyboard-bindings.js', ver=c.rhodecode_version_hash)}"></script>
1145 <script src="${h.asset('js/rhodecode/base/keyboard-bindings.js', ver=c.rhodecode_version_hash)}"></script>
1147 </%def>
1146 </%def>
1148
1147
1149 <div class="modal" id="help_kb" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
1148 <div class="modal" id="help_kb" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
1150 <div class="modal-dialog">
1149 <div class="modal-dialog">
1151 <div class="modal-content">
1150 <div class="modal-content">
1152 <div class="modal-header">
1151 <div class="modal-header">
1153 <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
1152 <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
1154 <h4 class="modal-title" id="myModalLabel">${_('Keyboard shortcuts')}</h4>
1153 <h4 class="modal-title" id="myModalLabel">${_('Keyboard shortcuts')}</h4>
1155 </div>
1154 </div>
1156 <div class="modal-body">
1155 <div class="modal-body">
1157 <div class="block-left">
1156 <div class="block-left">
1158 <table class="keyboard-mappings">
1157 <table class="keyboard-mappings">
1159 <tbody>
1158 <tbody>
1160 <tr>
1159 <tr>
1161 <th></th>
1160 <th></th>
1162 <th>${_('Site-wide shortcuts')}</th>
1161 <th>${_('Site-wide shortcuts')}</th>
1163 </tr>
1162 </tr>
1164 <%
1163 <%
1165 elems = [
1164 elems = [
1166 ('/', 'Use quick search box'),
1165 ('/', 'Use quick search box'),
1167 ('g h', 'Goto home page'),
1166 ('g h', 'Goto home page'),
1168 ('g g', 'Goto my private gists page'),
1167 ('g g', 'Goto my private gists page'),
1169 ('g G', 'Goto my public gists page'),
1168 ('g G', 'Goto my public gists page'),
1170 ('g 0-9', 'Goto bookmarked items from 0-9'),
1169 ('g 0-9', 'Goto bookmarked items from 0-9'),
1171 ('n r', 'New repository page'),
1170 ('n r', 'New repository page'),
1172 ('n g', 'New gist page'),
1171 ('n g', 'New gist page'),
1173 ]
1172 ]
1174 %>
1173 %>
1175 %for key, desc in elems:
1174 %for key, desc in elems:
1176 <tr>
1175 <tr>
1177 <td class="keys">
1176 <td class="keys">
1178 <span class="key tag">${key}</span>
1177 <span class="key tag">${key}</span>
1179 </td>
1178 </td>
1180 <td>${desc}</td>
1179 <td>${desc}</td>
1181 </tr>
1180 </tr>
1182 %endfor
1181 %endfor
1183 </tbody>
1182 </tbody>
1184 </table>
1183 </table>
1185 </div>
1184 </div>
1186 <div class="block-left">
1185 <div class="block-left">
1187 <table class="keyboard-mappings">
1186 <table class="keyboard-mappings">
1188 <tbody>
1187 <tbody>
1189 <tr>
1188 <tr>
1190 <th></th>
1189 <th></th>
1191 <th>${_('Repositories')}</th>
1190 <th>${_('Repositories')}</th>
1192 </tr>
1191 </tr>
1193 <%
1192 <%
1194 elems = [
1193 elems = [
1195 ('g s', 'Goto summary page'),
1194 ('g s', 'Goto summary page'),
1196 ('g c', 'Goto changelog page'),
1195 ('g c', 'Goto changelog page'),
1197 ('g f', 'Goto files page'),
1196 ('g f', 'Goto files page'),
1198 ('g F', 'Goto files page with file search activated'),
1197 ('g F', 'Goto files page with file search activated'),
1199 ('g p', 'Goto pull requests page'),
1198 ('g p', 'Goto pull requests page'),
1200 ('g o', 'Goto repository settings'),
1199 ('g o', 'Goto repository settings'),
1201 ('g O', 'Goto repository access permissions settings'),
1200 ('g O', 'Goto repository access permissions settings'),
1202 ('t s', 'Toggle sidebar on some pages'),
1201 ('t s', 'Toggle sidebar on some pages'),
1203 ]
1202 ]
1204 %>
1203 %>
1205 %for key, desc in elems:
1204 %for key, desc in elems:
1206 <tr>
1205 <tr>
1207 <td class="keys">
1206 <td class="keys">
1208 <span class="key tag">${key}</span>
1207 <span class="key tag">${key}</span>
1209 </td>
1208 </td>
1210 <td>${desc}</td>
1209 <td>${desc}</td>
1211 </tr>
1210 </tr>
1212 %endfor
1211 %endfor
1213 </tbody>
1212 </tbody>
1214 </table>
1213 </table>
1215 </div>
1214 </div>
1216 </div>
1215 </div>
1217 <div class="modal-footer">
1216 <div class="modal-footer">
1218 </div>
1217 </div>
1219 </div><!-- /.modal-content -->
1218 </div><!-- /.modal-content -->
1220 </div><!-- /.modal-dialog -->
1219 </div><!-- /.modal-dialog -->
1221 </div><!-- /.modal -->
1220 </div><!-- /.modal -->
1222
1221
1223
1222
1224 <script type="text/javascript">
1223 <script type="text/javascript">
1225 (function () {
1224 (function () {
1226 "use sctrict";
1225 "use sctrict";
1227
1226
1228 // details block auto-hide menu
1227 // details block auto-hide menu
1229 $(document).mouseup(function(e) {
1228 $(document).mouseup(function(e) {
1230 var container = $('.details-inline-block');
1229 var container = $('.details-inline-block');
1231 if (!container.is(e.target) && container.has(e.target).length === 0) {
1230 if (!container.is(e.target) && container.has(e.target).length === 0) {
1232 $('.details-inline-block[open]').removeAttr('open')
1231 $('.details-inline-block[open]').removeAttr('open')
1233 }
1232 }
1234 });
1233 });
1235
1234
1236 var $sideBar = $('.right-sidebar');
1235 var $sideBar = $('.right-sidebar');
1237 var expanded = $sideBar.hasClass('right-sidebar-expanded');
1236 var expanded = $sideBar.hasClass('right-sidebar-expanded');
1238 var sidebarState = templateContext.session_attrs.sidebarState;
1237 var sidebarState = templateContext.session_attrs.sidebarState;
1239 var sidebarEnabled = $('aside.right-sidebar').get(0);
1238 var sidebarEnabled = $('aside.right-sidebar').get(0);
1240
1239
1241 if (sidebarState === 'expanded') {
1240 if (sidebarState === 'expanded') {
1242 expanded = true
1241 expanded = true
1243 } else if (sidebarState === 'collapsed') {
1242 } else if (sidebarState === 'collapsed') {
1244 expanded = false
1243 expanded = false
1245 }
1244 }
1246 if (sidebarEnabled) {
1245 if (sidebarEnabled) {
1247 // show sidebar since it's hidden on load
1246 // show sidebar since it's hidden on load
1248 $('.right-sidebar').show();
1247 $('.right-sidebar').show();
1249
1248
1250 // init based on set initial class, or if defined user session attrs
1249 // init based on set initial class, or if defined user session attrs
1251 if (expanded) {
1250 if (expanded) {
1252 window.expandSidebar();
1251 window.expandSidebar();
1253 window.updateStickyHeader();
1252 window.updateStickyHeader();
1254
1253
1255 } else {
1254 } else {
1256 window.collapseSidebar();
1255 window.collapseSidebar();
1257 window.updateStickyHeader();
1256 window.updateStickyHeader();
1258 }
1257 }
1259 }
1258 }
1260 })()
1259 })()
1261
1260
1262 </script>
1261 </script>
@@ -1,168 +1,169 b''
1 ## snippet for sidebar elements
1 ## snippet for sidebar elements
2 ## usage:
2 ## usage:
3 ## <%namespace name="sidebar" file="/base/sidebar.mako"/>
3 ## <%namespace name="sidebar" file="/base/sidebar.mako"/>
4 ## ${sidebar.comments_table()}
4 ## ${sidebar.comments_table()}
5 <%namespace name="base" file="/base/base.mako"/>
5 <%namespace name="base" file="/base/base.mako"/>
6
6
7 <%def name="comments_table(comments, counter_num, todo_comments=False, draft_comments=False, existing_ids=None, is_pr=True)">
7 <%def name="comments_table(comments, counter_num, todo_comments=False, draft_comments=False, existing_ids=None, is_pr=True)">
8 <%
8 <%
9 if todo_comments:
9 if todo_comments:
10 cls_ = 'todos-content-table'
10 cls_ = 'todos-content-table'
11 def sorter(entry):
11 def sorter(entry):
12 user_id = entry.author.user_id
12 user_id = entry.author.user_id
13 resolved = '1' if entry.resolved else '0'
13 resolved = '1' if entry.resolved else '0'
14 if user_id == c.rhodecode_user.user_id:
14 if user_id == c.rhodecode_user.user_id:
15 # own comments first
15 # own comments first
16 user_id = 0
16 user_id = 0
17 return '{}'.format(str(entry.comment_id).zfill(10000))
17 return '{}'.format(str(entry.comment_id).zfill(10000))
18 elif draft_comments:
18 elif draft_comments:
19 cls_ = 'drafts-content-table'
19 cls_ = 'drafts-content-table'
20 def sorter(entry):
20 def sorter(entry):
21 return '{}'.format(str(entry.comment_id).zfill(10000))
21 return '{}'.format(str(entry.comment_id).zfill(10000))
22 else:
22 else:
23 cls_ = 'comments-content-table'
23 cls_ = 'comments-content-table'
24 def sorter(entry):
24 def sorter(entry):
25 return '{}'.format(str(entry.comment_id).zfill(10000))
25 return '{}'.format(str(entry.comment_id).zfill(10000))
26
26
27 existing_ids = existing_ids or []
27 existing_ids = existing_ids or []
28
28
29 %>
29 %>
30
30
31 <table class="todo-table ${cls_}" data-total-count="${len(comments)}" data-counter="${counter_num}">
31 <table class="todo-table ${cls_}" data-total-count="${len(comments)}" data-counter="${counter_num}">
32
32
33 % for loop_obj, comment_obj in h.looper(reversed(sorted(comments, key=sorter))):
33 % for loop_obj, comment_obj in h.looper(reversed(sorted(comments, key=sorter))):
34 <%
34 <%
35 display = ''
35 display = ''
36 _cls = ''
36 _cls = ''
37 ## Extra precaution to not show drafts in the sidebar for todo/comments
37 ## Extra precaution to not show drafts in the sidebar for todo/comments
38 if comment_obj.draft and not draft_comments:
38 if comment_obj.draft and not draft_comments:
39 continue
39 continue
40 %>
40 %>
41
41
42
42
43 <%
43 <%
44 comment_ver_index = comment_obj.get_index_version(getattr(c, 'versions', []))
44 vers = getattr(c, 'versions', [])
45
46 comment_ver_index = comment_obj.get_index_version(vers)
45 prev_comment_ver_index = 0
47 prev_comment_ver_index = 0
46 if loop_obj.previous:
48 if loop_obj.previous:
47 prev_comment_ver_index = loop_obj.previous.get_index_version(getattr(c, 'versions', []))
49 prev_comment_ver_index = loop_obj.previous.get_index_version(vers)
48
49 ver_info = None
50 ver_info = None
50 if getattr(c, 'versions', []):
51 if vers:
51 ver_info = c.versions[comment_ver_index-1] if comment_ver_index else None
52 ver_info = c.versions[comment_ver_index-1] if comment_ver_index else None
52 %>
53 %>
53 <% hidden_at_ver = comment_obj.outdated_at_version_js(c.at_version_num) %>
54 <% hidden_at_ver = comment_obj.outdated_at_version_js(c.at_version_num) %>
54 <% is_from_old_ver = comment_obj.older_than_version_js(c.at_version_num) %>
55 <% is_from_old_ver = comment_obj.older_than_version_js(c.at_version_num) %>
55 <%
56 <%
56 if (prev_comment_ver_index > comment_ver_index):
57 if prev_comment_ver_index > comment_ver_index:
57 comments_ver_divider = comment_ver_index
58 comments_ver_divider = comment_ver_index
58 else:
59 else:
59 comments_ver_divider = None
60 comments_ver_divider = None
60 %>
61 %>
61
62
62 % if todo_comments:
63 % if todo_comments:
63 % if comment_obj.resolved:
64 % if comment_obj.resolved:
64 <% _cls = 'resolved-todo' %>
65 <% _cls = 'resolved-todo' %>
65 <% display = 'none' %>
66 <% display = 'none' %>
66 % endif
67 % endif
67 % else:
68 % else:
68 ## SKIP TODOs we display them in other area
69 ## SKIP TODOs we display them in other area
69 % if comment_obj.is_todo and not comment_obj.draft:
70 % if comment_obj.is_todo and not comment_obj.draft:
70 <% display = 'none' %>
71 <% display = 'none' %>
71 % endif
72 % endif
72 ## Skip outdated comments
73 ## Skip outdated comments
73 % if comment_obj.outdated:
74 % if comment_obj.outdated:
74 <% display = 'none' %>
75 <% display = 'none' %>
75 <% _cls = 'hidden-comment' %>
76 <% _cls = 'hidden-comment' %>
76 % endif
77 % endif
77 % endif
78 % endif
78
79
79 % if not todo_comments and comments_ver_divider:
80 % if not todo_comments and comments_ver_divider:
80 <tr class="old-comments-marker">
81 <tr class="old-comments-marker">
81 <td colspan="3">
82 <td colspan="3">
82 % if ver_info:
83 % if ver_info:
83 <code>v${comments_ver_divider} ${h.age_component(ver_info.created_on, time_is_local=True, tooltip=False)}</code>
84 <code>v${comments_ver_divider} ${h.age_component(ver_info.created_on, time_is_local=True, tooltip=False)}</code>
84 % else:
85 % else:
85 <code>v${comments_ver_divider}</code>
86 <code>v${comments_ver_divider}</code>
86 % endif
87 % endif
87 </td>
88 </td>
88 </tr>
89 </tr>
89
90
90 % endif
91 % endif
91
92
92 <tr class="${_cls}" style="display: ${display};" data-sidebar-comment-id="${comment_obj.comment_id}">
93 <tr class="${_cls}" style="display: ${display};" data-sidebar-comment-id="${comment_obj.comment_id}">
93 % if draft_comments:
94 % if draft_comments:
94 <td style="width: 15px;">
95 <td style="width: 15px;">
95 ${h.checkbox('submit_draft', id=None, value=comment_obj.comment_id)}
96 ${h.checkbox('submit_draft', id=None, value=comment_obj.comment_id)}
96 </td>
97 </td>
97 % endif
98 % endif
98 <td class="td-todo-number">
99 <td class="td-todo-number">
99 <%
100 <%
100 version_info = ''
101 version_info = ''
101 if is_pr:
102 if is_pr:
102 version_info = (' made in older version (v{})'.format(comment_ver_index) if is_from_old_ver == 'true' else ' made in this version')
103 version_info = (' made in older version (v{})'.format(comment_ver_index) if is_from_old_ver == 'true' else ' made in this version')
103 %>
104 %>
104 ## new comments, since refresh
105 ## new comments, since refresh
105 % if existing_ids and comment_obj.comment_id not in existing_ids:
106 % if existing_ids and comment_obj.comment_id not in existing_ids:
106 <div class="tooltip" style="position: absolute; left: 8px; color: #682668" title="New comment">
107 <div class="tooltip" style="position: absolute; left: 8px; color: #682668" title="New comment">
107 !
108 !
108 </div>
109 </div>
109 % endif
110 % endif
110
111
111 <%
112 <%
112 data = h.str_json({
113 data = h.str_json({
113 'comment_id': comment_obj.comment_id,
114 'comment_id': comment_obj.comment_id,
114 'version_info': version_info,
115 'version_info': version_info,
115 'file_name': comment_obj.f_path,
116 'file_name': comment_obj.f_path,
116 'line_no': comment_obj.line_no,
117 'line_no': comment_obj.line_no,
117 'outdated': comment_obj.outdated,
118 'outdated': comment_obj.outdated,
118 'inline': comment_obj.is_inline,
119 'inline': comment_obj.is_inline,
119 'is_todo': comment_obj.is_todo,
120 'is_todo': comment_obj.is_todo,
120 'created_on': h.format_date(comment_obj.created_on),
121 'created_on': h.format_date(comment_obj.created_on),
121 'datetime': '{}{}'.format(comment_obj.created_on, h.get_timezone(comment_obj.created_on, time_is_local=True)),
122 'datetime': '{}{}'.format(comment_obj.created_on, h.get_timezone(comment_obj.created_on, time_is_local=True)),
122 'review_status': (comment_obj.review_status or '')
123 'review_status': (comment_obj.review_status or '')
123 })
124 })
124
125
125 icon = ''
126 icon = ''
126
127
127 if comment_obj.outdated:
128 if comment_obj.outdated:
128 icon += ' icon-comment-toggle'
129 icon += ' icon-comment-toggle'
129 elif comment_obj.is_inline:
130 elif comment_obj.is_inline:
130 icon += ' icon-code'
131 icon += ' icon-code'
131 else:
132 else:
132 icon += ' icon-comment'
133 icon += ' icon-comment'
133
134
134 if comment_obj.draft:
135 if comment_obj.draft:
135 if comment_obj.is_todo:
136 if comment_obj.is_todo:
136 icon = 'icon-flag-filled icon-draft'
137 icon = 'icon-flag-filled icon-draft'
137 else:
138 else:
138 icon = 'icon-comment icon-draft'
139 icon = 'icon-comment icon-draft'
139
140
140 %>
141 %>
141
142
142 <i id="commentHovercard${comment_obj.comment_id}"
143 <i id="commentHovercard${comment_obj.comment_id}"
143 class="${icon} tooltip-hovercard"
144 class="${icon} tooltip-hovercard"
144 data-hovercard-url="javascript:sidebarComment(${comment_obj.comment_id})"
145 data-hovercard-url="javascript:sidebarComment(${comment_obj.comment_id})"
145 data-comment-json-b64='${h.b64(data)}'>
146 data-comment-json-b64='${h.b64(data)}'>
146 </i>
147 </i>
147
148
148 </td>
149 </td>
149
150
150 <td class="td-todo-gravatar">
151 <td class="td-todo-gravatar">
151 ${base.gravatar(comment_obj.author.email, 16, user=comment_obj.author, tooltip=True, extra_class=['no-margin'])}
152 ${base.gravatar(comment_obj.author.email, 16, user=comment_obj.author, tooltip=True, extra_class=['no-margin'])}
152 </td>
153 </td>
153 <td class="todo-comment-text-wrapper">
154 <td class="todo-comment-text-wrapper">
154 <div class="todo-comment-text ${('todo-resolved' if comment_obj.resolved else '')}">
155 <div class="todo-comment-text ${('todo-resolved' if comment_obj.resolved else '')}">
155 <a class="${('todo-resolved' if comment_obj.resolved else '')} permalink"
156 <a class="${('todo-resolved' if comment_obj.resolved else '')} permalink"
156 href="#comment-${comment_obj.comment_id}"
157 href="#comment-${comment_obj.comment_id}"
157 onclick="return Rhodecode.comments.scrollToComment($('#comment-${comment_obj.comment_id}'), 0, ${hidden_at_ver})">
158 onclick="return Rhodecode.comments.scrollToComment($('#comment-${comment_obj.comment_id}'), 0, ${hidden_at_ver})">
158
159
159 ${h.chop_at_smart(comment_obj.text, '\n', suffix_if_chopped='...')}
160 ${h.chop_at_smart(comment_obj.text, '\n', suffix_if_chopped='...')}
160 </a>
161 </a>
161 </div>
162 </div>
162 </td>
163 </td>
163 </tr>
164 </tr>
164 % endfor
165 % endfor
165
166
166 </table>
167 </table>
167
168
168 </%def> No newline at end of file
169 </%def>
@@ -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_safe(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_str(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_safe(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