Show More
The requested changes are too big and content was truncated. Show full diff
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
@@ -0,0 +1,30 b'' | |||||
|
1 | import logging | |||
|
2 | ||||
|
3 | from sqlalchemy import * | |||
|
4 | ||||
|
5 | from rhodecode.model import meta | |||
|
6 | from rhodecode.lib.dbmigrate.versions import _reset_base, notify | |||
|
7 | ||||
|
8 | log = logging.getLogger(__name__) | |||
|
9 | ||||
|
10 | ||||
|
11 | def upgrade(migrate_engine): | |||
|
12 | """ | |||
|
13 | Upgrade operations go here. | |||
|
14 | Don't create your own engine; bind migrate_engine to your metadata | |||
|
15 | """ | |||
|
16 | _reset_base(migrate_engine) | |||
|
17 | from rhodecode.lib.dbmigrate.schema import db_4_16_0_1 as db | |||
|
18 | ||||
|
19 | db.UserBookmark.__table__.create() | |||
|
20 | ||||
|
21 | fixups(db, meta.Session) | |||
|
22 | ||||
|
23 | ||||
|
24 | def downgrade(migrate_engine): | |||
|
25 | meta = MetaData() | |||
|
26 | meta.bind = migrate_engine | |||
|
27 | ||||
|
28 | ||||
|
29 | def fixups(models, _SESSION): | |||
|
30 | pass |
@@ -0,0 +1,222 b'' | |||||
|
1 | <%namespace name="dt" file="/data_table/_dt_elements.mako"/> | |||
|
2 | ||||
|
3 | <%def name="form_item(count, position=None, title=None, redirect_url=None, repo=None, repo_group=None)"> | |||
|
4 | <tr> | |||
|
5 | <td class="td-align-top" > | |||
|
6 | <div class="label"> | |||
|
7 | <label for="position">${_('Position')}:</label> | |||
|
8 | </div> | |||
|
9 | <div class="input"> | |||
|
10 | <input type="text" name="position" value="${position or count}" style="width: 40px"/> | |||
|
11 | </div> | |||
|
12 | </td> | |||
|
13 | ||||
|
14 | <td> | |||
|
15 | <div class="label"> | |||
|
16 | <label for="title">${_('Bookmark title (max 30 characters, optional)')}:</label> | |||
|
17 | </div> | |||
|
18 | <div class="input"> | |||
|
19 | <input type="text" name="title" value="${title}" style="width: 300px" maxlength="30"/> | |||
|
20 | ||||
|
21 | <div class="field pull-right"> | |||
|
22 | <div> | |||
|
23 | <label class="btn-link btn-danger">${_('Clear')}:</label> | |||
|
24 | ${h.checkbox('remove', value=True)} | |||
|
25 | </div> | |||
|
26 | </div> | |||
|
27 | </div> | |||
|
28 | ||||
|
29 | <div class="label"> | |||
|
30 | <label for="redirect_url">${_('Redirect URL')}:</label> | |||
|
31 | </div> | |||
|
32 | <div class="input"> | |||
|
33 | <input type="text" name="redirect_url" value="${redirect_url}" style="width: 600px"/> | |||
|
34 | </div> | |||
|
35 | ||||
|
36 | ||||
|
37 | <div class="select"> | |||
|
38 | % if repo: | |||
|
39 | <div class="label"> | |||
|
40 | <label for="redirect_url">${_('Repository template')}:</label> | |||
|
41 | </div> | |||
|
42 | ${dt.repo_name(name=repo.repo_name, rtype=repo.repo_type,rstate=None,private=None,archived=False,fork_of=False)} | |||
|
43 | ${h.hidden('bookmark_repo', repo.repo_id)} | |||
|
44 | % elif repo_group: | |||
|
45 | <div class="label"> | |||
|
46 | <label for="redirect_url">${_('Repository group template')}:</label> | |||
|
47 | </div> | |||
|
48 | ${dt.repo_group_name(repo_group.group_name)} | |||
|
49 | ${h.hidden('bookmark_repo_group', repo_group.group_id)} | |||
|
50 | % else: | |||
|
51 | <div class="label"> | |||
|
52 | <label for="redirect_url">${_('Template Repository or Repository group')}:</label> | |||
|
53 | </div> | |||
|
54 | ${h.hidden('bookmark_repo', class_='bookmark_repo')} | |||
|
55 | <span style="padding-right:15px">OR</span> | |||
|
56 | ${h.hidden('bookmark_repo_group', class_='bookmark_repo_group')} | |||
|
57 | % endif | |||
|
58 | </div> | |||
|
59 | ||||
|
60 | <p class="help-block help-block-inline" > | |||
|
61 | % if repo: | |||
|
62 | ${_('Available as ${repo_url} e.g. Redirect url: ${repo_url}/changelog')} | |||
|
63 | % elif repo_group: | |||
|
64 | ${_('Available as ${repo_group_url} e.g. Redirect url: ${repo_group_url}')} | |||
|
65 | % else: | |||
|
66 | ${_('Available as full url variables in redirect url. i.e: ${repo_url}, ${repo_group_url}.')} | |||
|
67 | % endif | |||
|
68 | </p> | |||
|
69 | </td> | |||
|
70 | ||||
|
71 | </tr> | |||
|
72 | </%def> | |||
|
73 | ||||
|
74 | <div class="panel panel-default"> | |||
|
75 | <div class="panel-heading"> | |||
|
76 | <h3 class="panel-title">${_('Your Bookmarks')}</h3> | |||
|
77 | </div> | |||
|
78 | ||||
|
79 | <div class="panel-body"> | |||
|
80 | <p> | |||
|
81 | ${_('Store upto 10 bookmark links to favorite repositories, external issue tracker or CI server. ')} | |||
|
82 | <br/> | |||
|
83 | ${_('Bookmarks are accessible from your username dropdown or by keyboard shortcut `g 0-9`')} | |||
|
84 | </p> | |||
|
85 | ||||
|
86 | ${h.secure_form(h.route_path('my_account_bookmarks_update'), request=request)} | |||
|
87 | <div class="form-vertical"> | |||
|
88 | <table class="rctable"> | |||
|
89 | ## generate always 10 entries | |||
|
90 | <input type="hidden" name="__start__" value="bookmarks:sequence"/> | |||
|
91 | % for cnt, item in enumerate((c.bookmark_items + [None for i in range(10)])[:10]): | |||
|
92 | <input type="hidden" name="__start__" value="bookmark:mapping"/> | |||
|
93 | % if item is None: | |||
|
94 | ## empty placehodlder | |||
|
95 | ${form_item(cnt)} | |||
|
96 | % else: | |||
|
97 | ## actual entry | |||
|
98 | ${form_item(cnt, position=item.position, title=item.title, redirect_url=item.redirect_url, repo=item.repository, repo_group=item.repository_group)} | |||
|
99 | % endif | |||
|
100 | <input type="hidden" name="__end__" value="bookmark:mapping"/> | |||
|
101 | % endfor | |||
|
102 | <input type="hidden" name="__end__" value="bookmarks:sequence"/> | |||
|
103 | </table> | |||
|
104 | <div class="buttons"> | |||
|
105 | ${h.submit('save',_('Save'),class_="btn")} | |||
|
106 | </div> | |||
|
107 | </div> | |||
|
108 | ${h.end_form()} | |||
|
109 | </div> | |||
|
110 | </div> | |||
|
111 | ||||
|
112 | <script> | |||
|
113 | $(document).ready(function(){ | |||
|
114 | ||||
|
115 | ||||
|
116 | var repoFilter = function (data) { | |||
|
117 | var results = []; | |||
|
118 | ||||
|
119 | if (!data.results[0]) { | |||
|
120 | return data | |||
|
121 | } | |||
|
122 | ||||
|
123 | $.each(data.results[0].children, function () { | |||
|
124 | // replace name to ID for submision | |||
|
125 | this.id = this.repo_id; | |||
|
126 | results.push(this); | |||
|
127 | }); | |||
|
128 | ||||
|
129 | data.results[0].children = results; | |||
|
130 | return data; | |||
|
131 | }; | |||
|
132 | ||||
|
133 | ||||
|
134 | $(".bookmark_repo").select2({ | |||
|
135 | cachedDataSource: {}, | |||
|
136 | minimumInputLength: 2, | |||
|
137 | placeholder: "${_('repository')}", | |||
|
138 | dropdownAutoWidth: true, | |||
|
139 | containerCssClass: "drop-menu", | |||
|
140 | dropdownCssClass: "drop-menu-dropdown", | |||
|
141 | formatResult: formatRepoResult, | |||
|
142 | query: $.debounce(250, function (query) { | |||
|
143 | self = this; | |||
|
144 | var cacheKey = query.term; | |||
|
145 | var cachedData = self.cachedDataSource[cacheKey]; | |||
|
146 | ||||
|
147 | if (cachedData) { | |||
|
148 | query.callback({results: cachedData.results}); | |||
|
149 | } else { | |||
|
150 | $.ajax({ | |||
|
151 | url: pyroutes.url('repo_list_data'), | |||
|
152 | data: {'query': query.term}, | |||
|
153 | dataType: 'json', | |||
|
154 | type: 'GET', | |||
|
155 | success: function (data) { | |||
|
156 | data = repoFilter(data); | |||
|
157 | self.cachedDataSource[cacheKey] = data; | |||
|
158 | query.callback({results: data.results}); | |||
|
159 | }, | |||
|
160 | error: function (data, textStatus, errorThrown) { | |||
|
161 | alert("Error while fetching entries.\nError code {0} ({1}).".format(data.status, data.statusText)); | |||
|
162 | } | |||
|
163 | }) | |||
|
164 | } | |||
|
165 | }), | |||
|
166 | }); | |||
|
167 | ||||
|
168 | var repoGroupFilter = function (data) { | |||
|
169 | var results = []; | |||
|
170 | ||||
|
171 | if (!data.results[0]) { | |||
|
172 | return data | |||
|
173 | } | |||
|
174 | ||||
|
175 | $.each(data.results[0].children, function () { | |||
|
176 | // replace name to ID for submision | |||
|
177 | this.id = this.repo_group_id; | |||
|
178 | results.push(this); | |||
|
179 | }); | |||
|
180 | ||||
|
181 | data.results[0].children = results; | |||
|
182 | return data; | |||
|
183 | }; | |||
|
184 | ||||
|
185 | $(".bookmark_repo_group").select2({ | |||
|
186 | cachedDataSource: {}, | |||
|
187 | minimumInputLength: 2, | |||
|
188 | placeholder: "${_('repository group')}", | |||
|
189 | dropdownAutoWidth: true, | |||
|
190 | containerCssClass: "drop-menu", | |||
|
191 | dropdownCssClass: "drop-menu-dropdown", | |||
|
192 | formatResult: formatRepoGroupResult, | |||
|
193 | query: $.debounce(250, function (query) { | |||
|
194 | self = this; | |||
|
195 | var cacheKey = query.term; | |||
|
196 | var cachedData = self.cachedDataSource[cacheKey]; | |||
|
197 | ||||
|
198 | if (cachedData) { | |||
|
199 | query.callback({results: cachedData.results}); | |||
|
200 | } else { | |||
|
201 | $.ajax({ | |||
|
202 | url: pyroutes.url('repo_group_list_data'), | |||
|
203 | data: {'query': query.term}, | |||
|
204 | dataType: 'json', | |||
|
205 | type: 'GET', | |||
|
206 | success: function (data) { | |||
|
207 | data = repoGroupFilter(data); | |||
|
208 | self.cachedDataSource[cacheKey] = data; | |||
|
209 | query.callback({results: data.results}); | |||
|
210 | }, | |||
|
211 | error: function (data, textStatus, errorThrown) { | |||
|
212 | alert("Error while fetching entries.\nError code {0} ({1}).".format(data.status, data.statusText)); | |||
|
213 | } | |||
|
214 | }) | |||
|
215 | } | |||
|
216 | }) | |||
|
217 | }); | |||
|
218 | ||||
|
219 | ||||
|
220 | }); | |||
|
221 | ||||
|
222 | </script> |
@@ -45,7 +45,7 b' PYRAMID_SETTINGS = {}' | |||||
45 | EXTENSIONS = {} |
|
45 | EXTENSIONS = {} | |
46 |
|
46 | |||
47 | __version__ = ('.'.join((str(each) for each in VERSION[:3]))) |
|
47 | __version__ = ('.'.join((str(each) for each in VERSION[:3]))) | |
48 |
__dbversion__ = 9 |
|
48 | __dbversion__ = 94 # defines current db version for migrations | |
49 | __platform__ = platform.system() |
|
49 | __platform__ = platform.system() | |
50 | __license__ = 'AGPLv3, and Commercial License' |
|
50 | __license__ = 'AGPLv3, and Commercial License' | |
51 | __author__ = 'RhodeCode GmbH' |
|
51 | __author__ = 'RhodeCode GmbH' |
@@ -56,6 +56,10 b' def includeme(config):' | |||||
56 | pattern='/_repos') |
|
56 | pattern='/_repos') | |
57 |
|
57 | |||
58 | config.add_route( |
|
58 | config.add_route( | |
|
59 | name='repo_group_list_data', | |||
|
60 | pattern='/_repo_groups') | |||
|
61 | ||||
|
62 | config.add_route( | |||
59 | name='goto_switcher_data', |
|
63 | name='goto_switcher_data', | |
60 | pattern='/_goto_data') |
|
64 | pattern='/_goto_data') | |
61 |
|
65 |
@@ -172,7 +172,9 b' class HomeView(BaseAppView):' | |||||
172 | 'id': obj.group_name, |
|
172 | 'id': obj.group_name, | |
173 | 'value': org_query, |
|
173 | 'value': org_query, | |
174 | 'value_display': obj.group_name, |
|
174 | 'value_display': obj.group_name, | |
|
175 | 'text': obj.group_name, | |||
175 | 'type': 'repo_group', |
|
176 | 'type': 'repo_group', | |
|
177 | 'repo_group_id': obj.group_id, | |||
176 | 'url': h.route_path( |
|
178 | 'url': h.route_path( | |
177 | 'repo_group_home', repo_group_name=obj.group_name) |
|
179 | 'repo_group_home', repo_group_name=obj.group_name) | |
178 | } |
|
180 | } | |
@@ -302,6 +304,33 b' class HomeView(BaseAppView):' | |||||
302 | } |
|
304 | } | |
303 | return data |
|
305 | return data | |
304 |
|
306 | |||
|
307 | @LoginRequired() | |||
|
308 | @view_config( | |||
|
309 | route_name='repo_group_list_data', request_method='GET', | |||
|
310 | renderer='json_ext', xhr=True) | |||
|
311 | def repo_group_list_data(self): | |||
|
312 | _ = self.request.translate | |||
|
313 | self.load_default_context() | |||
|
314 | ||||
|
315 | query = self.request.GET.get('query') | |||
|
316 | ||||
|
317 | log.debug('generating repo group list, query:%s', | |||
|
318 | query) | |||
|
319 | ||||
|
320 | res = [] | |||
|
321 | repo_groups = self._get_repo_group_list(query) | |||
|
322 | if repo_groups: | |||
|
323 | res.append({ | |||
|
324 | 'text': _('Repository Groups'), | |||
|
325 | 'children': repo_groups | |||
|
326 | }) | |||
|
327 | ||||
|
328 | data = { | |||
|
329 | 'more': False, | |||
|
330 | 'results': res | |||
|
331 | } | |||
|
332 | return data | |||
|
333 | ||||
305 | def _get_default_search_queries(self, search_context, searcher, query): |
|
334 | def _get_default_search_queries(self, search_context, searcher, query): | |
306 | if not searcher: |
|
335 | if not searcher: | |
307 | return [] |
|
336 | return [] |
@@ -95,6 +95,18 b' def includeme(config):' | |||||
95 | pattern=ADMIN_PREFIX + '/my_account/watched') |
|
95 | pattern=ADMIN_PREFIX + '/my_account/watched') | |
96 |
|
96 | |||
97 | config.add_route( |
|
97 | config.add_route( | |
|
98 | name='my_account_bookmarks', | |||
|
99 | pattern=ADMIN_PREFIX + '/my_account/bookmarks') | |||
|
100 | ||||
|
101 | config.add_route( | |||
|
102 | name='my_account_bookmarks_update', | |||
|
103 | pattern=ADMIN_PREFIX + '/my_account/bookmarks/update') | |||
|
104 | ||||
|
105 | config.add_route( | |||
|
106 | name='my_account_goto_bookmark', | |||
|
107 | pattern=ADMIN_PREFIX + '/my_account/bookmark/{bookmark_id}') | |||
|
108 | ||||
|
109 | config.add_route( | |||
98 | name='my_account_perms', |
|
110 | name='my_account_perms', | |
99 | pattern=ADMIN_PREFIX + '/my_account/perms') |
|
111 | pattern=ADMIN_PREFIX + '/my_account/perms') | |
100 |
|
112 |
@@ -20,29 +20,30 b'' | |||||
20 |
|
20 | |||
21 | import logging |
|
21 | import logging | |
22 | import datetime |
|
22 | import datetime | |
|
23 | import string | |||
23 |
|
24 | |||
24 | import formencode |
|
25 | import formencode | |
25 | import formencode.htmlfill |
|
26 | import formencode.htmlfill | |
|
27 | import peppercorn | |||
26 | from pyramid.httpexceptions import HTTPFound |
|
28 | from pyramid.httpexceptions import HTTPFound | |
27 | from pyramid.view import view_config |
|
29 | from pyramid.view import view_config | |
28 | from pyramid.renderers import render |
|
|||
29 | from pyramid.response import Response |
|
|||
30 |
|
30 | |||
31 | from rhodecode.apps._base import BaseAppView, DataGridAppView |
|
31 | from rhodecode.apps._base import BaseAppView, DataGridAppView | |
32 | from rhodecode import forms |
|
32 | from rhodecode import forms | |
33 | from rhodecode.lib import helpers as h |
|
33 | from rhodecode.lib import helpers as h | |
34 | from rhodecode.lib import audit_logger |
|
34 | from rhodecode.lib import audit_logger | |
35 | from rhodecode.lib.ext_json import json |
|
35 | from rhodecode.lib.ext_json import json | |
36 | from rhodecode.lib.auth import LoginRequired, NotAnonymous, CSRFRequired |
|
36 | from rhodecode.lib.auth import LoginRequired, NotAnonymous, CSRFRequired, \ | |
|
37 | HasRepoPermissionAny, HasRepoGroupPermissionAny | |||
37 | from rhodecode.lib.channelstream import ( |
|
38 | from rhodecode.lib.channelstream import ( | |
38 | channelstream_request, ChannelstreamException) |
|
39 | channelstream_request, ChannelstreamException) | |
39 | from rhodecode.lib.utils2 import safe_int, md5, str2bool |
|
40 | from rhodecode.lib.utils2 import safe_int, md5, str2bool | |
40 | from rhodecode.model.auth_token import AuthTokenModel |
|
41 | from rhodecode.model.auth_token import AuthTokenModel | |
41 | from rhodecode.model.comment import CommentsModel |
|
42 | from rhodecode.model.comment import CommentsModel | |
42 | from rhodecode.model.db import ( |
|
43 | from rhodecode.model.db import ( | |
43 | Repository, UserEmailMap, UserApiKeys, UserFollowing, joinedload, |
|
44 | IntegrityError, joinedload, | |
44 | PullRequest) |
|
45 | Repository, UserEmailMap, UserApiKeys, UserFollowing, | |
45 | from rhodecode.model.forms import UserForm, UserExtraEmailForm |
|
46 | PullRequest, UserBookmark, RepoGroup) | |
46 | from rhodecode.model.meta import Session |
|
47 | from rhodecode.model.meta import Session | |
47 | from rhodecode.model.pull_request import PullRequestModel |
|
48 | from rhodecode.model.pull_request import PullRequestModel | |
48 | from rhodecode.model.scm import RepoList |
|
49 | from rhodecode.model.scm import RepoList | |
@@ -392,6 +393,140 b' class MyAccountView(BaseAppView, DataGri' | |||||
392 | @LoginRequired() |
|
393 | @LoginRequired() | |
393 | @NotAnonymous() |
|
394 | @NotAnonymous() | |
394 | @view_config( |
|
395 | @view_config( | |
|
396 | route_name='my_account_bookmarks', request_method='GET', | |||
|
397 | renderer='rhodecode:templates/admin/my_account/my_account.mako') | |||
|
398 | def my_account_bookmarks(self): | |||
|
399 | c = self.load_default_context() | |||
|
400 | c.active = 'bookmarks' | |||
|
401 | return self._get_template_context(c) | |||
|
402 | ||||
|
403 | def _process_entry(self, entry, user_id): | |||
|
404 | position = safe_int(entry.get('position')) | |||
|
405 | if position is None: | |||
|
406 | return | |||
|
407 | ||||
|
408 | # check if this is an existing entry | |||
|
409 | is_new = False | |||
|
410 | db_entry = UserBookmark().get_by_position_for_user(position, user_id) | |||
|
411 | ||||
|
412 | if db_entry and str2bool(entry.get('remove')): | |||
|
413 | log.debug('Marked bookmark %s for deletion', db_entry) | |||
|
414 | Session().delete(db_entry) | |||
|
415 | return | |||
|
416 | ||||
|
417 | if not db_entry: | |||
|
418 | # new | |||
|
419 | db_entry = UserBookmark() | |||
|
420 | is_new = True | |||
|
421 | ||||
|
422 | should_save = False | |||
|
423 | default_redirect_url = '' | |||
|
424 | ||||
|
425 | # save repo | |||
|
426 | if entry.get('bookmark_repo'): | |||
|
427 | repo = Repository.get(entry['bookmark_repo']) | |||
|
428 | perm_check = HasRepoPermissionAny( | |||
|
429 | 'repository.read', 'repository.write', 'repository.admin') | |||
|
430 | if repo and perm_check(repo_name=repo.repo_name): | |||
|
431 | db_entry.repository = repo | |||
|
432 | should_save = True | |||
|
433 | default_redirect_url = '${repo_url}' | |||
|
434 | # save repo group | |||
|
435 | elif entry.get('bookmark_repo_group'): | |||
|
436 | repo_group = RepoGroup.get(entry['bookmark_repo_group']) | |||
|
437 | perm_check = HasRepoGroupPermissionAny( | |||
|
438 | 'group.read', 'group.write', 'group.admin') | |||
|
439 | ||||
|
440 | if repo_group and perm_check(group_name=repo_group.group_name): | |||
|
441 | db_entry.repository_group = repo_group | |||
|
442 | should_save = True | |||
|
443 | default_redirect_url = '${repo_group_url}' | |||
|
444 | # save generic info | |||
|
445 | elif entry.get('title') and entry.get('redirect_url'): | |||
|
446 | should_save = True | |||
|
447 | ||||
|
448 | if should_save: | |||
|
449 | log.debug('Saving bookmark %s, new:%s', db_entry, is_new) | |||
|
450 | # mark user and position | |||
|
451 | db_entry.user_id = user_id | |||
|
452 | db_entry.position = position | |||
|
453 | db_entry.title = entry.get('title') | |||
|
454 | db_entry.redirect_url = entry.get('redirect_url') or default_redirect_url | |||
|
455 | ||||
|
456 | Session().add(db_entry) | |||
|
457 | ||||
|
458 | @LoginRequired() | |||
|
459 | @NotAnonymous() | |||
|
460 | @CSRFRequired() | |||
|
461 | @view_config( | |||
|
462 | route_name='my_account_bookmarks_update', request_method='POST') | |||
|
463 | def my_account_bookmarks_update(self): | |||
|
464 | _ = self.request.translate | |||
|
465 | c = self.load_default_context() | |||
|
466 | c.active = 'bookmarks' | |||
|
467 | ||||
|
468 | controls = peppercorn.parse(self.request.POST.items()) | |||
|
469 | user_id = c.user.user_id | |||
|
470 | ||||
|
471 | try: | |||
|
472 | for entry in controls.get('bookmarks', []): | |||
|
473 | self._process_entry(entry, user_id) | |||
|
474 | ||||
|
475 | Session().commit() | |||
|
476 | h.flash(_("Update Bookmarks"), category='success') | |||
|
477 | except IntegrityError: | |||
|
478 | h.flash(_("Failed to update bookmarks. " | |||
|
479 | "Make sure an unique position is used"), category='error') | |||
|
480 | ||||
|
481 | return HTTPFound(h.route_path('my_account_bookmarks')) | |||
|
482 | ||||
|
483 | @LoginRequired() | |||
|
484 | @NotAnonymous() | |||
|
485 | @view_config( | |||
|
486 | route_name='my_account_goto_bookmark', request_method='GET', | |||
|
487 | renderer='rhodecode:templates/admin/my_account/my_account.mako') | |||
|
488 | def my_account_goto_bookmark(self): | |||
|
489 | ||||
|
490 | bookmark_id = self.request.matchdict['bookmark_id'] | |||
|
491 | user_bookmark = UserBookmark().query()\ | |||
|
492 | .filter(UserBookmark.user_id == self.request.user.user_id) \ | |||
|
493 | .filter(UserBookmark.position == bookmark_id).scalar() | |||
|
494 | ||||
|
495 | redirect_url = h.route_path('my_account_bookmarks') | |||
|
496 | if not user_bookmark: | |||
|
497 | raise HTTPFound(redirect_url) | |||
|
498 | ||||
|
499 | if user_bookmark.repository: | |||
|
500 | repo_name = user_bookmark.repository.repo_name | |||
|
501 | base_redirect_url = h.route_path( | |||
|
502 | 'repo_summary', repo_name=repo_name) | |||
|
503 | if user_bookmark.redirect_url and \ | |||
|
504 | '${repo_url}' in user_bookmark.redirect_url: | |||
|
505 | redirect_url = string.Template(user_bookmark.redirect_url)\ | |||
|
506 | .safe_substitute({'repo_url': base_redirect_url}) | |||
|
507 | else: | |||
|
508 | redirect_url = base_redirect_url | |||
|
509 | ||||
|
510 | elif user_bookmark.repository_group: | |||
|
511 | repo_group_name = user_bookmark.repository_group.group_name | |||
|
512 | base_redirect_url = h.route_path( | |||
|
513 | 'repo_group_home', repo_group_name=repo_group_name) | |||
|
514 | if user_bookmark.redirect_url and \ | |||
|
515 | '${repo_group_url}' in user_bookmark.redirect_url: | |||
|
516 | redirect_url = string.Template(user_bookmark.redirect_url)\ | |||
|
517 | .safe_substitute({'repo_group_url': base_redirect_url}) | |||
|
518 | else: | |||
|
519 | redirect_url = base_redirect_url | |||
|
520 | ||||
|
521 | elif user_bookmark.redirect_url: | |||
|
522 | redirect_url = user_bookmark.redirect_url | |||
|
523 | ||||
|
524 | log.debug('Redirecting bookmark %s to %s', user_bookmark, redirect_url) | |||
|
525 | raise HTTPFound(redirect_url) | |||
|
526 | ||||
|
527 | @LoginRequired() | |||
|
528 | @NotAnonymous() | |||
|
529 | @view_config( | |||
395 | route_name='my_account_perms', request_method='GET', |
|
530 | route_name='my_account_perms', request_method='GET', | |
396 | renderer='rhodecode:templates/admin/my_account/my_account.mako') |
|
531 | renderer='rhodecode:templates/admin/my_account/my_account.mako') | |
397 | def my_account_perms(self): |
|
532 | def my_account_perms(self): |
@@ -44,7 +44,7 b' from rhodecode.lib.exceptions import Use' | |||||
44 | from rhodecode.lib.utils import (password_changed, get_enabled_hook_classes) |
|
44 | from rhodecode.lib.utils import (password_changed, get_enabled_hook_classes) | |
45 | from rhodecode.lib.utils2 import ( |
|
45 | from rhodecode.lib.utils2 import ( | |
46 | str2bool, safe_unicode, AttributeDict, safe_int, sha1, aslist, safe_str) |
|
46 | str2bool, safe_unicode, AttributeDict, safe_int, sha1, aslist, safe_str) | |
47 | from rhodecode.model.db import Repository, User, ChangesetComment |
|
47 | from rhodecode.model.db import Repository, User, ChangesetComment, UserBookmark | |
48 | from rhodecode.model.notification import NotificationModel |
|
48 | from rhodecode.model.notification import NotificationModel | |
49 | from rhodecode.model.settings import VcsSettingsModel, SettingsModel |
|
49 | from rhodecode.model.settings import VcsSettingsModel, SettingsModel | |
50 |
|
50 | |||
@@ -282,7 +282,7 b' def get_current_lang(request):' | |||||
282 | return getattr(request, '_LOCALE_', request.locale_name) |
|
282 | return getattr(request, '_LOCALE_', request.locale_name) | |
283 |
|
283 | |||
284 |
|
284 | |||
285 | def attach_context_attributes(context, request, user_id): |
|
285 | def attach_context_attributes(context, request, user_id=None): | |
286 | """ |
|
286 | """ | |
287 | Attach variables into template context called `c`. |
|
287 | Attach variables into template context called `c`. | |
288 | """ |
|
288 | """ | |
@@ -422,7 +422,13 b' def attach_context_attributes(context, r' | |||||
422 | context.csrf_token = auth.get_csrf_token(session=request.session) |
|
422 | context.csrf_token = auth.get_csrf_token(session=request.session) | |
423 | context.backends = rhodecode.BACKENDS.keys() |
|
423 | context.backends = rhodecode.BACKENDS.keys() | |
424 | context.backends.sort() |
|
424 | context.backends.sort() | |
425 | context.unread_notifications = NotificationModel().get_unread_cnt_for_user(user_id) |
|
425 | unread_count = 0 | |
|
426 | user_bookmark_list = [] | |||
|
427 | if user_id: | |||
|
428 | unread_count = NotificationModel().get_unread_cnt_for_user(user_id) | |||
|
429 | user_bookmark_list = UserBookmark.get_bookmarks_for_user(user_id) | |||
|
430 | context.unread_notifications = unread_count | |||
|
431 | context.bookmark_items = user_bookmark_list | |||
426 |
|
432 | |||
427 | # web case |
|
433 | # web case | |
428 | if hasattr(request, 'user'): |
|
434 | if hasattr(request, 'user'): |
@@ -4797,6 +4797,49 b' class UserGroupToRepoBranchPermission(Ba' | |||||
4797 | self.user_group_repo_to_perm, self.branch_pattern) |
|
4797 | self.user_group_repo_to_perm, self.branch_pattern) | |
4798 |
|
4798 | |||
4799 |
|
4799 | |||
|
4800 | class UserBookmark(Base, BaseModel): | |||
|
4801 | __tablename__ = 'user_bookmarks' | |||
|
4802 | __table_args__ = ( | |||
|
4803 | UniqueConstraint('user_id', 'bookmark_repo_id'), | |||
|
4804 | UniqueConstraint('user_id', 'bookmark_repo_group_id'), | |||
|
4805 | UniqueConstraint('user_id', 'bookmark_position'), | |||
|
4806 | base_table_args | |||
|
4807 | ) | |||
|
4808 | ||||
|
4809 | user_bookmark_id = Column("user_bookmark_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) | |||
|
4810 | user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None) | |||
|
4811 | position = Column("bookmark_position", Integer(), nullable=False) | |||
|
4812 | title = Column("bookmark_title", String(255), nullable=True, unique=None, default=None) | |||
|
4813 | redirect_url = Column("bookmark_redirect_url", String(10240), nullable=True, unique=None, default=None) | |||
|
4814 | created_on = Column("created_on", DateTime(timezone=False), nullable=False, default=datetime.datetime.now) | |||
|
4815 | ||||
|
4816 | bookmark_repo_id = Column("bookmark_repo_id", Integer(), ForeignKey("repositories.repo_id"), nullable=True, unique=None, default=None) | |||
|
4817 | bookmark_repo_group_id = Column("bookmark_repo_group_id", Integer(), ForeignKey("groups.group_id"), nullable=True, unique=None, default=None) | |||
|
4818 | ||||
|
4819 | user = relationship("User") | |||
|
4820 | ||||
|
4821 | repository = relationship("Repository") | |||
|
4822 | repository_group = relationship("RepoGroup") | |||
|
4823 | ||||
|
4824 | @classmethod | |||
|
4825 | def get_by_position_for_user(cls, position, user_id): | |||
|
4826 | return cls.query() \ | |||
|
4827 | .filter(UserBookmark.user_id == user_id) \ | |||
|
4828 | .filter(UserBookmark.position == position).scalar() | |||
|
4829 | ||||
|
4830 | @classmethod | |||
|
4831 | def get_bookmarks_for_user(cls, user_id): | |||
|
4832 | return cls.query() \ | |||
|
4833 | .filter(UserBookmark.user_id == user_id) \ | |||
|
4834 | .options(joinedload(UserBookmark.repository)) \ | |||
|
4835 | .options(joinedload(UserBookmark.repository_group)) \ | |||
|
4836 | .order_by(UserBookmark.position.asc()) \ | |||
|
4837 | .all() | |||
|
4838 | ||||
|
4839 | def __unicode__(self): | |||
|
4840 | return u'<UserBookmark(%d @ %r)>' % (self.position, self.redirect_url) | |||
|
4841 | ||||
|
4842 | ||||
4800 | class DbMigrateVersion(Base, BaseModel): |
|
4843 | class DbMigrateVersion(Base, BaseModel): | |
4801 | __tablename__ = 'db_migrate_version' |
|
4844 | __tablename__ = 'db_migrate_version' | |
4802 | __table_args__ = ( |
|
4845 | __table_args__ = ( |
@@ -200,7 +200,27 b'' | |||||
200 | .user-menu.submenu { |
|
200 | .user-menu.submenu { | |
201 | right: 0; |
|
201 | right: 0; | |
202 | left: auto; |
|
202 | left: auto; | |
|
203 | min-width: 290px; | |||
203 | } |
|
204 | } | |
|
205 | ||||
|
206 | ||||
|
207 | .user-menu { | |||
|
208 | .bookmark-items { | |||
|
209 | padding: 4px 2px; | |||
|
210 | color: @grey3; | |||
|
211 | border-bottom: @grey3; | |||
|
212 | ||||
|
213 | a { | |||
|
214 | padding: 0 !important; | |||
|
215 | color: @rcblue !important; | |||
|
216 | } | |||
|
217 | } | |||
|
218 | a.bookmark-item { | |||
|
219 | color: @rcblue !important; | |||
|
220 | } | |||
|
221 | } | |||
|
222 | ||||
|
223 | ||||
204 | #quick_login { |
|
224 | #quick_login { | |
205 | left: auto; |
|
225 | left: auto; | |
206 | right: 0; |
|
226 | right: 0; |
@@ -172,7 +172,9 b' table.dataTable {' | |||||
172 | &.td-buttons { |
|
172 | &.td-buttons { | |
173 | padding: .3em 0; |
|
173 | padding: .3em 0; | |
174 | } |
|
174 | } | |
175 |
|
175 | &.td-align-top { | ||
|
176 | vertical-align: text-top | |||
|
177 | } | |||
176 | &.td-action { |
|
178 | &.td-action { | |
177 | // this is for the remove/delete/edit buttons |
|
179 | // this is for the remove/delete/edit buttons | |
178 | padding-right: 0; |
|
180 | padding-right: 0; |
@@ -526,6 +526,10 b' address {' | |||||
526 | font-family: @text-regular; |
|
526 | font-family: @text-regular; | |
527 | } |
|
527 | } | |
528 |
|
528 | |||
|
529 | .help-block-inline { | |||
|
530 | margin: 0; | |||
|
531 | } | |||
|
532 | ||||
529 | // help block text |
|
533 | // help block text | |
530 | .help-block { |
|
534 | .help-block { | |
531 | display: block; |
|
535 | display: block; |
@@ -51,6 +51,38 b' function setRCMouseBindings(repoName, re' | |||||
51 | Mousetrap.bind(['g G'], function(e) { |
|
51 | Mousetrap.bind(['g G'], function(e) { | |
52 | window.location = pyroutes.url('gists_show', {'public': 1}); |
|
52 | window.location = pyroutes.url('gists_show', {'public': 1}); | |
53 | }); |
|
53 | }); | |
|
54 | ||||
|
55 | Mousetrap.bind(['g 0'], function(e) { | |||
|
56 | window.location = pyroutes.url('my_account_goto_bookmark', {'bookmark_id': 0}); | |||
|
57 | }); | |||
|
58 | Mousetrap.bind(['g 1'], function(e) { | |||
|
59 | window.location = pyroutes.url('my_account_goto_bookmark', {'bookmark_id': 1}); | |||
|
60 | }); | |||
|
61 | Mousetrap.bind(['g 2'], function(e) { | |||
|
62 | window.location = pyroutes.url('my_account_goto_bookmark', {'bookmark_id': 2}); | |||
|
63 | }); | |||
|
64 | Mousetrap.bind(['g 3'], function(e) { | |||
|
65 | window.location = pyroutes.url('my_account_goto_bookmark', {'bookmark_id': 3}); | |||
|
66 | }); | |||
|
67 | Mousetrap.bind(['g 4'], function(e) { | |||
|
68 | window.location = pyroutes.url('my_account_goto_bookmark', {'bookmark_id': 4}); | |||
|
69 | }); | |||
|
70 | Mousetrap.bind(['g 5'], function(e) { | |||
|
71 | window.location = pyroutes.url('my_account_goto_bookmark', {'bookmark_id': 5}); | |||
|
72 | }); | |||
|
73 | Mousetrap.bind(['g 6'], function(e) { | |||
|
74 | window.location = pyroutes.url('my_account_goto_bookmark', {'bookmark_id': 6}); | |||
|
75 | }); | |||
|
76 | Mousetrap.bind(['g 7'], function(e) { | |||
|
77 | window.location = pyroutes.url('my_account_goto_bookmark', {'bookmark_id': 7}); | |||
|
78 | }); | |||
|
79 | Mousetrap.bind(['g 8'], function(e) { | |||
|
80 | window.location = pyroutes.url('my_account_goto_bookmark', {'bookmark_id': 8}); | |||
|
81 | }); | |||
|
82 | Mousetrap.bind(['g 9'], function(e) { | |||
|
83 | window.location = pyroutes.url('my_account_goto_bookmark', {'bookmark_id': 9}); | |||
|
84 | }); | |||
|
85 | ||||
54 | Mousetrap.bind(['n g'], function(e) { |
|
86 | Mousetrap.bind(['n g'], function(e) { | |
55 | window.location = pyroutes.url('gists_new'); |
|
87 | window.location = pyroutes.url('gists_new'); | |
56 | }); |
|
88 | }); | |
@@ -58,7 +90,7 b' function setRCMouseBindings(repoName, re' | |||||
58 | window.location = pyroutes.url('repo_new'); |
|
90 | window.location = pyroutes.url('repo_new'); | |
59 | }); |
|
91 | }); | |
60 |
|
92 | |||
61 | if (repoName && repoName != '') { |
|
93 | if (repoName && repoName !== '') { | |
62 | // nav in repo context |
|
94 | // nav in repo context | |
63 | Mousetrap.bind(['g s'], function(e) { |
|
95 | Mousetrap.bind(['g s'], function(e) { | |
64 | window.location = pyroutes.url( |
|
96 | window.location = pyroutes.url( |
@@ -143,6 +143,7 b' function registerRCRoutes() {' | |||||
143 | pyroutes.register('user_autocomplete_data', '/_users', []); |
|
143 | pyroutes.register('user_autocomplete_data', '/_users', []); | |
144 | pyroutes.register('user_group_autocomplete_data', '/_user_groups', []); |
|
144 | pyroutes.register('user_group_autocomplete_data', '/_user_groups', []); | |
145 | pyroutes.register('repo_list_data', '/_repos', []); |
|
145 | pyroutes.register('repo_list_data', '/_repos', []); | |
|
146 | pyroutes.register('repo_group_list_data', '/_repo_groups', []); | |||
146 | pyroutes.register('goto_switcher_data', '/_goto_data', []); |
|
147 | pyroutes.register('goto_switcher_data', '/_goto_data', []); | |
147 | pyroutes.register('markup_preview', '/_markup_preview', []); |
|
148 | pyroutes.register('markup_preview', '/_markup_preview', []); | |
148 | pyroutes.register('store_user_session_value', '/_store_session_attr', []); |
|
149 | pyroutes.register('store_user_session_value', '/_store_session_attr', []); | |
@@ -297,6 +298,9 b' function registerRCRoutes() {' | |||||
297 | pyroutes.register('my_account_emails_delete', '/_admin/my_account/emails/delete', []); |
|
298 | pyroutes.register('my_account_emails_delete', '/_admin/my_account/emails/delete', []); | |
298 | pyroutes.register('my_account_repos', '/_admin/my_account/repos', []); |
|
299 | pyroutes.register('my_account_repos', '/_admin/my_account/repos', []); | |
299 | pyroutes.register('my_account_watched', '/_admin/my_account/watched', []); |
|
300 | pyroutes.register('my_account_watched', '/_admin/my_account/watched', []); | |
|
301 | pyroutes.register('my_account_bookmarks', '/_admin/my_account/bookmarks', []); | |||
|
302 | pyroutes.register('my_account_bookmarks_update', '/_admin/my_account/bookmarks/update', []); | |||
|
303 | pyroutes.register('my_account_goto_bookmark', '/_admin/my_account/bookmark/%(bookmark_id)s', ['bookmark_id']); | |||
300 | pyroutes.register('my_account_perms', '/_admin/my_account/perms', []); |
|
304 | pyroutes.register('my_account_perms', '/_admin/my_account/perms', []); | |
301 | pyroutes.register('my_account_notifications', '/_admin/my_account/notifications', []); |
|
305 | pyroutes.register('my_account_notifications', '/_admin/my_account/notifications', []); | |
302 | pyroutes.register('my_account_notifications_toggle_visibility', '/_admin/my_account/toggle_visibility', []); |
|
306 | pyroutes.register('my_account_notifications_toggle_visibility', '/_admin/my_account/toggle_visibility', []); |
@@ -28,6 +28,7 b'' | |||||
28 | <ul class="nav nav-pills nav-stacked"> |
|
28 | <ul class="nav nav-pills nav-stacked"> | |
29 | <li class="${'active' if c.active=='profile' or c.active=='profile_edit' else ''}"><a href="${h.route_path('my_account_profile')}">${_('Profile')}</a></li> |
|
29 | <li class="${'active' if c.active=='profile' or c.active=='profile_edit' else ''}"><a href="${h.route_path('my_account_profile')}">${_('Profile')}</a></li> | |
30 | <li class="${'active' if c.active=='password' else ''}"><a href="${h.route_path('my_account_password')}">${_('Password')}</a></li> |
|
30 | <li class="${'active' if c.active=='password' else ''}"><a href="${h.route_path('my_account_password')}">${_('Password')}</a></li> | |
|
31 | <li class="${'active' if c.active=='bookmarks' else ''}"><a href="${h.route_path('my_account_bookmarks')}">${_('Bookmarks')}</a></li> | |||
31 | <li class="${'active' if c.active=='auth_tokens' else ''}"><a href="${h.route_path('my_account_auth_tokens')}">${_('Auth Tokens')}</a></li> |
|
32 | <li class="${'active' if c.active=='auth_tokens' else ''}"><a href="${h.route_path('my_account_auth_tokens')}">${_('Auth Tokens')}</a></li> | |
32 | <li class="${'active' if c.active in ['ssh_keys', 'ssh_keys_generate'] else ''}"><a href="${h.route_path('my_account_ssh_keys')}">${_('SSH Keys')}</a></li> |
|
33 | <li class="${'active' if c.active in ['ssh_keys', 'ssh_keys_generate'] else ''}"><a href="${h.route_path('my_account_ssh_keys')}">${_('SSH Keys')}</a></li> | |
33 | <li class="${'active' if c.active=='user_group_membership' else ''}"><a href="${h.route_path('my_account_user_group_membership')}">${_('User Group Membership')}</a></li> |
|
34 | <li class="${'active' if c.active=='user_group_membership' else ''}"><a href="${h.route_path('my_account_user_group_membership')}">${_('User Group Membership')}</a></li> |
@@ -52,7 +52,7 b'' | |||||
52 | <p class="server-instance" style="display:${sid}"> |
|
52 | <p class="server-instance" style="display:${sid}"> | |
53 | ## display hidden instance ID if specially defined |
|
53 | ## display hidden instance ID if specially defined | |
54 | % if c.rhodecode_instanceid: |
|
54 | % if c.rhodecode_instanceid: | |
55 |
${_('RhodeCode instance id: |
|
55 | ${_('RhodeCode instance id: {}').format(c.rhodecode_instanceid)} | |
56 | % endif |
|
56 | % endif | |
57 | </p> |
|
57 | </p> | |
58 | </div> |
|
58 | </div> | |
@@ -331,6 +331,50 b'' | |||||
331 | <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> |
|
331 | <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> | |
332 | % endif |
|
332 | % endif | |
333 | <li>${h.link_to(_(u'Pull Requests'), h.route_path('my_account_pullrequests'))}</li> |
|
333 | <li>${h.link_to(_(u'Pull Requests'), h.route_path('my_account_pullrequests'))}</li> | |
|
334 | ## bookmark-items | |||
|
335 | <li class="bookmark-items"> | |||
|
336 | ${_('Bookmarks')} | |||
|
337 | <div class="pull-right"> | |||
|
338 | <a href="${h.route_path('my_account_bookmarks')}">${_('Manage')}</a> | |||
|
339 | </div> | |||
|
340 | </li> | |||
|
341 | % if not c.bookmark_items: | |||
|
342 | <li> | |||
|
343 | <a href="${h.route_path('my_account_bookmarks')}">${_('No Bookmarks yet.')}</a> | |||
|
344 | </li> | |||
|
345 | % endif | |||
|
346 | % for item in c.bookmark_items: | |||
|
347 | <li> | |||
|
348 | % if item.repository: | |||
|
349 | <div> | |||
|
350 | <a class="bookmark-item" href="${h.route_path('my_account_goto_bookmark', bookmark_id=item.position)}"> | |||
|
351 | ${item.position} | |||
|
352 | % if item.repository.repo_type == 'hg': | |||
|
353 | <i class="icon-hg" title="${_('Repository')}" style="font-size: 16px"></i> | |||
|
354 | % elif item.repository.repo_type == 'git': | |||
|
355 | <i class="icon-git" title="${_('Repository')}" style="font-size: 16px"></i> | |||
|
356 | % elif item.repository.repo_type == 'svn': | |||
|
357 | <i class="icon-svn" title="${_('Repository')}" style="font-size: 16px"></i> | |||
|
358 | % endif | |||
|
359 | ${(item.title or h.shorter(item.repository.repo_name, 30))} | |||
|
360 | </a> | |||
|
361 | </div> | |||
|
362 | % elif item.repository_group: | |||
|
363 | <div> | |||
|
364 | <a class="bookmark-item" href="${h.route_path('my_account_goto_bookmark', bookmark_id=item.position)}"> | |||
|
365 | ${item.position} | |||
|
366 | <i class="icon-folder-close" title="${_('Repository group')}" style="font-size: 16px"></i> | |||
|
367 | ${(item.title or h.shorter(item.repository_group.group_name, 30))} | |||
|
368 | </a> | |||
|
369 | </div> | |||
|
370 | % else: | |||
|
371 | <a class="bookmark-item" href="${h.route_path('my_account_goto_bookmark', bookmark_id=item.position)}"> | |||
|
372 | ${item.position} | |||
|
373 | ${item.title} | |||
|
374 | </a> | |||
|
375 | % endif | |||
|
376 | </li> | |||
|
377 | % endfor | |||
334 |
|
378 | |||
335 | <li class="logout"> |
|
379 | <li class="logout"> | |
336 | ${h.secure_form(h.route_path('logout'), request=request)} |
|
380 | ${h.secure_form(h.route_path('logout'), request=request)} | |
@@ -483,6 +527,26 b' commit:efced4, to search for commits' | |||||
483 | }(result, escapeMarkup); |
|
527 | }(result, escapeMarkup); | |
484 | }; |
|
528 | }; | |
485 |
|
529 | |||
|
530 | var formatRepoGroupResult = function(result, container, query, escapeMarkup) { | |||
|
531 | return function(data, escapeMarkup) { | |||
|
532 | if (!data.repo_group_id){ | |||
|
533 | return data.text; // optgroup text Repositories | |||
|
534 | } | |||
|
535 | ||||
|
536 | var tmpl = ''; | |||
|
537 | var repoGroupName = data['text']; | |||
|
538 | ||||
|
539 | if(data){ | |||
|
540 | ||||
|
541 | tmpl += '<i class="icon-folder-close"></i> '; | |||
|
542 | ||||
|
543 | } | |||
|
544 | tmpl += escapeMarkup(repoGroupName); | |||
|
545 | return tmpl; | |||
|
546 | ||||
|
547 | }(result, escapeMarkup); | |||
|
548 | }; | |||
|
549 | ||||
486 |
|
550 | |||
487 | var autocompleteMainFilterFormatResult = function (data, value, org_formatter) { |
|
551 | var autocompleteMainFilterFormatResult = function (data, value, org_formatter) { | |
488 |
|
552 | |||
@@ -610,6 +674,7 b' commit:efced4, to search for commits' | |||||
610 | ('g h', 'Goto home page'), |
|
674 | ('g h', 'Goto home page'), | |
611 | ('g g', 'Goto my private gists page'), |
|
675 | ('g g', 'Goto my private gists page'), | |
612 | ('g G', 'Goto my public gists page'), |
|
676 | ('g G', 'Goto my public gists page'), | |
|
677 | ('g 0-9', 'Goto bookmarked items from 0-9'), | |||
613 | ('n r', 'New repository page'), |
|
678 | ('n r', 'New repository page'), | |
614 | ('n g', 'New gist page'), |
|
679 | ('n g', 'New gist page'), | |
615 | ] |
|
680 | ] |
@@ -88,9 +88,9 b'' | |||||
88 | %endif |
|
88 | %endif | |
89 |
|
89 | |||
90 | ##PRIVATE/PUBLIC |
|
90 | ##PRIVATE/PUBLIC | |
91 | %if private and c.visual.show_private_icon: |
|
91 | %if private is True and c.visual.show_private_icon: | |
92 | <i class="icon-lock" title="${_('Private repository')}"></i> |
|
92 | <i class="icon-lock" title="${_('Private repository')}"></i> | |
93 |
%elif |
|
93 | %elif private is False and c.visual.show_public_icon: | |
94 | <i class="icon-unlock-alt" title="${_('Public repository')}"></i> |
|
94 | <i class="icon-unlock-alt" title="${_('Public repository')}"></i> | |
95 | %else: |
|
95 | %else: | |
96 | <span></span> |
|
96 | <span></span> |
General Comments 0
You need to be logged in to leave comments.
Login now