##// END OF EJS Templates
repo: added base CE display of new artifacts
marcink -
r3671:91540e53 new-ui
parent child Browse files
Show More
@@ -0,0 +1,48 b''
1 # -*- coding: utf-8 -*-
2
3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 #
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
21 import logging
22
23 from pyramid.view import view_config
24
25 from rhodecode.apps._base import RepoAppView
26 from rhodecode.lib.auth import (
27 LoginRequired, HasRepoPermissionAnyDecorator)
28
29 log = logging.getLogger(__name__)
30
31
32 class RepoArtifactsView(RepoAppView):
33
34 def load_default_context(self):
35 c = self._get_local_tmpl_context(include_app_defaults=True)
36 c.rhodecode_repo = self.rhodecode_vcs_repo
37 return c
38
39 @LoginRequired()
40 @HasRepoPermissionAnyDecorator(
41 'repository.read', 'repository.write', 'repository.admin')
42 @view_config(
43 route_name='repo_artifacts_list', request_method='GET',
44 renderer='rhodecode:templates/artifacts/artifact_list.mako')
45 def repo_artifacts(self):
46 c = self.load_default_context()
47 c.active = 'artifacts'
48 return self._get_template_context(c)
@@ -0,0 +1,28 b''
1 ## -*- coding: utf-8 -*-
2 <%inherit file="/base/base.mako"/>
3
4 <%def name="title()">
5 ${_('{} Artifacts').format(c.repo_name)}
6 %if c.rhodecode_name:
7 &middot; ${h.branding(c.rhodecode_name)}
8 %endif
9 </%def>
10
11 <%def name="breadcrumbs_links()"></%def>
12
13 <%def name="menu_bar_nav()">
14 ${self.menu_items(active='repositories')}
15 </%def>
16
17 <%def name="menu_bar_subnav()">
18 ${self.repo_menu(active='artifacts')}
19 </%def>
20
21 <%def name="main()">
22 <div class="box">
23
24 <h4>${_('This feature is available in RhodeCode EE edition only. Contact {sales_email} to obtain a trial license.').format(sales_email='<a href="mailto:sales@rhodecode.com">sales@rhodecode.com</a>')|n}</h4>
25 <img style="width: 100%; height: 100%" src="${h.asset('images/ee_features/repo_artifacts.png')}"/>
26 </div>
27
28 </%def>
@@ -1,483 +1,488 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
17 17 # This program is dual-licensed. If you wish to learn more about the
18 18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20 from rhodecode.apps._base import add_route_with_slash
21 21
22 22
23 23 def includeme(config):
24 24
25 25 # repo creating checks, special cases that aren't repo routes
26 26 config.add_route(
27 27 name='repo_creating',
28 28 pattern='/{repo_name:.*?[^/]}/repo_creating')
29 29
30 30 config.add_route(
31 31 name='repo_creating_check',
32 32 pattern='/{repo_name:.*?[^/]}/repo_creating_check')
33 33
34 34 # Summary
35 35 # NOTE(marcink): one additional route is defined in very bottom, catch
36 36 # all pattern
37 37 config.add_route(
38 38 name='repo_summary_explicit',
39 39 pattern='/{repo_name:.*?[^/]}/summary', repo_route=True)
40 40 config.add_route(
41 41 name='repo_summary_commits',
42 42 pattern='/{repo_name:.*?[^/]}/summary-commits', repo_route=True)
43 43
44 44 # Commits
45 45 config.add_route(
46 46 name='repo_commit',
47 47 pattern='/{repo_name:.*?[^/]}/changeset/{commit_id}', repo_route=True)
48 48
49 49 config.add_route(
50 50 name='repo_commit_children',
51 51 pattern='/{repo_name:.*?[^/]}/changeset_children/{commit_id}', repo_route=True)
52 52
53 53 config.add_route(
54 54 name='repo_commit_parents',
55 55 pattern='/{repo_name:.*?[^/]}/changeset_parents/{commit_id}', repo_route=True)
56 56
57 57 config.add_route(
58 58 name='repo_commit_raw',
59 59 pattern='/{repo_name:.*?[^/]}/changeset-diff/{commit_id}', repo_route=True)
60 60
61 61 config.add_route(
62 62 name='repo_commit_patch',
63 63 pattern='/{repo_name:.*?[^/]}/changeset-patch/{commit_id}', repo_route=True)
64 64
65 65 config.add_route(
66 66 name='repo_commit_download',
67 67 pattern='/{repo_name:.*?[^/]}/changeset-download/{commit_id}', repo_route=True)
68 68
69 69 config.add_route(
70 70 name='repo_commit_data',
71 71 pattern='/{repo_name:.*?[^/]}/changeset-data/{commit_id}', repo_route=True)
72 72
73 73 config.add_route(
74 74 name='repo_commit_comment_create',
75 75 pattern='/{repo_name:.*?[^/]}/changeset/{commit_id}/comment/create', repo_route=True)
76 76
77 77 config.add_route(
78 78 name='repo_commit_comment_preview',
79 79 pattern='/{repo_name:.*?[^/]}/changeset/{commit_id}/comment/preview', repo_route=True)
80 80
81 81 config.add_route(
82 82 name='repo_commit_comment_delete',
83 83 pattern='/{repo_name:.*?[^/]}/changeset/{commit_id}/comment/{comment_id}/delete', repo_route=True)
84 84
85 85 # still working url for backward compat.
86 86 config.add_route(
87 87 name='repo_commit_raw_deprecated',
88 88 pattern='/{repo_name:.*?[^/]}/raw-changeset/{commit_id}', repo_route=True)
89 89
90 90 # Files
91 91 config.add_route(
92 92 name='repo_archivefile',
93 93 pattern='/{repo_name:.*?[^/]}/archive/{fname}', repo_route=True)
94 94
95 95 config.add_route(
96 96 name='repo_files_diff',
97 97 pattern='/{repo_name:.*?[^/]}/diff/{f_path:.*}', repo_route=True)
98 98 config.add_route( # legacy route to make old links work
99 99 name='repo_files_diff_2way_redirect',
100 100 pattern='/{repo_name:.*?[^/]}/diff-2way/{f_path:.*}', repo_route=True)
101 101
102 102 config.add_route(
103 103 name='repo_files',
104 104 pattern='/{repo_name:.*?[^/]}/files/{commit_id}/{f_path:.*}', repo_route=True)
105 105 config.add_route(
106 106 name='repo_files:default_path',
107 107 pattern='/{repo_name:.*?[^/]}/files/{commit_id}/', repo_route=True)
108 108 config.add_route(
109 109 name='repo_files:default_commit',
110 110 pattern='/{repo_name:.*?[^/]}/files', repo_route=True)
111 111
112 112 config.add_route(
113 113 name='repo_files:rendered',
114 114 pattern='/{repo_name:.*?[^/]}/render/{commit_id}/{f_path:.*}', repo_route=True)
115 115
116 116 config.add_route(
117 117 name='repo_files:annotated',
118 118 pattern='/{repo_name:.*?[^/]}/annotate/{commit_id}/{f_path:.*}', repo_route=True)
119 119 config.add_route(
120 120 name='repo_files:annotated_previous',
121 121 pattern='/{repo_name:.*?[^/]}/annotate-previous/{commit_id}/{f_path:.*}', repo_route=True)
122 122
123 123 config.add_route(
124 124 name='repo_nodetree_full',
125 125 pattern='/{repo_name:.*?[^/]}/nodetree_full/{commit_id}/{f_path:.*}', repo_route=True)
126 126 config.add_route(
127 127 name='repo_nodetree_full:default_path',
128 128 pattern='/{repo_name:.*?[^/]}/nodetree_full/{commit_id}/', repo_route=True)
129 129
130 130 config.add_route(
131 131 name='repo_files_nodelist',
132 132 pattern='/{repo_name:.*?[^/]}/nodelist/{commit_id}/{f_path:.*}', repo_route=True)
133 133
134 134 config.add_route(
135 135 name='repo_file_raw',
136 136 pattern='/{repo_name:.*?[^/]}/raw/{commit_id}/{f_path:.*}', repo_route=True)
137 137
138 138 config.add_route(
139 139 name='repo_file_download',
140 140 pattern='/{repo_name:.*?[^/]}/download/{commit_id}/{f_path:.*}', repo_route=True)
141 141 config.add_route( # backward compat to keep old links working
142 142 name='repo_file_download:legacy',
143 143 pattern='/{repo_name:.*?[^/]}/rawfile/{commit_id}/{f_path:.*}',
144 144 repo_route=True)
145 145
146 146 config.add_route(
147 147 name='repo_file_history',
148 148 pattern='/{repo_name:.*?[^/]}/history/{commit_id}/{f_path:.*}', repo_route=True)
149 149
150 150 config.add_route(
151 151 name='repo_file_authors',
152 152 pattern='/{repo_name:.*?[^/]}/authors/{commit_id}/{f_path:.*}', repo_route=True)
153 153
154 154 config.add_route(
155 155 name='repo_files_remove_file',
156 156 pattern='/{repo_name:.*?[^/]}/remove_file/{commit_id}/{f_path:.*}',
157 157 repo_route=True)
158 158 config.add_route(
159 159 name='repo_files_delete_file',
160 160 pattern='/{repo_name:.*?[^/]}/delete_file/{commit_id}/{f_path:.*}',
161 161 repo_route=True)
162 162 config.add_route(
163 163 name='repo_files_edit_file',
164 164 pattern='/{repo_name:.*?[^/]}/edit_file/{commit_id}/{f_path:.*}',
165 165 repo_route=True)
166 166 config.add_route(
167 167 name='repo_files_update_file',
168 168 pattern='/{repo_name:.*?[^/]}/update_file/{commit_id}/{f_path:.*}',
169 169 repo_route=True)
170 170 config.add_route(
171 171 name='repo_files_add_file',
172 172 pattern='/{repo_name:.*?[^/]}/add_file/{commit_id}/{f_path:.*}',
173 173 repo_route=True)
174 174 config.add_route(
175 175 name='repo_files_create_file',
176 176 pattern='/{repo_name:.*?[^/]}/create_file/{commit_id}/{f_path:.*}',
177 177 repo_route=True)
178 178
179 179 # Refs data
180 180 config.add_route(
181 181 name='repo_refs_data',
182 182 pattern='/{repo_name:.*?[^/]}/refs-data', repo_route=True)
183 183
184 184 config.add_route(
185 185 name='repo_refs_changelog_data',
186 186 pattern='/{repo_name:.*?[^/]}/refs-data-changelog', repo_route=True)
187 187
188 188 config.add_route(
189 189 name='repo_stats',
190 190 pattern='/{repo_name:.*?[^/]}/repo_stats/{commit_id}', repo_route=True)
191 191
192 192 # Changelog
193 193 config.add_route(
194 194 name='repo_changelog',
195 195 pattern='/{repo_name:.*?[^/]}/changelog', repo_route=True)
196 196 config.add_route(
197 197 name='repo_changelog_file',
198 198 pattern='/{repo_name:.*?[^/]}/changelog/{commit_id}/{f_path:.*}', repo_route=True)
199 199 config.add_route(
200 200 name='repo_changelog_elements',
201 201 pattern='/{repo_name:.*?[^/]}/changelog_elements', repo_route=True)
202 202 config.add_route(
203 203 name='repo_changelog_elements_file',
204 204 pattern='/{repo_name:.*?[^/]}/changelog_elements/{commit_id}/{f_path:.*}', repo_route=True)
205 205
206 206 # Compare
207 207 config.add_route(
208 208 name='repo_compare_select',
209 209 pattern='/{repo_name:.*?[^/]}/compare', repo_route=True)
210 210
211 211 config.add_route(
212 212 name='repo_compare',
213 213 pattern='/{repo_name:.*?[^/]}/compare/{source_ref_type}@{source_ref:.*?}...{target_ref_type}@{target_ref:.*?}', repo_route=True)
214 214
215 215 # Tags
216 216 config.add_route(
217 217 name='tags_home',
218 218 pattern='/{repo_name:.*?[^/]}/tags', repo_route=True)
219 219
220 220 # Branches
221 221 config.add_route(
222 222 name='branches_home',
223 223 pattern='/{repo_name:.*?[^/]}/branches', repo_route=True)
224 224
225 225 # Bookmarks
226 226 config.add_route(
227 227 name='bookmarks_home',
228 228 pattern='/{repo_name:.*?[^/]}/bookmarks', repo_route=True)
229 229
230 230 # Forks
231 231 config.add_route(
232 232 name='repo_fork_new',
233 233 pattern='/{repo_name:.*?[^/]}/fork', repo_route=True,
234 234 repo_forbid_when_archived=True,
235 235 repo_accepted_types=['hg', 'git'])
236 236
237 237 config.add_route(
238 238 name='repo_fork_create',
239 239 pattern='/{repo_name:.*?[^/]}/fork/create', repo_route=True,
240 240 repo_forbid_when_archived=True,
241 241 repo_accepted_types=['hg', 'git'])
242 242
243 243 config.add_route(
244 244 name='repo_forks_show_all',
245 245 pattern='/{repo_name:.*?[^/]}/forks', repo_route=True,
246 246 repo_accepted_types=['hg', 'git'])
247 247 config.add_route(
248 248 name='repo_forks_data',
249 249 pattern='/{repo_name:.*?[^/]}/forks/data', repo_route=True,
250 250 repo_accepted_types=['hg', 'git'])
251 251
252 252 # Pull Requests
253 253 config.add_route(
254 254 name='pullrequest_show',
255 255 pattern='/{repo_name:.*?[^/]}/pull-request/{pull_request_id:\d+}',
256 256 repo_route=True)
257 257
258 258 config.add_route(
259 259 name='pullrequest_show_all',
260 260 pattern='/{repo_name:.*?[^/]}/pull-request',
261 261 repo_route=True, repo_accepted_types=['hg', 'git'])
262 262
263 263 config.add_route(
264 264 name='pullrequest_show_all_data',
265 265 pattern='/{repo_name:.*?[^/]}/pull-request-data',
266 266 repo_route=True, repo_accepted_types=['hg', 'git'])
267 267
268 268 config.add_route(
269 269 name='pullrequest_repo_refs',
270 270 pattern='/{repo_name:.*?[^/]}/pull-request/refs/{target_repo_name:.*?[^/]}',
271 271 repo_route=True)
272 272
273 273 config.add_route(
274 274 name='pullrequest_repo_targets',
275 275 pattern='/{repo_name:.*?[^/]}/pull-request/repo-targets',
276 276 repo_route=True)
277 277
278 278 config.add_route(
279 279 name='pullrequest_new',
280 280 pattern='/{repo_name:.*?[^/]}/pull-request/new',
281 281 repo_route=True, repo_accepted_types=['hg', 'git'],
282 282 repo_forbid_when_archived=True)
283 283
284 284 config.add_route(
285 285 name='pullrequest_create',
286 286 pattern='/{repo_name:.*?[^/]}/pull-request/create',
287 287 repo_route=True, repo_accepted_types=['hg', 'git'],
288 288 repo_forbid_when_archived=True)
289 289
290 290 config.add_route(
291 291 name='pullrequest_update',
292 292 pattern='/{repo_name:.*?[^/]}/pull-request/{pull_request_id:\d+}/update',
293 293 repo_route=True, repo_forbid_when_archived=True)
294 294
295 295 config.add_route(
296 296 name='pullrequest_merge',
297 297 pattern='/{repo_name:.*?[^/]}/pull-request/{pull_request_id:\d+}/merge',
298 298 repo_route=True, repo_forbid_when_archived=True)
299 299
300 300 config.add_route(
301 301 name='pullrequest_delete',
302 302 pattern='/{repo_name:.*?[^/]}/pull-request/{pull_request_id:\d+}/delete',
303 303 repo_route=True, repo_forbid_when_archived=True)
304 304
305 305 config.add_route(
306 306 name='pullrequest_comment_create',
307 307 pattern='/{repo_name:.*?[^/]}/pull-request/{pull_request_id:\d+}/comment',
308 308 repo_route=True)
309 309
310 310 config.add_route(
311 311 name='pullrequest_comment_delete',
312 312 pattern='/{repo_name:.*?[^/]}/pull-request/{pull_request_id:\d+}/comment/{comment_id}/delete',
313 313 repo_route=True, repo_accepted_types=['hg', 'git'])
314 314
315 # Artifacts, (EE feature)
316 config.add_route(
317 name='repo_artifacts_list',
318 pattern='/{repo_name:.*?[^/]}/artifacts', repo_route=True)
319
315 320 # Settings
316 321 config.add_route(
317 322 name='edit_repo',
318 323 pattern='/{repo_name:.*?[^/]}/settings', repo_route=True)
319 324 # update is POST on edit_repo
320 325
321 326 # Settings advanced
322 327 config.add_route(
323 328 name='edit_repo_advanced',
324 329 pattern='/{repo_name:.*?[^/]}/settings/advanced', repo_route=True)
325 330 config.add_route(
326 331 name='edit_repo_advanced_archive',
327 332 pattern='/{repo_name:.*?[^/]}/settings/advanced/archive', repo_route=True)
328 333 config.add_route(
329 334 name='edit_repo_advanced_delete',
330 335 pattern='/{repo_name:.*?[^/]}/settings/advanced/delete', repo_route=True)
331 336 config.add_route(
332 337 name='edit_repo_advanced_locking',
333 338 pattern='/{repo_name:.*?[^/]}/settings/advanced/locking', repo_route=True)
334 339 config.add_route(
335 340 name='edit_repo_advanced_journal',
336 341 pattern='/{repo_name:.*?[^/]}/settings/advanced/journal', repo_route=True)
337 342 config.add_route(
338 343 name='edit_repo_advanced_fork',
339 344 pattern='/{repo_name:.*?[^/]}/settings/advanced/fork', repo_route=True)
340 345
341 346 config.add_route(
342 347 name='edit_repo_advanced_hooks',
343 348 pattern='/{repo_name:.*?[^/]}/settings/advanced/hooks', repo_route=True)
344 349
345 350 # Caches
346 351 config.add_route(
347 352 name='edit_repo_caches',
348 353 pattern='/{repo_name:.*?[^/]}/settings/caches', repo_route=True)
349 354
350 355 # Permissions
351 356 config.add_route(
352 357 name='edit_repo_perms',
353 358 pattern='/{repo_name:.*?[^/]}/settings/permissions', repo_route=True)
354 359
355 360 # Permissions Branch (EE feature)
356 361 config.add_route(
357 362 name='edit_repo_perms_branch',
358 363 pattern='/{repo_name:.*?[^/]}/settings/branch_permissions', repo_route=True)
359 364 config.add_route(
360 365 name='edit_repo_perms_branch_delete',
361 366 pattern='/{repo_name:.*?[^/]}/settings/branch_permissions/{rule_id}/delete',
362 367 repo_route=True)
363 368
364 369 # Maintenance
365 370 config.add_route(
366 371 name='edit_repo_maintenance',
367 372 pattern='/{repo_name:.*?[^/]}/settings/maintenance', repo_route=True)
368 373
369 374 config.add_route(
370 375 name='edit_repo_maintenance_execute',
371 376 pattern='/{repo_name:.*?[^/]}/settings/maintenance/execute', repo_route=True)
372 377
373 378 # Fields
374 379 config.add_route(
375 380 name='edit_repo_fields',
376 381 pattern='/{repo_name:.*?[^/]}/settings/fields', repo_route=True)
377 382 config.add_route(
378 383 name='edit_repo_fields_create',
379 384 pattern='/{repo_name:.*?[^/]}/settings/fields/create', repo_route=True)
380 385 config.add_route(
381 386 name='edit_repo_fields_delete',
382 387 pattern='/{repo_name:.*?[^/]}/settings/fields/{field_id}/delete', repo_route=True)
383 388
384 389 # Locking
385 390 config.add_route(
386 391 name='repo_edit_toggle_locking',
387 392 pattern='/{repo_name:.*?[^/]}/settings/toggle_locking', repo_route=True)
388 393
389 394 # Remote
390 395 config.add_route(
391 396 name='edit_repo_remote',
392 397 pattern='/{repo_name:.*?[^/]}/settings/remote', repo_route=True)
393 398 config.add_route(
394 399 name='edit_repo_remote_pull',
395 400 pattern='/{repo_name:.*?[^/]}/settings/remote/pull', repo_route=True)
396 401 config.add_route(
397 402 name='edit_repo_remote_push',
398 403 pattern='/{repo_name:.*?[^/]}/settings/remote/push', repo_route=True)
399 404
400 405 # Statistics
401 406 config.add_route(
402 407 name='edit_repo_statistics',
403 408 pattern='/{repo_name:.*?[^/]}/settings/statistics', repo_route=True)
404 409 config.add_route(
405 410 name='edit_repo_statistics_reset',
406 411 pattern='/{repo_name:.*?[^/]}/settings/statistics/update', repo_route=True)
407 412
408 413 # Issue trackers
409 414 config.add_route(
410 415 name='edit_repo_issuetracker',
411 416 pattern='/{repo_name:.*?[^/]}/settings/issue_trackers', repo_route=True)
412 417 config.add_route(
413 418 name='edit_repo_issuetracker_test',
414 419 pattern='/{repo_name:.*?[^/]}/settings/issue_trackers/test', repo_route=True)
415 420 config.add_route(
416 421 name='edit_repo_issuetracker_delete',
417 422 pattern='/{repo_name:.*?[^/]}/settings/issue_trackers/delete', repo_route=True)
418 423 config.add_route(
419 424 name='edit_repo_issuetracker_update',
420 425 pattern='/{repo_name:.*?[^/]}/settings/issue_trackers/update', repo_route=True)
421 426
422 427 # VCS Settings
423 428 config.add_route(
424 429 name='edit_repo_vcs',
425 430 pattern='/{repo_name:.*?[^/]}/settings/vcs', repo_route=True)
426 431 config.add_route(
427 432 name='edit_repo_vcs_update',
428 433 pattern='/{repo_name:.*?[^/]}/settings/vcs/update', repo_route=True)
429 434
430 435 # svn pattern
431 436 config.add_route(
432 437 name='edit_repo_vcs_svn_pattern_delete',
433 438 pattern='/{repo_name:.*?[^/]}/settings/vcs/svn_pattern/delete', repo_route=True)
434 439
435 440 # Repo Review Rules (EE feature)
436 441 config.add_route(
437 442 name='repo_reviewers',
438 443 pattern='/{repo_name:.*?[^/]}/settings/review/rules', repo_route=True)
439 444
440 445 config.add_route(
441 446 name='repo_default_reviewers_data',
442 447 pattern='/{repo_name:.*?[^/]}/settings/review/default-reviewers', repo_route=True)
443 448
444 449 # Repo Automation (EE feature)
445 450 config.add_route(
446 451 name='repo_automation',
447 452 pattern='/{repo_name:.*?[^/]}/settings/automation', repo_route=True)
448 453
449 454 # Strip
450 455 config.add_route(
451 456 name='edit_repo_strip',
452 457 pattern='/{repo_name:.*?[^/]}/settings/strip', repo_route=True)
453 458
454 459 config.add_route(
455 460 name='strip_check',
456 461 pattern='/{repo_name:.*?[^/]}/settings/strip_check', repo_route=True)
457 462
458 463 config.add_route(
459 464 name='strip_execute',
460 465 pattern='/{repo_name:.*?[^/]}/settings/strip_execute', repo_route=True)
461 466
462 467 # Audit logs
463 468 config.add_route(
464 469 name='edit_repo_audit_logs',
465 470 pattern='/{repo_name:.*?[^/]}/settings/audit_logs', repo_route=True)
466 471
467 472 # ATOM/RSS Feed
468 473 config.add_route(
469 474 name='rss_feed_home',
470 475 pattern='/{repo_name:.*?[^/]}/feed/rss', repo_route=True)
471 476
472 477 config.add_route(
473 478 name='atom_feed_home',
474 479 pattern='/{repo_name:.*?[^/]}/feed/atom', repo_route=True)
475 480
476 481 # NOTE(marcink): needs to be at the end for catch-all
477 482 add_route_with_slash(
478 483 config,
479 484 name='repo_summary',
480 485 pattern='/{repo_name:.*?[^/]}', repo_route=True)
481 486
482 487 # Scan module for configuration decorators.
483 488 config.scan('.views', ignore='.tests')
@@ -1,960 +1,962 b''
1 1 ## -*- coding: utf-8 -*-
2 2 <%inherit file="root.mako"/>
3 3
4 4 <%include file="/ejs_templates/templates.html"/>
5 5
6 6 <div class="outerwrapper">
7 7 <!-- HEADER -->
8 8 <div class="header">
9 9 <div id="header-inner" class="wrapper">
10 10 <div id="logo">
11 11 <div class="logo-wrapper">
12 12 <a href="${h.route_path('home')}"><img src="${h.asset('images/rhodecode-logo-white-60x60.png')}" alt="RhodeCode"/></a>
13 13 </div>
14 14 % if c.rhodecode_name:
15 15 <div class="branding">
16 16 <a href="${h.route_path('home')}">${h.branding(c.rhodecode_name)}</a>
17 17 </div>
18 18 % endif
19 19 </div>
20 20 <!-- MENU BAR NAV -->
21 21 ${self.menu_bar_nav()}
22 22 <!-- END MENU BAR NAV -->
23 23 </div>
24 24 </div>
25 25 ${self.menu_bar_subnav()}
26 26 <!-- END HEADER -->
27 27
28 28 <!-- CONTENT -->
29 29 <div id="content" class="wrapper">
30 30
31 31 <rhodecode-toast id="notifications"></rhodecode-toast>
32 32
33 33 <div class="main">
34 34 ${next.main()}
35 35 </div>
36 36 </div>
37 37 <!-- END CONTENT -->
38 38
39 39 </div>
40 40 <!-- FOOTER -->
41 41 <div id="footer">
42 42 <div id="footer-inner" class="title wrapper">
43 43 <div>
44 44 <p class="footer-link-right">
45 45 % if c.visual.show_version:
46 46 RhodeCode Enterprise ${c.rhodecode_version} ${c.rhodecode_edition}
47 47 % endif
48 48 &copy; 2010-${h.datetime.today().year}, <a href="${h.route_url('rhodecode_official')}" target="_blank">RhodeCode GmbH</a>. All rights reserved.
49 49 % if c.visual.rhodecode_support_url:
50 50 <a href="${c.visual.rhodecode_support_url}" target="_blank">${_('Support')}</a>
51 51 % endif
52 52 </p>
53 53 <% sid = 'block' if request.GET.get('showrcid') else 'none' %>
54 54 <p class="server-instance" style="display:${sid}">
55 55 ## display hidden instance ID if specially defined
56 56 % if c.rhodecode_instanceid:
57 57 ${_('RhodeCode instance id: {}').format(c.rhodecode_instanceid)}
58 58 % endif
59 59 </p>
60 60 </div>
61 61 </div>
62 62 </div>
63 63
64 64 <!-- END FOOTER -->
65 65
66 66 ### MAKO DEFS ###
67 67
68 68 <%def name="menu_bar_subnav()">
69 69 </%def>
70 70
71 71 <%def name="breadcrumbs(class_='breadcrumbs')">
72 72 <div class="${class_}">
73 73 ${self.breadcrumbs_links()}
74 74 </div>
75 75 </%def>
76 76
77 77 <%def name="admin_menu(active=None)">
78 78 <%
79 79 def is_active(selected):
80 80 if selected == active:
81 81 return "active"
82 82 %>
83 83
84 84 <div id="context-bar">
85 85 <div class="wrapper">
86 86 <div class="title">
87 87 <div class="title-content">
88 88 <div class="title-main">
89 89 % if c.is_super_admin:
90 90 ${_('Super Admin Panel')}
91 91 % else:
92 92 ${_('Delegated Admin Panel')}
93 93 % endif
94 94 </div>
95 95 </div>
96 96 </div>
97 97
98 98 <ul id="context-pages" class="navigation horizontal-list">
99 99
100 100 ## super admin case
101 101 % if c.is_super_admin:
102 102 <li class="${is_active('audit_logs')}"><a href="${h.route_path('admin_audit_logs')}">${_('Admin audit logs')}</a></li>
103 103 <li class="${is_active('repositories')}"><a href="${h.route_path('repos')}">${_('Repositories')}</a></li>
104 104 <li class="${is_active('repository_groups')}"><a href="${h.route_path('repo_groups')}">${_('Repository groups')}</a></li>
105 105 <li class="${is_active('users')}"><a href="${h.route_path('users')}">${_('Users')}</a></li>
106 106 <li class="${is_active('user_groups')}"><a href="${h.route_path('user_groups')}">${_('User groups')}</a></li>
107 107 <li class="${is_active('permissions')}"><a href="${h.route_path('admin_permissions_application')}">${_('Permissions')}</a></li>
108 108 <li class="${is_active('authentication')}"><a href="${h.route_path('auth_home', traverse='')}">${_('Authentication')}</a></li>
109 109 <li class="${is_active('integrations')}"><a href="${h.route_path('global_integrations_home')}">${_('Integrations')}</a></li>
110 110 <li class="${is_active('defaults')}"><a href="${h.route_path('admin_defaults_repositories')}">${_('Defaults')}</a></li>
111 111 <li class="${is_active('settings')}"><a href="${h.route_path('admin_settings')}">${_('Settings')}</a></li>
112 112
113 113 ## delegated admin
114 114 % elif c.is_delegated_admin:
115 115 <%
116 116 repositories=c.auth_user.repositories_admin or c.can_create_repo
117 117 repository_groups=c.auth_user.repository_groups_admin or c.can_create_repo_group
118 118 user_groups=c.auth_user.user_groups_admin or c.can_create_user_group
119 119 %>
120 120
121 121 %if repositories:
122 122 <li class="${is_active('repositories')} local-admin-repos"><a href="${h.route_path('repos')}">${_('Repositories')}</a></li>
123 123 %endif
124 124 %if repository_groups:
125 125 <li class="${is_active('repository_groups')} local-admin-repo-groups"><a href="${h.route_path('repo_groups')}">${_('Repository groups')}</a></li>
126 126 %endif
127 127 %if user_groups:
128 128 <li class="${is_active('user_groups')} local-admin-user-groups"><a href="${h.route_path('user_groups')}">${_('User groups')}</a></li>
129 129 %endif
130 130 % endif
131 131 </ul>
132 132
133 133 </div>
134 134 <div class="clear"></div>
135 135 </div>
136 136 </%def>
137 137
138 138 <%def name="dt_info_panel(elements)">
139 139 <dl class="dl-horizontal">
140 140 %for dt, dd, title, show_items in elements:
141 141 <dt>${dt}:</dt>
142 142 <dd title="${h.tooltip(title)}">
143 143 %if callable(dd):
144 144 ## allow lazy evaluation of elements
145 145 ${dd()}
146 146 %else:
147 147 ${dd}
148 148 %endif
149 149 %if show_items:
150 150 <span class="btn-collapse" data-toggle="item-${h.md5_safe(dt)[:6]}-details">${_('Show More')} </span>
151 151 %endif
152 152 </dd>
153 153
154 154 %if show_items:
155 155 <div class="collapsable-content" data-toggle="item-${h.md5_safe(dt)[:6]}-details" style="display: none">
156 156 %for item in show_items:
157 157 <dt></dt>
158 158 <dd>${item}</dd>
159 159 %endfor
160 160 </div>
161 161 %endif
162 162
163 163 %endfor
164 164 </dl>
165 165 </%def>
166 166
167 167 <%def name="gravatar(email, size=16)">
168 168 <%
169 169 if (size > 16):
170 170 gravatar_class = 'gravatar gravatar-large'
171 171 else:
172 172 gravatar_class = 'gravatar'
173 173 %>
174 174 <%doc>
175 175 TODO: johbo: For now we serve double size images to make it smooth
176 176 for retina. This is how it worked until now. Should be replaced
177 177 with a better solution at some point.
178 178 </%doc>
179 179 <img class="${gravatar_class}" src="${h.gravatar_url(email, size * 2)}" height="${size}" width="${size}">
180 180 </%def>
181 181
182 182
183 183 <%def name="gravatar_with_user(contact, size=16, show_disabled=False)">
184 184 <% email = h.email_or_none(contact) %>
185 185 <div class="rc-user tooltip" title="${h.tooltip(h.author_string(email))}">
186 186 ${self.gravatar(email, size)}
187 187 <span class="${'user user-disabled' if show_disabled else 'user'}"> ${h.link_to_user(contact)}</span>
188 188 </div>
189 189 </%def>
190 190
191 191
192 192 <%def name="repo_page_title(repo_instance)">
193 193 <div class="title-content repo-title">
194 194 <div class="title-main">
195 195 ## SVN/HG/GIT icons
196 196 %if h.is_hg(repo_instance):
197 197 <i class="icon-hg"></i>
198 198 %endif
199 199 %if h.is_git(repo_instance):
200 200 <i class="icon-git"></i>
201 201 %endif
202 202 %if h.is_svn(repo_instance):
203 203 <i class="icon-svn"></i>
204 204 %endif
205 205
206 206 ## public/private
207 207 %if repo_instance.private:
208 208 <i class="icon-repo-private"></i>
209 209 %else:
210 210 <i class="icon-repo-public"></i>
211 211 %endif
212 212
213 213 ## repo name with group name
214 214 ${h.breadcrumb_repo_link(repo_instance)}
215 215
216 216 ## Context Actions
217 217 <div class="pull-right">
218 218 %if c.rhodecode_user.username != h.DEFAULT_USER:
219 219 <a href="${h.route_path('atom_feed_home', repo_name=c.rhodecode_db_repo.repo_name, _query=dict(auth_token=c.rhodecode_user.feed_token))}" title="${_('RSS Feed')}" class="btn btn-sm"><i class="icon-rss-sign"></i>RSS</a>
220 220
221 221 <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 '')}">
222 222 % if c.repository_is_user_following:
223 223 Unwatch
224 224 % else:
225 225 Watch
226 226 % endif
227 227
228 228 </a>
229 229 %else:
230 230 <a href="${h.route_path('atom_feed_home', repo_name=c.rhodecode_db_repo.repo_name)}" title="${_('RSS Feed')}" class="btn btn-sm"><i class="icon-rss-sign"></i>RSS</a>
231 231 %endif
232 232 </div>
233 233
234 234 </div>
235 235
236 236 ## FORKED
237 237 %if repo_instance.fork:
238 238 <p class="discreet">
239 239 <i class="icon-code-fork"></i> ${_('Fork of')}
240 240 ${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))}
241 241 </p>
242 242 %endif
243 243
244 244 ## IMPORTED FROM REMOTE
245 245 %if repo_instance.clone_uri:
246 246 <p class="discreet">
247 247 <i class="icon-code-fork"></i> ${_('Clone from')}
248 248 <a href="${h.safe_str(h.hide_credentials(repo_instance.clone_uri))}">${h.hide_credentials(repo_instance.clone_uri)}</a>
249 249 </p>
250 250 %endif
251 251
252 252 ## LOCKING STATUS
253 253 %if repo_instance.locked[0]:
254 254 <p class="locking_locked discreet">
255 255 <i class="icon-repo-lock"></i>
256 256 ${_('Repository locked by %(user)s') % {'user': h.person_by_id(repo_instance.locked[0])}}
257 257 </p>
258 258 %elif repo_instance.enable_locking:
259 259 <p class="locking_unlocked discreet">
260 260 <i class="icon-repo-unlock"></i>
261 261 ${_('Repository not locked. Pull repository to lock it.')}
262 262 </p>
263 263 %endif
264 264
265 265 </div>
266 266 </%def>
267 267
268 268 <%def name="repo_menu(active=None)">
269 269 <%
270 270 def is_active(selected):
271 271 if selected == active:
272 272 return "active"
273 273 %>
274 274
275 275 <!--- REPO CONTEXT BAR -->
276 276 <div id="context-bar">
277 277 <div class="wrapper">
278 278
279 279 <div class="title">
280 280 ${self.repo_page_title(c.rhodecode_db_repo)}
281 281 </div>
282 282
283 283 <ul id="context-pages" class="navigation horizontal-list">
284 284 <li class="${is_active('summary')}"><a class="menulink" href="${h.route_path('repo_summary', repo_name=c.repo_name)}"><div class="menulabel">${_('Summary')}</div></a></li>
285 285 <li class="${is_active('changelog')}"><a class="menulink" href="${h.route_path('repo_changelog', repo_name=c.repo_name)}"><div class="menulabel">${_('Changelog')}</div></a></li>
286 286 <li class="${is_active('files')}"><a class="menulink" href="${h.route_path('repo_files', repo_name=c.repo_name, commit_id=c.rhodecode_db_repo.landing_rev[1], f_path='')}"><div class="menulabel">${_('Files')}</div></a></li>
287 287 <li class="${is_active('compare')}"><a class="menulink" href="${h.route_path('repo_compare_select',repo_name=c.repo_name)}"><div class="menulabel">${_('Compare')}</div></a></li>
288 288
289 289 ## TODO: anderson: ideally it would have a function on the scm_instance "enable_pullrequest() and enable_fork()"
290 290 %if c.rhodecode_db_repo.repo_type in ['git','hg']:
291 291 <li class="${is_active('showpullrequest')}">
292 292 <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)}">
293 293 <div class="menulabel">
294 294 %if c.repository_pull_requests == 1:
295 295 ${c.repository_pull_requests} ${_('Pull Request')}
296 296 %else:
297 297 ${c.repository_pull_requests} ${_('Pull Requests')}
298 298 %endif
299 299 </div>
300 300 </a>
301 301 </li>
302 302 %endif
303 303
304 <li class="${is_active('artifacts')}"><a class="menulink" href="${h.route_path('repo_artifacts_list',repo_name=c.repo_name)}"><div class="menulabel">${_('Artifacts')}</div></a></li>
305
304 306 %if h.HasRepoPermissionAll('repository.admin')(c.repo_name):
305 307 <li class="${is_active('settings')}"><a class="menulink" href="${h.route_path('edit_repo',repo_name=c.repo_name)}"><div class="menulabel">${_('Repository Settings')}</div></a></li>
306 308 %endif
307 309
308 310 <li class="${is_active('options')}">
309 311 <a class="menulink dropdown">
310 312 <div class="menulabel">${_('Options')} <div class="show_more"></div></div>
311 313 </a>
312 314 <ul class="submenu">
313 315
314 316 %if c.rhodecode_db_repo.fork:
315 317 <li>
316 318 <a title="${h.tooltip(_('Compare fork with %s' % c.rhodecode_db_repo.fork.repo_name))}"
317 319 href="${h.route_path('repo_compare',
318 320 repo_name=c.rhodecode_db_repo.fork.repo_name,
319 321 source_ref_type=c.rhodecode_db_repo.landing_rev[0],
320 322 source_ref=c.rhodecode_db_repo.landing_rev[1],
321 323 target_repo=c.repo_name,target_ref_type='branch' if request.GET.get('branch') else c.rhodecode_db_repo.landing_rev[0],
322 324 target_ref=request.GET.get('branch') or c.rhodecode_db_repo.landing_rev[1],
323 325 _query=dict(merge=1))}"
324 326 >
325 327 ${_('Compare fork')}
326 328 </a>
327 329 </li>
328 330 %endif
329 331
330 332 %if h.HasRepoPermissionAny('repository.write','repository.admin')(c.repo_name) and c.rhodecode_db_repo.enable_locking:
331 333 %if c.rhodecode_db_repo.locked[0]:
332 334 <li><a class="locking_del" href="${h.route_path('repo_edit_toggle_locking',repo_name=c.repo_name)}">${_('Unlock')}</a></li>
333 335 %else:
334 336 <li><a class="locking_add" href="${h.route_path('repo_edit_toggle_locking',repo_name=c.repo_name)}">${_('Lock')}</a></li>
335 337 %endif
336 338 %endif
337 339 %if c.rhodecode_user.username != h.DEFAULT_USER:
338 340 %if c.rhodecode_db_repo.repo_type in ['git','hg']:
339 341 <li><a href="${h.route_path('repo_fork_new',repo_name=c.repo_name)}">${_('Fork')}</a></li>
340 342 <li><a href="${h.route_path('pullrequest_new',repo_name=c.repo_name)}">${_('Create Pull Request')}</a></li>
341 343 %endif
342 344 %endif
343 345 </ul>
344 346 </li>
345 347 </ul>
346 348 </div>
347 349 <div class="clear"></div>
348 350 </div>
349 351 % if c.rhodecode_db_repo.archived:
350 352 <div class="alert alert-warning text-center">
351 353 <strong>${_('This repository has been archived. It is now read-only.')}</strong>
352 354 </div>
353 355 % endif
354 356 <!--- REPO END CONTEXT BAR -->
355 357
356 358 </%def>
357 359
358 360 <%def name="repo_group_page_title(repo_group_instance)">
359 361 <div class="title-content">
360 362 <div class="title-main">
361 363 ## Repository Group icon
362 364 <i class="icon-folder-close"></i>
363 365
364 366 ## repo name with group name
365 367 ${h.breadcrumb_repo_group_link(repo_group_instance)}
366 368 </div>
367 369
368 370 <%namespace name="dt" file="/data_table/_dt_elements.mako"/>
369 371 <div class="repo-group-desc discreet">
370 372 ${dt.repo_group_desc(repo_group_instance.description_safe, repo_group_instance.personal, c.visual.stylify_metatags)}
371 373 </div>
372 374
373 375 </div>
374 376 </%def>
375 377
376 378 <%def name="repo_group_menu(active=None)">
377 379 <%
378 380 def is_active(selected):
379 381 if selected == active:
380 382 return "active"
381 383
382 384 gr_name = c.repo_group.group_name if c.repo_group else None
383 385 # create repositories with write permission on group is set to true
384 386 create_on_write = h.HasPermissionAny('hg.create.write_on_repogroup.true')()
385 387 group_admin = h.HasRepoGroupPermissionAny('group.admin')(gr_name, 'group admin index page')
386 388 group_write = h.HasRepoGroupPermissionAny('group.write')(gr_name, 'can write into group index page')
387 389
388 390 %>
389 391
390 392 <!--- REPO GROUP CONTEXT BAR -->
391 393 <div id="context-bar">
392 394 <div class="wrapper">
393 395 <div class="title">
394 396 ${self.repo_group_page_title(c.repo_group)}
395 397 </div>
396 398
397 399 <ul id="context-pages" class="navigation horizontal-list">
398 400 <li class="${is_active('home')}"><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></li>
399 401 % if c.is_super_admin or group_admin:
400 402 <li class="${is_active('settings')}"><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></li>
401 403 % endif
402 404
403 405 <li class="${is_active('options')}">
404 406 <a class="menulink dropdown">
405 407 <div class="menulabel">${_('Options')} <div class="show_more"></div></div>
406 408 </a>
407 409 <ul class="submenu">
408 410 %if c.is_super_admin or group_admin or (group_write and create_on_write):
409 411 <li><a href="${h.route_path('repo_new',_query=dict(parent_group=c.repo_group.group_id))}">${_('Add Repository')}</a></li>
410 412 %endif
411 413 %if c.is_super_admin or group_admin:
412 414 <li><a href="${h.route_path('repo_group_new',_query=dict(parent_group=c.repo_group.group_id))}">${_(u'Add Parent Group')}</a></li>
413 415 %endif
414 416 </ul>
415 417 </li>
416 418 </ul>
417 419 </div>
418 420 <div class="clear"></div>
419 421 </div>
420 422
421 423 <!--- REPO GROUP CONTEXT BAR -->
422 424
423 425 </%def>
424 426
425 427
426 428 <%def name="usermenu(active=False)">
427 429 ## USER MENU
428 430 <li id="quick_login_li" class="${'active' if active else ''}">
429 431 % if c.rhodecode_user.username == h.DEFAULT_USER:
430 432 <a id="quick_login_link" class="menulink childs" href="${h.route_path('login', _query={'came_from': h.current_route_path(request)})}">
431 433 ${gravatar(c.rhodecode_user.email, 20)}
432 434 <span class="user">
433 435 <span>${_('Sign in')}</span>
434 436 </span>
435 437 </a>
436 438 % else:
437 439 ## logged in user
438 440 <a id="quick_login_link" class="menulink childs">
439 441 ${gravatar(c.rhodecode_user.email, 20)}
440 442 <span class="user">
441 443 <span class="menu_link_user">${c.rhodecode_user.username}</span>
442 444 <div class="show_more"></div>
443 445 </span>
444 446 </a>
445 447 ## subnav with menu for logged in user
446 448 <div class="user-menu submenu">
447 449 <div id="quick_login">
448 450 %if c.rhodecode_user.username != h.DEFAULT_USER:
449 451 <div class="">
450 452 <div class="big_gravatar">${gravatar(c.rhodecode_user.email, 48)}</div>
451 453 <div class="full_name">${c.rhodecode_user.full_name_or_username}</div>
452 454 <div class="email">${c.rhodecode_user.email}</div>
453 455 </div>
454 456 <div class="">
455 457 <ol class="links">
456 458 <li>${h.link_to(_(u'My account'),h.route_path('my_account_profile'))}</li>
457 459 % if c.rhodecode_user.personal_repo_group:
458 460 <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>
459 461 % endif
460 462 <li>${h.link_to(_(u'Pull Requests'), h.route_path('my_account_pullrequests'))}</li>
461 463 ## bookmark-items
462 464 <li class="bookmark-items">
463 465 ${_('Bookmarks')}
464 466 <div class="pull-right">
465 467 <a href="${h.route_path('my_account_bookmarks')}">${_('Manage')}</a>
466 468 </div>
467 469 </li>
468 470 % if not c.bookmark_items:
469 471 <li>
470 472 <a href="${h.route_path('my_account_bookmarks')}">${_('No Bookmarks yet.')}</a>
471 473 </li>
472 474 % endif
473 475 % for item in c.bookmark_items:
474 476 <li>
475 477 % if item.repository:
476 478 <div>
477 479 <a class="bookmark-item" href="${h.route_path('my_account_goto_bookmark', bookmark_id=item.position)}">
478 480 <code>${item.position}</code>
479 481 % if item.repository.repo_type == 'hg':
480 482 <i class="icon-hg" title="${_('Repository')}" style="font-size: 16px"></i>
481 483 % elif item.repository.repo_type == 'git':
482 484 <i class="icon-git" title="${_('Repository')}" style="font-size: 16px"></i>
483 485 % elif item.repository.repo_type == 'svn':
484 486 <i class="icon-svn" title="${_('Repository')}" style="font-size: 16px"></i>
485 487 % endif
486 488 ${(item.title or h.shorter(item.repository.repo_name, 30))}
487 489 </a>
488 490 </div>
489 491 % elif item.repository_group:
490 492 <div>
491 493 <a class="bookmark-item" href="${h.route_path('my_account_goto_bookmark', bookmark_id=item.position)}">
492 494 <code>${item.position}</code>
493 495 <i class="icon-folder-close" title="${_('Repository group')}" style="font-size: 16px"></i>
494 496 ${(item.title or h.shorter(item.repository_group.group_name, 30))}
495 497 </a>
496 498 </div>
497 499 % else:
498 500 <a class="bookmark-item" href="${h.route_path('my_account_goto_bookmark', bookmark_id=item.position)}">
499 501 <code>${item.position}</code>
500 502 ${item.title}
501 503 </a>
502 504 % endif
503 505 </li>
504 506 % endfor
505 507
506 508 <li class="logout">
507 509 ${h.secure_form(h.route_path('logout'), request=request)}
508 510 ${h.submit('log_out', _(u'Sign Out'),class_="btn btn-primary")}
509 511 ${h.end_form()}
510 512 </li>
511 513 </ol>
512 514 </div>
513 515 %endif
514 516 </div>
515 517 </div>
516 518 ## unread counter
517 519 <div class="pill_container">
518 520 <a class="menu_link_notifications ${'empty' if c.unread_notifications == 0 else ''}" href="${h.route_path('notifications_show_all')}">${c.unread_notifications}</a>
519 521 </div>
520 522 % endif
521 523 </li>
522 524 </%def>
523 525
524 526 <%def name="menu_items(active=None)">
525 527 <%
526 528 def is_active(selected):
527 529 if selected == active:
528 530 return "active"
529 531 return ""
530 532 %>
531 533
532 534 <ul id="quick" class="main_nav navigation horizontal-list">
533 535 ## notice box for important system messages
534 536 <li style="display: none">
535 537 <a class="notice-box" href="#openNotice" onclick="showNoticeBox(); return false">
536 538 <div class="menulabel-notice" >
537 539 0
538 540 </div>
539 541 </a>
540 542 </li>
541 543
542 544 ## Main filter
543 545 <li>
544 546 <div class="menulabel main_filter_box">
545 547 <div class="main_filter_input_box">
546 548 <ul class="searchItems">
547 549
548 550 % if c.template_context['search_context']['repo_id']:
549 551 <li class="searchTag searchTagFilter searchTagHidable" >
550 552 ##<a href="${h.route_path('search_repo',repo_name=c.template_context['search_context']['repo_name'])}">
551 553 <span class="tag">
552 554 This repo
553 555 <a href="#removeGoToFilter" onclick="removeGoToFilter(); return false"><i class="icon-delete"></i></a>
554 556 </span>
555 557 ##</a>
556 558 </li>
557 559 % elif c.template_context['search_context']['repo_group_id']:
558 560 <li class="searchTag searchTagFilter searchTagHidable">
559 561 ##<a href="${h.route_path('search_repo_group',repo_group_name=c.template_context['search_context']['repo_group_name'])}">
560 562 <span class="tag">
561 563 This group
562 564 <a href="#removeGoToFilter" onclick="removeGoToFilter(); return false"><i class="icon-delete"></i></a>
563 565 </span>
564 566 ##</a>
565 567 </li>
566 568 % endif
567 569
568 570 <li class="searchTagInput">
569 571 <input class="main_filter_input" id="main_filter" size="15" type="text" name="main_filter" placeholder="${_('search / go to...')}" value="" />
570 572 </li>
571 573 <li class="searchTag searchTagHelp">
572 574 <a href="#showFilterHelp" onclick="showMainFilterBox(); return false">?</a>
573 575 </li>
574 576 </ul>
575 577 </div>
576 578 </div>
577 579
578 580 <div id="main_filter_help" style="display: none">
579 581 - Use '/' key to quickly access this field.
580 582
581 583 - Enter a name of repository, or repository group for quick search.
582 584
583 585 - Prefix query to allow special search:
584 586
585 587 user:admin, to search for usernames, always global
586 588
587 589 user_group:devops, to search for user groups, always global
588 590
589 591 commit:efced4, to search for commits, scoped to repositories or groups
590 592
591 593 file:models.py, to search for file paths, scoped to repositories or groups
592 594
593 595 % if c.template_context['search_context']['repo_id']:
594 596 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>
595 597 % elif c.template_context['search_context']['repo_group_id']:
596 598 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>
597 599 % else:
598 600 For advanced full text search visit: <a href="${h.route_path('search')}">global search</a>
599 601 % endif
600 602 </div>
601 603 </li>
602 604
603 605 ## ROOT MENU
604 606 <li class="${is_active('home')}">
605 607 <a class="menulink" title="${_('Home')}" href="${h.route_path('home')}">
606 608 <div class="menulabel">${_('Home')}</div>
607 609 </a>
608 610 </li>
609 611
610 612 %if c.rhodecode_user.username != h.DEFAULT_USER:
611 613 <li class="${is_active('journal')}">
612 614 <a class="menulink" title="${_('Show activity journal')}" href="${h.route_path('journal')}">
613 615 <div class="menulabel">${_('Journal')}</div>
614 616 </a>
615 617 </li>
616 618 %else:
617 619 <li class="${is_active('journal')}">
618 620 <a class="menulink" title="${_('Show Public activity journal')}" href="${h.route_path('journal_public')}">
619 621 <div class="menulabel">${_('Public journal')}</div>
620 622 </a>
621 623 </li>
622 624 %endif
623 625
624 626 <li class="${is_active('gists')}">
625 627 <a class="menulink childs" title="${_('Show Gists')}" href="${h.route_path('gists_show')}">
626 628 <div class="menulabel">${_('Gists')}</div>
627 629 </a>
628 630 </li>
629 631
630 632 % if c.is_super_admin or c.is_delegated_admin:
631 633 <li class="${is_active('admin')}">
632 634 <a class="menulink childs" title="${_('Admin settings')}" href="${h.route_path('admin_home')}">
633 635 <div class="menulabel">${_('Admin')} </div>
634 636 </a>
635 637 </li>
636 638 % endif
637 639
638 640 ## render extra user menu
639 641 ${usermenu(active=(active=='my_account'))}
640 642
641 643 % if c.debug_style:
642 644 <li>
643 645 <a class="menulink" title="${_('Style')}" href="${h.route_path('debug_style_home')}">
644 646 <div class="menulabel">${_('[Style]')}</div>
645 647 </a>
646 648 </li>
647 649 % endif
648 650 </ul>
649 651
650 652 <script type="text/javascript">
651 653 var visualShowPublicIcon = "${c.visual.show_public_icon}" == "True";
652 654
653 655 var formatRepoResult = function(result, container, query, escapeMarkup) {
654 656 return function(data, escapeMarkup) {
655 657 if (!data.repo_id){
656 658 return data.text; // optgroup text Repositories
657 659 }
658 660
659 661 var tmpl = '';
660 662 var repoType = data['repo_type'];
661 663 var repoName = data['text'];
662 664
663 665 if(data && data.type == 'repo'){
664 666 if(repoType === 'hg'){
665 667 tmpl += '<i class="icon-hg"></i> ';
666 668 }
667 669 else if(repoType === 'git'){
668 670 tmpl += '<i class="icon-git"></i> ';
669 671 }
670 672 else if(repoType === 'svn'){
671 673 tmpl += '<i class="icon-svn"></i> ';
672 674 }
673 675 if(data['private']){
674 676 tmpl += '<i class="icon-lock" ></i> ';
675 677 }
676 678 else if(visualShowPublicIcon){
677 679 tmpl += '<i class="icon-unlock-alt"></i> ';
678 680 }
679 681 }
680 682 tmpl += escapeMarkup(repoName);
681 683 return tmpl;
682 684
683 685 }(result, escapeMarkup);
684 686 };
685 687
686 688 var formatRepoGroupResult = function(result, container, query, escapeMarkup) {
687 689 return function(data, escapeMarkup) {
688 690 if (!data.repo_group_id){
689 691 return data.text; // optgroup text Repositories
690 692 }
691 693
692 694 var tmpl = '';
693 695 var repoGroupName = data['text'];
694 696
695 697 if(data){
696 698
697 699 tmpl += '<i class="icon-folder-close"></i> ';
698 700
699 701 }
700 702 tmpl += escapeMarkup(repoGroupName);
701 703 return tmpl;
702 704
703 705 }(result, escapeMarkup);
704 706 };
705 707
706 708 var escapeRegExChars = function (value) {
707 709 return value.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
708 710 };
709 711
710 712 var getRepoIcon = function(repo_type) {
711 713 if (repo_type === 'hg') {
712 714 return '<i class="icon-hg"></i> ';
713 715 }
714 716 else if (repo_type === 'git') {
715 717 return '<i class="icon-git"></i> ';
716 718 }
717 719 else if (repo_type === 'svn') {
718 720 return '<i class="icon-svn"></i> ';
719 721 }
720 722 return ''
721 723 };
722 724
723 725 var autocompleteMainFilterFormatResult = function (data, value, org_formatter) {
724 726
725 727 if (value.split(':').length === 2) {
726 728 value = value.split(':')[1]
727 729 }
728 730
729 731 var searchType = data['type'];
730 732 var valueDisplay = data['value_display'];
731 733
732 734 var pattern = '(' + escapeRegExChars(value) + ')';
733 735
734 736 valueDisplay = Select2.util.escapeMarkup(valueDisplay);
735 737
736 738 // highlight match
737 739 if (searchType != 'text') {
738 740 valueDisplay = valueDisplay.replace(new RegExp(pattern, 'gi'), '<strong>$1<\/strong>');
739 741 }
740 742
741 743 var icon = '';
742 744
743 745 if (searchType === 'hint') {
744 746 icon += '<i class="icon-folder-close"></i> ';
745 747 }
746 748 // full text search
747 749 else if (searchType === 'search') {
748 750 icon += '<i class="icon-more"></i> ';
749 751 }
750 752 // repository
751 753 else if (searchType === 'repo') {
752 754
753 755 var repoIcon = getRepoIcon(data['repo_type']);
754 756 icon += repoIcon;
755 757
756 758 if (data['private']) {
757 759 icon += '<i class="icon-lock" ></i> ';
758 760 }
759 761 else if (visualShowPublicIcon) {
760 762 icon += '<i class="icon-unlock-alt"></i> ';
761 763 }
762 764 }
763 765 // repository groups
764 766 else if (searchType === 'repo_group') {
765 767 icon += '<i class="icon-folder-close"></i> ';
766 768 }
767 769 // user group
768 770 else if (searchType === 'user_group') {
769 771 icon += '<i class="icon-group"></i> ';
770 772 }
771 773 // user
772 774 else if (searchType === 'user') {
773 775 icon += '<img class="gravatar" src="{0}"/>'.format(data['icon_link']);
774 776 }
775 777 // commit
776 778 else if (searchType === 'commit') {
777 779 var repo_data = data['repo_data'];
778 780 var repoIcon = getRepoIcon(repo_data['repository_type']);
779 781 if (repoIcon) {
780 782 icon += repoIcon;
781 783 } else {
782 784 icon += '<i class="icon-tag"></i>';
783 785 }
784 786 }
785 787 // file
786 788 else if (searchType === 'file') {
787 789 var repo_data = data['repo_data'];
788 790 var repoIcon = getRepoIcon(repo_data['repository_type']);
789 791 if (repoIcon) {
790 792 icon += repoIcon;
791 793 } else {
792 794 icon += '<i class="icon-tag"></i>';
793 795 }
794 796 }
795 797 // generic text
796 798 else if (searchType === 'text') {
797 799 icon = '';
798 800 }
799 801
800 802 var tmpl = '<div class="ac-container-wrap">{0}{1}</div>';
801 803 return tmpl.format(icon, valueDisplay);
802 804 };
803 805
804 806 var handleSelect = function(element, suggestion) {
805 807 if (suggestion.type === "hint") {
806 808 // we skip action
807 809 $('#main_filter').focus();
808 810 }
809 811 else if (suggestion.type === "text") {
810 812 // we skip action
811 813 $('#main_filter').focus();
812 814
813 815 } else {
814 816 window.location = suggestion['url'];
815 817 }
816 818 };
817 819
818 820 var autocompleteMainFilterResult = function (suggestion, originalQuery, queryLowerCase) {
819 821 if (queryLowerCase.split(':').length === 2) {
820 822 queryLowerCase = queryLowerCase.split(':')[1]
821 823 }
822 824 if (suggestion.type === "text") {
823 825 // special case we don't want to "skip" display for
824 826 return true
825 827 }
826 828 return suggestion.value_display.toLowerCase().indexOf(queryLowerCase) !== -1;
827 829 };
828 830
829 831 var cleanContext = {
830 832 repo_view_type: null,
831 833
832 834 repo_id: null,
833 835 repo_name: "",
834 836
835 837 repo_group_id: null,
836 838 repo_group_name: null
837 839 };
838 840 var removeGoToFilter = function () {
839 841 $('.searchTagHidable').hide();
840 842 $('#main_filter').autocomplete(
841 843 'setOptions', {params:{search_context: cleanContext}});
842 844 };
843 845
844 846 $('#main_filter').autocomplete({
845 847 serviceUrl: pyroutes.url('goto_switcher_data'),
846 848 params: {
847 849 "search_context": templateContext.search_context
848 850 },
849 851 minChars:2,
850 852 maxHeight:400,
851 853 deferRequestBy: 300, //miliseconds
852 854 tabDisabled: true,
853 855 autoSelectFirst: false,
854 856 formatResult: autocompleteMainFilterFormatResult,
855 857 lookupFilter: autocompleteMainFilterResult,
856 858 onSelect: function (element, suggestion) {
857 859 handleSelect(element, suggestion);
858 860 return false;
859 861 },
860 862 onSearchError: function (element, query, jqXHR, textStatus, errorThrown) {
861 863 if (jqXHR !== 'abort') {
862 864 alert("Error during search.\nError code: {0}".format(textStatus));
863 865 window.location = '';
864 866 }
865 867 }
866 868 });
867 869
868 870 showMainFilterBox = function () {
869 871 $('#main_filter_help').toggle();
870 872 };
871 873
872 874 $('#main_filter').on('keydown.autocomplete', function (e) {
873 875
874 876 var BACKSPACE = 8;
875 877 var el = $(e.currentTarget);
876 878 if(e.which === BACKSPACE){
877 879 var inputVal = el.val();
878 880 if (inputVal === ""){
879 881 removeGoToFilter()
880 882 }
881 883 }
882 884 });
883 885
884 886 </script>
885 887 <script src="${h.asset('js/rhodecode/base/keyboard-bindings.js', ver=c.rhodecode_version_hash)}"></script>
886 888 </%def>
887 889
888 890 <div class="modal" id="help_kb" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
889 891 <div class="modal-dialog">
890 892 <div class="modal-content">
891 893 <div class="modal-header">
892 894 <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
893 895 <h4 class="modal-title" id="myModalLabel">${_('Keyboard shortcuts')}</h4>
894 896 </div>
895 897 <div class="modal-body">
896 898 <div class="block-left">
897 899 <table class="keyboard-mappings">
898 900 <tbody>
899 901 <tr>
900 902 <th></th>
901 903 <th>${_('Site-wide shortcuts')}</th>
902 904 </tr>
903 905 <%
904 906 elems = [
905 907 ('/', 'Use quick search box'),
906 908 ('g h', 'Goto home page'),
907 909 ('g g', 'Goto my private gists page'),
908 910 ('g G', 'Goto my public gists page'),
909 911 ('g 0-9', 'Goto bookmarked items from 0-9'),
910 912 ('n r', 'New repository page'),
911 913 ('n g', 'New gist page'),
912 914 ]
913 915 %>
914 916 %for key, desc in elems:
915 917 <tr>
916 918 <td class="keys">
917 919 <span class="key tag">${key}</span>
918 920 </td>
919 921 <td>${desc}</td>
920 922 </tr>
921 923 %endfor
922 924 </tbody>
923 925 </table>
924 926 </div>
925 927 <div class="block-left">
926 928 <table class="keyboard-mappings">
927 929 <tbody>
928 930 <tr>
929 931 <th></th>
930 932 <th>${_('Repositories')}</th>
931 933 </tr>
932 934 <%
933 935 elems = [
934 936 ('g s', 'Goto summary page'),
935 937 ('g c', 'Goto changelog page'),
936 938 ('g f', 'Goto files page'),
937 939 ('g F', 'Goto files page with file search activated'),
938 940 ('g p', 'Goto pull requests page'),
939 941 ('g o', 'Goto repository settings'),
940 942 ('g O', 'Goto repository permissions settings'),
941 943 ]
942 944 %>
943 945 %for key, desc in elems:
944 946 <tr>
945 947 <td class="keys">
946 948 <span class="key tag">${key}</span>
947 949 </td>
948 950 <td>${desc}</td>
949 951 </tr>
950 952 %endfor
951 953 </tbody>
952 954 </table>
953 955 </div>
954 956 </div>
955 957 <div class="modal-footer">
956 958 </div>
957 959 </div><!-- /.modal-content -->
958 960 </div><!-- /.modal-dialog -->
959 961 </div><!-- /.modal -->
960 962
General Comments 0
You need to be logged in to leave comments. Login now