##// END OF EJS Templates
Gist: added shortcut for my public gists
marcink -
r3847:bec04f37 beta
parent child Browse files
Show More
@@ -1,190 +1,196
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.controllers.admin.gist
3 rhodecode.controllers.admin.gist
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5
5
6 gist controller for RhodeCode
6 gist controller for RhodeCode
7
7
8 :created_on: May 9, 2013
8 :created_on: May 9, 2013
9 :author: marcink
9 :author: marcink
10 :copyright: (C) 2010-2013 Marcin Kuzminski <marcin@python-works.com>
10 :copyright: (C) 2010-2013 Marcin Kuzminski <marcin@python-works.com>
11 :license: GPLv3, see COPYING for more details.
11 :license: GPLv3, see COPYING for more details.
12 """
12 """
13 # This program is free software: you can redistribute it and/or modify
13 # This program is free software: you can redistribute it and/or modify
14 # it under the terms of the GNU General Public License as published by
14 # it under the terms of the GNU General Public License as published by
15 # the Free Software Foundation, either version 3 of the License, or
15 # the Free Software Foundation, either version 3 of the License, or
16 # (at your option) any later version.
16 # (at your option) any later version.
17 #
17 #
18 # This program is distributed in the hope that it will be useful,
18 # This program is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # GNU General Public License for more details.
21 # GNU General Public License for more details.
22 #
22 #
23 # You should have received a copy of the GNU General Public License
23 # You should have received a copy of the GNU General Public License
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25 import time
25 import time
26 import logging
26 import logging
27 import traceback
27 import traceback
28 import formencode
28 import formencode
29 from formencode import htmlfill
29 from formencode import htmlfill
30
30
31 from pylons import request, tmpl_context as c, url
31 from pylons import request, tmpl_context as c, url
32 from pylons.controllers.util import abort, redirect
32 from pylons.controllers.util import abort, redirect
33 from pylons.i18n.translation import _
33 from pylons.i18n.translation import _
34
34
35 from rhodecode.model.forms import GistForm
35 from rhodecode.model.forms import GistForm
36 from rhodecode.model.gist import GistModel
36 from rhodecode.model.gist import GistModel
37 from rhodecode.model.meta import Session
37 from rhodecode.model.meta import Session
38 from rhodecode.model.db import Gist
38 from rhodecode.model.db import Gist
39 from rhodecode.lib import helpers as h
39 from rhodecode.lib import helpers as h
40 from rhodecode.lib.base import BaseController, render
40 from rhodecode.lib.base import BaseController, render
41 from rhodecode.lib.auth import LoginRequired, NotAnonymous
41 from rhodecode.lib.auth import LoginRequired, NotAnonymous
42 from rhodecode.lib.utils2 import safe_str, safe_int, time_to_datetime
42 from rhodecode.lib.utils2 import safe_str, safe_int, time_to_datetime
43 from rhodecode.lib.helpers import Page
43 from rhodecode.lib.helpers import Page
44 from webob.exc import HTTPNotFound, HTTPForbidden
44 from webob.exc import HTTPNotFound, HTTPForbidden
45 from sqlalchemy.sql.expression import or_
45 from sqlalchemy.sql.expression import or_
46 from rhodecode.lib.vcs.exceptions import VCSError
46 from rhodecode.lib.vcs.exceptions import VCSError
47
47
48 log = logging.getLogger(__name__)
48 log = logging.getLogger(__name__)
49
49
50
50
51 class GistsController(BaseController):
51 class GistsController(BaseController):
52 """REST Controller styled on the Atom Publishing Protocol"""
52 """REST Controller styled on the Atom Publishing Protocol"""
53
53
54 def __load_defaults(self):
54 def __load_defaults(self):
55 c.lifetime_values = [
55 c.lifetime_values = [
56 (str(-1), _('forever')),
56 (str(-1), _('forever')),
57 (str(5), _('5 minutes')),
57 (str(5), _('5 minutes')),
58 (str(60), _('1 hour')),
58 (str(60), _('1 hour')),
59 (str(60 * 24), _('1 day')),
59 (str(60 * 24), _('1 day')),
60 (str(60 * 24 * 30), _('1 month')),
60 (str(60 * 24 * 30), _('1 month')),
61 ]
61 ]
62 c.lifetime_options = [(c.lifetime_values, _("Lifetime"))]
62 c.lifetime_options = [(c.lifetime_values, _("Lifetime"))]
63
63
64 @LoginRequired()
64 @LoginRequired()
65 def index(self, format='html'):
65 def index(self, format='html'):
66 """GET /admin/gists: All items in the collection"""
66 """GET /admin/gists: All items in the collection"""
67 # url('gists')
67 # url('gists')
68 c.show_private = request.GET.get('private') and c.rhodecode_user.username != 'default'
68 c.show_private = request.GET.get('private') and c.rhodecode_user.username != 'default'
69 c.show_public = request.GET.get('public') and c.rhodecode_user.username != 'default'
70
69 gists = Gist().query()\
71 gists = Gist().query()\
70 .filter(or_(Gist.gist_expires == -1, Gist.gist_expires >= time.time()))\
72 .filter(or_(Gist.gist_expires == -1, Gist.gist_expires >= time.time()))\
71 .order_by(Gist.created_on.desc())
73 .order_by(Gist.created_on.desc())
72 if c.show_private:
74 if c.show_private:
73 c.gists = gists.filter(Gist.gist_type == Gist.GIST_PRIVATE)\
75 c.gists = gists.filter(Gist.gist_type == Gist.GIST_PRIVATE)\
74 .filter(Gist.gist_owner == c.rhodecode_user.user_id)
76 .filter(Gist.gist_owner == c.rhodecode_user.user_id)
77 elif c.show_public:
78 c.gists = gists.filter(Gist.gist_type == Gist.GIST_PUBLIC)\
79 .filter(Gist.gist_owner == c.rhodecode_user.user_id)
80
75 else:
81 else:
76 c.gists = gists.filter(Gist.gist_type == Gist.GIST_PUBLIC)
82 c.gists = gists.filter(Gist.gist_type == Gist.GIST_PUBLIC)
77 p = safe_int(request.GET.get('page', 1), 1)
83 p = safe_int(request.GET.get('page', 1), 1)
78 c.gists_pager = Page(c.gists, page=p, items_per_page=10)
84 c.gists_pager = Page(c.gists, page=p, items_per_page=10)
79 return render('admin/gists/index.html')
85 return render('admin/gists/index.html')
80
86
81 @LoginRequired()
87 @LoginRequired()
82 @NotAnonymous()
88 @NotAnonymous()
83 def create(self):
89 def create(self):
84 """POST /admin/gists: Create a new item"""
90 """POST /admin/gists: Create a new item"""
85 # url('gists')
91 # url('gists')
86 self.__load_defaults()
92 self.__load_defaults()
87 gist_form = GistForm([x[0] for x in c.lifetime_values])()
93 gist_form = GistForm([x[0] for x in c.lifetime_values])()
88 try:
94 try:
89 form_result = gist_form.to_python(dict(request.POST))
95 form_result = gist_form.to_python(dict(request.POST))
90 #TODO: multiple files support, from the form
96 #TODO: multiple files support, from the form
91 nodes = {
97 nodes = {
92 form_result['filename'] or 'gistfile1.txt': {
98 form_result['filename'] or 'gistfile1.txt': {
93 'content': form_result['content'],
99 'content': form_result['content'],
94 'lexer': None # autodetect
100 'lexer': None # autodetect
95 }
101 }
96 }
102 }
97 _public = form_result['public']
103 _public = form_result['public']
98 gist_type = Gist.GIST_PUBLIC if _public else Gist.GIST_PRIVATE
104 gist_type = Gist.GIST_PUBLIC if _public else Gist.GIST_PRIVATE
99 gist = GistModel().create(
105 gist = GistModel().create(
100 description=form_result['description'],
106 description=form_result['description'],
101 owner=c.rhodecode_user,
107 owner=c.rhodecode_user,
102 gist_mapping=nodes,
108 gist_mapping=nodes,
103 gist_type=gist_type,
109 gist_type=gist_type,
104 lifetime=form_result['lifetime']
110 lifetime=form_result['lifetime']
105 )
111 )
106 Session().commit()
112 Session().commit()
107 new_gist_id = gist.gist_access_id
113 new_gist_id = gist.gist_access_id
108 except formencode.Invalid, errors:
114 except formencode.Invalid, errors:
109 defaults = errors.value
115 defaults = errors.value
110
116
111 return formencode.htmlfill.render(
117 return formencode.htmlfill.render(
112 render('admin/gists/new.html'),
118 render('admin/gists/new.html'),
113 defaults=defaults,
119 defaults=defaults,
114 errors=errors.error_dict or {},
120 errors=errors.error_dict or {},
115 prefix_error=False,
121 prefix_error=False,
116 encoding="UTF-8"
122 encoding="UTF-8"
117 )
123 )
118
124
119 except Exception, e:
125 except Exception, e:
120 log.error(traceback.format_exc())
126 log.error(traceback.format_exc())
121 h.flash(_('Error occurred during gist creation'), category='error')
127 h.flash(_('Error occurred during gist creation'), category='error')
122 return redirect(url('new_gist'))
128 return redirect(url('new_gist'))
123 return redirect(url('gist', id=new_gist_id))
129 return redirect(url('gist', id=new_gist_id))
124
130
125 @LoginRequired()
131 @LoginRequired()
126 @NotAnonymous()
132 @NotAnonymous()
127 def new(self, format='html'):
133 def new(self, format='html'):
128 """GET /admin/gists/new: Form to create a new item"""
134 """GET /admin/gists/new: Form to create a new item"""
129 # url('new_gist')
135 # url('new_gist')
130 self.__load_defaults()
136 self.__load_defaults()
131 return render('admin/gists/new.html')
137 return render('admin/gists/new.html')
132
138
133 @LoginRequired()
139 @LoginRequired()
134 @NotAnonymous()
140 @NotAnonymous()
135 def update(self, id):
141 def update(self, id):
136 """PUT /admin/gists/id: Update an existing item"""
142 """PUT /admin/gists/id: Update an existing item"""
137 # Forms posted to this method should contain a hidden field:
143 # Forms posted to this method should contain a hidden field:
138 # <input type="hidden" name="_method" value="PUT" />
144 # <input type="hidden" name="_method" value="PUT" />
139 # Or using helpers:
145 # Or using helpers:
140 # h.form(url('gist', id=ID),
146 # h.form(url('gist', id=ID),
141 # method='put')
147 # method='put')
142 # url('gist', id=ID)
148 # url('gist', id=ID)
143
149
144 @LoginRequired()
150 @LoginRequired()
145 @NotAnonymous()
151 @NotAnonymous()
146 def delete(self, id):
152 def delete(self, id):
147 """DELETE /admin/gists/id: Delete an existing item"""
153 """DELETE /admin/gists/id: Delete an existing item"""
148 # Forms posted to this method should contain a hidden field:
154 # Forms posted to this method should contain a hidden field:
149 # <input type="hidden" name="_method" value="DELETE" />
155 # <input type="hidden" name="_method" value="DELETE" />
150 # Or using helpers:
156 # Or using helpers:
151 # h.form(url('gist', id=ID),
157 # h.form(url('gist', id=ID),
152 # method='delete')
158 # method='delete')
153 # url('gist', id=ID)
159 # url('gist', id=ID)
154 gist = GistModel().get_gist(id)
160 gist = GistModel().get_gist(id)
155 owner = gist.gist_owner == c.rhodecode_user.user_id
161 owner = gist.gist_owner == c.rhodecode_user.user_id
156 if h.HasPermissionAny('hg.admin')() or owner:
162 if h.HasPermissionAny('hg.admin')() or owner:
157 GistModel().delete(gist)
163 GistModel().delete(gist)
158 Session().commit()
164 Session().commit()
159 h.flash(_('Deleted gist %s') % gist.gist_access_id, category='success')
165 h.flash(_('Deleted gist %s') % gist.gist_access_id, category='success')
160 else:
166 else:
161 raise HTTPForbidden()
167 raise HTTPForbidden()
162
168
163 return redirect(url('gists'))
169 return redirect(url('gists'))
164
170
165 @LoginRequired()
171 @LoginRequired()
166 def show(self, id, format='html'):
172 def show(self, id, format='html'):
167 """GET /admin/gists/id: Show a specific item"""
173 """GET /admin/gists/id: Show a specific item"""
168 # url('gist', id=ID)
174 # url('gist', id=ID)
169 gist_id = id
175 gist_id = id
170 c.gist = Gist.get_or_404(gist_id)
176 c.gist = Gist.get_or_404(gist_id)
171
177
172 #check if this gist is not expired
178 #check if this gist is not expired
173 if c.gist.gist_expires != -1:
179 if c.gist.gist_expires != -1:
174 if time.time() > c.gist.gist_expires:
180 if time.time() > c.gist.gist_expires:
175 log.error('Gist expired at %s' %
181 log.error('Gist expired at %s' %
176 (time_to_datetime(c.gist.gist_expires)))
182 (time_to_datetime(c.gist.gist_expires)))
177 raise HTTPNotFound()
183 raise HTTPNotFound()
178 try:
184 try:
179 c.file_changeset, c.files = GistModel().get_gist_files(gist_id)
185 c.file_changeset, c.files = GistModel().get_gist_files(gist_id)
180 except VCSError:
186 except VCSError:
181 log.error(traceback.format_exc())
187 log.error(traceback.format_exc())
182 raise HTTPNotFound()
188 raise HTTPNotFound()
183
189
184 return render('admin/gists/show.html')
190 return render('admin/gists/show.html')
185
191
186 @LoginRequired()
192 @LoginRequired()
187 @NotAnonymous()
193 @NotAnonymous()
188 def edit(self, id, format='html'):
194 def edit(self, id, format='html'):
189 """GET /admin/gists/id/edit: Form to edit an existing item"""
195 """GET /admin/gists/id/edit: Form to edit an existing item"""
190 # url('edit_gist', id=ID)
196 # url('edit_gist', id=ID)
@@ -1,68 +1,70
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 <%inherit file="/base/base.html"/>
2 <%inherit file="/base/base.html"/>
3
3
4 <%def name="title()">
4 <%def name="title()">
5 ${_('Gists')} &middot; ${c.rhodecode_name}
5 ${_('Gists')} &middot; ${c.rhodecode_name}
6 </%def>
6 </%def>
7
7
8 <%def name="breadcrumbs_links()">
8 <%def name="breadcrumbs_links()">
9 %if c.show_private:
9 %if c.show_private:
10 ${_('Private Gists for user %s') % c.rhodecode_user.username}
10 ${_('Private Gists for user %s') % c.rhodecode_user.username}
11 %elif c.show_public:
12 ${_('Public Gists for user %s') % c.rhodecode_user.username}
11 %else:
13 %else:
12 ${_('Public Gists')}
14 ${_('Public Gists')}
13 %endif
15 %endif
14 - ${c.gists_pager.item_count}
16 - ${c.gists_pager.item_count}
15 </%def>
17 </%def>
16
18
17 <%def name="page_nav()">
19 <%def name="page_nav()">
18 ${self.menu('gists')}
20 ${self.menu('gists')}
19 </%def>
21 </%def>
20
22
21 <%def name="main()">
23 <%def name="main()">
22 <div class="box">
24 <div class="box">
23 <!-- box / title -->
25 <!-- box / title -->
24 <div class="title">
26 <div class="title">
25 ${self.breadcrumbs()}
27 ${self.breadcrumbs()}
26 %if c.rhodecode_user.username != 'default':
28 %if c.rhodecode_user.username != 'default':
27 <ul class="links">
29 <ul class="links">
28 <li>
30 <li>
29 <span>${h.link_to(_(u'Create new gist'), h.url('new_gist'))}</span>
31 <span>${h.link_to(_(u'Create new gist'), h.url('new_gist'))}</span>
30 </li>
32 </li>
31 </ul>
33 </ul>
32 %endif
34 %endif
33 </div>
35 </div>
34 %if c.gists_pager.item_count>0:
36 %if c.gists_pager.item_count>0:
35 % for gist in c.gists_pager:
37 % for gist in c.gists_pager:
36 <div class="gist-item" style="padding:10px 20px 10px 15px">
38 <div class="gist-item" style="padding:10px 20px 10px 15px">
37
39
38 <div class="gravatar">
40 <div class="gravatar">
39 <img alt="gravatar" src="${h.gravatar_url(h.email_or_none(gist.owner.full_contact),24)}"/>
41 <img alt="gravatar" src="${h.gravatar_url(h.email_or_none(gist.owner.full_contact),24)}"/>
40 </div>
42 </div>
41 <div title="${gist.owner.full_contact}" class="user">
43 <div title="${gist.owner.full_contact}" class="user">
42 <b>${h.person(gist.owner.full_contact)}</b> /
44 <b>${h.person(gist.owner.full_contact)}</b> /
43 <b><a href="${h.url('gist',id=gist.gist_access_id)}">gist:${gist.gist_access_id}</a></b>
45 <b><a href="${h.url('gist',id=gist.gist_access_id)}">gist:${gist.gist_access_id}</a></b>
44 <span style="color: #AAA">
46 <span style="color: #AAA">
45 %if gist.gist_expires == -1:
47 %if gist.gist_expires == -1:
46 ${_('Expires')}: ${_('never')}
48 ${_('Expires')}: ${_('never')}
47 %else:
49 %else:
48 ${_('Expires')}: ${h.age(h.time_to_datetime(gist.gist_expires))}
50 ${_('Expires')}: ${h.age(h.time_to_datetime(gist.gist_expires))}
49 %endif
51 %endif
50 </span>
52 </span>
51 </div>
53 </div>
52 <div>${_('Created')} ${h.age(gist.created_on)}
54 <div>${_('Created')} ${h.age(gist.created_on)}
53 </div>
55 </div>
54
56
55 <div style="border:0px;padding:10px 0px 0px 35px;color:#AAA">${gist.gist_description}</div>
57 <div style="border:0px;padding:10px 0px 0px 35px;color:#AAA">${gist.gist_description}</div>
56 </div>
58 </div>
57 % endfor
59 % endfor
58
60
59 <div class="notification-paginator">
61 <div class="notification-paginator">
60 <div class="pagination-wh pagination-left">
62 <div class="pagination-wh pagination-left">
61 ${c.gists_pager.pager('$link_previous ~2~ $link_next')}
63 ${c.gists_pager.pager('$link_previous ~2~ $link_next')}
62 </div>
64 </div>
63 </div>
65 </div>
64 %else:
66 %else:
65 <div class="table">${_('There are no gists yet')}</div>
67 <div class="table">${_('There are no gists yet')}</div>
66 %endif
68 %endif
67 </div>
69 </div>
68 </%def>
70 </%def>
@@ -1,353 +1,354
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 <%inherit file="root.html"/>
2 <%inherit file="root.html"/>
3
3
4 <!-- HEADER -->
4 <!-- HEADER -->
5 <div id="header-dd"></div>
5 <div id="header-dd"></div>
6 <div id="header">
6 <div id="header">
7 <div id="header-inner" class="title">
7 <div id="header-inner" class="title">
8 <div id="logo">
8 <div id="logo">
9 <h1><a href="${h.url('home')}">${c.rhodecode_name}</a></h1>
9 <h1><a href="${h.url('home')}">${c.rhodecode_name}</a></h1>
10 </div>
10 </div>
11 <!-- MENU -->
11 <!-- MENU -->
12 ${self.page_nav()}
12 ${self.page_nav()}
13 <!-- END MENU -->
13 <!-- END MENU -->
14 ${self.body()}
14 ${self.body()}
15 </div>
15 </div>
16 </div>
16 </div>
17 <!-- END HEADER -->
17 <!-- END HEADER -->
18
18
19 <!-- CONTENT -->
19 <!-- CONTENT -->
20 <div id="content">
20 <div id="content">
21 <div class="flash_msg">
21 <div class="flash_msg">
22 <% messages = h.flash.pop_messages() %>
22 <% messages = h.flash.pop_messages() %>
23 % if messages:
23 % if messages:
24 <ul id="flash-messages">
24 <ul id="flash-messages">
25 % for message in messages:
25 % for message in messages:
26 <li class="${message.category}_msg">${message}</li>
26 <li class="${message.category}_msg">${message}</li>
27 % endfor
27 % endfor
28 </ul>
28 </ul>
29 % endif
29 % endif
30 </div>
30 </div>
31 <div id="main">
31 <div id="main">
32 ${next.main()}
32 ${next.main()}
33 </div>
33 </div>
34 </div>
34 </div>
35 <!-- END CONTENT -->
35 <!-- END CONTENT -->
36
36
37 <!-- FOOTER -->
37 <!-- FOOTER -->
38 <div id="footer">
38 <div id="footer">
39 <div id="footer-inner" class="title">
39 <div id="footer-inner" class="title">
40 <div>
40 <div>
41 <p class="footer-link">
41 <p class="footer-link">
42 ${_('Server instance: %s') % c.rhodecode_instanceid if c.rhodecode_instanceid else ''}
42 ${_('Server instance: %s') % c.rhodecode_instanceid if c.rhodecode_instanceid else ''}
43 </p>
43 </p>
44 <p class="footer-link-right">
44 <p class="footer-link-right">
45 <a href="${h.url('rhodecode_official')}">RhodeCode ${c.rhodecode_version}</a>
45 <a href="${h.url('rhodecode_official')}">RhodeCode ${c.rhodecode_version}</a>
46 &copy; 2010-${h.datetime.today().year} by Marcin Kuzminski and others
46 &copy; 2010-${h.datetime.today().year} by Marcin Kuzminski and others
47 &ndash; <a href="${h.url('bugtracker')}">${_('Report a bug')}</a>
47 &ndash; <a href="${h.url('bugtracker')}">${_('Report a bug')}</a>
48 </p>
48 </p>
49 </div>
49 </div>
50 </div>
50 </div>
51 </div>
51 </div>
52
52
53 <!-- END FOOTER -->
53 <!-- END FOOTER -->
54
54
55 ### MAKO DEFS ###
55 ### MAKO DEFS ###
56 <%def name="breadcrumbs()">
56 <%def name="breadcrumbs()">
57 <div class="breadcrumbs">
57 <div class="breadcrumbs">
58 ${self.breadcrumbs_links()}
58 ${self.breadcrumbs_links()}
59 </div>
59 </div>
60 </%def>
60 </%def>
61
61
62 <%def name="context_bar(current)">
62 <%def name="context_bar(current)">
63 ${repo_context_bar(current)}
63 ${repo_context_bar(current)}
64 </%def>
64 </%def>
65
65
66 <%def name="admin_menu()">
66 <%def name="admin_menu()">
67 <ul class="admin_menu">
67 <ul class="admin_menu">
68 <li>${h.link_to(_('Admin journal'),h.url('admin_home'),class_='journal ')}</li>
68 <li>${h.link_to(_('Admin journal'),h.url('admin_home'),class_='journal ')}</li>
69 <li>${h.link_to(_('Repositories'),h.url('repos'),class_='repos')}</li>
69 <li>${h.link_to(_('Repositories'),h.url('repos'),class_='repos')}</li>
70 <li>${h.link_to(_('Repository groups'),h.url('repos_groups'),class_='repos_groups')}</li>
70 <li>${h.link_to(_('Repository groups'),h.url('repos_groups'),class_='repos_groups')}</li>
71 <li>${h.link_to(_('Users'),h.url('users'),class_='users')}</li>
71 <li>${h.link_to(_('Users'),h.url('users'),class_='users')}</li>
72 <li>${h.link_to(_('User groups'),h.url('users_groups'),class_='groups')}</li>
72 <li>${h.link_to(_('User groups'),h.url('users_groups'),class_='groups')}</li>
73 <li>${h.link_to(_('Permissions'),h.url('edit_permission',id='default'),class_='permissions')}</li>
73 <li>${h.link_to(_('Permissions'),h.url('edit_permission',id='default'),class_='permissions')}</li>
74 <li>${h.link_to(_('LDAP'),h.url('ldap_home'),class_='ldap')}</li>
74 <li>${h.link_to(_('LDAP'),h.url('ldap_home'),class_='ldap')}</li>
75 <li>${h.link_to(_('Defaults'),h.url('defaults'),class_='defaults')}</li>
75 <li>${h.link_to(_('Defaults'),h.url('defaults'),class_='defaults')}</li>
76 <li class="last">${h.link_to(_('Settings'),h.url('admin_settings'),class_='settings')}</li>
76 <li class="last">${h.link_to(_('Settings'),h.url('admin_settings'),class_='settings')}</li>
77 </ul>
77 </ul>
78 </%def>
78 </%def>
79
79
80 <%def name="admin_menu_simple(repository_groups=None, user_groups=None)">
80 <%def name="admin_menu_simple(repository_groups=None, user_groups=None)">
81 <ul>
81 <ul>
82 %if repository_groups:
82 %if repository_groups:
83 <li>${h.link_to(_('Repository groups'),h.url('repos_groups'),class_='repos_groups')}</li>
83 <li>${h.link_to(_('Repository groups'),h.url('repos_groups'),class_='repos_groups')}</li>
84 %endif:
84 %endif:
85 %if user_groups:
85 %if user_groups:
86 <li>${h.link_to(_('User groups'),h.url('users_groups'),class_='groups')}</li>
86 <li>${h.link_to(_('User groups'),h.url('users_groups'),class_='groups')}</li>
87 %endif
87 %endif
88 </ul>
88 </ul>
89 </%def>
89 </%def>
90
90
91 <%def name="repo_context_bar(current=None)">
91 <%def name="repo_context_bar(current=None)">
92 <%
92 <%
93 def follow_class():
93 def follow_class():
94 if c.repository_following:
94 if c.repository_following:
95 return h.literal('following')
95 return h.literal('following')
96 else:
96 else:
97 return h.literal('follow')
97 return h.literal('follow')
98 %>
98 %>
99 <%
99 <%
100 def is_current(selected):
100 def is_current(selected):
101 if selected == current:
101 if selected == current:
102 return h.literal('class="current"')
102 return h.literal('class="current"')
103 %>
103 %>
104
104
105 <!--- CONTEXT BAR -->
105 <!--- CONTEXT BAR -->
106 <div id="context-bar" class="box">
106 <div id="context-bar" class="box">
107 <div id="breadcrumbs">
107 <div id="breadcrumbs">
108 ${h.link_to(_(u'Repositories'),h.url('home'))}
108 ${h.link_to(_(u'Repositories'),h.url('home'))}
109 &raquo;
109 &raquo;
110 ${h.repo_link(c.rhodecode_db_repo.groups_and_repo)}
110 ${h.repo_link(c.rhodecode_db_repo.groups_and_repo)}
111 </div>
111 </div>
112 <ul id="context-pages" class="horizontal-list">
112 <ul id="context-pages" class="horizontal-list">
113 <li ${is_current('summary')}><a href="${h.url('summary_home', repo_name=c.repo_name)}" class="summary">${_('Summary')}</a></li>
113 <li ${is_current('summary')}><a href="${h.url('summary_home', repo_name=c.repo_name)}" class="summary">${_('Summary')}</a></li>
114 <li ${is_current('changelog')}><a href="${h.url('changelog_home', repo_name=c.repo_name)}" class="changelogs">${_('Changelog')}</a></li>
114 <li ${is_current('changelog')}><a href="${h.url('changelog_home', repo_name=c.repo_name)}" class="changelogs">${_('Changelog')}</a></li>
115 <li ${is_current('files')}><a href="${h.url('files_home', repo_name=c.repo_name)}" class="files"></span>${_('Files')}</a></li>
115 <li ${is_current('files')}><a href="${h.url('files_home', repo_name=c.repo_name)}" class="files"></span>${_('Files')}</a></li>
116 <li ${is_current('switch-to')}>
116 <li ${is_current('switch-to')}>
117 <a href="#" id="branch_tag_switcher_2" class="dropdown switch-to"></span>${_('Switch To')}</a>
117 <a href="#" id="branch_tag_switcher_2" class="dropdown switch-to"></span>${_('Switch To')}</a>
118 <ul id="switch_to_list_2" class="switch_to submenu">
118 <ul id="switch_to_list_2" class="switch_to submenu">
119 <li><a href="#">${_('loading...')}</a></li>
119 <li><a href="#">${_('loading...')}</a></li>
120 </ul>
120 </ul>
121 </li>
121 </li>
122 <li ${is_current('options')}>
122 <li ${is_current('options')}>
123 <a href="#" class="dropdown options"></span>${_('Options')}</a>
123 <a href="#" class="dropdown options"></span>${_('Options')}</a>
124 <ul>
124 <ul>
125 %if h.HasRepoPermissionAll('repository.admin')(c.repo_name):
125 %if h.HasRepoPermissionAll('repository.admin')(c.repo_name):
126 <li>${h.link_to(_('Settings'),h.url('edit_repo',repo_name=c.repo_name),class_='settings')}</li>
126 <li>${h.link_to(_('Settings'),h.url('edit_repo',repo_name=c.repo_name),class_='settings')}</li>
127 %endif
127 %endif
128 %if c.rhodecode_db_repo.fork:
128 %if c.rhodecode_db_repo.fork:
129 <li>${h.link_to(_('Compare fork'),h.url('compare_url',repo_name=c.rhodecode_db_repo.fork.repo_name,org_ref_type='branch',org_ref='default',other_repo=c.repo_name,other_ref_type='branch',other_ref=request.GET.get('branch') or 'default', merge=1),class_='compare_request')}</li>
129 <li>${h.link_to(_('Compare fork'),h.url('compare_url',repo_name=c.rhodecode_db_repo.fork.repo_name,org_ref_type='branch',org_ref='default',other_repo=c.repo_name,other_ref_type='branch',other_ref=request.GET.get('branch') or 'default', merge=1),class_='compare_request')}</li>
130 %endif
130 %endif
131 <li>${h.link_to(_('Search'),h.url('search_repo',repo_name=c.repo_name),class_='search')}</li>
131 <li>${h.link_to(_('Search'),h.url('search_repo',repo_name=c.repo_name),class_='search')}</li>
132
132
133 %if h.HasRepoPermissionAny('repository.write','repository.admin')(c.repo_name) and c.rhodecode_db_repo.enable_locking:
133 %if h.HasRepoPermissionAny('repository.write','repository.admin')(c.repo_name) and c.rhodecode_db_repo.enable_locking:
134 %if c.rhodecode_db_repo.locked[0]:
134 %if c.rhodecode_db_repo.locked[0]:
135 <li>${h.link_to(_('Unlock'), h.url('toggle_locking',repo_name=c.repo_name),class_='locking_del')}</li>
135 <li>${h.link_to(_('Unlock'), h.url('toggle_locking',repo_name=c.repo_name),class_='locking_del')}</li>
136 %else:
136 %else:
137 <li>${h.link_to(_('Lock'), h.url('toggle_locking',repo_name=c.repo_name),class_='locking_add')}</li>
137 <li>${h.link_to(_('Lock'), h.url('toggle_locking',repo_name=c.repo_name),class_='locking_add')}</li>
138 %endif
138 %endif
139 %endif
139 %endif
140 ## TODO: this check feels wrong, it would be better to have a check for permissions
140 ## TODO: this check feels wrong, it would be better to have a check for permissions
141 ## also it feels like a job for the controller
141 ## also it feels like a job for the controller
142 %if c.rhodecode_user.username != 'default':
142 %if c.rhodecode_user.username != 'default':
143 <li>
143 <li>
144 <a class="${follow_class()}" onclick="javascript:toggleFollowingRepo(this,${c.rhodecode_db_repo.repo_id},'${str(h.get_token())}');">
144 <a class="${follow_class()}" onclick="javascript:toggleFollowingRepo(this,${c.rhodecode_db_repo.repo_id},'${str(h.get_token())}');">
145 <span class="show-follow">${_('Follow')}</span>
145 <span class="show-follow">${_('Follow')}</span>
146 <span class="show-following">${_('Unfollow')}</span>
146 <span class="show-following">${_('Unfollow')}</span>
147 </a>
147 </a>
148 </li>
148 </li>
149 <li><a href="${h.url('repo_fork_home',repo_name=c.repo_name)}" class="fork">${_('Fork')}</a></li>
149 <li><a href="${h.url('repo_fork_home',repo_name=c.repo_name)}" class="fork">${_('Fork')}</a></li>
150 %if h.is_hg(c.rhodecode_repo):
150 %if h.is_hg(c.rhodecode_repo):
151 <li><a href="${h.url('pullrequest_home',repo_name=c.repo_name)}" class="pull-request">${_('Create Pull Request')}</a></li>
151 <li><a href="${h.url('pullrequest_home',repo_name=c.repo_name)}" class="pull-request">${_('Create Pull Request')}</a></li>
152 %endif
152 %endif
153 %endif
153 %endif
154 </ul>
154 </ul>
155 </li>
155 </li>
156 <li ${is_current('showpullrequest')}>
156 <li ${is_current('showpullrequest')}>
157 <a href="${h.url('pullrequest_show_all',repo_name=c.repo_name)}" title="${_('Show Pull Requests')}" class="pull-request">${_('Pull Requests')}
157 <a href="${h.url('pullrequest_show_all',repo_name=c.repo_name)}" title="${_('Show Pull Requests')}" class="pull-request">${_('Pull Requests')}
158 %if c.repository_pull_requests:
158 %if c.repository_pull_requests:
159 <span>${c.repository_pull_requests}</span>
159 <span>${c.repository_pull_requests}</span>
160 %endif
160 %endif
161 </a>
161 </a>
162 </li>
162 </li>
163 </ul>
163 </ul>
164 </div>
164 </div>
165 <script type="text/javascript">
165 <script type="text/javascript">
166 YUE.on('branch_tag_switcher_2','mouseover',function(){
166 YUE.on('branch_tag_switcher_2','mouseover',function(){
167 var loaded = YUD.hasClass('branch_tag_switcher_2','loaded');
167 var loaded = YUD.hasClass('branch_tag_switcher_2','loaded');
168 if(!loaded){
168 if(!loaded){
169 YUD.addClass('branch_tag_switcher_2','loaded');
169 YUD.addClass('branch_tag_switcher_2','loaded');
170 ypjax("${h.url('branch_tag_switcher',repo_name=c.repo_name)}",'switch_to_list_2',
170 ypjax("${h.url('branch_tag_switcher',repo_name=c.repo_name)}",'switch_to_list_2',
171 function(o){},
171 function(o){},
172 function(o){YUD.removeClass('branch_tag_switcher_2','loaded');}
172 function(o){YUD.removeClass('branch_tag_switcher_2','loaded');}
173 ,null);
173 ,null);
174 }
174 }
175 return false;
175 return false;
176 });
176 });
177 </script>
177 </script>
178 <!--- END CONTEXT BAR -->
178 <!--- END CONTEXT BAR -->
179 </%def>
179 </%def>
180
180
181 <%def name="usermenu()">
181 <%def name="usermenu()">
182 ## USER MENU
182 ## USER MENU
183 <li>
183 <li>
184 <a class="menu_link childs" id="quick_login_link">
184 <a class="menu_link childs" id="quick_login_link">
185 <span class="icon">
185 <span class="icon">
186 <img src="${h.gravatar_url(c.rhodecode_user.email,20)}" alt="avatar">
186 <img src="${h.gravatar_url(c.rhodecode_user.email,20)}" alt="avatar">
187 </span>
187 </span>
188 %if c.rhodecode_user.username != 'default':
188 %if c.rhodecode_user.username != 'default':
189 <span class="menu_link_user">${c.rhodecode_user.username}</span>
189 <span class="menu_link_user">${c.rhodecode_user.username}</span>
190 %if c.unread_notifications != 0:
190 %if c.unread_notifications != 0:
191 <span class="menu_link_notifications">${c.unread_notifications}</span>
191 <span class="menu_link_notifications">${c.unread_notifications}</span>
192 %endif
192 %endif
193 %else:
193 %else:
194 <span>${_('Not logged in')}</span>
194 <span>${_('Not logged in')}</span>
195 %endif
195 %endif
196 </a>
196 </a>
197
197
198 <div class="user-menu">
198 <div class="user-menu">
199 <div id="quick_login">
199 <div id="quick_login">
200 %if c.rhodecode_user.username == 'default':
200 %if c.rhodecode_user.username == 'default':
201 <h4>${_('Login to your account')}</h4>
201 <h4>${_('Login to your account')}</h4>
202 ${h.form(h.url('login_home',came_from=h.url.current()))}
202 ${h.form(h.url('login_home',came_from=h.url.current()))}
203 <div class="form">
203 <div class="form">
204 <div class="fields">
204 <div class="fields">
205 <div class="field">
205 <div class="field">
206 <div class="label">
206 <div class="label">
207 <label for="username">${_('Username')}:</label>
207 <label for="username">${_('Username')}:</label>
208 </div>
208 </div>
209 <div class="input">
209 <div class="input">
210 ${h.text('username',class_='focus')}
210 ${h.text('username',class_='focus')}
211 </div>
211 </div>
212
212
213 </div>
213 </div>
214 <div class="field">
214 <div class="field">
215 <div class="label">
215 <div class="label">
216 <label for="password">${_('Password')}:</label>
216 <label for="password">${_('Password')}:</label>
217 </div>
217 </div>
218 <div class="input">
218 <div class="input">
219 ${h.password('password',class_='focus')}
219 ${h.password('password',class_='focus')}
220 </div>
220 </div>
221
221
222 </div>
222 </div>
223 <div class="buttons">
223 <div class="buttons">
224 <div class="password_forgoten">${h.link_to(_('Forgot password ?'),h.url('reset_password'))}</div>
224 <div class="password_forgoten">${h.link_to(_('Forgot password ?'),h.url('reset_password'))}</div>
225 <div class="register">
225 <div class="register">
226 %if h.HasPermissionAny('hg.admin', 'hg.register.auto_activate', 'hg.register.manual_activate')():
226 %if h.HasPermissionAny('hg.admin', 'hg.register.auto_activate', 'hg.register.manual_activate')():
227 ${h.link_to(_("Don't have an account ?"),h.url('register'))}
227 ${h.link_to(_("Don't have an account ?"),h.url('register'))}
228 %endif
228 %endif
229 </div>
229 </div>
230 <div class="submit">
230 <div class="submit">
231 ${h.submit('sign_in',_('Log In'),class_="ui-btn xsmall")}
231 ${h.submit('sign_in',_('Log In'),class_="ui-btn xsmall")}
232 </div>
232 </div>
233 </div>
233 </div>
234 </div>
234 </div>
235 </div>
235 </div>
236 ${h.end_form()}
236 ${h.end_form()}
237 %else:
237 %else:
238 <div class="links_left">
238 <div class="links_left">
239 <div class="big_gravatar"><img alt="gravatar" src="${h.gravatar_url(c.rhodecode_user.email,48)}" /></div>
239 <div class="big_gravatar"><img alt="gravatar" src="${h.gravatar_url(c.rhodecode_user.email,48)}" /></div>
240 <div class="full_name">${c.rhodecode_user.full_name_or_username}</div>
240 <div class="full_name">${c.rhodecode_user.full_name_or_username}</div>
241 <div class="email">${c.rhodecode_user.email}</div>
241 <div class="email">${c.rhodecode_user.email}</div>
242 </div>
242 </div>
243 <div class="links_right">
243 <div class="links_right">
244 <ol class="links">
244 <ol class="links">
245 <li><a href="${h.url('notifications')}">${_('Notifications')}: ${c.unread_notifications}</a></li>
245 <li><a href="${h.url('notifications')}">${_('Notifications')}: ${c.unread_notifications}</a></li>
246 <li>${h.link_to(_(u'My account'),h.url('admin_settings_my_account'))}</li>
246 <li>${h.link_to(_(u'My account'),h.url('admin_settings_my_account'))}</li>
247 <li class="logout">${h.link_to(_(u'Log Out'),h.url('logout_home'))}</li>
247 <li class="logout">${h.link_to(_(u'Log Out'),h.url('logout_home'))}</li>
248 </ol>
248 </ol>
249 </div>
249 </div>
250 %endif
250 %endif
251 </div>
251 </div>
252 </div>
252 </div>
253
253
254 </li>
254 </li>
255 </%def>
255 </%def>
256
256
257 <%def name="menu(current=None)">
257 <%def name="menu(current=None)">
258 <%
258 <%
259 def is_current(selected):
259 def is_current(selected):
260 if selected == current:
260 if selected == current:
261 return h.literal('class="current"')
261 return h.literal('class="current"')
262 %>
262 %>
263 <ul id="quick" class="horizontal-list">
263 <ul id="quick" class="horizontal-list">
264 <!-- repo switcher -->
264 <!-- repo switcher -->
265 <li ${is_current('repositories')}>
265 <li ${is_current('repositories')}>
266 <a class="menu_link repo_switcher childs" id="repo_switcher" title="${_('Switch repository')}" href="${h.url('home')}">
266 <a class="menu_link repo_switcher childs" id="repo_switcher" title="${_('Switch repository')}" href="${h.url('home')}">
267 ${_('Repositories')}
267 ${_('Repositories')}
268 </a>
268 </a>
269 <ul id="repo_switcher_list" class="repo_switcher">
269 <ul id="repo_switcher_list" class="repo_switcher">
270 <li>
270 <li>
271 <a href="#">${_('loading...')}</a>
271 <a href="#">${_('loading...')}</a>
272 </li>
272 </li>
273 </ul>
273 </ul>
274 </li>
274 </li>
275 ##ROOT MENU
275 ##ROOT MENU
276 %if c.rhodecode_user.username != 'default':
276 %if c.rhodecode_user.username != 'default':
277 <li ${is_current('journal')}>
277 <li ${is_current('journal')}>
278 <a class="menu_link journal" title="${_('Show recent activity')}" href="${h.url('journal')}">
278 <a class="menu_link journal" title="${_('Show recent activity')}" href="${h.url('journal')}">
279 ${_('Journal')}
279 ${_('Journal')}
280 </a>
280 </a>
281 </li>
281 </li>
282 %else:
282 %else:
283 <li ${is_current('journal')}>
283 <li ${is_current('journal')}>
284 <a class="menu_link journal" title="${_('Public journal')}" href="${h.url('public_journal')}">
284 <a class="menu_link journal" title="${_('Public journal')}" href="${h.url('public_journal')}">
285 ${_('Public journal')}
285 ${_('Public journal')}
286 </a>
286 </a>
287 </li>
287 </li>
288 %endif
288 %endif
289 <li ${is_current('gists')}>
289 <li ${is_current('gists')}>
290 <a class="menu_link gists childs" title="${_('Show public gists')}" href="${h.url('gists')}">
290 <a class="menu_link gists childs" title="${_('Show public gists')}" href="${h.url('gists')}">
291 ${_('Gists')}
291 ${_('Gists')}
292 </a>
292 </a>
293 <ul class="admin_menu">
293 <ul class="admin_menu">
294 <li>${h.link_to(_('Create new gist'),h.url('new_gist'),class_='gists-new ')}</li>
294 <li>${h.link_to(_('Create new gist'),h.url('new_gist'),class_='gists-new ')}</li>
295 <li>${h.link_to(_('Public gists'),h.url('gists'),class_='gists ')}</li>
295 <li>${h.link_to(_('All public gists'),h.url('gists'),class_='gists ')}</li>
296 %if c.rhodecode_user.username != 'default':
296 %if c.rhodecode_user.username != 'default':
297 <li>${h.link_to(_('My public gists'),h.url('gists', public=1),class_='gists')}</li>
297 <li>${h.link_to(_('My private gists'),h.url('gists', private=1),class_='gists-private ')}</li>
298 <li>${h.link_to(_('My private gists'),h.url('gists', private=1),class_='gists-private ')}</li>
298 %endif
299 %endif
299 </ul>
300 </ul>
300 </li>
301 </li>
301 <li ${is_current('search')}>
302 <li ${is_current('search')}>
302 <a class="menu_link search" title="${_('Search in repositories')}" href="${h.url('search')}">
303 <a class="menu_link search" title="${_('Search in repositories')}" href="${h.url('search')}">
303 ${_('Search')}
304 ${_('Search')}
304 </a>
305 </a>
305 </li>
306 </li>
306 % if h.HasPermissionAll('hg.admin')('access admin main page'):
307 % if h.HasPermissionAll('hg.admin')('access admin main page'):
307 <li ${is_current('admin')}>
308 <li ${is_current('admin')}>
308 <a class="menu_link admin childs" title="${_('Admin')}" href="${h.url('admin_home')}">
309 <a class="menu_link admin childs" title="${_('Admin')}" href="${h.url('admin_home')}">
309 ${_('Admin')}
310 ${_('Admin')}
310 </a>
311 </a>
311 ${admin_menu()}
312 ${admin_menu()}
312 </li>
313 </li>
313 % elif c.rhodecode_user.repository_groups_admin or c.rhodecode_user.user_groups_admin:
314 % elif c.rhodecode_user.repository_groups_admin or c.rhodecode_user.user_groups_admin:
314 <li ${is_current('admin')}>
315 <li ${is_current('admin')}>
315 <a class="menu_link admin childs" title="${_('Admin')}">
316 <a class="menu_link admin childs" title="${_('Admin')}">
316 ${_('Admin')}
317 ${_('Admin')}
317 </a>
318 </a>
318 ${admin_menu_simple(c.rhodecode_user.repository_groups_admin,
319 ${admin_menu_simple(c.rhodecode_user.repository_groups_admin,
319 c.rhodecode_user.user_groups_admin or h.HasPermissionAny('hg.usergroup.create.true')())}
320 c.rhodecode_user.user_groups_admin or h.HasPermissionAny('hg.usergroup.create.true')())}
320 </li>
321 </li>
321 % endif
322 % endif
322 ${usermenu()}
323 ${usermenu()}
323 <script type="text/javascript">
324 <script type="text/javascript">
324 YUE.on('repo_switcher','mouseover',function(){
325 YUE.on('repo_switcher','mouseover',function(){
325 var target = 'q_filter_rs';
326 var target = 'q_filter_rs';
326 var qfilter_activate = function(){
327 var qfilter_activate = function(){
327 var nodes = YUQ('ul#repo_switcher_list li a.repo_name');
328 var nodes = YUQ('ul#repo_switcher_list li a.repo_name');
328 var func = function(node){
329 var func = function(node){
329 return node.parentNode;
330 return node.parentNode;
330 }
331 }
331 q_filter(target,nodes,func);
332 q_filter(target,nodes,func);
332 }
333 }
333
334
334 var loaded = YUD.hasClass('repo_switcher','loaded');
335 var loaded = YUD.hasClass('repo_switcher','loaded');
335 if(!loaded){
336 if(!loaded){
336 YUD.addClass('repo_switcher','loaded');
337 YUD.addClass('repo_switcher','loaded');
337 ypjax("${h.url('repo_switcher')}",'repo_switcher_list',
338 ypjax("${h.url('repo_switcher')}",'repo_switcher_list',
338 function(o){qfilter_activate();YUD.get(target).focus()},
339 function(o){qfilter_activate();YUD.get(target).focus()},
339 function(o){YUD.removeClass('repo_switcher','loaded');}
340 function(o){YUD.removeClass('repo_switcher','loaded');}
340 ,null);
341 ,null);
341 }else{
342 }else{
342 YUD.get(target).focus();
343 YUD.get(target).focus();
343 }
344 }
344 return false;
345 return false;
345 });
346 });
346
347
347 YUE.on('header-dd', 'click',function(e){
348 YUE.on('header-dd', 'click',function(e){
348 YUD.addClass('header-inner', 'hover');
349 YUD.addClass('header-inner', 'hover');
349 YUD.addClass('content', 'hover');
350 YUD.addClass('content', 'hover');
350 });
351 });
351
352
352 </script>
353 </script>
353 </%def>
354 </%def>
General Comments 0
You need to be logged in to leave comments. Login now