##// END OF EJS Templates
static: change static path to serve rhodecode static assets from...
marcink -
r522:3662eb25 default
parent child Browse files
Show More
@@ -1,33 +1,33 b''
1 1 Apache Reverse Proxy
2 2 ^^^^^^^^^^^^^^^^^^^^
3 3
4 4 Here is a sample configuration file for using Apache as a reverse proxy.
5 5
6 6 .. code-block:: apache
7 7
8 8 <VirtualHost *:80>
9 9 ServerName hg.myserver.com
10 10 ServerAlias hg.myserver.com
11 11
12 12 ## uncomment to serve static files by Apache
13 ## ProxyPass /_static !
14 ## Alias /_static /path/to/.rccontrol/enterprise-1/static
13 ## ProxyPass /_static/rhodecode !
14 ## Alias /_static/rhodecode /path/to/.rccontrol/enterprise-1/static
15 15
16 16 <Proxy *>
17 17 Order allow,deny
18 18 Allow from all
19 19 </Proxy>
20 20
21 21 ## Important !
22 22 ## Directive to properly generate url (clone url) for pylons
23 23 ProxyPreserveHost On
24 24
25 25 ## RhodeCode instance running
26 26 ProxyPass / http://127.0.0.1:10002/
27 27 ProxyPassReverse / http://127.0.0.1:10002/
28 28
29 29 ## to enable https use line below
30 30 #SetEnvIf X-Url-Scheme https HTTPS=1
31 31
32 32 </VirtualHost>
33 33
@@ -1,92 +1,92 b''
1 1 Nginx Configuration Example
2 2 ---------------------------
3 3
4 4 Use the following example to configure Nginx as a your web server.
5 5
6 6 .. code-block:: nginx
7 7
8 8 upstream rc {
9 9
10 10 server 127.0.0.1:10002;
11 11
12 12 # add more instances for load balancing
13 13 # server 127.0.0.1:10003;
14 14 # server 127.0.0.1:10004;
15 15 }
16 16
17 17 ## gist alias
18 18
19 19 server {
20 20 listen 443;
21 21 server_name gist.myserver.com;
22 22 access_log /var/log/nginx/gist.access.log;
23 23 error_log /var/log/nginx/gist.error.log;
24 24
25 25 ssl on;
26 26 ssl_certificate gist.rhodecode.myserver.com.crt;
27 27 ssl_certificate_key gist.rhodecode.myserver.com.key;
28 28
29 29 ssl_session_timeout 5m;
30 30
31 31 ssl_protocols SSLv3 TLSv1;
32 32 ssl_ciphers DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:EDH-RSA-DES-CBC3-SHA:AES256-SHA:DES-CBC3-SHA:AES128-SHA:RC4-SHA:RC4-MD5;
33 33 ssl_prefer_server_ciphers on;
34 34 add_header Strict-Transport-Security "max-age=31536000; includeSubdomains;";
35 35
36 36 # Diffie-Hellman parameter for DHE ciphersuites, recommended 2048 bits
37 37 ssl_dhparam /etc/nginx/ssl/dhparam.pem;
38 38
39 39 rewrite ^/(.+)$ https://rhodecode.myserver.com/_admin/gists/$1;
40 40 rewrite (.*) https://rhodecode.myserver.com/_admin/gists;
41 41 }
42 42
43 43 server {
44 44 listen 443;
45 45 server_name rhodecode.myserver.com;
46 46 access_log /var/log/nginx/rhodecode.access.log;
47 47 error_log /var/log/nginx/rhodecode.error.log;
48 48
49 49 ssl on;
50 50 ssl_certificate rhodecode.myserver.com.crt;
51 51 ssl_certificate_key rhodecode.myserver.com.key;
52 52
53 53 ssl_session_timeout 5m;
54 54
55 55 ssl_protocols SSLv3 TLSv1;
56 56 ssl_ciphers DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:EDH-RSA-DES-CBC3-SHA:AES256-SHA:DES-CBC3-SHA:AES128-SHA:RC4-SHA:RC4-MD5;
57 57 ssl_prefer_server_ciphers on;
58 58
59 59 include /etc/nginx/proxy.conf;
60 60
61 61 ## uncomment to serve static files by nginx
62 # location /_static {
62 # location /_static/rhodecode {
63 63 # alias /path/to/.rccontrol/enterprise-1/static;
64 64 # }
65 65
66 66 ## channel stream live components
67 67 location /_channelstream {
68 68 rewrite /_channelstream/(.*) /$1 break;
69 69 proxy_connect_timeout 10;
70 70 proxy_send_timeout 10m;
71 71 proxy_read_timeout 10m;
72 72 tcp_nodelay off;
73 73 proxy_pass http://127.0.0.1:9800;
74 74 proxy_set_header Host $host;
75 75 proxy_set_header X-Real-IP $remote_addr;
76 76 proxy_set_header X-Url-Scheme $scheme;
77 77 proxy_set_header X-Forwarded-Proto $scheme;
78 78 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
79 79 gzip off;
80 80 proxy_http_version 1.1;
81 81 proxy_set_header Upgrade $http_upgrade;
82 82 proxy_set_header Connection "upgrade";
83 83 }
84 84
85 85 location / {
86 86 try_files $uri @rhode;
87 87 }
88 88
89 89 location @rhode {
90 90 proxy_pass http://rc;
91 91 }
92 92 }
@@ -1,395 +1,395 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2010-2016 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
21 21 """
22 22 Pylons middleware initialization
23 23 """
24 24 import logging
25 25
26 26 from paste.registry import RegistryManager
27 27 from paste.gzipper import make_gzip_middleware
28 28 from pylons.wsgiapp import PylonsApp
29 29 from pyramid.authorization import ACLAuthorizationPolicy
30 30 from pyramid.config import Configurator
31 31 from pyramid.static import static_view
32 32 from pyramid.settings import asbool, aslist
33 33 from pyramid.wsgi import wsgiapp
34 34 from pyramid.httpexceptions import HTTPError, HTTPInternalServerError
35 35 from pylons.controllers.util import abort, redirect
36 36 import pyramid.httpexceptions as httpexceptions
37 37 from pyramid.renderers import render_to_response, render
38 38 from routes.middleware import RoutesMiddleware
39 39 import routes.util
40 40
41 41 import rhodecode
42 42 import rhodecode.integrations # do not remove this as it registers celery tasks
43 43 from rhodecode.config import patches
44 44 from rhodecode.config.routing import STATIC_FILE_PREFIX
45 45 from rhodecode.config.environment import (
46 46 load_environment, load_pyramid_environment)
47 47 from rhodecode.lib.middleware import csrf
48 48 from rhodecode.lib.middleware.appenlight import wrap_in_appenlight_if_enabled
49 49 from rhodecode.lib.middleware.disable_vcs import DisableVCSPagesWrapper
50 50 from rhodecode.lib.middleware.https_fixup import HttpsFixup
51 51 from rhodecode.lib.middleware.vcs import VCSMiddleware
52 52 from rhodecode.lib.plugins.utils import register_rhodecode_plugin
53 53
54 54
55 55 log = logging.getLogger(__name__)
56 56
57 57
58 58 # this is used to avoid avoid the route lookup overhead in routesmiddleware
59 59 # for certain routes which won't go to pylons to - eg. static files, debugger
60 60 # it is only needed for the pylons migration and can be removed once complete
61 61 class SkippableRoutesMiddleware(RoutesMiddleware):
62 62 """ Routes middleware that allows you to skip prefixes """
63 63
64 64 def __init__(self, *args, **kw):
65 65 self.skip_prefixes = kw.pop('skip_prefixes', [])
66 66 super(SkippableRoutesMiddleware, self).__init__(*args, **kw)
67 67
68 68 def __call__(self, environ, start_response):
69 69 for prefix in self.skip_prefixes:
70 70 if environ['PATH_INFO'].startswith(prefix):
71 71 return self.app(environ, start_response)
72 72
73 73 return super(SkippableRoutesMiddleware, self).__call__(
74 74 environ, start_response)
75 75
76 76
77 77 def make_app(global_conf, full_stack=True, static_files=True, **app_conf):
78 78 """Create a Pylons WSGI application and return it
79 79
80 80 ``global_conf``
81 81 The inherited configuration for this application. Normally from
82 82 the [DEFAULT] section of the Paste ini file.
83 83
84 84 ``full_stack``
85 85 Whether or not this application provides a full WSGI stack (by
86 86 default, meaning it handles its own exceptions and errors).
87 87 Disable full_stack when this application is "managed" by
88 88 another WSGI middleware.
89 89
90 90 ``app_conf``
91 91 The application's local configuration. Normally specified in
92 92 the [app:<name>] section of the Paste ini file (where <name>
93 93 defaults to main).
94 94
95 95 """
96 96 # Apply compatibility patches
97 97 patches.kombu_1_5_1_python_2_7_11()
98 98 patches.inspect_getargspec()
99 99
100 100 # Configure the Pylons environment
101 101 config = load_environment(global_conf, app_conf)
102 102
103 103 # The Pylons WSGI app
104 104 app = PylonsApp(config=config)
105 105 if rhodecode.is_test:
106 106 app = csrf.CSRFDetector(app)
107 107
108 108 expected_origin = config.get('expected_origin')
109 109 if expected_origin:
110 110 # The API can be accessed from other Origins.
111 111 app = csrf.OriginChecker(app, expected_origin,
112 112 skip_urls=[routes.util.url_for('api')])
113 113
114 114
115 115 if asbool(full_stack):
116 116
117 117 # Appenlight monitoring and error handler
118 118 app, appenlight_client = wrap_in_appenlight_if_enabled(app, config)
119 119
120 120 # we want our low level middleware to get to the request ASAP. We don't
121 121 # need any pylons stack middleware in them
122 122 app = VCSMiddleware(app, config, appenlight_client)
123 123
124 124 # Establish the Registry for this application
125 125 app = RegistryManager(app)
126 126
127 127 app.config = config
128 128
129 129 return app
130 130
131 131
132 132 def make_pyramid_app(global_config, **settings):
133 133 """
134 134 Constructs the WSGI application based on Pyramid and wraps the Pylons based
135 135 application.
136 136
137 137 Specials:
138 138
139 139 * We migrate from Pylons to Pyramid. While doing this, we keep both
140 140 frameworks functional. This involves moving some WSGI middlewares around
141 141 and providing access to some data internals, so that the old code is
142 142 still functional.
143 143
144 144 * The application can also be integrated like a plugin via the call to
145 145 `includeme`. This is accompanied with the other utility functions which
146 146 are called. Changing this should be done with great care to not break
147 147 cases when these fragments are assembled from another place.
148 148
149 149 """
150 150 # The edition string should be available in pylons too, so we add it here
151 151 # before copying the settings.
152 152 settings.setdefault('rhodecode.edition', 'Community Edition')
153 153
154 154 # As long as our Pylons application does expect "unprepared" settings, make
155 155 # sure that we keep an unmodified copy. This avoids unintentional change of
156 156 # behavior in the old application.
157 157 settings_pylons = settings.copy()
158 158
159 159 sanitize_settings_and_apply_defaults(settings)
160 160 config = Configurator(settings=settings)
161 161 add_pylons_compat_data(config.registry, global_config, settings_pylons)
162 162
163 163 load_pyramid_environment(global_config, settings)
164 164
165 165 includeme_first(config)
166 166 includeme(config)
167 167 pyramid_app = config.make_wsgi_app()
168 168 pyramid_app = wrap_app_in_wsgi_middlewares(pyramid_app, config)
169 169 return pyramid_app
170 170
171 171
172 172 def add_pylons_compat_data(registry, global_config, settings):
173 173 """
174 174 Attach data to the registry to support the Pylons integration.
175 175 """
176 176 registry._pylons_compat_global_config = global_config
177 177 registry._pylons_compat_settings = settings
178 178
179 179
180 180 def webob_to_pyramid_http_response(webob_response):
181 181 ResponseClass = httpexceptions.status_map[webob_response.status_int]
182 182 pyramid_response = ResponseClass(webob_response.status)
183 183 pyramid_response.status = webob_response.status
184 184 pyramid_response.headers.update(webob_response.headers)
185 185 if pyramid_response.headers['content-type'] == 'text/html':
186 186 pyramid_response.headers['content-type'] = 'text/html; charset=UTF-8'
187 187 return pyramid_response
188 188
189 189
190 190 def error_handler(exception, request):
191 191 # TODO: dan: replace the old pylons error controller with this
192 192 from rhodecode.model.settings import SettingsModel
193 193 from rhodecode.lib.utils2 import AttributeDict
194 194
195 195 try:
196 196 rc_config = SettingsModel().get_all_settings()
197 197 except Exception:
198 198 log.exception('failed to fetch settings')
199 199 rc_config = {}
200 200
201 201 base_response = HTTPInternalServerError()
202 202 # prefer original exception for the response since it may have headers set
203 203 if isinstance(exception, HTTPError):
204 204 base_response = exception
205 205
206 206 c = AttributeDict()
207 207 c.error_message = base_response.status
208 208 c.error_explanation = base_response.explanation or str(base_response)
209 209 c.visual = AttributeDict()
210 210
211 211 c.visual.rhodecode_support_url = (
212 212 request.registry.settings.get('rhodecode_support_url') or
213 213 request.route_url('rhodecode_support')
214 214 )
215 215 c.redirect_time = 0
216 216 c.rhodecode_name = rc_config.get('rhodecode_title', '')
217 217 if not c.rhodecode_name:
218 218 c.rhodecode_name = 'Rhodecode'
219 219
220 220 response = render_to_response(
221 221 '/errors/error_document.html', {'c': c}, request=request,
222 222 response=base_response)
223 223
224 224 return response
225 225
226 226
227 227 def includeme(config):
228 228 settings = config.registry.settings
229 229
230 230 # plugin information
231 231 config.registry.rhodecode_plugins = {}
232 232
233 233 config.add_directive(
234 234 'register_rhodecode_plugin', register_rhodecode_plugin)
235 235
236 236 if asbool(settings.get('appenlight', 'false')):
237 237 config.include('appenlight_client.ext.pyramid_tween')
238 238
239 239 # Includes which are required. The application would fail without them.
240 240 config.include('pyramid_mako')
241 241 config.include('pyramid_beaker')
242 242 config.include('rhodecode.admin')
243 243 config.include('rhodecode.authentication')
244 244 config.include('rhodecode.integrations')
245 245 config.include('rhodecode.login')
246 246 config.include('rhodecode.tweens')
247 247 config.include('rhodecode.api')
248 248 config.add_route(
249 249 'rhodecode_support', 'https://rhodecode.com/help/', static=True)
250 250
251 251 # Set the authorization policy.
252 252 authz_policy = ACLAuthorizationPolicy()
253 253 config.set_authorization_policy(authz_policy)
254 254
255 255 # Set the default renderer for HTML templates to mako.
256 256 config.add_mako_renderer('.html')
257 257
258 258 # include RhodeCode plugins
259 259 includes = aslist(settings.get('rhodecode.includes', []))
260 260 for inc in includes:
261 261 config.include(inc)
262 262
263 263 pylons_app = make_app(
264 264 config.registry._pylons_compat_global_config,
265 265 **config.registry._pylons_compat_settings)
266 266 config.registry._pylons_compat_config = pylons_app.config
267 267
268 268 pylons_app_as_view = wsgiapp(pylons_app)
269 269
270 270 # Protect from VCS Server error related pages when server is not available
271 271 vcs_server_enabled = asbool(settings.get('vcs.server.enable', 'true'))
272 272 if not vcs_server_enabled:
273 273 pylons_app_as_view = DisableVCSPagesWrapper(pylons_app_as_view)
274 274
275 275
276 276 def pylons_app_with_error_handler(context, request):
277 277 """
278 278 Handle exceptions from rc pylons app:
279 279
280 280 - old webob type exceptions get converted to pyramid exceptions
281 281 - pyramid exceptions are passed to the error handler view
282 282 """
283 283 try:
284 284 response = pylons_app_as_view(context, request)
285 285 if 400 <= response.status_int <= 599: # webob type error responses
286 286 return error_handler(
287 287 webob_to_pyramid_http_response(response), request)
288 288 except HTTPError as e: # pyramid type exceptions
289 289 return error_handler(e, request)
290 290 except Exception:
291 291 if settings.get('debugtoolbar.enabled', False):
292 292 raise
293 293 return error_handler(HTTPInternalServerError(), request)
294 294 return response
295 295
296 296 # This is the glue which allows us to migrate in chunks. By registering the
297 297 # pylons based application as the "Not Found" view in Pyramid, we will
298 298 # fallback to the old application each time the new one does not yet know
299 299 # how to handle a request.
300 300 config.add_notfound_view(pylons_app_with_error_handler)
301 301
302 302 if not settings.get('debugtoolbar.enabled', False):
303 303 # if no toolbar, then any exception gets caught and rendered
304 304 config.add_view(error_handler, context=Exception)
305 305
306 306 config.add_view(error_handler, context=HTTPError)
307 307
308 308
309 309 def includeme_first(config):
310 310 # redirect automatic browser favicon.ico requests to correct place
311 311 def favicon_redirect(context, request):
312 312 return redirect(
313 313 request.static_url('rhodecode:public/images/favicon.ico'))
314 314
315 315 config.add_view(favicon_redirect, route_name='favicon')
316 316 config.add_route('favicon', '/favicon.ico')
317 317
318 318 config.add_static_view(
319 319 '_static/deform', 'deform:static')
320 320 config.add_static_view(
321 '_static', path='rhodecode:public', cache_max_age=3600 * 24)
321 '_static/rhodecode', path='rhodecode:public', cache_max_age=3600 * 24)
322 322
323 323 def wrap_app_in_wsgi_middlewares(pyramid_app, config):
324 324 """
325 325 Apply outer WSGI middlewares around the application.
326 326
327 327 Part of this has been moved up from the Pylons layer, so that the
328 328 data is also available if old Pylons code is hit through an already ported
329 329 view.
330 330 """
331 331 settings = config.registry.settings
332 332
333 333 # enable https redirects based on HTTP_X_URL_SCHEME set by proxy
334 334 pyramid_app = HttpsFixup(pyramid_app, settings)
335 335
336 336 # Add RoutesMiddleware to support the pylons compatibility tween during
337 337 # migration to pyramid.
338 338 pyramid_app = SkippableRoutesMiddleware(
339 339 pyramid_app, config.registry._pylons_compat_config['routes.map'],
340 340 skip_prefixes=(STATIC_FILE_PREFIX, '/_debug_toolbar'))
341 341
342 342 if asbool(settings.get('appenlight', 'false')):
343 343 pyramid_app, _ = wrap_in_appenlight_if_enabled(
344 344 pyramid_app, config.registry._pylons_compat_config)
345 345
346 346 if asbool(settings.get('gzip_responses', 'true')):
347 347 pyramid_app = make_gzip_middleware(
348 348 pyramid_app, settings, compress_level=1)
349 349
350 350 return pyramid_app
351 351
352 352
353 353 def sanitize_settings_and_apply_defaults(settings):
354 354 """
355 355 Applies settings defaults and does all type conversion.
356 356
357 357 We would move all settings parsing and preparation into this place, so that
358 358 we have only one place left which deals with this part. The remaining parts
359 359 of the application would start to rely fully on well prepared settings.
360 360
361 361 This piece would later be split up per topic to avoid a big fat monster
362 362 function.
363 363 """
364 364
365 365 # Pyramid's mako renderer has to search in the templates folder so that the
366 366 # old templates still work. Ported and new templates are expected to use
367 367 # real asset specifications for the includes.
368 368 mako_directories = settings.setdefault('mako.directories', [
369 369 # Base templates of the original Pylons application
370 370 'rhodecode:templates',
371 371 ])
372 372 log.debug(
373 373 "Using the following Mako template directories: %s",
374 374 mako_directories)
375 375
376 376 # Default includes, possible to change as a user
377 377 pyramid_includes = settings.setdefault('pyramid.includes', [
378 378 'rhodecode.lib.middleware.request_wrapper',
379 379 ])
380 380 log.debug(
381 381 "Using the following pyramid.includes: %s",
382 382 pyramid_includes)
383 383
384 384 # TODO: johbo: Re-think this, usually the call to config.include
385 385 # should allow to pass in a prefix.
386 386 settings.setdefault('rhodecode.api.url', '/_admin/api')
387 387
388 388 _bool_setting(settings, 'vcs.server.enable', 'true')
389 389 _bool_setting(settings, 'is_test', 'false')
390 390
391 391 return settings
392 392
393 393
394 394 def _bool_setting(settings, name, default):
395 395 settings[name] = asbool(settings.get(name, default))
@@ -1,235 +1,235 b''
1 1 // # Copyright (C) 2010-2016 RhodeCode GmbH
2 2 // #
3 3 // # This program is free software: you can redistribute it and/or modify
4 4 // # it under the terms of the GNU Affero General Public License, version 3
5 5 // # (only), as published by the Free Software Foundation.
6 6 // #
7 7 // # This program is distributed in the hope that it will be useful,
8 8 // # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 9 // # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 10 // # GNU General Public License for more details.
11 11 // #
12 12 // # You should have received a copy of the GNU Affero General Public License
13 13 // # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 14 // #
15 15 // # This program is dual-licensed. If you wish to learn more about the
16 16 // # RhodeCode Enterprise Edition, including its added features, Support services,
17 17 // # and proprietary license terms, please see https://rhodecode.com/licenses/
18 18
19 19 /**
20 20 * Object holding the registered pyroutes.
21 21 * Routes will be registered with the generated script
22 22 * rhodecode/public/js/rhodecode/base/pyroutes.js
23 23 */
24 24 var PROUTES_MAP = {};
25 25
26 26 /**
27 27 * PyRoutesJS
28 28 *
29 29 * Usage pyroutes.url('mark_error_fixed',{"error_id":error_id}) // /mark_error_fixed/<error_id>
30 30 */
31 31 var pyroutes = (function() {
32 32 // access global map defined in special file pyroutes
33 33 var matchlist = PROUTES_MAP;
34 34 var sprintf = (function() {
35 35 function get_type(variable) {
36 36 return Object.prototype.toString.call(variable).slice(8, -1).toLowerCase();
37 37 }
38 38 function str_repeat(input, multiplier) {
39 39 for (var output = []; multiplier > 0; output[--multiplier] = input) {
40 40 /* do nothing */
41 41 }
42 42 return output.join('');
43 43 }
44 44 var str_format = function() {
45 45 if (!str_format.cache.hasOwnProperty(arguments[0])) {
46 46 str_format.cache[arguments[0]] = str_format.parse(arguments[0]);
47 47 }
48 48 return str_format.format.call(null, str_format.cache[arguments[0]], arguments);
49 49 };
50 50
51 51 str_format.format = function(parse_tree, argv) {
52 52 var cursor = 1,
53 53 tree_length = parse_tree.length,
54 54 node_type = '',
55 55 arg,
56 56 output = [],
57 57 i, k,
58 58 match,
59 59 pad,
60 60 pad_character,
61 61 pad_length;
62 62 for (i = 0; i < tree_length; i++) {
63 63 node_type = get_type(parse_tree[i]);
64 64 if (node_type === 'string') {
65 65 output.push(parse_tree[i]);
66 66 }
67 67 else if (node_type === 'array') {
68 68 match = parse_tree[i]; // convenience purposes only
69 69 if (match[2]) { // keyword argument
70 70 arg = argv[cursor];
71 71 for (k = 0; k < match[2].length; k++) {
72 72 if (!arg.hasOwnProperty(match[2][k])) {
73 73 throw(sprintf('[sprintf] property "%s" does not exist', match[2][k]));
74 74 }
75 75 arg = arg[match[2][k]];
76 76 }
77 77 }
78 78 else if (match[1]) { // positional argument (explicit)
79 79 arg = argv[match[1]];
80 80 }
81 81 else { // positional argument (implicit)
82 82 arg = argv[cursor++];
83 83 }
84 84
85 85 if (/[^s]/.test(match[8]) && (get_type(arg) !== 'number')) {
86 86 throw(sprintf('[sprintf] expecting number but found %s', get_type(arg)));
87 87 }
88 88 switch (match[8]) {
89 89 case 'b': arg = arg.toString(2); break;
90 90 case 'c': arg = String.fromCharCode(arg); break;
91 91 case 'd': arg = parseInt(arg, 10); break;
92 92 case 'e': arg = match[7] ? arg.toExponential(match[7]) : arg.toExponential(); break;
93 93 case 'f': arg = match[7] ? parseFloat(arg).toFixed(match[7]) : parseFloat(arg); break;
94 94 case 'o': arg = arg.toString(8); break;
95 95 case 's': arg = ((arg = String(arg)) && match[7] ? arg.substring(0, match[7]) : arg);
96 96 break;
97 97 case 'u': arg = Math.abs(arg); break;
98 98 case 'x': arg = arg.toString(16); break;
99 99 case 'X': arg = arg.toString(16).toUpperCase(); break;
100 100 }
101 101 arg = (/[def]/.test(match[8]) && match[3] && arg >= 0 ? '+'+ arg : arg);
102 102 pad_character =
103 103 match[4] ? match[4] === '0' ? '0' : match[4].charAt(1) : ' ';
104 104 pad_length = match[6] - String(arg).length;
105 105 pad = match[6] ? str_repeat(pad_character, pad_length) : '';
106 106 output.push(match[5] ? arg + pad : pad + arg);
107 107 }
108 108 }
109 109 return output.join('');
110 110 };
111 111
112 112 str_format.cache = {};
113 113
114 114 str_format.parse = function(fmt) {
115 115 var _fmt = fmt, match = [], parse_tree = [], arg_names = 0;
116 116 while (_fmt) {
117 117 if ((match = /^[^\x25]+/.exec(_fmt)) !== null) {
118 118 parse_tree.push(match[0]);
119 119 }
120 120 else if ((match = /^\x25{2}/.exec(_fmt)) !== null) {
121 121 parse_tree.push('%');
122 122 }
123 123 else if (
124 124 (match = /^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(_fmt)) !== null) {
125 125 if (match[2]) {
126 126 arg_names |= 1;
127 127 var field_list = [], replacement_field = match[2], field_match = [];
128 128 if ((field_match = /^([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) {
129 129 field_list.push(field_match[1]);
130 130 while ((replacement_field = replacement_field.substring(field_match[0].length)) !== '') {
131 131 if ((field_match = /^\.([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) {
132 132 field_list.push(field_match[1]);
133 133 }
134 134 else if ((field_match = /^\[(\d+)\]/.exec(replacement_field)) !== null) {
135 135 field_list.push(field_match[1]);
136 136 }
137 137 else {
138 138 throw('[sprintf] huh?');
139 139 }
140 140 }
141 141 }
142 142 else {
143 143 throw('[sprintf] huh?');
144 144 }
145 145 match[2] = field_list;
146 146 }
147 147 else {
148 148 arg_names |= 2;
149 149 }
150 150 if (arg_names === 3) {
151 151 throw('[sprintf] mixing positional and named placeholders is not (yet) supported');
152 152 }
153 153 parse_tree.push(match);
154 154 }
155 155 else {
156 156 throw('[sprintf] huh?');
157 157 }
158 158 _fmt = _fmt.substring(match[0].length);
159 159 }
160 160 return parse_tree;
161 161 };
162 162 return str_format;
163 163 })();
164 164
165 165 var vsprintf = function(fmt, argv) {
166 166 argv.unshift(fmt);
167 167 return sprintf.apply(null, argv);
168 168 };
169 169 return {
170 170 'asset': function(path, ver) {
171 var asset_url = ASSET_URL || '/_static/';
171 var asset_url = ASSET_URL || '/_static/rhodecode/';
172 172 var ret = asset_url + path;
173 173 if (ver !== undefined) {
174 174 ret += '?ver=' + ver;
175 175 }
176 176 return ret;
177 177 },
178 178 'url': function(route_name, params) {
179 179 var result = route_name;
180 180 if (typeof(params) !== 'object'){
181 181 params = {};
182 182 }
183 183 if (matchlist.hasOwnProperty(route_name)) {
184 184 var route = matchlist[route_name];
185 185 // param substitution
186 186 for(var i=0; i < route[1].length; i++) {
187 187 var param_name = route[1][i];
188 188 if (!params.hasOwnProperty(param_name))
189 189 throw new Error(
190 190 'parameter '+
191 191 param_name +
192 192 ' is missing in route"' +
193 193 route_name + '" generation');
194 194 }
195 195 result = sprintf(route[0], params);
196 196
197 197 var ret = [];
198 198 // extra params => GET
199 199 for (var param in params){
200 200 if (route[1].indexOf(param) === -1){
201 201 ret.push(encodeURIComponent(param) + "=" +
202 202 encodeURIComponent(params[param]));
203 203 }
204 204 }
205 205 var _parts = ret.join("&");
206 206 if(_parts){
207 207 result = result +'?'+ _parts;
208 208 }
209 209 if(APPLICATION_URL) {
210 210 result = APPLICATION_URL + result;
211 211 }
212 212 }
213 213
214 214 return result;
215 215 },
216 216 'register': function(route_name, route_tmpl, req_params) {
217 217 if (typeof(req_params) !== 'object') {
218 218 req_params = [];
219 219 }
220 220 // fix escape
221 221 route_tmpl = unescape(route_tmpl);
222 222 keys = [];
223 223 for(var i=0; i < req_params.length; i++) {
224 224 keys.push(req_params[i]);
225 225 }
226 226 matchlist[route_name] = [
227 227 route_tmpl,
228 228 keys
229 229 ];
230 230 },
231 231 '_routes': function(){
232 232 return matchlist;
233 233 }
234 234 };
235 235 })();
@@ -1,545 +1,545 b''
1 1 ## -*- coding: utf-8 -*-
2 2 <%inherit file="/debug_style/index.html"/>
3 3
4 4 <%def name="breadcrumbs_links()">
5 5 ${h.link_to(_('Style'), h.url('debug_style_home'))}
6 6 &raquo;
7 7 ${c.active}
8 8 </%def>
9 9
10 10
11 11 <%def name="real_main()">
12 12 <div class="box">
13 13 <div class="title">
14 14 ${self.breadcrumbs()}
15 15 </div>
16 16
17 17 <div class='sidebar-col-wrapper'>
18 18 ##main
19 19 ${self.sidebar()}
20 20
21 21 <div class="main-content">
22 22
23 23 <div style="opacity:.5">
24 24
25 25 <h2>Simple tables</h2>
26 26
27 27 <p>These styles will be adjusted later to provide a baseline style
28 28 for all tables without classes added, whether part of the
29 29 application or not. Currently, some of the
30 30 application-specific styles are applied to this table.</p>
31 31 <p>This is a baseline style for all tables, whether part of the
32 32 application or not. It has no class applied for styling. Use
33 33 the "rctable" class as outlined before for tables which are
34 34 part of the RhodeCode application.</p>
35 35 <table>
36 36 <tbody>
37 37 <tr>
38 38 <th>Header A</th>
39 39 <th>Header B</th>
40 40 <th>Header C</th>
41 41 <th>Header D</th>
42 42 </tr>
43 43 <tr>
44 44 <td>Content of col A</td>
45 45 <td>Content of col B</td>
46 46 <td>Content of col C</td>
47 47 <td>Content of col D</td>
48 48 </tr>
49 49 <tr>
50 50 <td>Content of col A</td>
51 51 <td>Content of col B</td>
52 52 <td>Content of col C</td>
53 53 <td>Content of col D</td>
54 54 </tr>
55 55 <tr>
56 56 <td>Content of col A</td>
57 57 <td>Content of col B</td>
58 58 <td>Content of col C</td>
59 59 <td>Content of col D</td>
60 60 </tr>
61 61 <tr>
62 62 <td>Content of col A</td>
63 63 <td>Content of col B</td>
64 64 <td>Content of col C</td>
65 65 <td>Content of col D</td>
66 66 </tr>
67 67 </tbody>
68 68 </table>
69 69 </div>
70 70
71 71
72 72
73 73
74 74 <h2>RC application table with examples</h2>
75 75
76 76 <p>This is a standard table which applies the rhodecode-specific styling to be used
77 77 throughout the application; it has <code>&lt;table class="rctable"&gt;</code>.
78 78 <br/>
79 79 By default, table data is not truncated, and wraps inside of the <code>&lt;td&gt
80 80 ;</code>. To prevent wrapping and contain data on one line, use the <code>&lt;
81 81 class="truncate-wrap"&gt;</code> on the <code>&lt;td&gt;</code>, and <code>span
82 82 class="truncate"</code> around the specific data to be truncated.
83 83 </p>
84 84 <p>
85 85 Ellipsis is added via CSS. Please always add a row of headers using <code>&lt;th
86 86 &gt;</code> to the top of a table.
87 87 </p>
88 88
89 89 ## TODO: johbo: in case we have more tables with examples, we should
90 90 ## create a generic class here.
91 91 <table class="rctable issuetracker">
92 92 <thead>
93 93 <tr>
94 94 <th>Header A</th>
95 95 <th>Header B</th>
96 96 <th>Header C</th>
97 97 <th>Header D</th>
98 98 </tr>
99 99 </thead>
100 100 <tbody>
101 101 <tr>
102 102 <td class="issue-tracker-example">
103 103 Example of col A
104 104 </td>
105 105 <td class="issue-tracker-example">
106 106 Example of col B
107 107 </td>
108 108 <td class="issue-tracker-example">
109 109 Example of col C
110 110 </td>
111 111 <td class="issue-tracker-example">
112 112 Example of col D
113 113 </td>
114 114 </tr>
115 115 <tr>
116 116 <td>Content of col A</td>
117 117 <td>Content of col B</td>
118 118 <td>Content of col C which is very long and will not be
119 119 truncated because sometimes people just want to write
120 120 really, really long commit messages which explain what
121 121 they did in excruciating detail and you really, really
122 122 want to read them.</td>
123 123 <td>Content of col D</td>
124 124 </tr>
125 125 <tr>
126 126 <td>Content of col A</td>
127 127 <td>Content of col B</td>
128 128 <td>Content of col C</td>
129 129 <td class="truncate-wrap"><span class="truncate">Truncated
130 130 content of column D truncate truncate truncatetruncate
131 131 truncate truncate</span></td>
132 132 </tr>
133 133 </tbody>
134 134 </table>
135 135
136 136 <h2>RC application table data classes</h2>
137 137
138 138 <p>The following tables contain documentation of all existing table data classes.
139 139 Please update when new classes are made.
140 140 </p>
141 141 <table class="rctable examples">
142 142 <thead>
143 143 <tr>
144 144 <th>Class</th>
145 145 <th>Description</th>
146 146 <th>Example</th>
147 147 </tr>
148 148 </thead>
149 149 <tbody>
150 150 <td>td-user</td>
151 151 <td>Any username/gravatar combination (see also Icons style).</td>
152 152 <td class="td-user author">
153 153 <img class="gravatar" alt="gravatar" src="https://secure.gravatar.com/avatar/0c9a7e6674b6f0b35d98dbe073e3f0ab?d=identicon&amp;s=32" height="16" width="16">
154 154 <span title="Oliver Strobel <oliver@rhodecode.com>" class="user">ostrobel (Oliver Strobel)</span>
155 155 </td>
156 156 </tr>
157 157 <tr>
158 158 <td>td-hash</td>
159 159 <td>Any hash; a commit, revision, etc. Use <code>&lt;pre&gt;</code> and header 'Commit'</td>
160 160 <td class="td-commit">
161 161 <pre><a href="/anothercpythonforkkkk/files/8d6b27837c6979983b037693fe975cdbb761b500/">r93699:8d6b27837c69</a></pre>
162 162 </td>
163 163 </tr>
164 164 <tr>
165 165 <td>td-rss</td>
166 166 <td>RSS feed link icon</td>
167 167 <td class="td-rss">
168 168 <a title="Subscribe to rss feed" href="/feed/rss"><i class="icon-rss-sign"></i></a>
169 169 </td>
170 170 </tr>
171 171 <tr>
172 172 <td>td-componentname</td>
173 173 <td>Any group, file, gist, or directory name.</td>
174 174 <td class="td-componentname">
175 175 <a href="/cpythonfork">
176 176 <span title="Mercurial repository"><i class="icon-hg"></i></span>
177 177 <i class="icon-unlock-alt" title="Public repository"></i>
178 178 rhodecode-dev-restyle-fork
179 179 </a>
180 180 </td>
181 181 </tr>
182 182 <tr>
183 183 <td>td-tags</td>
184 184 <td>Any cell containing tags, including branches and bookmarks.</td>
185 185 <td class="td-tags">
186 186 <span class="branchtag tag" title="Branch default">
187 187 <a href="/rhodecode-dev-restyle- fork/changelog?branch=default"><i class="icon-code-fork"></i>default</a>
188 188 </span>
189 189 </td>
190 190 </tr>
191 191 <tr>
192 192 <td>tags-truncate</td>
193 193 <td>Used to truncate a cell containing tags; avoid if possible.</td>
194 194 <td class="td-tags truncate-wrap">
195 195 <div class="truncate tags-truncate">
196 196 <div class="autoexpand">
197 197 <span class="tagtag tag" title="Tag tip">
198 198 <a href="/rhodecode-dev-restyle-fork/files/e519d5a0e71466d27257ddff921c4a13c540408e/"><i class="icon-tag"></i>tip</a>
199 199 </span>
200 200 <span class="branchtag tag" title="Branch default">
201 201 <a href="/rhodecode-dev-restyle-fork/changelog?branch=default"><i class="icon-code-fork"></i>default</a>
202 202 </span>
203 203 <span class="branchtag tag" title="Branch default">
204 204 <a href="/rhodecode-dev-restyle-fork/changelog?branch=default"><i class="icon-code-fork"></i>default</a>
205 205 </span>
206 206 </div>
207 207 </div>
208 208 </td>
209 209 </tr>
210 210 <tr>
211 211 <td>td-ip</td>
212 212 <td>Any ip address.</td>
213 213 <td class="td-ip">
214 214 172.16.115.168
215 215 </td>
216 216 </tr>
217 217 <tr>
218 218 <td>td-type</td>
219 219 <td>A state or an auth type.</td>
220 220 <td class="td-type">
221 221 rhodecode
222 222 </td>
223 223 </tr>
224 224 <tr>
225 225 <td>td-authtoken</td>
226 226 <td>For auth tokens. Use truncate classes for hover expand; see html.</td>
227 227 <td class="truncate-wrap td-authtoken">
228 228 <div class="truncate autoexpand">
229 229 <code>688df65b87d3ad16ae9f8fc6338a551d40f41c7a</code>
230 230 </div>
231 231 </td>
232 232 </tr>
233 233 <tr>
234 234 <td>td-action</td>
235 235 <td>Buttons which perform an action.</td>
236 236 <td class="td-action">
237 237 <div class="grid_edit">
238 238 <a href="/_admin/users/2/edit" title="edit">
239 239 <i class="icon-pencil"></i>Edit</a>
240 240 </div>
241 241 <div class="grid_delete">
242 242 <form action="/_admin/users/2" method="post">
243 243 <i class="icon-remove-sign"></i>
244 244 <input class="btn btn-danger btn-link" id="remove_user_2" name="remove_" type="submit" value="delete">
245 245 </form>
246 246 </div>
247 247 </td>
248 248 </tr>
249 249 <tr>
250 250 <td>td-radio</td>
251 251 <td>Radio buttons for a form. Centers element.</td>
252 252 <td class="td-radio">
253 253 <input type="radio" checked="checked" value="" name="1" id="read"></td>
254 254 </tr>
255 255 <tr>
256 256 <td>td-checkbox</td>
257 257 <td>Checkbox for a form. Centers element.</td>
258 258 <td class="td-checkbox">
259 259 <input type="checkbox" checked="checked" value="" name="1" id="read"></td>
260 260 </tr>
261 261 <tr>
262 262 <tr>
263 263 <td>td-buttons</td>
264 264 <td>Buttons.</td>
265 265 <td class="td-buttons">
266 266 <span class="btn btn-mini btn-primary">feed access</span>
267 267 </td>
268 268 </tr>
269 269 <tr>
270 270 <td>td-compare</td>
271 271 <td>Radio buttons to compare commits.</td>
272 272 <td class=" td-compare">
273 273 <input class="compare-radio-button" type="radio" name="compare_source" value="2.0">
274 274 <input class="compare-radio-button" type="radio" name="compare_target" value="2.0">
275 275 </td>
276 276 </tr>
277 277 <tr>
278 278 <td>td-comments</td>
279 279 <td>Comments indicator icon.</td>
280 280 <td>
281 281 <i class="icon-comment icon-comment-colored"></i> 0
282 282 </td>
283 283 </tr>
284 284 <tr>
285 285 <td>td-status</td>
286 286 <td>Status indicator icon.</td>
287 287 <td class="td-description">
288 288 <div class="flag_status under_review pull-left"></div>
289 289 </td>
290 290 </tr>
291 291 </tbody>
292 292 </table>
293 293 <table class="dataTable rctable examples">
294 294 <tbody>
295 295 <tr>
296 296 <td>quick_repo_menu</td>
297 297 <td>Hidden menu generated by dataTable.</td>
298 298 <td class="quick_repo_menu">
299 299 <i class="pointer icon-more"></i>
300 300 <div class="menu_items_container" style="display: none;">
301 301 <ul class="menu_items">
302 302 <li>
303 303 <a title="Summary" href="/anothercpythonforkkkk-fork">
304 304 <span>Summary</span>
305 305 </a>
306 306 </li>
307 307 <li>
308 308 <a title="Changelog" href="/anothercpythonforkkkk-fork/changelog">
309 309 <span>Changelog</span>
310 310 </a>
311 311 </li>
312 312 <li>
313 313 <a title="Files" href="/anothercpythonforkkkk-fork/files/tip/">
314 314 <span>Files</span>
315 315 </a>
316 316 </li>
317 317 <li>
318 318 <a title="Fork" href="/anothercpythonforkkkk-fork/fork">
319 319 <span>Fork</span>
320 320 </a>
321 321 </li>
322 322 </ul>
323 323 </div>
324 324 </td>
325 325 <td></td>
326 326 </tr>
327 327 </tbody>
328 328 </table>
329 329 <script>quick_repo_menu();</script>
330 330 <table class="rctable examples">
331 331 <tbody>
332 332 <tr>
333 333 <td>td-description</td>
334 334 <td>Any description. They may be rather long, and using the expand_commit outlined below is recommended.</td>
335 335 <td class="td-description">
336 336 Ultrices mattis! Enim pellentesque lacus, sit magna natoque risus turpis ut, auctor ultrices facilisis dapibus odio? Parturient! Porta egestas nascetur, quis, elementum dolor, in magna ac dis sit etiam turpis, scelerisque! Integer tristique aliquam.
337 337 </td>
338 338 </tr>
339 339 </tbody>
340 340 </table>
341 341 <table id="changesets" class="rctable examples end">
342 342 <tbody>
343 343 <tr>
344 344 <td>expand_commit</td>
345 345 <td>Expands a long message; see html+js.</td>
346 346 <td class="expand_commit" data-commit-id="2ffc6faabc7a9c790b1b452943a3f0c047b8b436" title="Expand commit message">
347 347 <div class="show_more_col">
348 348 <i class="show_more"></i>
349 349 </div>
350 350 </td>
351 351 <td class="mid td-description">
352 352 <div class="log-container truncate-wrap">
353 353 <div id="c-2ffc6faabc7a9c790b1b452943a3f0c047b8b436" class="message truncate" data-message-raw="tests: Test echo method on the server object
354 354
355 355 This only works for Pyro4 so far, have to extend it still for HTTP to work.">tests: Test echo method on the server object
356 356
357 357 This only works for Pyro4 so far, have to extend it still for HTTP to work.</div>
358 358 </div>
359 359 </td>
360 360 </tr>
361 361 </tbody>
362 362 </table>
363 363 <script type="text/javascript">
364 364 var cache = {}
365 365 $('.expand_commit').on('click',function(e){
366 366 var target_expand = $(this);
367 367 var cid = target_expand.data('commitId');
368 368
369 369 if (target_expand.hasClass('open')){
370 370 $('#c-'+cid).css({'height': '1.5em', 'white-space': 'nowrap', 'text-overflow': 'ellipsis', 'overflow':'hidden'});
371 371 $('#t-'+cid).css({'height': '1.5em', 'max-height': '1.5em', 'text-overflow': 'ellipsis', 'overflow':'hidden', 'white-space':'nowrap'});
372 372 target_expand.removeClass('open');
373 373 }
374 374 else {
375 375 $('#c-'+cid).css({'height': 'auto', 'white-space': 'pre-line', 'text-overflow': 'initial', 'overflow':'visible'});
376 376 $('#t-'+cid).css({'height': 'auto', 'max-height': 'none', 'text-overflow': 'initial', 'overflow':'visible', 'white-space':'normal'});
377 377 target_expand.addClass('open');
378 378 }
379 379 });
380 380
381 381 </script>
382 382 <p>The following classes currently do not have unique styles applied.</p>
383 383 <table class="rctable examples end">
384 384 <tbody>
385 385 <tr>
386 386 <td>td-regex</td>
387 387 <td>Regex patterns</td>
388 388 <td class="td-regex">(?:#)(?P<issue_id>\d+)</td>
389 389 </tr>
390 390 <tr>
391 391 <td>td-url</td>
392 392 <td>Any URL.</td>
393 393 <td class="td-url">https://rhodecode.com</td>
394 394 </tr>
395 395 <tr>
396 396 <td>td-journalaction</td>
397 397 <td>Action listed in a journal</td>
398 398 <td class="td-journalaction">started following repository supervisor-fork-4</td>
399 399 </tr>
400 400 <tr>
401 401 <td>td-iprange</td>
402 402 <td>Any ip address.</td>
403 403 <td class="td-ip">127.0.0.1-127.0.0.10</td>
404 404 </tr>
405 405 <tr>
406 406 <td>td-exp</td>
407 407 <td>Expiration time.</td>
408 408 <td class="td-exp">never</td>
409 409 </tr>
410 410 <tr>
411 411 <td>td-prefix</td>
412 412 <td>Prefixes outlined in settings.</td>
413 413 <td class="td-prefix">ubuntu-92539</td>
414 414 </tr>
415 415 <tr>
416 416 <td>td-cachekey</td>
417 417 <td>Cache key value.</td>
418 418 <td class="td-cachekey">ubuntu-92539supervisor</td>
419 419 </tr>
420 420 <tr>
421 421 <td>td-email</td>
422 422 <td>Any email address.</td>
423 423 <td class="td-email">example@rhodecode.com</td>
424 424 </tr>
425 425 <tr>
426 426 <td>td-active</td>
427 427 <td>Shows active state with icon-true/icon-false.</td>
428 428 <td class="td-active"><i class="icon-false"></i></td>
429 429 </tr>
430 430 <tr>
431 431 <td>td-size</td>
432 432 <td>File, repo, or directory size.</td>
433 433 <td class="td-size">89 MB</td>
434 434 </tr>
435 435 <tr>
436 436 <td>td-number</td>
437 437 <td>Any numerical data.</td>
438 438 <td class="td-number">42</td>
439 439 </tr>
440 440 <tr>
441 441 <td>td-message</td>
442 442 <td>Any commit message. Often treated with the truncate class used for descriptions as well.</td>
443 443 <td class="td-message">Updated the files</td>
444 444 </tr>
445 445 </tbody>
446 446 </table>
447 447
448 448
449 449 <h2>Permissions table</h2>
450 450
451 451 <p>
452 452 This is a special-case table; it has
453 453 <code>table class="rctable permissions"</code>
454 454 where "rctable" applies the rhodecode styling as above, and
455 455 "permissions" adds an extra layer of customization specific to
456 456 permissions tables. Other special-case tables may exist or be
457 457 created if necessary.
458 458 </p>
459 459
460 460 <table class="rctable permissions">
461 461 <tr>
462 462 <th class="td-radio">none</th>
463 463 <th class="td-radio">read</th>
464 464 <th class="td-radio">write</th>
465 465 <th class="td-radio">admin</th>
466 466 <th>user/user group</th>
467 467 <th></th>
468 468 </tr>
469 469 <tr class="perm_admin_row">
470 470 <td class="td-radio"><input type="radio" value="repository.none"
471 471 name="admin_perm_2" id="admin_perm_2_repositorynone"
472 472 disabled="disabled"></td>
473 473 <td class="td-radio"><input type="radio" value="repository.read"
474 474 name="admin_perm_2" id="admin_perm_2_repositoryread"
475 475 disabled="disabled"></td>
476 476 <td class="td-radio"><input type="radio" value="repository.write"
477 477 name="admin_perm_2" id="admin_perm_2_repositorywrite"
478 478 disabled="disabled"></td>
479 479 <td class="td-radio"><input type="radio" value="repository.admin"
480 480 name="admin_perm_2" id="admin_perm_2_repositoryadmin"
481 481 disabled="disabled" checked="checked"></td>
482 482 <td>
483 483 <img class="gravatar" src="https://secure.gravatar.com/avatar/be9d18f611892a738e54f2a3a171e2f9?d=identicon&amp;s=32" height="16" width="16">
484 484 <span class="user">dev (super admin) (owner)</span>
485 485 </td>
486 486 <td></td>
487 487 </tr>
488 488 <tr>
489 489 <td colspan="4">
490 490 <span class="private_repo_msg">
491 491 private repository
492 492 </span>
493 493 </td>
494 494 <td class="private_repo_msg">
495 495 <i class="icon-user"></i>
496 496 default - only people explicitly added here will have access</td>
497 497 <td></td>
498 498 </tr>
499 499 <tr>
500 500 <td class="td-radio"><input type="radio" value="repository.none"
501 501 name="u_perm_1" id="u_perm_1_repositorynone"></td>
502 502 <td class="td-radio"><input type="radio" checked="checked"
503 503 value="repository.read" name="u_perm_1"
504 504 id="u_perm_1_repositoryread"></td>
505 505 <td class="td-radio"><input type="radio" value="repository.write"
506 506 name="u_perm_1" id="u_perm_1_repositorywrite"></td>
507 507 <td class="td-radio"><input type="radio" value="repository.admin"
508 508 name="u_perm_1" id="u_perm_1_repositoryadmin"></td>
509 509 <td>
510 <img class="gravatar" src="/_static/images/user30.png" height="16" width="16">
510 <img class="gravatar" src="/_static/rhodecode/images/user30.png" height="16" width="16">
511 511 <span class="user">default</span>
512 512 </td>
513 513 <td></td>
514 514 </tr>
515 515 <tr>
516 516 <td class="td-radio"><input type="radio" value="repository.none"
517 517 name="u_perm_2" id="u_perm_2_repositorynone"></td>
518 518 <td class="td-radio"><input type="radio" checked="checked"
519 519 value="repository.read" name="u_perm_2"
520 520 id="u_perm_2_repositoryread"></td>
521 521 <td class="td-radio"><input type="radio" value="repository.write"
522 522 name="u_perm_2" id="u_perm_2_repositorywrite"></td>
523 523 <td class="td-radio"><input type="radio" value="repository.admin"
524 524 name="u_perm_2" id="u_perm_2_repositoryadmin"></td>
525 525 <td>
526 526 <img class="gravatar" src="https://secure.gravatar.com/avatar/be9d18f611892a738e54f2a3a171e2f9?d=identicon&amp;s=32" height="16" width="16">
527 527 <a class="user" href="/_admin/users/2/edit">dev</a>
528 528 </td>
529 529 <td>
530 530 <span member_type="user" member="2"
531 531 class="btn action_button btn-link btn-danger">revoke</span>
532 532 </td>
533 533 </tr>
534 534 </tbody>
535 535 </table>
536 536 <div class="link" id="add_perm">
537 537 Add new
538 538 </div>
539 539
540 540
541 541
542 542 </div>
543 543 </div>
544 544 </div>
545 545 </%def>
General Comments 0
You need to be logged in to leave comments. Login now