##// END OF EJS Templates
pyramid: stop relying on global mako url() function....
marcink -
r1910:45702bf2 default
parent child Browse files
Show More
@@ -1,331 +1,330 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2010-2017 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 import io
21 21 import re
22 22 import datetime
23 23 import logging
24 24 import pylons
25 25 import Queue
26 26 import subprocess32
27 27 import os
28 28
29 29 from pyramid.i18n import get_localizer
30 30 from pyramid.threadlocal import get_current_request
31 31 from pyramid.interfaces import IRoutesMapper
32 32 from pyramid.settings import asbool
33 33 from pyramid.path import AssetResolver
34 34 from threading import Thread
35 35
36 36 from rhodecode.translation import _ as tsf
37 37 from rhodecode.config.jsroutes import generate_jsroutes_content
38 38
39 39 import rhodecode
40 40
41 41 from pylons.i18n.translation import _get_translator
42 42 from pylons.util import ContextObj
43 43 from routes.util import URLGenerator
44 44
45 45 from rhodecode.lib.base import attach_context_attributes, get_auth_user
46 46
47 47 log = logging.getLogger(__name__)
48 48
49 49
50 50 def add_renderer_globals(event):
51 51 from rhodecode.lib import helpers
52 52
53 53 # NOTE(marcink):
54 54 # Put pylons stuff into the context. This will be removed as soon as
55 55 # migration to pyramid is finished.
56 56 event['c'] = pylons.tmpl_context
57 event['url'] = pylons.url
58 57
59 58 # TODO: When executed in pyramid view context the request is not available
60 59 # in the event. Find a better solution to get the request.
61 60 request = event['request'] or get_current_request()
62 61
63 62 # Add Pyramid translation as '_' to context
64 63 event['_'] = request.translate
65 64 event['_ungettext'] = request.plularize
66 65 event['h'] = helpers
67 66
68 67
69 68 def add_localizer(event):
70 69 request = event.request
71 70 localizer = get_localizer(request)
72 71
73 72 def auto_translate(*args, **kwargs):
74 73 return localizer.translate(tsf(*args, **kwargs))
75 74
76 75 request.localizer = localizer
77 76 request.translate = auto_translate
78 77 request.plularize = localizer.pluralize
79 78
80 79
81 80 def set_user_lang(event):
82 81 request = event.request
83 82 cur_user = getattr(request, 'user', None)
84 83
85 84 if cur_user:
86 85 user_lang = cur_user.get_instance().user_data.get('language')
87 86 if user_lang:
88 87 log.debug('lang: setting current user:%s language to: %s', cur_user, user_lang)
89 88 event.request._LOCALE_ = user_lang
90 89
91 90
92 91 def add_request_user_context(event):
93 92 """
94 93 Adds auth user into request context
95 94 """
96 95 request = event.request
97 96
98 97 if hasattr(request, 'vcs_call'):
99 98 # skip vcs calls
100 99 return
101 100
102 101 if hasattr(request, 'rpc_method'):
103 102 # skip api calls
104 103 return
105 104
106 105 auth_user = get_auth_user(request)
107 106 request.user = auth_user
108 107 request.environ['rc_auth_user'] = auth_user
109 108
110 109
111 110 def add_pylons_context(event):
112 111 request = event.request
113 112
114 113 config = rhodecode.CONFIG
115 114 environ = request.environ
116 115 session = request.session
117 116
118 117 if hasattr(request, 'vcs_call'):
119 118 # skip vcs calls
120 119 return
121 120
122 121 # Setup pylons globals.
123 122 pylons.config._push_object(config)
124 123 pylons.request._push_object(request)
125 124 pylons.session._push_object(session)
126 125 pylons.translator._push_object(_get_translator(config.get('lang')))
127 126
128 127 pylons.url._push_object(URLGenerator(config['routes.map'], environ))
129 128 session_key = (
130 129 config['pylons.environ_config'].get('session', 'beaker.session'))
131 130 environ[session_key] = session
132 131
133 132 if hasattr(request, 'rpc_method'):
134 133 # skip api calls
135 134 return
136 135
137 136 # Setup the pylons context object ('c')
138 137 context = ContextObj()
139 138 context.rhodecode_user = request.user
140 139 attach_context_attributes(context, request, request.user.user_id)
141 140 pylons.tmpl_context._push_object(context)
142 141
143 142
144 143 def scan_repositories_if_enabled(event):
145 144 """
146 145 This is subscribed to the `pyramid.events.ApplicationCreated` event. It
147 146 does a repository scan if enabled in the settings.
148 147 """
149 148 settings = event.app.registry.settings
150 149 vcs_server_enabled = settings['vcs.server.enable']
151 150 import_on_startup = settings['startup.import_repos']
152 151 if vcs_server_enabled and import_on_startup:
153 152 from rhodecode.model.scm import ScmModel
154 153 from rhodecode.lib.utils import repo2db_mapper, get_rhodecode_base_path
155 154 repositories = ScmModel().repo_scan(get_rhodecode_base_path())
156 155 repo2db_mapper(repositories, remove_obsolete=False)
157 156
158 157
159 158 def write_metadata_if_needed(event):
160 159 """
161 160 Writes upgrade metadata
162 161 """
163 162 import rhodecode
164 163 from rhodecode.lib import system_info
165 164 from rhodecode.lib import ext_json
166 165
167 166 def write():
168 167 fname = '.rcmetadata.json'
169 168 ini_loc = os.path.dirname(rhodecode.CONFIG.get('__file__'))
170 169 metadata_destination = os.path.join(ini_loc, fname)
171 170
172 171 configuration = system_info.SysInfo(
173 172 system_info.rhodecode_config)()['value']
174 173 license_token = configuration['config']['license_token']
175 174 dbinfo = system_info.SysInfo(system_info.database_info)()['value']
176 175 del dbinfo['url']
177 176 metadata = dict(
178 177 desc='upgrade metadata info',
179 178 license_token=license_token,
180 179 created_on=datetime.datetime.utcnow().isoformat(),
181 180 usage=system_info.SysInfo(system_info.usage_info)()['value'],
182 181 platform=system_info.SysInfo(system_info.platform_type)()['value'],
183 182 database=dbinfo,
184 183 cpu=system_info.SysInfo(system_info.cpu)()['value'],
185 184 memory=system_info.SysInfo(system_info.memory)()['value'],
186 185 )
187 186
188 187 with open(metadata_destination, 'wb') as f:
189 188 f.write(ext_json.json.dumps(metadata))
190 189
191 190 settings = event.app.registry.settings
192 191 if settings.get('metadata.skip'):
193 192 return
194 193
195 194 try:
196 195 write()
197 196 except Exception:
198 197 pass
199 198
200 199
201 200 def write_js_routes_if_enabled(event):
202 201 registry = event.app.registry
203 202
204 203 mapper = registry.queryUtility(IRoutesMapper)
205 204 _argument_prog = re.compile('\{(.*?)\}|:\((.*)\)')
206 205
207 206 def _extract_route_information(route):
208 207 """
209 208 Convert a route into tuple(name, path, args), eg:
210 209 ('show_user', '/profile/%(username)s', ['username'])
211 210 """
212 211
213 212 routepath = route.pattern
214 213 pattern = route.pattern
215 214
216 215 def replace(matchobj):
217 216 if matchobj.group(1):
218 217 return "%%(%s)s" % matchobj.group(1).split(':')[0]
219 218 else:
220 219 return "%%(%s)s" % matchobj.group(2)
221 220
222 221 routepath = _argument_prog.sub(replace, routepath)
223 222
224 223 if not routepath.startswith('/'):
225 224 routepath = '/'+routepath
226 225
227 226 return (
228 227 route.name,
229 228 routepath,
230 229 [(arg[0].split(':')[0] if arg[0] != '' else arg[1])
231 230 for arg in _argument_prog.findall(pattern)]
232 231 )
233 232
234 233 def get_routes():
235 234 # pylons routes
236 235 for route in rhodecode.CONFIG['routes.map'].jsroutes():
237 236 yield route
238 237
239 238 # pyramid routes
240 239 for route in mapper.get_routes():
241 240 if not route.name.startswith('__'):
242 241 yield _extract_route_information(route)
243 242
244 243 if asbool(registry.settings.get('generate_js_files', 'false')):
245 244 static_path = AssetResolver().resolve('rhodecode:public').abspath()
246 245 jsroutes = get_routes()
247 246 jsroutes_file_content = generate_jsroutes_content(jsroutes)
248 247 jsroutes_file_path = os.path.join(
249 248 static_path, 'js', 'rhodecode', 'routes.js')
250 249
251 250 with io.open(jsroutes_file_path, 'w', encoding='utf-8') as f:
252 251 f.write(jsroutes_file_content)
253 252
254 253
255 254 class Subscriber(object):
256 255 """
257 256 Base class for subscribers to the pyramid event system.
258 257 """
259 258 def __call__(self, event):
260 259 self.run(event)
261 260
262 261 def run(self, event):
263 262 raise NotImplementedError('Subclass has to implement this.')
264 263
265 264
266 265 class AsyncSubscriber(Subscriber):
267 266 """
268 267 Subscriber that handles the execution of events in a separate task to not
269 268 block the execution of the code which triggers the event. It puts the
270 269 received events into a queue from which the worker process takes them in
271 270 order.
272 271 """
273 272 def __init__(self):
274 273 self._stop = False
275 274 self._eventq = Queue.Queue()
276 275 self._worker = self.create_worker()
277 276 self._worker.start()
278 277
279 278 def __call__(self, event):
280 279 self._eventq.put(event)
281 280
282 281 def create_worker(self):
283 282 worker = Thread(target=self.do_work)
284 283 worker.daemon = True
285 284 return worker
286 285
287 286 def stop_worker(self):
288 287 self._stop = False
289 288 self._eventq.put(None)
290 289 self._worker.join()
291 290
292 291 def do_work(self):
293 292 while not self._stop:
294 293 event = self._eventq.get()
295 294 if event is not None:
296 295 self.run(event)
297 296
298 297
299 298 class AsyncSubprocessSubscriber(AsyncSubscriber):
300 299 """
301 300 Subscriber that uses the subprocess32 module to execute a command if an
302 301 event is received. Events are handled asynchronously.
303 302 """
304 303
305 304 def __init__(self, cmd, timeout=None):
306 305 super(AsyncSubprocessSubscriber, self).__init__()
307 306 self._cmd = cmd
308 307 self._timeout = timeout
309 308
310 309 def run(self, event):
311 310 cmd = self._cmd
312 311 timeout = self._timeout
313 312 log.debug('Executing command %s.', cmd)
314 313
315 314 try:
316 315 output = subprocess32.check_output(
317 316 cmd, timeout=timeout, stderr=subprocess32.STDOUT)
318 317 log.debug('Command finished %s', cmd)
319 318 if output:
320 319 log.debug('Command output: %s', output)
321 320 except subprocess32.TimeoutExpired as e:
322 321 log.exception('Timeout while executing command.')
323 322 if e.output:
324 323 log.error('Command output: %s', e.output)
325 324 except subprocess32.CalledProcessError as e:
326 325 log.exception('Error while executing command.')
327 326 if e.output:
328 327 log.error('Command output: %s', e.output)
329 328 except:
330 329 log.exception(
331 330 'Exception while executing command %s.', cmd)
@@ -1,81 +1,81 b''
1 1 <div class="panel panel-default">
2 2 <div class="panel-heading">
3 3 <h3 class="panel-title">${_('Default Settings For New Repositories')}</h3>
4 4 </div>
5 5 <div class="panel-body">
6 ${h.secure_form(url('admin_defaults_repositories'), method='post')}
6 ${h.secure_form(h.url('admin_defaults_repositories'), method='post')}
7 7 <div class="form">
8 8 <!-- fields -->
9 9
10 10 <div class="fields">
11 11
12 12 <div class="field">
13 13 <div class="label">
14 14 <label for="default_repo_type">${_('Type')}:</label>
15 15 </div>
16 16 <div class="select">
17 17 ${h.select('default_repo_type','hg',c.backends,class_="medium")}
18 18 </div>
19 19 </div>
20 20
21 21 <div class="field">
22 22 <div class="label label-checkbox">
23 23 <label for="default_repo_private">${_('Private Repository')}:</label>
24 24 </div>
25 25 <div class="checkboxes">
26 26 ${h.checkbox('default_repo_private',value="True")}
27 27 <span class="help-block">${_('Private repositories are only visible to people explicitly added as collaborators.')}</span>
28 28 </div>
29 29 </div>
30 30
31 31
32 32 <div class="field">
33 33 <div class="label label-checkbox">
34 34 <label for="default_repo_enable_statistics">${_('Enable Statistics')}:</label>
35 35 </div>
36 36 <div class="checkboxes">
37 37 ${h.checkbox('default_repo_enable_statistics',value="True")}
38 38 <span class="help-block">${_('Enable a statistics window on the repository summary page.')}</span>
39 39 </div>
40 40 </div>
41 41
42 42 <div class="field">
43 43 <div class="label label-checkbox">
44 44 <label for="default_repo_enable_downloads">${_('Enable Downloads')}:</label>
45 45 </div>
46 46 <div class="checkboxes">
47 47 ${h.checkbox('default_repo_enable_downloads',value="True")}
48 48 <span class="help-block">${_('Enable the download option on the repository summary page.')}</span>
49 49 </div>
50 50 </div>
51 51
52 52 <div class="field">
53 53 <div class="label label-checkbox">
54 54 <label for="default_repo_enable_locking">${_('Enable Locking')}:</label>
55 55 </div>
56 56 <div class="checkboxes">
57 57 ${h.checkbox('default_repo_enable_locking',value="True")}
58 58 <span class="help-block">${_('Enable automatic repository locking. Pulling from a repository will lock it, and it is unlocked by pushing back by the same user.')}</span>
59 59 </div>
60 60 </div>
61 61
62 62 <div class="buttons">
63 63 ${h.submit('save',_('Save'),class_="btn")}
64 64 </div>
65 65 </div>
66 66 </div>
67 67 ${h.end_form()}
68 68 </div>
69 69
70 70 </div>
71 71
72 72 <script>
73 73 $(document).ready(function(){
74 74 $("#default_repo_type").select2({
75 75 containerCssClass: 'drop-menu',
76 76 dropdownCssClass: 'drop-menu-dropdown',
77 77 dropdownAutoWidth: true,
78 78 minimumResultsForSearch: -1
79 79 });
80 80 })
81 81 </script>
@@ -1,78 +1,78 b''
1 1 ## -*- coding: utf-8 -*-
2 2 <%inherit file="/base/base.mako"/>
3 3
4 4 <%def name="title()">
5 5 ${_('My Notifications')} ${c.rhodecode_user.username}
6 6 %if c.rhodecode_name:
7 7 &middot; ${h.branding(c.rhodecode_name)}
8 8 %endif
9 9 </%def>
10 10
11 11 <%def name="breadcrumbs_links()">
12 12 ${_('My Notifications')}
13 13 </%def>
14 14
15 15 <%def name="menu_bar_nav()">
16 16 ${self.menu_items(active='admin')}
17 17 </%def>
18 18
19 19 <%def name="main()">
20 20 <div class="box">
21 21 <!-- box / title -->
22 22 <div class="title">
23 23 ${self.breadcrumbs()}
24 24 ##<ul class="links">
25 25 ## <li>
26 26 ## <span ><a href="#">${_('Compose message')}</a></span>
27 27 ## </li>
28 28 ##</ul>
29 29
30 30 <div class="notifications_buttons">
31 31 <span id='all' class="action-link first ${'active' if c.current_filter=='all' else ''}"><a href="${h.url.current()}">${_('All')}</a></span>
32 32 <span id='comment' class="action-link ${'active' if c.current_filter=='comment' else ''}"><a href="${h.url.current(type=c.comment_type)}">${_('Comments')}</a></span>
33 33 <span id='pull_request' class="action-link last ${'active' if c.current_filter=='pull_request' else ''}"><a href="${h.url.current(type=c.pull_request_type)}">${_('Pull Requests')}</a></span>
34 34
35 35 %if c.notifications:
36 36
37 37 <span id='mark_all_read' class="btn btn-default">${_('Mark all as read')}</span>
38 38
39 39 %endif
40 40 </div>
41 41 </div>
42 42 <div id='notification_data' class='main-content-full'>
43 43 <%include file='notifications_data.mako'/>
44 44 </div>
45 45 </div>
46 46 <script type="text/javascript">
47 var url_action = "${url('notification', notification_id='__NOTIFICATION_ID__')}";
47 var url_action = "${h.url('notification', notification_id='__NOTIFICATION_ID__')}";
48 48 var run = function(){
49 49 $('#notification_data').on('click','.delete-notification',function(e){
50 50 var notification_id = e.currentTarget.id;
51 51 deleteNotification(url_action,notification_id)
52 52 });
53 53 $('#notification_data').on('click','.read-notification',function(e){
54 54 var notification_id = e.currentTarget.id;
55 55 readNotification(url_action,notification_id)
56 56 })
57 57 };
58 58 run();
59 59 $('#mark_all_read').on('click',function(e){
60 60 //set notifications as read
61 61 var url = "${h.url('notifications_mark_all_read', **request.GET.mixed())}";
62 62 $.post(url, {'csrf_token': CSRF_TOKEN}).
63 63 done(function(data){
64 64 // hide notifications counter
65 65 $('#quick_login_link > .menu_link_notifications').hide();
66 66 $('#notification_data').html(data);
67 67 })
68 68 .fail(function(data, textStatus, errorThrown){
69 69 alert("Error while saving notifications.\nError code {0} ({1}). URL: {2}".format(data.status,data.statusText,$(this)[0].url));
70 70 });
71 71 });
72 72
73 73 var current_filter = $("${c.current_filter}");
74 74 if (current_filter.length){
75 75 current_filter.addClass('active');
76 76 }
77 77 </script>
78 78 </%def>
@@ -1,40 +1,40 b''
1 1 <%namespace name="base" file="/base/base.mako"/>
2 2 %if c.notifications:
3 3 <%
4 4 unread = lambda n:{False:'unread'}.get(n)
5 5 %>
6 6
7 7
8 8 <div class="notification-list notification-table">
9 9 %for notification in c.notifications:
10 10 <div id="notification_${notification.notification.notification_id}" class="container ${unread(notification.read)}">
11 11 <div class="notification-header">
12 12 <div class="desc ${unread(notification.read)}">
13 <a href="${url('notification', notification_id=notification.notification.notification_id)}">
13 <a href="${h.url('notification', notification_id=notification.notification.notification_id)}">
14 14 ${base.gravatar(notification.notification.created_by_user.email, 16)}
15 15 ${notification.notification.description}
16 16 </a>
17 17 </div>
18 18 <div class="delete-notifications">
19 19 <span id="${notification.notification.notification_id}" class="delete-notification"><i class="icon-delete" ></i></span>
20 20 </div>
21 21 <div class="read-notifications">
22 22 %if not notification.read:
23 23 <span id="${notification.notification.notification_id}" class="read-notification"><i class="icon-ok" ></i></span>
24 24 %endif
25 25 </div>
26 26 </div>
27 27 <div class="notification-subject"></div>
28 28 </div>
29 29 %endfor
30 30 </div>
31 31
32 32 <div class="notification-paginator">
33 33 <div class="pagination-wh pagination-left">
34 34 ${c.notifications.pager('$link_previous ~2~ $link_next')}
35 35 </div>
36 36 </div>
37 37
38 38 %else:
39 39 <div class="table">${_('No notifications here yet')}</div>
40 40 %endif
@@ -1,57 +1,57 b''
1 1 ## -*- coding: utf-8 -*-
2 2 <%inherit file="/base/base.mako"/>
3 3
4 4 <%def name="title()">
5 5 ${_('Show notification')} ${c.rhodecode_user.username}
6 6 %if c.rhodecode_name:
7 7 &middot; ${h.branding(c.rhodecode_name)}
8 8 %endif
9 9 </%def>
10 10
11 11 <%def name="breadcrumbs_links()">
12 12 ${h.link_to(_('Notifications'), h.url('notifications'))}
13 13 &raquo;
14 14 ${_('Show notification')}
15 15 </%def>
16 16
17 17 <%def name="menu_bar_nav()">
18 18 ${self.menu_items(active='admin')}
19 19 </%def>
20 20
21 21 <%def name="main()">
22 22 <div class="box">
23 23 <!-- box / title -->
24 24 <div class="title">
25 25 ${self.breadcrumbs()}
26 26 </div>
27 27 <div class="table">
28 28 <div id="notification_${c.notification.notification_id}" class="main-content-full">
29 29 <div class="notification-header">
30 30 ${self.gravatar(c.notification.created_by_user.email, 30)}
31 31 <div class="desc">
32 32 ${c.notification.description}
33 33 </div>
34 34 <div class="delete-notifications">
35 35 <span id="${c.notification.notification_id}" class="delete-notification action"><i class="icon-delete" ></i></span>
36 36 </div>
37 37 </div>
38 38 <div class="notification-body">
39 39 <div class="notification-subject">
40 40 <h3>${_('Subject')}: ${c.notification.subject}</h3>
41 41 </div>
42 42 %if c.notification.body:
43 43 ${h.render(c.notification.body, renderer=c.visual.default_renderer, mentions=True)}
44 44 %endif
45 45 </div>
46 46 </div>
47 47 </div>
48 48 </div>
49 49 <script type="text/javascript">
50 var url = "${url('notification', notification_id='__NOTIFICATION_ID__')}";
51 var main = "${url('notifications')}";
50 var url = "${h.url('notification', notification_id='__NOTIFICATION_ID__')}";
51 var main = "${h.url('notifications')}";
52 52 $('.delete-notification').on('click',function(e){
53 53 var notification_id = e.currentTarget.id;
54 54 deleteNotification(url,notification_id,[function(){window.location=main}])
55 55 })
56 56 </script>
57 57 </%def>
@@ -1,81 +1,81 b''
1 1 <div class="panel panel-default">
2 2 <div class="panel-heading">
3 3 <h3 class="panel-title">${_('System Wide Application Permissions')}</h3>
4 4 </div>
5 5 <div class="panel-body">
6 ${h.secure_form(url('admin_permissions_application'), method='post')}
6 ${h.secure_form(h.url('admin_permissions_application'), method='post')}
7 7 <div class="form">
8 8 <!-- fields -->
9 9 <div class="fields">
10 10 <div class="field">
11 11 <div class="label label-checkbox">
12 12 <label for="anonymous">${_('Anonymous Access')}:</label>
13 13 </div>
14 14 <div class="checkboxes">
15 15 <div class="checkbox">
16 16 ${h.checkbox('anonymous',True)} Allow Anonymous Access
17 17 </div>
18 18 <span class="help-block">${h.literal(_('Allow access to RhodeCode Enterprise without requiring users to login. Anonymous users get the %s permission settings.' % (h.link_to('"default user"',h.url('admin_permissions_object')))))}</span>
19 19 </div>
20 20 </div>
21 21
22 22 <div class="field">
23 23 <div class="label label-select">
24 24 <label for="default_register">${_('Registration')}:</label>
25 25 </div>
26 26 <div class="select">
27 27 ${h.select('default_register','',c.register_choices)}
28 28 </div>
29 29 </div>
30 30
31 31 <div class="field">
32 32 <div class="label label-select">
33 33 <label for="default_password_reset">${_('Password Reset')}:</label>
34 34 </div>
35 35 <div class="select">
36 36 ${h.select('default_password_reset','',c.password_reset_choices)}
37 37 </div>
38 38 </div>
39 39
40 40 <div class="field">
41 41 <div class="label label-textarea">
42 42 <label for="default_register_message">${_('Registration Page Message')}:</label>
43 43 </div>
44 44 <div class="textarea text-area editor" >
45 45 ${h.textarea('default_register_message', class_="medium", )}
46 46 <span class="help-block">${_('Custom message to be displayed on the registration page. HTML syntax is supported.')}</span>
47 47 </div>
48 48 </div>
49 49
50 50 <div class="field">
51 51 <div class="label">
52 52 <label for="default_extern_activate">${_('External Authentication Account Activation')}:</label>
53 53 </div>
54 54 <div class="select">
55 55 ${h.select('default_extern_activate','',c.extern_activate_choices)}
56 56 </div>
57 57 </div>
58 58 <div class="buttons">
59 59 ${h.submit('save',_('Save'),class_="btn")}
60 60 ${h.reset('reset',_('Reset'),class_="btn")}
61 61 </div>
62 62 </div>
63 63 </div>
64 64 ${h.end_form()}
65 65 </div>
66 66 </div>
67 67
68 68 <script>
69 69 $(document).ready(function(){
70 70 var select2Options = {
71 71 containerCssClass: 'drop-menu',
72 72 dropdownCssClass: 'drop-menu-dropdown',
73 73 dropdownAutoWidth: true,
74 74 minimumResultsForSearch: -1
75 75 };
76 76
77 77 $("#default_register").select2(select2Options);
78 78 $("#default_password_reset").select2(select2Options);
79 79 $("#default_extern_activate").select2(select2Options);
80 80 });
81 81 </script>
@@ -1,10 +1,10 b''
1 1
2 ${h.secure_form(url('admin_permissions_global'), method='post')}
2 ${h.secure_form(h.url('admin_permissions_global'), method='post')}
3 3 <div class="form permissions-global">
4 4 <!-- fields -->
5 5 <div class="fields">
6 6 <%namespace name="dpb" file="/base/default_perms_box.mako"/>
7 7 ${dpb.default_perms_radios(global_permissions_template = True)}
8 8 </div>
9 9 </div>
10 10 ${h.end_form()}
@@ -1,77 +1,77 b''
1 1 <div class="panel panel-default">
2 2 <div class="panel-heading">
3 3 <h3 class="panel-title">${_('Default Permissions for Repositories, User Groups and Repository Groups.')}</h3>
4 4 </div>
5 5 <div class="panel-body">
6 6 <p>${_('Default system permissions. Each permissions management entity will be created with the following default settings. Check the overwrite checkbox to force any permission changes on already existing settings.')}
7 7 </p>
8 ${h.secure_form(url('admin_permissions_object'), method='post')}
8 ${h.secure_form(h.url('admin_permissions_object'), method='post')}
9 9 <div class="form">
10 10 <div class="fields">
11 11 <div class="field">
12 12 <div class="label">
13 13 <label for="default_repo_perm">${_('Repository')}:</label>
14 14 </div>
15 15 <div class="select">
16 16 ${h.select('default_repo_perm','',c.repo_perms_choices)}
17 17
18 18 ${h.checkbox('overwrite_default_repo','true')}
19 19 <label for="overwrite_default_repo">
20 20 <span class="tooltip" title="${h.tooltip(_('All default permissions on each repository will be reset to chosen permission, note that all custom default permission on repositories will be lost'))}">
21 21 ${_('Overwrite Existing Settings')}
22 22 </span>
23 23 </label>
24 24 </div>
25 25 </div>
26 26 <div class="field">
27 27 <div class="label">
28 28 <label for="default_group_perm">${_('Repository Groups')}:</label>
29 29 </div>
30 30 <div class="select">
31 31 ${h.select('default_group_perm','',c.group_perms_choices)}
32 32 ${h.checkbox('overwrite_default_group','true')}
33 33 <label for="overwrite_default_group">
34 34 <span class="tooltip" title="${h.tooltip(_('All default permissions on each repository group will be reset to chosen permission, note that all custom default permission on repository groups will be lost'))}">
35 35 ${_('Overwrite Existing Settings')}
36 36 </span>
37 37 </label>
38 38 </div>
39 39 </div>
40 40 <div class="field">
41 41 <div class="label">
42 42 <label for="default_group_perm">${_('User Groups')}:</label>
43 43 </div>
44 44 <div class="select">
45 45 ${h.select('default_user_group_perm','',c.user_group_perms_choices)}
46 46 ${h.checkbox('overwrite_default_user_group','true')}
47 47 <label for="overwrite_default_user_group">
48 48 <span class="tooltip" title="${h.tooltip(_('All default permissions on each user group will be reset to chosen permission, note that all custom default permission on repository groups will be lost'))}">
49 49 ${_('Overwrite Existing Settings')}
50 50 </span>
51 51 </label>
52 52 </div>
53 53 </div>
54 54
55 55 <div class="buttons">
56 56 ${h.submit('save',_('Save'),class_="btn")}
57 57 ${h.reset('reset',_('Reset'),class_="btn")}
58 58 </div>
59 59 </div>
60 60 </div>
61 61 ${h.end_form()}
62 62 </div>
63 63 </div>
64 64
65 65 <script>
66 66 $(document).ready(function(){
67 67 var select2Options = {
68 68 containerCssClass: 'drop-menu',
69 69 dropdownCssClass: 'drop-menu-dropdown',
70 70 dropdownAutoWidth: true,
71 71 minimumResultsForSearch: -1
72 72 };
73 73 $("#default_repo_perm").select2(select2Options);
74 74 $("#default_group_perm").select2(select2Options);
75 75 $("#default_user_group_perm").select2(select2Options);
76 76 });
77 77 </script>
@@ -1,100 +1,100 b''
1 1 ## -*- coding: utf-8 -*-
2 2 <%inherit file="/base/base.mako"/>
3 3
4 4 <%def name="title()">
5 5 ${_('Add repository group')}
6 6 %if c.rhodecode_name:
7 7 &middot; ${h.branding(c.rhodecode_name)}
8 8 %endif
9 9 </%def>
10 10
11 11 <%def name="breadcrumbs_links()">
12 12 ${h.link_to(_('Admin'),h.route_path('admin_home'))}
13 13 &raquo;
14 14 ${h.link_to(_('Repository groups'),h.url('repo_groups'))}
15 15 &raquo;
16 16 ${_('Add Repository Group')}
17 17 </%def>
18 18
19 19 <%def name="menu_bar_nav()">
20 20 ${self.menu_items(active='admin')}
21 21 </%def>
22 22
23 23 <%def name="main()">
24 24 <div class="box">
25 25 <!-- box / title -->
26 26 <div class="title">
27 27 ${self.breadcrumbs()}
28 28 </div>
29 29 <!-- end box / title -->
30 ${h.secure_form(url('repo_groups'), method='post')}
30 ${h.secure_form(h.url('repo_groups'), method='post')}
31 31 <div class="form">
32 32 <!-- fields -->
33 33 <div class="fields">
34 34 <div class="field">
35 35 <div class="label">
36 36 <label for="group_name">${_('Group Name')}:</label>
37 37 </div>
38 38 <div class="input">
39 39 ${h.text('group_name', class_="medium")}
40 40 </div>
41 41 </div>
42 42
43 43 <div class="field">
44 44 <div class="label">
45 45 <label for="group_description">${_('Description')}:</label>
46 46 </div>
47 47 <div class="textarea editor">
48 48 ${h.textarea('group_description',cols=23,rows=5,class_="medium")}
49 49 </div>
50 50 </div>
51 51
52 52 <div class="field">
53 53 <div class="label">
54 54 <label for="group_parent_id">${_('Group Parent')}:</label>
55 55 </div>
56 56 <div class="select">
57 57 ${h.select('group_parent_id',request.GET.get('parent_group'),c.repo_groups,class_="medium")}
58 58 </div>
59 59 </div>
60 60
61 61 <div id="copy_perms" class="field">
62 62 <div class="label label-checkbox">
63 63 <label for="group_copy_permissions">${_('Copy Parent Group Permissions')}:</label>
64 64 </div>
65 65 <div class="checkboxes">
66 66 ${h.checkbox('group_copy_permissions', value="True", checked="checked")}
67 67 <span class="help-block">${_('Copy permission settings from parent repository group.')}</span>
68 68 </div>
69 69 </div>
70 70
71 71 <div class="buttons">
72 72 ${h.submit('save',_('Save'),class_="btn")}
73 73 </div>
74 74 </div>
75 75 </div>
76 76 ${h.end_form()}
77 77 </div>
78 78 <script>
79 79 $(document).ready(function(){
80 80 var setCopyPermsOption = function(group_val){
81 81 if(group_val != "-1"){
82 82 $('#copy_perms').show()
83 83 }
84 84 else{
85 85 $('#copy_perms').hide();
86 86 }
87 87 }
88 88 $("#group_parent_id").select2({
89 89 'containerCssClass': "drop-menu",
90 90 'dropdownCssClass': "drop-menu-dropdown",
91 91 'dropdownAutoWidth': true
92 92 });
93 93 setCopyPermsOption($('#group_parent_id').val())
94 94 $("#group_parent_id").on("change", function(e) {
95 95 setCopyPermsOption(e.val)
96 96 })
97 97 $('#group_name').focus();
98 98 })
99 99 </script>
100 100 </%def>
@@ -1,148 +1,148 b''
1 1 <%namespace name="base" file="/base/base.mako"/>
2 2
3 3 <div class="panel panel-default">
4 4 <div class="panel-heading">
5 5 <h3 class="panel-title">${_('Repository Group Permissions')}</h3>
6 6 </div>
7 7 <div class="panel-body">
8 ${h.secure_form(url('edit_repo_group_perms', group_name=c.repo_group.group_name),method='put')}
8 ${h.secure_form(h.url('edit_repo_group_perms', group_name=c.repo_group.group_name),method='put')}
9 9 <table id="permissions_manage" class="rctable permissions">
10 10 <tr>
11 11 <th class="td-radio">${_('None')}</th>
12 12 <th class="td-radio">${_('Read')}</th>
13 13 <th class="td-radio">${_('Write')}</th>
14 14 <th class="td-radio">${_('Admin')}</th>
15 15 <th class="td-user">${_('User/User Group')}</th>
16 16 <th></th>
17 17 </tr>
18 18 ## USERS
19 19 %for _user in c.repo_group.permissions():
20 20 %if getattr(_user, 'admin_row', None) or getattr(_user, 'owner_row', None):
21 21 <tr class="perm_admin_row">
22 22 <td class="td-radio">${h.radio('admin_perm_%s' % _user.user_id,'repository.none', disabled="disabled")}</td>
23 23 <td class="td-radio">${h.radio('admin_perm_%s' % _user.user_id,'repository.read', disabled="disabled")}</td>
24 24 <td class="td-radio">${h.radio('admin_perm_%s' % _user.user_id,'repository.write', disabled="disabled")}</td>
25 25 <td class="td-radio">${h.radio('admin_perm_%s' % _user.user_id,'repository.admin', 'repository.admin', disabled="disabled")}</td>
26 26 <td class="td-user">
27 27 ${base.gravatar(_user.email, 16)}
28 28 <span class="user">
29 29 ${h.link_to_user(_user.username)}
30 30 %if getattr(_user, 'admin_row', None):
31 31 (${_('super admin')})
32 32 %endif
33 33 %if getattr(_user, 'owner_row', None):
34 34 (${_('owner')})
35 35 %endif
36 36 </span>
37 37 </td>
38 38 <td></td>
39 39 </tr>
40 40 %else:
41 41 ##forbid revoking permission from yourself, except if you're an super admin
42 42 <tr>
43 43 %if c.rhodecode_user.user_id != _user.user_id or c.rhodecode_user.is_admin:
44 44 <td class="td-radio">${h.radio('u_perm_%s' % _user.user_id,'group.none')}</td>
45 45 <td class="td-radio">${h.radio('u_perm_%s' % _user.user_id,'group.read')}</td>
46 46 <td class="td-radio">${h.radio('u_perm_%s' % _user.user_id,'group.write')}</td>
47 47 <td class="td-radio">${h.radio('u_perm_%s' % _user.user_id,'group.admin')}</td>
48 48 <td class="td-user">
49 49 ${base.gravatar(_user.email, 16)}
50 50 <span class="user">
51 51 % if _user.username == h.DEFAULT_USER:
52 52 ${h.DEFAULT_USER} <span class="user-perm-help-text"> - ${_('permission for all other users')}</span>
53 53 % else:
54 54 ${h.link_to_user(_user.username)}
55 55 % endif
56 56 </span>
57 57 </td>
58 58 <td class="td-action">
59 59 %if _user.username != h.DEFAULT_USER:
60 60 <span class="btn btn-link btn-danger revoke_perm"
61 61 member="${_user.user_id}" member_type="user">
62 62 <i class="icon-remove"></i> ${_('Revoke')}
63 63 </span>
64 64 %endif
65 65 </td>
66 66 %else:
67 67 ## special case for current user permissions, we make sure he cannot take his own permissions
68 68 <td class="td-radio">${h.radio('u_perm_%s' % _user.user_id,'group.none', disabled="disabled")}</td>
69 69 <td class="td-radio">${h.radio('u_perm_%s' % _user.user_id,'group.read', disabled="disabled")}</td>
70 70 <td class="td-radio">${h.radio('u_perm_%s' % _user.user_id,'group.write', disabled="disabled")}</td>
71 71 <td class="td-radio">${h.radio('u_perm_%s' % _user.user_id,'group.admin', disabled="disabled")}</td>
72 72 <td class="td-user">
73 73 ${base.gravatar(_user.email, 16)}
74 74 <span class="user">
75 75 % if _user.username == h.DEFAULT_USER:
76 76 ${h.DEFAULT_USER} <span class="user-perm-help-text"> - ${_('permission for all other users')}</span>
77 77 % else:
78 78 ${h.link_to_user(_user.username)}
79 79 % endif
80 80 <span class="user-perm-help-text">(${_('delegated admin')})</span>
81 81 </span>
82 82 </td>
83 83 <td></td>
84 84 %endif
85 85 </tr>
86 86 %endif
87 87 %endfor
88 88
89 89 ## USER GROUPS
90 90 %for _user_group in c.repo_group.permission_user_groups():
91 91 <tr id="id${id(_user_group.users_group_name)}">
92 92 <td class="td-radio">${h.radio('g_perm_%s' % _user_group.users_group_id,'group.none')}</td>
93 93 <td class="td-radio">${h.radio('g_perm_%s' % _user_group.users_group_id,'group.read')}</td>
94 94 <td class="td-radio">${h.radio('g_perm_%s' % _user_group.users_group_id,'group.write')}</td>
95 95 <td class="td-radio">${h.radio('g_perm_%s' % _user_group.users_group_id,'group.admin')}</td>
96 96 <td class="td-componentname">
97 97 <i class="icon-group" ></i>
98 98 %if h.HasPermissionAny('hg.admin')():
99 99 <a href="${h.url('edit_users_group',user_group_id=_user_group.users_group_id)}">
100 100 ${_user_group.users_group_name}
101 101 </a>
102 102 %else:
103 103 ${_user_group.users_group_name}
104 104 %endif
105 105 </td>
106 106 <td class="td-action">
107 107 <span class="btn btn-link btn-danger revoke_perm"
108 108 member="${_user_group.users_group_id}" member_type="user_group">
109 109 <i class="icon-remove"></i> ${_('Revoke')}
110 110 </span>
111 111 </td>
112 112 </tr>
113 113 %endfor
114 114
115 115 <tr class="new_members" id="add_perm_input"></tr>
116 116 </table>
117 117 <div id="add_perm" class="link">
118 118 ${_('Add new')}
119 119 </div>
120 120 <div class="fields">
121 121 <div class="field">
122 122 <div class="label label-radio">
123 123 ${_('Apply to children')}:
124 124 </div>
125 125 <div class="radios">
126 126 ${h.radio('recursive', 'none', label=_('None'), checked="checked")}
127 127 ${h.radio('recursive', 'groups', label=_('Repository Groups'))}
128 128 ${h.radio('recursive', 'repos', label=_('Repositories'))}
129 129 ${h.radio('recursive', 'all', label=_('Both'))}
130 130 <span class="help-block">${_('Set or revoke permissions to selected types of children of this group, including non-private repositories and other groups if chosen.')}</span>
131 131 </div>
132 132 </div>
133 133 </div>
134 134 <div class="buttons">
135 135 ${h.submit('save',_('Save'),class_="btn btn-primary")}
136 136 ${h.reset('reset',_('Reset'),class_="btn btn-danger")}
137 137 </div>
138 138 ${h.end_form()}
139 139 </div>
140 140 </div>
141 141 <script type="text/javascript">
142 142 $('#add_perm').on('click', function(e){
143 143 addNewPermInput($(this), 'group');
144 144 });
145 145 $('.revoke_perm').on('click', function(e){
146 146 markRevokePermInput($(this), 'group');
147 147 })
148 148 </script>
@@ -1,84 +1,84 b''
1 1 ## -*- coding: utf-8 -*-
2 2 <%namespace name="base" file="/base/base.mako"/>
3 3
4 4 <div class="panel panel-default">
5 5 <div class="panel-heading">
6 6 <h3 class="panel-title">${_('Settings for Repository Group: %s') % c.repo_group.name}</h3>
7 7 </div>
8 8 <div class="panel-body">
9 ${h.secure_form(url('update_repo_group',group_name=c.repo_group.group_name),method='put')}
9 ${h.secure_form(h.url('update_repo_group',group_name=c.repo_group.group_name),method='put')}
10 10 <div class="form">
11 11 <!-- fields -->
12 12 <div class="fields">
13 13 <div class="field">
14 14 <div class="label">
15 15 <label for="group_name">${_('Group Name')}:</label>
16 16 </div>
17 17 <div class="input">
18 18 ${h.text('group_name',class_='medium')}
19 19 </div>
20 20 </div>
21 21
22 22 <div class="field badged-field">
23 23 <div class="label">
24 24 <label for="user">${_('Owner')}:</label>
25 25 </div>
26 26 <div class="input">
27 27 <div class="badge-input-container">
28 28 <div class="user-badge">
29 29 ${base.gravatar_with_user(c.repo_group.user.email, show_disabled=not c.repo_group.user.active)}
30 30 </div>
31 31 <div class="badge-input-wrap">
32 32 ${h.text('user', class_="medium", autocomplete="off")}
33 33 </div>
34 34 </div>
35 35 <form:error name="user"/>
36 36 <p class="help-block">${_('Change owner of this repository group.')}</p>
37 37 </div>
38 38 </div>
39 39
40 40 <div class="field">
41 41 <div class="label label-textarea">
42 42 <label for="group_description">${_('Description')}:</label>
43 43 </div>
44 44 <div class="textarea text-area editor">
45 45 ${h.textarea('group_description',cols=23,rows=5,class_="medium")}
46 46 </div>
47 47 </div>
48 48
49 49 <div class="field">
50 50 <div class="label">
51 51 <label for="group_parent_id">${_('Group parent')}:</label>
52 52 </div>
53 53 <div class="select">
54 54 ${h.select('group_parent_id','',c.repo_groups,class_="medium")}
55 55 </div>
56 56 </div>
57 57 <div class="field">
58 58 <div class="label label-checkbox">
59 59 <label for="enable_locking">${_('Enable Repository Locking')}:</label>
60 60 </div>
61 61 <div class="checkboxes">
62 62 ${h.checkbox('enable_locking',value="True")}
63 63 <span class="help-block">${_('Repository locking will be enabled on all subgroups and repositories inside this repository group. Pulling from a repository locks it, and it is unlocked by pushing back by the same user.')}</span>
64 64 </div>
65 65 </div>
66 66 <div class="buttons">
67 67 ${h.submit('save',_('Save'),class_="btn")}
68 68 ${h.reset('reset',_('Reset'),class_="btn")}
69 69 </div>
70 70 </div>
71 71 </div>
72 72 ${h.end_form()}
73 73 </div>
74 74 </div>
75 75 <script>
76 76 $(document).ready(function(){
77 77 $("#group_parent_id").select2({
78 78 'containerCssClass': "drop-menu",
79 79 'dropdownCssClass': "drop-menu-dropdown",
80 80 'dropdownAutoWidth': true
81 81 });
82 82 UsersAutoComplete('user', '${c.rhodecode_user.user_id}');
83 83 })
84 84 </script>
@@ -1,159 +1,159 b''
1 1 ## -*- coding: utf-8 -*-
2 2
3 ${h.secure_form(url('repos'))}
3 ${h.secure_form(h.url('repos'))}
4 4 <div class="form">
5 5 <!-- fields -->
6 6 <div class="fields">
7 7 <div class="field">
8 8 <div class="label">
9 9 <label for="repo_name">${_('Name')}:</label>
10 10 </div>
11 11 <div class="input">
12 12 ${h.text('repo_name', class_="medium")}
13 13 <div class="info-block">
14 14 <a id="remote_clone_toggle" href="#"><i class="icon-download-alt"></i> ${_('Import Existing Repository ?')}</a>
15 15 </div>
16 16 %if not c.rhodecode_user.is_admin:
17 17 ${h.hidden('user_created',True)}
18 18 %endif
19 19 </div>
20 20 </div>
21 21 <div id="remote_clone" class="field" style="display: none;">
22 22 <div class="label">
23 23 <label for="clone_uri">${_('Clone from')}:</label>
24 24 </div>
25 25 <div class="input">
26 26 ${h.text('clone_uri', class_="medium")}
27 27 <span class="help-block">
28 28 <pre>
29 29 - The repository must be accessible over http:// or https://
30 30 - For Git projects it's recommended appending .git to the end of clone url.
31 31 - Make sure to select proper repository type from the below selector before importing it.
32 32 - If your HTTP[S] repository is not publicly accessible,
33 33 add authentication information to the URL: https://username:password@server.company.com/repo-name.
34 34 - The Git LFS/Mercurial Largefiles objects will not be imported.
35 35 - For very large repositories, it's recommended to manually copy them into the
36 36 RhodeCode <a href="${h.url('admin_settings_vcs', anchor='vcs-storage-options')}">storage location</a> and run <a href="${h.url('admin_settings_mapping')}">Remap and Rescan</a>.
37 37 </pre>
38 38 </span>
39 39 </div>
40 40 </div>
41 41 <div class="field">
42 42 <div class="label">
43 43 <label for="repo_description">${_('Description')}:</label>
44 44 </div>
45 45 <div class="textarea editor">
46 46 ${h.textarea('repo_description')}
47 47 <span class="help-block">${_('Keep it short and to the point. Use a README file for longer descriptions.')}</span>
48 48 </div>
49 49 </div>
50 50 <div class="field">
51 51 <div class="label">
52 52 <label for="repo_group">${_('Repository Group')}:</label>
53 53 </div>
54 54 <div class="select">
55 55 ${h.select('repo_group',request.GET.get('parent_group'),c.repo_groups,class_="medium")}
56 56 % if c.personal_repo_group:
57 57 <a class="btn" href="#" id="select_my_group" data-personal-group-id="${c.personal_repo_group.group_id}">
58 58 ${_('Select my personal group (%(repo_group_name)s)') % {'repo_group_name': c.personal_repo_group.group_name}}
59 59 </a>
60 60 % endif
61 61 <span class="help-block">${_('Optionally select a group to put this repository into.')}</span>
62 62 </div>
63 63 </div>
64 64 <div id="copy_perms" class="field">
65 65 <div class="label label-checkbox">
66 66 <label for="repo_copy_permissions">${_('Copy Parent Group Permissions')}:</label>
67 67 </div>
68 68 <div class="checkboxes">
69 69 ${h.checkbox('repo_copy_permissions', value="True", checked="checked")}
70 70 <span class="help-block">${_('Copy permission set from the parent repository group.')}</span>
71 71 </div>
72 72 </div>
73 73 <div class="field">
74 74 <div class="label">
75 75 <label for="repo_type">${_('Type')}:</label>
76 76 </div>
77 77 <div class="select">
78 78 ${h.select('repo_type','hg',c.backends)}
79 79 <span class="help-block">${_('Set the type of repository to create.')}</span>
80 80 </div>
81 81 </div>
82 82 <div class="field">
83 83 <div class="label">
84 84 <label for="repo_landing_rev">${_('Landing commit')}:</label>
85 85 </div>
86 86 <div class="select">
87 87 ${h.select('repo_landing_rev','',c.landing_revs,class_="medium")}
88 88 <span class="help-block">${_('The default commit for file pages, downloads, full text search index, and README generation.')}</span>
89 89 </div>
90 90 </div>
91 91 <div class="field">
92 92 <div class="label label-checkbox">
93 93 <label for="repo_private">${_('Private Repository')}:</label>
94 94 </div>
95 95 <div class="checkboxes">
96 96 ${h.checkbox('repo_private',value="True")}
97 97 <span class="help-block">${_('Private repositories are only visible to people explicitly added as collaborators.')}</span>
98 98 </div>
99 99 </div>
100 100 <div class="buttons">
101 101 ${h.submit('save',_('Save'),class_="btn")}
102 102 </div>
103 103 </div>
104 104 </div>
105 105 <script>
106 106 $(document).ready(function(){
107 107 var setCopyPermsOption = function(group_val){
108 108 if(group_val != "-1"){
109 109 $('#copy_perms').show()
110 110 }
111 111 else{
112 112 $('#copy_perms').hide();
113 113 }
114 114 };
115 115
116 116 $('#remote_clone_toggle').on('click', function(e){
117 117 $('#remote_clone').show();
118 118 e.preventDefault();
119 119 });
120 120
121 121 if($('#remote_clone input').hasClass('error')){
122 122 $('#remote_clone').show();
123 123 }
124 124 if($('#remote_clone input').val()){
125 125 $('#remote_clone').show();
126 126 }
127 127
128 128 $("#repo_group").select2({
129 129 'containerCssClass': "drop-menu",
130 130 'dropdownCssClass': "drop-menu-dropdown",
131 131 'dropdownAutoWidth': true,
132 132 'width': "resolve"
133 133 });
134 134
135 135 setCopyPermsOption($('#repo_group').val());
136 136 $("#repo_group").on("change", function(e) {
137 137 setCopyPermsOption(e.val)
138 138 });
139 139
140 140 $("#repo_type").select2({
141 141 'containerCssClass': "drop-menu",
142 142 'dropdownCssClass': "drop-menu-dropdown",
143 143 'minimumResultsForSearch': -1,
144 144 });
145 145 $("#repo_landing_rev").select2({
146 146 'containerCssClass': "drop-menu",
147 147 'dropdownCssClass': "drop-menu-dropdown",
148 148 'minimumResultsForSearch': -1,
149 149 });
150 150 $('#repo_name').focus();
151 151
152 152 $('#select_my_group').on('click', function(e){
153 153 e.preventDefault();
154 154 $("#repo_group").val($(this).data('personalGroupId')).trigger("change");
155 155 })
156 156
157 157 })
158 158 </script>
159 159 ${h.end_form()}
@@ -1,79 +1,79 b''
1 1 <div class="panel panel-default">
2 2 <div class="panel-heading">
3 3 <h3 class="panel-title">${_('Custom extra fields for this repository')}</h3>
4 4 </div>
5 5 <div class="panel-body">
6 6 %if c.visual.repository_fields:
7 7 %if c.repo_fields:
8 8 <div class="emails_wrap">
9 9 <table class="rctable edit_fields">
10 10 <th>${_('Label')}</th>
11 11 <th>${_('Key')}</th>
12 12 <th>${_('Type')}</th>
13 13 <th>${_('Action')}</th>
14 14
15 15 %for field in c.repo_fields:
16 16 <tr>
17 17 <td class="td-tags">${field.field_label}</td>
18 18 <td class="td-hash">${field.field_key}</td>
19 19 <td class="td-type">${field.field_type}</td>
20 20 <td class="td-action">
21 ${h.secure_form(url('delete_repo_fields', repo_name=c.repo_info.repo_name, field_id=field.repo_field_id),method='delete')}
21 ${h.secure_form(h.url('delete_repo_fields', repo_name=c.repo_info.repo_name, field_id=field.repo_field_id),method='delete')}
22 22 ${h.hidden('del_repo_field',field.repo_field_id)}
23 23 <button class="btn btn-link btn-danger" type="submit"
24 24 onclick="return confirm('${_('Confirm to delete this field: %s') % field.field_key}');">
25 25 ${_('Delete')}
26 26 </button>
27 27 ${h.end_form()}
28 28 </td>
29 29 </tr>
30 30 %endfor
31 31 </table>
32 32 </div>
33 33 %endif
34 ${h.secure_form(url('create_repo_fields', repo_name=c.repo_name),method='put')}
34 ${h.secure_form(h.url('create_repo_fields', repo_name=c.repo_name),method='put')}
35 35 <div class="form">
36 36 <!-- fields -->
37 37 <div class="fields">
38 38 <div class="field">
39 39 <div class="label">
40 40 <label for="new_field_key">${_('New Field Key')}:</label>
41 41 </div>
42 42 <div class="input">
43 43 ${h.text('new_field_key', class_='medium')}
44 44 </div>
45 45 </div>
46 46 <div class="field">
47 47 <div class="label">
48 48 <label for="new_field_label">${_('New Field Label')}:</label>
49 49 </div>
50 50 <div class="input">
51 51 ${h.text('new_field_label', class_='medium', placeholder=_('Enter short label'))}
52 52 </div>
53 53 </div>
54 54
55 55 <div class="field">
56 56 <div class="label">
57 57 <label for="new_field_desc">${_('New Field Description')}:</label>
58 58 </div>
59 59 <div class="input">
60 60 ${h.text('new_field_desc', class_='medium', placeholder=_('Enter a full description for the field'))}
61 61 </div>
62 62 </div>
63 63
64 64 <div class="buttons">
65 65 ${h.submit('save',_('Add'),class_="btn")}
66 66 ${h.reset('reset',_('Reset'),class_="btn")}
67 67 </div>
68 68 </div>
69 69 </div>
70 70 ${h.end_form()}
71 71 %else:
72 72 <h2>
73 73 ${_('Extra fields are disabled. You can enable them from the Admin/Settings/Visual page.')}
74 74 </h2>
75 75 %endif
76 76 </div>
77 77 </div>
78 78
79 79
@@ -1,109 +1,109 b''
1 1 <%namespace name="its" file="/base/issue_tracker_settings.mako"/>
2 2
3 3 <div id="repo_issue_tracker" class="${'inherited' if c.settings_model.inherit_global_settings else ''}">
4 ${h.secure_form(url('repo_issuetracker_save', repo_name=c.repo_name), method='post', id="inherit-form")}
4 ${h.secure_form(h.url('repo_issuetracker_save', repo_name=c.repo_name), method='post', id="inherit-form")}
5 5 <div class="panel panel-default panel-body">
6 6 <div class="fields">
7 7 <div class="field">
8 8 <div class="label label-checkbox">
9 9 <label for="inherit_default_permissions">${_('Inherit from global settings')}:</label>
10 10 </div>
11 11 <div class="checkboxes">
12 12 ${h.checkbox('inherit_global_issuetracker', value='inherited', checked=c.settings_model.inherit_global_settings)}
13 13 <span class="help-block">
14 14 ${h.literal(_('Select to inherit global patterns for issue tracker.'))}
15 15 </span>
16 16 </div>
17 17 </div>
18 18 </div>
19 19 </div>
20 20
21 21 <div id="inherit_overlay">
22 22 <div class="panel panel-default">
23 23 <div class="panel-heading">
24 24 <h3 class="panel-title">${_('Inherited Issue Tracker Patterns')}</h3>
25 25 </div>
26 26 <div class="panel-body">
27 27 <table class="rctable issuetracker readonly">
28 28 <tr>
29 29 <th>${_('Description')}</th>
30 30 <th>${_('Pattern')}</th>
31 31 <th>${_('Url')}</th>
32 32 <th>${_('Prefix')}</th>
33 33 <th ></th>
34 34 </tr>
35 35 %for uid, entry in c.global_patterns.items():
36 36 <tr id="${uid}">
37 37 <td class="td-description issuetracker_desc">
38 38 <span class="entry">
39 39 ${entry.desc}
40 40 </span>
41 41 </td>
42 42 <td class="td-regex issuetracker_pat">
43 43 <span class="entry">
44 44 ${entry.pat}
45 45 </span>
46 46 </td>
47 47 <td class="td-url issuetracker_url">
48 48 <span class="entry">
49 49 ${entry.url}
50 50 </span>
51 51 </td>
52 52 <td class="td-prefix issuetracker_pref">
53 53 <span class="entry">
54 54 ${entry.pref}
55 55 </span>
56 56 </td>
57 57 <td class="td-action">
58 58 </td>
59 59 </tr>
60 60 %endfor
61 61
62 62 </table>
63 63 </div>
64 64 </div>
65 65 </div>
66 66
67 67 <div id="custom_overlay">
68 68 <div class="panel panel-default">
69 69 <div class="panel-heading">
70 70 <h3 class="panel-title">${_('Issue Tracker / Wiki Patterns')}</h3>
71 71 </div>
72 72 <div class="panel-body">
73 73 ${its.issue_tracker_settings_table(
74 74 patterns=c.repo_patterns.items(),
75 form_url=url('repo_settings_issuetracker', repo_name=c.repo_info.repo_name),
76 delete_url=url('repo_issuetracker_delete', repo_name=c.repo_info.repo_name)
75 form_url=h.url('repo_settings_issuetracker', repo_name=c.repo_info.repo_name),
76 delete_url=h.url('repo_issuetracker_delete', repo_name=c.repo_info.repo_name)
77 77 )}
78 78 <div class="buttons">
79 79 <button type="submit" class="btn btn-primary save-inheritance" id="save">${_('Save')}</button>
80 80 <button type="reset" class="btn reset-inheritance">${_('Reset')}</button>
81 81 </div>
82 82 </div>
83 83 </div>
84 84 </div>
85 85
86 86
87 87 ${h.end_form()}
88 88
89 89 <div class="panel panel-default">
90 90 <div class="panel-heading">
91 91 <h3 class="panel-title">${_('Test Patterns')}</h3>
92 92 </div>
93 93 <div class="panel-body">
94 94 ${its.issue_tracker_new_row()}
95 ${its.issue_tracker_settings_test(test_url=url('repo_issuetracker_test', repo_name=c.repo_info.repo_name))}
95 ${its.issue_tracker_settings_test(test_url=h.url('repo_issuetracker_test', repo_name=c.repo_info.repo_name))}
96 96 </div>
97 97 </div>
98 98
99 99 </div>
100 100
101 101 <script>
102 102 $('#inherit_global_issuetracker').on('change', function(e){
103 103 $('#repo_issue_tracker').toggleClass('inherited',this.checked);
104 104 });
105 105
106 106 $('.reset-inheritance').on('click', function(e){
107 107 $('#inherit_global_issuetracker').prop('checked', false).change();
108 108 });
109 109 </script>
@@ -1,40 +1,40 b''
1 1 <div class="panel panel-default">
2 2 <div class="panel-heading">
3 3 <h3 class="panel-title">${_('Remote url')}</h3>
4 4 </div>
5 5 <div class="panel-body">
6 6
7 7 <h4>${_('Manually pull changes from external repository.')}</h4>
8 8
9 9 %if c.repo_info.clone_uri:
10 10
11 11 ${_('Remote mirror url')}:
12 12 <a href="${c.repo_info.clone_uri}">${c.repo_info.clone_uri_hidden}</a>
13 13
14 14 <p>
15 15 ${_('Pull can be automated by such api call. Can be called periodically in crontab etc.')}
16 16 <br/>
17 17 <code>
18 18 ${h.api_call_example(method='pull', args={"repoid": c.repo_info.repo_name})}
19 19 </code>
20 20 </p>
21 21
22 ${h.secure_form(url('edit_repo_remote', repo_name=c.repo_name), method='put')}
22 ${h.secure_form(h.url('edit_repo_remote', repo_name=c.repo_name), method='put')}
23 23 <div class="form">
24 24 <div class="fields">
25 25 ${h.submit('remote_pull_%s' % c.repo_info.repo_name,_('Pull changes from remote location'),class_="btn btn-small",onclick="return confirm('"+_('Confirm to pull changes from remote side')+"');")}
26 26 </div>
27 27 </div>
28 28 ${h.end_form()}
29 29 %else:
30 30
31 31 ${_('This repository does not have any remote mirror url set.')}
32 32 <a href="${h.route_path('edit_repo', repo_name=c.repo_info.repo_name)}">${_('Set remote url.')}</a>
33 33 <br/>
34 34 <br/>
35 35 <button class="btn disabled" type="submit" disabled="disabled">
36 36 ${_('Pull changes from remote location')}
37 37 </button>
38 38 %endif
39 39 </div>
40 40 </div>
@@ -1,22 +1,22 b''
1 1 <div class="panel panel-default">
2 2 <div class="panel-heading">
3 3 <h3 class="panel-title">${_('Repository statistics')}</h3>
4 4 </div>
5 5 <div class="panel-body">
6 ${h.secure_form(url('edit_repo_statistics', repo_name=c.repo_info.repo_name), method='put')}
6 ${h.secure_form(h.url('edit_repo_statistics', repo_name=c.repo_info.repo_name), method='put')}
7 7 <div class="form">
8 8 <div class="fields">
9 9 <div class="field" >
10 10 <dl class="dl-horizontal settings">
11 11 <dt>${_('Processed commits')}:</dt><dd>${c.stats_revision}/${c.repo_last_rev}</dd>
12 12 <dt>${_('Processed progress')}:</dt><dd>${c.stats_percentage}%</dd>
13 13 </dl>
14 14 </div>
15 15 ${h.submit('reset_stats_%s' % c.repo_info.repo_name,_('Reset statistics'),class_="btn btn-small",onclick="return confirm('"+_('Confirm to remove current statistics')+"');")}
16 16 </div>
17 17 </div>
18 18 ${h.end_form()}
19 19 </div>
20 20 </div>
21 21
22 22
@@ -1,74 +1,74 b''
1 1 <%namespace name="vcss" file="/base/vcs_settings.mako"/>
2 2
3 3 <div id="repo_vcs_settings" class="${'inherited' if c.inherit_global_settings else ''}">
4 ${h.secure_form(url('repo_vcs_settings', repo_name=c.repo_info.repo_name), method='post')}
4 ${h.secure_form(h.url('repo_vcs_settings', repo_name=c.repo_info.repo_name), method='post')}
5 5 <div class="form panel panel-default">
6 6 <div class="fields panel-body">
7 7 <div class="field">
8 8 <div class="label label-checkbox">
9 9 <label for="inherit_global_settings">${_('Inherit from global settings')}:</label>
10 10 </div>
11 11 <div class="checkboxes">
12 12 ${h.checkbox('inherit_global_settings',value=True)}
13 13 <span class="help-block">${h.literal(_('Select to inherit global vcs settings.'))}</span>
14 14 </div>
15 15 </div>
16 16 </div>
17 17 </div>
18 18
19 19 <div id="inherit_overlay_vcs_default">
20 20 <div>
21 21 ${vcss.vcs_settings_fields(
22 22 suffix='_inherited',
23 23 svn_tag_patterns=c.global_svn_tag_patterns,
24 24 svn_branch_patterns=c.global_svn_branch_patterns,
25 25 repo_type=c.repo_info.repo_type,
26 26 disabled='disabled'
27 27 )}
28 28 </div>
29 29 </div>
30 30
31 31 <div id="inherit_overlay_vcs_custom">
32 32 <div>
33 33 ${vcss.vcs_settings_fields(
34 34 suffix='',
35 35 svn_tag_patterns=c.svn_tag_patterns,
36 36 svn_branch_patterns=c.svn_branch_patterns,
37 37 repo_type=c.repo_info.repo_type
38 38 )}
39 39 </div>
40 40 </div>
41 41
42 42 <div class="buttons">
43 43 ${h.submit('save',_('Save settings'),class_="btn")}
44 44 ${h.reset('reset',_('Reset'),class_="btn")}
45 45 </div>
46 46
47 47 ${h.end_form()}
48 48 </div>
49 49
50 50 <script type="text/javascript">
51 51
52 52 function ajaxDeletePattern(pattern_id, field_id) {
53 53 var sUrl = "${h.url('repo_vcs_settings', repo_name=c.repo_info.repo_name)}";
54 54 var callback = function (o) {
55 55 var elem = $("#"+field_id);
56 56 elem.remove();
57 57 };
58 58 var postData = {
59 59 '_method': 'delete',
60 60 'delete_svn_pattern': pattern_id,
61 61 'csrf_token': CSRF_TOKEN
62 62 };
63 63 var request = $.post(sUrl, postData)
64 64 .done(callback)
65 65 .fail(function (data, textStatus, errorThrown) {
66 66 alert("Error while deleting hooks.\nError code {0} ({1}). URL: {2}".format(data.status,data.statusText,$(this)[0].url));
67 67 });
68 68 }
69 69
70 70 $('#inherit_global_settings').on('change', function(e){
71 71 $('#repo_vcs_settings').toggleClass('inherited', this.checked);
72 72 });
73 73
74 74 </script>
@@ -1,56 +1,56 b''
1 1 <div class="panel panel-default">
2 2 <div class="panel-heading">
3 3 <h3 class="panel-title">${_('Email Configuration')}</h3>
4 4 </div>
5 5 <div class="panel-body">
6 6 <%
7 7 elems = [
8 8 (_('Email prefix'), c.rhodecode_ini.get('email_prefix'), ''),
9 9 (_('RhodeCode email from'), c.rhodecode_ini.get('app_email_from'), ''),
10 10 (_('Error email from'), c.rhodecode_ini.get('error_email_from'), ''),
11 11 (_('Error email recipients'), c.rhodecode_ini.get('email_to'), ''),
12 12
13 13 (_('SMTP server'), c.rhodecode_ini.get('smtp_server'), ''),
14 14 (_('SMTP username'), c.rhodecode_ini.get('smtp_username'), ''),
15 15 (_('SMTP password'), '%s chars' % len(c.rhodecode_ini.get('smtp_password', '')), ''),
16 16 (_('SMTP port'), c.rhodecode_ini.get('smtp_port'), ''),
17 17
18 18 (_('SMTP use TLS'), c.rhodecode_ini.get('smtp_use_tls'), ''),
19 19 (_('SMTP use SSL'), c.rhodecode_ini.get('smtp_use_ssl'), ''),
20 20 (_('SMTP auth'), c.rhodecode_ini.get('smtp_auth'), ''),
21 21 ]
22 22 %>
23 23 <dl class="dl-horizontal settings">
24 24 %for dt, dd, tt in elems:
25 25 <dt >${dt}:</dt>
26 26 <dd title="${h.tooltip(tt)}">${dd}</dd>
27 27 %endfor
28 28 </dl>
29 29 </div>
30 30 </div>
31 31
32 32 <div class="panel panel-default">
33 33 <div class="panel-heading">
34 34 <h3 class="panel-title">${_('Test Email')}</h3>
35 35 </div>
36 36 <div class="panel-body">
37 ${h.secure_form(url('admin_settings_email'), method='post')}
37 ${h.secure_form(h.url('admin_settings_email'), method='post')}
38 38
39 39 <div class="field input">
40 40 ${h.text('test_email', size=60, placeholder=_('enter valid email'))}
41 41 </div>
42 42 <div class="field">
43 43 <span class="help-block">
44 44 ${_('Send an auto-generated email from this server to above email...')}
45 45 </span>
46 46 </div>
47 47 <div class="buttons">
48 48 ${h.submit('send',_('Send'),class_="btn")}
49 49 </div>
50 50 ${h.end_form()}
51 51 </div>
52 52 </div>
53 53
54 54
55 55
56 56
@@ -1,295 +1,295 b''
1 ${h.secure_form(url('admin_settings_global'), method='post')}
1 ${h.secure_form(h.url('admin_settings_global'), method='post')}
2 2
3 3 <div class="panel panel-default">
4 4 <div class="panel-heading" id="branding-options">
5 5 <h3 class="panel-title">${_('Branding')} <a class="permalink" href="#branding-options"> ¶</a></h3>
6 6 </div>
7 7 <div class="panel-body">
8 8 <div class="label">
9 9 <label for="rhodecode_title">${_('Title')}</label>
10 10 </div>
11 11 <div class="field input">
12 12 ${h.text('rhodecode_title',size=60)}
13 13 </div>
14 14 <div class="field">
15 15 <span class="help-block">
16 16 ${_('Set a custom title for your RhodeCode instance (limited to 40 characters).')}
17 17 </span>
18 18 </div>
19 19 <div class="label">
20 20 <label for="rhodecode_realm">${_('HTTP[S] authentication realm')}</label>
21 21 </div>
22 22 <div class="field input">
23 23 ${h.text('rhodecode_realm',size=60)}
24 24 </div>
25 25 <div class="field">
26 26 <span class="help-block">
27 27 ${_('Set a custom text that is shown as authentication message to clients trying to connect.')}
28 28 </span>
29 29 </div>
30 30 </div>
31 31 </div>
32 32
33 33
34 34 <div class="panel panel-default">
35 35 <div class="panel-heading" id="personal-group-options">
36 36 <h3 class="panel-title">${_('Personal Repository Group')} <a class="permalink" href="#personal-group-options"> ¶</a></h3>
37 37 </div>
38 38 <div class="panel-body">
39 39 <div class="checkbox">
40 40 ${h.checkbox('rhodecode_create_personal_repo_group','True')}
41 41 <label for="rhodecode_create_personal_repo_group">${_('Create Personal Repository Group')}</label>
42 42 </div>
43 43 <span class="help-block">
44 44 ${_('Always create Personal Repository Groups for new users.')} <br/>
45 45 ${_('When creating new users from add user form or API you can still turn this off via a checkbox or flag')}
46 46 </span>
47 47
48 48 <div class="label">
49 49 <label for="rhodecode_personal_repo_group_pattern">${_('Personal Repo Group Pattern')}</label>
50 50 </div>
51 51 <div class="field input">
52 52 ${h.text('rhodecode_personal_repo_group_pattern',size=60, placeholder=c.personal_repo_group_default_pattern)}
53 53 </div>
54 54 <span class="help-block">
55 55 ${_('Pattern used to create Personal Repository Groups. Prefix can be other existing repository group path[s], eg. /u/${username}')} <br/>
56 56 ${_('Available variables are currently ${username} and ${user_id}')}
57 57 </span>
58 58 </div>
59 59 </div>
60 60
61 61
62 62 <div class="panel panel-default">
63 63 <div class="panel-heading" id="captcha-options">
64 64 <h3 class="panel-title">${_('Registration Captcha')} <a class="permalink" href="#captcha-options"> ¶</a></h3>
65 65 </div>
66 66 <div class="panel-body">
67 67 <div class="label">
68 68 <label for="rhodecode_captcha_public_key">${_('Google ReCaptcha public key')}</label>
69 69 </div>
70 70 <div class="field input">
71 71 ${h.text('rhodecode_captcha_public_key',size=60)}
72 72 </div>
73 73 <div class="field">
74 74 <span class="help-block">
75 75 ${_('Public key for reCaptcha system.')}
76 76 </span>
77 77 </div>
78 78
79 79 <div class="label">
80 80 <label for="rhodecode_captcha_private_key">${_('Google ReCaptcha private key')}</label>
81 81 </div>
82 82 <div class="field input">
83 83 ${h.text('rhodecode_captcha_private_key',size=60)}
84 84 </div>
85 85 <div class="field">
86 86 <span class="help-block">
87 87 ${_('Private key for reCaptcha system. Setting this value will enable captcha on registration')}
88 88 </span>
89 89 </div>
90 90 </div>
91 91 </div>
92 92
93 93 <div class="panel panel-default">
94 94 <div class="panel-heading" id="header-code-options">
95 95 <h3 class="panel-title">${_('Custom Header Code')} <a class="permalink" href="#header-code-options"> ¶</a></h3>
96 96 </div>
97 97 <div class="panel-body">
98 98 <div class="select">
99 99 <select id="pre_template" >
100 100 <option value="#">${_('Templates...')}</option>
101 101 <option value="ga">Google Analytics</option>
102 102 <option value="clicky">Clicky</option>
103 103 <option value="server_announce">${_('Server Announcement')}</option>
104 104 <option value="flash_filtering">${_('Flash message filtering')}</option>
105 105 </select>
106 106 </div>
107 107 <div style="padding: 10px 0px"></div>
108 108 <div class="textarea text-area">
109 109 ${h.textarea('rhodecode_pre_code',cols=23,rows=5,class_="medium")}
110 110 <span class="help-block">${_('Custom js/css code added at the end of the <header/> tag.')}
111 111 ${_('Use <script/> or <css/> tags to define custom styling or scripting')}</span>
112 112 </div>
113 113 </div>
114 114 </div>
115 115
116 116 <div class="panel panel-default">
117 117 <div class="panel-heading" id="footer-code-options">
118 118 <h3 class="panel-title">${_('Custom Footer Code')} <a class="permalink" href="#footer-code-options"> ¶</a></h3>
119 119 </div>
120 120 <div class="panel-body">
121 121 <div class="select">
122 122 <select id="post_template" >
123 123 <option value="#">${_('Templates...')}</option>
124 124 <option value="ga">Google Analytics</option>
125 125 <option value="clicky">Clicky</option>
126 126 <option value="server_announce">${_('Server Announcement')}</option>
127 127 </select>
128 128 </div>
129 129 <div style="padding: 10px 0px"></div>
130 130 <div class="textarea text-area">
131 131 ${h.textarea('rhodecode_post_code',cols=23,rows=5, class_="medium")}
132 132 <span class="help-block">${_('Custom js/css code added at the end of the <body> tag.')}
133 133 ${_('Use <script> or <css> tags to define custom styling or scripting')}</span>
134 134 </div>
135 135 </div>
136 136 </div>
137 137
138 138 <div class="buttons">
139 139 ${h.submit('save',_('Save settings'),class_="btn")}
140 140 ${h.reset('reset',_('Reset'),class_="btn")}
141 141 </div>
142 142 ${h.end_form()}
143 143
144 144
145 145
146 146 ## TEMPLATES ##
147 147 ###############
148 148
149 149 <script id="ga_tmpl" type="text/x-template">
150 150 <%text filter="h">
151 151 <script>
152 152 // Google Analytics
153 153 // Put your Google Analytics code instead of _GACODE_
154 154 var _gaq_code = '_GACODE_';
155 155 var _gaq = _gaq || [];
156 156 _gaq.push(['_setAccount', _gaq_code]);
157 157 _gaq.push(['_trackPageview']);
158 158
159 159 (function() {
160 160 var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
161 161 ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
162 162 var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
163 163 })();
164 164
165 165 rhodecode_statechange_callback = function(url, data){
166 166 // ANALYTICS callback on html5 history state changed
167 167 // triggered by file browser, url is the new url,
168 168 // data is extra info passed from the State object
169 169 if (typeof window._gaq !== 'undefined') {
170 170 _gaq.push(['_trackPageview', url]);
171 171 }
172 172 };
173 173 </script>
174 174 </%text>
175 175 </script>
176 176
177 177
178 178
179 179 <script id="clicky_tmpl" type="text/x-template">
180 180 <%text filter="h">
181 181 <script src="//static.getclicky.com/js" type="text/javascript"></script>
182 182 <script type="text/javascript">
183 183 // Clicky Analytics - should be used in the footer code section.
184 184 // Put your Clicky code instead of _CLICKYCODE_ here,
185 185 // and below in the <img> tag.
186 186 var _cl_code = _CLICKYCODE_;
187 187 try{clicky.init(_cl_code);}catch(e){}
188 188
189 189 rhodecode_statechange_callback = function(url, data){
190 190 // ANALYTICS callback on html5 history state changed
191 191 // triggered by file browser, url is the new url,
192 192 // data is extra info passed from the State object
193 193 if (typeof window.clicky !== 'undefined') {
194 194 clicky.log(url);
195 195 }
196 196 }
197 197 </script>
198 198 <noscript>
199 199 // Put your clicky code in the src file.
200 200 <p><img alt="Clicky" width="1" height="1"
201 201 src="//in.getclicky.com/_CLICKYCODE_ns.gif" /></p>
202 202 </noscript>
203 203 </%text>
204 204 </script>
205 205
206 206
207 207
208 208 <script id="server_announce_tmpl" type='text/x-template'>
209 209 <%text filter="h">
210 210 <script>
211 211 // Server announcement displayed on the top of the page.
212 212 // This can be used to send a global maintenance messages or other
213 213 // important messages to all users of the RhodeCode Enterprise system.
214 214
215 215 $(document).ready(function(e){
216 216
217 217 // EDIT - put your message below
218 218 var message = "TYPE YOUR MESSAGE HERE";
219 219
220 220 // EDIT - choose "info"/"warning"/"error"/"success"/"neutral" as appropriate
221 221 var alert_level = "info";
222 222
223 223 $("#body").prepend(
224 224 ("<div id='server-announcement' class='"+alert_level+"'>_MSG_"+"</div>").replace("_MSG_", message)
225 225 )
226 226 })
227 227 </script>
228 228 </%text>
229 229 </script>
230 230
231 231 <script id="flash_filtering_tmpl" type='text/x-template'>
232 232 <%text filter="h">
233 233 <script>
234 234 // This filters out some flash messages before they are presented to user
235 235 // based on their contents. Could be used to filter out warnings/errors
236 236 // of license messages
237 237
238 238 var filteredMessages = [];
239 239 for(var i =0; i< alertMessagePayloads.length; i++){
240 240 if (typeof alertMessagePayloads[i].message.subdata.subtype !== 'undefined' &&
241 241 alertMessagePayloads[i].message.subdata.subtype.indexOf('rc_license') !== -1){
242 242 continue
243 243 }
244 244 filteredMessages.push(alertMessagePayloads[i]);
245 245 }
246 246 alertMessagePayloads = filteredMessages;
247 247 </script>
248 248 </%text>
249 249 </script>
250 250
251 251 <script>
252 252 var pre_cm = initCodeMirror('rhodecode_pre_code', '', false);
253 253 var pre_old = pre_cm.getValue();
254 254
255 255 var post_cm = initCodeMirror('rhodecode_post_code', '', false);
256 256 var post_old = post_cm.getValue();
257 257
258 258 var get_data = function(type, old){
259 259 var get_tmpl = function(tmpl_name){
260 260 // unescape some stuff
261 261 return htmlEnDeCode.htmlDecode($('#'+tmpl_name+'_tmpl').html());
262 262 };
263 263 return {
264 264 '#': old,
265 265 'ga': get_tmpl('ga'),
266 266 'clicky': get_tmpl('clicky'),
267 267 'server_announce': get_tmpl('server_announce'),
268 268 'flash_filtering': get_tmpl('flash_filtering')
269 269 }[type]
270 270 };
271 271
272 272 $('#pre_template').select2({
273 273 containerCssClass: 'drop-menu',
274 274 dropdownCssClass: 'drop-menu-dropdown',
275 275 dropdownAutoWidth: true,
276 276 minimumResultsForSearch: -1
277 277 });
278 278
279 279 $('#post_template').select2({
280 280 containerCssClass: 'drop-menu',
281 281 dropdownCssClass: 'drop-menu-dropdown',
282 282 dropdownAutoWidth: true,
283 283 minimumResultsForSearch: -1
284 284 });
285 285
286 286 $('#post_template').on('change', function(e){
287 287 var sel = this.value;
288 288 post_cm.setValue(get_data(sel, post_old))
289 289 });
290 290
291 291 $('#pre_template').on('change', function(e){
292 292 var sel = this.value;
293 293 pre_cm.setValue(get_data(sel, pre_old))
294 294 })
295 295 </script>
@@ -1,93 +1,93 b''
1 1 <div class="panel panel-default">
2 2 <div class="panel-heading">
3 3 <h3 class="panel-title">${_('Built in Mercurial hooks - read only')}</h3>
4 4 </div>
5 5 <div class="panel-body">
6 6 <div class="form">
7 7 <div class="fields">
8 8 % for hook in c.hooks:
9 9 <div class="field">
10 10 <div class="label label">
11 11 <label for="${hook.ui_key}">${hook.ui_key}</label>
12 12 </div>
13 13 <div class="input" >
14 14 ${h.text(hook.ui_key,hook.ui_value,size=59,readonly="readonly")}
15 15 </div>
16 16 </div>
17 17 % endfor
18 18 </div>
19 19 <span class="help-block">${_('Hooks can be used to trigger actions on certain events such as push / pull. They can trigger Python functions or external applications.')}</span>
20 20 </div>
21 21 </div>
22 22 </div>
23 23
24 24
25 25 <div class="panel panel-default">
26 26 <div class="panel-heading">
27 27 <h3 class="panel-title">${_('Custom hooks')}</h3>
28 28 </div>
29 29 <div class="panel-body">
30 30 % if c.visual.allow_custom_hooks_settings:
31 ${h.secure_form(url('admin_settings_hooks'), method='post')}
31 ${h.secure_form(h.url('admin_settings_hooks'), method='post')}
32 32 <div class="form">
33 33 <div class="fields">
34 34
35 35 % for hook in c.custom_hooks:
36 36 <div class="field" id="${'id%s' % hook.ui_id }">
37 37 <div class="label label">
38 38 <label for="${hook.ui_key}">${hook.ui_key}</label>
39 39 </div>
40 40 <div class="input" >
41 41 ${h.hidden('hook_ui_key',hook.ui_key)}
42 42 ${h.hidden('hook_ui_value',hook.ui_value)}
43 43 ${h.text('hook_ui_value_new',hook.ui_value,size=59)}
44 44 <span class="btn btn-danger"
45 45 onclick="ajaxActionHook(${hook.ui_id},'${'id%s' % hook.ui_id }')">
46 46 ${_('Delete')}
47 47 </span>
48 48 </div>
49 49 </div>
50 50 % endfor
51 51
52 52 <div class="field customhooks">
53 53 <div class="label">
54 54 <div class="input-wrapper">
55 55 ${h.text('new_hook_ui_key',size=30)}
56 56 </div>
57 57 </div>
58 58 <div class="input">
59 59 ${h.text('new_hook_ui_value',size=59)}
60 60 </div>
61 61 </div>
62 62 <div class="buttons">
63 63 ${h.submit('save',_('Save'),class_="btn")}
64 64 </div>
65 65 </div>
66 66 </div>
67 67 ${h.end_form()}
68 68 %else:
69 69 DISABLED
70 70 % endif
71 71 </div>
72 72 </div>
73 73
74 74
75 75 <script type="text/javascript">
76 76 function ajaxActionHook(hook_id,field_id) {
77 77 var sUrl = "${h.url('admin_settings_hooks')}";
78 78 var callback = function (o) {
79 79 var elem = $("#"+field_id);
80 80 elem.remove();
81 81 };
82 82 var postData = {
83 83 '_method': 'delete',
84 84 'hook_id': hook_id,
85 85 'csrf_token': CSRF_TOKEN
86 86 };
87 87 var request = $.post(sUrl, postData)
88 88 .done(callback)
89 89 .fail(function (data, textStatus, errorThrown) {
90 90 alert("Error while deleting hooks.\nError code {0} ({1}). URL: {2}".format(data.status,data.statusText,$(this)[0].url));
91 91 });
92 92 };
93 93 </script>
@@ -1,34 +1,34 b''
1 1 <%namespace name="its" file="/base/issue_tracker_settings.mako"/>
2 2
3 3 <div class="panel panel-default">
4 4 <div class="panel-heading">
5 5 <h3 class="panel-title">${_('Issue Tracker / Wiki Patterns')}</h3>
6 6 </div>
7 7 <div class="panel-body">
8 ${h.secure_form(url('admin_settings_issuetracker_save'), method='post')}
8 ${h.secure_form(h.url('admin_settings_issuetracker_save'), method='post')}
9 9 ${its.issue_tracker_settings_table(
10 10 patterns=c.issuetracker_entries.items(),
11 form_url=url('admin_settings_issuetracker'),
12 delete_url=url('admin_issuetracker_delete')
11 form_url=h.url('admin_settings_issuetracker'),
12 delete_url=h.url('admin_issuetracker_delete')
13 13 )}
14 14 <div class="buttons">
15 15 <button type="submit" class="btn btn-primary" id="save">${_('Save')}</button>
16 16 <button type="reset" class="btn">${_('Reset')}</button>
17 17 </div>
18 18 ${h.end_form()}
19 19 </div>
20 20 </div>
21 21
22 22 <div class="panel panel-default">
23 23 <div class="panel-heading">
24 24 <h3 class="panel-title">${_('Test Patterns')}</h3>
25 25 </div>
26 26 <div class="panel-body">
27 27 ${its.issue_tracker_new_row()}
28 ${its.issue_tracker_settings_test(test_url=url('admin_issuetracker_test'))}
28 ${its.issue_tracker_settings_test(test_url=h.url('admin_issuetracker_test'))}
29 29 </div>
30 30 </div>
31 31
32 32
33 33
34 34
@@ -1,58 +1,58 b''
1 1 <div class="panel panel-default">
2 2 <div class="panel-heading">
3 3 <h3 class="panel-title">${_('Labs Settings')}</h3>
4 4 </div>
5 5 <div class="panel-body">
6 ${h.secure_form(url('admin_settings_labs'), method='post')}
6 ${h.secure_form(h.url('admin_settings_labs'), method='post')}
7 7 <div class="form">
8 8 <div class="fields">
9 9 % if not c.lab_settings:
10 10 ${_('There are no Labs settings currently')}
11 11 % else:
12 12 % for lab_setting in c.lab_settings:
13 13 <div class="field">
14 14 <div class="label">
15 15 <label>${lab_setting.group}:</label>
16 16 </div>
17 17 % if lab_setting.type == 'bool':
18 18 <div class="checkboxes">
19 19 <div class="checkbox">
20 20 ${h.checkbox(lab_setting.key, 'True')}
21 21 % if lab_setting.label:
22 22 <label for="${lab_setting.key}">${lab_setting.label}</label>
23 23 % endif
24 24 </div>
25 25 % if lab_setting.help:
26 26 <p class="help-block">${lab_setting.help}</p>
27 27 % endif
28 28 </div>
29 29 % else:
30 30 <div class="input">
31 31 ${h.text(lab_setting.key, size=60)}
32 32
33 33 ## TODO: johbo: This style does not yet exist for our forms,
34 34 ## the lab settings seem not to adhere to the structure which
35 35 ## we use in other places.
36 36 % if lab_setting.label:
37 37 <label for="${lab_setting.key}">${lab_setting.label}</label>
38 38 % endif
39 39
40 40 % if lab_setting.help:
41 41 <p class="help-block">${lab_setting.help}</p>
42 42 % endif
43 43 </div>
44 44 % endif
45 45 </div>
46 46 % endfor
47 47 <div class="buttons">
48 48 ${h.submit('save', _('Save settings'), class_='btn')}
49 49 ${h.reset('reset', _('Reset'), class_='btn')}
50 50 </div>
51 51 % endif
52 52 </div>
53 53 </div>
54 54 ${h.end_form()}
55 55 </div>
56 56 </div>
57 57
58 58
@@ -1,28 +1,28 b''
1 ${h.secure_form(url('admin_settings_mapping'), method='post')}
1 ${h.secure_form(h.url('admin_settings_mapping'), method='post')}
2 2
3 3 <div class="panel panel-default">
4 4 <div class="panel-heading">
5 5 <h3 class="panel-title">${_('Import New Groups or Repositories')}</h3>
6 6 </div>
7 7 <div class="panel-body">
8 8 <div class="checkbox">
9 9 ${h.checkbox('destroy',True)}
10 10 <label for="destroy">${_('Destroy old data')}</label>
11 11 </div>
12 12 <span class="help-block">${_('In case a repository or a group was deleted from the filesystem and it still exists in the database, check this option to remove obsolete data from the database.')}</span>
13 13
14 14 <div class="checkbox">
15 15 ${h.checkbox('invalidate',True)}
16 16 <label for="invalidate"> ${_('Invalidate cache for all repositories')}</label>
17 17 </div>
18 18 <span class="help-block">${_('Each cache data for repositories will be cleaned with this option selected. Use this to reload data and clear cache keys.')}</span>
19 19
20 20 <div class="buttons">
21 21 ${h.submit('rescan',_('Rescan Filesystem'),class_="btn")}
22 22 </div>
23 23
24 24 </div>
25 25 </div>
26 26
27 27
28 28 ${h.end_form()}
@@ -1,66 +1,66 b''
1 1 <%namespace name="vcss" file="/base/vcs_settings.mako"/>
2 2
3 ${h.secure_form(url('admin_settings_vcs'), method='post')}
3 ${h.secure_form(h.url('admin_settings_vcs'), method='post')}
4 4 <div>
5 5 ${vcss.vcs_settings_fields(
6 6 suffix='',
7 7 svn_tag_patterns=c.svn_tag_patterns,
8 8 svn_branch_patterns=c.svn_branch_patterns,
9 9 display_globals=True,
10 10 allow_repo_location_change=c.visual.allow_repo_location_change
11 11 )}
12 12 <div class="buttons">
13 13 ${h.submit('save',_('Save settings'),class_="btn")}
14 14 ${h.reset('reset',_('Reset'),class_="btn")}
15 15 </div>
16 16 </div>
17 17 ${h.end_form()}
18 18
19 19 <script type="text/javascript">
20 20
21 21 function ajaxDeletePattern(pattern_id, field_id) {
22 22 var sUrl = "${h.url('admin_settings_vcs')}";
23 23 var callback = function (o) {
24 24 var elem = $("#"+field_id);
25 25 elem.remove();
26 26 };
27 27 var postData = {
28 28 '_method': 'delete',
29 29 'delete_svn_pattern': pattern_id,
30 30 'csrf_token': CSRF_TOKEN
31 31 };
32 32 var request = $.post(sUrl, postData)
33 33 .done(callback)
34 34 .fail(function (data, textStatus, errorThrown) {
35 35 alert("Error while deleting hooks.\nError code {0} ({1}). URL: {2}".format(data.status,data.statusText,$(this)[0].url));
36 36 });
37 37 };
38 38
39 39 $(document).ready(function() {
40 40
41 41 var unlockpath = function() {
42 42 $('#path_unlock_icon').removeClass('icon-lock').addClass('icon-unlock');
43 43 $('#paths_root_path').removeAttr('readonly').removeClass('disabled');
44 44 };
45 45
46 46 $('#path_unlock').on('click', function(e) {
47 47 unlockpath();
48 48 });
49 49
50 50 if ($('.locked_input').children().hasClass('error-message')) {
51 51 unlockpath();
52 52 }
53 53
54 54 /* On click handler for the `Generate Apache Config` button. It sends a
55 55 POST request to trigger the (re)generation of the mod_dav_svn config. */
56 56 $('#vcs_svn_generate_cfg').on('click', function(event) {
57 57 event.preventDefault();
58 58 var url = "${h.route_path('admin_settings_vcs_svn_generate_cfg')}";
59 59 var jqxhr = $.post(url, {'csrf_token': CSRF_TOKEN});
60 60 jqxhr.done(function(data) {
61 61 $.Topic('/notifications').publish(data);
62 62 });
63 63 });
64 64
65 65 });
66 66 </script>
@@ -1,237 +1,237 b''
1 ${h.secure_form(url('admin_settings_visual'), method='post')}
1 ${h.secure_form(h.url('admin_settings_visual'), method='post')}
2 2
3 3 <div class="panel panel-default">
4 4 <div class="panel-heading" id="general">
5 5 <h3 class="panel-title">${_('General')}</h3>
6 6 </div>
7 7 <div class="panel-body">
8 8 <div class="checkbox">
9 9 ${h.checkbox('rhodecode_repository_fields','True')}
10 10 <label for="rhodecode_repository_fields">${_('Use repository extra fields')}</label>
11 11 </div>
12 12 <span class="help-block">${_('Allows storing additional customized fields per repository.')}</span>
13 13
14 14 <div></div>
15 15 <div class="checkbox">
16 16 ${h.checkbox('rhodecode_show_version','True')}
17 17 <label for="rhodecode_show_version">${_('Show RhodeCode version')}</label>
18 18 </div>
19 19 <span class="help-block">${_('Shows or hides a version number of RhodeCode displayed in the footer.')}</span>
20 20 </div>
21 21 </div>
22 22
23 23
24 24 <div class="panel panel-default">
25 25 <div class="panel-heading" id="gravatars">
26 26 <h3 class="panel-title">${_('Gravatars')}</h3>
27 27 </div>
28 28 <div class="panel-body">
29 29 <div class="checkbox">
30 30 ${h.checkbox('rhodecode_use_gravatar','True')}
31 31 <label for="rhodecode_use_gravatar">${_('Use Gravatars based avatars')}</label>
32 32 </div>
33 33 <span class="help-block">${_('Use gravatar.com as avatar system for RhodeCode accounts. If this is disabled avatars are generated based on initials and email.')}</span>
34 34
35 35 <div class="label">
36 36 <label for="rhodecode_gravatar_url">${_('Gravatar URL')}</label>
37 37 </div>
38 38 <div class="input">
39 39 <div class="field">
40 40 ${h.text('rhodecode_gravatar_url', size='100%')}
41 41 </div>
42 42
43 43 <div class="field">
44 44 <span class="help-block">${_('''Gravatar url allows you to use other avatar server application.
45 45 Following variables of the URL will be replaced accordingly.
46 46 {scheme} 'http' or 'https' sent from running RhodeCode server,
47 47 {email} user email,
48 48 {md5email} md5 hash of the user email (like at gravatar.com),
49 49 {size} size of the image that is expected from the server application,
50 50 {netloc} network location/server host of running RhodeCode server''')}</span>
51 51 </div>
52 52 </div>
53 53 </div>
54 54 </div>
55 55
56 56
57 57 <div class="panel panel-default">
58 58 <div class="panel-heading" id="meta-tagging">
59 59 <h3 class="panel-title">${_('Meta-Tagging')}</h3>
60 60 </div>
61 61 <div class="panel-body">
62 62 <div class="checkbox">
63 63 ${h.checkbox('rhodecode_stylify_metatags','True')}
64 64 <label for="rhodecode_stylify_metatags">${_('Stylify recognised meta tags')}</label>
65 65 </div>
66 66 <span class="help-block">${_('Parses meta tags from repository description field and turns them into colored tags.')}</span>
67 67 <div>
68 68 <table>
69 69 <tr><td>[featured] </td><td><span class="metatag" tag="featured">featured</span></td></tr>
70 70 <tr><td>[stale] </td><td><span class="metatag" tag="stale">stale</span></td></tr>
71 71 <tr><td>[dead] </td><td><span class="metatag" tag="dead">dead</span></td></tr>
72 72 <tr><td>[personal] </td><td><span class="metatag" tag="personal">personal</span></td></tr>
73 73
74 74 <tr><td>[lang =&gt; lang] </td><td><span class="metatag" tag="lang" >lang</span></td></tr>
75 75
76 76 <tr><td>[license =&gt; License] </td><td><span class="metatag" tag="license"><a href="http://www.opensource.org/licenses/License" >License</a></span></td></tr>
77 77 <tr><td>[requires =&gt; Repo] </td><td><span class="metatag" tag="requires" >requires =&gt; <a href="#" >Repo</a></span></td></tr>
78 78 <tr><td>[recommends =&gt; Repo] </td><td><span class="metatag" tag="recommends" >recommends =&gt; <a href="#" >Repo</a></span></td></tr>
79 79 <tr><td>[see =&gt; URI] </td><td><span class="metatag" tag="see">see =&gt; <a href="#">URI</a> </span></td></tr>
80 80 </table>
81 81 </div>
82 82 </div>
83 83 </div>
84 84
85 85
86 86 <div class="panel panel-default">
87 87 <div class="panel-heading">
88 88 <h3 class="panel-title">${_('Dashboard Items')}</h3>
89 89 </div>
90 90 <div class="panel-body">
91 91 <div class="label">
92 92 <label for="rhodecode_dashboard_items">${_('Main page dashboard items')}</label>
93 93 </div>
94 94 <div class="field input">
95 95 ${h.text('rhodecode_dashboard_items',size=5)}
96 96 </div>
97 97 <div class="field">
98 98 <span class="help-block">${_('Number of items displayed in the main page dashboard before pagination is shown.')}</span>
99 99 </div>
100 100
101 101 <div class="label">
102 102 <label for="rhodecode_admin_grid_items">${_('Admin pages items')}</label>
103 103 </div>
104 104 <div class="field input">
105 105 ${h.text('rhodecode_admin_grid_items',size=5)}
106 106 </div>
107 107 <div class="field">
108 108 <span class="help-block">${_('Number of items displayed in the admin pages grids before pagination is shown.')}</span>
109 109 </div>
110 110 </div>
111 111 </div>
112 112
113 113
114 114
115 115 <div class="panel panel-default">
116 116 <div class="panel-heading" id="commit-id">
117 117 <h3 class="panel-title">${_('Commit ID Style')}</h3>
118 118 </div>
119 119 <div class="panel-body">
120 120 <div class="label">
121 121 <label for="rhodecode_show_sha_length">${_('Commit sha length')}</label>
122 122 </div>
123 123 <div class="input">
124 124 <div class="field">
125 125 ${h.text('rhodecode_show_sha_length',size=5)}
126 126 </div>
127 127 <div class="field">
128 128 <span class="help-block">${_('''Number of chars to show in commit sha displayed in web interface.
129 129 By default it's shown as r123:9043a6a4c226 this value defines the
130 130 length of the sha after the `r123:` part.''')}</span>
131 131 </div>
132 132 </div>
133 133
134 134 <div class="checkbox">
135 135 ${h.checkbox('rhodecode_show_revision_number','True')}
136 136 <label for="rhodecode_show_revision_number">${_('Show commit ID numeric reference')} / ${_('Commit show revision number')}</label>
137 137 </div>
138 138 <span class="help-block">${_('''Show revision number in commit sha displayed in web interface.
139 139 By default it's shown as r123:9043a6a4c226 this value defines the
140 140 if the `r123:` part is shown.''')}</span>
141 141 </div>
142 142 </div>
143 143
144 144
145 145 <div class="panel panel-default">
146 146 <div class="panel-heading" id="icons">
147 147 <h3 class="panel-title">${_('Icons')}</h3>
148 148 </div>
149 149 <div class="panel-body">
150 150 <div class="checkbox">
151 151 ${h.checkbox('rhodecode_show_public_icon','True')}
152 152 <label for="rhodecode_show_public_icon">${_('Show public repo icon on repositories')}</label>
153 153 </div>
154 154 <div></div>
155 155
156 156 <div class="checkbox">
157 157 ${h.checkbox('rhodecode_show_private_icon','True')}
158 158 <label for="rhodecode_show_private_icon">${_('Show private repo icon on repositories')}</label>
159 159 </div>
160 160 <span class="help-block">${_('Show public/private icons next to repositories names.')}</span>
161 161 </div>
162 162 </div>
163 163
164 164
165 165 <div class="panel panel-default">
166 166 <div class="panel-heading">
167 167 <h3 class="panel-title">${_('Markup Renderer')}</h3>
168 168 </div>
169 169 <div class="panel-body">
170 170 <div class="field select">
171 171 ${h.select('rhodecode_markup_renderer', '', ['rst', 'markdown'])}
172 172 </div>
173 173 <div class="field">
174 174 <span class="help-block">${_('Default renderer used to render comments, pull request descriptions and other description elements. After change old entries will still work correctly.')}</span>
175 175 </div>
176 176 </div>
177 177 </div>
178 178
179 179 <div class="panel panel-default">
180 180 <div class="panel-heading">
181 181 <h3 class="panel-title">${_('Clone URL')}</h3>
182 182 </div>
183 183 <div class="panel-body">
184 184 <div class="field">
185 185 ${h.text('rhodecode_clone_uri_tmpl', size=60)}
186 186 </div>
187 187
188 188 <div class="field">
189 189 <span class="help-block">
190 190 ${_('''Schema of clone url construction eg. '{scheme}://{user}@{netloc}/{repo}', available vars:
191 191 {scheme} 'http' or 'https' sent from running RhodeCode server,
192 192 {user} current user username,
193 193 {netloc} network location/server host of running RhodeCode server,
194 194 {repo} full repository name,
195 195 {repoid} ID of repository, can be used to contruct clone-by-id''')}
196 196 </span>
197 197 </div>
198 198 </div>
199 199 </div>
200 200
201 201 <div class="panel panel-default">
202 202 <div class="panel-heading">
203 203 <h3 class="panel-title">${_('Custom Support Link')}</h3>
204 204 </div>
205 205 <div class="panel-body">
206 206 <div class="field">
207 207 ${h.text('rhodecode_support_url', size=60)}
208 208 </div>
209 209 <div class="field">
210 210 <span class="help-block">
211 211 ${_('''Custom url for the support link located at the bottom.
212 212 The default is set to %(default_url)s. In case there's a need
213 213 to change the support link to internal issue tracker, it should be done here.
214 214 ''') % {'default_url': h.url('rhodecode_support')}}
215 215 </span>
216 216 </div>
217 217 </div>
218 218 </div>
219 219
220 220 <div class="buttons">
221 221 ${h.submit('save',_('Save settings'),class_="btn")}
222 222 ${h.reset('reset',_('Reset'),class_="btn")}
223 223 </div>
224 224
225 225
226 226 ${h.end_form()}
227 227
228 228 <script>
229 229 $(document).ready(function() {
230 230 $('#rhodecode_markup_renderer').select2({
231 231 containerCssClass: 'drop-menu',
232 232 dropdownCssClass: 'drop-menu-dropdown',
233 233 dropdownAutoWidth: true,
234 234 minimumResultsForSearch: -1
235 235 });
236 236 });
237 237 </script>
@@ -1,72 +1,72 b''
1 1 ## -*- coding: utf-8 -*-
2 2 <%inherit file="/base/base.mako"/>
3 3
4 4 <%def name="title()">
5 5 ${_('Add user group')}
6 6 %if c.rhodecode_name:
7 7 &middot; ${h.branding(c.rhodecode_name)}
8 8 %endif
9 9 </%def>
10 10 <%def name="breadcrumbs_links()">
11 11 ${h.link_to(_('Admin'),h.route_path('admin_home'))}
12 12 &raquo;
13 13 ${h.link_to(_('User groups'),h.url('users_groups'))}
14 14 &raquo;
15 15 ${_('Add User Group')}
16 16 </%def>
17 17
18 18 <%def name="menu_bar_nav()">
19 19 ${self.menu_items(active='admin')}
20 20 </%def>
21 21
22 22 <%def name="main()">
23 23 <div class="box main-content">
24 24 <!-- box / title -->
25 25 <div class="title">
26 26 ${self.breadcrumbs()}
27 27 </div>
28 28 <!-- end box / title -->
29 ${h.secure_form(url('users_groups'))}
29 ${h.secure_form(h.url('users_groups'))}
30 30 <div class="form">
31 31 <!-- fields -->
32 32 <div class="fields">
33 33 <div class="field">
34 34 <div class="label">
35 35 <label for="users_group_name">${_('Group name')}:</label>
36 36 </div>
37 37 <div class="input">
38 38 ${h.text('users_group_name', class_='medium')}
39 39 </div>
40 40 </div>
41 41 <div class="field">
42 42 <div class="label">
43 43 <label for="user_group_description">${_('Description')}:</label>
44 44 </div>
45 45 <div class="textarea editor">
46 46 ${h.textarea('user_group_description')}
47 47 <span class="help-block">${_('Short, optional description for this user group.')}</span>
48 48 </div>
49 49 </div>
50 50 <div class="field">
51 51 <div class="label">
52 52 <label for="users_group_active">${_('Active')}:</label>
53 53 </div>
54 54 <div class="checkboxes">
55 55 ${h.checkbox('users_group_active',value=True, checked='checked')}
56 56 </div>
57 57 </div>
58 58
59 59 <div class="buttons">
60 60 ${h.submit('save',_('Save'),class_="btn")}
61 61 </div>
62 62 </div>
63 63 </div>
64 64 ${h.end_form()}
65 65 </div>
66 66 </%def>
67 67
68 68 <script>
69 69 $(document).ready(function(){
70 70 $('#users_group_name').focus();
71 71 })
72 72 </script>
@@ -1,3 +1,3 b''
1 1 <%namespace name="dpb" file="/base/default_perms_box.mako"/>
2 ${dpb.default_perms_box(url('edit_user_group_global_perms', user_group_id=c.user_group.users_group_id))}
2 ${dpb.default_perms_box(h.url('edit_user_group_global_perms', user_group_id=c.user_group.users_group_id))}
3 3
@@ -1,134 +1,134 b''
1 1 <%namespace name="base" file="/base/base.mako"/>
2 2
3 3 <div class="panel panel-default">
4 4 <div class="panel-heading">
5 5 <h3 class="panel-title">${_('User Group Permissions')}</h3>
6 6 </div>
7 7 <div class="panel-body">
8 ${h.secure_form(url('edit_user_group_perms', user_group_id=c.user_group.users_group_id),method='put')}
8 ${h.secure_form(h.url('edit_user_group_perms', user_group_id=c.user_group.users_group_id),method='put')}
9 9 <table id="permissions_manage" class="rctable permissions">
10 10 <tr>
11 11 <th class="td-radio">${_('None')}</th>
12 12 <th class="td-radio">${_('Read')}</th>
13 13 <th class="td-radio">${_('Write')}</th>
14 14 <th class="td-radio">${_('Admin')}</th>
15 15 <th>${_('User/User Group')}</th>
16 16 <th></th>
17 17 </tr>
18 18 ## USERS
19 19 %for _user in c.user_group.permissions():
20 20 %if getattr(_user, 'admin_row', None) or getattr(_user, 'owner_row', None):
21 21 <tr class="perm_admin_row">
22 22 <td class="td-radio">${h.radio('admin_perm_%s' % _user.user_id,'repository.none', disabled="disabled")}</td>
23 23 <td class="td-radio">${h.radio('admin_perm_%s' % _user.user_id,'repository.read', disabled="disabled")}</td>
24 24 <td class="td-radio">${h.radio('admin_perm_%s' % _user.user_id,'repository.write', disabled="disabled")}</td>
25 25 <td class="td-radio">${h.radio('admin_perm_%s' % _user.user_id,'repository.admin', 'repository.admin', disabled="disabled")}</td>
26 26 <td class="td-user">
27 27 ${base.gravatar(_user.email, 16)}
28 28 <span class="user">
29 29 ${h.link_to_user(_user.username)}
30 30 %if getattr(_user, 'admin_row', None):
31 31 (${_('super admin')})
32 32 %endif
33 33 %if getattr(_user, 'owner_row', None):
34 34 (${_('owner')})
35 35 %endif
36 36 </span>
37 37 </td>
38 38 <td></td>
39 39 </tr>
40 40 %else:
41 41 ##forbid revoking permission from yourself, except if you're an super admin
42 42 <tr>
43 43 %if c.rhodecode_user.user_id != _user.user_id or c.rhodecode_user.is_admin:
44 44 <td class="td-radio">${h.radio('u_perm_%s' % _user.user_id,'usergroup.none')}</td>
45 45 <td class="td-radio">${h.radio('u_perm_%s' % _user.user_id,'usergroup.read')}</td>
46 46 <td class="td-radio">${h.radio('u_perm_%s' % _user.user_id,'usergroup.write')}</td>
47 47 <td class="td-radio">${h.radio('u_perm_%s' % _user.user_id,'usergroup.admin')}</td>
48 48 <td class="td-user">
49 49 ${base.gravatar(_user.email, 16)}
50 50 <span class="user">
51 51 % if _user.username == h.DEFAULT_USER:
52 52 ${h.DEFAULT_USER} <span class="user-perm-help-text"> - ${_('permission for all other users')}</span>
53 53 % else:
54 54 ${h.link_to_user(_user.username)}
55 55 % endif
56 56 </span>
57 57 </td>
58 58 <td class="td-action">
59 59 %if _user.username != h.DEFAULT_USER:
60 60 <span class="btn btn-link btn-danger revoke_perm"
61 61 member="${_user.user_id}" member_type="user">
62 62 <i class="icon-remove"></i> ${_('revoke')}
63 63 </span>
64 64 %endif
65 65 </td>
66 66 %else:
67 67 ## special case for current user permissions, we make sure he cannot take his own permissions
68 68 <td class="td-radio">${h.radio('u_perm_%s' % _user.user_id,'usergroup.none', disabled="disabled")}</td>
69 69 <td class="td-radio">${h.radio('u_perm_%s' % _user.user_id,'usergroup.read', disabled="disabled")}</td>
70 70 <td class="td-radio">${h.radio('u_perm_%s' % _user.user_id,'usergroup.write', disabled="disabled")}</td>
71 71 <td class="td-radio">${h.radio('u_perm_%s' % _user.user_id,'usergroup.admin', disabled="disabled")}</td>
72 72 <td class="td-user">
73 73 ${base.gravatar(_user.email, 16)}
74 74 <span class="user">
75 75 % if _user.username == h.DEFAULT_USER:
76 76 ${h.DEFAULT_USER} <span class="user-perm-help-text"> - ${_('permission for all other users')}</span>
77 77 % else:
78 78 ${h.link_to_user(_user.username)}
79 79 % endif
80 80 <span class="user-perm-help-text">(${_('delegated admin')})</span>
81 81 </span>
82 82 </td>
83 83 <td></td>
84 84 %endif
85 85 </tr>
86 86 %endif
87 87 %endfor
88 88
89 89 ## USER GROUPS
90 90 %for _user_group in c.user_group.permission_user_groups():
91 91 <tr>
92 92 <td class="td-radio">${h.radio('g_perm_%s' % _user_group.users_group_id,'usergroup.none')}</td>
93 93 <td class="td-radio">${h.radio('g_perm_%s' % _user_group.users_group_id,'usergroup.read')}</td>
94 94 <td class="td-radio">${h.radio('g_perm_%s' % _user_group.users_group_id,'usergroup.write')}</td>
95 95 <td class="td-radio">${h.radio('g_perm_%s' % _user_group.users_group_id,'usergroup.admin')}</td>
96 96 <td class="td-user">
97 97 <i class="icon-group" ></i>
98 98 %if h.HasPermissionAny('hg.admin')():
99 99 <a href="${h.url('edit_users_group',user_group_id=_user_group.users_group_id)}">
100 100 ${_user_group.users_group_name}
101 101 </a>
102 102 %else:
103 103 ${_user_group.users_group_name}
104 104 %endif
105 105 </td>
106 106 <td class="td-action">
107 107 <span class="btn btn-link btn-danger revoke_perm"
108 108 member="${_user_group.users_group_id}" member_type="user_group">
109 109 <i class="icon-remove"></i> ${_('revoke')}
110 110 </span>
111 111 </td>
112 112 </tr>
113 113 %endfor
114 114 <tr class="new_members" id="add_perm_input"></tr>
115 115 </table>
116 116 <div id="add_perm" class="link">
117 117 ${_('Add new')}
118 118 </div>
119 119 <div class="buttons">
120 120 ${h.submit('save',_('Save'),class_="btn btn-primary")}
121 121 ${h.reset('reset',_('Reset'),class_="btn btn-danger")}
122 122 </div>
123 123 ${h.end_form()}
124 124 </div>
125 125 </div>
126 126
127 127 <script type="text/javascript">
128 128 $('#add_perm').on('click', function(e){
129 129 addNewPermInput($(this), 'usergroup');
130 130 });
131 131 $('.revoke_perm').on('click', function(e){
132 132 markRevokePermInput($(this), 'usergroup');
133 133 });
134 134 </script>
@@ -1,186 +1,186 b''
1 1 ## -*- coding: utf-8 -*-
2 2 <%namespace name="base" file="/base/base.mako"/>
3 3
4 4 <div class="panel panel-default">
5 5 <div class="panel-heading">
6 6 <h3 class="panel-title">${_('User Group: %s') % c.user_group.users_group_name}</h3>
7 7 </div>
8 8 <div class="panel-body">
9 ${h.secure_form(url('update_users_group', user_group_id=c.user_group.users_group_id),method='put', id='edit_users_group')}
9 ${h.secure_form(h.url('update_users_group', user_group_id=c.user_group.users_group_id),method='put', id='edit_users_group')}
10 10 <div class="form">
11 11 <!-- fields -->
12 12 <div class="fields">
13 13 <div class="field">
14 14 <div class="label">
15 15 <label for="users_group_name">${_('Group name')}:</label>
16 16 </div>
17 17 <div class="input">
18 18 ${h.text('users_group_name',class_='medium')}
19 19 </div>
20 20 </div>
21 21
22 22 <div class="field badged-field">
23 23 <div class="label">
24 24 <label for="user">${_('Owner')}:</label>
25 25 </div>
26 26 <div class="input">
27 27 <div class="badge-input-container">
28 28 <div class="user-badge">
29 29 ${base.gravatar_with_user(c.user_group.user.email, show_disabled=not c.user_group.user.active)}
30 30 </div>
31 31 <div class="badge-input-wrap">
32 32 ${h.text('user', class_="medium", autocomplete="off")}
33 33 </div>
34 34 </div>
35 35 <form:error name="user"/>
36 36 <p class="help-block">${_('Change owner of this user group.')}</p>
37 37 </div>
38 38 </div>
39 39
40 40 <div class="field">
41 41 <div class="label label-textarea">
42 42 <label for="user_group_description">${_('Description')}:</label>
43 43 </div>
44 44 <div class="textarea textarea-small editor">
45 45 ${h.textarea('user_group_description',cols=23,rows=5,class_="medium")}
46 46 <span class="help-block">${_('Short, optional description for this user group.')}</span>
47 47 </div>
48 48 </div>
49 49 <div class="field">
50 50 <div class="label label-checkbox">
51 51 <label for="users_group_active">${_('Active')}:</label>
52 52 </div>
53 53 <div class="checkboxes">
54 54 ${h.checkbox('users_group_active',value=True)}
55 55 </div>
56 56 </div>
57 57
58 58 <div class="field">
59 59 <div class="label label-checkbox">
60 60 <label for="users_group_active">${_('Add members')}:</label>
61 61 </div>
62 62 <div class="input">
63 63 ${h.text('user_group_add_members', placeholder="user/usergroup", class_="medium")}
64 64 </div>
65 65 </div>
66 66
67 67 <input type="hidden" name="__start__" value="user_group_members:sequence"/>
68 68 <table id="group_members_placeholder" class="rctable group_members">
69 69 <tr>
70 70 <th>${_('Username')}</th>
71 71 <th>${_('Action')}</th>
72 72 </tr>
73 73
74 74 % if c.group_members_obj:
75 75 % for user in c.group_members_obj:
76 76 <tr>
77 77 <td id="member_user_${user.user_id}" class="td-author">
78 78 <div class="group_member">
79 79 ${base.gravatar(user.email, 16)}
80 80 <span class="username user">${h.link_to(h.person(user), h.url( 'edit_user',user_id=user.user_id))}</span>
81 81 <input type="hidden" name="__start__" value="member:mapping">
82 82 <input type="hidden" name="member_user_id" value="${user.user_id}">
83 83 <input type="hidden" name="type" value="existing" id="member_${user.user_id}">
84 84 <input type="hidden" name="__end__" value="member:mapping">
85 85 </div>
86 86 </td>
87 87 <td class="">
88 88 <div class="usergroup_member_remove action_button" onclick="removeUserGroupMember(${user.user_id}, true)" style="visibility: visible;">
89 89 <i class="icon-remove-sign"></i>
90 90 </div>
91 91 </td>
92 92 </tr>
93 93 % endfor
94 94
95 95 % else:
96 96 <tr><td colspan="2">${_('No members yet')}</td></tr>
97 97 % endif
98 98 </table>
99 99 <input type="hidden" name="__end__" value="user_group_members:sequence"/>
100 100
101 101 <div class="buttons">
102 102 ${h.submit('Save',_('Save'),class_="btn")}
103 103 </div>
104 104 </div>
105 105 </div>
106 106 ${h.end_form()}
107 107 </div>
108 108 </div>
109 109 <script>
110 110 $(document).ready(function(){
111 111 $("#group_parent_id").select2({
112 112 'containerCssClass': "drop-menu",
113 113 'dropdownCssClass': "drop-menu-dropdown",
114 114 'dropdownAutoWidth': true
115 115 });
116 116
117 117 removeUserGroupMember = function(userId){
118 118 $('#member_'+userId).val('remove');
119 119 $('#member_user_'+userId).addClass('to-delete');
120 120 };
121 121
122 122 $('#user_group_add_members').autocomplete({
123 123 serviceUrl: pyroutes.url('user_autocomplete_data'),
124 124 minChars:2,
125 125 maxHeight:400,
126 126 width:300,
127 127 deferRequestBy: 300, //miliseconds
128 128 showNoSuggestionNotice: true,
129 129 params: { user_groups:true },
130 130 formatResult: autocompleteFormatResult,
131 131 lookupFilter: autocompleteFilterResult,
132 132 onSelect: function(element, suggestion){
133 133
134 134 function addMember(user, fromUserGroup) {
135 135 var gravatar = user.icon_link;
136 136 var username = user.value_display;
137 137 var userLink = pyroutes.url('edit_user', {"user_id": user.id});
138 138 var uid = user.id;
139 139
140 140 if (fromUserGroup) {
141 141 username = username +" "+ _gettext('(from usergroup {0})'.format(fromUserGroup))
142 142 }
143 143
144 144 var elem = $(
145 145 ('<tr>'+
146 146 '<td id="member_user_{6}" class="td-author td-author-new-entry">'+
147 147 '<div class="group_member">'+
148 148 '<img class="gravatar" src="{0}" height="16" width="16">'+
149 149 '<span class="username user"><a href="{1}">{2}</a></span>'+
150 150 '<input type="hidden" name="__start__" value="member:mapping">'+
151 151 '<input type="hidden" name="member_user_id" value="{3}">'+
152 152 '<input type="hidden" name="type" value="new" id="member_{4}">'+
153 153 '<input type="hidden" name="__end__" value="member:mapping">'+
154 154 '</div>'+
155 155 '</td>'+
156 156 '<td class="td-author-new-entry">'+
157 157 '<div class="usergroup_member_remove action_button" onclick="removeUserGroupMember({5}, true)" style="visibility: visible;">'+
158 158 '<i class="icon-remove-sign"></i>'+
159 159 '</div>'+
160 160 '</td>'+
161 161 '</tr>').format(gravatar, userLink, username,
162 162 uid, uid, uid, uid)
163 163 );
164 164 $('#group_members_placeholder').append(elem)
165 165 }
166 166
167 167 if (suggestion.value_type == 'user_group') {
168 168 $.getJSON(
169 169 pyroutes.url('edit_user_group_members',
170 170 {'user_group_id': suggestion.id}),
171 171 function(data) {
172 172 $.each(data.members, function(idx, user) {
173 173 addMember(user, suggestion.value)
174 174 });
175 175 }
176 176 );
177 177 } else if (suggestion.value_type == 'user') {
178 178 addMember(suggestion, null);
179 179 }
180 180 }
181 181 });
182 182
183 183
184 184 UsersAutoComplete('user', '${c.rhodecode_user.user_id}');
185 185 })
186 186 </script>
@@ -1,147 +1,147 b''
1 1 ## -*- coding: utf-8 -*-
2 2 <%inherit file="/base/base.mako"/>
3 3
4 4 <%def name="title()">
5 5 ${_('Add user')}
6 6 %if c.rhodecode_name:
7 7 &middot; ${h.branding(c.rhodecode_name)}
8 8 %endif
9 9 </%def>
10 10 <%def name="breadcrumbs_links()">
11 11 ${h.link_to(_('Admin'),h.route_path('admin_home'))}
12 12 &raquo;
13 13 ${h.link_to(_('Users'),h.route_path('users'))}
14 14 &raquo;
15 15 ${_('Add User')}
16 16 </%def>
17 17
18 18 <%def name="menu_bar_nav()">
19 19 ${self.menu_items(active='admin')}
20 20 </%def>
21 21
22 22 <%def name="main()">
23 23 <div class="box">
24 24 <!-- box / title -->
25 25 <div class="title">
26 26 ${self.breadcrumbs()}
27 27 </div>
28 28 <!-- end box / title -->
29 ${h.secure_form(url('users'))}
29 ${h.secure_form(h.url('users'))}
30 30 <div class="form">
31 31 <!-- fields -->
32 32 <div class="fields">
33 33 <div class="field">
34 34 <div class="label">
35 35 <label for="username">${_('Username')}:</label>
36 36 </div>
37 37 <div class="input">
38 38 ${h.text('username', class_='medium')}
39 39 </div>
40 40 </div>
41 41
42 42 <div class="field">
43 43 <div class="label">
44 44 <label for="password">${_('Password')}:</label>
45 45 </div>
46 46 <div class="input">
47 47 ${h.password('password', class_='medium')}
48 48 </div>
49 49 </div>
50 50
51 51 <div class="field">
52 52 <div class="label">
53 53 <label for="password_confirmation">${_('Password confirmation')}:</label>
54 54 </div>
55 55 <div class="input">
56 56 ${h.password('password_confirmation',autocomplete="off", class_='medium')}
57 57 <div class="info-block">
58 58 <a id="generate_password" href="#">
59 59 <i class="icon-lock"></i> ${_('Generate password')}
60 60 </a>
61 61 <span id="generate_password_preview"></span>
62 62 </div>
63 63 </div>
64 64 </div>
65 65
66 66 <div class="field">
67 67 <div class="label">
68 68 <label for="firstname">${_('First Name')}:</label>
69 69 </div>
70 70 <div class="input">
71 71 ${h.text('firstname', class_='medium')}
72 72 </div>
73 73 </div>
74 74
75 75 <div class="field">
76 76 <div class="label">
77 77 <label for="lastname">${_('Last Name')}:</label>
78 78 </div>
79 79 <div class="input">
80 80 ${h.text('lastname', class_='medium')}
81 81 </div>
82 82 </div>
83 83
84 84 <div class="field">
85 85 <div class="label">
86 86 <label for="email">${_('Email')}:</label>
87 87 </div>
88 88 <div class="input">
89 89 ${h.text('email', class_='medium')}
90 90 ${h.hidden('extern_name', c.default_extern_type)}
91 91 ${h.hidden('extern_type', c.default_extern_type)}
92 92 </div>
93 93 </div>
94 94
95 95 <div class="field">
96 96 <div class="label label-checkbox">
97 97 <label for="active">${_('Active')}:</label>
98 98 </div>
99 99 <div class="checkboxes">
100 100 ${h.checkbox('active',value=True,checked='checked')}
101 101 </div>
102 102 </div>
103 103
104 104 <div class="field">
105 105 <div class="label label-checkbox">
106 106 <label for="password_change">${_('Password change')}:</label>
107 107 </div>
108 108 <div class="checkboxes">
109 109 ${h.checkbox('password_change',value=True)}
110 110 <span class="help-block">${_('Force user to change his password on the next login')}</span>
111 111 </div>
112 112 </div>
113 113
114 114 <div class="field">
115 115 <div class="label label-checkbox">
116 116 <label for="create_repo_group">${_('Add personal repository group')}:</label>
117 117 </div>
118 118 <div class="checkboxes">
119 119 ${h.checkbox('create_repo_group',value=True, checked=c.default_create_repo_group)}
120 120 <span class="help-block">
121 121 ${_('New group will be created at: `/%(path)s`') % {'path': c.personal_repo_group_name}}<br/>
122 122 ${_('User will be automatically set as this group owner.')}
123 123 </span>
124 124 </div>
125 125 </div>
126 126
127 127 <div class="buttons">
128 128 ${h.submit('save',_('Save'),class_="btn")}
129 129 </div>
130 130 </div>
131 131 </div>
132 132 ${h.end_form()}
133 133 </div>
134 134 <script>
135 135 $(document).ready(function(){
136 136 $('#username').focus();
137 137
138 138 $('#generate_password').on('click', function(e){
139 139 var tmpl = "(${_('generated password:')} {0})";
140 140 var new_passwd = generatePassword(12);
141 141 $('#generate_password_preview').html(tmpl.format(new_passwd));
142 142 $('#password').val(new_passwd);
143 143 $('#password_confirmation').val(new_passwd);
144 144 })
145 145 })
146 146 </script>
147 147 </%def>
@@ -1,2 +1,2 b''
1 1 <%namespace name="dpb" file="/base/default_perms_box.mako"/>
2 ${dpb.default_perms_box(url('edit_user_global_perms', user_id=c.user.user_id))}
2 ${dpb.default_perms_box(h.url('edit_user_global_perms', user_id=c.user.user_id))}
@@ -1,150 +1,150 b''
1 1 <%namespace name="base" file="/base/base.mako"/>
2 2
3 3 <div class="panel panel-default user-profile">
4 4 <div class="panel-heading">
5 5 <h3 class="panel-title">${_('User Profile')}</h3>
6 6 </div>
7 7 <div class="panel-body">
8 8 <div class="user-profile-content">
9 ${h.secure_form(url('update_user', user_id=c.user.user_id),method='put', class_='form')}
9 ${h.secure_form(h.url('update_user', user_id=c.user.user_id),method='put', class_='form')}
10 10 <% readonly = None %>
11 11 <% disabled = "" %>
12 12 %if c.extern_type != 'rhodecode':
13 13 <% readonly = "readonly" %>
14 14 <% disabled = " disabled" %>
15 15 <div class="infoform">
16 16 <div class="fields">
17 17 <p>${_('This user was created from external source (%s). Editing some of the settings is limited.' % c.extern_type)}</p>
18 18 </div>
19 19 </div>
20 20 %endif
21 21 <div class="form">
22 22 <div class="fields">
23 23 <div class="field">
24 24 <div class="label photo">
25 25 ${_('Photo')}:
26 26 </div>
27 27 <div class="input profile">
28 28 %if c.visual.use_gravatar:
29 29 ${base.gravatar(c.user.email, 100)}
30 30 <p class="help-block">${_('Change the avatar at')} <a href="http://gravatar.com">gravatar.com</a>.</p>
31 31 %else:
32 32 ${base.gravatar(c.user.email, 20)}
33 33 ${_('Avatars are disabled')}
34 34 %endif
35 35 </div>
36 36 </div>
37 37 <div class="field">
38 38 <div class="label">
39 39 ${_('Username')}:
40 40 </div>
41 41 <div class="input">
42 42 ${h.text('username', class_='%s medium' % disabled, readonly=readonly)}
43 43 </div>
44 44 </div>
45 45 <div class="field">
46 46 <div class="label">
47 47 <label for="name">${_('First Name')}:</label>
48 48 </div>
49 49 <div class="input">
50 50 ${h.text('firstname', class_="medium")}
51 51 </div>
52 52 </div>
53 53
54 54 <div class="field">
55 55 <div class="label">
56 56 <label for="lastname">${_('Last Name')}:</label>
57 57 </div>
58 58 <div class="input">
59 59 ${h.text('lastname', class_="medium")}
60 60 </div>
61 61 </div>
62 62
63 63 <div class="field">
64 64 <div class="label">
65 65 <label for="email">${_('Email')}:</label>
66 66 </div>
67 67 <div class="input">
68 68 ## we should be able to edit email !
69 69 ${h.text('email', class_="medium")}
70 70 </div>
71 71 </div>
72 72 <div class="field">
73 73 <div class="label">
74 74 ${_('New Password')}:
75 75 </div>
76 76 <div class="input">
77 77 ${h.password('new_password',class_='%s medium' % disabled,autocomplete="off",readonly=readonly)}
78 78 </div>
79 79 </div>
80 80 <div class="field">
81 81 <div class="label">
82 82 ${_('New Password Confirmation')}:
83 83 </div>
84 84 <div class="input">
85 85 ${h.password('password_confirmation',class_="%s medium" % disabled,autocomplete="off",readonly=readonly)}
86 86 </div>
87 87 </div>
88 88 <div class="field">
89 89 <div class="label-text">
90 90 ${_('Active')}:
91 91 </div>
92 92 <div class="input user-checkbox">
93 93 ${h.checkbox('active',value=True)}
94 94 </div>
95 95 </div>
96 96 <div class="field">
97 97 <div class="label-text">
98 98 ${_('Super Admin')}:
99 99 </div>
100 100 <div class="input user-checkbox">
101 101 ${h.checkbox('admin',value=True)}
102 102 </div>
103 103 </div>
104 104 <div class="field">
105 105 <div class="label-text">
106 106 ${_('Source of Record')}:
107 107 </div>
108 108 <div class="input">
109 109 <p>${c.extern_type}</p>
110 110 ${h.hidden('extern_type', readonly="readonly")}
111 111 </div>
112 112 </div>
113 113 <div class="field">
114 114 <div class="label-text">
115 115 ${_('Name in Source of Record')}:
116 116 </div>
117 117 <div class="input">
118 118 <p>${c.extern_name}</p>
119 119 ${h.hidden('extern_name', readonly="readonly")}
120 120 </div>
121 121 </div>
122 122 <div class="field">
123 123 <div class="label">
124 124 ${_('Language')}:
125 125 </div>
126 126 <div class="input">
127 127 ## allowed_languages is defined in the users.py
128 128 ## c.language comes from base.py as a default language
129 129 ${h.select('language', c.language, c.allowed_languages)}
130 130 <p class="help-block">${h.literal(_('Help translate %(rc_link)s into your language.') % {'rc_link': h.link_to('RhodeCode Enterprise', h.route_url('rhodecode_translations'))})}</p>
131 131 </div>
132 132 </div>
133 133 <div class="buttons">
134 134 ${h.submit('save', _('Save'), class_="btn")}
135 135 ${h.reset('reset', _('Reset'), class_="btn")}
136 136 </div>
137 137 </div>
138 138 </div>
139 139 ${h.end_form()}
140 140 </div>
141 141 </div>
142 142 </div>
143 143
144 144 <script>
145 145 $('#language').select2({
146 146 'containerCssClass': "drop-menu",
147 147 'dropdownCssClass': "drop-menu-dropdown",
148 148 'dropdownAutoWidth': true
149 149 });
150 150 </script>
@@ -1,156 +1,156 b''
1 1 ## snippet for displaying default permission box
2 2 ## usage:
3 3 ## <%namespace name="dpb" file="/base/default_perms_box.mako"/>
4 4 ## ${dpb.default_perms_box(<url_to_form>)}
5 5 ## ${dpb.default_perms_radios()}
6 6
7 7 <%def name="default_perms_radios(global_permissions_template = False, suffix='', **kwargs)">
8 8 <div class="main-content-full-width">
9 9 <div class="panel panel-default">
10 10
11 11 ## displayed according to checkbox selection
12 12 <div class="panel-heading">
13 13 %if not global_permissions_template:
14 14 <h3 class="inherit_overlay_default panel-title">${_('Inherited Permissions')}</h3>
15 15 <h3 class="inherit_overlay panel-title">${_('Custom Permissions')}</h3>
16 16 %else:
17 17 <h3 class="panel-title">${_('Default Global Permissions')}</h3>
18 18 %endif
19 19 </div>
20 20
21 21 <div class="panel-body">
22 22 %if global_permissions_template:
23 23 <p>${_('The following options configure the default permissions each user or group will inherit. You can override these permissions for each individual user or user group using individual permissions settings.')}</p>
24 24 %endif
25 25 <div class="field">
26 26 <div class="label">
27 27 <label for="default_repo_create${suffix}">${_('Repository Creation')}:</label>
28 28 </div>
29 29 <div class="radios">
30 30 ${h.radio('default_repo_create' + suffix, c.repo_create_choices[1][0], label=c.repo_create_choices[1][1], **kwargs)}
31 31 ${h.radio('default_repo_create' + suffix, c.repo_create_choices[0][0], label=c.repo_create_choices[0][1], **kwargs)}
32 32 <span class="help-block">${_('Permission to create root level repositories. When disabled, users can still create repositories inside their own repository groups.')}</span>
33 33 </div>
34 34 </div>
35 35 <div class="field">
36 36 <div class="label">
37 37 <label for="default_repo_create_on_write${suffix}">${_('Repository Creation With Group Write Access')}:</label>
38 38 </div>
39 39 <div class="radios">
40 40 ${h.radio('default_repo_create_on_write' + suffix, c.repo_create_on_write_choices[1][0], label=c.repo_create_on_write_choices[1][1], **kwargs)}
41 41 ${h.radio('default_repo_create_on_write' + suffix, c.repo_create_on_write_choices[0][0], label=c.repo_create_on_write_choices[0][1], **kwargs)}
42 42 <span class="help-block">${_('Write permission given on a repository group will allow creating repositories inside that group.')}</span>
43 43 </div>
44 44 </div>
45 45 <div class="field">
46 46 <div class="label">
47 47 <label for="default_fork_create${suffix}">${_('Repository Forking')}:</label>
48 48 </div>
49 49 <div class="radios">
50 50 ${h.radio('default_fork_create' + suffix, c.fork_choices[1][0], label=c.fork_choices[1][1], **kwargs)}
51 51 ${h.radio('default_fork_create' + suffix, c.fork_choices[0][0], label=c.fork_choices[0][1], **kwargs)}
52 52 <span class="help-block">${_('Permission to create root level repository forks. When disabled, users can still fork repositories inside their own repository groups.')}</span>
53 53 </div>
54 54 </div>
55 55 <div class="field">
56 56 <div class="label">
57 57 <label for="default_repo_group_create${suffix}">${_('Repository Group Creation')}:</label>
58 58 </div>
59 59 <div class="radios">
60 60 ${h.radio('default_repo_group_create' + suffix, c.repo_group_create_choices[1][0], label=c.repo_group_create_choices[1][1], **kwargs)}
61 61 ${h.radio('default_repo_group_create' + suffix, c.repo_group_create_choices[0][0], label=c.repo_group_create_choices[0][1], **kwargs)}
62 62 <span class="help-block">${_('Permission to create root level repository groups. When disabled, repository group admins can still create repository subgroups within their repository groups.')}</span>
63 63 </div>
64 64 </div>
65 65 <div class="field">
66 66 <div class="label">
67 67 <label for="default_user_group_create${suffix}">${_('User Group Creation')}:</label>
68 68 </div>
69 69 <div class="radios">
70 70 ${h.radio('default_user_group_create' + suffix, c.user_group_create_choices[1][0], label=c.user_group_create_choices[1][1], **kwargs)}
71 71 ${h.radio('default_user_group_create' + suffix, c.user_group_create_choices[0][0], label=c.user_group_create_choices[0][1], **kwargs)}
72 72 <span class="help-block">${_('Permission to allow user group creation.')}</span>
73 73 </div>
74 74 </div>
75 75
76 76 <div class="field">
77 77 <div class="label">
78 78 <label for="default_inherit_default_permissions${suffix}">${_('Inherit Permissions From The Default User')}:</label>
79 79 </div>
80 80 <div class="radios">
81 81 ${h.radio('default_inherit_default_permissions' + suffix, c.inherit_default_permission_choices[1][0], label=c.inherit_default_permission_choices[1][1], **kwargs)}
82 82 ${h.radio('default_inherit_default_permissions' + suffix, c.inherit_default_permission_choices[0][0], label=c.inherit_default_permission_choices[0][1], **kwargs)}
83 83 <span class="help-block">${_('Inherit default permissions from the default user. Turn off this option to force explicit permissions for users, even if they are more restrictive than the default user permissions.')}</span>
84 84 </div>
85 85 </div>
86 86
87 87 <div class="buttons">
88 88 ${h.submit('save',_('Save'),class_="btn")}
89 89 ${h.reset('reset',_('Reset'),class_="btn")}
90 90 </div>
91 91 </div>
92 92 </div>
93 93 </div>
94 94 </%def>
95 95
96 96 <%def name="default_perms_box(form_url)">
97 97 ${h.secure_form(form_url, method='put')}
98 98 <div class="form">
99 99 <div class="fields">
100 100 <div class="field panel panel-default panel-body">
101 101 <div class="label label-checkbox">
102 102 <label for="inherit_default_permissions">${_('Inherit from default settings')}:</label>
103 103 </div>
104 104 <div class="checkboxes">
105 105 ${h.checkbox('inherit_default_permissions',value=True)}
106 106 <span class="help-block">
107 107 ${h.literal(_('Select to inherit permissions from %s permissions settings, '
108 108 'including default IP address whitelist and inheritance of \npermission by members of user groups.')
109 % h.link_to('default user', url('admin_permissions_global')))}
109 % h.link_to('default user', h.url('admin_permissions_global')))}
110 110 </span>
111 111 </div>
112 112 </div>
113 113
114 114 ## INHERITED permissions == the user permissions in admin
115 115 ## if inherit checkbox is set this is displayed in non-edit mode
116 116 <div class="inherit_overlay_default">
117 117 ${default_perms_radios(global_permissions_template = False, suffix='_inherited', disabled="disabled")}
118 118 </div>
119 119
120 120 ## CUSTOM permissions
121 121 <div class="inherit_overlay">
122 122 ${default_perms_radios(global_permissions_template = False)}
123 123 </div>
124 124 </div>
125 125 </div>
126 126 ${h.end_form()}
127 127
128 128
129 129 ## JS
130 130 <script>
131 131 var show_custom_perms = function(inherit_default){
132 132 if(inherit_default) {
133 133 $('.inherit_overlay_default').show();
134 134 $('.inherit_overlay').hide();
135 135 }
136 136 else {
137 137 $('.inherit_overlay').show();
138 138 $('.inherit_overlay_default').hide();
139 139 }
140 140 };
141 141 $(document).ready(function(e){
142 142 var inherit_checkbox = $('#inherit_default_permissions');
143 143 var defaults = inherit_checkbox.prop('checked');
144 144 show_custom_perms(defaults);
145 145 inherit_checkbox.on('change', function(){
146 146 if($(this).prop('checked')){
147 147 show_custom_perms(true);
148 148 }
149 149 else{
150 150 show_custom_perms(false);
151 151 }
152 152 })
153 153 })
154 154 </script>
155 155
156 156 </%def>
@@ -1,351 +1,351 b''
1 1 ## -*- coding: utf-8 -*-
2 2
3 3 <%inherit file="/base/base.mako"/>
4 4 <%namespace name="diff_block" file="/changeset/diff_block.mako"/>
5 5
6 6 <%def name="title()">
7 7 ${_('%s Commit') % c.repo_name} - ${h.show_id(c.commit)}
8 8 %if c.rhodecode_name:
9 9 &middot; ${h.branding(c.rhodecode_name)}
10 10 %endif
11 11 </%def>
12 12
13 13 <%def name="menu_bar_nav()">
14 14 ${self.menu_items(active='repositories')}
15 15 </%def>
16 16
17 17 <%def name="menu_bar_subnav()">
18 18 ${self.repo_menu(active='changelog')}
19 19 </%def>
20 20
21 21 <%def name="main()">
22 22 <script>
23 23 // TODO: marcink switch this to pyroutes
24 AJAX_COMMENT_DELETE_URL = "${url('changeset_comment_delete',repo_name=c.repo_name,comment_id='__COMMENT_ID__')}";
24 AJAX_COMMENT_DELETE_URL = "${h.url('changeset_comment_delete',repo_name=c.repo_name,comment_id='__COMMENT_ID__')}";
25 25 templateContext.commit_data.commit_id = "${c.commit.raw_id}";
26 26 </script>
27 27 <div class="box">
28 28 <div class="title">
29 29 ${self.repo_page_title(c.rhodecode_db_repo)}
30 30 </div>
31 31
32 32 <div id="changeset_compare_view_content" class="summary changeset">
33 33 <div class="summary-detail">
34 34 <div class="summary-detail-header">
35 35 <span class="breadcrumbs files_location">
36 36 <h4>${_('Commit')}
37 37 <code>
38 38 ${h.show_id(c.commit)}
39 39 % if hasattr(c.commit, 'phase'):
40 40 <span class="tag phase-${c.commit.phase} tooltip" title="${_('Commit phase')}">${c.commit.phase}</span>
41 41 % endif
42 42
43 43 ## obsolete commits
44 44 % if hasattr(c.commit, 'obsolete'):
45 45 % if c.commit.obsolete:
46 46 <span class="tag obsolete-${c.commit.obsolete} tooltip" title="${_('Evolve State')}">${_('obsolete')}</span>
47 47 % endif
48 48 % endif
49 49
50 50 ## hidden commits
51 51 % if hasattr(c.commit, 'hidden'):
52 52 % if c.commit.hidden:
53 53 <span class="tag hidden-${c.commit.hidden} tooltip" title="${_('Evolve State')}">${_('hidden')}</span>
54 54 % endif
55 55 % endif
56 56
57 57 </code>
58 58 </h4>
59 59 </span>
60 60 <div class="pull-right">
61 61 <span id="parent_link">
62 62 <a href="#" title="${_('Parent Commit')}">${_('Parent')}</a>
63 63 </span>
64 64 |
65 65 <span id="child_link">
66 66 <a href="#" title="${_('Child Commit')}">${_('Child')}</a>
67 67 </span>
68 68 </div>
69 69 </div>
70 70
71 71 <div class="fieldset">
72 72 <div class="left-label">
73 73 ${_('Description')}:
74 74 </div>
75 75 <div class="right-content">
76 76 <div id="trimmed_message_box" class="commit">${h.urlify_commit_message(c.commit.message,c.repo_name)}</div>
77 77 <div id="message_expand" style="display:none;">
78 78 ${_('Expand')}
79 79 </div>
80 80 </div>
81 81 </div>
82 82
83 83 %if c.statuses:
84 84 <div class="fieldset">
85 85 <div class="left-label">
86 86 ${_('Commit status')}:
87 87 </div>
88 88 <div class="right-content">
89 89 <div class="changeset-status-ico">
90 90 <div class="${'flag_status %s' % c.statuses[0]} pull-left"></div>
91 91 </div>
92 92 <div title="${_('Commit status')}" class="changeset-status-lbl">[${h.commit_status_lbl(c.statuses[0])}]</div>
93 93 </div>
94 94 </div>
95 95 %endif
96 96
97 97 <div class="fieldset">
98 98 <div class="left-label">
99 99 ${_('References')}:
100 100 </div>
101 101 <div class="right-content">
102 102 <div class="tags">
103 103
104 104 %if c.commit.merge:
105 105 <span class="mergetag tag">
106 106 <i class="icon-merge"></i>${_('merge')}
107 107 </span>
108 108 %endif
109 109
110 110 %if h.is_hg(c.rhodecode_repo):
111 111 %for book in c.commit.bookmarks:
112 112 <span class="booktag tag" title="${h.tooltip(_('Bookmark %s') % book)}">
113 113 <a href="${h.url('files_home',repo_name=c.repo_name,revision=c.commit.raw_id)}"><i class="icon-bookmark"></i>${h.shorter(book)}</a>
114 114 </span>
115 115 %endfor
116 116 %endif
117 117
118 118 %for tag in c.commit.tags:
119 119 <span class="tagtag tag" title="${h.tooltip(_('Tag %s') % tag)}">
120 120 <a href="${h.url('files_home',repo_name=c.repo_name,revision=c.commit.raw_id)}"><i class="icon-tag"></i>${tag}</a>
121 121 </span>
122 122 %endfor
123 123
124 124 %if c.commit.branch:
125 125 <span class="branchtag tag" title="${h.tooltip(_('Branch %s') % c.commit.branch)}">
126 126 <a href="${h.url('files_home',repo_name=c.repo_name,revision=c.commit.raw_id)}"><i class="icon-code-fork"></i>${h.shorter(c.commit.branch)}</a>
127 127 </span>
128 128 %endif
129 129 </div>
130 130 </div>
131 131 </div>
132 132
133 133 <div class="fieldset">
134 134 <div class="left-label">
135 135 ${_('Diff options')}:
136 136 </div>
137 137 <div class="right-content">
138 138 <div class="diff-actions">
139 139 <a href="${h.url('changeset_raw_home',repo_name=c.repo_name,revision=c.commit.raw_id)}" class="tooltip" title="${h.tooltip(_('Raw diff'))}">
140 140 ${_('Raw Diff')}
141 141 </a>
142 142 |
143 143 <a href="${h.url('changeset_patch_home',repo_name=c.repo_name,revision=c.commit.raw_id)}" class="tooltip" title="${h.tooltip(_('Patch diff'))}">
144 144 ${_('Patch Diff')}
145 145 </a>
146 146 |
147 147 <a href="${h.url('changeset_download_home',repo_name=c.repo_name,revision=c.commit.raw_id,diff='download')}" class="tooltip" title="${h.tooltip(_('Download diff'))}">
148 148 ${_('Download Diff')}
149 149 </a>
150 150 |
151 151 ${c.ignorews_url(request.GET)}
152 152 |
153 153 ${c.context_url(request.GET)}
154 154 </div>
155 155 </div>
156 156 </div>
157 157
158 158 <div class="fieldset">
159 159 <div class="left-label">
160 160 ${_('Comments')}:
161 161 </div>
162 162 <div class="right-content">
163 163 <div class="comments-number">
164 164 %if c.comments:
165 165 <a href="#comments">${ungettext("%d Commit comment", "%d Commit comments", len(c.comments)) % len(c.comments)}</a>,
166 166 %else:
167 167 ${ungettext("%d Commit comment", "%d Commit comments", len(c.comments)) % len(c.comments)}
168 168 %endif
169 169 %if c.inline_cnt:
170 170 <a href="#" onclick="return Rhodecode.comments.nextComment();" id="inline-comments-counter">${ungettext("%d Inline Comment", "%d Inline Comments", c.inline_cnt) % c.inline_cnt}</a>
171 171 %else:
172 172 ${ungettext("%d Inline Comment", "%d Inline Comments", c.inline_cnt) % c.inline_cnt}
173 173 %endif
174 174 </div>
175 175 </div>
176 176 </div>
177 177
178 178 <div class="fieldset">
179 179 <div class="left-label">
180 180 ${_('Unresolved TODOs')}:
181 181 </div>
182 182 <div class="right-content">
183 183 <div class="comments-number">
184 184 % if c.unresolved_comments:
185 185 % for co in c.unresolved_comments:
186 186 <a class="permalink" href="#comment-${co.comment_id}" onclick="Rhodecode.comments.scrollToComment($('#comment-${co.comment_id}'))"> #${co.comment_id}</a>${'' if loop.last else ','}
187 187 % endfor
188 188 % else:
189 189 ${_('There are no unresolved TODOs')}
190 190 % endif
191 191 </div>
192 192 </div>
193 193 </div>
194 194
195 195 </div> <!-- end summary-detail -->
196 196
197 197 <div id="commit-stats" class="sidebar-right">
198 198 <div class="summary-detail-header">
199 199 <h4 class="item">
200 200 ${_('Author')}
201 201 </h4>
202 202 </div>
203 203 <div class="sidebar-right-content">
204 204 ${self.gravatar_with_user(c.commit.author)}
205 205 <div class="user-inline-data">- ${h.age_component(c.commit.date)}</div>
206 206 </div>
207 207 </div><!-- end sidebar -->
208 208 </div> <!-- end summary -->
209 209 <div class="cs_files">
210 210 <%namespace name="cbdiffs" file="/codeblocks/diffs.mako"/>
211 211 ${cbdiffs.render_diffset_menu()}
212 212 ${cbdiffs.render_diffset(
213 213 c.changes[c.commit.raw_id], commit=c.commit, use_comments=True)}
214 214 </div>
215 215
216 216 ## template for inline comment form
217 217 <%namespace name="comment" file="/changeset/changeset_file_comment.mako"/>
218 218
219 219 ## render comments
220 220 ${comment.generate_comments(c.comments)}
221 221
222 222 ## main comment form and it status
223 223 ${comment.comments(h.url('changeset_comment', repo_name=c.repo_name, revision=c.commit.raw_id),
224 224 h.commit_status(c.rhodecode_db_repo, c.commit.raw_id))}
225 225 </div>
226 226
227 227 ## FORM FOR MAKING JS ACTION AS CHANGESET COMMENTS
228 228 <script type="text/javascript">
229 229
230 230 $(document).ready(function() {
231 231
232 232 var boxmax = parseInt($('#trimmed_message_box').css('max-height'), 10);
233 233 if($('#trimmed_message_box').height() === boxmax){
234 234 $('#message_expand').show();
235 235 }
236 236
237 237 $('#message_expand').on('click', function(e){
238 238 $('#trimmed_message_box').css('max-height', 'none');
239 239 $(this).hide();
240 240 });
241 241
242 242 $('.show-inline-comments').on('click', function(e){
243 243 var boxid = $(this).attr('data-comment-id');
244 244 var button = $(this);
245 245
246 246 if(button.hasClass("comments-visible")) {
247 247 $('#{0} .inline-comments'.format(boxid)).each(function(index){
248 248 $(this).hide();
249 249 });
250 250 button.removeClass("comments-visible");
251 251 } else {
252 252 $('#{0} .inline-comments'.format(boxid)).each(function(index){
253 253 $(this).show();
254 254 });
255 255 button.addClass("comments-visible");
256 256 }
257 257 });
258 258
259 259
260 260 // next links
261 261 $('#child_link').on('click', function(e){
262 262 // fetch via ajax what is going to be the next link, if we have
263 263 // >1 links show them to user to choose
264 264 if(!$('#child_link').hasClass('disabled')){
265 265 $.ajax({
266 266 url: '${h.url('changeset_children',repo_name=c.repo_name, revision=c.commit.raw_id)}',
267 267 success: function(data) {
268 268 if(data.results.length === 0){
269 269 $('#child_link').html("${_('No Child Commits')}").addClass('disabled');
270 270 }
271 271 if(data.results.length === 1){
272 272 var commit = data.results[0];
273 273 window.location = pyroutes.url('changeset_home', {'repo_name': '${c.repo_name}','revision': commit.raw_id});
274 274 }
275 275 else if(data.results.length === 2){
276 276 $('#child_link').addClass('disabled');
277 277 $('#child_link').addClass('double');
278 278 var _html = '';
279 279 _html +='<a title="__title__" href="__url__">__rev__</a> '
280 280 .replace('__rev__','r{0}:{1}'.format(data.results[0].revision, data.results[0].raw_id.substr(0,6)))
281 281 .replace('__title__', data.results[0].message)
282 282 .replace('__url__', pyroutes.url('changeset_home', {'repo_name': '${c.repo_name}','revision': data.results[0].raw_id}));
283 283 _html +=' | ';
284 284 _html +='<a title="__title__" href="__url__">__rev__</a> '
285 285 .replace('__rev__','r{0}:{1}'.format(data.results[1].revision, data.results[1].raw_id.substr(0,6)))
286 286 .replace('__title__', data.results[1].message)
287 287 .replace('__url__', pyroutes.url('changeset_home', {'repo_name': '${c.repo_name}','revision': data.results[1].raw_id}));
288 288 $('#child_link').html(_html);
289 289 }
290 290 }
291 291 });
292 292 e.preventDefault();
293 293 }
294 294 });
295 295
296 296 // prev links
297 297 $('#parent_link').on('click', function(e){
298 298 // fetch via ajax what is going to be the next link, if we have
299 299 // >1 links show them to user to choose
300 300 if(!$('#parent_link').hasClass('disabled')){
301 301 $.ajax({
302 302 url: '${h.url("changeset_parents",repo_name=c.repo_name, revision=c.commit.raw_id)}',
303 303 success: function(data) {
304 304 if(data.results.length === 0){
305 305 $('#parent_link').html('${_('No Parent Commits')}').addClass('disabled');
306 306 }
307 307 if(data.results.length === 1){
308 308 var commit = data.results[0];
309 309 window.location = pyroutes.url('changeset_home', {'repo_name': '${c.repo_name}','revision': commit.raw_id});
310 310 }
311 311 else if(data.results.length === 2){
312 312 $('#parent_link').addClass('disabled');
313 313 $('#parent_link').addClass('double');
314 314 var _html = '';
315 315 _html +='<a title="__title__" href="__url__">Parent __rev__</a>'
316 316 .replace('__rev__','r{0}:{1}'.format(data.results[0].revision, data.results[0].raw_id.substr(0,6)))
317 317 .replace('__title__', data.results[0].message)
318 318 .replace('__url__', pyroutes.url('changeset_home', {'repo_name': '${c.repo_name}','revision': data.results[0].raw_id}));
319 319 _html +=' | ';
320 320 _html +='<a title="__title__" href="__url__">Parent __rev__</a>'
321 321 .replace('__rev__','r{0}:{1}'.format(data.results[1].revision, data.results[1].raw_id.substr(0,6)))
322 322 .replace('__title__', data.results[1].message)
323 323 .replace('__url__', pyroutes.url('changeset_home', {'repo_name': '${c.repo_name}','revision': data.results[1].raw_id}));
324 324 $('#parent_link').html(_html);
325 325 }
326 326 }
327 327 });
328 328 e.preventDefault();
329 329 }
330 330 });
331 331
332 332 if (location.hash) {
333 333 var result = splitDelimitedHash(location.hash);
334 334 var line = $('html').find(result.loc);
335 335 if (line.length > 0){
336 336 offsetScroll(line, 70);
337 337 }
338 338 }
339 339
340 340 // browse tree @ revision
341 341 $('#files_link').on('click', function(e){
342 342 window.location = '${h.url('files_home',repo_name=c.repo_name, revision=c.commit.raw_id, f_path='')}';
343 343 e.preventDefault();
344 344 });
345 345
346 346 // inject comments into their proper positions
347 347 var file_comments = $('.inline-comment-placeholder');
348 348 })
349 349 </script>
350 350
351 351 </%def>
@@ -1,129 +1,129 b''
1 1 ## -*- coding: utf-8 -*-
2 2 <%inherit file="/base/base.mako"/>
3 3
4 4 <%def name="title()">
5 5 ${_('Fork repository %s') % c.repo_name}
6 6 %if c.rhodecode_name:
7 7 &middot; ${h.branding(c.rhodecode_name)}
8 8 %endif
9 9 </%def>
10 10
11 11 <%def name="breadcrumbs_links()">
12 12 ${_('New Fork')}
13 13 </%def>
14 14
15 15 <%def name="menu_bar_nav()">
16 16 ${self.menu_items(active='repositories')}
17 17 </%def>
18 18
19 19 <%def name="menu_bar_subnav()">
20 20 ${self.repo_menu(active='options')}
21 21 </%def>
22 22
23 23 <%def name="main()">
24 24 <div class="box">
25 25 <div class="title">
26 26 ${self.repo_page_title(c.rhodecode_db_repo)}
27 27 ${self.breadcrumbs()}
28 28 </div>
29 29
30 ${h.secure_form(url('repo_fork_create_home',repo_name=c.repo_info.repo_name))}
30 ${h.secure_form(h.url('repo_fork_create_home',repo_name=c.repo_info.repo_name))}
31 31 <div class="form">
32 32 <!-- fields -->
33 33 <div class="fields">
34 34
35 35 <div class="field">
36 36 <div class="label">
37 37 <label for="repo_name">${_('Fork name')}:</label>
38 38 </div>
39 39 <div class="input">
40 40 ${h.text('repo_name', class_="medium")}
41 41 ${h.hidden('repo_type',c.repo_info.repo_type)}
42 42 ${h.hidden('fork_parent_id',c.repo_info.repo_id)}
43 43 </div>
44 44 </div>
45 45
46 46 <div class="field">
47 47 <div class="label label-textarea">
48 48 <label for="description">${_('Description')}:</label>
49 49 </div>
50 50 <div class="textarea-repo textarea text-area editor">
51 51 ${h.textarea('description')}
52 52 <span class="help-block">${_('Keep it short and to the point. Use a README file for longer descriptions.')}</span>
53 53 </div>
54 54 </div>
55 55
56 56 <div class="field">
57 57 <div class="label">
58 58 <label for="repo_group">${_('Repository group')}:</label>
59 59 </div>
60 60 <div class="select">
61 61 ${h.select('repo_group','',c.repo_groups,class_="medium")}
62 62 % if c.personal_repo_group:
63 63 <a class="btn" href="#" id="select_my_group" data-personal-group-id="${c.personal_repo_group.group_id}">
64 64 ${_('Select my personal group (%(repo_group_name)s)') % {'repo_group_name': c.personal_repo_group.group_name}}
65 65 </a>
66 66 % endif
67 67 <span class="help-block">${_('Optionally select a group to put this repository into.')}</span>
68 68 </div>
69 69 </div>
70 70
71 71 <div class="field">
72 72 <div class="label">
73 73 <label for="landing_rev">${_('Landing commit')}:</label>
74 74 </div>
75 75 <div class="select">
76 76 ${h.select('landing_rev','',c.landing_revs,class_="medium")}
77 77 <span class="help-block">${_('Default commit for files page, downloads, whoosh and readme')}</span>
78 78 </div>
79 79 </div>
80 80
81 81 <div class="field">
82 82 <div class="label label-checkbox">
83 83 <label for="private">${_('Private')}:</label>
84 84 </div>
85 85 <div class="checkboxes">
86 86 ${h.checkbox('private',value="True")}
87 87 <span class="help-block">${_('Private repositories are only visible to people explicitly added as collaborators.')}</span>
88 88 </div>
89 89 </div>
90 90
91 91 <div class="field">
92 92 <div class="label label-checkbox">
93 93 <label for="private">${_('Copy permissions')}:</label>
94 94 </div>
95 95 <div class="checkboxes">
96 96 ${h.checkbox('copy_permissions',value="True", checked="checked")}
97 97 <span class="help-block">${_('Copy permissions from forked repository')}</span>
98 98 </div>
99 99 </div>
100 100
101 101 <div class="buttons">
102 102 ${h.submit('',_('Fork this Repository'),class_="btn")}
103 103 </div>
104 104 </div>
105 105 </div>
106 106 ${h.end_form()}
107 107 </div>
108 108 <script>
109 109 $(document).ready(function(){
110 110 $("#repo_group").select2({
111 111 'dropdownAutoWidth': true,
112 112 'containerCssClass': "drop-menu",
113 113 'dropdownCssClass': "drop-menu-dropdown",
114 114 'width': "resolve"
115 115 });
116 116 $("#landing_rev").select2({
117 117 'containerCssClass': "drop-menu",
118 118 'dropdownCssClass': "drop-menu-dropdown",
119 119 'minimumResultsForSearch': -1
120 120 });
121 121 $('#repo_name').focus();
122 122
123 123 $('#select_my_group').on('click', function(e){
124 124 e.preventDefault();
125 125 $("#repo_group").val($(this).data('personalGroupId')).trigger("change");
126 126 })
127 127 })
128 128 </script>
129 129 </%def>
@@ -1,526 +1,526 b''
1 1 <%inherit file="/base/base.mako"/>
2 2
3 3 <%def name="title()">
4 4 ${c.repo_name} ${_('New pull request')}
5 5 </%def>
6 6
7 7 <%def name="breadcrumbs_links()">
8 8 ${_('New pull request')}
9 9 </%def>
10 10
11 11 <%def name="menu_bar_nav()">
12 12 ${self.menu_items(active='repositories')}
13 13 </%def>
14 14
15 15 <%def name="menu_bar_subnav()">
16 16 ${self.repo_menu(active='showpullrequest')}
17 17 </%def>
18 18
19 19 <%def name="main()">
20 20 <div class="box">
21 21 <div class="title">
22 22 ${self.repo_page_title(c.rhodecode_db_repo)}
23 23 </div>
24 24
25 ${h.secure_form(url('pullrequest', repo_name=c.repo_name), method='post', id='pull_request_form')}
25 ${h.secure_form(h.url('pullrequest', repo_name=c.repo_name), method='post', id='pull_request_form')}
26 26
27 27 ${self.breadcrumbs()}
28 28
29 29 <div class="box pr-summary">
30 30
31 31 <div class="summary-details block-left">
32 32
33 33
34 34 <div class="pr-details-title">
35 35 ${_('Pull request summary')}
36 36 </div>
37 37
38 38 <div class="form" style="padding-top: 10px">
39 39 <!-- fields -->
40 40
41 41 <div class="fields" >
42 42
43 43 <div class="field">
44 44 <div class="label">
45 45 <label for="pullrequest_title">${_('Title')}:</label>
46 46 </div>
47 47 <div class="input">
48 48 ${h.text('pullrequest_title', c.default_title, class_="medium autogenerated-title")}
49 49 </div>
50 50 </div>
51 51
52 52 <div class="field">
53 53 <div class="label label-textarea">
54 54 <label for="pullrequest_desc">${_('Description')}:</label>
55 55 </div>
56 56 <div class="textarea text-area editor">
57 57 ${h.textarea('pullrequest_desc',size=30, )}
58 58 <span class="help-block">${_('Write a short description on this pull request')}</span>
59 59 </div>
60 60 </div>
61 61
62 62 <div class="field">
63 63 <div class="label label-textarea">
64 64 <label for="pullrequest_desc">${_('Commit flow')}:</label>
65 65 </div>
66 66
67 67 ## TODO: johbo: Abusing the "content" class here to get the
68 68 ## desired effect. Should be replaced by a proper solution.
69 69
70 70 ##ORG
71 71 <div class="content">
72 72 <strong>${_('Source repository')}:</strong>
73 73 ${c.rhodecode_db_repo.description}
74 74 </div>
75 75 <div class="content">
76 76 ${h.hidden('source_repo')}
77 77 ${h.hidden('source_ref')}
78 78 </div>
79 79
80 80 ##OTHER, most Probably the PARENT OF THIS FORK
81 81 <div class="content">
82 82 ## filled with JS
83 83 <div id="target_repo_desc"></div>
84 84 </div>
85 85
86 86 <div class="content">
87 87 ${h.hidden('target_repo')}
88 88 ${h.hidden('target_ref')}
89 89 <span id="target_ref_loading" style="display: none">
90 90 ${_('Loading refs...')}
91 91 </span>
92 92 </div>
93 93 </div>
94 94
95 95 <div class="field">
96 96 <div class="label label-textarea">
97 97 <label for="pullrequest_submit"></label>
98 98 </div>
99 99 <div class="input">
100 100 <div class="pr-submit-button">
101 101 ${h.submit('save',_('Submit Pull Request'),class_="btn")}
102 102 </div>
103 103 <div id="pr_open_message"></div>
104 104 </div>
105 105 </div>
106 106
107 107 <div class="pr-spacing-container"></div>
108 108 </div>
109 109 </div>
110 110 </div>
111 111 <div>
112 112 ## AUTHOR
113 113 <div class="reviewers-title block-right">
114 114 <div class="pr-details-title">
115 115 ${_('Author of this pull request')}
116 116 </div>
117 117 </div>
118 118 <div class="block-right pr-details-content reviewers">
119 119 <ul class="group_members">
120 120 <li>
121 121 ${self.gravatar_with_user(c.rhodecode_user.email, 16)}
122 122 </li>
123 123 </ul>
124 124 </div>
125 125
126 126 ## REVIEW RULES
127 127 <div id="review_rules" style="display: none" class="reviewers-title block-right">
128 128 <div class="pr-details-title">
129 129 ${_('Reviewer rules')}
130 130 </div>
131 131 <div class="pr-reviewer-rules">
132 132 ## review rules will be appended here, by default reviewers logic
133 133 </div>
134 134 </div>
135 135
136 136 ## REVIEWERS
137 137 <div class="reviewers-title block-right">
138 138 <div class="pr-details-title">
139 139 ${_('Pull request reviewers')}
140 140 <span class="calculate-reviewers"> - ${_('loading...')}</span>
141 141 </div>
142 142 </div>
143 143 <div id="reviewers" class="block-right pr-details-content reviewers">
144 144 ## members goes here, filled via JS based on initial selection !
145 145 <input type="hidden" name="__start__" value="review_members:sequence">
146 146 <ul id="review_members" class="group_members"></ul>
147 147 <input type="hidden" name="__end__" value="review_members:sequence">
148 148 <div id="add_reviewer_input" class='ac'>
149 149 <div class="reviewer_ac">
150 150 ${h.text('user', class_='ac-input', placeholder=_('Add reviewer or reviewer group'))}
151 151 <div id="reviewers_container"></div>
152 152 </div>
153 153 </div>
154 154 </div>
155 155 </div>
156 156 </div>
157 157 <div class="box">
158 158 <div>
159 159 ## overview pulled by ajax
160 160 <div id="pull_request_overview"></div>
161 161 </div>
162 162 </div>
163 163 ${h.end_form()}
164 164 </div>
165 165
166 166 <script type="text/javascript">
167 167 $(function(){
168 168 var defaultSourceRepo = '${c.default_repo_data['source_repo_name']}';
169 169 var defaultSourceRepoData = ${c.default_repo_data['source_refs_json']|n};
170 170 var defaultTargetRepo = '${c.default_repo_data['target_repo_name']}';
171 171 var defaultTargetRepoData = ${c.default_repo_data['target_refs_json']|n};
172 172
173 173 var $pullRequestForm = $('#pull_request_form');
174 174 var $sourceRepo = $('#source_repo', $pullRequestForm);
175 175 var $targetRepo = $('#target_repo', $pullRequestForm);
176 176 var $sourceRef = $('#source_ref', $pullRequestForm);
177 177 var $targetRef = $('#target_ref', $pullRequestForm);
178 178
179 179 var sourceRepo = function() { return $sourceRepo.eq(0).val() };
180 180 var sourceRef = function() { return $sourceRef.eq(0).val().split(':') };
181 181
182 182 var targetRepo = function() { return $targetRepo.eq(0).val() };
183 183 var targetRef = function() { return $targetRef.eq(0).val().split(':') };
184 184
185 185 var calculateContainerWidth = function() {
186 186 var maxWidth = 0;
187 187 var repoSelect2Containers = ['#source_repo', '#target_repo'];
188 188 $.each(repoSelect2Containers, function(idx, value) {
189 189 $(value).select2('container').width('auto');
190 190 var curWidth = $(value).select2('container').width();
191 191 if (maxWidth <= curWidth) {
192 192 maxWidth = curWidth;
193 193 }
194 194 $.each(repoSelect2Containers, function(idx, value) {
195 195 $(value).select2('container').width(maxWidth + 10);
196 196 });
197 197 });
198 198 };
199 199
200 200 var initRefSelection = function(selectedRef) {
201 201 return function(element, callback) {
202 202 // translate our select2 id into a text, it's a mapping to show
203 203 // simple label when selecting by internal ID.
204 204 var id, refData;
205 205 if (selectedRef === undefined) {
206 206 id = element.val();
207 207 refData = element.val().split(':');
208 208 } else {
209 209 id = selectedRef;
210 210 refData = selectedRef.split(':');
211 211 }
212 212
213 213 var text = refData[1];
214 214 if (refData[0] === 'rev') {
215 215 text = text.substring(0, 12);
216 216 }
217 217
218 218 var data = {id: id, text: text};
219 219
220 220 callback(data);
221 221 };
222 222 };
223 223
224 224 var formatRefSelection = function(item) {
225 225 var prefix = '';
226 226 var refData = item.id.split(':');
227 227 if (refData[0] === 'branch') {
228 228 prefix = '<i class="icon-branch"></i>';
229 229 }
230 230 else if (refData[0] === 'book') {
231 231 prefix = '<i class="icon-bookmark"></i>';
232 232 }
233 233 else if (refData[0] === 'tag') {
234 234 prefix = '<i class="icon-tag"></i>';
235 235 }
236 236
237 237 var originalOption = item.element;
238 238 return prefix + item.text;
239 239 };
240 240
241 241 // custom code mirror
242 242 var codeMirrorInstance = initPullRequestsCodeMirror('#pullrequest_desc');
243 243
244 244 reviewersController = new ReviewersController();
245 245
246 246 var queryTargetRepo = function(self, query) {
247 247 // cache ALL results if query is empty
248 248 var cacheKey = query.term || '__';
249 249 var cachedData = self.cachedDataSource[cacheKey];
250 250
251 251 if (cachedData) {
252 252 query.callback({results: cachedData.results});
253 253 } else {
254 254 $.ajax({
255 255 url: pyroutes.url('pullrequest_repo_destinations', {'repo_name': templateContext.repo_name}),
256 256 data: {query: query.term},
257 257 dataType: 'json',
258 258 type: 'GET',
259 259 success: function(data) {
260 260 self.cachedDataSource[cacheKey] = data;
261 261 query.callback({results: data.results});
262 262 },
263 263 error: function(data, textStatus, errorThrown) {
264 264 alert(
265 265 "Error while fetching entries.\nError code {0} ({1}).".format(data.status, data.statusText));
266 266 }
267 267 });
268 268 }
269 269 };
270 270
271 271 var queryTargetRefs = function(initialData, query) {
272 272 var data = {results: []};
273 273 // filter initialData
274 274 $.each(initialData, function() {
275 275 var section = this.text;
276 276 var children = [];
277 277 $.each(this.children, function() {
278 278 if (query.term.length === 0 ||
279 279 this.text.toUpperCase().indexOf(query.term.toUpperCase()) >= 0 ) {
280 280 children.push({'id': this.id, 'text': this.text})
281 281 }
282 282 });
283 283 data.results.push({'text': section, 'children': children})
284 284 });
285 285 query.callback({results: data.results});
286 286 };
287 287
288 288 var loadRepoRefDiffPreview = function() {
289 289
290 290 var url_data = {
291 291 'repo_name': targetRepo(),
292 292 'target_repo': sourceRepo(),
293 293 'source_ref': targetRef()[2],
294 294 'source_ref_type': 'rev',
295 295 'target_ref': sourceRef()[2],
296 296 'target_ref_type': 'rev',
297 297 'merge': true,
298 298 '_': Date.now() // bypass browser caching
299 299 }; // gather the source/target ref and repo here
300 300
301 301 if (sourceRef().length !== 3 || targetRef().length !== 3) {
302 302 prButtonLock(true, "${_('Please select source and target')}");
303 303 return;
304 304 }
305 305 var url = pyroutes.url('compare_url', url_data);
306 306
307 307 // lock PR button, so we cannot send PR before it's calculated
308 308 prButtonLock(true, "${_('Loading compare ...')}", 'compare');
309 309
310 310 if (loadRepoRefDiffPreview._currentRequest) {
311 311 loadRepoRefDiffPreview._currentRequest.abort();
312 312 }
313 313
314 314 loadRepoRefDiffPreview._currentRequest = $.get(url)
315 315 .error(function(data, textStatus, errorThrown) {
316 316 alert(
317 317 "Error while processing request.\nError code {0} ({1}).".format(
318 318 data.status, data.statusText));
319 319 })
320 320 .done(function(data) {
321 321 loadRepoRefDiffPreview._currentRequest = null;
322 322 $('#pull_request_overview').html(data);
323 323
324 324 var commitElements = $(data).find('tr[commit_id]');
325 325
326 326 var prTitleAndDesc = getTitleAndDescription(
327 327 sourceRef()[1], commitElements, 5);
328 328
329 329 var title = prTitleAndDesc[0];
330 330 var proposedDescription = prTitleAndDesc[1];
331 331
332 332 var useGeneratedTitle = (
333 333 $('#pullrequest_title').hasClass('autogenerated-title') ||
334 334 $('#pullrequest_title').val() === "");
335 335
336 336 if (title && useGeneratedTitle) {
337 337 // use generated title if we haven't specified our own
338 338 $('#pullrequest_title').val(title);
339 339 $('#pullrequest_title').addClass('autogenerated-title');
340 340
341 341 }
342 342
343 343 var useGeneratedDescription = (
344 344 !codeMirrorInstance._userDefinedDesc ||
345 345 codeMirrorInstance.getValue() === "");
346 346
347 347 if (proposedDescription && useGeneratedDescription) {
348 348 // set proposed content, if we haven't defined our own,
349 349 // or we don't have description written
350 350 codeMirrorInstance._userDefinedDesc = false; // reset state
351 351 codeMirrorInstance.setValue(proposedDescription);
352 352 }
353 353
354 354 var msg = '';
355 355 if (commitElements.length === 1) {
356 356 msg = "${ungettext('This pull request will consist of __COMMITS__ commit.', 'This pull request will consist of __COMMITS__ commits.', 1)}";
357 357 } else {
358 358 msg = "${ungettext('This pull request will consist of __COMMITS__ commit.', 'This pull request will consist of __COMMITS__ commits.', 2)}";
359 359 }
360 360
361 361 msg += ' <a id="pull_request_overview_url" href="{0}" target="_blank">${_('Show detailed compare.')}</a>'.format(url);
362 362
363 363 if (commitElements.length) {
364 364 var commitsLink = '<a href="#pull_request_overview"><strong>{0}</strong></a>'.format(commitElements.length);
365 365 prButtonLock(false, msg.replace('__COMMITS__', commitsLink), 'compare');
366 366 }
367 367 else {
368 368 prButtonLock(true, "${_('There are no commits to merge.')}", 'compare');
369 369 }
370 370
371 371
372 372 });
373 373 };
374 374
375 375 var Select2Box = function(element, overrides) {
376 376 var globalDefaults = {
377 377 dropdownAutoWidth: true,
378 378 containerCssClass: "drop-menu",
379 379 dropdownCssClass: "drop-menu-dropdown"
380 380 };
381 381
382 382 var initSelect2 = function(defaultOptions) {
383 383 var options = jQuery.extend(globalDefaults, defaultOptions, overrides);
384 384 element.select2(options);
385 385 };
386 386
387 387 return {
388 388 initRef: function() {
389 389 var defaultOptions = {
390 390 minimumResultsForSearch: 5,
391 391 formatSelection: formatRefSelection
392 392 };
393 393
394 394 initSelect2(defaultOptions);
395 395 },
396 396
397 397 initRepo: function(defaultValue, readOnly) {
398 398 var defaultOptions = {
399 399 initSelection : function (element, callback) {
400 400 var data = {id: defaultValue, text: defaultValue};
401 401 callback(data);
402 402 }
403 403 };
404 404
405 405 initSelect2(defaultOptions);
406 406
407 407 element.select2('val', defaultSourceRepo);
408 408 if (readOnly === true) {
409 409 element.select2('readonly', true);
410 410 }
411 411 }
412 412 };
413 413 };
414 414
415 415 var initTargetRefs = function(refsData, selectedRef){
416 416 Select2Box($targetRef, {
417 417 query: function(query) {
418 418 queryTargetRefs(refsData, query);
419 419 },
420 420 initSelection : initRefSelection(selectedRef)
421 421 }).initRef();
422 422
423 423 if (!(selectedRef === undefined)) {
424 424 $targetRef.select2('val', selectedRef);
425 425 }
426 426 };
427 427
428 428 var targetRepoChanged = function(repoData) {
429 429 // generate new DESC of target repo displayed next to select
430 430 $('#target_repo_desc').html(
431 431 "<strong>${_('Target repository')}</strong>: {0}".format(repoData['description'])
432 432 );
433 433
434 434 // generate dynamic select2 for refs.
435 435 initTargetRefs(repoData['refs']['select2_refs'],
436 436 repoData['refs']['selected_ref']);
437 437
438 438 };
439 439
440 440 var sourceRefSelect2 = Select2Box($sourceRef, {
441 441 placeholder: "${_('Select commit reference')}",
442 442 query: function(query) {
443 443 var initialData = defaultSourceRepoData['refs']['select2_refs'];
444 444 queryTargetRefs(initialData, query)
445 445 },
446 446 initSelection: initRefSelection()
447 447 }
448 448 );
449 449
450 450 var sourceRepoSelect2 = Select2Box($sourceRepo, {
451 451 query: function(query) {}
452 452 });
453 453
454 454 var targetRepoSelect2 = Select2Box($targetRepo, {
455 455 cachedDataSource: {},
456 456 query: $.debounce(250, function(query) {
457 457 queryTargetRepo(this, query);
458 458 }),
459 459 formatResult: formatResult
460 460 });
461 461
462 462 sourceRefSelect2.initRef();
463 463
464 464 sourceRepoSelect2.initRepo(defaultSourceRepo, true);
465 465
466 466 targetRepoSelect2.initRepo(defaultTargetRepo, false);
467 467
468 468 $sourceRef.on('change', function(e){
469 469 loadRepoRefDiffPreview();
470 470 reviewersController.loadDefaultReviewers(
471 471 sourceRepo(), sourceRef(), targetRepo(), targetRef());
472 472 });
473 473
474 474 $targetRef.on('change', function(e){
475 475 loadRepoRefDiffPreview();
476 476 reviewersController.loadDefaultReviewers(
477 477 sourceRepo(), sourceRef(), targetRepo(), targetRef());
478 478 });
479 479
480 480 $targetRepo.on('change', function(e){
481 481 var repoName = $(this).val();
482 482 calculateContainerWidth();
483 483 $targetRef.select2('destroy');
484 484 $('#target_ref_loading').show();
485 485
486 486 $.ajax({
487 487 url: pyroutes.url('pullrequest_repo_refs',
488 488 {'repo_name': templateContext.repo_name, 'target_repo_name':repoName}),
489 489 data: {},
490 490 dataType: 'json',
491 491 type: 'GET',
492 492 success: function(data) {
493 493 $('#target_ref_loading').hide();
494 494 targetRepoChanged(data);
495 495 loadRepoRefDiffPreview();
496 496 },
497 497 error: function(data, textStatus, errorThrown) {
498 498 alert("Error while fetching entries.\nError code {0} ({1}).".format(data.status, data.statusText));
499 499 }
500 500 })
501 501
502 502 });
503 503
504 504 prButtonLock(true, "${_('Please select source and target')}", 'all');
505 505
506 506 // auto-load on init, the target refs select2
507 507 calculateContainerWidth();
508 508 targetRepoChanged(defaultTargetRepoData);
509 509
510 510 $('#pullrequest_title').on('keyup', function(e){
511 511 $(this).removeClass('autogenerated-title');
512 512 });
513 513
514 514 % if c.default_source_ref:
515 515 // in case we have a pre-selected value, use it now
516 516 $sourceRef.select2('val', '${c.default_source_ref}');
517 517 loadRepoRefDiffPreview();
518 518 reviewersController.loadDefaultReviewers(
519 519 sourceRepo(), sourceRef(), targetRepo(), targetRef());
520 520 % endif
521 521
522 522 ReviewerAutoComplete('#user');
523 523 });
524 524 </script>
525 525
526 526 </%def>
@@ -1,63 +1,63 b''
1 1
2 2 <div class="pull-request-wrap">
3 3
4 4 % if c.pr_merge_possible:
5 5 <h2 class="merge-status">
6 6 <span class="merge-icon success"><i class="icon-true"></i></span>
7 7 ${_('This pull request can be merged automatically.')}
8 8 </h2>
9 9 % else:
10 10 <h2 class="merge-status">
11 11 <span class="merge-icon warning"><i class="icon-false"></i></span>
12 12 ${_('Merge is not currently possible because of below failed checks.')}
13 13 </h2>
14 14 % endif
15 15
16 16 <ul>
17 17 % for pr_check_key, pr_check_details in c.pr_merge_errors.items():
18 18 <% pr_check_type = pr_check_details['error_type'] %>
19 19 <li>
20 20 <span class="merge-message ${pr_check_type}" data-role="merge-message">
21 21 - ${pr_check_details['message']}
22 22 % if pr_check_key == 'todo':
23 23 % for co in pr_check_details['details']:
24 24 <a class="permalink" href="#comment-${co.comment_id}" onclick="Rhodecode.comments.scrollToComment($('#comment-${co.comment_id}'), 0, ${h.json.dumps(co.outdated)})"> #${co.comment_id}</a>${'' if loop.last else ','}
25 25 % endfor
26 26 % endif
27 27 </span>
28 28 </li>
29 29 % endfor
30 30 </ul>
31 31
32 32 <div class="pull-request-merge-actions">
33 33 % if c.allowed_to_merge:
34 34 <div class="pull-right">
35 ${h.secure_form(url('pullrequest_merge', repo_name=c.repo_name, pull_request_id=c.pull_request.pull_request_id), id='merge_pull_request_form')}
35 ${h.secure_form(h.url('pullrequest_merge', repo_name=c.repo_name, pull_request_id=c.pull_request.pull_request_id), id='merge_pull_request_form')}
36 36 <% merge_disabled = ' disabled' if c.pr_merge_possible is False else '' %>
37 37 <a class="btn" href="#" onclick="refreshMergeChecks(); return false;">${_('refresh checks')}</a>
38 38 <input type="submit" id="merge_pull_request" value="${_('Merge Pull Request')}" class="btn${merge_disabled}"${merge_disabled}>
39 39 ${h.end_form()}
40 40 </div>
41 41 % elif c.rhodecode_user.username != h.DEFAULT_USER:
42 42 <a class="btn" href="#" onclick="refreshMergeChecks(); return false;">${_('refresh checks')}</a>
43 43 <input type="submit" value="${_('Merge Pull Request')}" class="btn disabled" disabled="disabled" title="${_('You are not allowed to merge this pull request.')}">
44 44 % else:
45 45 <input type="submit" value="${_('Login to Merge this Pull Request')}" class="btn disabled" disabled="disabled">
46 46 % endif
47 47 </div>
48 48
49 49 % if c.allowed_to_close:
50 50 ## close PR action, injected later next to COMMENT button
51 51 <div id="close-pull-request-action" style="display: none">
52 52 % if c.pull_request_review_status == c.REVIEW_STATUS_APPROVED:
53 53 <a class="btn btn-approved-status" href="#close-as-approved" onclick="closePullRequest('${c.REVIEW_STATUS_APPROVED}'); return false;">
54 54 ${_('Close with status {}').format(h.commit_status_lbl(c.REVIEW_STATUS_APPROVED))}
55 55 </a>
56 56 % else:
57 57 <a class="btn btn-rejected-status" href="#close-as-rejected" onclick="closePullRequest('${c.REVIEW_STATUS_REJECTED}'); return false;">
58 58 ${_('Close with status {}').format(h.commit_status_lbl(c.REVIEW_STATUS_REJECTED))}
59 59 </a>
60 60 % endif
61 61 </div>
62 62 % endif
63 63 </div>
@@ -1,860 +1,860 b''
1 1 <%inherit file="/base/base.mako"/>
2 2 <%namespace name="base" file="/base/base.mako"/>
3 3
4 4 <%def name="title()">
5 5 ${_('%s Pull Request #%s') % (c.repo_name, c.pull_request.pull_request_id)}
6 6 %if c.rhodecode_name:
7 7 &middot; ${h.branding(c.rhodecode_name)}
8 8 %endif
9 9 </%def>
10 10
11 11 <%def name="breadcrumbs_links()">
12 12 <span id="pr-title">
13 13 ${c.pull_request.title}
14 14 %if c.pull_request.is_closed():
15 15 (${_('Closed')})
16 16 %endif
17 17 </span>
18 18 <div id="pr-title-edit" class="input" style="display: none;">
19 19 ${h.text('pullrequest_title', id_="pr-title-input", class_="large", value=c.pull_request.title)}
20 20 </div>
21 21 </%def>
22 22
23 23 <%def name="menu_bar_nav()">
24 24 ${self.menu_items(active='repositories')}
25 25 </%def>
26 26
27 27 <%def name="menu_bar_subnav()">
28 28 ${self.repo_menu(active='showpullrequest')}
29 29 </%def>
30 30
31 31 <%def name="main()">
32 32
33 33 <script type="text/javascript">
34 34 // TODO: marcink switch this to pyroutes
35 AJAX_COMMENT_DELETE_URL = "${url('pullrequest_comment_delete',repo_name=c.repo_name,comment_id='__COMMENT_ID__')}";
35 AJAX_COMMENT_DELETE_URL = "${h.url('pullrequest_comment_delete',repo_name=c.repo_name,comment_id='__COMMENT_ID__')}";
36 36 templateContext.pull_request_data.pull_request_id = ${c.pull_request.pull_request_id};
37 37 </script>
38 38 <div class="box">
39 39
40 40 <div class="title">
41 41 ${self.repo_page_title(c.rhodecode_db_repo)}
42 42 </div>
43 43
44 44 ${self.breadcrumbs()}
45 45
46 46 <div class="box pr-summary">
47 47
48 48 <div class="summary-details block-left">
49 49 <% summary = lambda n:{False:'summary-short'}.get(n) %>
50 50 <div class="pr-details-title">
51 51 <a href="${h.route_path('pull_requests_global', pull_request_id=c.pull_request.pull_request_id)}">${_('Pull request #%s') % c.pull_request.pull_request_id}</a> ${_('From')} ${h.format_date(c.pull_request.created_on)}
52 52 %if c.allowed_to_update:
53 53 <div id="delete_pullrequest" class="pull-right action_button ${'' if c.allowed_to_delete else 'disabled' }" style="clear:inherit;padding: 0">
54 54 % if c.allowed_to_delete:
55 ${h.secure_form(url('pullrequest_delete', repo_name=c.pull_request.target_repo.repo_name, pull_request_id=c.pull_request.pull_request_id),method='delete')}
55 ${h.secure_form(h.url('pullrequest_delete', repo_name=c.pull_request.target_repo.repo_name, pull_request_id=c.pull_request.pull_request_id),method='delete')}
56 56 ${h.submit('remove_%s' % c.pull_request.pull_request_id, _('Delete'),
57 57 class_="btn btn-link btn-danger no-margin",onclick="return confirm('"+_('Confirm to delete this pull request')+"');")}
58 58 ${h.end_form()}
59 59 % else:
60 60 ${_('Delete')}
61 61 % endif
62 62 </div>
63 63 <div id="open_edit_pullrequest" class="pull-right action_button">${_('Edit')}</div>
64 64 <div id="close_edit_pullrequest" class="pull-right action_button" style="display: none;padding: 0">${_('Cancel')}</div>
65 65 %endif
66 66 </div>
67 67
68 68 <div id="summary" class="fields pr-details-content">
69 69 <div class="field">
70 70 <div class="label-summary">
71 71 <label>${_('Source')}:</label>
72 72 </div>
73 73 <div class="input">
74 74 <div class="pr-origininfo">
75 75 ## branch link is only valid if it is a branch
76 76 <span class="tag">
77 77 %if c.pull_request.source_ref_parts.type == 'branch':
78 78 <a href="${h.url('changelog_home', repo_name=c.pull_request.source_repo.repo_name, branch=c.pull_request.source_ref_parts.name)}">${c.pull_request.source_ref_parts.type}: ${c.pull_request.source_ref_parts.name}</a>
79 79 %else:
80 80 ${c.pull_request.source_ref_parts.type}: ${c.pull_request.source_ref_parts.name}
81 81 %endif
82 82 </span>
83 83 <span class="clone-url">
84 84 <a href="${h.route_path('repo_summary', repo_name=c.pull_request.source_repo.repo_name)}">${c.pull_request.source_repo.clone_url()}</a>
85 85 </span>
86 86 <br/>
87 87 % if c.ancestor_commit:
88 88 ${_('Common ancestor')}:
89 89 <code><a href="${h.url('changeset_home', repo_name=c.target_repo.repo_name, revision=c.ancestor_commit.raw_id)}">${h.show_id(c.ancestor_commit)}</a></code>
90 90 % endif
91 91 </div>
92 92 <div class="pr-pullinfo">
93 93 %if h.is_hg(c.pull_request.source_repo):
94 94 <input type="text" class="input-monospace" value="hg pull -r ${h.short_id(c.source_ref)} ${c.pull_request.source_repo.clone_url()}" readonly="readonly">
95 95 %elif h.is_git(c.pull_request.source_repo):
96 96 <input type="text" class="input-monospace" value="git pull ${c.pull_request.source_repo.clone_url()} ${c.pull_request.source_ref_parts.name}" readonly="readonly">
97 97 %endif
98 98 </div>
99 99 </div>
100 100 </div>
101 101 <div class="field">
102 102 <div class="label-summary">
103 103 <label>${_('Target')}:</label>
104 104 </div>
105 105 <div class="input">
106 106 <div class="pr-targetinfo">
107 107 ## branch link is only valid if it is a branch
108 108 <span class="tag">
109 109 %if c.pull_request.target_ref_parts.type == 'branch':
110 110 <a href="${h.url('changelog_home', repo_name=c.pull_request.target_repo.repo_name, branch=c.pull_request.target_ref_parts.name)}">${c.pull_request.target_ref_parts.type}: ${c.pull_request.target_ref_parts.name}</a>
111 111 %else:
112 112 ${c.pull_request.target_ref_parts.type}: ${c.pull_request.target_ref_parts.name}
113 113 %endif
114 114 </span>
115 115 <span class="clone-url">
116 116 <a href="${h.route_path('repo_summary', repo_name=c.pull_request.target_repo.repo_name)}">${c.pull_request.target_repo.clone_url()}</a>
117 117 </span>
118 118 </div>
119 119 </div>
120 120 </div>
121 121
122 122 ## Link to the shadow repository.
123 123 <div class="field">
124 124 <div class="label-summary">
125 125 <label>${_('Merge')}:</label>
126 126 </div>
127 127 <div class="input">
128 128 % if not c.pull_request.is_closed() and c.pull_request.shadow_merge_ref:
129 129 <div class="pr-mergeinfo">
130 130 %if h.is_hg(c.pull_request.target_repo):
131 131 <input type="text" class="input-monospace" value="hg clone -u ${c.pull_request.shadow_merge_ref.name} ${c.shadow_clone_url} pull-request-${c.pull_request.pull_request_id}" readonly="readonly">
132 132 %elif h.is_git(c.pull_request.target_repo):
133 133 <input type="text" class="input-monospace" value="git clone --branch ${c.pull_request.shadow_merge_ref.name} ${c.shadow_clone_url} pull-request-${c.pull_request.pull_request_id}" readonly="readonly">
134 134 %endif
135 135 </div>
136 136 % else:
137 137 <div class="">
138 138 ${_('Shadow repository data not available')}.
139 139 </div>
140 140 % endif
141 141 </div>
142 142 </div>
143 143
144 144 <div class="field">
145 145 <div class="label-summary">
146 146 <label>${_('Review')}:</label>
147 147 </div>
148 148 <div class="input">
149 149 %if c.pull_request_review_status:
150 150 <div class="${'flag_status %s' % c.pull_request_review_status} tooltip pull-left"></div>
151 151 <span class="changeset-status-lbl tooltip">
152 152 %if c.pull_request.is_closed():
153 153 ${_('Closed')},
154 154 %endif
155 155 ${h.commit_status_lbl(c.pull_request_review_status)}
156 156 </span>
157 157 - ${ungettext('calculated based on %s reviewer vote', 'calculated based on %s reviewers votes', len(c.pull_request_reviewers)) % len(c.pull_request_reviewers)}
158 158 %endif
159 159 </div>
160 160 </div>
161 161 <div class="field">
162 162 <div class="pr-description-label label-summary">
163 163 <label>${_('Description')}:</label>
164 164 </div>
165 165 <div id="pr-desc" class="input">
166 166 <div class="pr-description">${h.urlify_commit_message(c.pull_request.description, c.repo_name)}</div>
167 167 </div>
168 168 <div id="pr-desc-edit" class="input textarea editor" style="display: none;">
169 169 <textarea id="pr-description-input" size="30">${c.pull_request.description}</textarea>
170 170 </div>
171 171 </div>
172 172
173 173 <div class="field">
174 174 <div class="label-summary">
175 175 <label>${_('Versions')}:</label>
176 176 </div>
177 177
178 178 <% outdated_comm_count_ver = len(c.inline_versions[None]['outdated']) %>
179 179 <% general_outdated_comm_count_ver = len(c.comment_versions[None]['outdated']) %>
180 180
181 181 <div class="pr-versions">
182 182 % if c.show_version_changes:
183 183 <% outdated_comm_count_ver = len(c.inline_versions[c.at_version_num]['outdated']) %>
184 184 <% general_outdated_comm_count_ver = len(c.comment_versions[c.at_version_num]['outdated']) %>
185 185 <a id="show-pr-versions" class="input" onclick="return versionController.toggleVersionView(this)" href="#show-pr-versions"
186 186 data-toggle-on="${ungettext('{} version available for this pull request, show it.', '{} versions available for this pull request, show them.', len(c.versions)).format(len(c.versions))}"
187 187 data-toggle-off="${_('Hide all versions of this pull request')}">
188 188 ${ungettext('{} version available for this pull request, show it.', '{} versions available for this pull request, show them.', len(c.versions)).format(len(c.versions))}
189 189 </a>
190 190 <table>
191 191 ## SHOW ALL VERSIONS OF PR
192 192 <% ver_pr = None %>
193 193
194 194 % for data in reversed(list(enumerate(c.versions, 1))):
195 195 <% ver_pos = data[0] %>
196 196 <% ver = data[1] %>
197 197 <% ver_pr = ver.pull_request_version_id %>
198 198 <% display_row = '' if c.at_version and (c.at_version_num == ver_pr or c.from_version_num == ver_pr) else 'none' %>
199 199
200 200 <tr class="version-pr" style="display: ${display_row}">
201 201 <td>
202 202 <code>
203 203 <a href="${h.url.current(version=ver_pr or 'latest')}">v${ver_pos}</a>
204 204 </code>
205 205 </td>
206 206 <td>
207 207 <input ${'checked="checked"' if c.from_version_num == ver_pr else ''} class="compare-radio-button" type="radio" name="ver_source" value="${ver_pr or 'latest'}" data-ver-pos="${ver_pos}"/>
208 208 <input ${'checked="checked"' if c.at_version_num == ver_pr else ''} class="compare-radio-button" type="radio" name="ver_target" value="${ver_pr or 'latest'}" data-ver-pos="${ver_pos}"/>
209 209 </td>
210 210 <td>
211 211 <% review_status = c.review_versions[ver_pr].status if ver_pr in c.review_versions else 'not_reviewed' %>
212 212 <div class="${'flag_status %s' % review_status} tooltip pull-left" title="${_('Your review status at this version')}">
213 213 </div>
214 214 </td>
215 215 <td>
216 216 % if c.at_version_num != ver_pr:
217 217 <i class="icon-comment"></i>
218 218 <code class="tooltip" title="${_('Comment from pull request version {0}, general:{1} inline:{2}').format(ver_pos, len(c.comment_versions[ver_pr]['at']), len(c.inline_versions[ver_pr]['at']))}">
219 219 G:${len(c.comment_versions[ver_pr]['at'])} / I:${len(c.inline_versions[ver_pr]['at'])}
220 220 </code>
221 221 % endif
222 222 </td>
223 223 <td>
224 224 ##<code>${ver.source_ref_parts.commit_id[:6]}</code>
225 225 </td>
226 226 <td>
227 227 ${h.age_component(ver.updated_on, time_is_local=True)}
228 228 </td>
229 229 </tr>
230 230 % endfor
231 231
232 232 <tr>
233 233 <td colspan="6">
234 234 <button id="show-version-diff" onclick="return versionController.showVersionDiff()" class="btn btn-sm" style="display: none"
235 235 data-label-text-locked="${_('select versions to show changes')}"
236 236 data-label-text-diff="${_('show changes between versions')}"
237 237 data-label-text-show="${_('show pull request for this version')}"
238 238 >
239 239 ${_('select versions to show changes')}
240 240 </button>
241 241 </td>
242 242 </tr>
243 243
244 244 ## show comment/inline comments summary
245 245 <%def name="comments_summary()">
246 246 <tr>
247 247 <td colspan="6" class="comments-summary-td">
248 248
249 249 % if c.at_version:
250 250 <% inline_comm_count_ver = len(c.inline_versions[c.at_version_num]['display']) %>
251 251 <% general_comm_count_ver = len(c.comment_versions[c.at_version_num]['display']) %>
252 252 ${_('Comments at this version')}:
253 253 % else:
254 254 <% inline_comm_count_ver = len(c.inline_versions[c.at_version_num]['until']) %>
255 255 <% general_comm_count_ver = len(c.comment_versions[c.at_version_num]['until']) %>
256 256 ${_('Comments for this pull request')}:
257 257 % endif
258 258
259 259
260 260 %if general_comm_count_ver:
261 261 <a href="#comments">${_("%d General ") % general_comm_count_ver}</a>
262 262 %else:
263 263 ${_("%d General ") % general_comm_count_ver}
264 264 %endif
265 265
266 266 %if inline_comm_count_ver:
267 267 , <a href="#" onclick="return Rhodecode.comments.nextComment();" id="inline-comments-counter">${_("%d Inline") % inline_comm_count_ver}</a>
268 268 %else:
269 269 , ${_("%d Inline") % inline_comm_count_ver}
270 270 %endif
271 271
272 272 %if outdated_comm_count_ver:
273 273 , <a href="#" onclick="showOutdated(); Rhodecode.comments.nextOutdatedComment(); return false;">${_("%d Outdated") % outdated_comm_count_ver}</a>
274 274 <a href="#" class="showOutdatedComments" onclick="showOutdated(this); return false;"> | ${_('show outdated comments')}</a>
275 275 <a href="#" class="hideOutdatedComments" style="display: none" onclick="hideOutdated(this); return false;"> | ${_('hide outdated comments')}</a>
276 276 %else:
277 277 , ${_("%d Outdated") % outdated_comm_count_ver}
278 278 %endif
279 279 </td>
280 280 </tr>
281 281 </%def>
282 282 ${comments_summary()}
283 283 </table>
284 284 % else:
285 285 <div class="input">
286 286 ${_('Pull request versions not available')}.
287 287 </div>
288 288 <div>
289 289 <table>
290 290 ${comments_summary()}
291 291 </table>
292 292 </div>
293 293 % endif
294 294 </div>
295 295 </div>
296 296
297 297 <div id="pr-save" class="field" style="display: none;">
298 298 <div class="label-summary"></div>
299 299 <div class="input">
300 300 <span id="edit_pull_request" class="btn btn-small no-margin">${_('Save Changes')}</span>
301 301 </div>
302 302 </div>
303 303 </div>
304 304 </div>
305 305 <div>
306 306 ## AUTHOR
307 307 <div class="reviewers-title block-right">
308 308 <div class="pr-details-title">
309 309 ${_('Author of this pull request')}
310 310 </div>
311 311 </div>
312 312 <div class="block-right pr-details-content reviewers">
313 313 <ul class="group_members">
314 314 <li>
315 315 ${self.gravatar_with_user(c.pull_request.author.email, 16)}
316 316 </li>
317 317 </ul>
318 318 </div>
319 319
320 320 ## REVIEW RULES
321 321 <div id="review_rules" style="display: none" class="reviewers-title block-right">
322 322 <div class="pr-details-title">
323 323 ${_('Reviewer rules')}
324 324 %if c.allowed_to_update:
325 325 <span id="close_edit_reviewers" class="block-right action_button last-item" style="display: none;">${_('Close')}</span>
326 326 %endif
327 327 </div>
328 328 <div class="pr-reviewer-rules">
329 329 ## review rules will be appended here, by default reviewers logic
330 330 </div>
331 331 <input id="review_data" type="hidden" name="review_data" value="">
332 332 </div>
333 333
334 334 ## REVIEWERS
335 335 <div class="reviewers-title block-right">
336 336 <div class="pr-details-title">
337 337 ${_('Pull request reviewers')}
338 338 %if c.allowed_to_update:
339 339 <span id="open_edit_reviewers" class="block-right action_button last-item">${_('Edit')}</span>
340 340 %endif
341 341 </div>
342 342 </div>
343 343 <div id="reviewers" class="block-right pr-details-content reviewers">
344 344 ## members goes here !
345 345 <input type="hidden" name="__start__" value="review_members:sequence">
346 346 <ul id="review_members" class="group_members">
347 347 %for member,reasons,mandatory,status in c.pull_request_reviewers:
348 348 <li id="reviewer_${member.user_id}" class="reviewer_entry">
349 349 <div class="reviewers_member">
350 350 <div class="reviewer_status tooltip" title="${h.tooltip(h.commit_status_lbl(status[0][1].status if status else 'not_reviewed'))}">
351 351 <div class="${'flag_status %s' % (status[0][1].status if status else 'not_reviewed')} pull-left reviewer_member_status"></div>
352 352 </div>
353 353 <div id="reviewer_${member.user_id}_name" class="reviewer_name">
354 354 ${self.gravatar_with_user(member.email, 16)}
355 355 </div>
356 356 <input type="hidden" name="__start__" value="reviewer:mapping">
357 357 <input type="hidden" name="__start__" value="reasons:sequence">
358 358 %for reason in reasons:
359 359 <div class="reviewer_reason">- ${reason}</div>
360 360 <input type="hidden" name="reason" value="${reason}">
361 361
362 362 %endfor
363 363 <input type="hidden" name="__end__" value="reasons:sequence">
364 364 <input id="reviewer_${member.user_id}_input" type="hidden" value="${member.user_id}" name="user_id" />
365 365 <input type="hidden" name="mandatory" value="${mandatory}"/>
366 366 <input type="hidden" name="__end__" value="reviewer:mapping">
367 367 % if mandatory:
368 368 <div class="reviewer_member_mandatory_remove">
369 369 <i class="icon-remove-sign"></i>
370 370 </div>
371 371 <div class="reviewer_member_mandatory">
372 372 <i class="icon-lock" title="${h.tooltip(_('Mandatory reviewer'))}"></i>
373 373 </div>
374 374 % else:
375 375 %if c.allowed_to_update:
376 376 <div class="reviewer_member_remove action_button" onclick="reviewersController.removeReviewMember(${member.user_id}, true)" style="visibility: hidden;">
377 377 <i class="icon-remove-sign" ></i>
378 378 </div>
379 379 %endif
380 380 % endif
381 381 </div>
382 382 </li>
383 383 %endfor
384 384 </ul>
385 385 <input type="hidden" name="__end__" value="review_members:sequence">
386 386
387 387 %if not c.pull_request.is_closed():
388 388 <div id="add_reviewer" class="ac" style="display: none;">
389 389 %if c.allowed_to_update:
390 390 % if not c.forbid_adding_reviewers:
391 391 <div id="add_reviewer_input" class="reviewer_ac">
392 392 ${h.text('user', class_='ac-input', placeholder=_('Add reviewer or reviewer group'))}
393 393 <div id="reviewers_container"></div>
394 394 </div>
395 395 % endif
396 396 <div class="pull-right">
397 397 <button id="update_pull_request" class="btn btn-small no-margin">${_('Save Changes')}</button>
398 398 </div>
399 399 %endif
400 400 </div>
401 401 %endif
402 402 </div>
403 403 </div>
404 404 </div>
405 405 <div class="box">
406 406 ##DIFF
407 407 <div class="table" >
408 408 <div id="changeset_compare_view_content">
409 409 ##CS
410 410 % if c.missing_requirements:
411 411 <div class="box">
412 412 <div class="alert alert-warning">
413 413 <div>
414 414 <strong>${_('Missing requirements:')}</strong>
415 415 ${_('These commits cannot be displayed, because this repository uses the Mercurial largefiles extension, which was not enabled.')}
416 416 </div>
417 417 </div>
418 418 </div>
419 419 % elif c.missing_commits:
420 420 <div class="box">
421 421 <div class="alert alert-warning">
422 422 <div>
423 423 <strong>${_('Missing commits')}:</strong>
424 424 ${_('This pull request cannot be displayed, because one or more commits no longer exist in the source repository.')}
425 425 ${_('Please update this pull request, push the commits back into the source repository, or consider closing this pull request.')}
426 426 </div>
427 427 </div>
428 428 </div>
429 429 % endif
430 430
431 431 <div class="compare_view_commits_title">
432 432 % if not c.compare_mode:
433 433
434 434 % if c.at_version_pos:
435 435 <h4>
436 436 ${_('Showing changes at v%d, commenting is disabled.') % c.at_version_pos}
437 437 </h4>
438 438 % endif
439 439
440 440 <div class="pull-left">
441 441 <div class="btn-group">
442 442 <a
443 443 class="btn"
444 444 href="#"
445 445 onclick="$('.compare_select').show();$('.compare_select_hidden').hide(); return false">
446 446 ${ungettext('Expand %s commit','Expand %s commits', len(c.commit_ranges)) % len(c.commit_ranges)}
447 447 </a>
448 448 <a
449 449 class="btn"
450 450 href="#"
451 451 onclick="$('.compare_select').hide();$('.compare_select_hidden').show(); return false">
452 452 ${ungettext('Collapse %s commit','Collapse %s commits', len(c.commit_ranges)) % len(c.commit_ranges)}
453 453 </a>
454 454 </div>
455 455 </div>
456 456
457 457 <div class="pull-right">
458 458 % if c.allowed_to_update and not c.pull_request.is_closed():
459 459 <a id="update_commits" class="btn btn-primary no-margin pull-right">${_('Update commits')}</a>
460 460 % else:
461 461 <a class="tooltip btn disabled pull-right" disabled="disabled" title="${_('Update is disabled for current view')}">${_('Update commits')}</a>
462 462 % endif
463 463
464 464 </div>
465 465 % endif
466 466 </div>
467 467
468 468 % if not c.missing_commits:
469 469 % if c.compare_mode:
470 470 % if c.at_version:
471 471 <h4>
472 472 ${_('Commits and changes between v{ver_from} and {ver_to} of this pull request, commenting is disabled').format(ver_from=c.from_version_pos, ver_to=c.at_version_pos if c.at_version_pos else 'latest')}:
473 473 </h4>
474 474
475 475 <div class="subtitle-compare">
476 476 ${_('commits added: {}, removed: {}').format(len(c.commit_changes_summary.added), len(c.commit_changes_summary.removed))}
477 477 </div>
478 478
479 479 <div class="container">
480 480 <table class="rctable compare_view_commits">
481 481 <tr>
482 482 <th></th>
483 483 <th>${_('Time')}</th>
484 484 <th>${_('Author')}</th>
485 485 <th>${_('Commit')}</th>
486 486 <th></th>
487 487 <th>${_('Description')}</th>
488 488 </tr>
489 489
490 490 % for c_type, commit in c.commit_changes:
491 491 % if c_type in ['a', 'r']:
492 492 <%
493 493 if c_type == 'a':
494 494 cc_title = _('Commit added in displayed changes')
495 495 elif c_type == 'r':
496 496 cc_title = _('Commit removed in displayed changes')
497 497 else:
498 498 cc_title = ''
499 499 %>
500 500 <tr id="row-${commit.raw_id}" commit_id="${commit.raw_id}" class="compare_select">
501 501 <td>
502 502 <div class="commit-change-indicator color-${c_type}-border">
503 503 <div class="commit-change-content color-${c_type} tooltip" title="${h.tooltip(cc_title)}">
504 504 ${c_type.upper()}
505 505 </div>
506 506 </div>
507 507 </td>
508 508 <td class="td-time">
509 509 ${h.age_component(commit.date)}
510 510 </td>
511 511 <td class="td-user">
512 512 ${base.gravatar_with_user(commit.author, 16)}
513 513 </td>
514 514 <td class="td-hash">
515 515 <code>
516 516 <a href="${h.url('changeset_home', repo_name=c.target_repo.repo_name, revision=commit.raw_id)}">
517 517 r${commit.revision}:${h.short_id(commit.raw_id)}
518 518 </a>
519 519 ${h.hidden('revisions', commit.raw_id)}
520 520 </code>
521 521 </td>
522 522 <td class="expand_commit" data-commit-id="${commit.raw_id}" title="${_( 'Expand commit message')}">
523 523 <div class="show_more_col">
524 524 <i class="show_more"></i>
525 525 </div>
526 526 </td>
527 527 <td class="mid td-description">
528 528 <div class="log-container truncate-wrap">
529 529 <div class="message truncate" id="c-${commit.raw_id}" data-message-raw="${commit.message}">
530 530 ${h.urlify_commit_message(commit.message, c.repo_name)}
531 531 </div>
532 532 </div>
533 533 </td>
534 534 </tr>
535 535 % endif
536 536 % endfor
537 537 </table>
538 538 </div>
539 539
540 540 <script>
541 541 $('.expand_commit').on('click',function(e){
542 542 var target_expand = $(this);
543 543 var cid = target_expand.data('commitId');
544 544
545 545 if (target_expand.hasClass('open')){
546 546 $('#c-'+cid).css({
547 547 'height': '1.5em',
548 548 'white-space': 'nowrap',
549 549 'text-overflow': 'ellipsis',
550 550 'overflow':'hidden'
551 551 });
552 552 target_expand.removeClass('open');
553 553 }
554 554 else {
555 555 $('#c-'+cid).css({
556 556 'height': 'auto',
557 557 'white-space': 'pre-line',
558 558 'text-overflow': 'initial',
559 559 'overflow':'visible'
560 560 });
561 561 target_expand.addClass('open');
562 562 }
563 563 });
564 564 </script>
565 565
566 566 % endif
567 567
568 568 % else:
569 569 <%include file="/compare/compare_commits.mako" />
570 570 % endif
571 571
572 572 <div class="cs_files">
573 573 <%namespace name="cbdiffs" file="/codeblocks/diffs.mako"/>
574 574 ${cbdiffs.render_diffset_menu()}
575 575 ${cbdiffs.render_diffset(
576 576 c.diffset, use_comments=True,
577 577 collapse_when_files_over=30,
578 578 disable_new_comments=not c.allowed_to_comment,
579 579 deleted_files_comments=c.deleted_files_comments)}
580 580 </div>
581 581 % else:
582 582 ## skipping commits we need to clear the view for missing commits
583 583 <div style="clear:both;"></div>
584 584 % endif
585 585
586 586 </div>
587 587 </div>
588 588
589 589 ## template for inline comment form
590 590 <%namespace name="comment" file="/changeset/changeset_file_comment.mako"/>
591 591
592 592 ## render general comments
593 593
594 594 <div id="comment-tr-show">
595 595 <div class="comment">
596 596 % if general_outdated_comm_count_ver:
597 597 <div class="meta">
598 598 % if general_outdated_comm_count_ver == 1:
599 599 ${_('there is {num} general comment from older versions').format(num=general_outdated_comm_count_ver)},
600 600 <a href="#show-hidden-comments" onclick="$('.comment-general.comment-outdated').show(); $(this).parent().hide(); return false;">${_('show it')}</a>
601 601 % else:
602 602 ${_('there are {num} general comments from older versions').format(num=general_outdated_comm_count_ver)},
603 603 <a href="#show-hidden-comments" onclick="$('.comment-general.comment-outdated').show(); $(this).parent().hide(); return false;">${_('show them')}</a>
604 604 % endif
605 605 </div>
606 606 % endif
607 607 </div>
608 608 </div>
609 609
610 610 ${comment.generate_comments(c.comments, include_pull_request=True, is_pull_request=True)}
611 611
612 612 % if not c.pull_request.is_closed():
613 613 ## merge status, and merge action
614 614 <div class="pull-request-merge">
615 615 <%include file="/pullrequests/pullrequest_merge_checks.mako"/>
616 616 </div>
617 617
618 618 ## main comment form and it status
619 619 ${comment.comments(h.url('pullrequest_comment', repo_name=c.repo_name,
620 620 pull_request_id=c.pull_request.pull_request_id),
621 621 c.pull_request_review_status,
622 622 is_pull_request=True, change_status=c.allowed_to_change_status)}
623 623 %endif
624 624
625 625 <script type="text/javascript">
626 626 if (location.hash) {
627 627 var result = splitDelimitedHash(location.hash);
628 628 var line = $('html').find(result.loc);
629 629 // show hidden comments if we use location.hash
630 630 if (line.hasClass('comment-general')) {
631 631 $(line).show();
632 632 } else if (line.hasClass('comment-inline')) {
633 633 $(line).show();
634 634 var $cb = $(line).closest('.cb');
635 635 $cb.removeClass('cb-collapsed')
636 636 }
637 637 if (line.length > 0){
638 638 offsetScroll(line, 70);
639 639 }
640 640 }
641 641
642 642 versionController = new VersionController();
643 643 versionController.init();
644 644
645 645 reviewersController = new ReviewersController();
646 646
647 647 $(function(){
648 648
649 649 // custom code mirror
650 650 var codeMirrorInstance = initPullRequestsCodeMirror('#pr-description-input');
651 651
652 652 var PRDetails = {
653 653 editButton: $('#open_edit_pullrequest'),
654 654 closeButton: $('#close_edit_pullrequest'),
655 655 deleteButton: $('#delete_pullrequest'),
656 656 viewFields: $('#pr-desc, #pr-title'),
657 657 editFields: $('#pr-desc-edit, #pr-title-edit, #pr-save'),
658 658
659 659 init: function() {
660 660 var that = this;
661 661 this.editButton.on('click', function(e) { that.edit(); });
662 662 this.closeButton.on('click', function(e) { that.view(); });
663 663 },
664 664
665 665 edit: function(event) {
666 666 this.viewFields.hide();
667 667 this.editButton.hide();
668 668 this.deleteButton.hide();
669 669 this.closeButton.show();
670 670 this.editFields.show();
671 671 codeMirrorInstance.refresh();
672 672 },
673 673
674 674 view: function(event) {
675 675 this.editButton.show();
676 676 this.deleteButton.show();
677 677 this.editFields.hide();
678 678 this.closeButton.hide();
679 679 this.viewFields.show();
680 680 }
681 681 };
682 682
683 683 var ReviewersPanel = {
684 684 editButton: $('#open_edit_reviewers'),
685 685 closeButton: $('#close_edit_reviewers'),
686 686 addButton: $('#add_reviewer'),
687 687 removeButtons: $('.reviewer_member_remove,.reviewer_member_mandatory_remove,.reviewer_member_mandatory'),
688 688
689 689 init: function() {
690 690 var self = this;
691 691 this.editButton.on('click', function(e) { self.edit(); });
692 692 this.closeButton.on('click', function(e) { self.close(); });
693 693 },
694 694
695 695 edit: function(event) {
696 696 this.editButton.hide();
697 697 this.closeButton.show();
698 698 this.addButton.show();
699 699 this.removeButtons.css('visibility', 'visible');
700 700 // review rules
701 701 reviewersController.loadReviewRules(
702 702 ${c.pull_request.reviewer_data_json | n});
703 703 },
704 704
705 705 close: function(event) {
706 706 this.editButton.show();
707 707 this.closeButton.hide();
708 708 this.addButton.hide();
709 709 this.removeButtons.css('visibility', 'hidden');
710 710 // hide review rules
711 711 reviewersController.hideReviewRules()
712 712 }
713 713 };
714 714
715 715 PRDetails.init();
716 716 ReviewersPanel.init();
717 717
718 718 showOutdated = function(self){
719 719 $('.comment-inline.comment-outdated').show();
720 720 $('.filediff-outdated').show();
721 721 $('.showOutdatedComments').hide();
722 722 $('.hideOutdatedComments').show();
723 723 };
724 724
725 725 hideOutdated = function(self){
726 726 $('.comment-inline.comment-outdated').hide();
727 727 $('.filediff-outdated').hide();
728 728 $('.hideOutdatedComments').hide();
729 729 $('.showOutdatedComments').show();
730 730 };
731 731
732 732 refreshMergeChecks = function(){
733 733 var loadUrl = "${h.url.current(merge_checks=1)}";
734 734 $('.pull-request-merge').css('opacity', 0.3);
735 735 $('.action-buttons-extra').css('opacity', 0.3);
736 736
737 737 $('.pull-request-merge').load(
738 738 loadUrl, function() {
739 739 $('.pull-request-merge').css('opacity', 1);
740 740
741 741 $('.action-buttons-extra').css('opacity', 1);
742 742 injectCloseAction();
743 743 }
744 744 );
745 745 };
746 746
747 747 injectCloseAction = function() {
748 748 var closeAction = $('#close-pull-request-action').html();
749 749 var $actionButtons = $('.action-buttons-extra');
750 750 // clear the action before
751 751 $actionButtons.html("");
752 752 $actionButtons.html(closeAction);
753 753 };
754 754
755 755 closePullRequest = function (status) {
756 756 // inject closing flag
757 757 $('.action-buttons-extra').append('<input type="hidden" class="close-pr-input" id="close_pull_request" value="1">');
758 758 $(generalCommentForm.statusChange).select2("val", status).trigger('change');
759 759 $(generalCommentForm.submitForm).submit();
760 760 };
761 761
762 762 $('#show-outdated-comments').on('click', function(e){
763 763 var button = $(this);
764 764 var outdated = $('.comment-outdated');
765 765
766 766 if (button.html() === "(Show)") {
767 767 button.html("(Hide)");
768 768 outdated.show();
769 769 } else {
770 770 button.html("(Show)");
771 771 outdated.hide();
772 772 }
773 773 });
774 774
775 775 $('.show-inline-comments').on('change', function(e){
776 776 var show = 'none';
777 777 var target = e.currentTarget;
778 778 if(target.checked){
779 779 show = ''
780 780 }
781 781 var boxid = $(target).attr('id_for');
782 782 var comments = $('#{0} .inline-comments'.format(boxid));
783 783 var fn_display = function(idx){
784 784 $(this).css('display', show);
785 785 };
786 786 $(comments).each(fn_display);
787 787 var btns = $('#{0} .inline-comments-button'.format(boxid));
788 788 $(btns).each(fn_display);
789 789 });
790 790
791 791 $('#merge_pull_request_form').submit(function() {
792 792 if (!$('#merge_pull_request').attr('disabled')) {
793 793 $('#merge_pull_request').attr('disabled', 'disabled');
794 794 }
795 795 return true;
796 796 });
797 797
798 798 $('#edit_pull_request').on('click', function(e){
799 799 var title = $('#pr-title-input').val();
800 800 var description = codeMirrorInstance.getValue();
801 801 editPullRequest(
802 802 "${c.repo_name}", "${c.pull_request.pull_request_id}",
803 803 title, description);
804 804 });
805 805
806 806 $('#update_pull_request').on('click', function(e){
807 807 $(this).attr('disabled', 'disabled');
808 808 $(this).addClass('disabled');
809 809 $(this).html(_gettext('Saving...'));
810 810 reviewersController.updateReviewers(
811 811 "${c.repo_name}", "${c.pull_request.pull_request_id}");
812 812 });
813 813
814 814 $('#update_commits').on('click', function(e){
815 815 var isDisabled = !$(e.currentTarget).attr('disabled');
816 816 $(e.currentTarget).attr('disabled', 'disabled');
817 817 $(e.currentTarget).addClass('disabled');
818 818 $(e.currentTarget).removeClass('btn-primary');
819 819 $(e.currentTarget).text(_gettext('Updating...'));
820 820 if(isDisabled){
821 821 updateCommits(
822 822 "${c.repo_name}", "${c.pull_request.pull_request_id}");
823 823 }
824 824 });
825 825 // fixing issue with caches on firefox
826 826 $('#update_commits').removeAttr("disabled");
827 827
828 828 $('.show-inline-comments').on('click', function(e){
829 829 var boxid = $(this).attr('data-comment-id');
830 830 var button = $(this);
831 831
832 832 if(button.hasClass("comments-visible")) {
833 833 $('#{0} .inline-comments'.format(boxid)).each(function(index){
834 834 $(this).hide();
835 835 });
836 836 button.removeClass("comments-visible");
837 837 } else {
838 838 $('#{0} .inline-comments'.format(boxid)).each(function(index){
839 839 $(this).show();
840 840 });
841 841 button.addClass("comments-visible");
842 842 }
843 843 });
844 844
845 845 // register submit callback on commentForm form to track TODOs
846 846 window.commentFormGlobalSubmitSuccessCallback = function(){
847 847 refreshMergeChecks();
848 848 };
849 849 // initial injection
850 850 injectCloseAction();
851 851
852 852 ReviewerAutoComplete('#user');
853 853
854 854 })
855 855 </script>
856 856
857 857 </div>
858 858 </div>
859 859
860 860 </%def>
General Comments 0
You need to be logged in to leave comments. Login now